From 52c32c37d83b54558409edb6ad34f4baec9bdfa2 Mon Sep 17 00:00:00 2001 From: Serhii Vecherenko Date: Thu, 30 Jul 2026 14:01:54 -0700 Subject: [PATCH] feat(schedules): add automation triage and completion policies - add cron scheduling, run lifecycle controls, and inbox state - expose schedule management through MCP, IPC, and remote clients - add execution and triage UI with localized copy --- .../scripts/poracode-integration-smoke.mjs | 4 +- package.json | 1 + pnpm-lock.yaml | 17 + scripts/build-desktop-artifact.mjs | 1 + .../AppControlsMcpIngress.test.ts | 6 +- .../app-controls/AppControlsMcpIngress.ts | 9 +- .../app-controls/mcp/scheduleToolSchemas.ts | 121 ++++ .../app-controls/mcp/toolRegistry.test.ts | 214 +++++- src/main/app-controls/mcp/toolRegistry.ts | 181 +++--- src/main/db.ts | 5 + src/main/db/connection.ts | 81 ++- src/main/db/runtimeItems.test.ts | 35 + src/main/db/runtimeItems.ts | 24 + src/main/db/scheduleRuns.test.ts | 237 ++++++- src/main/db/scheduleRuns.ts | 187 +++++- src/main/db/schedules.ts | 19 +- src/main/ipc/localHandlers.ts | 11 + src/main/main.ts | 26 +- .../remote/DesktopRemoteAccessController.ts | 23 +- src/main/remote/RemoteAccessServer.test.ts | 109 +++- src/main/remote/RemoteAccessServer.ts | 7 + src/main/remote/server/httpRouter.ts | 28 + .../schedules/ScheduleRunCoordinator.test.ts | 335 +++++++++- src/main/schedules/ScheduleRunCoordinator.ts | 614 ++++++++++++++---- src/main/schedules/ScheduleService.test.ts | 600 ++++++++++++++++- src/main/schedules/ScheduleService.ts | 398 ++++++++++-- src/main/schedules/index.ts | 10 +- src/main/schedules/scheduleRunResults.ts | 91 +++ src/main/schedules/types.ts | 29 + src/mobile/bridge.test.ts | 63 ++ src/mobile/bridge.ts | 21 + src/mobile/settingsSections.ts | 4 +- src/mobile/views/SettingsView.test.tsx | 2 +- .../components/common/LightballTabs.tsx | 16 + .../components/mcp/McpServersManager.test.tsx | 3 +- src/renderer/i18n/sharedMessages.ts | 45 ++ src/renderer/locales/de/messages.po | 500 +++++++++++++- src/renderer/locales/en/messages.po | 500 +++++++++++++- src/renderer/locales/es/messages.po | 500 +++++++++++++- src/renderer/locales/fr/messages.po | 500 +++++++++++++- src/renderer/locales/ja/messages.po | 500 +++++++++++++- src/renderer/locales/ko/messages.po | 500 +++++++++++++- src/renderer/locales/pl/messages.po | 500 +++++++++++++- src/renderer/locales/pt-BR/messages.po | 500 +++++++++++++- src/renderer/locales/ru/messages.po | 500 +++++++++++++- src/renderer/locales/tr/messages.po | 500 +++++++++++++- src/renderer/locales/uk/messages.po | 500 +++++++++++++- src/renderer/locales/vi/messages.po | 500 +++++++++++++- src/renderer/locales/zh-CN/messages.po | 500 +++++++++++++- src/renderer/state/remoteServersStore.test.ts | 3 +- .../views/MainView/parts/Sidebar/Sidebar.tsx | 4 +- .../PrReviewOverlay/parts/PrTabsPill.tsx | 26 +- .../views/SchedulesView/ScheduleEditor.tsx | 133 +++- .../SchedulesView/SchedulesView.test.tsx | 200 +++++- .../views/SchedulesView/SchedulesView.tsx | 433 +++++++----- .../SchedulesView/parts/PreviousRunsModal.tsx | 19 +- .../parts/ScheduleExecutionSection.test.tsx | 117 ++++ .../parts/ScheduleExecutionSection.tsx | 335 ++++++++++ .../views/SchedulesView/parts/ScheduleRow.tsx | 9 +- .../views/SchedulesView/parts/TriagePanel.tsx | 306 +++++++++ .../views/SchedulesView/scheduleDraft.test.ts | 295 ++++++++- .../views/SchedulesView/scheduleDraft.ts | 312 ++++++++- src/server/createHeadlessRemoteHost.test.ts | 5 +- src/server/createHeadlessRemoteHost.ts | 41 +- src/shared/contracts/mcpServer.ts | 7 + src/shared/contracts/schedule.ts | 265 +++++++- src/shared/ipc/procedureMap.ts | 4 + src/shared/ipc/procedures/schedules.ts | 37 ++ src/shared/messages.ts | Bin 10298 -> 12047 bytes src/shared/remote/client.test.ts | 82 ++- src/shared/remote/client.ts | 49 ++ src/shared/remote/protocol.ts | 32 +- src/shared/schedules.test.ts | 157 ++++- src/shared/schedules.ts | 128 ++++ src/supervisor/ipcHandlers.ts | 1 + src/supervisor/mcp/probeMcpWorker.ts | 2 +- src/supervisor/runtime/generationService.ts | 10 + .../scheduleCompletionEvaluator.test.ts | 121 ++++ src/supervisor/scheduleCompletionEvaluator.ts | 83 +++ vite.config.ts | 5 + 80 files changed, 12624 insertions(+), 674 deletions(-) create mode 100644 src/main/app-controls/mcp/scheduleToolSchemas.ts create mode 100644 src/main/schedules/scheduleRunResults.ts create mode 100644 src/main/schedules/types.ts create mode 100644 src/mobile/bridge.test.ts create mode 100644 src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.test.tsx create mode 100644 src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx create mode 100644 src/renderer/views/SchedulesView/parts/TriagePanel.tsx create mode 100644 src/supervisor/scheduleCompletionEvaluator.test.ts create mode 100644 src/supervisor/scheduleCompletionEvaluator.ts diff --git a/.agents/skills/interactive-testing/scripts/poracode-integration-smoke.mjs b/.agents/skills/interactive-testing/scripts/poracode-integration-smoke.mjs index 4976f26eb..2a8a9e469 100644 --- a/.agents/skills/interactive-testing/scripts/poracode-integration-smoke.mjs +++ b/.agents/skills/interactive-testing/scripts/poracode-integration-smoke.mjs @@ -976,14 +976,14 @@ async function schedulesScenario(client) { client, `(() => { const button = [...document.querySelectorAll('button, [role="button"]')].find( - (candidate) => candidate.getAttribute("aria-label") === "Schedules" || candidate.textContent?.trim() === "Schedules", + (candidate) => candidate.getAttribute("aria-label") === "Automations" || candidate.textContent?.trim() === "Automations", ); if (!(button instanceof HTMLElement)) return false; button.click(); return true; })()`, ); - assert(opened, "Schedules was not available in the main sidebar"); + assert(opened, "Automations was not available in the main sidebar"); const rendered = await waitForValue( () => evaluate( diff --git a/package.json b/package.json index a8d422d95..b528a9fc5 100644 --- a/package.json +++ b/package.json @@ -114,6 +114,7 @@ "@xterm/addon-webgl": "0.20.0-beta.218", "@xterm/xterm": "6.1.0-beta.219", "better-sqlite3": "^12.11.1", + "cron-parser": "5.6.1", "dexie": "^4.4.4", "drizzle-orm": "1.0.0-rc.1", "electron-updater": "^6.8.9", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 11a7d604d..a5895186e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -159,6 +159,9 @@ importers: better-sqlite3: specifier: ^12.11.1 version: 12.11.1 + cron-parser: + specifier: 5.6.1 + version: 5.6.1 dexie: specifier: ^4.4.4 version: 4.4.4 @@ -3810,6 +3813,10 @@ packages: cose-base@2.2.0: resolution: {integrity: sha512-AzlgcsCbUMymkADOJtQm3wO9S3ltPfYOFD5033keQn9NJzIbtnZj+UdBJe7DYml/8TdbtHJW3j58SOnKhWY/5g==} + cron-parser@5.6.1: + resolution: {integrity: sha512-QBm4o1PwZiuY7KFbVvW7FLC8bozy7YWzv+Fz6KRS7sQghzcbDZCGxr/Bc5b6TQreAoSwuWVP491dIcK0THCX6A==} + engines: {node: '>=18'} + cross-dirname@0.1.0: resolution: {integrity: sha512-+R08/oI0nl3vfPcqftZRpytksBXDzOUveBq/NBVx0sUp1axwzPQrKinNx5yd5sxPu8j1wIy8AfnVQ+5eFdha6Q==} @@ -5223,6 +5230,10 @@ packages: peerDependencies: react: ^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0 + luxon@3.7.2: + resolution: {integrity: sha512-vtEhXh/gNjI9Yg1u4jX/0YVPMvxzHuGgCm6tC5kZyb08yjGWGnqAjGJvcXbqQR2P3MyMEFnRbpcdFS6PBcLqew==} + engines: {node: '>=12'} + lz-string@1.5.0: resolution: {integrity: sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==} hasBin: true @@ -10346,6 +10357,10 @@ snapshots: dependencies: layout-base: 2.0.1 + cron-parser@5.6.1: + dependencies: + luxon: 3.7.2 + cross-dirname@0.1.0: optional: true @@ -11750,6 +11765,8 @@ snapshots: dependencies: react: 19.2.7 + luxon@3.7.2: {} + lz-string@1.5.0: {} magic-string@0.30.21: diff --git a/scripts/build-desktop-artifact.mjs b/scripts/build-desktop-artifact.mjs index 1b062f488..88f89fc77 100644 --- a/scripts/build-desktop-artifact.mjs +++ b/scripts/build-desktop-artifact.mjs @@ -43,6 +43,7 @@ const RUNTIME_DEPS = [ "@sentry/electron", "@sentry/node", "better-sqlite3", + "cron-parser", "drizzle-orm", "json5", "micromatch", diff --git a/src/main/app-controls/AppControlsMcpIngress.test.ts b/src/main/app-controls/AppControlsMcpIngress.test.ts index 669c8ca56..b3eae1276 100644 --- a/src/main/app-controls/AppControlsMcpIngress.test.ts +++ b/src/main/app-controls/AppControlsMcpIngress.test.ts @@ -24,7 +24,11 @@ describe("AppControlsMcpIngress", () => { agentKind: "codex", config: { model: "gpt-5.6", effort: "high" }, } as Thread; - ingress = new AppControlsMcpIngress(service, (id) => (id === thread.id ? thread : null)); + ingress = new AppControlsMcpIngress(service, (id) => (id === thread.id ? thread : null), { + listScheduleRuns: vi.fn<() => never[]>(() => []), + listScheduleRunInbox: vi.fn<() => never[]>(() => []), + updateScheduleRunState: vi.fn<() => null>(() => null), + }); const info = await ingress.start(); const response = await fetch(`${info.url}/mcp?thread=thread-1`, { diff --git a/src/main/app-controls/AppControlsMcpIngress.ts b/src/main/app-controls/AppControlsMcpIngress.ts index 01803fe76..f5097831d 100644 --- a/src/main/app-controls/AppControlsMcpIngress.ts +++ b/src/main/app-controls/AppControlsMcpIngress.ts @@ -10,6 +10,7 @@ import { dispatchTool, formatToolResult, isKnownToolName, + type AppControlsScheduleRunControls, type AppControlsToolContext, } from "./mcp/toolRegistry"; @@ -18,13 +19,17 @@ export type AppControlsMcpIngressInfo = StreamableHttpMcpIngressInfo; export class AppControlsMcpIngress { private readonly ingress: StreamableHttpMcpIngress; - constructor(scheduleService: ScheduleService, getThread: (threadId: string) => Thread | null) { + constructor( + scheduleService: ScheduleService, + getThread: (threadId: string) => Thread | null, + scheduleRuns: AppControlsScheduleRunControls, + ) { this.ingress = new StreamableHttpMcpIngress({ serverInfo: { name: "poracode", version: "1.0.0" }, instructions: APP_CONTROLS_MCP_INSTRUCTIONS, tools: TOOLS, isKnownToolName, - buildContext: (identity) => ({ identity, scheduleService, getThread }), + buildContext: (identity) => ({ identity, scheduleService, scheduleRuns, getThread }), dispatchTool, formatToolResult, }); diff --git a/src/main/app-controls/mcp/scheduleToolSchemas.ts b/src/main/app-controls/mcp/scheduleToolSchemas.ts new file mode 100644 index 000000000..1cad971b5 --- /dev/null +++ b/src/main/app-controls/mcp/scheduleToolSchemas.ts @@ -0,0 +1,121 @@ +import { z } from "zod"; +import { + agentKindSchema, + scheduleAutomationSchema, + scheduleRecurrenceSchema, + scheduleRunInboxQuerySchema, +} from "@/shared/contracts"; + +export const createScheduleArgsSchema = z.object({ + name: z.string().trim().min(1).max(120), + prompt: z.string().trim().min(1).max(50_000), + recurrence: scheduleRecurrenceSchema, + enabled: z.boolean().optional().default(true), + agentKind: agentKindSchema.optional(), + model: z.string().min(1).optional(), + effort: z.string().min(1).optional(), + automation: scheduleAutomationSchema.optional(), +}); + +export const updateScheduleArgsSchema = z.object({ + id: z.string().uuid(), + name: z.string().trim().min(1).max(120).optional(), + prompt: z.string().trim().min(1).max(50_000).optional(), + recurrence: scheduleRecurrenceSchema.optional(), + enabled: z.boolean().optional(), + agentKind: agentKindSchema.optional(), + model: z.string().min(1).optional(), + effort: z.string().min(1).nullable().optional(), + automation: scheduleAutomationSchema.optional(), +}); + +export const idArgsSchema = z.object({ id: z.string().uuid() }); +export const scheduleRunsArgsSchema = z.object({ scheduleId: z.string().uuid() }); +export const scheduleRunInboxArgsSchema = scheduleRunInboxQuerySchema.extend({ + filter: scheduleRunInboxQuerySchema.shape.filter.default("unread"), +}); + +export function idJsonSchema(): Record { + return { + type: "object", + additionalProperties: false, + required: ["id"], + properties: { id: { type: "string", format: "uuid" } }, + }; +} + +export function recurrenceJsonSchema(): Record { + return { + oneOf: [ + { + type: "object", + additionalProperties: false, + required: ["kind", "minute"], + properties: { + kind: { const: "hourly" }, + minute: { type: "integer", minimum: 0, maximum: 59 }, + }, + }, + { + type: "object", + additionalProperties: false, + required: ["kind", "days", "time"], + properties: { + kind: { const: "weekly" }, + days: { + type: "array", + minItems: 1, + items: { type: "integer", minimum: 0, maximum: 6 }, + }, + time: { type: "string", pattern: "^([01]\\d|2[0-3]):[0-5]\\d$" }, + timeZone: { type: "string", minLength: 1, maxLength: 128 }, + }, + }, + { + type: "object", + additionalProperties: false, + required: ["kind", "runAt"], + properties: { + kind: { const: "once" }, + runAt: { type: "string", format: "date-time" }, + }, + }, + { + type: "object", + additionalProperties: false, + required: ["kind", "every", "unit"], + properties: { + kind: { const: "interval" }, + every: { type: "integer", minimum: 1, maximum: 999 }, + unit: { enum: ["minutes", "hours", "days"] }, + }, + }, + { + type: "object", + additionalProperties: false, + required: ["kind", "expression", "timeZone"], + properties: { + kind: { const: "cron" }, + expression: { + type: "string", + minLength: 1, + maxLength: 120, + pattern: "^\\s*[0-9*,/-]+(?:\\s+[0-9*,/-]+){4}\\s*$", + description: "Five numeric cron fields: minute, hour, day, month, and weekday.", + }, + timeZone: { type: "string", minLength: 1, maxLength: 128 }, + }, + }, + ], + }; +} + +export function automationJsonSchema(): Record { + const jsonSchema = z.toJSONSchema(scheduleAutomationSchema); + delete jsonSchema.$schema; + return { + ...jsonSchema, + description: + "Complete automation policy. AI-evaluated completion conditions are valid only in heartbeat mode.", + }; +} diff --git a/src/main/app-controls/mcp/toolRegistry.test.ts b/src/main/app-controls/mcp/toolRegistry.test.ts index 426ea2043..95faed4f0 100644 --- a/src/main/app-controls/mcp/toolRegistry.test.ts +++ b/src/main/app-controls/mcp/toolRegistry.test.ts @@ -1,7 +1,16 @@ import { describe, expect, it, vi } from "vitest"; -import type { ScheduledTask, ScheduledTaskInput, Thread } from "@/shared/contracts"; +import type { + ScheduleAutomation, + ScheduledTask, + ScheduledTaskInput, + ScheduledTaskRun, + Thread, +} from "@/shared/contracts"; import type { ScheduleService } from "../../schedules/ScheduleService"; -import { dispatchTool, type AppControlsToolContext } from "./toolRegistry"; +import { dispatchTool, TOOLS, type AppControlsToolContext } from "./toolRegistry"; + +const SCHEDULE_ID = "d2ac39e9-14ac-4776-9279-37a1e455a5db"; +const RUN_ID = "6c7406dc-a3b2-4841-89aa-b7e2eba78c79"; const thread = { id: "thread-1", @@ -24,17 +33,126 @@ function context(tasks: ScheduledTask[] = []) { runNow: vi.fn<(id: string) => ScheduledTask>( (id) => ({ id, lastStatus: "running" }) as ScheduledTask, ), + cancelRun: vi.fn<(id: string) => boolean>(() => true), delete: vi.fn<(id: string) => void>(), } as unknown as ScheduleService; + const run = { id: RUN_ID, scheduleId: SCHEDULE_ID } as ScheduledTaskRun; + const scheduleRuns = { + listScheduleRuns: vi.fn<(scheduleId: string) => ScheduledTaskRun[]>(() => [run]), + listScheduleRunInbox: vi.fn<() => ScheduledTaskRun[]>(() => [run]), + updateScheduleRunState: vi.fn<() => ScheduledTaskRun | null>(() => run), + }; const ctx: AppControlsToolContext = { identity: { threadId: thread.id, title: "Schedule this" }, scheduleService: service, + scheduleRuns, getThread: (id) => (id === thread.id ? thread : null), }; - return { ctx, service }; + return { ctx, service, scheduleRuns, run }; } +const heartbeatAutomation: ScheduleAutomation = { + version: 1, + mode: { kind: "heartbeat", targetThreadId: thread.id }, + maxRuntimeSeconds: 900, + maxIterations: 12, + stopOnError: true, + misfirePolicy: "run-latest", + retryPolicy: { + kind: "exponential", + maxAttempts: 4, + initialDelaySeconds: 10, + maxDelaySeconds: 120, + }, + completionPolicy: { + kind: "ai-evaluated", + stopWhen: "All migration checks pass.", + confidenceThreshold: 0.9, + }, +}; + describe("Poracode app control tools", () => { + it("advertises every supported schedule recurrence", () => { + const createTool = TOOLS.find((tool) => tool.name === "create_schedule")!; + const schema = createTool.inputSchema as { + properties: { + recurrence: { + oneOf: { + properties: { kind: { const: string }; expression?: { pattern: string } }; + }[]; + }; + }; + }; + + expect(schema.properties.recurrence.oneOf.map((entry) => entry.properties.kind.const)).toEqual([ + "hourly", + "weekly", + "once", + "interval", + "cron", + ]); + const cron = schema.properties.recurrence.oneOf.find( + (entry) => entry.properties.kind.const === "cron", + ); + expect(cron?.properties.expression?.pattern).toBe("^\\s*[0-9*,/-]+(?:\\s+[0-9*,/-]+){4}\\s*$"); + }); + + it("advertises the complete automation policy and run-result controls", () => { + const createTool = TOOLS.find((tool) => tool.name === "create_schedule")!; + const schema = createTool.inputSchema as { + properties: { + automation: { + required: string[]; + properties: { + mode: { oneOf: { properties: { kind: { const: string } } }[] }; + retryPolicy: { oneOf: { properties: { kind: { const: string } } }[] }; + completionPolicy: { oneOf: { properties: { kind: { const: string } } }[] }; + }; + }; + }; + }; + + expect(schema.properties.automation.required).toEqual([ + "version", + "mode", + "maxRuntimeSeconds", + "maxIterations", + "stopOnError", + "misfirePolicy", + "retryPolicy", + "completionPolicy", + ]); + expect( + schema.properties.automation.properties.mode.oneOf.map( + (entry) => entry.properties.kind.const, + ), + ).toEqual(["new-thread", "heartbeat"]); + expect( + schema.properties.automation.properties.retryPolicy.oneOf.map( + (entry) => entry.properties.kind.const, + ), + ).toEqual(["none", "fixed", "exponential"]); + expect( + schema.properties.automation.properties.completionPolicy.oneOf.map( + (entry) => entry.properties.kind.const, + ), + ).toEqual(["none", "ai-evaluated"]); + expect(TOOLS.map((tool) => tool.name)).toEqual([ + "list_schedules", + "create_schedule", + "update_schedule", + "run_schedule", + "delete_schedule", + "list_schedule_runs", + "list_schedule_run_inbox", + "mark_schedule_run_read", + "mark_schedule_run_unread", + "archive_schedule_run", + "restore_schedule_run", + "cancel_schedule_run", + ]); + }); + it("creates a schedule with the calling thread's agent defaults", async () => { const { ctx, service } = context(); await dispatchTool( @@ -57,15 +175,34 @@ describe("Poracode app control tools", () => { }); }); + it("creates a schedule with the full automation policy", async () => { + const { ctx, service } = context(); + await dispatchTool( + "create_schedule", + { + name: "Migration heartbeat", + prompt: "Continue the migration", + recurrence: { kind: "interval", every: 15, unit: "minutes" }, + automation: heartbeatAutomation, + }, + ctx, + ); + + expect(service.create).toHaveBeenCalledWith( + expect.objectContaining({ automation: heartbeatAutomation }), + ); + }); + it("updates only the requested schedule fields", async () => { const task = { - id: "d2ac39e9-14ac-4776-9279-37a1e455a5db", + id: SCHEDULE_ID, name: "Old name", prompt: "Keep this prompt", agentKind: "claude:home", config: { model: "claude-fable-5", effort: "medium" }, recurrence: { kind: "hourly", minute: 0 }, enabled: true, + automation: heartbeatAutomation, } as ScheduledTask; const { ctx, service } = context([task]); @@ -78,7 +215,76 @@ describe("Poracode app control tools", () => { prompt: "Keep this prompt", enabled: false, recurrence: { kind: "hourly", minute: 0 }, + automation: heartbeatAutomation, }), ); }); + + it("updates the full automation policy", async () => { + const task = { + id: SCHEDULE_ID, + name: "Migration", + prompt: "Continue", + agentKind: "codex", + config: { model: "gpt-5.6" }, + recurrence: { kind: "interval", every: 15, unit: "minutes" }, + enabled: true, + } as ScheduledTask; + const { ctx, service } = context([task]); + + await dispatchTool("update_schedule", { id: task.id, automation: heartbeatAutomation }, ctx); + + expect(service.update).toHaveBeenCalledWith( + task.id, + expect.objectContaining({ automation: heartbeatAutomation }), + ); + }); + + it("lists results for one schedule and the global inbox", async () => { + const task = { id: SCHEDULE_ID } as ScheduledTask; + const { ctx, scheduleRuns, run } = context([task]); + + await expect( + dispatchTool("list_schedule_runs", { scheduleId: SCHEDULE_ID }, ctx), + ).resolves.toEqual([run]); + expect(scheduleRuns.listScheduleRuns).toHaveBeenCalledWith(SCHEDULE_ID); + + await expect( + dispatchTool("list_schedule_run_inbox", { filter: "archived", limit: 25 }, ctx), + ).resolves.toEqual([run]); + expect(scheduleRuns.listScheduleRunInbox).toHaveBeenCalledWith({ + filter: "archived", + limit: 25, + }); + }); + + it("defaults the run inbox to unread results", async () => { + const { ctx, scheduleRuns } = context(); + + await dispatchTool("list_schedule_run_inbox", {}, ctx); + + expect(scheduleRuns.listScheduleRunInbox).toHaveBeenCalledWith({ filter: "unread" }); + }); + + it.each([ + ["mark_schedule_run_read", { unread: false }], + ["mark_schedule_run_unread", { unread: true }], + ["archive_schedule_run", { archived: true }], + ["restore_schedule_run", { archived: false }], + ])("applies the %s state transition", async (tool, patch) => { + const { ctx, scheduleRuns, run } = context(); + + await expect(dispatchTool(tool, { id: RUN_ID }, ctx)).resolves.toBe(run); + expect(scheduleRuns.updateScheduleRunState).toHaveBeenCalledWith({ id: RUN_ID, ...patch }); + }); + + it("cancels an active run through the schedule service", async () => { + const { ctx, service } = context(); + + await expect(dispatchTool("cancel_schedule_run", { id: RUN_ID }, ctx)).resolves.toEqual({ + id: RUN_ID, + cancelled: true, + }); + expect(service.cancelRun).toHaveBeenCalledWith(RUN_ID); + }); }); diff --git a/src/main/app-controls/mcp/toolRegistry.ts b/src/main/app-controls/mcp/toolRegistry.ts index 83760e182..d71c0cab6 100644 --- a/src/main/app-controls/mcp/toolRegistry.ts +++ b/src/main/app-controls/mcp/toolRegistry.ts @@ -1,50 +1,44 @@ -import { z } from "zod"; import type { McpThreadIdentity } from "@/shared/browserMcpThread"; import { isHomeProjectId } from "@/shared/homeScope"; import { - agentKindSchema, - scheduleRecurrenceSchema, + type ScheduleRunInboxQuery, type ScheduledTask, type ScheduledTaskInput, + type ScheduledTaskRun, type Thread, + type UpdateScheduleRunStatePayload, } from "@/shared/contracts"; import type { StreamableHttpMcpToolResult, StreamableHttpMcpToolSpec, } from "../../mcp/StreamableHttpMcpIngress"; import type { ScheduleService } from "../../schedules/ScheduleService"; +import { + automationJsonSchema, + createScheduleArgsSchema, + idArgsSchema, + idJsonSchema, + recurrenceJsonSchema, + scheduleRunInboxArgsSchema, + scheduleRunsArgsSchema, + updateScheduleArgsSchema, +} from "./scheduleToolSchemas"; export interface AppControlsToolContext { identity: McpThreadIdentity; scheduleService: ScheduleService; + scheduleRuns: AppControlsScheduleRunControls; getThread(threadId: string): Thread | null; } -const createArgsSchema = z.object({ - name: z.string().trim().min(1).max(120), - prompt: z.string().trim().min(1).max(50_000), - recurrence: scheduleRecurrenceSchema, - enabled: z.boolean().optional().default(true), - agentKind: agentKindSchema.optional(), - model: z.string().min(1).optional(), - effort: z.string().min(1).optional(), -}); - -const updateArgsSchema = z.object({ - id: z.string().uuid(), - name: z.string().trim().min(1).max(120).optional(), - prompt: z.string().trim().min(1).max(50_000).optional(), - recurrence: scheduleRecurrenceSchema.optional(), - enabled: z.boolean().optional(), - agentKind: agentKindSchema.optional(), - model: z.string().min(1).optional(), - effort: z.string().min(1).nullable().optional(), -}); - -const idArgsSchema = z.object({ id: z.string().uuid() }); +export interface AppControlsScheduleRunControls { + listScheduleRuns(scheduleId: string): ScheduledTaskRun[]; + listScheduleRunInbox(query: ScheduleRunInboxQuery): ScheduledTaskRun[]; + updateScheduleRunState(payload: UpdateScheduleRunStatePayload): ScheduledTaskRun | null; +} export const APP_CONTROLS_MCP_INSTRUCTIONS = - "Use these Poracode controls to list, create, update, run, and delete the user's device schedules. Explain consequential changes before making them. Schedules run only while the device is awake and Poracode is open."; + "Use these Poracode controls to manage the user's device schedules, automation policies, and run-result inbox. Explain consequential changes before making them. Schedules run only while the device is awake and Poracode is open."; export const TOOLS: readonly StreamableHttpMcpToolSpec[] = [ { @@ -68,6 +62,7 @@ export const TOOLS: readonly StreamableHttpMcpToolSpec[] = [ agentKind: { type: "string" }, model: { type: "string" }, effort: { type: "string" }, + automation: automationJsonSchema(), }, }, }, @@ -87,6 +82,7 @@ export const TOOLS: readonly StreamableHttpMcpToolSpec[] = [ agentKind: { type: "string" }, model: { type: "string" }, effort: { type: ["string", "null"] }, + automation: automationJsonSchema(), }, }, }, @@ -100,6 +96,53 @@ export const TOOLS: readonly StreamableHttpMcpToolSpec[] = [ description: "Permanently delete an existing schedule from this device.", inputSchema: idJsonSchema(), }, + { + name: "list_schedule_runs", + description: "List the newest run results for one schedule.", + inputSchema: { + type: "object", + additionalProperties: false, + required: ["scheduleId"], + properties: { scheduleId: { type: "string", format: "uuid" } }, + }, + }, + { + name: "list_schedule_run_inbox", + description: "List unread, current, or archived schedule run results across all schedules.", + inputSchema: { + type: "object", + additionalProperties: false, + properties: { + filter: { enum: ["unread", "all", "archived"], default: "unread" }, + limit: { type: "integer", minimum: 1, maximum: 100 }, + }, + }, + }, + { + name: "mark_schedule_run_read", + description: "Mark a schedule run result as read.", + inputSchema: idJsonSchema(), + }, + { + name: "mark_schedule_run_unread", + description: "Mark a schedule run result as unread.", + inputSchema: idJsonSchema(), + }, + { + name: "archive_schedule_run", + description: "Archive a schedule run result and mark it read.", + inputSchema: idJsonSchema(), + }, + { + name: "restore_schedule_run", + description: "Restore an archived schedule run result to the current inbox.", + inputSchema: idJsonSchema(), + }, + { + name: "cancel_schedule_run", + description: "Cancel an active schedule run by its run ID.", + inputSchema: idJsonSchema(), + }, ]; const TOOL_NAMES = new Set(TOOLS.map((tool) => tool.name)); @@ -115,7 +158,7 @@ export async function dispatchTool( ): Promise { if (name === "list_schedules") return ctx.scheduleService.list(); if (name === "create_schedule") { - const parsed = createArgsSchema.parse(args); + const parsed = createScheduleArgsSchema.parse(args); const sourceThread = ctx.identity.threadId ? ctx.getThread(ctx.identity.threadId) : null; const agentKind = parsed.agentKind ?? sourceThread?.agentKind; const model = parsed.model ?? sourceThread?.config.model; @@ -134,6 +177,7 @@ export async function dispatchTool( enabled: parsed.enabled, agentKind, ...(projectId ? { projectId } : {}), + ...(parsed.automation ? { automation: parsed.automation } : {}), config: { model, ...((parsed.effort ?? sourceThread?.config.effort) @@ -145,14 +189,17 @@ export async function dispatchTool( return ctx.scheduleService.create(input); } if (name === "update_schedule") { - const parsed = updateArgsSchema.parse(args); + const parsed = updateScheduleArgsSchema.parse(args); const current = requireSchedule(ctx, parsed.id); + const automation = parsed.automation ?? current.automation; return ctx.scheduleService.update(parsed.id, { name: parsed.name ?? current.name, prompt: parsed.prompt ?? current.prompt, recurrence: parsed.recurrence ?? current.recurrence, enabled: parsed.enabled ?? current.enabled, agentKind: parsed.agentKind ?? current.agentKind, + projectId: current.projectId ?? null, + ...(automation ? { automation } : {}), config: { model: parsed.model ?? current.config.model, ...(parsed.effort === null @@ -175,6 +222,30 @@ export async function dispatchTool( ctx.scheduleService.delete(id); return { deleted: true, id }; } + if (name === "list_schedule_runs") { + const { scheduleId } = scheduleRunsArgsSchema.parse(args); + requireSchedule(ctx, scheduleId); + return ctx.scheduleRuns.listScheduleRuns(scheduleId); + } + if (name === "list_schedule_run_inbox") { + return ctx.scheduleRuns.listScheduleRunInbox(scheduleRunInboxArgsSchema.parse(args)); + } + if (name === "mark_schedule_run_read") { + return updateScheduleRunState(ctx, idArgsSchema.parse(args).id, { unread: false }); + } + if (name === "mark_schedule_run_unread") { + return updateScheduleRunState(ctx, idArgsSchema.parse(args).id, { unread: true }); + } + if (name === "archive_schedule_run") { + return updateScheduleRunState(ctx, idArgsSchema.parse(args).id, { archived: true }); + } + if (name === "restore_schedule_run") { + return updateScheduleRunState(ctx, idArgsSchema.parse(args).id, { archived: false }); + } + if (name === "cancel_schedule_run") { + const { id } = idArgsSchema.parse(args); + return { id, cancelled: ctx.scheduleService.cancelRun(id) }; + } throw new Error(`Unknown tool: ${name}`); } @@ -188,50 +259,12 @@ function requireSchedule(ctx: AppControlsToolContext, id: string): ScheduledTask return task; } -function idJsonSchema(): Record { - return { - type: "object", - additionalProperties: false, - required: ["id"], - properties: { id: { type: "string", format: "uuid" } }, - }; -} - -function recurrenceJsonSchema(): Record { - return { - oneOf: [ - { - type: "object", - additionalProperties: false, - required: ["kind", "minute"], - properties: { - kind: { const: "hourly" }, - minute: { type: "integer", minimum: 0, maximum: 59 }, - }, - }, - { - type: "object", - additionalProperties: false, - required: ["kind", "days", "time"], - properties: { - kind: { const: "weekly" }, - days: { - type: "array", - minItems: 1, - items: { type: "integer", minimum: 0, maximum: 6 }, - }, - time: { type: "string", pattern: "^([01]\\d|2[0-3]):[0-5]\\d$" }, - }, - }, - { - type: "object", - additionalProperties: false, - required: ["kind", "runAt"], - properties: { - kind: { const: "once" }, - runAt: { type: "string", format: "date-time" }, - }, - }, - ], - }; +function updateScheduleRunState( + ctx: AppControlsToolContext, + id: string, + patch: Omit, +): ScheduledTaskRun { + const run = ctx.scheduleRuns.updateScheduleRunState({ id, ...patch }); + if (!run) throw new Error("Scheduled run not found."); + return run; } diff --git a/src/main/db.ts b/src/main/db.ts index 854f02306..a32016c69 100644 --- a/src/main/db.ts +++ b/src/main/db.ts @@ -34,6 +34,8 @@ export { dbReadThreadRuntimeSummaries, dbGetThreadRuntimeSummaries, dbGetThreadRuntimeItems, + dbGetThreadRuntimeItemCursor, + dbGetThreadRuntimeItemsAfter, dbGetThreadRuntimeItemsPage, dbTruncateThreadRuntimeAfter, dbApplyThreadRuntimeEvents, @@ -62,6 +64,9 @@ export { dbInsertScheduleRun, dbUpdateScheduleRun, dbListScheduleRuns, + dbListScheduleRunInbox, + dbGetUnreadScheduleRunCount, + dbUpdateScheduleRunState, dbDeleteScheduleRuns, dbInterruptScheduleRuns, type ScheduleRunPatch, diff --git a/src/main/db/connection.ts b/src/main/db/connection.ts index 9cbbbeec8..182ac28c2 100644 --- a/src/main/db/connection.ts +++ b/src/main/db/connection.ts @@ -186,6 +186,7 @@ export function initDatabase(dbPath: string) { agent_kind TEXT NOT NULL, config TEXT NOT NULL, recurrence TEXT NOT NULL, + automation TEXT, enabled INTEGER NOT NULL DEFAULT 1, project_id TEXT, next_run_at TEXT, @@ -194,6 +195,7 @@ export function initDatabase(dbPath: string) { last_status TEXT NOT NULL DEFAULT 'never', last_result TEXT, last_error TEXT, + iteration_count INTEGER NOT NULL DEFAULT 0, created_at TEXT NOT NULL, updated_at TEXT NOT NULL ); @@ -203,11 +205,19 @@ export function initDatabase(dbPath: string) { id TEXT PRIMARY KEY, schedule_id TEXT NOT NULL REFERENCES scheduled_tasks(id) ON DELETE CASCADE, thread_id TEXT NOT NULL, + scheduled_for TEXT NOT NULL, + trigger TEXT NOT NULL DEFAULT 'scheduled', + attempt INTEGER NOT NULL DEFAULT 1, + iteration INTEGER NOT NULL DEFAULT 1, started_at TEXT NOT NULL, completed_at TEXT, status TEXT NOT NULL, summary TEXT, - error TEXT + error TEXT, + result TEXT, + automation_snapshot TEXT, + unread INTEGER NOT NULL DEFAULT 0, + archived_at TEXT ); CREATE INDEX IF NOT EXISTS idx_scheduled_task_runs_schedule ON scheduled_task_runs (schedule_id, started_at DESC); @@ -225,7 +235,7 @@ export function initDatabase(dbPath: string) { // Baseline schema version for future DB migrations. // New upgrade steps should live behind this gate when we need them. - const SCHEMA_VERSION = 25; + const SCHEMA_VERSION = 26; const storedVersion = Number( ( @@ -419,6 +429,7 @@ export function initDatabase(dbPath: string) { agent_kind TEXT NOT NULL, config TEXT NOT NULL, recurrence TEXT NOT NULL, + automation TEXT, enabled INTEGER NOT NULL DEFAULT 1, next_run_at TEXT, last_run_at TEXT, @@ -426,6 +437,7 @@ export function initDatabase(dbPath: string) { last_status TEXT NOT NULL DEFAULT 'never', last_result TEXT, last_error TEXT, + iteration_count INTEGER NOT NULL DEFAULT 0, created_at TEXT NOT NULL, updated_at TEXT NOT NULL ); @@ -443,11 +455,19 @@ export function initDatabase(dbPath: string) { id TEXT PRIMARY KEY, schedule_id TEXT NOT NULL REFERENCES scheduled_tasks(id) ON DELETE CASCADE, thread_id TEXT NOT NULL, + scheduled_for TEXT NOT NULL, + trigger TEXT NOT NULL DEFAULT 'scheduled', + attempt INTEGER NOT NULL DEFAULT 1, + iteration INTEGER NOT NULL DEFAULT 1, started_at TEXT NOT NULL, completed_at TEXT, status TEXT NOT NULL, summary TEXT, - error TEXT + error TEXT, + result TEXT, + automation_snapshot TEXT, + unread INTEGER NOT NULL DEFAULT 0, + archived_at TEXT ); CREATE INDEX IF NOT EXISTS idx_scheduled_task_runs_schedule ON scheduled_task_runs (schedule_id, started_at DESC); @@ -486,6 +506,61 @@ export function initDatabase(dbPath: string) { `); } + if (storedVersion < 26) { + const taskColumns = sqlite.prepare("PRAGMA table_info(scheduled_tasks)").all() as { + name: string; + }[]; + if (!taskColumns.some((column) => column.name === "automation")) { + sqlite.exec("ALTER TABLE scheduled_tasks ADD COLUMN automation TEXT"); + } + if (!taskColumns.some((column) => column.name === "iteration_count")) { + sqlite.exec( + "ALTER TABLE scheduled_tasks ADD COLUMN iteration_count INTEGER NOT NULL DEFAULT 0", + ); + } + + const runColumns = sqlite.prepare("PRAGMA table_info(scheduled_task_runs)").all() as { + name: string; + }[]; + if (!runColumns.some((column) => column.name === "scheduled_for")) { + sqlite.exec("ALTER TABLE scheduled_task_runs ADD COLUMN scheduled_for TEXT"); + } + if (!runColumns.some((column) => column.name === "trigger")) { + sqlite.exec( + "ALTER TABLE scheduled_task_runs ADD COLUMN trigger TEXT NOT NULL DEFAULT 'scheduled'", + ); + } + if (!runColumns.some((column) => column.name === "attempt")) { + sqlite.exec( + "ALTER TABLE scheduled_task_runs ADD COLUMN attempt INTEGER NOT NULL DEFAULT 1", + ); + } + if (!runColumns.some((column) => column.name === "iteration")) { + sqlite.exec( + "ALTER TABLE scheduled_task_runs ADD COLUMN iteration INTEGER NOT NULL DEFAULT 1", + ); + } + if (!runColumns.some((column) => column.name === "result")) { + sqlite.exec("ALTER TABLE scheduled_task_runs ADD COLUMN result TEXT"); + } + if (!runColumns.some((column) => column.name === "automation_snapshot")) { + sqlite.exec("ALTER TABLE scheduled_task_runs ADD COLUMN automation_snapshot TEXT"); + } + if (!runColumns.some((column) => column.name === "unread")) { + sqlite.exec("ALTER TABLE scheduled_task_runs ADD COLUMN unread INTEGER NOT NULL DEFAULT 0"); + } + if (!runColumns.some((column) => column.name === "archived_at")) { + sqlite.exec("ALTER TABLE scheduled_task_runs ADD COLUMN archived_at TEXT"); + } + sqlite.exec(` + UPDATE scheduled_task_runs + SET scheduled_for = started_at + WHERE scheduled_for IS NULL; + CREATE INDEX IF NOT EXISTS idx_scheduled_task_runs_inbox + ON scheduled_task_runs (unread, archived_at, started_at DESC); + `); + } + sqlite .prepare( "INSERT INTO app_state (key, value) VALUES ('schema_version', ?) ON CONFLICT(key) DO UPDATE SET value = excluded.value", diff --git a/src/main/db/runtimeItems.test.ts b/src/main/db/runtimeItems.test.ts index b0b929228..1633f4f0d 100644 --- a/src/main/db/runtimeItems.test.ts +++ b/src/main/db/runtimeItems.test.ts @@ -9,7 +9,9 @@ import { dbUpsertProject, dbUpsertThread } from "./projectsThreads"; import { dbApplyThreadRuntimeEvents, dbGetThreadContextUsage, + dbGetThreadRuntimeItemCursor, dbGetThreadRuntimeItems, + dbGetThreadRuntimeItemsAfter, dbGetThreadRuntimeItemsPage, dbReplaceThreadRuntimeItems, dbTruncateThreadRuntimeAfter, @@ -209,4 +211,37 @@ describe.skipIf(!sqliteAvailable)("runtimeItems incremental persistence", () => expect(dbGetThreadRuntimeItems("thread-1")).toHaveLength(125); expect(dbGetThreadRuntimeItems("thread-1").at(-1)?.id).toBe("item-124"); }); + + it("reads only runtime items appended after a cursor", () => { + dbReplaceThreadRuntimeItems("thread-1", [ + { id: "old-assistant", type: "assistant_message", state: "completed", streams: {} }, + ]); + const cursor = dbGetThreadRuntimeItemCursor("thread-1"); + + dbApplyThreadRuntimeEvents("thread-1", [ + { + type: "item.started", + threadId: "thread-1", + itemId: "new-assistant", + itemType: "assistant_message", + }, + { + type: "content.delta", + threadId: "thread-1", + itemId: "new-assistant", + stream: "assistant_text", + delta: "Fresh result", + }, + ]); + + expect(cursor).toBe(0); + expect(dbGetThreadRuntimeItemsAfter("thread-1", cursor)).toEqual([ + { + id: "new-assistant", + type: "assistant_message", + state: "updated", + streams: { assistant_text: "Fresh result" }, + }, + ]); + }); }); diff --git a/src/main/db/runtimeItems.ts b/src/main/db/runtimeItems.ts index dd0fd7e35..5fa326e60 100644 --- a/src/main/db/runtimeItems.ts +++ b/src/main/db/runtimeItems.ts @@ -160,6 +160,30 @@ export function dbGetThreadRuntimeItems(threadId: string): PersistedRuntimeItem[ return rows.map(mapRuntimeItemRow); } +export function dbGetThreadRuntimeItemCursor(threadId: string): number { + const row = getSqlite() + .prepare( + "SELECT COALESCE(MAX(position), -1) AS position FROM thread_runtime_items WHERE thread_id = ?", + ) + .get(threadId) as { position: number }; + return row.position; +} + +export function dbGetThreadRuntimeItemsAfter( + threadId: string, + cursor: number, +): PersistedRuntimeItem[] { + const rows = getSqlite() + .prepare( + `SELECT item_id, type, state, payload, streams, parent_item_id + FROM thread_runtime_items + WHERE thread_id = ? AND position > ? + ORDER BY position ASC`, + ) + .all(threadId, cursor) as PersistedRuntimeItemRow[]; + return rows.map(mapRuntimeItemRow); +} + export function dbGetThreadRuntimeItemsPage( threadId: string, beforePosition: number | undefined, diff --git a/src/main/db/scheduleRuns.test.ts b/src/main/db/scheduleRuns.test.ts index 59767733f..83a953405 100644 --- a/src/main/db/scheduleRuns.test.ts +++ b/src/main/db/scheduleRuns.test.ts @@ -3,16 +3,24 @@ import { tmpdir } from "node:os"; import { join } from "node:path"; import Database from "better-sqlite3"; import { afterEach, beforeEach, describe, expect, it } from "vitest"; -import type { ScheduledTask, ScheduledTaskRun } from "@/shared/contracts"; +import { + DEFAULT_SCHEDULE_AUTOMATION, + type ScheduleRunResult, + type ScheduledTask, + type ScheduledTaskRun, +} from "@/shared/contracts"; import { closeDatabase, initDatabase } from "./connection"; import { dbDeleteScheduleRuns, + dbGetUnreadScheduleRunCount, dbInsertScheduleRun, dbInterruptScheduleRuns, + dbListScheduleRunInbox, dbListScheduleRuns, dbUpdateScheduleRun, + dbUpdateScheduleRunState, } from "./scheduleRuns"; -import { dbDeleteSchedule, dbUpsertSchedule } from "./schedules"; +import { dbDeleteSchedule, dbGetSchedule, dbUpsertSchedule } from "./schedules"; const serverNativeBinding = join(process.cwd(), "dist", "server-native", "better_sqlite3.node"); let nativeBindingEnv: string | undefined; @@ -37,6 +45,7 @@ function schedule(): ScheduledTask { agentKind: "claude:home", config: { model: "claude-fable-5" }, recurrence: { kind: "hourly", minute: 0 }, + automation: DEFAULT_SCHEDULE_AUTOMATION, enabled: true, nextRunAt: null, lastRunAt: null, @@ -44,6 +53,7 @@ function schedule(): ScheduledTask { lastStatus: "never", lastResult: null, lastError: null, + iterationCount: 0, createdAt: "2026-01-01T00:00:00.000Z", updatedAt: "2026-01-01T00:00:00.000Z", }; @@ -57,17 +67,37 @@ function run(overrides: Partial = {}): ScheduledTaskRun { id: `22222222-2222-4222-8222-${suffix}`, scheduleId: SCHEDULE_ID, threadId: `33333333-3333-4333-8333-${suffix}`, + scheduledFor: `2026-07-10T00:00:${String(runSeq % 60).padStart(2, "0")}.000Z`, + trigger: "scheduled", + attempt: 1, + iteration: 1, startedAt: `2026-07-10T00:00:${String(runSeq % 60).padStart(2, "0")}.000Z`, completedAt: null, status: "running", summary: null, error: null, + result: null, + automationSnapshot: DEFAULT_SCHEDULE_AUTOMATION, + ...overrides, + }; +} + +function result(overrides: Partial = {}): ScheduleRunResult { + return { + outcome: "findings", + summary: "Found something useful.", + severity: "info", + unread: false, + archivedAt: null, + changedFiles: [], + stopReason: null, ...overrides, }; } describe.skipIf(!sqliteAvailable)("scheduleRuns (real sqlite round-trip)", () => { let dir: string; + let dbPath: string; beforeEach(() => { if (nativeBindingEnv) { @@ -75,7 +105,8 @@ describe.skipIf(!sqliteAvailable)("scheduleRuns (real sqlite round-trip)", () => } runSeq = 0; dir = mkdtempSync(join(tmpdir(), "lc-runs-test-")); - initDatabase(join(dir, "state.sqlite")); + dbPath = join(dir, "state.sqlite"); + initDatabase(dbPath); dbUpsertSchedule(schedule()); }); @@ -93,7 +124,33 @@ describe.skipIf(!sqliteAvailable)("scheduleRuns (real sqlite round-trip)", () => const rows = dbListScheduleRuns(SCHEDULE_ID); expect(rows.map((row) => row.id)).toEqual([second.id, first.id]); - expect(rows[0]).toMatchObject({ status: "running", completedAt: null }); + expect(rows[0]).toMatchObject({ + status: "running", + completedAt: null, + scheduledFor: second.scheduledFor, + trigger: "scheduled", + attempt: 1, + iteration: 1, + automationSnapshot: DEFAULT_SCHEDULE_AUTOMATION, + }); + }); + + it("round-trips task automation and iteration state", () => { + const configured: ScheduledTask = { + ...schedule(), + automation: { + ...DEFAULT_SCHEDULE_AUTOMATION, + mode: { kind: "heartbeat", targetThreadId: "thread-1" }, + maxIterations: 8, + }, + iterationCount: 3, + }; + dbUpsertSchedule(configured); + + expect(dbGetSchedule(SCHEDULE_ID)).toMatchObject({ + automation: configured.automation, + iterationCount: 3, + }); }); it("updates a run by id", () => { @@ -102,21 +159,108 @@ describe.skipIf(!sqliteAvailable)("scheduleRuns (real sqlite round-trip)", () => dbUpdateScheduleRun(row.id, { completedAt: "2026-07-10T01:00:00.000Z", status: "succeeded", - summary: null, + summary: "Finished.", + attempt: 2, + iteration: 3, + result: result({ unread: true, summary: "Finished." }), }); const [stored] = dbListScheduleRuns(SCHEDULE_ID); expect(stored).toMatchObject({ status: "succeeded", completedAt: "2026-07-10T01:00:00.000Z", + summary: "Finished.", + attempt: 2, + iteration: 3, + result: expect.objectContaining({ unread: true, summary: "Finished." }), }); }); - it("prunes to at most 20 runs per schedule", () => { + it("prunes to the newest 20 read runs", () => { for (let i = 0; i < 25; i += 1) dbInsertScheduleRun(run()); expect(dbListScheduleRuns(SCHEDULE_ID, 100)).toHaveLength(20); }); + it("preserves every unread result alongside the newest 20 read runs", () => { + const unreadIds: string[] = []; + for (let i = 0; i < 3; i += 1) { + const row = run({ + status: "succeeded", + completedAt: "2026-07-10T01:00:00.000Z", + result: result({ unread: true }), + }); + unreadIds.push(row.id); + dbInsertScheduleRun(row); + } + for (let i = 0; i < 25; i += 1) { + dbInsertScheduleRun( + run({ + status: "succeeded", + completedAt: "2026-07-10T01:00:00.000Z", + result: result(), + }), + ); + } + + const rows = dbListScheduleRuns(SCHEDULE_ID, 100); + expect(rows).toHaveLength(23); + expect( + rows + .filter((row) => row.result?.unread) + .map((row) => row.id) + .sort(), + ).toEqual(unreadIds.sort()); + }); + + it("queries and updates inbox state", () => { + const unread = run({ + status: "succeeded", + completedAt: "2026-07-10T01:00:00.000Z", + result: result({ unread: true }), + }); + const read = run({ + status: "succeeded", + completedAt: "2026-07-10T01:00:00.000Z", + result: result(), + }); + const archived = run({ + status: "succeeded", + completedAt: "2026-07-10T01:00:00.000Z", + result: result({ archivedAt: "2026-07-10T02:00:00.000Z" }), + }); + const running = run(); + dbInsertScheduleRun(unread); + dbInsertScheduleRun(read); + dbInsertScheduleRun(archived); + dbInsertScheduleRun(running); + + expect(dbListScheduleRunInbox({ filter: "unread" }).map((row) => row.id)).toEqual([unread.id]); + expect(dbListScheduleRunInbox({ filter: "all" }).map((row) => row.id)).toEqual([ + running.id, + read.id, + unread.id, + ]); + expect(dbListScheduleRunInbox({ filter: "archived" }).map((row) => row.id)).toEqual([ + archived.id, + ]); + expect(dbGetUnreadScheduleRunCount()).toBe(1); + + const updated = dbUpdateScheduleRunState( + { id: unread.id, archived: true }, + "2026-07-10T03:00:00.000Z", + ); + expect(updated?.result).toMatchObject({ + unread: false, + archivedAt: "2026-07-10T03:00:00.000Z", + }); + expect(dbListScheduleRunInbox({ filter: "unread" })).toHaveLength(0); + expect(dbGetUnreadScheduleRunCount()).toBe(0); + + const restored = dbUpdateScheduleRunState({ id: unread.id, archived: false, unread: true }); + expect(restored?.result).toMatchObject({ unread: true, archivedAt: null }); + expect(dbListScheduleRunInbox({ filter: "unread" }).map((row) => row.id)).toEqual([unread.id]); + }); + it("marks dangling running rows interrupted", () => { dbInsertScheduleRun(run()); dbInsertScheduleRun(run({ status: "succeeded", completedAt: "2026-07-10T00:30:00.000Z" })); @@ -125,6 +269,87 @@ describe.skipIf(!sqliteAvailable)("scheduleRuns (real sqlite round-trip)", () => const rows = dbListScheduleRuns(SCHEDULE_ID); const statuses = rows.map((row) => row.status).sort(); expect(statuses).toEqual(["interrupted", "succeeded"]); + expect(dbListScheduleRunInbox({ filter: "unread" })[0]?.result).toMatchObject({ + outcome: "needs-attention", + unread: true, + stopReason: "interrupted", + }); + }); + + it("migrates v25 schedule rows with backward-compatible defaults", () => { + closeDatabase(); + rmSync(dbPath, { force: true }); + const legacy = new Database( + dbPath, + nativeBindingEnv ? { nativeBinding: nativeBindingEnv } : {}, + ); + legacy.exec(` + PRAGMA foreign_keys = ON; + CREATE TABLE app_state (key TEXT PRIMARY KEY, value TEXT NOT NULL); + INSERT INTO app_state (key, value) VALUES ('schema_version', '25'); + CREATE TABLE scheduled_tasks ( + id TEXT PRIMARY KEY, + name TEXT NOT NULL, + prompt TEXT NOT NULL, + agent_kind TEXT NOT NULL, + config TEXT NOT NULL, + recurrence TEXT NOT NULL, + enabled INTEGER NOT NULL DEFAULT 1, + project_id TEXT, + next_run_at TEXT, + last_run_at TEXT, + last_completed_at TEXT, + last_status TEXT NOT NULL DEFAULT 'never', + last_result TEXT, + last_error TEXT, + created_at TEXT NOT NULL, + updated_at TEXT NOT NULL + ); + CREATE TABLE scheduled_task_runs ( + id TEXT PRIMARY KEY, + schedule_id TEXT NOT NULL REFERENCES scheduled_tasks(id) ON DELETE CASCADE, + thread_id TEXT NOT NULL, + started_at TEXT NOT NULL, + completed_at TEXT, + status TEXT NOT NULL, + summary TEXT, + error TEXT + ); + INSERT INTO scheduled_tasks ( + id, name, prompt, agent_kind, config, recurrence, enabled, project_id, + next_run_at, last_run_at, last_completed_at, last_status, + last_result, last_error, created_at, updated_at + ) VALUES ( + '${SCHEDULE_ID}', 'Legacy', 'Review.', 'claude:home', + '{"model":"claude-fable-5"}', '{"kind":"hourly","minute":0}', + 1, NULL, NULL, NULL, NULL, 'succeeded', NULL, NULL, + '2026-01-01T00:00:00.000Z', '2026-01-01T00:00:00.000Z' + ); + INSERT INTO scheduled_task_runs ( + id, schedule_id, thread_id, started_at, completed_at, status, summary, error + ) VALUES ( + '22222222-2222-4222-8222-000000000001', '${SCHEDULE_ID}', 'legacy-thread', + '2026-07-10T00:00:00.000Z', '2026-07-10T00:01:00.000Z', + 'succeeded', 'Legacy result', NULL + ); + `); + legacy.close(); + + initDatabase(dbPath); + + expect(dbGetSchedule(SCHEDULE_ID)).toMatchObject({ + automation: DEFAULT_SCHEDULE_AUTOMATION, + iterationCount: 0, + }); + expect(dbListScheduleRuns(SCHEDULE_ID)[0]).toMatchObject({ + scheduledFor: "2026-07-10T00:00:00.000Z", + trigger: "scheduled", + attempt: 1, + iteration: 1, + result: null, + automationSnapshot: DEFAULT_SCHEDULE_AUTOMATION, + }); + expect(dbListScheduleRunInbox({ filter: "unread" })).toHaveLength(0); }); it("cascade-deletes runs when the parent schedule is deleted", () => { diff --git a/src/main/db/scheduleRuns.ts b/src/main/db/scheduleRuns.ts index 5d7ad4569..dff8dffcd 100644 --- a/src/main/db/scheduleRuns.ts +++ b/src/main/db/scheduleRuns.ts @@ -1,18 +1,47 @@ -import { scheduledTaskRunSchema, type ScheduledTaskRun } from "@/shared/contracts"; +import { + resolveScheduleAutomation, + scheduleAutomationSchema, + scheduleRunInboxQuerySchema, + scheduleRunResultSchema, + scheduledTaskRunSchema, + updateScheduleRunStatePayloadSchema, + type ScheduleRunInboxQuery, + type ScheduleRunResult, + type ScheduledTaskRun, + type UpdateScheduleRunStatePayload, +} from "@/shared/contracts"; import { getSqlite } from "./connection"; -/** Keep at most this many run rows per schedule; older rows are pruned on insert. */ -const MAX_RUNS_PER_SCHEDULE = 20; +/** Keep the newest read/archived rows per schedule; unread findings are never pruned. */ +const MAX_READ_RUNS_PER_SCHEDULE = 20; +const DEFAULT_INBOX_LIMIT = 50; interface ScheduledTaskRunRow { id: string; schedule_id: string; thread_id: string; + scheduled_for: string | null; + trigger: string | null; + attempt: number | null; + iteration: number | null; started_at: string; completed_at: string | null; status: string; summary: string | null; error: string | null; + result: string | null; + automation_snapshot: string | null; + unread: number | null; + archived_at: string | null; +} + +function parseResult(row: ScheduledTaskRunRow): ScheduleRunResult | null { + if (!row.result) return null; + return scheduleRunResultSchema.parse({ + ...JSON.parse(row.result), + unread: row.unread === 1, + archivedAt: row.archived_at, + }); } function fromRow(row: ScheduledTaskRunRow): ScheduledTaskRun { @@ -20,11 +49,19 @@ function fromRow(row: ScheduledTaskRunRow): ScheduledTaskRun { id: row.id, scheduleId: row.schedule_id, threadId: row.thread_id, + scheduledFor: row.scheduled_for || row.started_at, + trigger: row.trigger ?? "scheduled", + attempt: row.attempt ?? 1, + iteration: row.iteration ?? 1, startedAt: row.started_at, completedAt: row.completed_at, status: row.status, summary: row.summary, error: row.error, + result: parseResult(row), + automationSnapshot: row.automation_snapshot + ? scheduleAutomationSchema.parse(JSON.parse(row.automation_snapshot)) + : resolveScheduleAutomation(undefined), }); } @@ -34,18 +71,28 @@ export function dbInsertScheduleRun(run: ScheduledTaskRun): void { sqlite .prepare( `INSERT INTO scheduled_task_runs ( - id, schedule_id, thread_id, started_at, completed_at, status, summary, error - ) VALUES (?, ?, ?, ?, ?, ?, ?, ?)`, + id, schedule_id, thread_id, scheduled_for, trigger, attempt, iteration, + started_at, completed_at, status, summary, error, result, + automation_snapshot, unread, archived_at + ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, ) .run( parsed.id, parsed.scheduleId, parsed.threadId, + parsed.scheduledFor, + parsed.trigger, + parsed.attempt, + parsed.iteration, parsed.startedAt, parsed.completedAt, parsed.status, parsed.summary, parsed.error, + parsed.result ? JSON.stringify(parsed.result) : null, + JSON.stringify(parsed.automationSnapshot), + parsed.result?.unread ? 1 : 0, + parsed.result?.archivedAt ?? null, ); pruneScheduleRuns(parsed.scheduleId); } @@ -55,11 +102,14 @@ export interface ScheduleRunPatch { status?: ScheduledTaskRun["status"]; summary?: string | null; error?: string | null; + attempt?: number; + iteration?: number; + result?: ScheduleRunResult | null; } export function dbUpdateScheduleRun(id: string, patch: ScheduleRunPatch): void { const sets: string[] = []; - const values: (string | null)[] = []; + const values: (string | number | null)[] = []; if ("completedAt" in patch) { sets.push("completed_at = ?"); values.push(patch.completedAt ?? null); @@ -76,6 +126,23 @@ export function dbUpdateScheduleRun(id: string, patch: ScheduleRunPatch): void { sets.push("error = ?"); values.push(patch.error ?? null); } + if ("attempt" in patch && patch.attempt !== undefined) { + sets.push("attempt = ?"); + values.push(patch.attempt); + } + if ("iteration" in patch && patch.iteration !== undefined) { + sets.push("iteration = ?"); + values.push(patch.iteration); + } + if ("result" in patch) { + const result = patch.result ? scheduleRunResultSchema.parse(patch.result) : null; + sets.push("result = ?", "unread = ?", "archived_at = ?"); + values.push( + result ? JSON.stringify(result) : null, + result?.unread ? 1 : 0, + result?.archivedAt ?? null, + ); + } if (sets.length === 0) return; values.push(id); getSqlite() @@ -85,7 +152,7 @@ export function dbUpdateScheduleRun(id: string, patch: ScheduleRunPatch): void { export function dbListScheduleRuns( scheduleId: string, - limit = MAX_RUNS_PER_SCHEDULE, + limit = MAX_READ_RUNS_PER_SCHEDULE, ): ScheduledTaskRun[] { const rows = getSqlite() .prepare( @@ -98,6 +165,79 @@ export function dbListScheduleRuns( return rows.map(fromRow); } +export function dbListScheduleRunInbox(query: ScheduleRunInboxQuery): ScheduledTaskRun[] { + const parsed = scheduleRunInboxQuerySchema.parse(query); + const stateClause = + parsed.filter === "unread" + ? "unread = 1 AND archived_at IS NULL" + : parsed.filter === "archived" + ? "archived_at IS NOT NULL" + : "archived_at IS NULL"; + const rows = getSqlite() + .prepare( + `SELECT * FROM scheduled_task_runs + WHERE (result IS NOT NULL OR status = 'running') AND ${stateClause} + ORDER BY started_at DESC, rowid DESC + LIMIT ?`, + ) + .all(parsed.limit ?? DEFAULT_INBOX_LIMIT) as ScheduledTaskRunRow[]; + return rows.map(fromRow); +} + +export function dbGetUnreadScheduleRunCount(): number { + const row = getSqlite() + .prepare( + `SELECT COUNT(*) AS count + FROM scheduled_task_runs + WHERE unread = 1 AND archived_at IS NULL`, + ) + .get() as { count: number }; + return row.count; +} + +export function dbUpdateScheduleRunState( + payload: UpdateScheduleRunStatePayload, + archivedAt = new Date().toISOString(), +): ScheduledTaskRun | null { + const parsed = updateScheduleRunStatePayloadSchema.parse(payload); + const sqlite = getSqlite(); + const row = sqlite.prepare("SELECT * FROM scheduled_task_runs WHERE id = ?").get(parsed.id) as + | ScheduledTaskRunRow + | undefined; + if (!row) return null; + + const current = fromRow(row); + const currentResult: ScheduleRunResult = current.result ?? { + outcome: "unknown", + summary: current.summary, + severity: current.error ? "error" : "info", + unread: false, + archivedAt: null, + changedFiles: [], + stopReason: null, + }; + const nextResult = scheduleRunResultSchema.parse({ + ...currentResult, + unread: parsed.archived === true ? false : (parsed.unread ?? currentResult.unread), + archivedAt: + parsed.archived === undefined + ? currentResult.archivedAt + : parsed.archived + ? archivedAt + : null, + }); + sqlite + .prepare("UPDATE scheduled_task_runs SET result = ?, unread = ?, archived_at = ? WHERE id = ?") + .run(JSON.stringify(nextResult), nextResult.unread ? 1 : 0, nextResult.archivedAt, parsed.id); + + return fromRow({ + ...row, + result: JSON.stringify(nextResult), + unread: nextResult.unread ? 1 : 0, + archived_at: nextResult.archivedAt, + }); +} + export function dbDeleteScheduleRuns(scheduleId: string): void { getSqlite().prepare("DELETE FROM scheduled_task_runs WHERE schedule_id = ?").run(scheduleId); } @@ -108,11 +248,29 @@ export function dbDeleteScheduleRuns(scheduleId: string): void { * service's post-startup normalization. */ export function dbInterruptScheduleRuns(scheduleId: string, completedAt: string): void { - getSqlite() - .prepare( - "UPDATE scheduled_task_runs SET status = 'interrupted', completed_at = ? WHERE schedule_id = ? AND status = 'running'", - ) - .run(completedAt, scheduleId); + const sqlite = getSqlite(); + const rows = sqlite + .prepare("SELECT * FROM scheduled_task_runs WHERE schedule_id = ? AND status = 'running'") + .all(scheduleId) as ScheduledTaskRunRow[]; + const update = sqlite.prepare( + `UPDATE scheduled_task_runs + SET status = 'interrupted', completed_at = ?, result = ?, unread = 1, archived_at = NULL + WHERE id = ?`, + ); + sqlite.transaction(() => { + for (const row of rows) { + const result = scheduleRunResultSchema.parse({ + outcome: "needs-attention", + summary: row.summary, + severity: "warning", + unread: true, + archivedAt: null, + changedFiles: [], + stopReason: "interrupted", + }); + update.run(completedAt, JSON.stringify(result), row.id); + } + })(); } function pruneScheduleRuns(scheduleId: string): void { @@ -120,12 +278,13 @@ function pruneScheduleRuns(scheduleId: string): void { .prepare( `DELETE FROM scheduled_task_runs WHERE schedule_id = ? + AND unread = 0 AND id NOT IN ( SELECT id FROM scheduled_task_runs - WHERE schedule_id = ? + WHERE schedule_id = ? AND unread = 0 ORDER BY started_at DESC, rowid DESC LIMIT ? )`, ) - .run(scheduleId, scheduleId, MAX_RUNS_PER_SCHEDULE); + .run(scheduleId, scheduleId, MAX_READ_RUNS_PER_SCHEDULE); } diff --git a/src/main/db/schedules.ts b/src/main/db/schedules.ts index ffe538dc5..a9e0ee060 100644 --- a/src/main/db/schedules.ts +++ b/src/main/db/schedules.ts @@ -1,4 +1,6 @@ import { + resolveScheduleAutomation, + scheduleAutomationSchema, scheduledTaskConfigSchema, scheduledTaskSchema, scheduleRecurrenceSchema, @@ -13,6 +15,7 @@ interface ScheduledTaskRow { agent_kind: string; config: string; recurrence: string; + automation: string | null; enabled: number; project_id: string | null; next_run_at: string | null; @@ -21,6 +24,7 @@ interface ScheduledTaskRow { last_status: string; last_result: string | null; last_error: string | null; + iteration_count: number; created_at: string; updated_at: string; } @@ -33,6 +37,9 @@ function fromRow(row: ScheduledTaskRow): ScheduledTask { agentKind: row.agent_kind, config: scheduledTaskConfigSchema.parse(JSON.parse(row.config)), recurrence: scheduleRecurrenceSchema.parse(JSON.parse(row.recurrence)), + automation: row.automation + ? scheduleAutomationSchema.parse(JSON.parse(row.automation)) + : resolveScheduleAutomation(undefined), enabled: row.enabled === 1, projectId: row.project_id, nextRunAt: row.next_run_at, @@ -41,6 +48,7 @@ function fromRow(row: ScheduledTaskRow): ScheduledTask { lastStatus: row.last_status, lastResult: row.last_result, lastError: row.last_error, + iterationCount: row.iteration_count ?? 0, createdAt: row.created_at, updatedAt: row.updated_at, }); @@ -62,19 +70,21 @@ export function dbGetSchedule(id: string): ScheduledTask | null { export function dbUpsertSchedule(task: ScheduledTask): void { const parsed = scheduledTaskSchema.parse(task); + const automation = resolveScheduleAutomation(parsed.automation); getSqlite() .prepare( `INSERT INTO scheduled_tasks ( - id, name, prompt, agent_kind, config, recurrence, enabled, project_id, + id, name, prompt, agent_kind, config, recurrence, automation, enabled, project_id, next_run_at, last_run_at, last_completed_at, last_status, - last_result, last_error, created_at, updated_at - ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) + last_result, last_error, iteration_count, created_at, updated_at + ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) ON CONFLICT(id) DO UPDATE SET name = excluded.name, prompt = excluded.prompt, agent_kind = excluded.agent_kind, config = excluded.config, recurrence = excluded.recurrence, + automation = excluded.automation, enabled = excluded.enabled, project_id = excluded.project_id, next_run_at = excluded.next_run_at, @@ -83,6 +93,7 @@ export function dbUpsertSchedule(task: ScheduledTask): void { last_status = excluded.last_status, last_result = excluded.last_result, last_error = excluded.last_error, + iteration_count = excluded.iteration_count, updated_at = excluded.updated_at`, ) .run( @@ -92,6 +103,7 @@ export function dbUpsertSchedule(task: ScheduledTask): void { parsed.agentKind, JSON.stringify(parsed.config), JSON.stringify(parsed.recurrence), + JSON.stringify(automation), parsed.enabled ? 1 : 0, parsed.projectId ?? null, parsed.nextRunAt, @@ -100,6 +112,7 @@ export function dbUpsertSchedule(task: ScheduledTask): void { parsed.lastStatus, parsed.lastResult, parsed.lastError, + parsed.iterationCount ?? 0, parsed.createdAt, parsed.updatedAt, ); diff --git a/src/main/ipc/localHandlers.ts b/src/main/ipc/localHandlers.ts index 198ce25ba..857e9c8c6 100644 --- a/src/main/ipc/localHandlers.ts +++ b/src/main/ipc/localHandlers.ts @@ -16,6 +16,8 @@ import { dbTruncateThreadRuntimeAfter, dbGetThreads, dbListScheduleRuns, + dbListScheduleRunInbox, + dbGetUnreadScheduleRunCount, dbReplaceThreadCompletedTurns, dbReplaceThreadRuntimeSnapshot, dbReplaceThreadRuntimeItems, @@ -24,6 +26,7 @@ import { dbSyncAll, dbUpsertProject, dbUpsertThread, + dbUpdateScheduleRunState, } from "../db"; import { deleteThreadAttachments, @@ -430,11 +433,19 @@ export function createLocalIpcHandlers( dbGetProjectNotes: ({ projectId }) => dbGetProjectNotes(projectId), dbSetProjectNotes: (notes) => dbSetProjectNotes(notes), getSchedules: () => options.scheduleService.list(), + getAutomationsSnapshot: (query) => ({ + schedules: options.scheduleService.list(), + runs: dbListScheduleRunInbox(query), + unreadCount: dbGetUnreadScheduleRunCount(), + }), createSchedule: (task) => options.scheduleService.create(task), updateSchedule: ({ id, task }) => options.scheduleService.update(id, task), deleteSchedule: ({ id }) => options.scheduleService.delete(id), runScheduleNow: ({ id }) => options.scheduleService.runNow(id), getScheduleRuns: ({ id }) => dbListScheduleRuns(id), + getScheduleRunInbox: (query) => dbListScheduleRunInbox(query), + updateScheduleRunState: (payload) => dbUpdateScheduleRunState(payload), + cancelScheduleRun: ({ id }) => options.scheduleService.cancelRun(id), checkForUpdate: () => options.autoUpdater.checkForUpdate(), startUpdateDownload: () => options.autoUpdater.startUpdateDownload(), installUpdate: () => options.autoUpdater.installUpdate(), diff --git a/src/main/main.ts b/src/main/main.ts index 81152f4d3..f2868b1d7 100644 --- a/src/main/main.ts +++ b/src/main/main.ts @@ -16,10 +16,15 @@ import { dbDeleteThread, dbGetProject, dbGetThread, + dbGetThreadRuntimeItemCursor, + dbGetThreadRuntimeItemsAfter, dbGetThreads, dbInsertScheduleRun, dbInterruptScheduleRuns, + dbListScheduleRunInbox, + dbListScheduleRuns, dbUpdateScheduleRun, + dbUpdateScheduleRunState, dbUpsertThread, initDatabase, } from "./db"; @@ -694,12 +699,17 @@ if (!hasSingleInstanceLock) { forwardAgentStatusEventToQuickComposer(event); }, onReset: () => { + scheduleRunCoordinator?.handleSupervisorReset(); workingThreads.clear(); updatePowerSaveBlocker(); }, }); const scheduleCoordinator = new ScheduleRunCoordinator({ startThread: (payload) => supervisorClient.call("startThread", payload), + sendThreadInput: (payload) => supervisorClient.call("sendThreadInput", payload), + interruptThread: (threadId) => supervisorClient.call("interruptThread", { threadId }), + evaluateCompletion: (payload) => + supervisorClient.call("evaluateScheduleCompletion", payload), getAgentStatuses: (wslDistros) => supervisorClient.call("getAgentStatuses", { wslDistros }), sendThreadCommand: (command) => { if (!mainWindow) return false; @@ -708,6 +718,9 @@ if (!hasSingleInstanceLock) { }, ensureHomeProject: ensureHomeProjectRow, getProject: dbGetProject, + getThread: dbGetThread, + getThreadRuntimeItemCursor: dbGetThreadRuntimeItemCursor, + getThreadRuntimeItemsAfter: dbGetThreadRuntimeItemsAfter, getSharedSettings: () => readSharedSettingsFile(requirePoracodePaths().settingsPath), upsertThread: dbUpsertThread, deleteThread: dbDeleteThread, @@ -717,11 +730,20 @@ if (!hasSingleInstanceLock) { }); scheduleRunCoordinator = scheduleCoordinator; const scheduleService = createDeviceScheduleService({ - runTask: (task) => scheduleCoordinator.runScheduleAsThread(task), + runTask: (task, context) => scheduleCoordinator.runScheduleAsThread(task, context), + cancelRun: (runId) => scheduleCoordinator.cancelRun(runId), + recordSkipped: (task, context) => scheduleCoordinator.recordSkippedRun(task, context), + onRetryingRun: (runId) => { + dbUpdateScheduleRunState({ id: runId, unread: false, archived: true }); + }, onStartupInterrupted: (scheduleId) => dbInterruptScheduleRuns(scheduleId, new Date().toISOString()), }); - appControlsMcpIngress = new AppControlsMcpIngress(scheduleService, dbGetThread); + appControlsMcpIngress = new AppControlsMcpIngress(scheduleService, dbGetThread, { + listScheduleRuns: dbListScheduleRuns, + listScheduleRunInbox: dbListScheduleRunInbox, + updateScheduleRunState: dbUpdateScheduleRunState, + }); const autoUpdaterController = createAutoUpdaterController( (status) => { diff --git a/src/main/remote/DesktopRemoteAccessController.ts b/src/main/remote/DesktopRemoteAccessController.ts index b91039d81..8cf479c17 100644 --- a/src/main/remote/DesktopRemoteAccessController.ts +++ b/src/main/remote/DesktopRemoteAccessController.ts @@ -1,5 +1,12 @@ import type { BrowserPanelManager } from "../browser"; -import { dbGetProject, dbGetProjects, dbGetThreads } from "../db"; +import { + dbGetProject, + dbGetProjects, + dbGetThreads, + dbListScheduleRunInbox, + dbListScheduleRuns, + dbUpdateScheduleRunState, +} from "../db"; import { patchSharedSettingsFile, readSharedSettingsFile } from "../sharedSettingsFile"; import type { PoracodeDiagnosticTags } from "@/shared/diagnostics/sentryPrivacy"; import type { @@ -311,9 +318,17 @@ export function createDesktopRemoteAccessController( return pickRemoteSettings(next); }, }, - // `ScheduleService`'s public methods already match the gateway - // interface, so pass it directly instead of re-wrapping each method. - schedules: options.scheduleService, + schedules: { + list: () => options.scheduleService.list(), + create: (task) => options.scheduleService.create(task), + update: (id, task) => options.scheduleService.update(id, task), + delete: (id) => options.scheduleService.delete(id), + runNow: (id) => options.scheduleService.runNow(id), + listRuns: (scheduleId) => dbListScheduleRuns(scheduleId), + listInbox: (query) => dbListScheduleRunInbox(query), + updateRunState: (payload) => dbUpdateScheduleRunState(payload), + cancelRun: (runId) => options.scheduleService.cancelRun(runId), + }, pushRegistrations: { upsert: (registration) => pushStore.upsert(registration), remove: (deviceId) => pushStore.remove(deviceId), diff --git a/src/main/remote/RemoteAccessServer.test.ts b/src/main/remote/RemoteAccessServer.test.ts index a92495ce6..a6146ac00 100644 --- a/src/main/remote/RemoteAccessServer.test.ts +++ b/src/main/remote/RemoteAccessServer.test.ts @@ -8,7 +8,16 @@ import { import { connect, createServer as createNetServer, type AddressInfo, type Socket } from "node:net"; import { WebSocket, WebSocketServer } from "ws"; import { afterEach, describe, expect, it, vi } from "vitest"; -import type { Project, ScheduledTask, ScheduledTaskInput, Thread } from "@/shared/contracts"; +import { + DEFAULT_SCHEDULE_AUTOMATION, + type Project, + type ScheduleRunInboxQuery, + type ScheduledTask, + type ScheduledTaskInput, + type ScheduledTaskRun, + type Thread, + type UpdateScheduleRunStatePayload, +} from "@/shared/contracts"; import type { SupervisorEvent } from "@/shared/ipc"; import { pickRemoteSettings, type RemoteSettings } from "@/shared/remote"; import { defaultSharedSettings } from "@/shared/settings"; @@ -2996,6 +3005,30 @@ describe("RemoteAccessServer", () => { it("lists and modifies device schedules with read and operate scopes", async () => { let stored: ScheduledTask[] = []; + const run: ScheduledTaskRun = { + id: "6f3b1a2c-1111-4d5e-8a9b-0c1d2e3f4a5b", + scheduleId: "d2ac39e9-14ac-4776-9279-37a1e455a5db", + threadId: "thread-schedule-run", + scheduledFor: "2026-07-13T15:00:00.000Z", + trigger: "scheduled", + attempt: 1, + iteration: 1, + startedAt: "2026-07-13T15:00:00.000Z", + completedAt: "2026-07-13T15:01:00.000Z", + status: "succeeded", + summary: "Found one item.", + error: null, + result: { + outcome: "findings", + summary: "Found one item.", + severity: "warning", + unread: true, + archivedAt: null, + changedFiles: [], + stopReason: null, + }, + automationSnapshot: DEFAULT_SCHEDULE_AUTOMATION, + }; const input: ScheduledTaskInput = { name: "Daily brief", prompt: "Summarize my priorities.", @@ -3020,6 +3053,15 @@ describe("RemoteAccessServer", () => { stored = [created]; return created; }); + const listRuns = vi.fn<(scheduleId: string) => ScheduledTaskRun[]>(() => [run]); + const listInbox = vi.fn<(query: ScheduleRunInboxQuery) => ScheduledTaskRun[]>(() => [run]); + const updateRunState = vi.fn< + (payload: UpdateScheduleRunStatePayload) => ScheduledTaskRun | null + >(() => ({ + ...run, + result: run.result ? { ...run.result, unread: false } : null, + })); + const cancelRun = vi.fn<(runId: string) => boolean>(() => true); const server = new RemoteAccessServer({ appVersion: "1.0.0", identity: { desktopId: "desktop-test", label: "Test Desktop" }, @@ -3042,6 +3084,10 @@ describe("RemoteAccessServer", () => { stored = [next]; return next; }, + listRuns, + listInbox, + updateRunState, + cancelRun, }, }); servers.push(server); @@ -3062,6 +3108,37 @@ describe("RemoteAccessServer", () => { }); expect(denied.status).toBe(403); + const scheduleRunsResponse = await fetch( + new URL("/api/schedules/runs/query", info.httpBaseUrl), + { + method: "POST", + headers: { ...readHeaders, "content-type": "application/json" }, + body: JSON.stringify({ + kind: "schedule", + payload: { id: run.scheduleId }, + }), + }, + ); + expect(scheduleRunsResponse.status).toBe(200); + await expect(scheduleRunsResponse.json()).resolves.toEqual({ runs: [run] }); + expect(listRuns).toHaveBeenCalledWith(run.scheduleId); + + const inboxResponse = await fetch(new URL("/api/schedules/runs/query", info.httpBaseUrl), { + method: "POST", + headers: { ...readHeaders, "content-type": "application/json" }, + body: JSON.stringify({ kind: "inbox", query: { filter: "unread", limit: 25 } }), + }); + expect(inboxResponse.status).toBe(200); + await expect(inboxResponse.json()).resolves.toEqual({ runs: [run] }); + expect(listInbox).toHaveBeenCalledWith({ filter: "unread", limit: 25 }); + + const deniedRunCommand = await fetch(new URL("/api/schedules/runs/command", info.httpBaseUrl), { + method: "POST", + headers: { ...readHeaders, "content-type": "application/json" }, + body: JSON.stringify({ kind: "cancel", id: run.id }), + }); + expect(deniedRunCommand.status).toBe(403); + const pairing = new URL(server.issuePairingUrl()); const credential = new URLSearchParams(pairing.hash.slice(1)).get("token"); const tokenResponse = await fetch(new URL("/oauth/token", info.httpBaseUrl), { @@ -3088,6 +3165,36 @@ describe("RemoteAccessServer", () => { schedules: [{ name: "Daily brief" }], }); expect(create).toHaveBeenCalledWith(input); + + const operateHeaders = { + authorization: `Bearer ${operateToken}`, + "content-type": "application/json", + }; + const updateRunResponse = await fetch( + new URL("/api/schedules/runs/command", info.httpBaseUrl), + { + method: "POST", + headers: operateHeaders, + body: JSON.stringify({ + kind: "update-state", + payload: { id: run.id, unread: false }, + }), + }, + ); + expect(updateRunResponse.status).toBe(200); + await expect(updateRunResponse.json()).resolves.toMatchObject({ + run: { id: run.id, result: { unread: false } }, + }); + expect(updateRunState).toHaveBeenCalledWith({ id: run.id, unread: false }); + + const cancelResponse = await fetch(new URL("/api/schedules/runs/command", info.httpBaseUrl), { + method: "POST", + headers: operateHeaders, + body: JSON.stringify({ kind: "cancel", id: run.id }), + }); + expect(cancelResponse.status).toBe(200); + await expect(cancelResponse.json()).resolves.toEqual({ cancelled: true }); + expect(cancelRun).toHaveBeenCalledWith(run.id); }); it("serves profile devices/stats reads and the identity write, gated by scope", async () => { diff --git a/src/main/remote/RemoteAccessServer.ts b/src/main/remote/RemoteAccessServer.ts index 53236e26b..5855e8833 100644 --- a/src/main/remote/RemoteAccessServer.ts +++ b/src/main/remote/RemoteAccessServer.ts @@ -13,8 +13,11 @@ import { import type { McpLaunchSnapshot, RemoteThreadCommand, + ScheduleRunInboxQuery, ScheduledTask, ScheduledTaskInput, + ScheduledTaskRun, + UpdateScheduleRunStatePayload, } from "@/shared/contracts"; import type { IpcProcedurePayload, @@ -148,6 +151,10 @@ export interface RemoteAccessServerOptions { update(id: string, task: ScheduledTaskInput): ScheduledTask; delete(id: string): void; runNow(id: string): ScheduledTask; + listRuns(scheduleId: string): ScheduledTaskRun[]; + listInbox(query: ScheduleRunInboxQuery): ScheduledTaskRun[]; + updateRunState(payload: UpdateScheduleRunStatePayload): ScheduledTaskRun | null; + cancelRun(runId: string): boolean; }; /** Latest per-thread git/PR summaries published by the desktop renderer. */ gitSummaries?(): RemoteGitSummaries; diff --git a/src/main/remote/server/httpRouter.ts b/src/main/remote/server/httpRouter.ts index 1aaa222d0..790e2b962 100644 --- a/src/main/remote/server/httpRouter.ts +++ b/src/main/remote/server/httpRouter.ts @@ -12,6 +12,8 @@ import { remotePushUnregisterSchema, remoteSettingsPatchSchema, remoteScheduleCommandSchema, + remoteScheduleRunCommandSchema, + remoteScheduleRunsQuerySchema, remoteTokenExchangePayloadSchema, REMOTE_COMMAND_ID_HEADER, type RemoteAccessScope, @@ -413,6 +415,32 @@ export async function handleHttp( writeJson(res, 200, { schedule, schedules: schedules.list() }); return; } + if (req.method === "POST" && url.pathname === "/api/schedules/runs/query") { + ctx.security.requireBearer(req, ["session:read"]); + const request = remoteScheduleRunsQuerySchema.parse(await readJsonBody(req)); + const schedules = ctx.requireSchedulesGateway(); + const runs = + request.kind === "schedule" + ? schedules.listRuns(request.payload.id) + : schedules.listInbox(request.query); + writeJson(res, 200, { runs }); + return; + } + if (req.method === "POST" && url.pathname === "/api/schedules/runs/command") { + ctx.security.requireBearer(req, ["session:operate"]); + const command = remoteScheduleRunCommandSchema.parse(await readJsonBody(req)); + const schedules = ctx.requireSchedulesGateway(); + if (command.kind === "cancel") { + writeJson(res, 200, { cancelled: schedules.cancelRun(command.id) }); + return; + } + const run = schedules.updateRunState(command.payload); + if (!run) { + throw new RemoteHttpError("schedule_run_not_found", "Schedule run not found.", 404); + } + writeJson(res, 200, { run }); + return; + } if (req.method === "GET" && url.pathname === "/api/browser/state") { ctx.security.requireBearer(req, ["session:read"]); writeJson(res, 200, { state: ctx.requireBrowserGateway().state() }); diff --git a/src/main/schedules/ScheduleRunCoordinator.test.ts b/src/main/schedules/ScheduleRunCoordinator.test.ts index 45fa92862..8c74afd7d 100644 --- a/src/main/schedules/ScheduleRunCoordinator.test.ts +++ b/src/main/schedules/ScheduleRunCoordinator.test.ts @@ -8,9 +8,10 @@ import type { Thread, ThreadStatus, } from "@/shared/contracts"; -import { agentStatusesResponseSchema } from "@/shared/contracts"; +import { agentStatusesResponseSchema, DEFAULT_SCHEDULE_AUTOMATION } from "@/shared/contracts"; import type { SupervisorEvent } from "@/shared/ipc"; import { defaultSharedSettings } from "@/shared/settings"; +import type { PersistedRuntimeItem } from "../db/runtimeItems"; import { ScheduleRunCoordinator, type ScheduleRunCoordinatorDeps } from "./ScheduleRunCoordinator"; const HOME_PROJECT: Project = { @@ -46,6 +47,39 @@ const task: ScheduledTask = { updatedAt: "2026-07-10T00:00:00.000Z", }; +function heartbeatTask( + automation: Partial> = {}, +): ScheduledTask { + return { + ...task, + automation: { + ...DEFAULT_SCHEDULE_AUTOMATION, + ...automation, + mode: { kind: "heartbeat", targetThreadId: "target-thread" }, + }, + }; +} + +function targetThread(overrides: Partial = {}): Thread { + return { + id: "target-thread", + projectId: HOME_PROJECT.id, + title: "Ongoing automation", + agentKind: task.agentKind, + config: { model: task.config.model }, + status: "idle", + attention: "none", + canResumeWithConfig: true, + archived: false, + done: false, + starred: false, + presentationMode: "gui", + createdAt: "2026-01-01T00:00:00.000Z", + updatedAt: "2026-07-10T00:00:00.000Z", + ...overrides, + }; +} + /** Codex-like posture: bypass options advertised for both approval and sandbox. */ function agentStatuses( capabilities: Record = { @@ -80,18 +114,24 @@ interface Harness { runs: Map; sent: RemoteThreadCommand[]; startThread: ReturnType; + sendThreadInput: ReturnType; + runtimeItems: Map; } function makeHarness(overrides: Partial = {}): Harness { const threads = new Map(); const runs = new Map(); const sent: RemoteThreadCommand[] = []; + const runtimeItems = new Map(); const ids = ["thread-1", "run-1"]; let idx = 0; const startThread = vi.fn<() => Promise>().mockResolvedValue(undefined); + const sendThreadInput = vi.fn<() => Promise>().mockResolvedValue(undefined); const deps: ScheduleRunCoordinatorDeps = { startThread, + sendThreadInput, + interruptThread: vi.fn<() => Promise>().mockResolvedValue(undefined), getAgentStatuses: async () => agentStatuses(), sendThreadCommand: (command) => { sent.push(command); @@ -99,6 +139,10 @@ function makeHarness(overrides: Partial = {}): Harne }, ensureHomeProject: () => HOME_PROJECT, getProject: (projectId) => (projectId === WORK_PROJECT.id ? WORK_PROJECT : null), + getThread: (threadId) => threads.get(threadId) ?? null, + getThreadRuntimeItemCursor: (threadId) => (runtimeItems.get(threadId)?.length ?? 0) - 1, + getThreadRuntimeItemsAfter: (threadId, cursor) => + (runtimeItems.get(threadId) ?? []).slice(cursor + 1), upsertThread: (thread) => { threads.set(thread.id, thread); }, @@ -118,6 +162,7 @@ function makeHarness(overrides: Partial = {}): Harne ...(patch.status !== undefined ? { status: patch.status } : {}), ...(patch.summary !== undefined ? { summary: patch.summary } : {}), ...(patch.error !== undefined ? { error: patch.error } : {}), + ...(patch.result !== undefined ? { result: patch.result } : {}), }); }, newId: () => ids[idx++] ?? `id-${idx}`, @@ -125,7 +170,15 @@ function makeHarness(overrides: Partial = {}): Harne ...overrides, }; - return { coordinator: new ScheduleRunCoordinator(deps), threads, runs, sent, startThread }; + return { + coordinator: new ScheduleRunCoordinator(deps), + threads, + runs, + sent, + startThread, + sendThreadInput, + runtimeItems, + }; } function threadState( @@ -192,7 +245,7 @@ describe("ScheduleRunCoordinator", () => { coordinator.observeSupervisorEvent(threadState("thread-1", "working")); coordinator.observeSupervisorEvent(threadState("thread-1", "idle")); - await expect(settled).resolves.toBe(""); + await expect(settled).resolves.toMatchObject({ status: "succeeded" }); expect(runs.get("run-1")).toMatchObject({ status: "succeeded", summary: null }); expect(runs.get("run-1")?.completedAt).not.toBeNull(); }); @@ -205,7 +258,7 @@ describe("ScheduleRunCoordinator", () => { coordinator.observeSupervisorEvent(threadState("thread-1", "working")); coordinator.observeSupervisorEvent(threadState("thread-1", "error", "model exploded")); - await expect(settled).rejects.toThrow("model exploded"); + await expect(settled).resolves.toMatchObject({ status: "failed", error: "model exploded" }); expect(runs.get("run-1")).toMatchObject({ status: "failed", error: "model exploded" }); }); @@ -220,7 +273,7 @@ describe("ScheduleRunCoordinator", () => { coordinator.observeSupervisorEvent(threadState("thread-1", "working")); coordinator.observeSupervisorEvent(threadState("thread-1", "finished")); - await expect(settled).resolves.toBe(""); + await expect(settled).resolves.toMatchObject({ status: "succeeded" }); expect(runs.get("run-1")?.status).toBe("succeeded"); }); @@ -229,7 +282,10 @@ describe("ScheduleRunCoordinator", () => { startThread: vi.fn<() => Promise>().mockRejectedValue(new Error("supervisor down")), }); - await expect(coordinator.runScheduleAsThread(task)).rejects.toThrow("supervisor down"); + await expect(coordinator.runScheduleAsThread(task)).resolves.toMatchObject({ + status: "failed", + error: "supervisor down", + }); expect(threads.has("thread-1")).toBe(false); expect(sent.some((command) => command.kind === "delete")).toBe(true); expect(runs.get("run-1")).toMatchObject({ status: "failed", error: "supervisor down" }); @@ -246,7 +302,7 @@ describe("ScheduleRunCoordinator", () => { coordinator.observeSupervisorEvent(threadState("thread-1", "working")); coordinator.observeSupervisorEvent(threadState("thread-1", "idle")); - await expect(settled).resolves.toBe(""); + await expect(settled).resolves.toMatchObject({ status: "succeeded" }); expect(runs.get("run-1")?.status).toBe("succeeded"); }); @@ -263,7 +319,7 @@ describe("ScheduleRunCoordinator", () => { coordinator.observeSupervisorEvent(threadState("thread-1", "working")); coordinator.observeSupervisorEvent(threadState("thread-1", "idle")); - await expect(settled).resolves.toBe(""); + await expect(settled).resolves.toMatchObject({ status: "succeeded" }); }); it("resolves global and project MCP settings for scheduled launches", async () => { @@ -304,7 +360,7 @@ describe("ScheduleRunCoordinator", () => { coordinator.observeSupervisorEvent(threadState("thread-1", "working")); coordinator.observeSupervisorEvent(threadState("thread-1", "idle")); - await expect(settled).resolves.toBe(""); + await expect(settled).resolves.toMatchObject({ status: "succeeded" }); }); it("launches scheduled runs with the provider's most-permissive policy", async () => { @@ -325,7 +381,7 @@ describe("ScheduleRunCoordinator", () => { coordinator.observeSupervisorEvent(threadState("thread-1", "working")); coordinator.observeSupervisorEvent(threadState("thread-1", "idle")); - await expect(settled).resolves.toBe(""); + await expect(settled).resolves.toMatchObject({ status: "succeeded" }); }); it("falls back to the declared bypass posture when no options are advertised", async () => { @@ -348,7 +404,7 @@ describe("ScheduleRunCoordinator", () => { coordinator.observeSupervisorEvent(threadState("thread-1", "working")); coordinator.observeSupervisorEvent(threadState("thread-1", "idle")); - await expect(settled).resolves.toBe(""); + await expect(settled).resolves.toMatchObject({ status: "succeeded" }); }); it("keeps provider defaults when the capability lookup fails", async () => { @@ -366,7 +422,7 @@ describe("ScheduleRunCoordinator", () => { coordinator.observeSupervisorEvent(threadState("thread-1", "working")); coordinator.observeSupervisorEvent(threadState("thread-1", "idle")); - await expect(settled).resolves.toBe(""); + await expect(settled).resolves.toMatchObject({ status: "succeeded" }); }); it("fails the run when the task's project no longer exists", async () => { @@ -374,9 +430,258 @@ describe("ScheduleRunCoordinator", () => { await expect( coordinator.runScheduleAsThread({ ...task, projectId: "deleted-project-id" }), - ).rejects.toThrow("Project no longer exists."); - // No thread row or run row is created when the project can't be resolved. + ).resolves.toMatchObject({ status: "failed", error: "Project no longer exists." }); + // Configuration failures are durable even when no thread can be created. expect(threads.size).toBe(0); - expect(runs.size).toBe(0); + expect(runs.size).toBe(1); + }); + + it("captures fresh assistant text and changed files as a typed finding", async () => { + const { coordinator, runtimeItems, runs } = makeHarness(); + const settled = coordinator.runScheduleAsThread(task); + await flush(); + runtimeItems.set("thread-1", [ + { + id: "assistant-1", + type: "assistant_message", + state: "completed", + streams: { assistant_text: "Updated the release notes." }, + }, + { + id: "file-1", + type: "file_change", + state: "completed", + payload: { path: "CHANGELOG.md", changeKind: "edit", status: "success" }, + streams: {}, + }, + ]); + + coordinator.observeSupervisorEvent(threadState("thread-1", "working")); + coordinator.observeSupervisorEvent(threadState("thread-1", "idle")); + + await expect(settled).resolves.toMatchObject({ + summary: "Updated the release notes.", + result: { + outcome: "changed-files", + unread: true, + changedFiles: ["CHANGELOG.md"], + }, + }); + expect(runs.get("run-1")?.summary).toBe("Updated the release notes."); + }); + + it("keeps text-only successful results unknown instead of inventing findings", async () => { + const { coordinator, runtimeItems } = makeHarness(); + const settled = coordinator.runScheduleAsThread(task); + await flush(); + runtimeItems.set("thread-1", [ + { + id: "assistant-1", + type: "assistant_message", + state: "completed", + streams: { assistant_text: "No issues found." }, + }, + ]); + + coordinator.observeSupervisorEvent(threadState("thread-1", "working")); + coordinator.observeSupervisorEvent(threadState("thread-1", "idle")); + + await expect(settled).resolves.toMatchObject({ + summary: "No issues found.", + result: { outcome: "unknown", unread: true }, + }); + }); + + it("runs a heartbeat in an idle conversation and excludes its prior items", async () => { + const { coordinator, threads, runtimeItems, sendThreadInput } = makeHarness(); + threads.set("target-thread", targetThread()); + runtimeItems.set("target-thread", [ + { + id: "old-assistant", + type: "assistant_message", + state: "completed", + streams: { assistant_text: "Old result" }, + }, + ]); + const settled = coordinator.runScheduleAsThread(heartbeatTask()); + await flush(); + expect(sendThreadInput).toHaveBeenCalledWith( + expect.objectContaining({ threadId: "target-thread", prompt: task.prompt }), + ); + runtimeItems.get("target-thread")!.push({ + id: "new-assistant", + type: "assistant_message", + state: "completed", + streams: { assistant_text: "Fresh result" }, + }); + + coordinator.observeSupervisorEvent(threadState("target-thread", "working")); + coordinator.observeSupervisorEvent(threadState("target-thread", "idle")); + + await expect(settled).resolves.toMatchObject({ + status: "succeeded", + summary: "Fresh result", + }); + }); + + it("resumes a persisted heartbeat session before sending its turn", async () => { + const { coordinator, threads, sendThreadInput, startThread } = makeHarness(); + threads.set( + "target-thread", + targetThread({ + status: "inactive", + sessionRef: { + providerSessionId: "provider-session", + discoveredAt: "2026-07-10T00:00:00.000Z", + }, + }), + ); + sendThreadInput.mockRejectedValueOnce(new Error("Unknown thread session")); + const settled = coordinator.runScheduleAsThread(heartbeatTask()); + await flush(); + + expect(startThread).toHaveBeenCalledWith( + expect.objectContaining({ + threadId: "target-thread", + prompt: "", + sessionRef: expect.objectContaining({ providerSessionId: "provider-session" }), + }), + ); + expect(sendThreadInput).toHaveBeenCalledTimes(2); + + coordinator.observeSupervisorEvent(threadState("target-thread", "working")); + coordinator.observeSupervisorEvent(threadState("target-thread", "idle")); + await expect(settled).resolves.toMatchObject({ status: "succeeded" }); + }); + + it("rejects a heartbeat target that is already working", async () => { + const { coordinator, threads, sendThreadInput } = makeHarness(); + threads.set("target-thread", targetThread({ status: "working" })); + + await expect(coordinator.runScheduleAsThread(heartbeatTask())).resolves.toMatchObject({ + status: "failed", + error: "The heartbeat conversation is currently busy.", + }); + expect(sendThreadInput).not.toHaveBeenCalled(); + }); + + it("rejects an archived heartbeat target", async () => { + const { coordinator, threads, sendThreadInput } = makeHarness(); + threads.set("target-thread", targetThread({ archived: true })); + + await expect(coordinator.runScheduleAsThread(heartbeatTask())).resolves.toMatchObject({ + status: "failed", + error: "The heartbeat conversation is archived.", + }); + expect(sendThreadInput).not.toHaveBeenCalled(); + }); + + it("surfaces an unattended approval request in triage", async () => { + const { coordinator } = makeHarness(); + const settled = coordinator.runScheduleAsThread(task); + await flush(); + coordinator.observeSupervisorEvent(threadState("thread-1", "working")); + coordinator.observeSupervisorEvent(threadState("thread-1", "needs_approval")); + + await expect(settled).resolves.toMatchObject({ + status: "waiting-for-approval", + result: { outcome: "needs-attention", unread: true }, + }); + }); + + it("evaluates a heartbeat completion condition after a successful turn", async () => { + const { coordinator, threads, runtimeItems } = makeHarness({ + evaluateCompletion: vi + .fn>() + .mockResolvedValue({ + stopMatched: true, + confidence: 0.95, + reason: "The requested artifact exists.", + }), + }); + threads.set("target-thread", targetThread()); + const scheduled = heartbeatTask({ + completionPolicy: { + kind: "ai-evaluated", + stopWhen: "The artifact exists", + confidenceThreshold: 0.9, + }, + }); + const settled = coordinator.runScheduleAsThread(scheduled); + await flush(); + runtimeItems.set("target-thread", [ + { + id: "assistant-1", + type: "assistant_message", + state: "completed", + streams: { assistant_text: "Created the artifact." }, + }, + ]); + coordinator.observeSupervisorEvent(threadState("target-thread", "working")); + coordinator.observeSupervisorEvent(threadState("target-thread", "idle")); + + await expect(settled).resolves.toMatchObject({ + stopMatched: true, + result: { + stopReason: "completion-condition", + completionEvaluation: { + condition: "The artifact exists", + stopMatched: true, + }, + }, + }); + }); + + it("cancels an active automation by run id", async () => { + const { coordinator, runs } = makeHarness(); + const settled = coordinator.runScheduleAsThread(task); + await flush(); + const runId = [...runs.keys()][0]!; + + expect(coordinator.cancelRun(runId)).toBe(true); + await expect(settled).resolves.toMatchObject({ status: "cancelled" }); + expect(coordinator.cancelRun(runId)).toBe(false); + }); + + it("cancels an automation while its completion condition is being evaluated", async () => { + const evaluateCompletion = vi.fn>( + () => new Promise(() => undefined), + ); + const { coordinator, runs, threads } = makeHarness({ evaluateCompletion }); + threads.set("target-thread", targetThread()); + const scheduled = heartbeatTask({ + completionPolicy: { + kind: "ai-evaluated", + stopWhen: "The artifact exists", + confidenceThreshold: 0.9, + }, + }); + const settled = coordinator.runScheduleAsThread(scheduled); + await flush(); + const runId = [...runs.keys()][0]!; + coordinator.observeSupervisorEvent(threadState("target-thread", "working")); + coordinator.observeSupervisorEvent(threadState("target-thread", "idle")); + await vi.waitFor(() => expect(evaluateCompletion).toHaveBeenCalledOnce()); + + expect(coordinator.cancelRun(runId)).toBe(true); + await expect(settled).resolves.toMatchObject({ + status: "cancelled", + result: { stopReason: "cancelled" }, + }); + expect(runs.get(runId)).toMatchObject({ status: "cancelled" }); + expect(coordinator.cancelRun(runId)).toBe(false); + }); + + it("interrupts active automations when the supervisor resets", async () => { + const { coordinator } = makeHarness(); + const settled = coordinator.runScheduleAsThread(task); + await flush(); + + coordinator.handleSupervisorReset(); + + await expect(settled).resolves.toMatchObject({ + status: "interrupted", + result: { stopReason: "supervisor-reset" }, + }); }); }); diff --git a/src/main/schedules/ScheduleRunCoordinator.ts b/src/main/schedules/ScheduleRunCoordinator.ts index 5a31166e8..6783d890e 100644 --- a/src/main/schedules/ScheduleRunCoordinator.ts +++ b/src/main/schedules/ScheduleRunCoordinator.ts @@ -5,49 +5,60 @@ import type { Project, ProjectLocation, RemoteThreadCommand, + RuntimeEvent, + ScheduleCompletionPolicy, + ScheduleCompletionEvaluationInput, + ScheduleCompletionEvaluationResult, + ScheduleRunResult, + ScheduleRunStatus, ScheduledTask, ScheduledTaskRun, + SendThreadInputPayload, StartThreadPayload, Thread, ThreadConfig, ThreadStatus, } from "@/shared/contracts"; -import type { SharedSettings } from "@/shared/settings"; -import { DEFAULT_TERMINAL_SIZE, resolveMcpLaunchSnapshot } from "@/shared/contracts"; +import { + DEFAULT_TERMINAL_SIZE, + isThreadTurnActive, + resolveMcpLaunchSnapshot, + resolveScheduleAutomation, +} from "@/shared/contracts"; import { getProjectAgentStatuses } from "@/shared/agentStatus"; import { resolveUnrestrictedPermissionConfig, type UnrestrictedPermissionConfig, } from "@/shared/agents/unrestrictedPermissions"; +import type { SharedSettings } from "@/shared/settings"; +import { toErrorMessage } from "@/shared/errorMessage"; +import { msg } from "@/shared/messages"; import type { SupervisorEvent } from "@/shared/ipc"; +import type { PersistedRuntimeItem } from "../db/runtimeItems"; import type { ScheduleRunPatch } from "../db/scheduleRuns"; +import { buildScheduleRunResult, collectScheduleRunItems } from "./scheduleRunResults"; +import type { ScheduleRunContext, ScheduleTaskExecutionOutcome } from "./types"; -/** - * A `thread-state` transition ends the run only once the turn fully settles. - * `needs_approval`/`needs_reply` are mid-turn pauses (they can resume under - * auto-approval), so — matching {@link isThreadTurnActive} — they are NOT - * treated as terminal here; that avoids settling a run while its thread keeps - * working. - */ const TERMINAL_STATUSES: ReadonlySet = new Set([ "idle", "finished", "inactive", "error", ]); - export interface ScheduleRunCoordinatorDeps { - /** Launch the child session in the supervisor (main → supervisor request). */ startThread(payload: StartThreadPayload): Promise; - /** Cached agent detection for the given WSL distros (supervisor request). */ + sendThreadInput?(payload: SendThreadInputPayload): Promise; + interruptThread?(threadId: string): Promise; + evaluateCompletion?( + payload: ScheduleCompletionEvaluationInput, + ): Promise; getAgentStatuses(wslDistros: string[]): Promise; - /** Mirror a thread command to the renderer store; false when no window is up. */ sendThreadCommand(command: RemoteThreadCommand): boolean; - /** Resolve (creating if absent) the persisted home-scope project row. */ ensureHomeProject(): Project; - /** Resolve a persisted project row by id, or null when it no longer exists. */ getProject(projectId: string): Project | null; - /** Current global MCP settings; optional for isolated tests/embedders. */ + getThread?(threadId: string): Thread | null; + getThreadRuntimeItemCursor(threadId: string): number; + getThreadRuntimeItemsAfter(threadId: string, cursor: number): PersistedRuntimeItem[]; getSharedSettings(): SharedSettings; upsertThread(thread: Thread, sortOrder: number): void; deleteThread(threadId: string): void; @@ -60,66 +71,489 @@ export interface ScheduleRunCoordinatorDeps { interface PendingRun { runId: string; + threadId: string; + task: ScheduledTask; + projectLocation: ProjectLocation; + runtimeItemCursor: number; sawActive: boolean; - resolve: (summary: string) => void; - reject: (error: Error) => void; + timer: ReturnType; + settling: boolean; + resolveSettlementOverride: ((completion: CompletionInput) => void) | null; + resolve: (outcome: ScheduleTaskExecutionOutcome) => void; } -/** - * Runs a scheduled task as a REAL GUI thread (persisted, sidebar-visible) - * instead of a headless one-shot prompt, and records a run-history row linked - * to that thread. - * - * Start ordering mirrors {@link handleOrchestratorThreadCreated}: persist the - * thread row first, mirror it to the renderer (`launchRuntime: false`, - * `focus: false`), then call the supervisor's `startThread`. The returned - * promise settles when the thread's turn ends (observed via `thread-state`), - * so the caller's `ScheduleService.settle` keeps working unchanged. - */ +interface CompletionInput { + status: Exclude; + error: string | null; + stopReason: string | null; +} + +/** Executes scheduled turns as persisted GUI conversations and records typed results. */ export class ScheduleRunCoordinator { - private readonly pending = new Map(); + private readonly pendingByThread = new Map(); + private readonly pendingByRunId = new Map(); constructor(private readonly deps: ScheduleRunCoordinatorDeps) {} - /** Wire into the supervisor event tap (main.ts `onEvent`). */ observeSupervisorEvent(event: SupervisorEvent): void { + if (event.type === "thread-runtime-event") { + this.observeRuntimeEvent(event.event); + return; + } + if (event.type === "thread-runtime-events") { + for (const runtimeEvent of event.events) this.observeRuntimeEvent(runtimeEvent); + return; + } + if (event.type === "thread-runtime-events-multi") { + for (const batch of event.batches) { + for (const runtimeEvent of batch.events) this.observeRuntimeEvent(runtimeEvent); + } + return; + } + if (event.type === "thread-exited") { + if (!this.pendingByThread.has(event.threadId)) return; + void this.finishPending(event.threadId, { + status: "interrupted", + error: msg("automation.run.exited"), + stopReason: "thread-exited", + }); + return; + } if (event.type !== "thread-state") return; - const run = this.pending.get(event.threadId); - if (!run) return; + const pending = this.pendingByThread.get(event.threadId); + if (!pending) return; if (event.status === "launching" || event.status === "working") { - run.sawActive = true; + pending.sawActive = true; return; } if (event.status === "needs_approval" || event.status === "needs_reply") { - // Mid-turn pause — the turn is still active; wait for a terminal state. + const replyRequired = event.status === "needs_reply"; + void this.finishPending(event.threadId, { + status: "waiting-for-approval", + error: replyRequired + ? msg("automation.run.replyRequired") + : msg("automation.run.approvalRequired"), + stopReason: replyRequired ? "reply-required" : "approval-required", + }); return; } if (!TERMINAL_STATUSES.has(event.status)) return; - // "inactive" before the run ever became active is a stale pre-launch echo. - if (event.status === "inactive" && !run.sawActive) return; - - this.pending.delete(event.threadId); - const completedAt = this.nowIso(); + if (event.status === "inactive" && !pending.sawActive) return; if (event.status === "error") { - const error = event.errorMessage ?? "Scheduled run failed."; - this.deps.updateRun(run.runId, { completedAt, status: "failed", error }); - run.reject(new Error(error)); + void this.finishPending(event.threadId, { + status: "failed", + error: event.errorMessage ?? msg("automation.run.failed"), + stopReason: "runtime-error", + }); return; } - this.deps.updateRun(run.runId, { completedAt, status: "succeeded" }); - // Final assistant text is not captured in main without heavy runtime-event - // plumbing, so the summary stays null and the schedule's quick-glance - // lastResult resolves to an empty string. - run.resolve(""); + void this.finishPending(event.threadId, { + status: "succeeded", + error: null, + stopReason: null, + }); + } + + handleSupervisorReset(): void { + for (const threadId of [...this.pendingByThread.keys()]) { + void this.finishPending(threadId, { + status: "interrupted", + error: msg("automation.run.exited"), + stopReason: "supervisor-reset", + }); + } + } + + async runScheduleAsThread( + task: ScheduledTask, + context: ScheduleRunContext = { + scheduledFor: this.nowIso(), + trigger: "manual", + attempt: 1, + iteration: (task.iterationCount ?? 0) + 1, + }, + ): Promise { + const automation = resolveScheduleAutomation(task.automation); + const threadId = + automation.mode.kind === "heartbeat" + ? automation.mode.targetThreadId + : (this.deps.newId ?? randomUUID)(); + const runId = (this.deps.newId ?? randomUUID)(); + const startedAt = this.nowIso(); + this.deps.insertRun({ + id: runId, + scheduleId: task.id, + threadId, + scheduledFor: context.scheduledFor, + trigger: context.trigger, + attempt: context.attempt, + iteration: context.iteration, + startedAt, + completedAt: null, + status: "running", + summary: null, + error: null, + result: null, + automationSnapshot: automation, + }); + + if (this.pendingByThread.has(threadId)) { + return this.finishUnstarted( + runId, + { + status: "failed", + error: msg("automation.run.targetInUse"), + stopReason: "target-busy", + }, + automation.completionPolicy, + ); + } + + let project: Project; + let config: ThreadConfig; + let runtimeItemCursor = -1; + let freshThread = false; + try { + project = this.resolveProject(task); + config = await this.buildThreadConfig(task, project.location); + if (automation.mode.kind === "heartbeat") { + const target = this.requireHeartbeatTarget(task, project, automation.mode.targetThreadId); + runtimeItemCursor = this.deps.getThreadRuntimeItemCursor(target.id); + } else { + freshThread = !this.deps.threadExists(threadId); + this.persistFreshThread(task, project, threadId, config, startedAt); + } + } catch (error) { + return this.finishUnstarted( + runId, + { + status: "failed", + error: toErrorMessage(error), + stopReason: "configuration-error", + }, + automation.completionPolicy, + ); + } + + let resolveRun!: (outcome: ScheduleTaskExecutionOutcome) => void; + const settled = new Promise((resolve) => { + resolveRun = resolve; + }); + const timer = setTimeout(() => { + void this.finishPending(threadId, { + status: "failed", + error: msg("automation.run.timeLimit"), + stopReason: "time-limit", + }); + void this.deps.interruptThread?.(threadId).catch(() => undefined); + }, automation.maxRuntimeSeconds * 1_000); + timer.unref?.(); + const pending: PendingRun = { + runId, + threadId, + task, + projectLocation: project.location, + runtimeItemCursor, + sawActive: false, + timer, + settling: false, + resolveSettlementOverride: null, + resolve: resolveRun, + }; + this.pendingByThread.set(threadId, pending); + this.pendingByRunId.set(runId, pending); + + try { + if (automation.mode.kind === "heartbeat") { + await this.dispatchHeartbeat(task, project, threadId, config); + } else { + await this.deps.startThread(this.startPayload(task, project, threadId, config)); + } + } catch (error) { + if (freshThread) { + this.deps.deleteThread(threadId); + this.deps.sendThreadCommand({ kind: "delete", threadId }); + } + if (this.pendingByRunId.has(runId)) { + await this.finishPending(threadId, { + status: "failed", + error: toErrorMessage(error), + stopReason: "launch-error", + }); + } + } + + return settled; + } + + cancelRun(runId: string): boolean { + const pending = this.pendingByRunId.get(runId); + if (!pending) return false; + void this.finishPending(pending.threadId, { + status: "cancelled", + error: null, + stopReason: "cancelled", + }); + void this.deps.interruptThread?.(pending.threadId).catch(() => undefined); + return true; } - async runScheduleAsThread(task: ScheduledTask): Promise { - const project = this.resolveProject(task); - const threadId = (this.deps.newId ?? randomUUID)(); - const nowIso = this.nowIso(); + recordSkippedRun(task: ScheduledTask, context: ScheduleRunContext): ScheduledTaskRun { + const automation = resolveScheduleAutomation(task.automation); + const now = this.nowIso(); + const result = buildScheduleRunResult({ + status: "skipped", + summary: null, + changedFiles: [], + completedAt: now, + stopReason: "misfire-policy", + }); + const run: ScheduledTaskRun = { + id: (this.deps.newId ?? randomUUID)(), + scheduleId: task.id, + threadId: + automation.mode.kind === "heartbeat" + ? automation.mode.targetThreadId + : `schedule:${task.id}`, + scheduledFor: context.scheduledFor, + trigger: context.trigger, + attempt: context.attempt, + iteration: context.iteration, + startedAt: now, + completedAt: now, + status: "skipped", + summary: null, + error: null, + result, + automationSnapshot: automation, + }; + this.deps.insertRun(run); + return run; + } - const config = await this.buildThreadConfig(task, project.location); + private observeRuntimeEvent(event: RuntimeEvent): void { + const pending = this.pendingByThread.get(event.threadId); + if (!pending) return; + if (event.type === "turn.started") { + pending.sawActive = true; + return; + } + if (event.type === "error") { + void this.finishPending(event.threadId, { + status: "failed", + error: event.message, + stopReason: "runtime-error", + }); + return; + } + if (event.type !== "turn.completed") return; + if (event.state === "completed") { + void this.finishPending(event.threadId, { + status: "succeeded", + error: null, + stopReason: null, + }); + return; + } + void this.finishPending(event.threadId, { + status: + event.state === "cancelled" + ? "cancelled" + : event.state === "interrupted" + ? "interrupted" + : "failed", + error: event.state === "failed" ? msg("automation.run.failed") : null, + stopReason: event.state, + }); + } + + private async finishPending(threadId: string, completion: CompletionInput): Promise { + const pending = this.pendingByThread.get(threadId); + if (!pending) return; + if (pending.settling) { + if (completion.status === "cancelled" || completion.status === "interrupted") { + pending.resolveSettlementOverride?.(completion); + } + return; + } + pending.settling = true; + clearTimeout(pending.timer); + + let items: PersistedRuntimeItem[] = []; + try { + items = this.deps.getThreadRuntimeItemsAfter(pending.threadId, pending.runtimeItemCursor); + } catch { + // Settlement remains durable even if transcript hydration fails. + } + const { summary, changedFiles } = collectScheduleRunItems(items); + let status = completion.status; + let error = completion.error; + let stopReason = completion.stopReason; + let completionEvaluation: ScheduleRunResult["completionEvaluation"]; + let stopMatched = false; + const completionPolicy = resolveScheduleAutomation(pending.task.automation).completionPolicy; + if (status === "succeeded" && completionPolicy.kind === "ai-evaluated") { + try { + if (!this.deps.evaluateCompletion) { + throw new Error(msg("automation.run.completionUnavailable")); + } + const override = new Promise<{ kind: "override"; completion: CompletionInput }>( + (resolve) => { + pending.resolveSettlementOverride = (nextCompletion) => + resolve({ kind: "override", completion: nextCompletion }); + }, + ); + const evaluation = this.deps + .evaluateCompletion({ + projectLocation: pending.projectLocation, + agentKind: pending.task.agentKind, + config: pending.task.config, + condition: completionPolicy.stopWhen, + summary, + changedFiles, + }) + .then((result) => ({ kind: "evaluation" as const, result })); + const settled = await Promise.race([evaluation, override]); + pending.resolveSettlementOverride = null; + if (settled.kind === "override") { + status = settled.completion.status; + error = settled.completion.error; + stopReason = settled.completion.stopReason; + } else { + completionEvaluation = { + ...settled.result, + condition: completionPolicy.stopWhen, + evaluatedAt: this.nowIso(), + }; + stopMatched = + settled.result.stopMatched && + settled.result.confidence >= completionPolicy.confidenceThreshold; + if (stopMatched) stopReason = "completion-condition"; + } + } catch (evaluationError) { + pending.resolveSettlementOverride = null; + status = "failed"; + error = msg("automation.run.completionFailed", { + detail: toErrorMessage(evaluationError), + }); + stopReason = "completion-evaluation-error"; + } + } + + const completedAt = this.nowIso(); + const result = buildScheduleRunResult({ + status, + summary, + changedFiles, + completedAt, + stopReason, + ...(completionEvaluation ? { completionEvaluation } : {}), + }); + this.pendingByThread.delete(threadId); + this.pendingByRunId.delete(pending.runId); + this.deps.updateRun(pending.runId, { + completedAt, + status, + summary, + error, + result, + }); + pending.resolve({ + runId: pending.runId, + status, + summary, + error, + result, + stopMatched, + completionPolicySnapshot: completionPolicy, + }); + } + + private finishUnstarted( + runId: string, + completion: CompletionInput, + completionPolicySnapshot: ScheduleCompletionPolicy, + ): ScheduleTaskExecutionOutcome { + const completedAt = this.nowIso(); + const result = buildScheduleRunResult({ + status: completion.status, + summary: null, + changedFiles: [], + completedAt, + stopReason: completion.stopReason, + }); + this.deps.updateRun(runId, { + completedAt, + status: completion.status, + error: completion.error, + result, + }); + return { + runId, + status: completion.status, + summary: null, + error: completion.error, + result, + stopMatched: false, + completionPolicySnapshot, + }; + } + + private requireHeartbeatTarget(task: ScheduledTask, project: Project, threadId: string): Thread { + const target = this.deps.getThread?.(threadId); + if (!target) throw new Error(msg("automation.heartbeat.missing")); + if (target.archived) throw new Error(msg("automation.heartbeat.archived")); + if (target.presentationMode !== "gui") { + throw new Error(msg("automation.heartbeat.nativeChatRequired")); + } + if (target.projectId !== project.id) { + throw new Error(msg("automation.heartbeat.differentProject")); + } + if (target.agentKind !== task.agentKind) { + throw new Error(msg("automation.heartbeat.differentAgent")); + } + if (isThreadTurnActive(target.status)) { + throw new Error(msg("automation.heartbeat.busy")); + } + return target; + } + + private async dispatchHeartbeat( + task: ScheduledTask, + project: Project, + threadId: string, + config: ThreadConfig, + ): Promise { + if (!this.deps.sendThreadInput) { + throw new Error(msg("automation.heartbeat.unavailable")); + } + try { + await this.deps.sendThreadInput({ threadId, prompt: task.prompt, config }); + return; + } catch (error) { + if (!/unknown thread session|session.*not found/iu.test(toErrorMessage(error))) throw error; + } + + const target = this.deps.getThread?.(threadId); + if (!target?.sessionRef) { + throw new Error(msg("automation.heartbeat.cannotResume")); + } + await this.deps.startThread({ + ...this.startPayload(task, project, threadId, config), + prompt: "", + sessionRef: target.sessionRef, + }); + await this.deps.sendThreadInput({ threadId, prompt: task.prompt, config }); + } + + private persistFreshThread( + task: ScheduledTask, + project: Project, + threadId: string, + config: ThreadConfig, + nowIso: string, + ): void { const thread: Thread = { id: threadId, projectId: project.id, @@ -138,15 +572,7 @@ export class ScheduleRunCoordinator { updatedAt: nowIso, activeTurnStartedAt: nowIso, }; - - const existed = this.deps.threadExists(threadId); - // New rows sort to the top via a descending timestamp (same convention as - // the orchestrator bridge and the remote-access server). this.deps.upsertThread(thread, -Date.now()); - - // Mirror to the renderer; a forwarded title is authoritative and disables - // AI title generation (the schedule name is the thread title). `false` from - // sendThreadCommand (no window) is expected and must not fail the run. this.deps.sendThreadCommand({ kind: "start", threadId, @@ -159,24 +585,15 @@ export class ScheduleRunCoordinator { launchRuntime: false, focus: false, }); + } - const run: ScheduledTaskRun = { - id: (this.deps.newId ?? randomUUID)(), - scheduleId: task.id, - threadId, - startedAt: nowIso, - completedAt: null, - status: "running", - summary: null, - error: null, - }; - this.deps.insertRun(run); - - const settled = new Promise((resolve, reject) => { - this.pending.set(threadId, { runId: run.id, sawActive: false, resolve, reject }); - }); - - const startPayload: StartThreadPayload = { + private startPayload( + task: ScheduledTask, + project: Project, + threadId: string, + config: ThreadConfig, + ): StartThreadPayload { + return { threadId, projectLocation: project.location, agentKind: task.agentKind, @@ -186,40 +603,12 @@ export class ScheduleRunCoordinator { presentationMode: "gui", ...resolveMcpLaunchSnapshot(this.deps.getSharedSettings(), project.mcpServers ?? []), }; - - try { - await this.deps.startThread(startPayload); - } catch (error) { - this.pending.delete(threadId); - const message = error instanceof Error ? error.message : String(error); - this.deps.updateRun(run.id, { - completedAt: this.nowIso(), - status: "failed", - error: message, - }); - // Roll back the fresh row (follow the orchestrator bridge): drop it from - // the DB and tell the renderer to forget it, but keep a pre-existing row. - if (!existed) { - this.deps.deleteThread(threadId); - this.deps.sendThreadCommand({ kind: "delete", threadId }); - } - throw error instanceof Error ? error : new Error(message); - } - - return settled; } - /** - * Resolve the project the run's thread lives in. A null/absent `projectId` - * uses the built-in Home scope; a set id must still reference an existing - * project row — if the user deleted it, fail the run with a clear message so - * they notice and can edit the schedule (rather than silently reverting to - * Home). - */ private resolveProject(task: ScheduledTask): Project { if (task.projectId == null) return this.deps.ensureHomeProject(); const project = this.deps.getProject(task.projectId); - if (!project) throw new Error("Project no longer exists."); + if (!project) throw new Error(msg("automation.run.projectMissing")); return project; } @@ -235,14 +624,6 @@ export class ScheduleRunCoordinator { }; } - /** - * Scheduled runs execute unattended — nobody is around to answer approval - * prompts — so every run launches with the provider's most-permissive - * advertised policy (same capabilities-driven resolution the subagent lane - * uses; no provider-specific branching here). If the capability lookup - * fails or the agent is unknown, fall back to provider defaults rather - * than failing the run. - */ private async resolveUnrestrictedPermissions( agentKind: AgentKind, location: ProjectLocation, @@ -253,8 +634,7 @@ export class ScheduleRunCoordinator { ); const agents = getProjectAgentStatuses(location, statuses.windows, statuses.wsl); const agent = agents.find((status) => status.kind === agentKind); - if (!agent) return {}; - return resolveUnrestrictedPermissionConfig(agent.capabilities); + return agent ? resolveUnrestrictedPermissionConfig(agent.capabilities) : {}; } catch { return {}; } diff --git a/src/main/schedules/ScheduleService.test.ts b/src/main/schedules/ScheduleService.test.ts index a41358483..da0b03bbd 100644 --- a/src/main/schedules/ScheduleService.test.ts +++ b/src/main/schedules/ScheduleService.test.ts @@ -1,6 +1,15 @@ import { describe, expect, it, vi } from "vitest"; -import type { ScheduledTask, ScheduledTaskInput } from "@/shared/contracts"; -import { ScheduleService, type ScheduleStore } from "./ScheduleService"; +import { + DEFAULT_SCHEDULE_AUTOMATION, + type ScheduledTask, + type ScheduledTaskInput, +} from "@/shared/contracts"; +import { + ScheduleService, + type ScheduleServiceOptions, + type ScheduleStore, +} from "./ScheduleService"; +import type { ScheduleTaskExecutionOutcome } from "./types"; function memoryStore(): ScheduleStore { const tasks = new Map(); @@ -23,6 +32,29 @@ const input: ScheduledTaskInput = { enabled: true, }; +function executionOutcome( + overrides: Partial = {}, +): ScheduleTaskExecutionOutcome { + return { + runId: "run-1", + status: "succeeded", + summary: "Done", + error: null, + stopMatched: false, + completionPolicySnapshot: { kind: "none" }, + result: { + outcome: "findings", + summary: "Done", + severity: "info", + unread: true, + archivedAt: null, + changedFiles: [], + stopReason: null, + }, + ...overrides, + }; +} + describe("ScheduleService", () => { it("creates device schedules with a future next run and no project fields", () => { const now = new Date(2026, 6, 6, 7, 0).getTime(); @@ -61,6 +93,216 @@ describe("ScheduleService", () => { expect(store.get(task.id)?.lastResult).toBe("Done"); }); + it("coalesces overlapping interval runs and advances from the due tick", async () => { + const store = memoryStore(); + let now = Date.parse("2026-07-10T12:00:00.000Z"); + let resolveRun!: (output: string) => void; + const runTask = vi.fn<() => Promise>( + () => new Promise((resolve) => (resolveRun = resolve)), + ); + const service = new ScheduleService({ store, runTask, now: () => now }); + const task = service.create({ + ...input, + recurrence: { kind: "interval", every: 30, unit: "minutes" }, + }); + + expect(task.nextRunAt).toBe("2026-07-10T12:30:00.000Z"); + now = Date.parse("2026-07-10T12:30:00.000Z"); + service.tick(); + service.tick(); + expect(runTask).toHaveBeenCalledTimes(1); + expect(store.get(task.id)?.nextRunAt).toBe("2026-07-10T13:00:00.000Z"); + + resolveRun("Done"); + await vi.waitFor(() => expect(store.get(task.id)?.lastStatus).toBe("succeeded")); + }); + + it("keeps an interval anchored when a due tick is late", () => { + const store = memoryStore(); + let now = Date.parse("2026-07-10T12:00:00.000Z"); + const service = new ScheduleService({ + store, + runTask: vi.fn<() => Promise>().mockResolvedValue("Done"), + now: () => now, + }); + const task = service.create({ + ...input, + recurrence: { kind: "interval", every: 30, unit: "minutes" }, + }); + + now = Date.parse("2026-07-10T12:47:00.000Z"); + service.tick(); + + expect(store.get(task.id)?.nextRunAt).toBe("2026-07-10T13:00:00.000Z"); + }); + + it("coalesces a missed interval once after restart", () => { + const store = memoryStore(); + let now = Date.parse("2026-07-10T12:00:00.000Z"); + const seed = new ScheduleService({ + store, + runTask: vi.fn<() => Promise>(), + now: () => now, + }); + const task = seed.create({ + ...input, + recurrence: { kind: "interval", every: 30, unit: "minutes" }, + }); + + now = Date.parse("2026-07-10T12:10:00.000Z"); + const beforeDue = new ScheduleService({ + store, + runTask: vi.fn<() => Promise>(), + now: () => now, + }); + beforeDue.start(); + expect(store.get(task.id)?.nextRunAt).toBe("2026-07-10T12:30:00.000Z"); + beforeDue.dispose(); + + now = Date.parse("2026-07-10T13:05:00.000Z"); + const afterMissedRuns = new ScheduleService({ + store, + runTask: vi.fn<() => Promise>(), + now: () => now, + }); + afterMissedRuns.start(); + expect(store.get(task.id)?.nextRunAt).toBe("2026-07-10T12:30:00.000Z"); + afterMissedRuns.dispose(); + }); + + it("keeps an interval anchored when unrelated fields are updated", () => { + const store = memoryStore(); + let now = Date.parse("2026-07-10T12:00:00.000Z"); + const service = new ScheduleService({ + store, + runTask: vi.fn<() => Promise>(), + now: () => now, + }); + const task = service.create({ + ...input, + recurrence: { kind: "interval", every: 30, unit: "minutes" }, + }); + + now = Date.parse("2026-07-10T12:10:00.000Z"); + const updated = service.update(task.id, { + ...input, + name: "Renamed brief", + recurrence: { kind: "interval", every: 30, unit: "minutes" }, + }); + + expect(updated.nextRunAt).toBe("2026-07-10T12:30:00.000Z"); + }); + + it("normalizes weekly days and cron whitespace", () => { + const service = new ScheduleService({ + store: memoryStore(), + runTask: vi.fn<() => Promise>(), + now: () => Date.parse("2026-07-10T12:00:00.000Z"), + }); + const weekly = service.create({ + ...input, + recurrence: { + kind: "weekly", + days: [5, 1, 5], + time: "09:00", + timeZone: " America/New_York ", + }, + }); + const cron = service.create({ + ...input, + recurrence: { + kind: "cron", + expression: " 0 9 * * 1-5 ", + timeZone: " Europe/London ", + }, + }); + + expect(weekly.recurrence).toEqual({ + kind: "weekly", + days: [1, 5], + time: "09:00", + timeZone: "America/New_York", + }); + expect(cron.recurrence).toEqual({ + kind: "cron", + expression: "0 9 * * 1-5", + timeZone: "Europe/London", + }); + }); + + it("adapts and reschedules its timer after schedule mutations", async () => { + vi.useFakeTimers(); + try { + const now = Date.parse("2026-07-10T12:00:00.000Z"); + vi.setSystemTime(now); + const store = memoryStore(); + const runTask = vi.fn<() => Promise>().mockResolvedValue("Done"); + const service = new ScheduleService({ store, runTask, tickIntervalMs: 300_000 }); + service.start(); + + const task = service.create({ + ...input, + recurrence: { kind: "once", runAt: new Date(now + 10_000).toISOString() }, + }); + service.update(task.id, { + ...input, + recurrence: { kind: "once", runAt: new Date(now + 1_000).toISOString() }, + }); + const deleted = service.create({ + ...input, + recurrence: { kind: "once", runAt: new Date(now + 500).toISOString() }, + }); + service.delete(deleted.id); + + await vi.advanceTimersByTimeAsync(999); + expect(runTask).not.toHaveBeenCalled(); + await vi.advanceTimersByTimeAsync(1); + expect(runTask).toHaveBeenCalledTimes(1); + service.dispose(); + } finally { + vi.useRealTimers(); + } + }); + + it("does not busy-loop while an overlapping manual run is active", async () => { + vi.useFakeTimers(); + try { + const now = Date.parse("2026-07-10T12:00:00.000Z"); + vi.setSystemTime(now); + const store = memoryStore(); + const list = vi.spyOn(store, "list"); + let resolveManual!: (output: string) => void; + const runTask = vi + .fn<() => Promise>() + .mockImplementationOnce(() => new Promise((resolve) => (resolveManual = resolve))) + .mockResolvedValue("Automatic run"); + const service = new ScheduleService({ store, runTask, tickIntervalMs: 300_000 }); + service.start(); + const task = service.create({ + ...input, + recurrence: { kind: "interval", every: 1, unit: "minutes" }, + }); + + service.runNow(task.id); + await vi.advanceTimersByTimeAsync(60_000); + expect(runTask).toHaveBeenCalledTimes(1); + const listCallsWhileDue = list.mock.calls.length; + await vi.advanceTimersByTimeAsync(10_000); + expect(list).toHaveBeenCalledTimes(listCallsWhileDue); + + resolveManual("Manual run"); + await Promise.resolve(); + await Promise.resolve(); + await vi.advanceTimersByTimeAsync(49); + expect(runTask).toHaveBeenCalledTimes(1); + await vi.advanceTimersByTimeAsync(1); + expect(runTask).toHaveBeenCalledTimes(2); + service.dispose(); + } finally { + vi.useRealTimers(); + } + }); + it("marks dangling runs interrupted for tasks left running on startup", () => { const store = memoryStore(); const now = new Date(2026, 6, 6, 9, 0).getTime(); @@ -83,7 +325,7 @@ describe("ScheduleService", () => { restarted.start(); expect(onStartupInterrupted).toHaveBeenCalledWith(task.id); - expect(store.get(task.id)?.lastStatus).toBe("failed"); + expect(store.get(task.id)?.lastStatus).toBe("interrupted"); restarted.dispose(); }); @@ -125,4 +367,356 @@ describe("ScheduleService", () => { await Promise.resolve(); expect(store.get(task.id)).toBeNull(); }); + + it("retries failed runs with the configured fixed delay", async () => { + vi.useFakeTimers(); + try { + const now = Date.parse("2026-07-10T12:00:00.000Z"); + vi.setSystemTime(now); + const store = memoryStore(); + const runTask = vi + .fn() + .mockResolvedValueOnce( + executionOutcome({ + status: "failed", + error: "Temporary failure", + result: { + ...executionOutcome().result, + outcome: "needs-attention", + severity: "error", + stopReason: "runtime-error", + }, + }), + ) + .mockResolvedValueOnce(executionOutcome({ runId: "run-2" })); + const onRetryingRun = vi.fn>(); + const service = new ScheduleService({ store, runTask, onRetryingRun }); + const task = service.create({ + ...input, + automation: { + ...DEFAULT_SCHEDULE_AUTOMATION, + retryPolicy: { kind: "fixed", maxAttempts: 2, delaySeconds: 10 }, + }, + }); + + service.runNow(task.id); + await Promise.resolve(); + expect(runTask).toHaveBeenCalledTimes(1); + expect(onRetryingRun).toHaveBeenCalledWith("run-1"); + await vi.advanceTimersByTimeAsync(10_000); + await vi.waitFor(() => expect(store.get(task.id)?.lastStatus).toBe("succeeded")); + expect(runTask).toHaveBeenNthCalledWith( + 2, + expect.anything(), + expect.objectContaining({ trigger: "retry", attempt: 2, iteration: 1 }), + ); + } finally { + vi.useRealTimers(); + } + }); + + it("cancels a pending retry by its failed run id", async () => { + vi.useFakeTimers(); + try { + const store = memoryStore(); + const runTask = vi + .fn() + .mockResolvedValueOnce( + executionOutcome({ + status: "failed", + error: "Temporary failure", + result: { + ...executionOutcome().result, + outcome: "needs-attention", + severity: "error", + stopReason: "runtime-error", + }, + }), + ) + .mockResolvedValueOnce(executionOutcome({ runId: "run-2" })); + const service = new ScheduleService({ store, runTask }); + const task = service.create({ + ...input, + automation: { + ...DEFAULT_SCHEDULE_AUTOMATION, + retryPolicy: { kind: "fixed", maxAttempts: 2, delaySeconds: 10 }, + }, + }); + + service.runNow(task.id); + await Promise.resolve(); + await Promise.resolve(); + expect(service.cancelRun("run-1")).toBe(true); + await vi.waitFor(() => expect(store.get(task.id)?.lastStatus).toBe("cancelled")); + await vi.advanceTimersByTimeAsync(10_000); + expect(runTask).toHaveBeenCalledTimes(1); + } finally { + vi.useRealTimers(); + } + }); + + it("cancels a pending retry when the schedule is paused", async () => { + vi.useFakeTimers(); + try { + const store = memoryStore(); + const automation = { + ...DEFAULT_SCHEDULE_AUTOMATION, + retryPolicy: { kind: "fixed" as const, maxAttempts: 2, delaySeconds: 10 }, + }; + const runTask = vi.fn().mockResolvedValue( + executionOutcome({ + status: "failed", + error: "Temporary failure", + result: { + ...executionOutcome().result, + outcome: "needs-attention", + severity: "error", + stopReason: "runtime-error", + }, + }), + ); + const service = new ScheduleService({ store, runTask }); + const task = service.create({ ...input, automation }); + + service.runNow(task.id); + await Promise.resolve(); + await Promise.resolve(); + service.update(task.id, { ...input, enabled: false, automation }); + + await vi.waitFor(() => expect(store.get(task.id)?.lastStatus).toBe("cancelled")); + await vi.advanceTimersByTimeAsync(10_000); + expect(runTask).toHaveBeenCalledTimes(1); + expect(store.get(task.id)?.enabled).toBe(false); + } finally { + vi.useRealTimers(); + } + }); + + it("stops after the configured maximum heartbeat iterations", async () => { + const store = memoryStore(); + const service = new ScheduleService({ + store, + runTask: vi.fn().mockResolvedValue(executionOutcome()), + now: () => Date.parse("2026-07-10T12:00:00.000Z"), + }); + const task = service.create({ + ...input, + automation: { + ...DEFAULT_SCHEDULE_AUTOMATION, + mode: { kind: "heartbeat", targetThreadId: "thread-1" }, + maxIterations: 1, + }, + }); + + service.runNow(task.id); + await vi.waitFor(() => expect(store.get(task.id)?.lastStatus).toBe("succeeded")); + expect(store.get(task.id)).toMatchObject({ + enabled: false, + nextRunAt: null, + iterationCount: 1, + }); + }); + + it("stops a heartbeat only when the evaluated completion policy is still current", async () => { + const store = memoryStore(); + let resolveRun!: (outcome: ScheduleTaskExecutionOutcome) => void; + const service = new ScheduleService({ + store, + runTask: () => + new Promise((resolve) => { + resolveRun = resolve; + }), + now: () => Date.parse("2026-07-10T12:00:00.000Z"), + }); + const automation = { + ...DEFAULT_SCHEDULE_AUTOMATION, + mode: { kind: "heartbeat" as const, targetThreadId: "thread-1" }, + completionPolicy: { + kind: "ai-evaluated" as const, + stopWhen: "Condition A", + confidenceThreshold: 0.9, + }, + }; + const task = service.create({ ...input, automation }); + service.runNow(task.id); + service.update(task.id, { + ...input, + automation: { + ...automation, + completionPolicy: { + kind: "ai-evaluated", + stopWhen: "Condition A", + confidenceThreshold: 1, + }, + }, + }); + resolveRun( + executionOutcome({ + stopMatched: true, + completionPolicySnapshot: automation.completionPolicy, + result: { + ...executionOutcome().result, + stopReason: "completion-condition", + completionEvaluation: { + stopMatched: true, + confidence: 0.99, + reason: "Matched", + condition: "Condition A", + evaluatedAt: "2026-07-10T12:00:01.000Z", + }, + }, + }), + ); + + await vi.waitFor(() => expect(store.get(task.id)?.lastStatus).toBe("succeeded")); + expect(store.get(task.id)?.enabled).toBe(true); + }); + + it("fails closed when completion evaluation cannot run", async () => { + const store = memoryStore(); + const service = new ScheduleService({ + store, + runTask: vi.fn().mockResolvedValue( + executionOutcome({ + status: "failed", + error: "Completion evaluation failed", + result: { + ...executionOutcome().result, + outcome: "needs-attention", + severity: "error", + stopReason: "completion-evaluation-error", + }, + }), + ), + now: () => Date.parse("2026-07-10T12:00:00.000Z"), + }); + const task = service.create({ + ...input, + automation: { + ...DEFAULT_SCHEDULE_AUTOMATION, + mode: { kind: "heartbeat", targetThreadId: "thread-1" }, + completionPolicy: { + kind: "ai-evaluated", + stopWhen: "Done", + confidenceThreshold: 0.9, + }, + }, + }); + + service.runNow(task.id); + await vi.waitFor(() => expect(store.get(task.id)?.lastStatus).toBe("failed")); + expect(store.get(task.id)?.enabled).toBe(false); + }); + + it("does not retry completed work when completion evaluation fails", async () => { + const store = memoryStore(); + const runTask = vi.fn().mockResolvedValue( + executionOutcome({ + status: "failed", + error: "Completion evaluation failed", + result: { + ...executionOutcome().result, + outcome: "needs-attention", + severity: "error", + stopReason: "completion-evaluation-error", + }, + }), + ); + const service = new ScheduleService({ store, runTask }); + const task = service.create({ + ...input, + automation: { + ...DEFAULT_SCHEDULE_AUTOMATION, + retryPolicy: { kind: "fixed", maxAttempts: 3, delaySeconds: 1 }, + }, + }); + + service.runNow(task.id); + await vi.waitFor(() => expect(store.get(task.id)?.lastStatus).toBe("failed")); + expect(runTask).toHaveBeenCalledTimes(1); + expect(store.get(task.id)?.enabled).toBe(false); + }); + + it("does not treat user cancellation as a stop-on-error failure", async () => { + const store = memoryStore(); + const service = new ScheduleService({ + store, + runTask: vi.fn().mockResolvedValue( + executionOutcome({ + status: "cancelled", + result: { + ...executionOutcome().result, + outcome: "no-findings", + unread: false, + archivedAt: "2026-07-10T12:00:00.000Z", + stopReason: "cancelled", + }, + }), + ), + }); + const task = service.create({ + ...input, + automation: { ...DEFAULT_SCHEDULE_AUTOMATION, stopOnError: true }, + }); + + service.runNow(task.id); + await vi.waitFor(() => expect(store.get(task.id)?.lastStatus).toBe("cancelled")); + expect(store.get(task.id)?.enabled).toBe(true); + }); + + it("skips a missed run at startup when configured", () => { + const store = memoryStore(); + let now = Date.parse("2026-07-10T12:00:00.000Z"); + const seed = new ScheduleService({ + store, + runTask: vi.fn(), + now: () => now, + }); + const task = seed.create({ + ...input, + recurrence: { kind: "interval", every: 30, unit: "minutes" }, + automation: { ...DEFAULT_SCHEDULE_AUTOMATION, misfirePolicy: "skip" }, + }); + now = Date.parse("2026-07-10T13:05:00.000Z"); + const recordSkipped = vi.fn>(); + const restarted = new ScheduleService({ + store, + runTask: vi.fn(), + recordSkipped, + now: () => now, + }); + + restarted.start(); + expect(store.get(task.id)).toMatchObject({ + lastStatus: "skipped", + nextRunAt: "2026-07-10T13:35:00.000Z", + }); + expect(recordSkipped).toHaveBeenCalledWith( + expect.objectContaining({ id: task.id }), + expect.objectContaining({ + scheduledFor: "2026-07-10T12:30:00.000Z", + trigger: "scheduled", + }), + ); + restarted.dispose(); + }); + + it("reanchors a late interval with the run-latest misfire policy", () => { + const store = memoryStore(); + let now = Date.parse("2026-07-10T12:00:00.000Z"); + const service = new ScheduleService({ + store, + runTask: vi.fn().mockResolvedValue("Done"), + now: () => now, + }); + const task = service.create({ + ...input, + recurrence: { kind: "interval", every: 30, unit: "minutes" }, + automation: { ...DEFAULT_SCHEDULE_AUTOMATION, misfirePolicy: "run-latest" }, + }); + now = Date.parse("2026-07-10T12:47:00.000Z"); + + service.tick(); + expect(store.get(task.id)?.nextRunAt).toBe("2026-07-10T13:17:00.000Z"); + }); }); diff --git a/src/main/schedules/ScheduleService.ts b/src/main/schedules/ScheduleService.ts index a3f210a14..32c6ade19 100644 --- a/src/main/schedules/ScheduleService.ts +++ b/src/main/schedules/ScheduleService.ts @@ -1,11 +1,23 @@ import { randomUUID } from "node:crypto"; import { + resolveScheduleAutomation, scheduledTaskInputSchema, + type ScheduleAutomation, type ScheduleRecurrence, + type ScheduledTaskRunStatus, type ScheduledTask, type ScheduledTaskInput, } from "@/shared/contracts"; -import { nextScheduleRunAt } from "@/shared/schedules"; +import { normalizeCronExpression } from "@/shared/contracts/schedule"; +import { advanceScheduleRunAt, nextScheduleRunAt } from "@/shared/schedules"; +import { toErrorMessage } from "@/shared/errorMessage"; +import { msg } from "@/shared/messages"; +import type { ScheduleRunContext, ScheduleTaskExecutionOutcome, ScheduleTaskRunner } from "./types"; + +const MIN_TICK_DELAY_MS = 50; +const MISFIRE_GRACE_MS = 1_000; + +class ScheduleRetryCancelledError extends Error {} export interface ScheduleStore { list(): ScheduledTask[]; @@ -16,7 +28,10 @@ export interface ScheduleStore { export interface ScheduleServiceOptions { store: ScheduleStore; - runTask(task: ScheduledTask): Promise; + runTask: ScheduleTaskRunner; + cancelRun?(runId: string): boolean; + recordSkipped?(task: ScheduledTask, context: ScheduleRunContext): void; + onRetryingRun?(runId: string): void; /** * Called during post-startup normalization for each task that was left in a * `running` state by a previous process. Lets the run-history layer mark its @@ -30,22 +45,37 @@ export interface ScheduleServiceOptions { export class ScheduleService { private readonly runningIds = new Set(); - private timer: ReturnType | null = null; + private readonly retryWaiters = new Map< + string, + { + timer: ReturnType; + resolve: (continueRetrying: boolean) => void; + runId: string | null; + } + >(); + private timer: ReturnType | null = null; + private started = false; private disposed = false; constructor(private readonly options: ScheduleServiceOptions) {} start(): void { - if (this.timer || this.disposed) return; + if (this.started || this.disposed) return; + this.started = true; this.normalizeAfterStartup(); - this.timer = setInterval(() => this.tick(), this.options.tickIntervalMs ?? 15_000); - this.timer.unref?.(); + this.rescheduleTimer(); } dispose(): void { this.disposed = true; - if (this.timer) clearInterval(this.timer); + this.started = false; + if (this.timer) clearTimeout(this.timer); this.timer = null; + for (const waiter of this.retryWaiters.values()) { + clearTimeout(waiter.timer); + waiter.resolve(false); + } + this.retryWaiters.clear(); } list(): ScheduledTask[] { @@ -63,6 +93,7 @@ export class ScheduleService { const task: ScheduledTask = { id: randomUUID(), ...parsed, + automation: resolveScheduleAutomation(parsed.automation), enabled, nextRunAt, lastRunAt: null, @@ -70,52 +101,119 @@ export class ScheduleService { lastStatus: "never", lastResult: null, lastError: null, + iterationCount: 0, createdAt: new Date(now).toISOString(), updatedAt: new Date(now).toISOString(), }; this.options.store.upsert(task); + this.rescheduleTimer(); return task; } update(id: string, input: ScheduledTaskInput): ScheduledTask { const current = this.requireTask(id); const parsed = this.normalizeInput(input); + if (!parsed.enabled) this.cancelRetryWaiter(id); const now = this.now(); - const { enabled, nextRunAt } = this.resolveEnablement(parsed.recurrence, parsed.enabled, now); + const schedule = + current.enabled && + parsed.enabled && + current.nextRunAt && + current.recurrence.kind === "interval" && + parsed.recurrence.kind === "interval" && + current.recurrence.every === parsed.recurrence.every && + current.recurrence.unit === parsed.recurrence.unit + ? this.resolveExistingInterval(parsed.recurrence, current.nextRunAt, now) + : this.resolveEnablement(parsed.recurrence, parsed.enabled, now); + const automation = resolveScheduleAutomation(parsed.automation); + const resetIterations = + (!current.enabled && schedule.enabled) || + JSON.stringify(resolveScheduleAutomation(current.automation)) !== JSON.stringify(automation); const task: ScheduledTask = { ...current, ...parsed, - enabled, - nextRunAt, + automation, + enabled: schedule.enabled, + nextRunAt: schedule.nextRunAt, + ...(resetIterations ? { iterationCount: 0 } : {}), updatedAt: new Date(now).toISOString(), }; this.options.store.upsert(task); + this.rescheduleTimer(); return task; } delete(id: string): void { + this.cancelRetryWaiter(id); this.options.store.delete(id); + this.rescheduleTimer(); } runNow(id: string): ScheduledTask { - const task = this.requireTask(id); - return this.startRun(task, false); + let task = this.requireTask(id); + const automation = resolveScheduleAutomation(task.automation); + if ( + automation.maxIterations !== null && + (task.iterationCount ?? 0) >= automation.maxIterations + ) { + task = { ...task, iterationCount: 0 }; + this.options.store.upsert(task); + } + const running = this.startRun(task, false, "manual"); + this.rescheduleTimer(); + return running; + } + + cancelRun(runId: string): boolean { + if (this.options.cancelRun?.(runId)) return true; + for (const [scheduleId, waiter] of this.retryWaiters) { + if (waiter.runId === runId) return this.cancelRetryWaiter(scheduleId); + } + return false; } tick(): void { if (this.disposed) return; const now = this.now(); for (const task of this.options.store.list()) { - if (!task.enabled || !task.nextRunAt || Date.parse(task.nextRunAt) > now) continue; - this.startRun(task, true); + if ( + this.runningIds.has(task.id) || + !task.enabled || + !task.nextRunAt || + Date.parse(task.nextRunAt) > now + ) { + continue; + } + const automation = resolveScheduleAutomation(task.automation); + if ( + automation.misfirePolicy === "skip" && + now - Date.parse(task.nextRunAt) > MISFIRE_GRACE_MS + ) { + this.skipDueRun(task, now); + continue; + } + this.startRun(task, true, "scheduled"); } + this.rescheduleTimer(); } - private startRun(task: ScheduledTask, advanceSchedule: boolean): ScheduledTask { + private startRun( + task: ScheduledTask, + advanceSchedule: boolean, + trigger: ScheduleRunContext["trigger"], + ): ScheduledTask { if (this.runningIds.has(task.id)) return this.requireTask(task.id); const now = this.now(); - const nextRunAt = advanceSchedule ? nextScheduleRunAt(task.recurrence, now) : task.nextRunAt; + const scheduledFor = advanceSchedule ? task.nextRunAt! : new Date(now).toISOString(); + const automation = resolveScheduleAutomation(task.automation); + const nextRunAt = advanceSchedule + ? automation.misfirePolicy === "run-latest" && + now - Date.parse(scheduledFor) > MISFIRE_GRACE_MS + ? nextScheduleRunAt(task.recurrence, now) + : advanceScheduleRunAt(task.recurrence, Date.parse(scheduledFor), now) + : task.nextRunAt; + const iteration = (task.iterationCount ?? 0) + 1; const running: ScheduledTask = { ...task, ...(advanceSchedule ? { enabled: task.enabled && nextRunAt !== null, nextRunAt } : {}), @@ -124,52 +222,209 @@ export class ScheduleService { lastStatus: "running", lastResult: null, lastError: null, + iterationCount: iteration, updatedAt: new Date(now).toISOString(), }; this.runningIds.add(task.id); this.options.store.upsert(running); - void this.options - .runTask(running) - .then((output) => this.settle(task.id, "succeeded", output, null)) - .catch((error: unknown) => - this.settle( - task.id, - "failed", - null, - error instanceof Error ? error.message : String(error), - ), - ); + const context: ScheduleRunContext = { + scheduledFor, + trigger, + attempt: 1, + iteration, + }; + void this.runWithRetries(running, context) + .then((outcome) => this.settleOutcome(task.id, outcome)) + .catch((error: unknown) => { + if (error instanceof ScheduleRetryCancelledError) { + this.settle(task.id, "cancelled", null, null); + return; + } + this.settle(task.id, "failed", null, toErrorMessage(error)); + }); return running; } + private skipDueRun(task: ScheduledTask, now: number): void { + const scheduledFor = task.nextRunAt!; + const nextRunAt = advanceScheduleRunAt(task.recurrence, Date.parse(scheduledFor), now); + this.options.recordSkipped?.(task, { + scheduledFor, + trigger: "scheduled", + attempt: 1, + iteration: (task.iterationCount ?? 0) + 1, + }); + this.options.store.upsert({ + ...task, + enabled: task.enabled && nextRunAt !== null, + nextRunAt, + lastRunAt: new Date(now).toISOString(), + lastCompletedAt: new Date(now).toISOString(), + lastStatus: "skipped", + lastResult: null, + lastError: null, + updatedAt: new Date(now).toISOString(), + }); + } + + private async runWithRetries( + task: ScheduledTask, + initialContext: ScheduleRunContext, + ): Promise { + const retryPolicy = resolveScheduleAutomation(task.automation).retryPolicy; + const maxAttempts = retryPolicy.kind === "none" ? 1 : retryPolicy.maxAttempts; + let context = initialContext; + let failedRunId: string | null = null; + + while (true) { + try { + const outcome = await this.options.runTask(task, context); + if ( + typeof outcome === "string" || + outcome.status !== "failed" || + outcome.result.stopReason === "completion-evaluation-error" || + context.attempt >= maxAttempts + ) { + return outcome; + } + failedRunId = outcome.runId; + this.options.onRetryingRun?.(outcome.runId); + } catch (error) { + if (context.attempt >= maxAttempts) throw error; + failedRunId = null; + } + + const delaySeconds = this.retryDelaySeconds(retryPolicy, context.attempt); + if (!(await this.waitForRetry(task.id, delaySeconds * 1_000, failedRunId))) { + throw new ScheduleRetryCancelledError(msg("automation.retry.cancelled")); + } + if (!this.options.store.get(task.id)) { + throw new Error(msg("automation.retry.taskDeleted")); + } + context = { + ...context, + trigger: "retry", + attempt: context.attempt + 1, + }; + } + } + + private retryDelaySeconds( + policy: ScheduleAutomation["retryPolicy"], + failedAttempt: number, + ): number { + if (policy.kind === "fixed") return policy.delaySeconds; + if (policy.kind === "exponential") { + return Math.min( + policy.maxDelaySeconds, + policy.initialDelaySeconds * 2 ** (failedAttempt - 1), + ); + } + return 0; + } + + private waitForRetry( + scheduleId: string, + delayMs: number, + runId: string | null, + ): Promise { + return new Promise((resolve) => { + const timer = setTimeout(() => { + this.retryWaiters.delete(scheduleId); + resolve(true); + }, delayMs); + timer.unref?.(); + this.retryWaiters.set(scheduleId, { timer, resolve, runId }); + }); + } + + private cancelRetryWaiter(scheduleId: string): boolean { + const waiter = this.retryWaiters.get(scheduleId); + if (!waiter) return false; + clearTimeout(waiter.timer); + this.retryWaiters.delete(scheduleId); + waiter.resolve(false); + return true; + } + + private settleOutcome(id: string, outcome: ScheduleTaskExecutionOutcome | string): void { + if (typeof outcome === "string") { + this.settle(id, "succeeded", outcome, null); + return; + } + const currentPolicy = resolveScheduleAutomation( + this.options.store.get(id)?.automation, + ).completionPolicy; + const stopMatched = + outcome.stopMatched && + JSON.stringify(currentPolicy) === JSON.stringify(outcome.completionPolicySnapshot); + this.settle( + id, + outcome.status, + outcome.summary, + outcome.error, + stopMatched, + outcome.result.stopReason === "completion-evaluation-error", + ); + } + private settle( id: string, - status: "succeeded" | "failed", + status: Exclude, result: string | null, error: string | null, + stopMatched = false, + policyFailure = false, ): void { this.runningIds.delete(id); + this.cancelRetryWaiter(id); if (this.disposed) return; const current = this.options.store.get(id); - if (!current) return; + if (!current) { + this.rescheduleTimer(); + return; + } const now = this.now(); + const automation = resolveScheduleAutomation(current.automation); + const reachedIterationLimit = + automation.maxIterations !== null && + (current.iterationCount ?? 0) >= automation.maxIterations; + const stoppedOnError = automation.stopOnError && status === "failed"; + const shouldDisable = stopMatched || policyFailure || reachedIterationLimit || stoppedOnError; this.options.store.upsert({ ...current, + ...(shouldDisable ? { enabled: false, nextRunAt: null } : {}), lastCompletedAt: new Date(now).toISOString(), lastStatus: status, lastResult: result, lastError: error, updatedAt: new Date(now).toISOString(), }); + this.rescheduleTimer(); } private normalizeAfterStartup(): void { const now = this.now(); for (const task of this.options.store.list()) { - const { enabled, nextRunAt } = this.resolveEnablement(task.recurrence, task.enabled, now); + const automation = resolveScheduleAutomation(task.automation); + const isMissed = task.enabled && task.nextRunAt !== null && Date.parse(task.nextRunAt) <= now; + const skipped = isMissed && automation.misfirePolicy === "skip"; + const { enabled, nextRunAt } = skipped + ? this.resolveEnablement(task.recurrence, task.enabled, now) + : isMissed + ? { enabled: task.enabled, nextRunAt: task.nextRunAt } + : this.resolveStartupEnablement(task, now); const wasRunning = task.lastStatus === "running"; if (wasRunning) this.options.onStartupInterrupted?.(task.id); + if (skipped && task.nextRunAt) { + this.options.recordSkipped?.(task, { + scheduledFor: task.nextRunAt, + trigger: "scheduled", + attempt: 1, + iteration: (task.iterationCount ?? 0) + 1, + }); + } this.options.store.upsert({ ...task, enabled, @@ -177,10 +432,17 @@ export class ScheduleService { ...(wasRunning ? { lastCompletedAt: new Date(now).toISOString(), - lastStatus: "failed" as const, + lastStatus: "interrupted" as const, lastError: null, } - : {}), + : skipped + ? { + lastCompletedAt: new Date(now).toISOString(), + lastStatus: "skipped" as const, + lastResult: null, + lastError: null, + } + : {}), updatedAt: new Date(now).toISOString(), }); } @@ -188,14 +450,28 @@ export class ScheduleService { private normalizeInput(input: ScheduledTaskInput): ScheduledTaskInput { const parsed = scheduledTaskInputSchema.parse(input); - if (parsed.recurrence.kind !== "weekly") return parsed; - return { - ...parsed, - recurrence: { - ...parsed.recurrence, - days: [...new Set(parsed.recurrence.days)].sort((left, right) => left - right), - }, - }; + if (parsed.recurrence.kind === "weekly") { + const { timeZone, ...recurrence } = parsed.recurrence; + return { + ...parsed, + recurrence: { + ...recurrence, + days: [...new Set(recurrence.days)].sort((left, right) => left - right), + ...(timeZone ? { timeZone: timeZone.trim() } : {}), + }, + }; + } + if (parsed.recurrence.kind === "cron") { + return { + ...parsed, + recurrence: { + ...parsed.recurrence, + expression: normalizeCronExpression(parsed.recurrence.expression), + timeZone: parsed.recurrence.timeZone.trim(), + }, + }; + } + return parsed; } /** @@ -212,6 +488,29 @@ export class ScheduleService { return { enabled: enabled && nextRunAt !== null, nextRunAt }; } + private resolveStartupEnablement( + task: ScheduledTask, + now: number, + ): { enabled: boolean; nextRunAt: string | null } { + if (task.enabled && task.recurrence.kind === "interval" && task.nextRunAt) { + return this.resolveExistingInterval(task.recurrence, task.nextRunAt, now); + } + return this.resolveEnablement(task.recurrence, task.enabled, now); + } + + private resolveExistingInterval( + recurrence: Extract, + nextRunAt: string, + now: number, + ): { enabled: true; nextRunAt: string } { + const scheduledAt = Date.parse(nextRunAt); + return { + enabled: true, + nextRunAt: + scheduledAt > now ? nextRunAt : advanceScheduleRunAt(recurrence, scheduledAt, now)!, + }; + } + private requireTask(id: string): ScheduledTask { const task = this.options.store.get(id); if (!task) throw new Error("Scheduled task not found."); @@ -221,4 +520,23 @@ export class ScheduleService { private now(): number { return (this.options.now ?? Date.now)(); } + + private rescheduleTimer(): void { + if (!this.started || this.disposed) return; + if (this.timer) clearTimeout(this.timer); + + const now = this.now(); + let delay = this.options.tickIntervalMs ?? 15_000; + for (const task of this.options.store.list()) { + if (this.runningIds.has(task.id) || !task.enabled || !task.nextRunAt) continue; + delay = Math.min(delay, Math.max(0, Date.parse(task.nextRunAt) - now)); + } + delay = Math.max(MIN_TICK_DELAY_MS, delay); + + this.timer = setTimeout(() => { + this.timer = null; + this.tick(); + }, delay); + this.timer.unref?.(); + } } diff --git a/src/main/schedules/index.ts b/src/main/schedules/index.ts index 661446865..8fa07f360 100644 --- a/src/main/schedules/index.ts +++ b/src/main/schedules/index.ts @@ -1,10 +1,14 @@ import { dbDeleteSchedule, dbGetSchedule, dbGetSchedules, dbUpsertSchedule } from "../db"; import type { ScheduledTask } from "@/shared/contracts"; import { ScheduleService } from "./ScheduleService"; +import type { ScheduleRunContext, ScheduleTaskRunner } from "./types"; export interface DeviceScheduleServiceOptions { /** Executes one due/manual run and resolves with its quick-glance summary. */ - runTask: (task: ScheduledTask) => Promise; + runTask: ScheduleTaskRunner; + cancelRun?: (runId: string) => boolean; + recordSkipped?: (task: ScheduledTask, context: ScheduleRunContext) => void; + onRetryingRun?: (runId: string) => void; /** Marks a schedule's dangling run rows interrupted after a restart. */ onStartupInterrupted?: (scheduleId: string) => void; } @@ -20,10 +24,14 @@ export function createDeviceScheduleService( delete: dbDeleteSchedule, }, runTask: options.runTask, + ...(options.cancelRun ? { cancelRun: options.cancelRun } : {}), + ...(options.recordSkipped ? { recordSkipped: options.recordSkipped } : {}), + ...(options.onRetryingRun ? { onRetryingRun: options.onRetryingRun } : {}), ...(options.onStartupInterrupted ? { onStartupInterrupted: options.onStartupInterrupted } : {}), }); } export { ScheduleService, type ScheduleStore } from "./ScheduleService"; export { ScheduleRunCoordinator, type ScheduleRunCoordinatorDeps } from "./ScheduleRunCoordinator"; +export type { ScheduleRunContext, ScheduleTaskExecutionOutcome, ScheduleTaskRunner } from "./types"; export { ensureHomeProjectRow, homeScopeLocation } from "./homeProject"; diff --git a/src/main/schedules/scheduleRunResults.ts b/src/main/schedules/scheduleRunResults.ts new file mode 100644 index 000000000..828245f87 --- /dev/null +++ b/src/main/schedules/scheduleRunResults.ts @@ -0,0 +1,91 @@ +import { + fileChangePayloadSchema, + messageItemPayloadSchema, + type ScheduleRunResult, + type ScheduleRunStatus, +} from "@/shared/contracts"; +import type { PersistedRuntimeItem } from "../db/runtimeItems"; + +export function collectScheduleRunItems(items: readonly PersistedRuntimeItem[]): { + summary: string | null; + changedFiles: string[]; +} { + const freshItems = items.filter((item) => item.parentItemId === undefined); + const summary = + freshItems + .filter((item) => item.type === "assistant_message") + .map(readAssistantText) + .filter((text): text is string => text !== null) + .at(-1) ?? null; + const changedFiles = [ + ...new Set( + freshItems.flatMap((item) => { + if (item.type !== "file_change") return []; + const parsed = fileChangePayloadSchema.safeParse(item.payload); + return parsed.success && parsed.data.status !== "error" ? [parsed.data.path] : []; + }), + ), + ].slice(0, 100); + return { summary, changedFiles }; +} + +function readAssistantText(item: PersistedRuntimeItem): string | null { + const streamText = item.streams.assistant_text?.trim(); + if (streamText) return streamText.slice(0, 2_000); + const parsed = messageItemPayloadSchema.safeParse(item.payload); + if (!parsed.success) return null; + const text = parsed.data.content + .filter((block) => block.kind === "text") + .map((block) => block.text) + .join("\n") + .trim(); + return text ? text.slice(0, 2_000) : null; +} + +export function buildScheduleRunResult(input: { + status: Exclude; + summary: string | null; + changedFiles: string[]; + completedAt: string; + stopReason: string | null; + completionEvaluation?: NonNullable; +}): ScheduleRunResult { + if (input.status === "succeeded") { + const outcome = + input.changedFiles.length > 0 ? "changed-files" : input.summary ? "unknown" : "no-findings"; + const unread = outcome !== "no-findings"; + return { + outcome, + summary: input.summary, + severity: "info", + unread, + archivedAt: unread ? null : input.completedAt, + changedFiles: input.changedFiles, + stopReason: input.stopReason, + ...(input.completionEvaluation ? { completionEvaluation: input.completionEvaluation } : {}), + }; + } + if (input.status === "cancelled" || input.status === "skipped") { + return { + outcome: "no-findings", + summary: input.summary, + severity: "info", + unread: false, + archivedAt: input.completedAt, + changedFiles: input.changedFiles, + stopReason: input.stopReason, + }; + } + return { + outcome: "needs-attention", + summary: input.summary, + severity: + input.status === "interrupted" || input.status === "waiting-for-approval" + ? "warning" + : "error", + unread: true, + archivedAt: null, + changedFiles: input.changedFiles, + stopReason: input.stopReason, + }; +} diff --git a/src/main/schedules/types.ts b/src/main/schedules/types.ts new file mode 100644 index 000000000..5ec369383 --- /dev/null +++ b/src/main/schedules/types.ts @@ -0,0 +1,29 @@ +import type { + ScheduleCompletionPolicy, + ScheduleRunResult, + ScheduleRunStatus, + ScheduleRunTrigger, + ScheduledTask, +} from "@/shared/contracts"; + +export interface ScheduleRunContext { + scheduledFor: string; + trigger: ScheduleRunTrigger; + attempt: number; + iteration: number; +} + +export interface ScheduleTaskExecutionOutcome { + runId: string; + status: Exclude; + summary: string | null; + error: string | null; + result: ScheduleRunResult; + stopMatched: boolean; + completionPolicySnapshot: ScheduleCompletionPolicy; +} + +export type ScheduleTaskRunner = ( + task: ScheduledTask, + context: ScheduleRunContext, +) => Promise; diff --git a/src/mobile/bridge.test.ts b/src/mobile/bridge.test.ts new file mode 100644 index 000000000..92673a4e8 --- /dev/null +++ b/src/mobile/bridge.test.ts @@ -0,0 +1,63 @@ +// @vitest-environment jsdom + +import { afterEach, describe, expect, it, vi } from "vitest"; +import type { ScheduleRunInboxQuery, UpdateScheduleRunStatePayload } from "@/shared/contracts"; +import type { PoracodeBridge } from "@/shared/ipc"; +import type { RemoteDesktopClient } from "./remoteClient"; +import { installRemoteBridge, setRemoteBridgeClient } from "./bridge"; + +vi.mock("./browserMirror", () => ({ + useBrowserMirrorStore: { getState: () => ({}) }, +})); +vi.mock("./settingsSync", () => ({ pushDesktopSettingsDiff: () => undefined })); +vi.mock("./storeSync", () => ({ applyAgentStatuses: () => undefined })); + +describe("remote schedule run bridge", () => { + afterEach(() => { + setRemoteBridgeClient(null); + Object.defineProperty(window, "poracode", { + configurable: true, + writable: true, + value: undefined, + }); + }); + + it("forwards schedule run operations to the active desktop client", async () => { + const scheduleRuns = vi.fn<(id: string) => Promise>(async () => []); + const scheduleRunInbox = vi.fn<(query: ScheduleRunInboxQuery) => Promise>( + async () => [], + ); + const updateScheduleRunState = vi.fn<(payload: UpdateScheduleRunStatePayload) => Promise>( + async () => null, + ); + const cancelScheduleRun = vi.fn<(id: string) => Promise>(async () => true); + setRemoteBridgeClient({ + scheduleRuns, + scheduleRunInbox, + updateScheduleRunState, + cancelScheduleRun, + } as unknown as RemoteDesktopClient); + Object.defineProperty(window, "poracode", { + configurable: true, + writable: true, + value: undefined, + }); + installRemoteBridge(); + const bridge = window.poracode as Pick< + PoracodeBridge, + "getScheduleRuns" | "getScheduleRunInbox" | "updateScheduleRunState" | "cancelScheduleRun" + >; + const scheduleId = "d2ac39e9-14ac-4776-9279-37a1e455a5db"; + const runId = "6f3b1a2c-1111-4d5e-8a9b-0c1d2e3f4a5b"; + + await bridge.getScheduleRuns({ id: scheduleId }); + await bridge.getScheduleRunInbox({ filter: "unread", limit: 25 }); + await bridge.updateScheduleRunState({ id: runId, unread: false }); + await bridge.cancelScheduleRun({ id: runId }); + + expect(scheduleRuns).toHaveBeenCalledWith(scheduleId); + expect(scheduleRunInbox).toHaveBeenCalledWith({ filter: "unread", limit: 25 }); + expect(updateScheduleRunState).toHaveBeenCalledWith({ id: runId, unread: false }); + expect(cancelScheduleRun).toHaveBeenCalledWith(runId); + }); +}); diff --git a/src/mobile/bridge.ts b/src/mobile/bridge.ts index c41c202b7..10ad1bac7 100644 --- a/src/mobile/bridge.ts +++ b/src/mobile/bridge.ts @@ -15,6 +15,8 @@ import type { StartThreadPayload, WriteTerminalPayload, ScheduledTaskInput, + ScheduleRunInboxQuery, + UpdateScheduleRunStatePayload, } from "@/shared/contracts"; import type { BrowserState, BrowserTabInfo, PoracodeBridge } from "@/shared/ipc"; import { @@ -159,11 +161,30 @@ const remoteBridge = { setProfileIdentity: (identity: ProfileIdentity) => requireClient().setProfileIdentity(identity), getSchedules: () => requireClient().schedules(), + getAutomationsSnapshot: async (query: ScheduleRunInboxQuery) => { + const [schedules, runs, unreadRuns] = await Promise.all([ + requireClient().schedules(), + requireClient().scheduleRunInbox(query), + query.filter === "unread" + ? Promise.resolve(null) + : requireClient().scheduleRunInbox({ filter: "unread", limit: 100 }), + ]); + return { + schedules, + runs, + unreadCount: (unreadRuns ?? runs).length, + }; + }, createSchedule: (task: ScheduledTaskInput) => requireClient().createSchedule(task), updateSchedule: ({ id, task }: { id: string; task: ScheduledTaskInput }) => requireClient().updateSchedule(id, task), deleteSchedule: ({ id }: { id: string }) => requireClient().deleteSchedule(id), runScheduleNow: ({ id }: { id: string }) => requireClient().runScheduleNow(id), + getScheduleRuns: ({ id }: { id: string }) => requireClient().scheduleRuns(id), + getScheduleRunInbox: (query: ScheduleRunInboxQuery) => requireClient().scheduleRunInbox(query), + updateScheduleRunState: (payload: UpdateScheduleRunStatePayload) => + requireClient().updateScheduleRunState(payload), + cancelScheduleRun: ({ id }: { id: string }) => requireClient().cancelScheduleRun(id), // Shared settings persist per device via the store's localStorage fallback. // Remote-editable keys (the desktop's AI helpers) are additionally diffed diff --git a/src/mobile/settingsSections.ts b/src/mobile/settingsSections.ts index 23f3f6418..48f900dd5 100644 --- a/src/mobile/settingsSections.ts +++ b/src/mobile/settingsSections.ts @@ -24,7 +24,7 @@ export const MOBILE_SETTINGS_SECTION_LABELS: Record { ); expect(screen.getByText("AI")).toBeInTheDocument(); - expect(screen.getByText("Schedules")).toBeInTheDocument(); + expect(screen.getByText("Automations")).toBeInTheDocument(); expect(screen.getByText("Agents")).toBeInTheDocument(); expect(screen.getByText("Archived Threads")).toBeInTheDocument(); expect(screen.queryByText("Appearance")).not.toBeInTheDocument(); diff --git a/src/renderer/components/common/LightballTabs.tsx b/src/renderer/components/common/LightballTabs.tsx index f90365ce5..485e019de 100644 --- a/src/renderer/components/common/LightballTabs.tsx +++ b/src/renderer/components/common/LightballTabs.tsx @@ -13,6 +13,22 @@ export interface LightballTab { disabled?: boolean; } +function LightballTabCount(props: { value: number; active: boolean }) { + return ( + + {props.value} + + ); +} + +export function makeLightballCountTrailing(count: number) { + return (active: boolean) => ; +} + /** * Shared pill-shaped tabs with a flying-lightball indicator. Used by the * Chat | CLI presentation switcher and the PR Review tabs. Consumers pick the diff --git a/src/renderer/components/mcp/McpServersManager.test.tsx b/src/renderer/components/mcp/McpServersManager.test.tsx index f6b9b8998..52908c22d 100644 --- a/src/renderer/components/mcp/McpServersManager.test.tsx +++ b/src/renderer/components/mcp/McpServersManager.test.tsx @@ -154,10 +154,11 @@ describe("McpServersManager", () => { const row = document.querySelector('[data-built-in-mcp-server="app-controls"]'); expect(row).not.toBeNull(); - fireEvent.click(within(row as HTMLElement).getByRole("button", { name: "5 tools" })); + fireEvent.click(within(row as HTMLElement).getByRole("button", { name: "12 tools" })); const dialog = screen.getByRole("dialog", { name: "App Controls" }); expect(within(dialog).getByText("list_schedules")).toBeInTheDocument(); + expect(within(dialog).getByText("list_schedule_run_inbox")).toBeInTheDocument(); expect(within(dialog).getByText("delete_schedule")).toBeInTheDocument(); fireEvent.click(within(dialog).getByRole("switch", { name: "Enable delete_schedule" })); expect(onBuiltInToolEnabledChange).toHaveBeenCalledWith( diff --git a/src/renderer/i18n/sharedMessages.ts b/src/renderer/i18n/sharedMessages.ts index 6f98feaf3..e3f6aaa4c 100644 --- a/src/renderer/i18n/sharedMessages.ts +++ b/src/renderer/i18n/sharedMessages.ts @@ -59,6 +59,51 @@ const SHARED_MESSAGE_DESCRIPTORS: Record = { "supervisor.restarted": msg({ message: "Background process restarted" }), "supervisor.exited": msg({ message: "Background process exited unexpectedly" }), "supervisor.notRunning": msg({ message: "Background process is not running" }), + "automation.run.exited": msg({ + message: "The automation conversation exited before the turn completed.", + }), + "automation.run.replyRequired": msg({ + message: "The automation needs a reply before it can continue.", + }), + "automation.run.approvalRequired": msg({ + message: "The automation needs approval before it can continue.", + }), + "automation.run.failed": msg({ message: "The scheduled automation failed." }), + "automation.run.targetInUse": msg({ + message: "Another automation is already using this conversation.", + }), + "automation.run.timeLimit": msg({ message: "The automation exceeded its time limit." }), + "automation.run.completionUnavailable": msg({ + message: "Completion evaluation is unavailable.", + }), + "automation.run.completionFailed": msg({ + message: "Completion evaluation failed: {detail}", + }), + "automation.run.projectMissing": msg({ message: "Project no longer exists." }), + "automation.heartbeat.missing": msg({ + message: "The heartbeat conversation no longer exists.", + }), + "automation.heartbeat.archived": msg({ + message: "The heartbeat conversation is archived.", + }), + "automation.heartbeat.nativeChatRequired": msg({ + message: "Heartbeat automations require a native chat conversation.", + }), + "automation.heartbeat.differentProject": msg({ + message: "The heartbeat conversation belongs to a different project.", + }), + "automation.heartbeat.differentAgent": msg({ + message: "The heartbeat conversation uses a different agent.", + }), + "automation.heartbeat.busy": msg({ + message: "The heartbeat conversation is currently busy.", + }), + "automation.heartbeat.unavailable": msg({ message: "Heartbeat execution is unavailable." }), + "automation.heartbeat.cannotResume": msg({ + message: "The heartbeat conversation cannot be resumed.", + }), + "automation.retry.cancelled": msg({ message: "Scheduled retry was cancelled." }), + "automation.retry.taskDeleted": msg({ message: "Scheduled task was deleted before retrying." }), "update.error": msg({ message: "Update error: {detail}" }), }; diff --git a/src/renderer/locales/de/messages.po b/src/renderer/locales/de/messages.po index 7cd1b4439..0a3027005 100644 --- a/src/renderer/locales/de/messages.po +++ b/src/renderer/locales/de/messages.po @@ -288,6 +288,11 @@ msgstr "{agentLabel}: {statusLabel}. Für Statusdetails den Mauszeiger darüber msgid "{agentLead} needs your input to continue." msgstr "{agentLead} benötigt deine Eingabe, um fortzufahren." +#. placeholder {0}: task.recurrence.timeZone +#: src/renderer/views/SchedulesView/SchedulesView.tsx +msgid "{cadence} in {0}" +msgstr "{cadence} in {0}" + #: src/mobile/views/pr/PrOverviewPage.tsx msgid "{commitsCount, plural, one {# commit} other {# commits}}" msgstr "{commitsCount, plural, one {# Commit} other {# Commits}}" @@ -315,6 +320,18 @@ msgstr "vor {days} d" msgid "{envOrAgentLabel} needs authentication." msgstr "{envOrAgentLabel} benötigt eine Authentifizierung." +#: src/renderer/views/SchedulesView/SchedulesView.tsx +msgid "{every, plural, one {Every day} other {Every # days}}" +msgstr "{every, plural, one {Jeden Tag} other {Alle # Tage}}" + +#: src/renderer/views/SchedulesView/SchedulesView.tsx +msgid "{every, plural, one {Every hour} other {Every # hours}}" +msgstr "{every, plural, one {Jede Stunde} other {Alle # Stunden}}" + +#: src/renderer/views/SchedulesView/SchedulesView.tsx +msgid "{every, plural, one {Every minute} other {Every # minutes}}" +msgstr "{every, plural, one {Jede Minute} other {Alle # Minuten}}" + #: src/mobile/views/pr/PrOverviewPage.tsx msgid "{filesCount, plural, one {# file changed} other {# files changed}}" msgstr "{filesCount, plural, one {# Datei geändert} other {# Dateien geändert}}" @@ -491,6 +508,10 @@ msgstr "~{money}{tokens} · {0} · geschätzt" msgid "≈{0}% by reset" msgstr "≈{0}% bis zum Reset" +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "0 9 * * 1-5" +msgstr "0 9 * * 1-5" + #: src/mobile/views/ThreadsView.tsx msgid "1 thread" msgstr "1 Thread" @@ -840,6 +861,10 @@ msgstr "KI-Git-Aktionen" msgid "AI providers" msgstr "KI-Anbieter" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "AI stop condition" +msgstr "KI-Stoppbedingung" + #: src/mobile/views/MoreView.tsx #~ msgid "AI, agents, and archived threads on the paired desktop" #~ msgstr "KI, Agents und archivierte Threads auf dem gekoppelten Desktop" @@ -851,6 +876,7 @@ msgstr "Benachrichtigungen, wenn Threads dich brauchen" #: src/renderer/commands/shortcutCatalog.ts #: src/renderer/components/skills/SkillsManager.tsx #: src/renderer/views/PullRequestsView/PullRequestsView.tsx +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx #: src/renderer/views/SchedulesView/SchedulesView.tsx #: src/renderer/views/SettingsOverlay/parts/ProfileSettings.tsx msgid "All" @@ -943,6 +969,10 @@ msgstr "Immer ausgeschlossen" msgid "An MCP server with this name already exists." msgstr "Ein MCP-Server mit diesem Namen ist bereits vorhanden." +#: src/renderer/i18n/sharedMessages.ts +msgid "Another automation is already using this conversation." +msgstr "Eine andere Automation verwendet dieses Gespräch bereits." + #: src/renderer/components/thread/ChatPane/parts/CheckpointRevertControls.tsx msgid "Another chat uses this same tree. File restore could overwrite that chat's changes." msgstr "Ein anderer Chat verwendet denselben Baum. Die Dateiwiederherstellung könnte die Änderungen dieses Chats überschreiben." @@ -1014,6 +1044,10 @@ msgstr "Alle archivieren" msgid "Archive all threads" msgstr "Alle Threads archivieren" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Archive finding" +msgstr "Ergebnis archivieren" + #: src/renderer/commands/registry.ts msgid "Archive the current thread" msgstr "Aktuellen Thread archivieren" @@ -1028,6 +1062,10 @@ msgstr "Thread archivieren" msgid "Archive Thread" msgstr "Thread archivieren" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Archived" +msgstr "Archiviert" + #: src/mobile/settingsSections.ts #: src/mobile/views/SettingsView.tsx #: src/renderer/views/SettingsOverlay/parts/ArchivedThreadsSettings.tsx @@ -1173,6 +1211,16 @@ msgstr "Terminal-Panel automatisch anzeigen" msgid "Automatically show the terminal panel when running commands or creating worktrees." msgstr "Zeigt das Terminal-Panel automatisch an, wenn Befehle ausgeführt oder Arbeitsbäume erstellt werden." +#: src/renderer/views/SchedulesView/SchedulesView.tsx +msgid "Automation sections" +msgstr "Automationsbereiche" + +#: src/mobile/settingsSections.ts +#: src/renderer/views/MainView/parts/Sidebar/Sidebar.tsx +#: src/renderer/views/SchedulesView/SchedulesView.tsx +msgid "Automations" +msgstr "Automationen" + #: src/renderer/components/skills/SkillImportModal.tsx msgid "Availability" msgstr "Verfügbarkeit" @@ -1459,6 +1507,10 @@ msgstr "Branch-Schutzregeln umgehen (Admin-Zusammenführung)" msgid "Cached only" msgstr "Nur im Cache" +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Calculated on desktop after saving" +msgstr "Wird nach dem Speichern auf dem Desktop berechnet" + #: src/mobile/QrScanner.tsx msgid "Camera access blocked" msgstr "Kamerazugriff blockiert" @@ -1513,11 +1565,16 @@ msgstr "Auswahl abbrechen" msgid "Cancel removing project" msgstr "Entfernen des Projekts abbrechen" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Cancel run" +msgstr "Ausführung abbrechen" + #: src/renderer/components/thread/ChatPane/parts/items/WorkflowOverlayBody.tsx msgid "cancelled" msgstr "abgebrochen" #: src/renderer/utils/prStatus.ts +#: src/renderer/views/SchedulesView/parts/PreviousRunsModal.tsx msgid "Cancelled" msgstr "Abgebrochen" @@ -1706,6 +1763,10 @@ msgstr "Wählen Sie die Anzeigesprache für die Benutzeroberfläche von Poracode msgid "Choose thread to attach to" msgstr "Thread zum Anhängen auswählen" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Choose what happens after a scheduled time was missed." +msgstr "Wählen Sie, was geschehen soll, wenn ein geplanter Zeitpunkt verpasst wurde." + #: src/renderer/views/SettingsOverlay/parts/BrowserSettings.tsx #: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts msgid "Choose whether links from Poracode and browser popups stay in Poracode or open externally." @@ -2185,6 +2246,14 @@ msgstr "abgeschlossen" msgid "Completed" msgstr "Abgeschlossen" +#: src/renderer/i18n/sharedMessages.ts +msgid "Completion evaluation failed: {detail}" +msgstr "Auswertung des Abschlusses fehlgeschlagen: {detail}" + +#: src/renderer/i18n/sharedMessages.ts +msgid "Completion evaluation is unavailable." +msgstr "Auswertung des Abschlusses ist nicht verfügbar." + #: src/renderer/commands/shortcutCatalog.ts #: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx #: src/renderer/views/SettingsOverlay/parts/settingsOptions.ts @@ -2223,6 +2292,14 @@ msgstr "Computer Use aktiviert — interaktive Aktionen übernehmen den Desktop; #~ msgid "Computer Use enabled for this thread" #~ msgstr "Computernutzung für diesen Thread aktiviert" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Confidence" +msgstr "Konfidenz" + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Confidence percent" +msgstr "Konfidenz in Prozent" + #: src/renderer/views/SettingsOverlay/parts/ClaudeProfileSettings.tsx msgid "Config directory" msgstr "Konfigurationsverzeichnis" @@ -2386,6 +2463,14 @@ msgstr "In einem anderen Anbieter fortfahren" msgid "Continue in..." msgstr "Weiter in..." +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Continue one conversation until a stop condition or limit is reached." +msgstr "Ein Gespräch fortsetzen, bis eine Stoppbedingung oder ein Limit erreicht ist." + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Control how each scheduled run continues and stops." +msgstr "Steuern Sie, wie jede geplante Ausführung fortgesetzt und beendet wird." + #: src/renderer/views/SettingsOverlay/parts/SearchSettings.tsx msgid "Control which files appear in the @file mention search. Per-project overrides live in each project's settings." msgstr "Steuern Sie, welche Dateien in der @file-Erwähnungssuche angezeigt werden. Projektspezifische Überschreibungen sind in den Einstellungen jedes Projekts verfügbar." @@ -2397,6 +2482,7 @@ msgstr "Steuert den gekoppelten Desktop, während der Agent klickt oder tippt" #: src/mobile/views/pr/PrConversationPage.tsx #: src/mobile/views/pr/PrOverviewPage.tsx #: src/renderer/views/PrReviewOverlay/parts/PrTabsPill.tsx +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx msgid "Conversation" msgstr "Gespräch" @@ -2697,6 +2783,24 @@ msgstr "Anmeldeinformationen sind konfiguriert." msgid "Credits" msgstr "Credits" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Critical" +msgstr "Kritisch" + +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Cron" +msgstr "Cron" + +#. placeholder {0}: task.recurrence.expression +#. placeholder {1}: task.recurrence.timeZone +#: src/renderer/views/SchedulesView/SchedulesView.tsx +msgid "Cron {0} in {1}" +msgstr "Cron {0} in {1}" + +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Cron expression" +msgstr "Cron-Ausdruck" + #: src/renderer/components/skills/SkillMarketplaceModal.tsx #~ msgid "Curated free and premium skills managed by MCP Market." #~ msgstr "Kuratierte kostenlose und Premium-Skills, verwaltet von MCP Market." @@ -2762,9 +2866,9 @@ msgstr "Tägliche Zusammenfassung" msgid "Dark" msgstr "Dunkel" -#: src/renderer/views/SchedulesView/SchedulesView.tsx -#~ msgid "Days" -#~ msgstr "Tage" +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Days" +msgstr "Tage" #: src/renderer/components/thread/ThreadRuntimeRequestPanel/structuredElicitation.tsx msgid "Decline" @@ -2911,6 +3015,10 @@ msgstr "Worktree {0} löschen" #~ msgid "Delete:" #~ msgstr "Löschen:" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Deleted schedule" +msgstr "Gelöschter Zeitplan" + #: src/renderer/views/SettingsOverlay/parts/AcpRegistrySettings.tsx msgid "Deleting" msgstr "Löschen" @@ -2923,6 +3031,10 @@ msgstr "Ablehnen" msgid "Deny and tell the agent what to do differently…" msgstr "Lehnen Sie ab und sagen Sie dem Agenten, was er anders machen soll ..." +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Describe the result that completes this heartbeat." +msgstr "Beschreiben Sie das Ergebnis, mit dem dieser Heartbeat abgeschlossen wird." + #: src/renderer/views/SchedulesView/ScheduleEditor.tsx msgid "Describe what the agent should do" msgstr "Beschreibe, was der Agent tun soll" @@ -2944,6 +3056,10 @@ msgstr "Desktop-Endpunkt" msgid "Desktop is unreachable." msgstr "Desktop ist nicht erreichbar." +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Desktop local time" +msgstr "Lokale Zeit des Desktops" + #: src/mobile/chrome.ts #: src/mobile/views/MoreView.tsx msgid "Desktop Settings" @@ -3056,6 +3172,10 @@ msgstr "Projekt deaktivieren" msgid "Disable Subagents" msgstr "Subagenten deaktivieren" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Disable the automation after retries are exhausted." +msgstr "Automatisierung deaktivieren, nachdem alle Wiederholungsversuche ausgeschöpft sind." + #: src/renderer/views/SettingsOverlay/parts/ClaudeProfileSettings.tsx msgid "Disable tiers an external provider collapses (e.g. keep only High and Max)." msgstr "Stufen deaktivieren, die ein externer Anbieter zusammenfasst (z. B. nur High und Max behalten)." @@ -3356,6 +3476,10 @@ msgstr "Aktivierte Server bleiben für neue Threads aktiv" msgid "Enables <0>cookies and <1>storage. Cookies can contain session tokens and storage often holds auth state — only enable when you trust both the agent and the sites it visits." msgstr "Aktiviert <0>Cookies und <1>Speicher. Cookies können Sitzungstoken enthalten und der Speicher enthält oft den Authentifizierungsstatus – aktivieren Sie sie nur, wenn Sie sowohl dem Agenten als auch den von ihm besuchten Websites vertrauen." +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +#~ msgid "End the heartbeat after retries are exhausted." +#~ msgstr "Heartbeat beenden, nachdem alle Wiederholungsversuche ausgeschöpft sind." + #: src/mobile/views/DesktopsView.tsx #: src/renderer/views/SettingsOverlay/parts/RemoteServersSettings.tsx msgid "Endpoint" @@ -3393,6 +3517,10 @@ msgstr "Gib einen gültigen Desktop-Endpunkt ein." msgid "Enter a valid HTTP or HTTPS URL." msgstr "Geben Sie eine gültige HTTP- oder HTTPS-URL ein." +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Enter a valid schedule" +msgstr "Gib einen gültigen Zeitplan ein" + #: src/mobile/views/DesktopsView.tsx msgid "Enter a valid SSH target and port." msgstr "Geben Sie ein gültiges SSH-Ziel und einen gültigen Port ein." @@ -3463,6 +3591,14 @@ msgstr "Fehler" msgid "Error · Agent encountered an error" msgstr "Fehler · Der Agent hat einen Fehler festgestellt" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Evaluate the result after every iteration." +msgstr "Das Ergebnis nach jeder Iteration auswerten." + +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Every" +msgstr "Alle" + #: src/renderer/views/SchedulesView/SchedulesView.tsx msgid "Every day at {time}" msgstr "Jeden Tag um {time}" @@ -3485,6 +3621,14 @@ msgstr "Jede Stunde {0} Minuten nach der vollen Stunde" msgid "Exclude patterns" msgstr "Muster ausschließen" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Execution" +msgstr "Ausführung" + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Execution mode" +msgstr "Ausführungsmodus" + #: src/renderer/components/thread/ChatPane/parts/items/toolDisplay.ts msgid "Exit plan mode" msgstr "Verlassen Sie den Planmodus" @@ -3534,6 +3678,10 @@ msgstr "Zum Prüfen oder Entziehen des Zugriffs erweitern." msgid "Expand todo dock" msgstr "Erweitern Sie das Aufgaben-Dock" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Exponential backoff" +msgstr "Exponentielle Verzögerung" + #: src/renderer/components/mcp/McpServersManager.tsx msgid "Export MCP servers" msgstr "MCP-Server exportieren" @@ -3716,6 +3864,10 @@ msgstr "Im Diff suchen" msgid "Find in terminal" msgstr "Im Terminal suchen" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Finding status" +msgstr "Ergebnisstatus" + #: src/renderer/views/PrReviewOverlay/parts/SubmitReviewPopover.tsx msgid "Finish your review" msgstr "Review abschließen" @@ -3777,6 +3929,10 @@ msgstr "Im Agenten beheben" msgid "Fixed" msgstr "Behoben" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Fixed delay" +msgstr "Feste Verzögerung" + #: src/renderer/commands/registry.ts msgid "Focus browser address bar" msgstr "Browseradressleiste fokussieren" @@ -4097,6 +4253,26 @@ msgstr "Hat einen ungesendeten Entwurf" msgid "Headers" msgstr "Header" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Heartbeat" +msgstr "Heartbeat" + +#: src/renderer/i18n/sharedMessages.ts +msgid "Heartbeat automations require a native chat conversation." +msgstr "Heartbeat-Automationen erfordern ein natives Chatgespräch." + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Heartbeat continues this conversation in the selected project." +msgstr "Der Heartbeat setzt dieses Gespräch im ausgewählten Projekt fort." + +#: src/renderer/i18n/sharedMessages.ts +msgid "Heartbeat execution is unavailable." +msgstr "Die Heartbeat-Ausführung ist nicht verfügbar." + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Heartbeats can continue making changes while you're away. Set hard limits below." +msgstr "Heartbeats können weiterhin Änderungen vornehmen, während Sie nicht da sind. Legen Sie unten feste Grenzen fest." + #: src/renderer/views/SchedulesView/SchedulesView.tsx msgid "Help me create a schedule. Ask for any missing details, then use the Poracode schedule controls to create it for me." msgstr "Hilf mir, einen Zeitplan zu erstellen. Frage nach fehlenden Details und erstelle ihn dann mit den Poracode-Zeitplansteuerungen für mich." @@ -4198,6 +4374,10 @@ msgstr "host.com, Alias oder benutzer@host.com" msgid "Hourly" msgstr "Stündlich" +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Hours" +msgstr "Stunden" + #: src/renderer/components/mcp/McpServerEditor.tsx msgid "HTTP (streamable)" msgstr "HTTP (streamfähig)" @@ -4328,6 +4508,14 @@ msgstr "Das Scannen mit der Kamera in der App funktioniert nur über HTTPS. Nutz msgid "Inactive" msgstr "Inaktiv" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Includes the first attempt." +msgstr "Schließt den ersten Versuch ein." + +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Info" +msgstr "Info" + #. Badge on an exclude pattern inherited from a lower scope #: src/renderer/views/SettingsOverlay/parts/SearchExcludeBody.tsx msgid "inherited" @@ -4338,6 +4526,14 @@ msgstr "geerbt" msgid "Inheriting the global setting (currently {0})." msgstr "Übernahme der globalen Einstellung (derzeit {0})." +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Initial retry delay" +msgstr "Anfängliche Wiederholungsverzögerung" + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Initial retry delay in seconds" +msgstr "Anfängliche Wiederholungsverzögerung in Sekunden" + #: src/renderer/views/GitReviewOverlay/parts/GitReviewSidebar/GitReviewSidebar.tsx msgid "Initialize Repository" msgstr "Repository initialisieren" @@ -4476,6 +4672,18 @@ msgstr "Unterbrochen" msgid "Interrupted: agent session ended before completion." msgstr "Unterbrochen: Agentensitzung wurde vorzeitig beendet." +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Interval" +msgstr "Intervall" + +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Interval amount" +msgstr "Intervallwert" + +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Interval unit" +msgstr "Intervalleinheit" + #: src/renderer/views/MainView/parts/RightPanel/parts/NotesPanel/NotesEditor.tsx msgid "Italic" msgstr "Kursiv" @@ -4560,6 +4768,14 @@ msgstr "Starten…" msgid "Leave a comment" msgstr "Kommentar hinterlassen" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Leave blank for no run limit." +msgstr "Leer lassen, um die Anzahl der Ausführungen nicht zu begrenzen." + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +#~ msgid "Leave blank to rely on the time limit." +#~ msgstr "Leer lassen, um das Zeitlimit zu verwenden." + #: src/renderer/views/ProfileOverlay/parts/ActivityHeatmap.tsx msgid "Less" msgstr "Weniger" @@ -4640,6 +4856,10 @@ msgstr "Editor wird geladen…" msgid "Loading file…" msgstr "Datei wird geladen…" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Loading findings" +msgstr "Ergebnisse werden geladen" + #: src/renderer/components/skills/SkillMarketplaceModal.tsx msgid "Loading marketplace…" msgstr "Marketplace wird geladen…" @@ -4864,6 +5084,14 @@ msgstr "Als erledigt markieren" msgid "Mark as not done" msgstr "Als nicht erledigt markieren" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Mark as read" +msgstr "Als gelesen markieren" + +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Mark as unread" +msgstr "Als ungelesen markieren" + #: src/renderer/components/thread/ThreadView.tsx msgid "Mark done" msgstr "Als erledigt markieren" @@ -4904,6 +5132,22 @@ msgstr "Maximieren" msgid "Maximize browser" msgstr "Browser maximieren" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Maximum attempts" +msgstr "Maximale Anzahl von Versuchen" + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Maximum iterations" +msgstr "Maximale Anzahl von Iterationen" + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Maximum retry delay" +msgstr "Maximale Wiederholungsverzögerung" + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Maximum retry delay in seconds" +msgstr "Maximale Wiederholungsverzögerung in Sekunden" + #: src/renderer/components/skills/SkillMarketplaceModal.tsx #~ msgid "MCP Market" #~ msgstr "MCP Market" @@ -5110,6 +5354,18 @@ msgstr "Auf Panel minimieren" msgid "Minute" msgstr "Minute" +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Minute, hour, day of month, month, and weekday." +msgstr "Minute, Stunde, Tag des Monats, Monat und Wochentag." + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "minutes" +msgstr "Minuten" + +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Minutes" +msgstr "Minuten" + #: src/mobile/views/BrowserView.tsx msgid "Mirrored desktop browser tab" msgstr "Gespiegelter Desktop-Browser-Tab" @@ -5118,6 +5374,10 @@ msgstr "Gespiegelter Desktop-Browser-Tab" msgid "Mirroring is unavailable." msgstr "Spiegelung ist nicht verfügbar." +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Missed runs" +msgstr "Verpasste Ausführungen" + #: src/renderer/views/SettingsOverlay/parts/RemoteAccessSettings.tsx msgid "Mobile push notifications" msgstr "Mobile Push-Benachrichtigungen" @@ -5469,6 +5729,10 @@ msgstr "Nächste Übereinstimmung" msgid "Next recently viewed chat" msgstr "Nächster zuletzt angesehener Chat" +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Next run" +msgstr "Nächste Ausführung" + #. placeholder {0}: dateTimeFormatter.format(new Date(task.nextRunAt)) #: src/renderer/views/SchedulesView/SchedulesView.tsx msgid "Next run {0}" @@ -5514,6 +5778,10 @@ msgstr "Keine Agenten installiert." msgid "No AI commits, PRs, or conflict resolutions tracked yet." msgstr "Noch keine KI-Commits, PRs oder Konfliktlösungen erfasst." +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "No archived findings." +msgstr "Keine archivierten Ergebnisse." + #: src/renderer/views/SettingsOverlay/parts/ArchivedThreadsSettings.tsx msgid "No archived threads." msgstr "Keine archivierten Threads." @@ -5610,6 +5878,10 @@ msgstr "Für {0} ist kein Unterschied verfügbar." msgid "No diff for {visiblePath}" msgstr "Kein Unterschied für {visiblePath}" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "No eligible conversations in this project." +msgstr "Keine geeigneten Gespräche in diesem Projekt." + #: src/renderer/components/skills/SkillImportModal.tsx msgid "No external skills were found in this scope." msgstr "In diesem Geltungsbereich wurden keine externen Skills gefunden." @@ -5625,6 +5897,10 @@ msgstr "Für diese Nachricht ist kein Dateiprüfpunkt hinterlegt." msgid "No files match \"{0}\"." msgstr "Keine Dateien stimmen mit „{0}“ überein." +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "No findings yet." +msgstr "Noch keine Ergebnisse." + #: src/renderer/views/MainView/parts/CreateProject/CloneProjectModal.tsx msgid "No GitHub CLI accounts found. Sign in with <0>gh auth login, or <1>paste a clone URL." msgstr "Keine GitHub-CLI-Konten gefunden. Melden Sie sich mit <0>gh auth login an oder <1>fügen Sie eine Klon-URL ein." @@ -5637,6 +5913,10 @@ msgstr "Noch kein Verlauf" msgid "No Lightcode data was found." msgstr "Keine Lightcode-Daten gefunden." +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "No limit" +msgstr "Kein Limit" + #: src/renderer/components/skills/SkillMarketplaceModal.tsx msgid "No marketplace skills match these filters." msgstr "Keine Marketplace-Skills entsprechen diesen Filtern." @@ -5653,6 +5933,10 @@ msgstr "Keine Übereinstimmungen." msgid "No matching agents." msgstr "Keine passenden Agenten." +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "No matching findings." +msgstr "Keine passenden Ergebnisse." + #: src/renderer/views/PullRequestsView/PullRequestsView.tsx msgid "No matching pull requests." msgstr "Keine passenden Pull Requests." @@ -5762,6 +6046,10 @@ msgstr "Keine Repositorys gefunden." msgid "No results" msgstr "Keine Ergebnisse" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "No retries" +msgstr "Keine Wiederholungsversuche" + #: src/renderer/views/SchedulesView/parts/PreviousRunsModal.tsx msgid "No runs yet." msgstr "Noch keine Ausführungen." @@ -5798,6 +6086,10 @@ msgstr "Keine Sprache erkannt." msgid "No staged changes" msgstr "Keine bereitgestellten Änderungen" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "No summary was provided." +msgstr "Keine Zusammenfassung vorhanden." + #: src/renderer/views/RemoteProjectModal/RemoteProjectModal.tsx msgid "No supported agents are installed on this remote machine. Install and sign in to an agent remotely before starting a thread." msgstr "Auf diesem Remotecomputer sind keine unterstützten Agenten installiert. Installieren Sie einen Agenten remote und melden Sie sich dort an, bevor Sie einen Thread starten." @@ -5827,6 +6119,10 @@ msgstr "Noch keine Threads" msgid "No threads yet." msgstr "Noch keine Threads." +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "No upcoming run" +msgstr "Keine anstehende Ausführung" + #: src/renderer/components/providers/usageFormat.ts msgid "No windows reported" msgstr "Keine Fenster gemeldet" @@ -6042,6 +6338,11 @@ msgstr "Öffnen Sie das Commit auf GitHub" msgid "Open conflict resolver in" msgstr "Öffnen Sie den Konfliktlöser in" +#. placeholder {0}: props.scheduleName +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Open conversation for {0}" +msgstr "Gespräch für {0} öffnen" + #: src/renderer/views/SettingsOverlay/parts/settingsOptions.ts msgid "Open dialog" msgstr "Dialog öffnen" @@ -6677,6 +6978,10 @@ msgstr "Projektordner aktualisiert. Öffnen Sie alle Terminals in diesem Projekt msgid "Project name" msgstr "Projektname" +#: src/renderer/i18n/sharedMessages.ts +msgid "Project no longer exists." +msgstr "Das Projekt existiert nicht mehr." + #: src/renderer/views/MainView/parts/RightPanel/parts/NotesPanel/NotesEditor.tsx msgid "Project notes" msgstr "Projektnotizen" @@ -7275,6 +7580,10 @@ msgstr "Details anfordern" msgid "requested changes" msgstr "angeforderte Änderungen" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Required confidence before stopping." +msgstr "Erforderliche Konfidenz vor dem Beenden." + #: src/mobile/views/pr/PrOverviewPage.tsx #: src/renderer/views/GitReviewOverlay/parts/GitReviewSidebar/parts/PrSection.tsx msgid "Required reviews, conversations, or status checks not met." @@ -7346,6 +7655,10 @@ msgstr "Browser wiederherstellen" msgid "Restore default worktree base folder" msgstr "Standard-Worktree-Basisordner wiederherstellen" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Restore finding" +msgstr "Ergebnis wiederherstellen" + #: src/mobile/settingsSections.ts msgid "Restore or delete" msgstr "Wiederherstellen oder löschen" @@ -7376,10 +7689,26 @@ msgstr "Prüfung von {serverName} wiederholen" msgid "Retry check" msgstr "Prüfung wiederholen" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Retry delay" +msgstr "Wiederholungsverzögerung" + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Retry delay in seconds" +msgstr "Wiederholungsverzögerung in Sekunden" + #: src/mobile/components.tsx msgid "Retry now" msgstr "Jetzt erneut versuchen" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Retry policy" +msgstr "Wiederholungsrichtlinie" + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Retry when a run fails before it completes." +msgstr "Erneut versuchen, wenn eine Ausführung vor dem Abschluss fehlschlägt." + #: src/renderer/hooks/usePrWriteActions.ts msgid "Retry with admin" msgstr "Versuchen Sie es noch einmal mit dem Administrator" @@ -7535,18 +7864,26 @@ msgstr "Lokale Transkription auf der GPU ausführen, sofern verfügbar." msgid "Run now" msgstr "Jetzt ausführen" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Run once after reopening" +msgstr "Nach erneutem Öffnen einmal ausführen" + #: src/renderer/views/SchedulesView/SchedulesView.tsx #~ msgid "Run standalone tasks on this device without a project." #~ msgstr "Eigenständige Aufgaben auf diesem Gerät ohne Projekt ausführen." #: src/renderer/views/SchedulesView/SchedulesView.tsx -msgid "Run standalone tasks on this device. Schedules run while the device is awake and Poracode is open." -msgstr "Führe eigenständige Aufgaben auf diesem Gerät aus. Zeitpläne laufen, solange das Gerät aktiv und Poracode geöffnet ist." +#~ msgid "Run standalone tasks on this device. Schedules run while the device is awake and Poracode is open." +#~ msgstr "Führe eigenständige Aufgaben auf diesem Gerät aus. Zeitpläne laufen, solange das Gerät aktiv und Poracode geöffnet ist." #: src/renderer/commands/registry.ts msgid "Run Terminal Command" msgstr "Terminalbefehl ausführen" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Run the latest missed run" +msgstr "Die zuletzt verpasste Ausführung starten" + #: src/renderer/views/SchedulesView/ScheduleEditor.tsx #~ msgid "Run this schedule automatically at the times above." #~ msgstr "Diesen Zeitplan automatisch zu den oben genannten Zeiten ausführen." @@ -7562,6 +7899,7 @@ msgstr "läuft" #: src/renderer/utils/prStatus.ts #: src/renderer/views/SchedulesView/parts/PreviousRunsModal.tsx +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx msgid "Running" msgstr "Wird ausgeführt" @@ -7585,6 +7923,10 @@ msgstr "Läuft früh aus" msgid "Runs out in {runOut}" msgstr "Läuft in {runOut} aus" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Runs that need attention will appear here." +msgstr "Ausführungen, die Ihre Aufmerksamkeit erfordern, werden hier angezeigt." + #: src/renderer/views/MainView/parts/CreateProject/CloneProjectModal.tsx #: src/renderer/views/MainView/parts/CreateProject/CreateProjectModal.tsx msgid "Runtime" @@ -7661,6 +8003,10 @@ msgstr "Durchsuchen von Windows und WSL nach installierten CLIs. Dies dauert nor msgid "Scanning your system for installed CLIs. This usually takes a couple of seconds." msgstr "System wird nach installierten CLIs durchsucht. Dies dauert normalerweise ein paar Sekunden." +#: src/renderer/views/SchedulesView/SchedulesView.tsx +msgid "Schedule autonomous work and review results that need your attention. Automations run while this device is awake and Poracode is open." +msgstr "Planen Sie autonome Arbeit und prüfen Sie Ergebnisse, die Ihre Aufmerksamkeit erfordern. Automationen werden ausgeführt, solange dieses Gerät aktiv und Poracode geöffnet ist." + #: src/renderer/views/SchedulesView/ScheduleEditor.tsx msgid "Schedule name" msgstr "Name des Zeitplans" @@ -7669,20 +8015,31 @@ msgstr "Name des Zeitplans" msgid "Schedule status" msgstr "Zeitplanstatus" +#: src/renderer/i18n/sharedMessages.ts +msgid "Scheduled retry was cancelled." +msgstr "Der geplante Wiederholungsversuch wurde abgebrochen." + +#: src/renderer/i18n/sharedMessages.ts +msgid "Scheduled task was deleted before retrying." +msgstr "Die geplante Aufgabe wurde vor dem Wiederholungsversuch gelöscht." + #: src/renderer/views/SchedulesView/SchedulesView.tsx -msgid "Scheduled tasks" -msgstr "Geplante Aufgaben" +#~ msgid "Scheduled tasks" +#~ msgstr "Geplante Aufgaben" #: src/mobile/settingsSections.ts -msgid "Scheduled tasks on this desktop" -msgstr "Geplante Aufgaben auf diesem Desktop" +#~ msgid "Scheduled tasks on this desktop" +#~ msgstr "Geplante Aufgaben auf diesem Desktop" #: src/renderer/views/SchedulesView/SchedulesView.tsx #~ msgid "Scheduled tasks run only while this device is awake and Poracode is open." #~ msgstr "Geplante Aufgaben werden nur ausgeführt, solange dieses Gerät aktiv und Poracode geöffnet ist." #: src/mobile/settingsSections.ts -#: src/renderer/views/MainView/parts/Sidebar/Sidebar.tsx +msgid "Scheduled work and triage on this desktop" +msgstr "Geplante Arbeit und Triage auf diesem Desktop" + +#: src/renderer/views/SchedulesView/SchedulesView.tsx msgid "Schedules" msgstr "Zeitpläne" @@ -7737,6 +8094,10 @@ msgstr "Branches durchsuchen..." msgid "Search files" msgstr "Dateien durchsuchen" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Search findings" +msgstr "Ergebnisse durchsuchen" + #: src/renderer/components/skills/SkillMarketplaceModal.tsx msgid "Search marketplace skills" msgstr "Marketplace-Skills durchsuchen" @@ -7831,6 +8192,10 @@ msgstr "Suche..." msgid "Searching…" msgstr "Suche..." +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "seconds" +msgstr "Sekunden" + #: src/renderer/components/skills/SkillMarketplaceModal.tsx #~ msgid "Security-focused directory with verified skill metadata." #~ msgstr "Sicherheitsorientiertes Verzeichnis mit verifizierten Skill-Metadaten." @@ -8221,6 +8586,10 @@ msgstr "{env} wird abgemeldet. Erkannte Agenten werden aktualisiert, wenn der Vo msgid "Signing out. Detected agents will refresh when it finishes." msgstr "Wird abgemeldet. Erkannte Agenten werden aktualisiert, wenn der Vorgang abgeschlossen ist." +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Single pass" +msgstr "Einzeldurchlauf" + #: src/renderer/components/skills/SkillImportModal.tsx #: src/renderer/components/skills/SkillMarketplaceModal.tsx msgid "Skill availability" @@ -8285,7 +8654,12 @@ msgstr "Skill-Marketplace" msgid "Skills.sh" msgstr "Skills.sh" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Skip missed runs" +msgstr "Verpasste Ausführungen überspringen" + #: src/renderer/utils/prStatus.ts +#: src/renderer/views/SchedulesView/parts/PreviousRunsModal.tsx msgid "Skipped" msgstr "Übersprungen" @@ -8424,6 +8798,10 @@ msgstr "{appName} starten, um die Nutzung zu sehen" msgid "Start a dev server on your desktop, then tap refresh." msgstr "Starten Sie einen Dev-Server auf Ihrem Desktop und tippen Sie dann auf Aktualisieren." +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Start a new conversation for each run." +msgstr "Für jede Ausführung ein neues Gespräch beginnen." + #: src/renderer/commands/registry.ts msgid "Start a new thread as panel instead of page" msgstr "Neuen Thread als Panel statt als Seite öffnen" @@ -8562,6 +8940,10 @@ msgstr "Stopp" msgid "Stop forwarding" msgstr "Weiterleitung stoppen" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Stop on error" +msgstr "Bei Fehler beenden" + #: src/renderer/components/thread/ThreadComposer.tsx msgid "Stop response" msgstr "Antwort stoppen" @@ -8574,10 +8956,18 @@ msgstr "Aufgabe stoppen" msgid "Stop the project's running threads before changing its folder." msgstr "Stoppen Sie die laufenden Threads des Projekts, bevor Sie dessen Ordner ändern." +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Stop the run when this total time is reached." +msgstr "Die Ausführung beenden, wenn diese Gesamtzeit erreicht ist." + #: src/renderer/components/composer/VoiceInputButton.tsx msgid "Stop voice input" msgstr "Spracheingabe stoppen" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Stop when" +msgstr "Beenden, wenn" + #: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts #: src/renderer/views/SettingsOverlay/parts/WorktreeSettings.tsx msgid "Storage location" @@ -8922,6 +9312,22 @@ msgstr "Der Agent" msgid "the app" msgstr "die App" +#: src/renderer/i18n/sharedMessages.ts +msgid "The automation conversation exited before the turn completed." +msgstr "Das Automationsgespräch wurde beendet, bevor der Durchlauf abgeschlossen war." + +#: src/renderer/i18n/sharedMessages.ts +msgid "The automation exceeded its time limit." +msgstr "Die Automation hat ihr Zeitlimit überschritten." + +#: src/renderer/i18n/sharedMessages.ts +msgid "The automation needs a reply before it can continue." +msgstr "Die Automation benötigt eine Antwort, bevor sie fortgesetzt werden kann." + +#: src/renderer/i18n/sharedMessages.ts +msgid "The automation needs approval before it can continue." +msgstr "Die Automation benötigt eine Genehmigung, bevor sie fortgesetzt werden kann." + #: src/renderer/views/MainView/parts/CreateProject/CloneProjectModal.tsx msgid "the chosen folder" msgstr "den gewählten Ordner" @@ -8935,11 +9341,39 @@ msgstr "Der Standard-Aktualisierungstakt im Hintergrund, der für jeden Anbieter msgid "The desktop server is still coming online." msgstr "Der Desktop-Server wird noch gestartet." +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "The finding is no longer available." +msgstr "Das Ergebnis ist nicht mehr verfügbar." + #. placeholder {0}: createTarget.wslDistro #: src/renderer/components/skills/SkillsManager.tsx msgid "the global {0} WSL scope" msgstr "den globalen WSL-Bereich {0}" +#: src/renderer/i18n/sharedMessages.ts +msgid "The heartbeat conversation belongs to a different project." +msgstr "Das Heartbeat-Gespräch gehört zu einem anderen Projekt." + +#: src/renderer/i18n/sharedMessages.ts +msgid "The heartbeat conversation cannot be resumed." +msgstr "Das Heartbeat-Gespräch kann nicht fortgesetzt werden." + +#: src/renderer/i18n/sharedMessages.ts +msgid "The heartbeat conversation is archived." +msgstr "Die Heartbeat-Unterhaltung ist archiviert." + +#: src/renderer/i18n/sharedMessages.ts +msgid "The heartbeat conversation is currently busy." +msgstr "Das Heartbeat-Gespräch ist derzeit beschäftigt." + +#: src/renderer/i18n/sharedMessages.ts +msgid "The heartbeat conversation no longer exists." +msgstr "Das Heartbeat-Gespräch existiert nicht mehr." + +#: src/renderer/i18n/sharedMessages.ts +msgid "The heartbeat conversation uses a different agent." +msgstr "Das Heartbeat-Gespräch verwendet einen anderen Agenten." + #: src/renderer/components/skills/SkillsManager.tsx msgid "the Linux user" msgstr "den Linux-Benutzer" @@ -8972,6 +9406,14 @@ msgstr "Der Remote-Server hat keine Kopplungszugangsdaten zurückgegeben." msgid "The repository location on disk. Update it if you moved the folder." msgstr "Der Speicherort des Repositorys auf der Festplatte. Aktualisieren Sie ihn, wenn Sie den Ordner verschoben haben." +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "The run could not be cancelled." +msgstr "Die Ausführung konnte nicht abgebrochen werden." + +#: src/renderer/i18n/sharedMessages.ts +msgid "The scheduled automation failed." +msgstr "Die geplante Automation ist fehlgeschlagen." + #: src/renderer/components/mcp/McpServersManager.tsx #~ msgid "The selected file does not contain valid MCP server configurations." #~ msgstr "Die ausgewählte Datei enthält keine gültigen MCP-Server-Konfigurationen." @@ -9227,6 +9669,18 @@ msgstr "Als erledigt markierte Threads, die so viele Tage lang nicht bearbeitet msgid "Time" msgstr "Uhrzeit" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Time limit" +msgstr "Zeitlimit" + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Time limit in minutes" +msgstr "Zeitlimit in Minuten" + +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Time zone" +msgstr "Zeitzone" + #: src/renderer/components/mcp/McpServerEditor.tsx msgid "Timeout (ms)" msgstr "Zeitüberschreitung (ms)" @@ -9356,6 +9810,10 @@ msgstr "Durchscheinende Seitenleiste" msgid "Trending now" msgstr "Aktuell im Trend" +#: src/renderer/views/SchedulesView/SchedulesView.tsx +msgid "Triage" +msgstr "Triage" + #: src/mobile/views/DesktopsView.tsx msgid "Trust and connect" msgstr "Vertrauen und verbinden" @@ -9598,6 +10056,10 @@ msgstr "Nicht zugewiesen" msgid "Unavailable" msgstr "Nicht verfügbar" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Unavailable conversation" +msgstr "Nicht verfügbares Gespräch" + #: src/renderer/views/SchedulesView/ScheduleEditor.tsx msgid "Unavailable project" msgstr "Nicht verfügbares Projekt" @@ -9676,6 +10138,10 @@ msgstr "Ohne Phase:" msgid "Unpin" msgstr "Lösen" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Unread" +msgstr "Ungelesen" + #: src/mobile/views/GitActionSheet.tsx #: src/renderer/views/GitReviewOverlay/parts/GitReviewSidebar/parts/FileRow.tsx #: src/renderer/views/GitReviewOverlay/parts/GitStackedDiff.tsx @@ -10002,6 +10468,12 @@ msgstr "Warten auf {methodName}-Authentifizierung. Erkannte Agenten werden aktua msgid "waiting for agent to stop" msgstr "Warten darauf, dass der Agent stoppt" +#: src/renderer/views/SchedulesView/parts/PreviousRunsModal.tsx +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +#: src/renderer/views/SchedulesView/SchedulesView.tsx +msgid "Waiting for approval" +msgstr "Warten auf Genehmigung" + #: src/renderer/components/thread/ChatPane/parts/items/WorkflowOverlayBody.tsx msgid "Waiting for workflow to spawn agents…" msgstr "Warten, bis der Workflow Agenten erzeugt …" @@ -10034,6 +10506,10 @@ msgstr "Aufwärmen von Shell-Umgebungen..." msgid "Warming up WSL shell environment…" msgstr "Aufwärmen der WSL-Shell-Umgebung…" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Warning" +msgstr "Warnung" + #: src/renderer/components/thread/ChatPane/parts/items/ToolCallGroup.tsx #: src/renderer/components/thread/ChatPane/parts/items/toolDisplay.ts #: src/renderer/components/thread/ChatPane/parts/items/WebSearchItem.tsx @@ -10326,6 +10802,10 @@ msgstr "WSL-Basisordner" #~ msgid "WSL user" #~ msgstr "WSL-Benutzer" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "You’re all caught up." +msgstr "Alles erledigt." + #: src/renderer/views/ProfileOverlay/parts/EditProfileDialog.tsx msgid "Your name" msgstr "Ihr Name" diff --git a/src/renderer/locales/en/messages.po b/src/renderer/locales/en/messages.po index f6bd67292..b31293d36 100644 --- a/src/renderer/locales/en/messages.po +++ b/src/renderer/locales/en/messages.po @@ -288,6 +288,11 @@ msgstr "{agentLabel}: {statusLabel}. Hover for status details." msgid "{agentLead} needs your input to continue." msgstr "{agentLead} needs your input to continue." +#. placeholder {0}: task.recurrence.timeZone +#: src/renderer/views/SchedulesView/SchedulesView.tsx +msgid "{cadence} in {0}" +msgstr "{cadence} in {0}" + #: src/mobile/views/pr/PrOverviewPage.tsx msgid "{commitsCount, plural, one {# commit} other {# commits}}" msgstr "{commitsCount, plural, one {# commit} other {# commits}}" @@ -315,6 +320,18 @@ msgstr "{days}d ago" msgid "{envOrAgentLabel} needs authentication." msgstr "{envOrAgentLabel} needs authentication." +#: src/renderer/views/SchedulesView/SchedulesView.tsx +msgid "{every, plural, one {Every day} other {Every # days}}" +msgstr "{every, plural, one {Every day} other {Every # days}}" + +#: src/renderer/views/SchedulesView/SchedulesView.tsx +msgid "{every, plural, one {Every hour} other {Every # hours}}" +msgstr "{every, plural, one {Every hour} other {Every # hours}}" + +#: src/renderer/views/SchedulesView/SchedulesView.tsx +msgid "{every, plural, one {Every minute} other {Every # minutes}}" +msgstr "{every, plural, one {Every minute} other {Every # minutes}}" + #: src/mobile/views/pr/PrOverviewPage.tsx msgid "{filesCount, plural, one {# file changed} other {# files changed}}" msgstr "{filesCount, plural, one {# file changed} other {# files changed}}" @@ -491,6 +508,10 @@ msgstr "~{money}{tokens} · {0} · est." msgid "≈{0}% by reset" msgstr "≈{0}% by reset" +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "0 9 * * 1-5" +msgstr "0 9 * * 1-5" + #: src/mobile/views/ThreadsView.tsx msgid "1 thread" msgstr "1 thread" @@ -840,6 +861,10 @@ msgstr "AI git actions" msgid "AI providers" msgstr "AI providers" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "AI stop condition" +msgstr "AI stop condition" + #: src/mobile/views/MoreView.tsx #~ msgid "AI, agents, and archived threads on the paired desktop" #~ msgstr "AI, agents, and archived threads on the paired desktop" @@ -851,6 +876,7 @@ msgstr "Alerts when threads need you" #: src/renderer/commands/shortcutCatalog.ts #: src/renderer/components/skills/SkillsManager.tsx #: src/renderer/views/PullRequestsView/PullRequestsView.tsx +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx #: src/renderer/views/SchedulesView/SchedulesView.tsx #: src/renderer/views/SettingsOverlay/parts/ProfileSettings.tsx msgid "All" @@ -943,6 +969,10 @@ msgstr "Always excluded" msgid "An MCP server with this name already exists." msgstr "An MCP server with this name already exists." +#: src/renderer/i18n/sharedMessages.ts +msgid "Another automation is already using this conversation." +msgstr "Another automation is already using this conversation." + #: src/renderer/components/thread/ChatPane/parts/CheckpointRevertControls.tsx msgid "Another chat uses this same tree. File restore could overwrite that chat's changes." msgstr "Another chat uses this same tree. File restore could overwrite that chat's changes." @@ -1014,6 +1044,10 @@ msgstr "Archive All" msgid "Archive all threads" msgstr "Archive all threads" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Archive finding" +msgstr "Archive finding" + #: src/renderer/commands/registry.ts msgid "Archive the current thread" msgstr "Archive the current thread" @@ -1028,6 +1062,10 @@ msgstr "Archive thread" msgid "Archive Thread" msgstr "Archive Thread" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Archived" +msgstr "Archived" + #: src/mobile/settingsSections.ts #: src/mobile/views/SettingsView.tsx #: src/renderer/views/SettingsOverlay/parts/ArchivedThreadsSettings.tsx @@ -1173,6 +1211,16 @@ msgstr "Auto-show terminal panel" msgid "Automatically show the terminal panel when running commands or creating worktrees." msgstr "Automatically show the terminal panel when running commands or creating worktrees." +#: src/renderer/views/SchedulesView/SchedulesView.tsx +msgid "Automation sections" +msgstr "Automation sections" + +#: src/mobile/settingsSections.ts +#: src/renderer/views/MainView/parts/Sidebar/Sidebar.tsx +#: src/renderer/views/SchedulesView/SchedulesView.tsx +msgid "Automations" +msgstr "Automations" + #: src/renderer/components/skills/SkillImportModal.tsx msgid "Availability" msgstr "Availability" @@ -1459,6 +1507,10 @@ msgstr "Bypass branch protection rules (admin merge)" msgid "Cached only" msgstr "Cached only" +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Calculated on desktop after saving" +msgstr "Calculated on desktop after saving" + #: src/mobile/QrScanner.tsx msgid "Camera access blocked" msgstr "Camera access blocked" @@ -1513,11 +1565,16 @@ msgstr "Cancel picker" msgid "Cancel removing project" msgstr "Cancel removing project" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Cancel run" +msgstr "Cancel run" + #: src/renderer/components/thread/ChatPane/parts/items/WorkflowOverlayBody.tsx msgid "cancelled" msgstr "cancelled" #: src/renderer/utils/prStatus.ts +#: src/renderer/views/SchedulesView/parts/PreviousRunsModal.tsx msgid "Cancelled" msgstr "Cancelled" @@ -1706,6 +1763,10 @@ msgstr "Choose the display language for Poracode's interface." msgid "Choose thread to attach to" msgstr "Choose thread to attach to" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Choose what happens after a scheduled time was missed." +msgstr "Choose what happens after a scheduled time was missed." + #: src/renderer/views/SettingsOverlay/parts/BrowserSettings.tsx #: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts msgid "Choose whether links from Poracode and browser popups stay in Poracode or open externally." @@ -2185,6 +2246,14 @@ msgstr "completed" msgid "Completed" msgstr "Completed" +#: src/renderer/i18n/sharedMessages.ts +msgid "Completion evaluation failed: {detail}" +msgstr "Completion evaluation failed: {detail}" + +#: src/renderer/i18n/sharedMessages.ts +msgid "Completion evaluation is unavailable." +msgstr "Completion evaluation is unavailable." + #: src/renderer/commands/shortcutCatalog.ts #: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx #: src/renderer/views/SettingsOverlay/parts/settingsOptions.ts @@ -2223,6 +2292,14 @@ msgstr "Computer Use enabled — interactive actions take over the desktop; don' #~ msgid "Computer Use enabled for this thread" #~ msgstr "Computer Use enabled for this thread" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Confidence" +msgstr "Confidence" + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Confidence percent" +msgstr "Confidence percent" + #: src/renderer/views/SettingsOverlay/parts/ClaudeProfileSettings.tsx msgid "Config directory" msgstr "Config directory" @@ -2386,6 +2463,14 @@ msgstr "Continue in another provider" msgid "Continue in..." msgstr "Continue in..." +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Continue one conversation until a stop condition or limit is reached." +msgstr "Continue one conversation until a stop condition or limit is reached." + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Control how each scheduled run continues and stops." +msgstr "Control how each scheduled run continues and stops." + #: src/renderer/views/SettingsOverlay/parts/SearchSettings.tsx msgid "Control which files appear in the @file mention search. Per-project overrides live in each project's settings." msgstr "Control which files appear in the @file mention search. Per-project overrides live in each project's settings." @@ -2397,6 +2482,7 @@ msgstr "Controls the paired desktop while the agent clicks or types" #: src/mobile/views/pr/PrConversationPage.tsx #: src/mobile/views/pr/PrOverviewPage.tsx #: src/renderer/views/PrReviewOverlay/parts/PrTabsPill.tsx +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx msgid "Conversation" msgstr "Conversation" @@ -2697,6 +2783,24 @@ msgstr "Credentials are configured." msgid "Credits" msgstr "Credits" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Critical" +msgstr "Critical" + +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Cron" +msgstr "Cron" + +#. placeholder {0}: task.recurrence.expression +#. placeholder {1}: task.recurrence.timeZone +#: src/renderer/views/SchedulesView/SchedulesView.tsx +msgid "Cron {0} in {1}" +msgstr "Cron {0} in {1}" + +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Cron expression" +msgstr "Cron expression" + #: src/renderer/components/skills/SkillMarketplaceModal.tsx #~ msgid "Curated free and premium skills managed by MCP Market." #~ msgstr "Curated free and premium skills managed by MCP Market." @@ -2762,9 +2866,9 @@ msgstr "Daily brief" msgid "Dark" msgstr "Dark" -#: src/renderer/views/SchedulesView/SchedulesView.tsx -#~ msgid "Days" -#~ msgstr "Days" +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Days" +msgstr "Days" #: src/renderer/components/thread/ThreadRuntimeRequestPanel/structuredElicitation.tsx msgid "Decline" @@ -2911,6 +3015,10 @@ msgstr "Delete worktree {0}" #~ msgid "Delete:" #~ msgstr "Delete:" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Deleted schedule" +msgstr "Deleted schedule" + #: src/renderer/views/SettingsOverlay/parts/AcpRegistrySettings.tsx msgid "Deleting" msgstr "Deleting" @@ -2923,6 +3031,10 @@ msgstr "Deny" msgid "Deny and tell the agent what to do differently…" msgstr "Deny and tell the agent what to do differently…" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Describe the result that completes this heartbeat." +msgstr "Describe the result that completes this heartbeat." + #: src/renderer/views/SchedulesView/ScheduleEditor.tsx msgid "Describe what the agent should do" msgstr "Describe what the agent should do" @@ -2944,6 +3056,10 @@ msgstr "Desktop endpoint" msgid "Desktop is unreachable." msgstr "Desktop is unreachable." +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Desktop local time" +msgstr "Desktop local time" + #: src/mobile/chrome.ts #: src/mobile/views/MoreView.tsx msgid "Desktop Settings" @@ -3056,6 +3172,10 @@ msgstr "Disable Project" msgid "Disable Subagents" msgstr "Disable Subagents" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Disable the automation after retries are exhausted." +msgstr "Disable the automation after retries are exhausted." + #: src/renderer/views/SettingsOverlay/parts/ClaudeProfileSettings.tsx msgid "Disable tiers an external provider collapses (e.g. keep only High and Max)." msgstr "Disable tiers an external provider collapses (e.g. keep only High and Max)." @@ -3356,6 +3476,10 @@ msgstr "Enabled servers stay on for new threads" msgid "Enables <0>cookies and <1>storage. Cookies can contain session tokens and storage often holds auth state — only enable when you trust both the agent and the sites it visits." msgstr "Enables <0>cookies and <1>storage. Cookies can contain session tokens and storage often holds auth state — only enable when you trust both the agent and the sites it visits." +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +#~ msgid "End the heartbeat after retries are exhausted." +#~ msgstr "End the heartbeat after retries are exhausted." + #: src/mobile/views/DesktopsView.tsx #: src/renderer/views/SettingsOverlay/parts/RemoteServersSettings.tsx msgid "Endpoint" @@ -3393,6 +3517,10 @@ msgstr "Enter a valid desktop endpoint." msgid "Enter a valid HTTP or HTTPS URL." msgstr "Enter a valid HTTP or HTTPS URL." +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Enter a valid schedule" +msgstr "Enter a valid schedule" + #: src/mobile/views/DesktopsView.tsx msgid "Enter a valid SSH target and port." msgstr "Enter a valid SSH target and port." @@ -3463,6 +3591,14 @@ msgstr "Error" msgid "Error · Agent encountered an error" msgstr "Error · Agent encountered an error" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Evaluate the result after every iteration." +msgstr "Evaluate the result after every iteration." + +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Every" +msgstr "Every" + #: src/renderer/views/SchedulesView/SchedulesView.tsx msgid "Every day at {time}" msgstr "Every day at {time}" @@ -3485,6 +3621,14 @@ msgstr "Every hour at {0} minutes past" msgid "Exclude patterns" msgstr "Exclude patterns" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Execution" +msgstr "Execution" + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Execution mode" +msgstr "Execution mode" + #: src/renderer/components/thread/ChatPane/parts/items/toolDisplay.ts msgid "Exit plan mode" msgstr "Exit plan mode" @@ -3534,6 +3678,10 @@ msgstr "Expand to review or revoke access." msgid "Expand todo dock" msgstr "Expand todo dock" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Exponential backoff" +msgstr "Exponential backoff" + #: src/renderer/components/mcp/McpServersManager.tsx msgid "Export MCP servers" msgstr "Export MCP servers" @@ -3716,6 +3864,10 @@ msgstr "Find in diff" msgid "Find in terminal" msgstr "Find in terminal" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Finding status" +msgstr "Finding status" + #: src/renderer/views/PrReviewOverlay/parts/SubmitReviewPopover.tsx msgid "Finish your review" msgstr "Finish your review" @@ -3777,6 +3929,10 @@ msgstr "Fix in Agent" msgid "Fixed" msgstr "Fixed" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Fixed delay" +msgstr "Fixed delay" + #: src/renderer/commands/registry.ts msgid "Focus browser address bar" msgstr "Focus browser address bar" @@ -4097,6 +4253,26 @@ msgstr "Has unsent draft" msgid "Headers" msgstr "Headers" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Heartbeat" +msgstr "Heartbeat" + +#: src/renderer/i18n/sharedMessages.ts +msgid "Heartbeat automations require a native chat conversation." +msgstr "Heartbeat automations require a native chat conversation." + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Heartbeat continues this conversation in the selected project." +msgstr "Heartbeat continues this conversation in the selected project." + +#: src/renderer/i18n/sharedMessages.ts +msgid "Heartbeat execution is unavailable." +msgstr "Heartbeat execution is unavailable." + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Heartbeats can continue making changes while you're away. Set hard limits below." +msgstr "Heartbeats can continue making changes while you're away. Set hard limits below." + #: src/renderer/views/SchedulesView/SchedulesView.tsx msgid "Help me create a schedule. Ask for any missing details, then use the Poracode schedule controls to create it for me." msgstr "Help me create a schedule. Ask for any missing details, then use the Poracode schedule controls to create it for me." @@ -4198,6 +4374,10 @@ msgstr "host.com, alias, or user@host.com" msgid "Hourly" msgstr "Hourly" +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Hours" +msgstr "Hours" + #: src/renderer/components/mcp/McpServerEditor.tsx msgid "HTTP (streamable)" msgstr "HTTP (streamable)" @@ -4328,6 +4508,14 @@ msgstr "In-app camera scanning only works over HTTPS. Use your phone's camera ap msgid "Inactive" msgstr "Inactive" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Includes the first attempt." +msgstr "Includes the first attempt." + +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Info" +msgstr "Info" + #. Badge on an exclude pattern inherited from a lower scope #: src/renderer/views/SettingsOverlay/parts/SearchExcludeBody.tsx msgid "inherited" @@ -4338,6 +4526,14 @@ msgstr "inherited" msgid "Inheriting the global setting (currently {0})." msgstr "Inheriting the global setting (currently {0})." +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Initial retry delay" +msgstr "Initial retry delay" + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Initial retry delay in seconds" +msgstr "Initial retry delay in seconds" + #: src/renderer/views/GitReviewOverlay/parts/GitReviewSidebar/GitReviewSidebar.tsx msgid "Initialize Repository" msgstr "Initialize Repository" @@ -4476,6 +4672,18 @@ msgstr "Interrupted" msgid "Interrupted: agent session ended before completion." msgstr "Interrupted: agent session ended before completion." +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Interval" +msgstr "Interval" + +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Interval amount" +msgstr "Interval amount" + +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Interval unit" +msgstr "Interval unit" + #: src/renderer/views/MainView/parts/RightPanel/parts/NotesPanel/NotesEditor.tsx msgid "Italic" msgstr "Italic" @@ -4560,6 +4768,14 @@ msgstr "Launching…" msgid "Leave a comment" msgstr "Leave a comment" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Leave blank for no run limit." +msgstr "Leave blank for no run limit." + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +#~ msgid "Leave blank to rely on the time limit." +#~ msgstr "Leave blank to rely on the time limit." + #: src/renderer/views/ProfileOverlay/parts/ActivityHeatmap.tsx msgid "Less" msgstr "Less" @@ -4640,6 +4856,10 @@ msgstr "Loading editor…" msgid "Loading file…" msgstr "Loading file…" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Loading findings" +msgstr "Loading findings" + #: src/renderer/components/skills/SkillMarketplaceModal.tsx msgid "Loading marketplace…" msgstr "Loading marketplace…" @@ -4864,6 +5084,14 @@ msgstr "Mark as done" msgid "Mark as not done" msgstr "Mark as not done" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Mark as read" +msgstr "Mark as read" + +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Mark as unread" +msgstr "Mark as unread" + #: src/renderer/components/thread/ThreadView.tsx msgid "Mark done" msgstr "Mark done" @@ -4904,6 +5132,22 @@ msgstr "Maximize" msgid "Maximize browser" msgstr "Maximize browser" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Maximum attempts" +msgstr "Maximum attempts" + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Maximum iterations" +msgstr "Maximum iterations" + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Maximum retry delay" +msgstr "Maximum retry delay" + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Maximum retry delay in seconds" +msgstr "Maximum retry delay in seconds" + #: src/renderer/components/skills/SkillMarketplaceModal.tsx #~ msgid "MCP Market" #~ msgstr "MCP Market" @@ -5110,6 +5354,18 @@ msgstr "Minimize to panel" msgid "Minute" msgstr "Minute" +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Minute, hour, day of month, month, and weekday." +msgstr "Minute, hour, day of month, month, and weekday." + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "minutes" +msgstr "minutes" + +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Minutes" +msgstr "Minutes" + #: src/mobile/views/BrowserView.tsx msgid "Mirrored desktop browser tab" msgstr "Mirrored desktop browser tab" @@ -5118,6 +5374,10 @@ msgstr "Mirrored desktop browser tab" msgid "Mirroring is unavailable." msgstr "Mirroring is unavailable." +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Missed runs" +msgstr "Missed runs" + #: src/renderer/views/SettingsOverlay/parts/RemoteAccessSettings.tsx msgid "Mobile push notifications" msgstr "Mobile push notifications" @@ -5469,6 +5729,10 @@ msgstr "Next match" msgid "Next recently viewed chat" msgstr "Next recently viewed chat" +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Next run" +msgstr "Next run" + #. placeholder {0}: dateTimeFormatter.format(new Date(task.nextRunAt)) #: src/renderer/views/SchedulesView/SchedulesView.tsx msgid "Next run {0}" @@ -5514,6 +5778,10 @@ msgstr "No agents installed." msgid "No AI commits, PRs, or conflict resolutions tracked yet." msgstr "No AI commits, PRs, or conflict resolutions tracked yet." +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "No archived findings." +msgstr "No archived findings." + #: src/renderer/views/SettingsOverlay/parts/ArchivedThreadsSettings.tsx msgid "No archived threads." msgstr "No archived threads." @@ -5610,6 +5878,10 @@ msgstr "No diff available for {0}" msgid "No diff for {visiblePath}" msgstr "No diff for {visiblePath}" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "No eligible conversations in this project." +msgstr "No eligible conversations in this project." + #: src/renderer/components/skills/SkillImportModal.tsx msgid "No external skills were found in this scope." msgstr "No external skills were found in this scope." @@ -5625,6 +5897,10 @@ msgstr "No file checkpoint is stored for this message." msgid "No files match \"{0}\"." msgstr "No files match \"{0}\"." +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "No findings yet." +msgstr "No findings yet." + #: src/renderer/views/MainView/parts/CreateProject/CloneProjectModal.tsx msgid "No GitHub CLI accounts found. Sign in with <0>gh auth login, or <1>paste a clone URL." msgstr "No GitHub CLI accounts found. Sign in with <0>gh auth login, or <1>paste a clone URL." @@ -5637,6 +5913,10 @@ msgstr "No history yet" msgid "No Lightcode data was found." msgstr "No Lightcode data was found." +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "No limit" +msgstr "No limit" + #: src/renderer/components/skills/SkillMarketplaceModal.tsx msgid "No marketplace skills match these filters." msgstr "No marketplace skills match these filters." @@ -5653,6 +5933,10 @@ msgstr "No matches." msgid "No matching agents." msgstr "No matching agents." +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "No matching findings." +msgstr "No matching findings." + #: src/renderer/views/PullRequestsView/PullRequestsView.tsx msgid "No matching pull requests." msgstr "No matching pull requests." @@ -5762,6 +6046,10 @@ msgstr "No repositories found." msgid "No results" msgstr "No results" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "No retries" +msgstr "No retries" + #: src/renderer/views/SchedulesView/parts/PreviousRunsModal.tsx msgid "No runs yet." msgstr "No runs yet." @@ -5798,6 +6086,10 @@ msgstr "No speech detected." msgid "No staged changes" msgstr "No staged changes" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "No summary was provided." +msgstr "No summary was provided." + #: src/renderer/views/RemoteProjectModal/RemoteProjectModal.tsx msgid "No supported agents are installed on this remote machine. Install and sign in to an agent remotely before starting a thread." msgstr "No supported agents are installed on this remote machine. Install and sign in to an agent remotely before starting a thread." @@ -5827,6 +6119,10 @@ msgstr "No threads yet" msgid "No threads yet." msgstr "No threads yet." +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "No upcoming run" +msgstr "No upcoming run" + #: src/renderer/components/providers/usageFormat.ts msgid "No windows reported" msgstr "No windows reported" @@ -6042,6 +6338,11 @@ msgstr "Open commit on GitHub" msgid "Open conflict resolver in" msgstr "Open conflict resolver in" +#. placeholder {0}: props.scheduleName +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Open conversation for {0}" +msgstr "Open conversation for {0}" + #: src/renderer/views/SettingsOverlay/parts/settingsOptions.ts msgid "Open dialog" msgstr "Open dialog" @@ -6677,6 +6978,10 @@ msgstr "Project folder updated. Reopen any terminals in this project." msgid "Project name" msgstr "Project name" +#: src/renderer/i18n/sharedMessages.ts +msgid "Project no longer exists." +msgstr "Project no longer exists." + #: src/renderer/views/MainView/parts/RightPanel/parts/NotesPanel/NotesEditor.tsx msgid "Project notes" msgstr "Project notes" @@ -7275,6 +7580,10 @@ msgstr "Request details" msgid "requested changes" msgstr "requested changes" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Required confidence before stopping." +msgstr "Required confidence before stopping." + #: src/mobile/views/pr/PrOverviewPage.tsx #: src/renderer/views/GitReviewOverlay/parts/GitReviewSidebar/parts/PrSection.tsx msgid "Required reviews, conversations, or status checks not met." @@ -7346,6 +7655,10 @@ msgstr "Restore browser" msgid "Restore default worktree base folder" msgstr "Restore default worktree base folder" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Restore finding" +msgstr "Restore finding" + #: src/mobile/settingsSections.ts msgid "Restore or delete" msgstr "Restore or delete" @@ -7376,10 +7689,26 @@ msgstr "Retry {serverName}" msgid "Retry check" msgstr "Retry check" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Retry delay" +msgstr "Retry delay" + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Retry delay in seconds" +msgstr "Retry delay in seconds" + #: src/mobile/components.tsx msgid "Retry now" msgstr "Retry now" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Retry policy" +msgstr "Retry policy" + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Retry when a run fails before it completes." +msgstr "Retry when a run fails before it completes." + #: src/renderer/hooks/usePrWriteActions.ts msgid "Retry with admin" msgstr "Retry with admin" @@ -7535,18 +7864,26 @@ msgstr "Run local transcription on the GPU when available." msgid "Run now" msgstr "Run now" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Run once after reopening" +msgstr "Run once after reopening" + #: src/renderer/views/SchedulesView/SchedulesView.tsx #~ msgid "Run standalone tasks on this device without a project." #~ msgstr "Run standalone tasks on this device without a project." #: src/renderer/views/SchedulesView/SchedulesView.tsx -msgid "Run standalone tasks on this device. Schedules run while the device is awake and Poracode is open." -msgstr "Run standalone tasks on this device. Schedules run while the device is awake and Poracode is open." +#~ msgid "Run standalone tasks on this device. Schedules run while the device is awake and Poracode is open." +#~ msgstr "Run standalone tasks on this device. Schedules run while the device is awake and Poracode is open." #: src/renderer/commands/registry.ts msgid "Run Terminal Command" msgstr "Run Terminal Command" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Run the latest missed run" +msgstr "Run the latest missed run" + #: src/renderer/views/SchedulesView/ScheduleEditor.tsx #~ msgid "Run this schedule automatically at the times above." #~ msgstr "Run this schedule automatically at the times above." @@ -7562,6 +7899,7 @@ msgstr "running" #: src/renderer/utils/prStatus.ts #: src/renderer/views/SchedulesView/parts/PreviousRunsModal.tsx +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx msgid "Running" msgstr "Running" @@ -7585,6 +7923,10 @@ msgstr "Runs out early" msgid "Runs out in {runOut}" msgstr "Runs out in {runOut}" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Runs that need attention will appear here." +msgstr "Runs that need attention will appear here." + #: src/renderer/views/MainView/parts/CreateProject/CloneProjectModal.tsx #: src/renderer/views/MainView/parts/CreateProject/CreateProjectModal.tsx msgid "Runtime" @@ -7661,6 +8003,10 @@ msgstr "Scanning Windows and WSL for installed CLIs. This usually takes a couple msgid "Scanning your system for installed CLIs. This usually takes a couple of seconds." msgstr "Scanning your system for installed CLIs. This usually takes a couple of seconds." +#: src/renderer/views/SchedulesView/SchedulesView.tsx +msgid "Schedule autonomous work and review results that need your attention. Automations run while this device is awake and Poracode is open." +msgstr "Schedule autonomous work and review results that need your attention. Automations run while this device is awake and Poracode is open." + #: src/renderer/views/SchedulesView/ScheduleEditor.tsx msgid "Schedule name" msgstr "Schedule name" @@ -7669,20 +8015,31 @@ msgstr "Schedule name" msgid "Schedule status" msgstr "Schedule status" +#: src/renderer/i18n/sharedMessages.ts +msgid "Scheduled retry was cancelled." +msgstr "Scheduled retry was cancelled." + +#: src/renderer/i18n/sharedMessages.ts +msgid "Scheduled task was deleted before retrying." +msgstr "Scheduled task was deleted before retrying." + #: src/renderer/views/SchedulesView/SchedulesView.tsx -msgid "Scheduled tasks" -msgstr "Scheduled tasks" +#~ msgid "Scheduled tasks" +#~ msgstr "Scheduled tasks" #: src/mobile/settingsSections.ts -msgid "Scheduled tasks on this desktop" -msgstr "Scheduled tasks on this desktop" +#~ msgid "Scheduled tasks on this desktop" +#~ msgstr "Scheduled tasks on this desktop" #: src/renderer/views/SchedulesView/SchedulesView.tsx #~ msgid "Scheduled tasks run only while this device is awake and Poracode is open." #~ msgstr "Scheduled tasks run only while this device is awake and Poracode is open." #: src/mobile/settingsSections.ts -#: src/renderer/views/MainView/parts/Sidebar/Sidebar.tsx +msgid "Scheduled work and triage on this desktop" +msgstr "Scheduled work and triage on this desktop" + +#: src/renderer/views/SchedulesView/SchedulesView.tsx msgid "Schedules" msgstr "Schedules" @@ -7737,6 +8094,10 @@ msgstr "Search branches..." msgid "Search files" msgstr "Search files" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Search findings" +msgstr "Search findings" + #: src/renderer/components/skills/SkillMarketplaceModal.tsx msgid "Search marketplace skills" msgstr "Search marketplace skills" @@ -7831,6 +8192,10 @@ msgstr "Searching..." msgid "Searching…" msgstr "Searching…" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "seconds" +msgstr "seconds" + #: src/renderer/components/skills/SkillMarketplaceModal.tsx #~ msgid "Security-focused directory with verified skill metadata." #~ msgstr "Security-focused directory with verified skill metadata." @@ -8221,6 +8586,10 @@ msgstr "Signing out {env}. Detected agents will refresh when it finishes." msgid "Signing out. Detected agents will refresh when it finishes." msgstr "Signing out. Detected agents will refresh when it finishes." +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Single pass" +msgstr "Single pass" + #: src/renderer/components/skills/SkillImportModal.tsx #: src/renderer/components/skills/SkillMarketplaceModal.tsx msgid "Skill availability" @@ -8285,7 +8654,12 @@ msgstr "Skills marketplace" msgid "Skills.sh" msgstr "Skills.sh" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Skip missed runs" +msgstr "Skip missed runs" + #: src/renderer/utils/prStatus.ts +#: src/renderer/views/SchedulesView/parts/PreviousRunsModal.tsx msgid "Skipped" msgstr "Skipped" @@ -8424,6 +8798,10 @@ msgstr "Start {appName} to see usage" msgid "Start a dev server on your desktop, then tap refresh." msgstr "Start a dev server on your desktop, then tap refresh." +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Start a new conversation for each run." +msgstr "Start a new conversation for each run." + #: src/renderer/commands/registry.ts msgid "Start a new thread as panel instead of page" msgstr "Start a new thread as panel instead of page" @@ -8562,6 +8940,10 @@ msgstr "Stop" msgid "Stop forwarding" msgstr "Stop forwarding" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Stop on error" +msgstr "Stop on error" + #: src/renderer/components/thread/ThreadComposer.tsx msgid "Stop response" msgstr "Stop response" @@ -8574,10 +8956,18 @@ msgstr "Stop task" msgid "Stop the project's running threads before changing its folder." msgstr "Stop the project's running threads before changing its folder." +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Stop the run when this total time is reached." +msgstr "Stop the run when this total time is reached." + #: src/renderer/components/composer/VoiceInputButton.tsx msgid "Stop voice input" msgstr "Stop voice input" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Stop when" +msgstr "Stop when" + #: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts #: src/renderer/views/SettingsOverlay/parts/WorktreeSettings.tsx msgid "Storage location" @@ -8922,6 +9312,22 @@ msgstr "The agent" msgid "the app" msgstr "the app" +#: src/renderer/i18n/sharedMessages.ts +msgid "The automation conversation exited before the turn completed." +msgstr "The automation conversation exited before the turn completed." + +#: src/renderer/i18n/sharedMessages.ts +msgid "The automation exceeded its time limit." +msgstr "The automation exceeded its time limit." + +#: src/renderer/i18n/sharedMessages.ts +msgid "The automation needs a reply before it can continue." +msgstr "The automation needs a reply before it can continue." + +#: src/renderer/i18n/sharedMessages.ts +msgid "The automation needs approval before it can continue." +msgstr "The automation needs approval before it can continue." + #: src/renderer/views/MainView/parts/CreateProject/CloneProjectModal.tsx msgid "the chosen folder" msgstr "the chosen folder" @@ -8935,11 +9341,39 @@ msgstr "The default background refresh cadence, used for any provider without it msgid "The desktop server is still coming online." msgstr "The desktop server is still coming online." +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "The finding is no longer available." +msgstr "The finding is no longer available." + #. placeholder {0}: createTarget.wslDistro #: src/renderer/components/skills/SkillsManager.tsx msgid "the global {0} WSL scope" msgstr "the global {0} WSL scope" +#: src/renderer/i18n/sharedMessages.ts +msgid "The heartbeat conversation belongs to a different project." +msgstr "The heartbeat conversation belongs to a different project." + +#: src/renderer/i18n/sharedMessages.ts +msgid "The heartbeat conversation cannot be resumed." +msgstr "The heartbeat conversation cannot be resumed." + +#: src/renderer/i18n/sharedMessages.ts +msgid "The heartbeat conversation is archived." +msgstr "The heartbeat conversation is archived." + +#: src/renderer/i18n/sharedMessages.ts +msgid "The heartbeat conversation is currently busy." +msgstr "The heartbeat conversation is currently busy." + +#: src/renderer/i18n/sharedMessages.ts +msgid "The heartbeat conversation no longer exists." +msgstr "The heartbeat conversation no longer exists." + +#: src/renderer/i18n/sharedMessages.ts +msgid "The heartbeat conversation uses a different agent." +msgstr "The heartbeat conversation uses a different agent." + #: src/renderer/components/skills/SkillsManager.tsx msgid "the Linux user" msgstr "the Linux user" @@ -8972,6 +9406,14 @@ msgstr "The remote server returned no pairing credential." msgid "The repository location on disk. Update it if you moved the folder." msgstr "The repository location on disk. Update it if you moved the folder." +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "The run could not be cancelled." +msgstr "The run could not be cancelled." + +#: src/renderer/i18n/sharedMessages.ts +msgid "The scheduled automation failed." +msgstr "The scheduled automation failed." + #: src/renderer/components/mcp/McpServersManager.tsx #~ msgid "The selected file does not contain valid MCP server configurations." #~ msgstr "The selected file does not contain valid MCP server configurations." @@ -9227,6 +9669,18 @@ msgstr "Threads marked done that have not been touched for this many days are ar msgid "Time" msgstr "Time" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Time limit" +msgstr "Time limit" + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Time limit in minutes" +msgstr "Time limit in minutes" + +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Time zone" +msgstr "Time zone" + #: src/renderer/components/mcp/McpServerEditor.tsx msgid "Timeout (ms)" msgstr "Timeout (ms)" @@ -9356,6 +9810,10 @@ msgstr "Translucent sidebar" msgid "Trending now" msgstr "Trending now" +#: src/renderer/views/SchedulesView/SchedulesView.tsx +msgid "Triage" +msgstr "Triage" + #: src/mobile/views/DesktopsView.tsx msgid "Trust and connect" msgstr "Trust and connect" @@ -9598,6 +10056,10 @@ msgstr "Unassigned" msgid "Unavailable" msgstr "Unavailable" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Unavailable conversation" +msgstr "Unavailable conversation" + #: src/renderer/views/SchedulesView/ScheduleEditor.tsx msgid "Unavailable project" msgstr "Unavailable project" @@ -9676,6 +10138,10 @@ msgstr "Unphased:" msgid "Unpin" msgstr "Unpin" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Unread" +msgstr "Unread" + #: src/mobile/views/GitActionSheet.tsx #: src/renderer/views/GitReviewOverlay/parts/GitReviewSidebar/parts/FileRow.tsx #: src/renderer/views/GitReviewOverlay/parts/GitStackedDiff.tsx @@ -10002,6 +10468,12 @@ msgstr "Waiting for {methodName} authentication. Detected agents will refresh wh msgid "waiting for agent to stop" msgstr "waiting for agent to stop" +#: src/renderer/views/SchedulesView/parts/PreviousRunsModal.tsx +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +#: src/renderer/views/SchedulesView/SchedulesView.tsx +msgid "Waiting for approval" +msgstr "Waiting for approval" + #: src/renderer/components/thread/ChatPane/parts/items/WorkflowOverlayBody.tsx msgid "Waiting for workflow to spawn agents…" msgstr "Waiting for workflow to spawn agents…" @@ -10034,6 +10506,10 @@ msgstr "Warming up shell environments..." msgid "Warming up WSL shell environment…" msgstr "Warming up WSL shell environment…" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Warning" +msgstr "Warning" + #: src/renderer/components/thread/ChatPane/parts/items/ToolCallGroup.tsx #: src/renderer/components/thread/ChatPane/parts/items/toolDisplay.ts #: src/renderer/components/thread/ChatPane/parts/items/WebSearchItem.tsx @@ -10326,6 +10802,10 @@ msgstr "WSL base folder" #~ msgid "WSL user" #~ msgstr "WSL user" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "You’re all caught up." +msgstr "You’re all caught up." + #: src/renderer/views/ProfileOverlay/parts/EditProfileDialog.tsx msgid "Your name" msgstr "Your name" diff --git a/src/renderer/locales/es/messages.po b/src/renderer/locales/es/messages.po index 8738a1f3a..7826051f9 100644 --- a/src/renderer/locales/es/messages.po +++ b/src/renderer/locales/es/messages.po @@ -288,6 +288,11 @@ msgstr "{agentLabel}: {statusLabel}. Pasa el cursor para ver detalles del estado msgid "{agentLead} needs your input to continue." msgstr "{agentLead} necesita tu respuesta para continuar." +#. placeholder {0}: task.recurrence.timeZone +#: src/renderer/views/SchedulesView/SchedulesView.tsx +msgid "{cadence} in {0}" +msgstr "{cadence} en {0}" + #: src/mobile/views/pr/PrOverviewPage.tsx msgid "{commitsCount, plural, one {# commit} other {# commits}}" msgstr "{commitsCount, plural, one {# commit} other {# commits}}" @@ -315,6 +320,18 @@ msgstr "hace {days}d" msgid "{envOrAgentLabel} needs authentication." msgstr "{envOrAgentLabel} necesita autenticación." +#: src/renderer/views/SchedulesView/SchedulesView.tsx +msgid "{every, plural, one {Every day} other {Every # days}}" +msgstr "{every, plural, one {Todos los días} other {Cada # días}}" + +#: src/renderer/views/SchedulesView/SchedulesView.tsx +msgid "{every, plural, one {Every hour} other {Every # hours}}" +msgstr "{every, plural, one {Cada hora} other {Cada # horas}}" + +#: src/renderer/views/SchedulesView/SchedulesView.tsx +msgid "{every, plural, one {Every minute} other {Every # minutes}}" +msgstr "{every, plural, one {Cada minuto} other {Cada # minutos}}" + #: src/mobile/views/pr/PrOverviewPage.tsx msgid "{filesCount, plural, one {# file changed} other {# files changed}}" msgstr "{filesCount, plural, one {# archivo cambiado} other {# archivos cambiados}}" @@ -491,6 +508,10 @@ msgstr "~{money}{tokens} · {0} · est." msgid "≈{0}% by reset" msgstr "≈{0}% para el restablecimiento" +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "0 9 * * 1-5" +msgstr "0 9 * * 1-5" + #: src/mobile/views/ThreadsView.tsx msgid "1 thread" msgstr "1 hilo" @@ -840,6 +861,10 @@ msgstr "Acciones de git con IA" msgid "AI providers" msgstr "Proveedores de IA" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "AI stop condition" +msgstr "Condición de detención por IA" + #: src/mobile/views/MoreView.tsx #~ msgid "AI, agents, and archived threads on the paired desktop" #~ msgstr "IA, agentes e hilos archivados en el escritorio emparejado" @@ -851,6 +876,7 @@ msgstr "Alertas cuando los hilos necesitan tu atención" #: src/renderer/commands/shortcutCatalog.ts #: src/renderer/components/skills/SkillsManager.tsx #: src/renderer/views/PullRequestsView/PullRequestsView.tsx +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx #: src/renderer/views/SchedulesView/SchedulesView.tsx #: src/renderer/views/SettingsOverlay/parts/ProfileSettings.tsx msgid "All" @@ -943,6 +969,10 @@ msgstr "Siempre excluido" msgid "An MCP server with this name already exists." msgstr "Ya existe un servidor MCP con este nombre." +#: src/renderer/i18n/sharedMessages.ts +msgid "Another automation is already using this conversation." +msgstr "Otra automatización ya está usando esta conversación." + #: src/renderer/components/thread/ChatPane/parts/CheckpointRevertControls.tsx msgid "Another chat uses this same tree. File restore could overwrite that chat's changes." msgstr "Otro chat usa este mismo árbol. Restaurar archivos podría sobrescribir los cambios de ese chat." @@ -1014,6 +1044,10 @@ msgstr "Archivar todo" msgid "Archive all threads" msgstr "Archivar todos los hilos" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Archive finding" +msgstr "Archivar hallazgo" + #: src/renderer/commands/registry.ts msgid "Archive the current thread" msgstr "Archivar el hilo actual" @@ -1028,6 +1062,10 @@ msgstr "Archivar hilo" msgid "Archive Thread" msgstr "Archivar hilo" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Archived" +msgstr "Archivados" + #: src/mobile/settingsSections.ts #: src/mobile/views/SettingsView.tsx #: src/renderer/views/SettingsOverlay/parts/ArchivedThreadsSettings.tsx @@ -1173,6 +1211,16 @@ msgstr "Mostrar el panel del terminal automáticamente" msgid "Automatically show the terminal panel when running commands or creating worktrees." msgstr "Mostrar automáticamente el panel del terminal al ejecutar comandos o crear worktrees." +#: src/renderer/views/SchedulesView/SchedulesView.tsx +msgid "Automation sections" +msgstr "Secciones de automatización" + +#: src/mobile/settingsSections.ts +#: src/renderer/views/MainView/parts/Sidebar/Sidebar.tsx +#: src/renderer/views/SchedulesView/SchedulesView.tsx +msgid "Automations" +msgstr "Automatizaciones" + #: src/renderer/components/skills/SkillImportModal.tsx msgid "Availability" msgstr "Disponibilidad" @@ -1459,6 +1507,10 @@ msgstr "Omitir las reglas de protección de ramas (fusión de administrador)" msgid "Cached only" msgstr "Solo en caché" +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Calculated on desktop after saving" +msgstr "Se calcula en el equipo después de guardar" + #: src/mobile/QrScanner.tsx msgid "Camera access blocked" msgstr "Acceso a la cámara bloqueado" @@ -1513,11 +1565,16 @@ msgstr "Cancelar selector" msgid "Cancel removing project" msgstr "Cancelar eliminación del proyecto" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Cancel run" +msgstr "Cancelar ejecución" + #: src/renderer/components/thread/ChatPane/parts/items/WorkflowOverlayBody.tsx msgid "cancelled" msgstr "cancelado" #: src/renderer/utils/prStatus.ts +#: src/renderer/views/SchedulesView/parts/PreviousRunsModal.tsx msgid "Cancelled" msgstr "Cancelado" @@ -1706,6 +1763,10 @@ msgstr "Elige el idioma de visualización de la interfaz de Poracode." msgid "Choose thread to attach to" msgstr "Elige el hilo al que adjuntar" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Choose what happens after a scheduled time was missed." +msgstr "Elige qué ocurre cuando se pierde una hora programada." + #: src/renderer/views/SettingsOverlay/parts/BrowserSettings.tsx #: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts msgid "Choose whether links from Poracode and browser popups stay in Poracode or open externally." @@ -2185,6 +2246,14 @@ msgstr "completado" msgid "Completed" msgstr "Completado" +#: src/renderer/i18n/sharedMessages.ts +msgid "Completion evaluation failed: {detail}" +msgstr "La evaluación de finalización falló: {detail}" + +#: src/renderer/i18n/sharedMessages.ts +msgid "Completion evaluation is unavailable." +msgstr "La evaluación de finalización no está disponible." + #: src/renderer/commands/shortcutCatalog.ts #: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx #: src/renderer/views/SettingsOverlay/parts/settingsOptions.ts @@ -2223,6 +2292,14 @@ msgstr "Computer Use activado: las acciones interactivas toman el control del es #~ msgid "Computer Use enabled for this thread" #~ msgstr "Uso del ordenador habilitado para este hilo" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Confidence" +msgstr "Confianza" + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Confidence percent" +msgstr "Porcentaje de confianza" + #: src/renderer/views/SettingsOverlay/parts/ClaudeProfileSettings.tsx msgid "Config directory" msgstr "Directorio de configuración" @@ -2386,6 +2463,14 @@ msgstr "Continuar en otro proveedor" msgid "Continue in..." msgstr "Continuar en..." +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Continue one conversation until a stop condition or limit is reached." +msgstr "Continúa una conversación hasta que se alcance una condición de detención o un límite." + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Control how each scheduled run continues and stops." +msgstr "Controla cómo continúa y se detiene cada ejecución programada." + #: src/renderer/views/SettingsOverlay/parts/SearchSettings.tsx msgid "Control which files appear in the @file mention search. Per-project overrides live in each project's settings." msgstr "Controla qué archivos aparecen en la búsqueda de menciones @file. Las anulaciones por proyecto están en la configuración de cada proyecto." @@ -2397,6 +2482,7 @@ msgstr "Controla el escritorio emparejado mientras el agente hace clic o escribe #: src/mobile/views/pr/PrConversationPage.tsx #: src/mobile/views/pr/PrOverviewPage.tsx #: src/renderer/views/PrReviewOverlay/parts/PrTabsPill.tsx +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx msgid "Conversation" msgstr "Conversación" @@ -2697,6 +2783,24 @@ msgstr "Las credenciales están configuradas." msgid "Credits" msgstr "Créditos" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Critical" +msgstr "Crítico" + +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Cron" +msgstr "Cron" + +#. placeholder {0}: task.recurrence.expression +#. placeholder {1}: task.recurrence.timeZone +#: src/renderer/views/SchedulesView/SchedulesView.tsx +msgid "Cron {0} in {1}" +msgstr "Cron {0} en {1}" + +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Cron expression" +msgstr "Expresión cron" + #: src/renderer/components/skills/SkillMarketplaceModal.tsx #~ msgid "Curated free and premium skills managed by MCP Market." #~ msgstr "Skills gratuitas y premium seleccionadas y gestionadas por MCP Market." @@ -2762,9 +2866,9 @@ msgstr "Resumen diario" msgid "Dark" msgstr "Oscuro" -#: src/renderer/views/SchedulesView/SchedulesView.tsx -#~ msgid "Days" -#~ msgstr "Días" +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Days" +msgstr "Días" #: src/renderer/components/thread/ThreadRuntimeRequestPanel/structuredElicitation.tsx msgid "Decline" @@ -2911,6 +3015,10 @@ msgstr "Eliminar worktree {0}" #~ msgid "Delete:" #~ msgstr "Eliminar:" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Deleted schedule" +msgstr "Programación eliminada" + #: src/renderer/views/SettingsOverlay/parts/AcpRegistrySettings.tsx msgid "Deleting" msgstr "Eliminando" @@ -2923,6 +3031,10 @@ msgstr "Denegar" msgid "Deny and tell the agent what to do differently…" msgstr "Denegar y decirle al agente qué hacer de otra manera…" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Describe the result that completes this heartbeat." +msgstr "Describe el resultado que completa este heartbeat." + #: src/renderer/views/SchedulesView/ScheduleEditor.tsx msgid "Describe what the agent should do" msgstr "Describe lo que debe hacer el agente" @@ -2944,6 +3056,10 @@ msgstr "Endpoint del escritorio" msgid "Desktop is unreachable." msgstr "No se puede contactar con el escritorio." +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Desktop local time" +msgstr "Hora local del equipo" + #: src/mobile/chrome.ts #: src/mobile/views/MoreView.tsx msgid "Desktop Settings" @@ -3056,6 +3172,10 @@ msgstr "Deshabilitar proyecto" msgid "Disable Subagents" msgstr "Deshabilitar subagentes" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Disable the automation after retries are exhausted." +msgstr "Desactiva la automatización después de agotar los reintentos." + #: src/renderer/views/SettingsOverlay/parts/ClaudeProfileSettings.tsx msgid "Disable tiers an external provider collapses (e.g. keep only High and Max)." msgstr "Desactiva los niveles que un proveedor externo unifica (p. ej. mantener solo High y Max)." @@ -3356,6 +3476,10 @@ msgstr "Los servidores activados permanecen activos para los nuevos hilos" msgid "Enables <0>cookies and <1>storage. Cookies can contain session tokens and storage often holds auth state — only enable when you trust both the agent and the sites it visits." msgstr "Activa <0>cookies y <1>almacenamiento. Las cookies pueden contener tokens de sesión y el almacenamiento suele guardar el estado de autenticación: actívalo solo cuando confíes tanto en el agente como en los sitios que visita." +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +#~ msgid "End the heartbeat after retries are exhausted." +#~ msgstr "Finaliza el heartbeat después de agotar los reintentos." + #: src/mobile/views/DesktopsView.tsx #: src/renderer/views/SettingsOverlay/parts/RemoteServersSettings.tsx msgid "Endpoint" @@ -3393,6 +3517,10 @@ msgstr "Introduce un endpoint de escritorio válido." msgid "Enter a valid HTTP or HTTPS URL." msgstr "Introduce una URL HTTP o HTTPS válida." +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Enter a valid schedule" +msgstr "Introduce una programación válida" + #: src/mobile/views/DesktopsView.tsx msgid "Enter a valid SSH target and port." msgstr "Introduce un destino SSH y un puerto válidos." @@ -3463,6 +3591,14 @@ msgstr "Error" msgid "Error · Agent encountered an error" msgstr "Error · El agente encontró un error" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Evaluate the result after every iteration." +msgstr "Evalúa el resultado después de cada iteración." + +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Every" +msgstr "Cada" + #: src/renderer/views/SchedulesView/SchedulesView.tsx msgid "Every day at {time}" msgstr "Todos los días a las {time}" @@ -3485,6 +3621,14 @@ msgstr "Cada hora, a los {0} minutos" msgid "Exclude patterns" msgstr "Patrones de exclusión" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Execution" +msgstr "Ejecución" + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Execution mode" +msgstr "Modo de ejecución" + #: src/renderer/components/thread/ChatPane/parts/items/toolDisplay.ts msgid "Exit plan mode" msgstr "Salir del modo plan" @@ -3534,6 +3678,10 @@ msgstr "Expandir para revisar o revocar el acceso." msgid "Expand todo dock" msgstr "Expandir panel de tareas" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Exponential backoff" +msgstr "Espera exponencial" + #: src/renderer/components/mcp/McpServersManager.tsx msgid "Export MCP servers" msgstr "Exportar servidores MCP" @@ -3716,6 +3864,10 @@ msgstr "Buscar en el diff" msgid "Find in terminal" msgstr "Buscar en el terminal" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Finding status" +msgstr "Estado del hallazgo" + #: src/renderer/views/PrReviewOverlay/parts/SubmitReviewPopover.tsx msgid "Finish your review" msgstr "Termina tu revisión" @@ -3777,6 +3929,10 @@ msgstr "Corregir en el agente" msgid "Fixed" msgstr "Corregido" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Fixed delay" +msgstr "Retraso fijo" + #: src/renderer/commands/registry.ts msgid "Focus browser address bar" msgstr "Enfocar barra de direcciones del navegador" @@ -4097,6 +4253,26 @@ msgstr "Tiene un borrador sin enviar" msgid "Headers" msgstr "Encabezados" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Heartbeat" +msgstr "Heartbeat" + +#: src/renderer/i18n/sharedMessages.ts +msgid "Heartbeat automations require a native chat conversation." +msgstr "Las automatizaciones de heartbeat requieren una conversación de chat nativa." + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Heartbeat continues this conversation in the selected project." +msgstr "El heartbeat continúa esta conversación en el proyecto seleccionado." + +#: src/renderer/i18n/sharedMessages.ts +msgid "Heartbeat execution is unavailable." +msgstr "La ejecución de heartbeat no está disponible." + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Heartbeats can continue making changes while you're away. Set hard limits below." +msgstr "Los heartbeats pueden seguir realizando cambios mientras no estás. Define límites estrictos abajo." + #: src/renderer/views/SchedulesView/SchedulesView.tsx msgid "Help me create a schedule. Ask for any missing details, then use the Poracode schedule controls to create it for me." msgstr "Ayúdame a crear una programación. Pregunta por los detalles que falten y usa los controles de programación de Poracode para crearla." @@ -4198,6 +4374,10 @@ msgstr "host.com, alias o usuario@host.com" msgid "Hourly" msgstr "Cada hora" +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Hours" +msgstr "Horas" + #: src/renderer/components/mcp/McpServerEditor.tsx msgid "HTTP (streamable)" msgstr "HTTP (transmisión continua)" @@ -4328,6 +4508,14 @@ msgstr "El escaneo con cámara dentro de la app solo funciona con HTTPS. Usa la msgid "Inactive" msgstr "Inactivo" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Includes the first attempt." +msgstr "Incluye el primer intento." + +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Info" +msgstr "Información" + #. Badge on an exclude pattern inherited from a lower scope #: src/renderer/views/SettingsOverlay/parts/SearchExcludeBody.tsx msgid "inherited" @@ -4338,6 +4526,14 @@ msgstr "heredado" msgid "Inheriting the global setting (currently {0})." msgstr "Heredando el ajuste global (actualmente {0})." +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Initial retry delay" +msgstr "Retraso inicial de reintento" + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Initial retry delay in seconds" +msgstr "Retraso inicial de reintento en segundos" + #: src/renderer/views/GitReviewOverlay/parts/GitReviewSidebar/GitReviewSidebar.tsx msgid "Initialize Repository" msgstr "Inicializar repositorio" @@ -4476,6 +4672,18 @@ msgstr "Interrumpida" msgid "Interrupted: agent session ended before completion." msgstr "Interrumpido: la sesión del agente terminó antes de completarse." +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Interval" +msgstr "Intervalo" + +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Interval amount" +msgstr "Cantidad del intervalo" + +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Interval unit" +msgstr "Unidad del intervalo" + #: src/renderer/views/MainView/parts/RightPanel/parts/NotesPanel/NotesEditor.tsx msgid "Italic" msgstr "Cursiva" @@ -4560,6 +4768,14 @@ msgstr "Lanzando…" msgid "Leave a comment" msgstr "Dejar un comentario" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Leave blank for no run limit." +msgstr "Déjalo en blanco para no limitar el número de ejecuciones." + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +#~ msgid "Leave blank to rely on the time limit." +#~ msgstr "Déjalo en blanco para usar el límite de tiempo." + #: src/renderer/views/ProfileOverlay/parts/ActivityHeatmap.tsx msgid "Less" msgstr "Menos" @@ -4640,6 +4856,10 @@ msgstr "Cargando editor…" msgid "Loading file…" msgstr "Cargando archivo…" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Loading findings" +msgstr "Cargando hallazgos" + #: src/renderer/components/skills/SkillMarketplaceModal.tsx msgid "Loading marketplace…" msgstr "Cargando marketplace…" @@ -4864,6 +5084,14 @@ msgstr "Marcar como hecho" msgid "Mark as not done" msgstr "Marcar como no hecho" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Mark as read" +msgstr "Marcar como leído" + +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Mark as unread" +msgstr "Marcar como no leído" + #: src/renderer/components/thread/ThreadView.tsx msgid "Mark done" msgstr "Marcar hecho" @@ -4904,6 +5132,22 @@ msgstr "Maximizar" msgid "Maximize browser" msgstr "Maximizar navegador" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Maximum attempts" +msgstr "Máximo de intentos" + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Maximum iterations" +msgstr "Máximo de iteraciones" + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Maximum retry delay" +msgstr "Retraso máximo de reintento" + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Maximum retry delay in seconds" +msgstr "Retraso máximo de reintento en segundos" + #: src/renderer/components/skills/SkillMarketplaceModal.tsx #~ msgid "MCP Market" #~ msgstr "MCP Market" @@ -5110,6 +5354,18 @@ msgstr "Minimizar al panel" msgid "Minute" msgstr "Minuto" +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Minute, hour, day of month, month, and weekday." +msgstr "Minuto, hora, día del mes, mes y día de la semana." + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "minutes" +msgstr "minutos" + +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Minutes" +msgstr "Minutos" + #: src/mobile/views/BrowserView.tsx msgid "Mirrored desktop browser tab" msgstr "Pestaña del navegador del escritorio duplicada" @@ -5118,6 +5374,10 @@ msgstr "Pestaña del navegador del escritorio duplicada" msgid "Mirroring is unavailable." msgstr "La duplicación no está disponible." +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Missed runs" +msgstr "Ejecuciones perdidas" + #: src/renderer/views/SettingsOverlay/parts/RemoteAccessSettings.tsx msgid "Mobile push notifications" msgstr "Notificaciones push móviles" @@ -5469,6 +5729,10 @@ msgstr "Coincidencia siguiente" msgid "Next recently viewed chat" msgstr "Siguiente chat visto recientemente" +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Next run" +msgstr "Próxima ejecución" + #. placeholder {0}: dateTimeFormatter.format(new Date(task.nextRunAt)) #: src/renderer/views/SchedulesView/SchedulesView.tsx msgid "Next run {0}" @@ -5514,6 +5778,10 @@ msgstr "No hay agentes instalados." msgid "No AI commits, PRs, or conflict resolutions tracked yet." msgstr "Aún no se han registrado commits, PRs ni resoluciones de conflictos con IA." +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "No archived findings." +msgstr "No hay hallazgos archivados." + #: src/renderer/views/SettingsOverlay/parts/ArchivedThreadsSettings.tsx msgid "No archived threads." msgstr "No hay hilos archivados." @@ -5610,6 +5878,10 @@ msgstr "No hay diff disponible para {0}" msgid "No diff for {visiblePath}" msgstr "No hay diff para {visiblePath}" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "No eligible conversations in this project." +msgstr "No hay conversaciones aptas en este proyecto." + #: src/renderer/components/skills/SkillImportModal.tsx msgid "No external skills were found in this scope." msgstr "No se encontraron skills externos en este ámbito." @@ -5625,6 +5897,10 @@ msgstr "No hay punto de control de archivos guardado para este mensaje." msgid "No files match \"{0}\"." msgstr "Ningún archivo coincide con \"{0}\"." +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "No findings yet." +msgstr "Aún no hay hallazgos." + #: src/renderer/views/MainView/parts/CreateProject/CloneProjectModal.tsx msgid "No GitHub CLI accounts found. Sign in with <0>gh auth login, or <1>paste a clone URL." msgstr "No se encontraron cuentas de GitHub CLI. Inicia sesión con <0>gh auth login, o <1>pega una URL de clonación." @@ -5637,6 +5913,10 @@ msgstr "Aún no hay historial" msgid "No Lightcode data was found." msgstr "No se encontraron datos de Lightcode." +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "No limit" +msgstr "Sin límite" + #: src/renderer/components/skills/SkillMarketplaceModal.tsx msgid "No marketplace skills match these filters." msgstr "Ninguna skill del marketplace coincide con estos filtros." @@ -5653,6 +5933,10 @@ msgstr "Sin coincidencias." msgid "No matching agents." msgstr "No hay agentes coincidentes." +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "No matching findings." +msgstr "No hay hallazgos coincidentes." + #: src/renderer/views/PullRequestsView/PullRequestsView.tsx msgid "No matching pull requests." msgstr "No hay pull requests coincidentes." @@ -5762,6 +6046,10 @@ msgstr "No se encontraron repositorios." msgid "No results" msgstr "Sin resultados" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "No retries" +msgstr "Sin reintentos" + #: src/renderer/views/SchedulesView/parts/PreviousRunsModal.tsx msgid "No runs yet." msgstr "Aún no hay ejecuciones." @@ -5798,6 +6086,10 @@ msgstr "No se detectó voz." msgid "No staged changes" msgstr "No hay cambios preparados" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "No summary was provided." +msgstr "No se proporcionó ningún resumen." + #: src/renderer/views/RemoteProjectModal/RemoteProjectModal.tsx msgid "No supported agents are installed on this remote machine. Install and sign in to an agent remotely before starting a thread." msgstr "No hay agentes compatibles instalados en esta máquina remota. Instala un agente e inicia sesión de forma remota antes de iniciar un hilo." @@ -5827,6 +6119,10 @@ msgstr "Aún no hay hilos" msgid "No threads yet." msgstr "Aún no hay hilos." +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "No upcoming run" +msgstr "No hay próximas ejecuciones" + #: src/renderer/components/providers/usageFormat.ts msgid "No windows reported" msgstr "No se informaron ventanas" @@ -6042,6 +6338,11 @@ msgstr "Abrir commit en GitHub" msgid "Open conflict resolver in" msgstr "Abrir el resolutor de conflictos en" +#. placeholder {0}: props.scheduleName +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Open conversation for {0}" +msgstr "Abrir conversación para {0}" + #: src/renderer/views/SettingsOverlay/parts/settingsOptions.ts msgid "Open dialog" msgstr "Abrir diálogo" @@ -6677,6 +6978,10 @@ msgstr "Carpeta del proyecto actualizada. Vuelve a abrir cualquier terminal de e msgid "Project name" msgstr "Nombre del proyecto" +#: src/renderer/i18n/sharedMessages.ts +msgid "Project no longer exists." +msgstr "El proyecto ya no existe." + #: src/renderer/views/MainView/parts/RightPanel/parts/NotesPanel/NotesEditor.tsx msgid "Project notes" msgstr "Notas del proyecto" @@ -7275,6 +7580,10 @@ msgstr "Detalles de la solicitud" msgid "requested changes" msgstr "cambios solicitados" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Required confidence before stopping." +msgstr "Confianza necesaria antes de detenerse." + #: src/mobile/views/pr/PrOverviewPage.tsx #: src/renderer/views/GitReviewOverlay/parts/GitReviewSidebar/parts/PrSection.tsx msgid "Required reviews, conversations, or status checks not met." @@ -7346,6 +7655,10 @@ msgstr "Restaurar navegador" msgid "Restore default worktree base folder" msgstr "Restaurar la carpeta base de worktrees predeterminada" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Restore finding" +msgstr "Restaurar hallazgo" + #: src/mobile/settingsSections.ts msgid "Restore or delete" msgstr "Restaurar o eliminar" @@ -7376,10 +7689,26 @@ msgstr "Reintentar la comprobación de {serverName}" msgid "Retry check" msgstr "Reintentar la comprobación" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Retry delay" +msgstr "Retraso de reintento" + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Retry delay in seconds" +msgstr "Retraso de reintento en segundos" + #: src/mobile/components.tsx msgid "Retry now" msgstr "Reintentar ahora" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Retry policy" +msgstr "Política de reintentos" + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Retry when a run fails before it completes." +msgstr "Reintenta cuando una ejecución falla antes de completarse." + #: src/renderer/hooks/usePrWriteActions.ts msgid "Retry with admin" msgstr "Reintentar como administrador" @@ -7535,18 +7864,26 @@ msgstr "Ejecutar la transcripción local en la GPU cuando esté disponible." msgid "Run now" msgstr "Ejecutar ahora" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Run once after reopening" +msgstr "Ejecutar una vez al volver a abrir" + #: src/renderer/views/SchedulesView/SchedulesView.tsx #~ msgid "Run standalone tasks on this device without a project." #~ msgstr "Ejecuta tareas independientes en este dispositivo sin un proyecto." #: src/renderer/views/SchedulesView/SchedulesView.tsx -msgid "Run standalone tasks on this device. Schedules run while the device is awake and Poracode is open." -msgstr "Ejecuta tareas independientes en este dispositivo. Las programaciones se ejecutan mientras el dispositivo está activo y Poracode está abierto." +#~ msgid "Run standalone tasks on this device. Schedules run while the device is awake and Poracode is open." +#~ msgstr "Ejecuta tareas independientes en este dispositivo. Las programaciones se ejecutan mientras el dispositivo está activo y Poracode está abierto." #: src/renderer/commands/registry.ts msgid "Run Terminal Command" msgstr "Ejecutar comando de terminal" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Run the latest missed run" +msgstr "Ejecutar la última ejecución perdida" + #: src/renderer/views/SchedulesView/ScheduleEditor.tsx #~ msgid "Run this schedule automatically at the times above." #~ msgstr "Ejecutar esta programación automáticamente en los horarios indicados arriba." @@ -7562,6 +7899,7 @@ msgstr "en ejecución" #: src/renderer/utils/prStatus.ts #: src/renderer/views/SchedulesView/parts/PreviousRunsModal.tsx +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx msgid "Running" msgstr "Ejecutándose" @@ -7585,6 +7923,10 @@ msgstr "Se agota antes" msgid "Runs out in {runOut}" msgstr "Se agota en {runOut}" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Runs that need attention will appear here." +msgstr "Las ejecuciones que necesiten atención aparecerán aquí." + #: src/renderer/views/MainView/parts/CreateProject/CloneProjectModal.tsx #: src/renderer/views/MainView/parts/CreateProject/CreateProjectModal.tsx msgid "Runtime" @@ -7661,6 +8003,10 @@ msgstr "Escaneando Windows y WSL en busca de CLIs instaladas. Esto suele tardar msgid "Scanning your system for installed CLIs. This usually takes a couple of seconds." msgstr "Escaneando tu sistema en busca de CLIs instaladas. Esto suele tardar un par de segundos." +#: src/renderer/views/SchedulesView/SchedulesView.tsx +msgid "Schedule autonomous work and review results that need your attention. Automations run while this device is awake and Poracode is open." +msgstr "Programa trabajo autónomo y revisa los resultados que requieren tu atención. Las automatizaciones se ejecutan mientras este dispositivo esté activo y Poracode esté abierto." + #: src/renderer/views/SchedulesView/ScheduleEditor.tsx msgid "Schedule name" msgstr "Nombre de la programación" @@ -7669,20 +8015,31 @@ msgstr "Nombre de la programación" msgid "Schedule status" msgstr "Estado de la programación" +#: src/renderer/i18n/sharedMessages.ts +msgid "Scheduled retry was cancelled." +msgstr "El reintento programado se canceló." + +#: src/renderer/i18n/sharedMessages.ts +msgid "Scheduled task was deleted before retrying." +msgstr "La tarea programada se eliminó antes del reintento." + #: src/renderer/views/SchedulesView/SchedulesView.tsx -msgid "Scheduled tasks" -msgstr "Tareas programadas" +#~ msgid "Scheduled tasks" +#~ msgstr "Tareas programadas" #: src/mobile/settingsSections.ts -msgid "Scheduled tasks on this desktop" -msgstr "Tareas programadas en este escritorio" +#~ msgid "Scheduled tasks on this desktop" +#~ msgstr "Tareas programadas en este escritorio" #: src/renderer/views/SchedulesView/SchedulesView.tsx #~ msgid "Scheduled tasks run only while this device is awake and Poracode is open." #~ msgstr "Las tareas programadas solo se ejecutan mientras este dispositivo está activo y Poracode está abierto." #: src/mobile/settingsSections.ts -#: src/renderer/views/MainView/parts/Sidebar/Sidebar.tsx +msgid "Scheduled work and triage on this desktop" +msgstr "Trabajo programado y triaje en este escritorio" + +#: src/renderer/views/SchedulesView/SchedulesView.tsx msgid "Schedules" msgstr "Programaciones" @@ -7737,6 +8094,10 @@ msgstr "Buscar ramas..." msgid "Search files" msgstr "Buscar archivos" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Search findings" +msgstr "Buscar hallazgos" + #: src/renderer/components/skills/SkillMarketplaceModal.tsx msgid "Search marketplace skills" msgstr "Buscar skills en el marketplace" @@ -7831,6 +8192,10 @@ msgstr "Buscando..." msgid "Searching…" msgstr "Buscando…" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "seconds" +msgstr "segundos" + #: src/renderer/components/skills/SkillMarketplaceModal.tsx #~ msgid "Security-focused directory with verified skill metadata." #~ msgstr "Directorio centrado en la seguridad con metadatos verificados de las skills." @@ -8221,6 +8586,10 @@ msgstr "Cerrando sesión en {env}. Los agentes detectados se actualizarán al fi msgid "Signing out. Detected agents will refresh when it finishes." msgstr "Cerrando sesión. Los agentes detectados se actualizarán al finalizar." +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Single pass" +msgstr "Una sola pasada" + #: src/renderer/components/skills/SkillImportModal.tsx #: src/renderer/components/skills/SkillMarketplaceModal.tsx msgid "Skill availability" @@ -8285,7 +8654,12 @@ msgstr "Marketplace de skills" msgid "Skills.sh" msgstr "Skills.sh" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Skip missed runs" +msgstr "Omitir ejecuciones perdidas" + #: src/renderer/utils/prStatus.ts +#: src/renderer/views/SchedulesView/parts/PreviousRunsModal.tsx msgid "Skipped" msgstr "Omitido" @@ -8424,6 +8798,10 @@ msgstr "Inicia {appName} para ver el uso" msgid "Start a dev server on your desktop, then tap refresh." msgstr "Inicia un servidor de desarrollo en tu escritorio y luego toca actualizar." +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Start a new conversation for each run." +msgstr "Inicia una conversación nueva para cada ejecución." + #: src/renderer/commands/registry.ts msgid "Start a new thread as panel instead of page" msgstr "Iniciar un nuevo hilo como panel en lugar de página" @@ -8562,6 +8940,10 @@ msgstr "Detener" msgid "Stop forwarding" msgstr "Detener reenvío" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Stop on error" +msgstr "Detener al producirse un error" + #: src/renderer/components/thread/ThreadComposer.tsx msgid "Stop response" msgstr "Detener respuesta" @@ -8574,10 +8956,18 @@ msgstr "Detener tarea" msgid "Stop the project's running threads before changing its folder." msgstr "Detén los hilos en ejecución del proyecto antes de cambiar su carpeta." +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Stop the run when this total time is reached." +msgstr "Detén la ejecución cuando se alcance este tiempo total." + #: src/renderer/components/composer/VoiceInputButton.tsx msgid "Stop voice input" msgstr "Detener entrada de voz" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Stop when" +msgstr "Detener cuando" + #: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts #: src/renderer/views/SettingsOverlay/parts/WorktreeSettings.tsx msgid "Storage location" @@ -8922,6 +9312,22 @@ msgstr "El agente" msgid "the app" msgstr "la app" +#: src/renderer/i18n/sharedMessages.ts +msgid "The automation conversation exited before the turn completed." +msgstr "La conversación de automatización terminó antes de que se completara el turno." + +#: src/renderer/i18n/sharedMessages.ts +msgid "The automation exceeded its time limit." +msgstr "La automatización superó su límite de tiempo." + +#: src/renderer/i18n/sharedMessages.ts +msgid "The automation needs a reply before it can continue." +msgstr "La automatización necesita una respuesta antes de poder continuar." + +#: src/renderer/i18n/sharedMessages.ts +msgid "The automation needs approval before it can continue." +msgstr "La automatización necesita aprobación antes de poder continuar." + #: src/renderer/views/MainView/parts/CreateProject/CloneProjectModal.tsx msgid "the chosen folder" msgstr "la carpeta elegida" @@ -8935,11 +9341,39 @@ msgstr "La cadencia de actualización en segundo plano predeterminada, usada par msgid "The desktop server is still coming online." msgstr "El servidor de escritorio todavía se está iniciando." +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "The finding is no longer available." +msgstr "El hallazgo ya no está disponible." + #. placeholder {0}: createTarget.wslDistro #: src/renderer/components/skills/SkillsManager.tsx msgid "the global {0} WSL scope" msgstr "el ámbito WSL global de {0}" +#: src/renderer/i18n/sharedMessages.ts +msgid "The heartbeat conversation belongs to a different project." +msgstr "La conversación de heartbeat pertenece a otro proyecto." + +#: src/renderer/i18n/sharedMessages.ts +msgid "The heartbeat conversation cannot be resumed." +msgstr "La conversación de heartbeat no se puede reanudar." + +#: src/renderer/i18n/sharedMessages.ts +msgid "The heartbeat conversation is archived." +msgstr "La conversación de heartbeat está archivada." + +#: src/renderer/i18n/sharedMessages.ts +msgid "The heartbeat conversation is currently busy." +msgstr "La conversación de heartbeat está ocupada en este momento." + +#: src/renderer/i18n/sharedMessages.ts +msgid "The heartbeat conversation no longer exists." +msgstr "La conversación de heartbeat ya no existe." + +#: src/renderer/i18n/sharedMessages.ts +msgid "The heartbeat conversation uses a different agent." +msgstr "La conversación de heartbeat usa un agente diferente." + #: src/renderer/components/skills/SkillsManager.tsx msgid "the Linux user" msgstr "el usuario de Linux" @@ -8972,6 +9406,14 @@ msgstr "El servidor remoto no devolvió credenciales de emparejamiento." msgid "The repository location on disk. Update it if you moved the folder." msgstr "La ubicación del repositorio en el disco. Actualízala si moviste la carpeta." +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "The run could not be cancelled." +msgstr "No se pudo cancelar la ejecución." + +#: src/renderer/i18n/sharedMessages.ts +msgid "The scheduled automation failed." +msgstr "La automatización programada falló." + #: src/renderer/components/mcp/McpServersManager.tsx #~ msgid "The selected file does not contain valid MCP server configurations." #~ msgstr "El archivo seleccionado no contiene configuraciones de servidores MCP válidas." @@ -9227,6 +9669,18 @@ msgstr "Los hilos marcados como finalizados que no se han tocado durante esta ca msgid "Time" msgstr "Hora" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Time limit" +msgstr "Límite de tiempo" + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Time limit in minutes" +msgstr "Límite de tiempo en minutos" + +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Time zone" +msgstr "Zona horaria" + #: src/renderer/components/mcp/McpServerEditor.tsx msgid "Timeout (ms)" msgstr "Tiempo de espera (ms)" @@ -9356,6 +9810,10 @@ msgstr "Panel lateral translúcido" msgid "Trending now" msgstr "Tendencias actuales" +#: src/renderer/views/SchedulesView/SchedulesView.tsx +msgid "Triage" +msgstr "Triaje" + #: src/mobile/views/DesktopsView.tsx msgid "Trust and connect" msgstr "Confiar y conectar" @@ -9598,6 +10056,10 @@ msgstr "Sin asignar" msgid "Unavailable" msgstr "No disponible" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Unavailable conversation" +msgstr "Conversación no disponible" + #: src/renderer/views/SchedulesView/ScheduleEditor.tsx msgid "Unavailable project" msgstr "Proyecto no disponible" @@ -9676,6 +10138,10 @@ msgstr "Sin fase:" msgid "Unpin" msgstr "Desanclar" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Unread" +msgstr "No leído" + #: src/mobile/views/GitActionSheet.tsx #: src/renderer/views/GitReviewOverlay/parts/GitReviewSidebar/parts/FileRow.tsx #: src/renderer/views/GitReviewOverlay/parts/GitStackedDiff.tsx @@ -10002,6 +10468,12 @@ msgstr "Esperando la autenticación de {methodName}. Los agentes detectados se a msgid "waiting for agent to stop" msgstr "esperando a que el agente se detenga" +#: src/renderer/views/SchedulesView/parts/PreviousRunsModal.tsx +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +#: src/renderer/views/SchedulesView/SchedulesView.tsx +msgid "Waiting for approval" +msgstr "Esperando aprobación" + #: src/renderer/components/thread/ChatPane/parts/items/WorkflowOverlayBody.tsx msgid "Waiting for workflow to spawn agents…" msgstr "Esperando a que el flujo de trabajo genere agentes…" @@ -10034,6 +10506,10 @@ msgstr "Preparando los entornos de shell..." msgid "Warming up WSL shell environment…" msgstr "Preparando el entorno de shell de WSL…" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Warning" +msgstr "Advertencia" + #: src/renderer/components/thread/ChatPane/parts/items/ToolCallGroup.tsx #: src/renderer/components/thread/ChatPane/parts/items/toolDisplay.ts #: src/renderer/components/thread/ChatPane/parts/items/WebSearchItem.tsx @@ -10326,6 +10802,10 @@ msgstr "Carpeta base de WSL" #~ msgid "WSL user" #~ msgstr "Usuario de WSL" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "You’re all caught up." +msgstr "Todo está al día." + #: src/renderer/views/ProfileOverlay/parts/EditProfileDialog.tsx msgid "Your name" msgstr "Tu nombre" diff --git a/src/renderer/locales/fr/messages.po b/src/renderer/locales/fr/messages.po index e0202ca50..1c321a975 100644 --- a/src/renderer/locales/fr/messages.po +++ b/src/renderer/locales/fr/messages.po @@ -288,6 +288,11 @@ msgstr "{agentLabel} : {statusLabel}. Passez la souris pour les détails du stat msgid "{agentLead} needs your input to continue." msgstr "{agentLead} a besoin de votre réponse pour continuer." +#. placeholder {0}: task.recurrence.timeZone +#: src/renderer/views/SchedulesView/SchedulesView.tsx +msgid "{cadence} in {0}" +msgstr "{cadence} dans le fuseau {0}" + #: src/mobile/views/pr/PrOverviewPage.tsx msgid "{commitsCount, plural, one {# commit} other {# commits}}" msgstr "{commitsCount, plural, one {# commit} other {# commits}}" @@ -315,6 +320,18 @@ msgstr "il y a {days} j" msgid "{envOrAgentLabel} needs authentication." msgstr "{envOrAgentLabel} nécessite une authentification." +#: src/renderer/views/SchedulesView/SchedulesView.tsx +msgid "{every, plural, one {Every day} other {Every # days}}" +msgstr "{every, plural, one {Tous les jours} other {Tous les # jours}}" + +#: src/renderer/views/SchedulesView/SchedulesView.tsx +msgid "{every, plural, one {Every hour} other {Every # hours}}" +msgstr "{every, plural, one {Toutes les heures} other {Toutes les # heures}}" + +#: src/renderer/views/SchedulesView/SchedulesView.tsx +msgid "{every, plural, one {Every minute} other {Every # minutes}}" +msgstr "{every, plural, one {Toutes les minutes} other {Toutes les # minutes}}" + #: src/mobile/views/pr/PrOverviewPage.tsx msgid "{filesCount, plural, one {# file changed} other {# files changed}}" msgstr "{filesCount, plural, one {# fichier modifié} other {# fichiers modifiés}}" @@ -491,6 +508,10 @@ msgstr "~{money}{tokens} · {0} · est." msgid "≈{0}% by reset" msgstr "≈{0}% par remise à zéro" +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "0 9 * * 1-5" +msgstr "0 9 * * 1-5" + #: src/mobile/views/ThreadsView.tsx msgid "1 thread" msgstr "1 fil" @@ -840,6 +861,10 @@ msgstr "Actions git IA" msgid "AI providers" msgstr "Fournisseurs d'IA" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "AI stop condition" +msgstr "Condition d’arrêt par l’IA" + #: src/mobile/views/MoreView.tsx #~ msgid "AI, agents, and archived threads on the paired desktop" #~ msgstr "IA, agents et fils de discussion archivés sur le bureau appairé" @@ -851,6 +876,7 @@ msgstr "Alertes lorsque les fils ont besoin de vous" #: src/renderer/commands/shortcutCatalog.ts #: src/renderer/components/skills/SkillsManager.tsx #: src/renderer/views/PullRequestsView/PullRequestsView.tsx +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx #: src/renderer/views/SchedulesView/SchedulesView.tsx #: src/renderer/views/SettingsOverlay/parts/ProfileSettings.tsx msgid "All" @@ -943,6 +969,10 @@ msgstr "Toujours exclu" msgid "An MCP server with this name already exists." msgstr "Un serveur MCP portant ce nom existe déjà." +#: src/renderer/i18n/sharedMessages.ts +msgid "Another automation is already using this conversation." +msgstr "Une autre automatisation utilise déjà cette conversation." + #: src/renderer/components/thread/ChatPane/parts/CheckpointRevertControls.tsx msgid "Another chat uses this same tree. File restore could overwrite that chat's changes." msgstr "Un autre chat utilise ce même arbre. La restauration de fichiers pourrait écraser les modifications apportées à cette discussion." @@ -1014,6 +1044,10 @@ msgstr "Archiver tout" msgid "Archive all threads" msgstr "Archiver tous les fils" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Archive finding" +msgstr "Archiver le résultat" + #: src/renderer/commands/registry.ts msgid "Archive the current thread" msgstr "Archiver le fil de discussion actuel" @@ -1028,6 +1062,10 @@ msgstr "Archiver le fil de discussion" msgid "Archive Thread" msgstr "Archiver le fil de discussion" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Archived" +msgstr "Archivés" + #: src/mobile/settingsSections.ts #: src/mobile/views/SettingsView.tsx #: src/renderer/views/SettingsOverlay/parts/ArchivedThreadsSettings.tsx @@ -1173,6 +1211,16 @@ msgstr "Afficher automatiquement le panneau de terminal" msgid "Automatically show the terminal panel when running commands or creating worktrees." msgstr "Afficher automatiquement le panneau de terminal lors de l'exécution de commandes ou de la création de worktrees." +#: src/renderer/views/SchedulesView/SchedulesView.tsx +msgid "Automation sections" +msgstr "Sections des automatisations" + +#: src/mobile/settingsSections.ts +#: src/renderer/views/MainView/parts/Sidebar/Sidebar.tsx +#: src/renderer/views/SchedulesView/SchedulesView.tsx +msgid "Automations" +msgstr "Automatisations" + #: src/renderer/components/skills/SkillImportModal.tsx msgid "Availability" msgstr "Disponibilité" @@ -1459,6 +1507,10 @@ msgstr "Contourner les règles de protection des branches (fusion des administra msgid "Cached only" msgstr "Cache uniquement" +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Calculated on desktop after saving" +msgstr "Calculé sur l’ordinateur après l’enregistrement" + #: src/mobile/QrScanner.tsx msgid "Camera access blocked" msgstr "Accès à la caméra bloqué" @@ -1513,11 +1565,16 @@ msgstr "Annuler le sélecteur" msgid "Cancel removing project" msgstr "Annuler la suppression du projet" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Cancel run" +msgstr "Annuler l’exécution" + #: src/renderer/components/thread/ChatPane/parts/items/WorkflowOverlayBody.tsx msgid "cancelled" msgstr "annulé" #: src/renderer/utils/prStatus.ts +#: src/renderer/views/SchedulesView/parts/PreviousRunsModal.tsx msgid "Cancelled" msgstr "Annulé" @@ -1706,6 +1763,10 @@ msgstr "Choisissez la langue d'affichage de l'interface de Poracode." msgid "Choose thread to attach to" msgstr "Choisissez le fil auquel attacher" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Choose what happens after a scheduled time was missed." +msgstr "Choisissez ce qui se passe lorsqu’une heure planifiée a été manquée." + #: src/renderer/views/SettingsOverlay/parts/BrowserSettings.tsx #: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts msgid "Choose whether links from Poracode and browser popups stay in Poracode or open externally." @@ -2185,6 +2246,14 @@ msgstr "terminé" msgid "Completed" msgstr "Terminé" +#: src/renderer/i18n/sharedMessages.ts +msgid "Completion evaluation failed: {detail}" +msgstr "Échec de l’évaluation de fin : {detail}" + +#: src/renderer/i18n/sharedMessages.ts +msgid "Completion evaluation is unavailable." +msgstr "L’évaluation de fin n’est pas disponible." + #: src/renderer/commands/shortcutCatalog.ts #: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx #: src/renderer/views/SettingsOverlay/parts/settingsOptions.ts @@ -2223,6 +2292,14 @@ msgstr "Computer Use activé — les actions interactives prennent le contrôle #~ msgid "Computer Use enabled for this thread" #~ msgstr "Utilisation de l'ordinateur activée pour ce fil de discussion" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Confidence" +msgstr "Confiance" + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Confidence percent" +msgstr "Pourcentage de confiance" + #: src/renderer/views/SettingsOverlay/parts/ClaudeProfileSettings.tsx msgid "Config directory" msgstr "Dossier de configuration" @@ -2386,6 +2463,14 @@ msgstr "Continuer dans un autre fournisseur" msgid "Continue in..." msgstr "Continuez dans..." +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Continue one conversation until a stop condition or limit is reached." +msgstr "Poursuivez une conversation jusqu’à ce qu’une condition d’arrêt ou une limite soit atteinte." + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Control how each scheduled run continues and stops." +msgstr "Contrôlez la poursuite et l’arrêt de chaque exécution planifiée." + #: src/renderer/views/SettingsOverlay/parts/SearchSettings.tsx msgid "Control which files appear in the @file mention search. Per-project overrides live in each project's settings." msgstr "Contrôlez quels fichiers apparaissent dans la recherche de mention @file. Les remplacements par projet sont disponibles dans les paramètres de chaque projet." @@ -2397,6 +2482,7 @@ msgstr "Contrôle le bureau associé pendant que l'agent clique ou tape" #: src/mobile/views/pr/PrConversationPage.tsx #: src/mobile/views/pr/PrOverviewPage.tsx #: src/renderer/views/PrReviewOverlay/parts/PrTabsPill.tsx +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx msgid "Conversation" msgstr "Conversation" @@ -2697,6 +2783,24 @@ msgstr "Les informations d'identification sont configurées." msgid "Credits" msgstr "Crédits" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Critical" +msgstr "Critique" + +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Cron" +msgstr "Cron" + +#. placeholder {0}: task.recurrence.expression +#. placeholder {1}: task.recurrence.timeZone +#: src/renderer/views/SchedulesView/SchedulesView.tsx +msgid "Cron {0} in {1}" +msgstr "Cron {0} dans le fuseau {1}" + +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Cron expression" +msgstr "Expression Cron" + #: src/renderer/components/skills/SkillMarketplaceModal.tsx #~ msgid "Curated free and premium skills managed by MCP Market." #~ msgstr "Skills gratuites et premium sélectionnées et gérées par MCP Market." @@ -2762,9 +2866,9 @@ msgstr "Brief quotidien" msgid "Dark" msgstr "Sombre" -#: src/renderer/views/SchedulesView/SchedulesView.tsx -#~ msgid "Days" -#~ msgstr "Jours" +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Days" +msgstr "Jours" #: src/renderer/components/thread/ThreadRuntimeRequestPanel/structuredElicitation.tsx msgid "Decline" @@ -2911,6 +3015,10 @@ msgstr "Supprimer l'arbre de travail {0}" #~ msgid "Delete:" #~ msgstr "Supprimer :" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Deleted schedule" +msgstr "Planification supprimée" + #: src/renderer/views/SettingsOverlay/parts/AcpRegistrySettings.tsx msgid "Deleting" msgstr "Suppression" @@ -2923,6 +3031,10 @@ msgstr "Refuser" msgid "Deny and tell the agent what to do differently…" msgstr "Refuser et dire à l’agent quoi faire différemment…" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Describe the result that completes this heartbeat." +msgstr "Décrivez le résultat qui termine ce heartbeat." + #: src/renderer/views/SchedulesView/ScheduleEditor.tsx msgid "Describe what the agent should do" msgstr "Décrivez ce que l'agent doit faire" @@ -2944,6 +3056,10 @@ msgstr "Point de terminaison du bureau" msgid "Desktop is unreachable." msgstr "L'ordinateur est injoignable." +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Desktop local time" +msgstr "Heure locale de l’ordinateur" + #: src/mobile/chrome.ts #: src/mobile/views/MoreView.tsx msgid "Desktop Settings" @@ -3056,6 +3172,10 @@ msgstr "Désactiver le projet" msgid "Disable Subagents" msgstr "Désactiver les sous-agents" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Disable the automation after retries are exhausted." +msgstr "Désactivez l’automatisation une fois toutes les tentatives épuisées." + #: src/renderer/views/SettingsOverlay/parts/ClaudeProfileSettings.tsx msgid "Disable tiers an external provider collapses (e.g. keep only High and Max)." msgstr "Désactivez les niveaux qu'un fournisseur externe regroupe (par ex. ne garder que High et Max)." @@ -3356,6 +3476,10 @@ msgstr "Les serveurs activés restent actifs pour les nouveaux fils de discussio msgid "Enables <0>cookies and <1>storage. Cookies can contain session tokens and storage often holds auth state — only enable when you trust both the agent and the sites it visits." msgstr "Active les <0>cookies et le <1>stockage. Les cookies peuvent contenir des jetons de session et le stockage contient souvent un état d'authentification : activez-le uniquement lorsque vous faites confiance à la fois à l'agent et aux sites qu'il visite." +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +#~ msgid "End the heartbeat after retries are exhausted." +#~ msgstr "Arrêtez le heartbeat une fois toutes les tentatives épuisées." + #: src/mobile/views/DesktopsView.tsx #: src/renderer/views/SettingsOverlay/parts/RemoteServersSettings.tsx msgid "Endpoint" @@ -3393,6 +3517,10 @@ msgstr "Saisissez un point de terminaison de bureau valide." msgid "Enter a valid HTTP or HTTPS URL." msgstr "Saisissez une URL HTTP ou HTTPS valide." +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Enter a valid schedule" +msgstr "Saisissez une planification valide" + #: src/mobile/views/DesktopsView.tsx msgid "Enter a valid SSH target and port." msgstr "Saisissez une cible SSH et un port valides." @@ -3463,6 +3591,14 @@ msgstr "Erreur" msgid "Error · Agent encountered an error" msgstr "Erreur · L'agent a rencontré une erreur" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Evaluate the result after every iteration." +msgstr "Évaluez le résultat après chaque itération." + +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Every" +msgstr "Fréquence" + #: src/renderer/views/SchedulesView/SchedulesView.tsx msgid "Every day at {time}" msgstr "Tous les jours à {time}" @@ -3485,6 +3621,14 @@ msgstr "Toutes les heures, à {0} minutes" msgid "Exclude patterns" msgstr "Exclure les motifs" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Execution" +msgstr "Exécution" + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Execution mode" +msgstr "Mode d’exécution" + #: src/renderer/components/thread/ChatPane/parts/items/toolDisplay.ts msgid "Exit plan mode" msgstr "Quitter le mode Planification" @@ -3534,6 +3678,10 @@ msgstr "Développez pour vérifier ou révoquer l’accès." msgid "Expand todo dock" msgstr "Développer le dock de tâches" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Exponential backoff" +msgstr "Délai exponentiel" + #: src/renderer/components/mcp/McpServersManager.tsx msgid "Export MCP servers" msgstr "Exporter les serveurs MCP" @@ -3716,6 +3864,10 @@ msgstr "Rechercher dans la différence" msgid "Find in terminal" msgstr "Rechercher dans le terminal" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Finding status" +msgstr "État du résultat" + #: src/renderer/views/PrReviewOverlay/parts/SubmitReviewPopover.tsx msgid "Finish your review" msgstr "Terminez votre revue" @@ -3777,6 +3929,10 @@ msgstr "Correction dans l'agent" msgid "Fixed" msgstr "Corrigé" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Fixed delay" +msgstr "Délai fixe" + #: src/renderer/commands/registry.ts msgid "Focus browser address bar" msgstr "Accéder à la barre d'adresse du navigateur" @@ -4097,6 +4253,26 @@ msgstr "Contient un brouillon non envoyé" msgid "Headers" msgstr "En-têtes" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Heartbeat" +msgstr "Heartbeat" + +#: src/renderer/i18n/sharedMessages.ts +msgid "Heartbeat automations require a native chat conversation." +msgstr "Les automatisations heartbeat nécessitent une conversation de chat native." + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Heartbeat continues this conversation in the selected project." +msgstr "Le heartbeat poursuit cette conversation dans le projet sélectionné." + +#: src/renderer/i18n/sharedMessages.ts +msgid "Heartbeat execution is unavailable." +msgstr "L’exécution heartbeat n’est pas disponible." + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Heartbeats can continue making changes while you're away. Set hard limits below." +msgstr "Les heartbeats peuvent continuer à apporter des modifications pendant votre absence. Définissez des limites strictes ci-dessous." + #: src/renderer/views/SchedulesView/SchedulesView.tsx msgid "Help me create a schedule. Ask for any missing details, then use the Poracode schedule controls to create it for me." msgstr "Aide-moi à créer une planification. Demande les détails manquants, puis utilise les contrôles de planification Poracode pour la créer." @@ -4198,6 +4374,10 @@ msgstr "host.com, alias ou utilisateur@host.com" msgid "Hourly" msgstr "Toutes les heures" +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Hours" +msgstr "Heures" + #: src/renderer/components/mcp/McpServerEditor.tsx msgid "HTTP (streamable)" msgstr "HTTP (diffusion en continu)" @@ -4328,6 +4508,14 @@ msgstr "Le scan avec la caméra dans l'app ne fonctionne qu'en HTTPS. Utilisez l msgid "Inactive" msgstr "Inactif" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Includes the first attempt." +msgstr "Inclut la première tentative." + +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Info" +msgstr "Informations" + #. Badge on an exclude pattern inherited from a lower scope #: src/renderer/views/SettingsOverlay/parts/SearchExcludeBody.tsx msgid "inherited" @@ -4338,6 +4526,14 @@ msgstr "hérité" msgid "Inheriting the global setting (currently {0})." msgstr "Hérité du paramètre global (actuellement {0})." +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Initial retry delay" +msgstr "Délai initial avant nouvelle tentative" + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Initial retry delay in seconds" +msgstr "Délai initial avant nouvelle tentative en secondes" + #: src/renderer/views/GitReviewOverlay/parts/GitReviewSidebar/GitReviewSidebar.tsx msgid "Initialize Repository" msgstr "Initialiser le dépôt" @@ -4476,6 +4672,18 @@ msgstr "Interrompue" msgid "Interrupted: agent session ended before completion." msgstr "Interrompu : la session de l'agent s'est terminée avant la fin." +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Interval" +msgstr "Intervalle" + +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Interval amount" +msgstr "Valeur de l’intervalle" + +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Interval unit" +msgstr "Unité de l’intervalle" + #: src/renderer/views/MainView/parts/RightPanel/parts/NotesPanel/NotesEditor.tsx msgid "Italic" msgstr "Italique" @@ -4560,6 +4768,14 @@ msgstr "Lancement…" msgid "Leave a comment" msgstr "Laisser un commentaire" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Leave blank for no run limit." +msgstr "Laissez ce champ vide pour ne pas limiter le nombre d’exécutions." + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +#~ msgid "Leave blank to rely on the time limit." +#~ msgstr "Laissez vide pour utiliser la limite de temps." + #: src/renderer/views/ProfileOverlay/parts/ActivityHeatmap.tsx msgid "Less" msgstr "Moins" @@ -4640,6 +4856,10 @@ msgstr "Chargement de l'éditeur…" msgid "Loading file…" msgstr "Chargement du fichier…" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Loading findings" +msgstr "Chargement des résultats" + #: src/renderer/components/skills/SkillMarketplaceModal.tsx msgid "Loading marketplace…" msgstr "Chargement de la place de marché…" @@ -4864,6 +5084,14 @@ msgstr "Marquer comme terminé" msgid "Mark as not done" msgstr "Marquer comme non terminé" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Mark as read" +msgstr "Marquer comme lu" + +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Mark as unread" +msgstr "Marquer comme non lu" + #: src/renderer/components/thread/ThreadView.tsx msgid "Mark done" msgstr "Marquer comme terminé" @@ -4904,6 +5132,22 @@ msgstr "Maximiser" msgid "Maximize browser" msgstr "Maximiser le navigateur" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Maximum attempts" +msgstr "Nombre maximal de tentatives" + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Maximum iterations" +msgstr "Nombre maximal d’itérations" + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Maximum retry delay" +msgstr "Délai maximal avant nouvelle tentative" + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Maximum retry delay in seconds" +msgstr "Délai maximal avant nouvelle tentative en secondes" + #: src/renderer/components/skills/SkillMarketplaceModal.tsx #~ msgid "MCP Market" #~ msgstr "MCP Market" @@ -5109,6 +5353,18 @@ msgstr "Réduire au panneau" msgid "Minute" msgstr "Minute" +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Minute, hour, day of month, month, and weekday." +msgstr "Minute, heure, jour du mois, mois et jour de la semaine." + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "minutes" +msgstr "minutes" + +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Minutes" +msgstr "Minutes" + #: src/mobile/views/BrowserView.tsx msgid "Mirrored desktop browser tab" msgstr "Onglet du navigateur de l'ordinateur en miroir" @@ -5117,6 +5373,10 @@ msgstr "Onglet du navigateur de l'ordinateur en miroir" msgid "Mirroring is unavailable." msgstr "La mise en miroir n'est pas disponible." +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Missed runs" +msgstr "Exécutions manquées" + #: src/renderer/views/SettingsOverlay/parts/RemoteAccessSettings.tsx msgid "Mobile push notifications" msgstr "Notifications push mobiles" @@ -5468,6 +5728,10 @@ msgstr "Correspondance suivante" msgid "Next recently viewed chat" msgstr "Chat récemment consulté suivant" +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Next run" +msgstr "Prochaine exécution" + #. placeholder {0}: dateTimeFormatter.format(new Date(task.nextRunAt)) #: src/renderer/views/SchedulesView/SchedulesView.tsx msgid "Next run {0}" @@ -5513,6 +5777,10 @@ msgstr "Aucun agent installé." msgid "No AI commits, PRs, or conflict resolutions tracked yet." msgstr "Aucun commit IA, PR ou résolution de conflit suivi pour l'instant." +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "No archived findings." +msgstr "Aucun résultat archivé." + #: src/renderer/views/SettingsOverlay/parts/ArchivedThreadsSettings.tsx msgid "No archived threads." msgstr "Aucun fil de discussion archivé." @@ -5609,6 +5877,10 @@ msgstr "Aucune différence disponible pour {0}" msgid "No diff for {visiblePath}" msgstr "Aucune différence pour {visiblePath}" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "No eligible conversations in this project." +msgstr "Aucune conversation admissible dans ce projet." + #: src/renderer/components/skills/SkillImportModal.tsx msgid "No external skills were found in this scope." msgstr "Aucune compétence externe n’a été trouvée dans cette portée." @@ -5624,6 +5896,10 @@ msgstr "Aucun point de contrôle de fichier n'est stocké pour ce message." msgid "No files match \"{0}\"." msgstr "Aucun fichier ne correspond à \"{0}\"." +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "No findings yet." +msgstr "Aucun résultat pour le moment." + #: src/renderer/views/MainView/parts/CreateProject/CloneProjectModal.tsx msgid "No GitHub CLI accounts found. Sign in with <0>gh auth login, or <1>paste a clone URL." msgstr "Aucun compte GitHub CLI trouvé. Connectez-vous avec <0>gh auth login ou <1>collez une URL de clonage." @@ -5636,6 +5912,10 @@ msgstr "Aucun historique pour l’instant" msgid "No Lightcode data was found." msgstr "Aucune donnée Lightcode n’a été trouvée." +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "No limit" +msgstr "Aucune limite" + #: src/renderer/components/skills/SkillMarketplaceModal.tsx msgid "No marketplace skills match these filters." msgstr "Aucune compétence de la place de marché ne correspond à ces filtres." @@ -5652,6 +5932,10 @@ msgstr "Aucune correspondance." msgid "No matching agents." msgstr "Aucun agent correspondant." +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "No matching findings." +msgstr "Aucun résultat correspondant." + #: src/renderer/views/PullRequestsView/PullRequestsView.tsx msgid "No matching pull requests." msgstr "Aucune pull request correspondante." @@ -5761,6 +6045,10 @@ msgstr "Aucun dépôt trouvé." msgid "No results" msgstr "Aucun résultat" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "No retries" +msgstr "Aucune nouvelle tentative" + #: src/renderer/views/SchedulesView/parts/PreviousRunsModal.tsx msgid "No runs yet." msgstr "Aucune exécution pour l'instant." @@ -5797,6 +6085,10 @@ msgstr "Aucune parole détectée." msgid "No staged changes" msgstr "Aucune modification indexée" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "No summary was provided." +msgstr "Aucun résumé n’a été fourni." + #: src/renderer/views/RemoteProjectModal/RemoteProjectModal.tsx msgid "No supported agents are installed on this remote machine. Install and sign in to an agent remotely before starting a thread." msgstr "Aucun agent compatible n’est installé sur cette machine distante. Installez un agent et connectez-vous à distance avant de démarrer un fil." @@ -5826,6 +6118,10 @@ msgstr "Aucun fil pour le moment" msgid "No threads yet." msgstr "Aucun fil pour l'instant." +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "No upcoming run" +msgstr "Aucune exécution à venir" + #: src/renderer/components/providers/usageFormat.ts msgid "No windows reported" msgstr "Aucune fenêtre signalée" @@ -6041,6 +6337,11 @@ msgstr "Ouvrir le commit sur GitHub" msgid "Open conflict resolver in" msgstr "Ouvrir le résolveur de conflits dans" +#. placeholder {0}: props.scheduleName +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Open conversation for {0}" +msgstr "Ouvrir la conversation pour {0}" + #: src/renderer/views/SettingsOverlay/parts/settingsOptions.ts msgid "Open dialog" msgstr "Ouvrir la boîte de dialogue" @@ -6676,6 +6977,10 @@ msgstr "Dossier du projet mis à jour. Rouvrez les terminaux de ce projet." msgid "Project name" msgstr "Nom du projet" +#: src/renderer/i18n/sharedMessages.ts +msgid "Project no longer exists." +msgstr "Le projet n’existe plus." + #: src/renderer/views/MainView/parts/RightPanel/parts/NotesPanel/NotesEditor.tsx msgid "Project notes" msgstr "Notes de projet" @@ -7274,6 +7579,10 @@ msgstr "Détails de la requête" msgid "requested changes" msgstr "modifications demandées" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Required confidence before stopping." +msgstr "Niveau de confiance requis avant l’arrêt." + #: src/mobile/views/pr/PrOverviewPage.tsx #: src/renderer/views/GitReviewOverlay/parts/GitReviewSidebar/parts/PrSection.tsx msgid "Required reviews, conversations, or status checks not met." @@ -7345,6 +7654,10 @@ msgstr "Restaurer le navigateur" msgid "Restore default worktree base folder" msgstr "Restaurer le dossier de base par défaut des arbres de travail" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Restore finding" +msgstr "Restaurer le résultat" + #: src/mobile/settingsSections.ts msgid "Restore or delete" msgstr "Restaurer ou supprimer" @@ -7375,10 +7688,26 @@ msgstr "Réessayer la vérification de {serverName}" msgid "Retry check" msgstr "Réessayer la vérification" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Retry delay" +msgstr "Délai avant nouvelle tentative" + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Retry delay in seconds" +msgstr "Délai avant nouvelle tentative en secondes" + #: src/mobile/components.tsx msgid "Retry now" msgstr "Réessayer maintenant" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Retry policy" +msgstr "Politique de nouvelle tentative" + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Retry when a run fails before it completes." +msgstr "Réessayez lorsqu’une exécution échoue avant de se terminer." + #: src/renderer/hooks/usePrWriteActions.ts msgid "Retry with admin" msgstr "Réessayer en tant qu'administrateur" @@ -7534,18 +7863,26 @@ msgstr "Exécutez la transcription locale sur le GPU lorsqu'elle est disponible. msgid "Run now" msgstr "Exécuter maintenant" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Run once after reopening" +msgstr "Exécuter une fois après la réouverture" + #: src/renderer/views/SchedulesView/SchedulesView.tsx #~ msgid "Run standalone tasks on this device without a project." #~ msgstr "Exécutez des tâches autonomes sur cet appareil sans projet." #: src/renderer/views/SchedulesView/SchedulesView.tsx -msgid "Run standalone tasks on this device. Schedules run while the device is awake and Poracode is open." -msgstr "Exécutez des tâches autonomes sur cet appareil. Les planifications s'exécutent tant que l'appareil est actif et que Poracode est ouvert." +#~ msgid "Run standalone tasks on this device. Schedules run while the device is awake and Poracode is open." +#~ msgstr "Exécutez des tâches autonomes sur cet appareil. Les planifications s'exécutent tant que l'appareil est actif et que Poracode est ouvert." #: src/renderer/commands/registry.ts msgid "Run Terminal Command" msgstr "Exécuter la commande du terminal" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Run the latest missed run" +msgstr "Exécuter la dernière occurrence manquée" + #: src/renderer/views/SchedulesView/ScheduleEditor.tsx #~ msgid "Run this schedule automatically at the times above." #~ msgstr "Exécuter cette planification automatiquement aux heures indiquées ci-dessus." @@ -7561,6 +7898,7 @@ msgstr "en cours d'exécution" #: src/renderer/utils/prStatus.ts #: src/renderer/views/SchedulesView/parts/PreviousRunsModal.tsx +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx msgid "Running" msgstr "En cours d'exécution" @@ -7584,6 +7922,10 @@ msgstr "S'épuise tôt" msgid "Runs out in {runOut}" msgstr "S'épuise dans {runOut}" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Runs that need attention will appear here." +msgstr "Les exécutions qui nécessitent votre attention apparaîtront ici." + #: src/renderer/views/MainView/parts/CreateProject/CloneProjectModal.tsx #: src/renderer/views/MainView/parts/CreateProject/CreateProjectModal.tsx msgid "Runtime" @@ -7660,6 +8002,10 @@ msgstr "Analyse de Windows et WSL pour les CLI installées. Cela prend général msgid "Scanning your system for installed CLIs. This usually takes a couple of seconds." msgstr "Analyse de votre système pour les CLI installées. Cela prend généralement quelques secondes." +#: src/renderer/views/SchedulesView/SchedulesView.tsx +msgid "Schedule autonomous work and review results that need your attention. Automations run while this device is awake and Poracode is open." +msgstr "Planifiez du travail autonome et consultez les résultats qui nécessitent votre attention. Les automatisations s’exécutent tant que cet appareil est actif et que Poracode est ouvert." + #: src/renderer/views/SchedulesView/ScheduleEditor.tsx msgid "Schedule name" msgstr "Nom de la planification" @@ -7668,20 +8014,31 @@ msgstr "Nom de la planification" msgid "Schedule status" msgstr "État de la planification" +#: src/renderer/i18n/sharedMessages.ts +msgid "Scheduled retry was cancelled." +msgstr "La nouvelle tentative planifiée a été annulée." + +#: src/renderer/i18n/sharedMessages.ts +msgid "Scheduled task was deleted before retrying." +msgstr "La tâche planifiée a été supprimée avant la nouvelle tentative." + #: src/renderer/views/SchedulesView/SchedulesView.tsx -msgid "Scheduled tasks" -msgstr "Tâches planifiées" +#~ msgid "Scheduled tasks" +#~ msgstr "Tâches planifiées" #: src/mobile/settingsSections.ts -msgid "Scheduled tasks on this desktop" -msgstr "Tâches planifiées sur cet ordinateur" +#~ msgid "Scheduled tasks on this desktop" +#~ msgstr "Tâches planifiées sur cet ordinateur" #: src/renderer/views/SchedulesView/SchedulesView.tsx #~ msgid "Scheduled tasks run only while this device is awake and Poracode is open." #~ msgstr "Les tâches planifiées ne s’exécutent que lorsque cet appareil est actif et que Poracode est ouvert." #: src/mobile/settingsSections.ts -#: src/renderer/views/MainView/parts/Sidebar/Sidebar.tsx +msgid "Scheduled work and triage on this desktop" +msgstr "Travail planifié et triage sur cet ordinateur" + +#: src/renderer/views/SchedulesView/SchedulesView.tsx msgid "Schedules" msgstr "Planifications" @@ -7736,6 +8093,10 @@ msgstr "Rechercher des branches..." msgid "Search files" msgstr "Rechercher des fichiers" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Search findings" +msgstr "Rechercher dans les résultats" + #: src/renderer/components/skills/SkillMarketplaceModal.tsx msgid "Search marketplace skills" msgstr "Rechercher des compétences sur la place de marché" @@ -7830,6 +8191,10 @@ msgstr "Recherche..." msgid "Searching…" msgstr "Recherche…" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "seconds" +msgstr "secondes" + #: src/renderer/components/skills/SkillMarketplaceModal.tsx #~ msgid "Security-focused directory with verified skill metadata." #~ msgstr "Annuaire axé sur la sécurité avec des métadonnées de skills vérifiées." @@ -8220,6 +8585,10 @@ msgstr "Déconnexion {env}. Les agents détectés seront actualisés une fois l' msgid "Signing out. Detected agents will refresh when it finishes." msgstr "Déconnexion. Les agents détectés seront actualisés une fois l'opération terminée." +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Single pass" +msgstr "Exécution unique" + #: src/renderer/components/skills/SkillImportModal.tsx #: src/renderer/components/skills/SkillMarketplaceModal.tsx msgid "Skill availability" @@ -8284,7 +8653,12 @@ msgstr "Place de marché des compétences" msgid "Skills.sh" msgstr "Skills.sh" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Skip missed runs" +msgstr "Ignorer les exécutions manquées" + #: src/renderer/utils/prStatus.ts +#: src/renderer/views/SchedulesView/parts/PreviousRunsModal.tsx msgid "Skipped" msgstr "Ignoré" @@ -8423,6 +8797,10 @@ msgstr "Lancez {appName} pour voir l'utilisation" msgid "Start a dev server on your desktop, then tap refresh." msgstr "Démarrez un serveur de développement sur votre bureau, puis appuyez sur actualiser." +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Start a new conversation for each run." +msgstr "Démarrez une nouvelle conversation pour chaque exécution." + #: src/renderer/commands/registry.ts msgid "Start a new thread as panel instead of page" msgstr "Démarrer un nouveau fil de discussion en tant que panneau plutôt qu'en tant que page" @@ -8561,6 +8939,10 @@ msgstr "Arrêter" msgid "Stop forwarding" msgstr "Arrêter le transfert" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Stop on error" +msgstr "Arrêter en cas d’erreur" + #: src/renderer/components/thread/ThreadComposer.tsx msgid "Stop response" msgstr "Arrêter la réponse" @@ -8573,10 +8955,18 @@ msgstr "Arrêter la tâche" msgid "Stop the project's running threads before changing its folder." msgstr "Arrêtez les fils de discussion en cours du projet avant de changer son dossier." +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Stop the run when this total time is reached." +msgstr "Arrêtez l’exécution lorsque cette durée totale est atteinte." + #: src/renderer/components/composer/VoiceInputButton.tsx msgid "Stop voice input" msgstr "Arrêter la saisie vocale" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Stop when" +msgstr "Arrêter lorsque" + #: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts #: src/renderer/views/SettingsOverlay/parts/WorktreeSettings.tsx msgid "Storage location" @@ -8921,6 +9311,22 @@ msgstr "L'agent" msgid "the app" msgstr "l'application" +#: src/renderer/i18n/sharedMessages.ts +msgid "The automation conversation exited before the turn completed." +msgstr "La conversation d’automatisation s’est fermée avant la fin du tour." + +#: src/renderer/i18n/sharedMessages.ts +msgid "The automation exceeded its time limit." +msgstr "L’automatisation a dépassé sa limite de temps." + +#: src/renderer/i18n/sharedMessages.ts +msgid "The automation needs a reply before it can continue." +msgstr "L’automatisation a besoin d’une réponse avant de pouvoir continuer." + +#: src/renderer/i18n/sharedMessages.ts +msgid "The automation needs approval before it can continue." +msgstr "L’automatisation a besoin d’une approbation avant de pouvoir continuer." + #: src/renderer/views/MainView/parts/CreateProject/CloneProjectModal.tsx msgid "the chosen folder" msgstr "le dossier choisi" @@ -8934,11 +9340,39 @@ msgstr "La cadence de rafraîchissement en arrière-plan par défaut, utilisée msgid "The desktop server is still coming online." msgstr "Le serveur du bureau est encore en cours de démarrage." +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "The finding is no longer available." +msgstr "Le résultat n’est plus disponible." + #. placeholder {0}: createTarget.wslDistro #: src/renderer/components/skills/SkillsManager.tsx msgid "the global {0} WSL scope" msgstr "la portée WSL globale de {0}" +#: src/renderer/i18n/sharedMessages.ts +msgid "The heartbeat conversation belongs to a different project." +msgstr "La conversation heartbeat appartient à un autre projet." + +#: src/renderer/i18n/sharedMessages.ts +msgid "The heartbeat conversation cannot be resumed." +msgstr "La conversation heartbeat ne peut pas être reprise." + +#: src/renderer/i18n/sharedMessages.ts +msgid "The heartbeat conversation is archived." +msgstr "La conversation Heartbeat est archivée." + +#: src/renderer/i18n/sharedMessages.ts +msgid "The heartbeat conversation is currently busy." +msgstr "La conversation heartbeat est actuellement occupée." + +#: src/renderer/i18n/sharedMessages.ts +msgid "The heartbeat conversation no longer exists." +msgstr "La conversation heartbeat n’existe plus." + +#: src/renderer/i18n/sharedMessages.ts +msgid "The heartbeat conversation uses a different agent." +msgstr "La conversation heartbeat utilise un autre agent." + #: src/renderer/components/skills/SkillsManager.tsx msgid "the Linux user" msgstr "l’utilisateur Linux" @@ -8971,6 +9405,14 @@ msgstr "Le serveur distant n’a renvoyé aucun identifiant d’association." msgid "The repository location on disk. Update it if you moved the folder." msgstr "L'emplacement du dépôt sur le disque. Mettez-le à jour si vous avez déplacé le dossier." +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "The run could not be cancelled." +msgstr "L’exécution n’a pas pu être annulée." + +#: src/renderer/i18n/sharedMessages.ts +msgid "The scheduled automation failed." +msgstr "L’automatisation planifiée a échoué." + #: src/renderer/components/mcp/McpServersManager.tsx #~ msgid "The selected file does not contain valid MCP server configurations." #~ msgstr "Le fichier sélectionné ne contient aucune configuration de serveur MCP valide." @@ -9226,6 +9668,18 @@ msgstr "Les fils de discussion marqués comme terminés qui n'ont pas été modi msgid "Time" msgstr "Heure" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Time limit" +msgstr "Limite de temps" + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Time limit in minutes" +msgstr "Limite de temps en minutes" + +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Time zone" +msgstr "Fuseau horaire" + #: src/renderer/components/mcp/McpServerEditor.tsx msgid "Timeout (ms)" msgstr "Délai d’expiration (ms)" @@ -9355,6 +9809,10 @@ msgstr "Barre latérale translucide" msgid "Trending now" msgstr "Tendances actuelles" +#: src/renderer/views/SchedulesView/SchedulesView.tsx +msgid "Triage" +msgstr "Triage" + #: src/mobile/views/DesktopsView.tsx msgid "Trust and connect" msgstr "Faire confiance et se connecter" @@ -9597,6 +10055,10 @@ msgstr "Non attribué" msgid "Unavailable" msgstr "Indisponible" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Unavailable conversation" +msgstr "Conversation indisponible" + #: src/renderer/views/SchedulesView/ScheduleEditor.tsx msgid "Unavailable project" msgstr "Projet indisponible" @@ -9675,6 +10137,10 @@ msgstr "Sans phase :" msgid "Unpin" msgstr "Désépingler" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Unread" +msgstr "Non lu" + #: src/mobile/views/GitActionSheet.tsx #: src/renderer/views/GitReviewOverlay/parts/GitReviewSidebar/parts/FileRow.tsx #: src/renderer/views/GitReviewOverlay/parts/GitStackedDiff.tsx @@ -10001,6 +10467,12 @@ msgstr "En attente de l'authentification {methodName}. Les agents détectés ser msgid "waiting for agent to stop" msgstr "en attente de l'arrêt de l'agent" +#: src/renderer/views/SchedulesView/parts/PreviousRunsModal.tsx +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +#: src/renderer/views/SchedulesView/SchedulesView.tsx +msgid "Waiting for approval" +msgstr "En attente d’approbation" + #: src/renderer/components/thread/ChatPane/parts/items/WorkflowOverlayBody.tsx msgid "Waiting for workflow to spawn agents…" msgstr "En attente que le flux de travail génère des agents…" @@ -10033,6 +10505,10 @@ msgstr "Préparation des environnements shell…" msgid "Warming up WSL shell environment…" msgstr "Préparation de l'environnement shell WSL…" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Warning" +msgstr "Avertissement" + #: src/renderer/components/thread/ChatPane/parts/items/ToolCallGroup.tsx #: src/renderer/components/thread/ChatPane/parts/items/toolDisplay.ts #: src/renderer/components/thread/ChatPane/parts/items/WebSearchItem.tsx @@ -10325,6 +10801,10 @@ msgstr "Dossier de base WSL" #~ msgid "WSL user" #~ msgstr "Utilisateur WSL" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "You’re all caught up." +msgstr "Vous êtes à jour." + #: src/renderer/views/ProfileOverlay/parts/EditProfileDialog.tsx msgid "Your name" msgstr "Votre nom" diff --git a/src/renderer/locales/ja/messages.po b/src/renderer/locales/ja/messages.po index f3a43bac8..a9bd7544d 100644 --- a/src/renderer/locales/ja/messages.po +++ b/src/renderer/locales/ja/messages.po @@ -288,6 +288,11 @@ msgstr "{agentLabel}:{statusLabel}。マウスを移動するとステータス msgid "{agentLead} needs your input to continue." msgstr "{agentLead}が続行するには入力が必要です。" +#. placeholder {0}: task.recurrence.timeZone +#: src/renderer/views/SchedulesView/SchedulesView.tsx +msgid "{cadence} in {0}" +msgstr "{cadence}({0})" + #: src/mobile/views/pr/PrOverviewPage.tsx msgid "{commitsCount, plural, one {# commit} other {# commits}}" msgstr "{commitsCount, plural, one {# 件のコミット} other {# 件のコミット}}" @@ -315,6 +320,18 @@ msgstr "{days}日前" msgid "{envOrAgentLabel} needs authentication." msgstr "{envOrAgentLabel}には認証が必要です。" +#: src/renderer/views/SchedulesView/SchedulesView.tsx +msgid "{every, plural, one {Every day} other {Every # days}}" +msgstr "{every, plural, one {毎日} other {#日ごと}}" + +#: src/renderer/views/SchedulesView/SchedulesView.tsx +msgid "{every, plural, one {Every hour} other {Every # hours}}" +msgstr "{every, plural, one {毎時} other {#時間ごと}}" + +#: src/renderer/views/SchedulesView/SchedulesView.tsx +msgid "{every, plural, one {Every minute} other {Every # minutes}}" +msgstr "{every, plural, one {毎分} other {#分ごと}}" + #: src/mobile/views/pr/PrOverviewPage.tsx msgid "{filesCount, plural, one {# file changed} other {# files changed}}" msgstr "{filesCount, plural, one {# 件のファイルを変更} other {# 件のファイルを変更}}" @@ -490,6 +507,10 @@ msgstr "~{money}{tokens}·{0}· 推定。" msgid "≈{0}% by reset" msgstr "≈{0}% (リセットまでに)" +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "0 9 * * 1-5" +msgstr "0 9 * * 1-5" + #: src/mobile/views/ThreadsView.tsx msgid "1 thread" msgstr "1 件のスレッド" @@ -839,6 +860,10 @@ msgstr "AIによるgit操作" msgid "AI providers" msgstr "AI プロバイダー" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "AI stop condition" +msgstr "AIによる停止条件" + #: src/mobile/views/MoreView.tsx #~ msgid "AI, agents, and archived threads on the paired desktop" #~ msgstr "ペアリング済みデスクトップ上の AI、エージェント、アーカイブ済みスレッド" @@ -850,6 +875,7 @@ msgstr "スレッドが対応を必要としたら通知" #: src/renderer/commands/shortcutCatalog.ts #: src/renderer/components/skills/SkillsManager.tsx #: src/renderer/views/PullRequestsView/PullRequestsView.tsx +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx #: src/renderer/views/SchedulesView/SchedulesView.tsx #: src/renderer/views/SettingsOverlay/parts/ProfileSettings.tsx msgid "All" @@ -942,6 +968,10 @@ msgstr "常に除外される" msgid "An MCP server with this name already exists." msgstr "この名前のMCPサーバーはすでに存在します。" +#: src/renderer/i18n/sharedMessages.ts +msgid "Another automation is already using this conversation." +msgstr "別の自動化がこの会話をすでに使用しています。" + #: src/renderer/components/thread/ChatPane/parts/CheckpointRevertControls.tsx msgid "Another chat uses this same tree. File restore could overwrite that chat's changes." msgstr "別のチャットはこれと同じツリーを使用します。ファイルを復元すると、チャットの変更が上書きされる可能性があります。" @@ -1013,6 +1043,10 @@ msgstr "すべてをアーカイブする" msgid "Archive all threads" msgstr "すべてのスレッドをアーカイブ" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Archive finding" +msgstr "検出結果をアーカイブ" + #: src/renderer/commands/registry.ts msgid "Archive the current thread" msgstr "現在のスレッドをアーカイブ" @@ -1027,6 +1061,10 @@ msgstr "スレッドをアーカイブ" msgid "Archive Thread" msgstr "アーカイブスレッド" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Archived" +msgstr "アーカイブ済み" + #: src/mobile/settingsSections.ts #: src/mobile/views/SettingsView.tsx #: src/renderer/views/SettingsOverlay/parts/ArchivedThreadsSettings.tsx @@ -1172,6 +1210,16 @@ msgstr "端末パネルの自動表示" msgid "Automatically show the terminal panel when running commands or creating worktrees." msgstr "コマンドの実行時またはワークツリーの作成時に、端末パネルを自動的に表示します。" +#: src/renderer/views/SchedulesView/SchedulesView.tsx +msgid "Automation sections" +msgstr "自動化セクション" + +#: src/mobile/settingsSections.ts +#: src/renderer/views/MainView/parts/Sidebar/Sidebar.tsx +#: src/renderer/views/SchedulesView/SchedulesView.tsx +msgid "Automations" +msgstr "自動化" + #: src/renderer/components/skills/SkillImportModal.tsx msgid "Availability" msgstr "利用範囲" @@ -1458,6 +1506,10 @@ msgstr "ブランチ保護ルールをバイパスする (管理マージ)" msgid "Cached only" msgstr "キャッシュのみ" +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Calculated on desktop after saving" +msgstr "保存後にデスクトップで計算されます" + #: src/mobile/QrScanner.tsx msgid "Camera access blocked" msgstr "カメラアクセスがブロックされています" @@ -1512,11 +1564,16 @@ msgstr "ピッカーのキャンセル" msgid "Cancel removing project" msgstr "プロジェクトの削除をキャンセル" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Cancel run" +msgstr "実行をキャンセル" + #: src/renderer/components/thread/ChatPane/parts/items/WorkflowOverlayBody.tsx msgid "cancelled" msgstr "キャンセルされました" #: src/renderer/utils/prStatus.ts +#: src/renderer/views/SchedulesView/parts/PreviousRunsModal.tsx msgid "Cancelled" msgstr "キャンセル済み" @@ -1705,6 +1762,10 @@ msgstr "Poracode のインターフェースの表示言語を選択します。 msgid "Choose thread to attach to" msgstr "接続するスレッドを選択してください" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Choose what happens after a scheduled time was missed." +msgstr "スケジュール時刻を逃した場合の動作を選択します。" + #: src/renderer/views/SettingsOverlay/parts/BrowserSettings.tsx #: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts msgid "Choose whether links from Poracode and browser popups stay in Poracode or open externally." @@ -2184,6 +2245,14 @@ msgstr "完了しました" msgid "Completed" msgstr "完了" +#: src/renderer/i18n/sharedMessages.ts +msgid "Completion evaluation failed: {detail}" +msgstr "完了評価に失敗しました: {detail}" + +#: src/renderer/i18n/sharedMessages.ts +msgid "Completion evaluation is unavailable." +msgstr "完了評価を利用できません。" + #: src/renderer/commands/shortcutCatalog.ts #: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx #: src/renderer/views/SettingsOverlay/parts/settingsOptions.ts @@ -2222,6 +2291,14 @@ msgstr "Computer Use が有効です — インタラクティブ操作はデス #~ msgid "Computer Use enabled for this thread" #~ msgstr "このスレッドに対してコンピュータ操作が有効になっています" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Confidence" +msgstr "信頼度" + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Confidence percent" +msgstr "信頼度(パーセント)" + #: src/renderer/views/SettingsOverlay/parts/ClaudeProfileSettings.tsx msgid "Config directory" msgstr "設定ディレクトリ" @@ -2385,6 +2462,14 @@ msgstr "別のプロバイダーで続行する" msgid "Continue in..." msgstr "...で続行" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Continue one conversation until a stop condition or limit is reached." +msgstr "停止条件または上限に達するまで、1つの会話を継続します。" + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Control how each scheduled run continues and stops." +msgstr "各スケジュール実行の継続方法と停止方法を設定します。" + #: src/renderer/views/SettingsOverlay/parts/SearchSettings.tsx msgid "Control which files appear in the @file mention search. Per-project overrides live in each project's settings." msgstr "@file メンション検索に表示されるファイルを制御します。プロジェクトごとのオーバーライドは、各プロジェクトの設定に反映されます。" @@ -2396,6 +2481,7 @@ msgstr "エージェントがクリックや入力をしている間、ペアリ #: src/mobile/views/pr/PrConversationPage.tsx #: src/mobile/views/pr/PrOverviewPage.tsx #: src/renderer/views/PrReviewOverlay/parts/PrTabsPill.tsx +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx msgid "Conversation" msgstr "会話" @@ -2696,6 +2782,24 @@ msgstr "資格情報が設定されています。" msgid "Credits" msgstr "クレジット" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Critical" +msgstr "重大" + +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Cron" +msgstr "Cron" + +#. placeholder {0}: task.recurrence.expression +#. placeholder {1}: task.recurrence.timeZone +#: src/renderer/views/SchedulesView/SchedulesView.tsx +msgid "Cron {0} in {1}" +msgstr "Cron {0}({1})" + +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Cron expression" +msgstr "Cron 式" + #: src/renderer/components/skills/SkillMarketplaceModal.tsx #~ msgid "Curated free and premium skills managed by MCP Market." #~ msgstr "MCP Market が管理する厳選された無料およびプレミアムスキル。" @@ -2761,9 +2865,9 @@ msgstr "デイリーブリーフ" msgid "Dark" msgstr "ダーク" -#: src/renderer/views/SchedulesView/SchedulesView.tsx -#~ msgid "Days" -#~ msgstr "曜日" +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Days" +msgstr "曜日" #: src/renderer/components/thread/ThreadRuntimeRequestPanel/structuredElicitation.tsx msgid "Decline" @@ -2910,6 +3014,10 @@ msgstr "ワークツリー{0}を削除します" #~ msgid "Delete:" #~ msgstr "削除:" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Deleted schedule" +msgstr "削除されたスケジュール" + #: src/renderer/views/SettingsOverlay/parts/AcpRegistrySettings.tsx msgid "Deleting" msgstr "削除中" @@ -2922,6 +3030,10 @@ msgstr "拒否する" msgid "Deny and tell the agent what to do differently…" msgstr "拒否し、エージェントに別の対処法を伝えます..." +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Describe the result that completes this heartbeat." +msgstr "このハートビートを完了する結果を記述します。" + #: src/renderer/views/SchedulesView/ScheduleEditor.tsx msgid "Describe what the agent should do" msgstr "エージェントに実行してほしい内容を説明してください" @@ -2943,6 +3055,10 @@ msgstr "デスクトップエンドポイント" msgid "Desktop is unreachable." msgstr "デスクトップに到達できません。" +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Desktop local time" +msgstr "デスクトップのローカル時刻" + #: src/mobile/chrome.ts #: src/mobile/views/MoreView.tsx msgid "Desktop Settings" @@ -3055,6 +3171,10 @@ msgstr "プロジェクトを無効にする" msgid "Disable Subagents" msgstr "サブエージェントを無効にする" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Disable the automation after retries are exhausted." +msgstr "再試行をすべて使い切った後にオートメーションを無効にします。" + #: src/renderer/views/SettingsOverlay/parts/ClaudeProfileSettings.tsx msgid "Disable tiers an external provider collapses (e.g. keep only High and Max)." msgstr "外部プロバイダーがまとめてしまうレベルを無効化します(例:HighとMaxのみを残す)。" @@ -3355,6 +3475,10 @@ msgstr "有効なサーバーは新しいスレッドでも有効なままです msgid "Enables <0>cookies and <1>storage. Cookies can contain session tokens and storage often holds auth state — only enable when you trust both the agent and the sites it visits." msgstr "<0>Cookie と <1>ストレージ を有効にします。Cookie にはセッション トークンが含まれることがあり、ストレージには認証状態が保持されることが多いため、エージェントとエージェントが訪問するサイトの両方を信頼できる場合にのみ有効にしてください。" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +#~ msgid "End the heartbeat after retries are exhausted." +#~ msgstr "再試行を使い切ったらハートビートを終了します。" + #: src/mobile/views/DesktopsView.tsx #: src/renderer/views/SettingsOverlay/parts/RemoteServersSettings.tsx msgid "Endpoint" @@ -3392,6 +3516,10 @@ msgstr "有効なデスクトップエンドポイントを入力してくださ msgid "Enter a valid HTTP or HTTPS URL." msgstr "有効なHTTPまたはHTTPSのURLを入力してください。" +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Enter a valid schedule" +msgstr "有効なスケジュールを入力してください" + #: src/mobile/views/DesktopsView.tsx msgid "Enter a valid SSH target and port." msgstr "有効な SSH 接続先とポートを入力してください。" @@ -3462,6 +3590,14 @@ msgstr "エラー" msgid "Error · Agent encountered an error" msgstr "エラー · エージェントでエラーが発生しました" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Evaluate the result after every iteration." +msgstr "各反復の後に結果を評価します。" + +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Every" +msgstr "間隔" + #: src/renderer/views/SchedulesView/SchedulesView.tsx msgid "Every day at {time}" msgstr "毎日{time}" @@ -3484,6 +3620,14 @@ msgstr "毎時{0}分" msgid "Exclude patterns" msgstr "パターンを除外する" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Execution" +msgstr "実行" + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Execution mode" +msgstr "実行モード" + #: src/renderer/components/thread/ChatPane/parts/items/toolDisplay.ts msgid "Exit plan mode" msgstr "計画モードを終了する" @@ -3533,6 +3677,10 @@ msgstr "展開してアクセスを確認または取り消します。" msgid "Expand todo dock" msgstr "Todo ドックを展開する" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Exponential backoff" +msgstr "指数バックオフ" + #: src/renderer/components/mcp/McpServersManager.tsx msgid "Export MCP servers" msgstr "MCPサーバーをエクスポート" @@ -3715,6 +3863,10 @@ msgstr "差分内を検索" msgid "Find in terminal" msgstr "ターミナル内を検索" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Finding status" +msgstr "検出結果の状態" + #: src/renderer/views/PrReviewOverlay/parts/SubmitReviewPopover.tsx msgid "Finish your review" msgstr "レビューを完了する" @@ -3776,6 +3928,10 @@ msgstr "エージェントで修正する" msgid "Fixed" msgstr "修正" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Fixed delay" +msgstr "固定遅延" + #: src/renderer/commands/registry.ts msgid "Focus browser address bar" msgstr "ブラウザのアドレスバーをフォーカス" @@ -4096,6 +4252,26 @@ msgstr "未送信の下書きがあります" msgid "Headers" msgstr "ヘッダー" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Heartbeat" +msgstr "ハートビート" + +#: src/renderer/i18n/sharedMessages.ts +msgid "Heartbeat automations require a native chat conversation." +msgstr "ハートビートの自動化にはネイティブチャットの会話が必要です。" + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Heartbeat continues this conversation in the selected project." +msgstr "ハートビートは選択したプロジェクトでこの会話を継続します。" + +#: src/renderer/i18n/sharedMessages.ts +msgid "Heartbeat execution is unavailable." +msgstr "ハートビートを実行できません。" + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Heartbeats can continue making changes while you're away. Set hard limits below." +msgstr "離席中もハートビートが変更を続ける場合があります。以下で厳格な上限を設定してください。" + #: src/renderer/views/SchedulesView/SchedulesView.tsx msgid "Help me create a schedule. Ask for any missing details, then use the Poracode schedule controls to create it for me." msgstr "スケジュール作成を手伝ってください。不足している詳細を確認し、Poracodeのスケジュール操作を使って作成してください。" @@ -4197,6 +4373,10 @@ msgstr "host.com、エイリアス、または user@host.com" msgid "Hourly" msgstr "毎時" +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Hours" +msgstr "時間" + #: src/renderer/components/mcp/McpServerEditor.tsx msgid "HTTP (streamable)" msgstr "HTTP(ストリーミング対応)" @@ -4327,6 +4507,14 @@ msgstr "アプリ内のカメラスキャンは HTTPS でのみ動作します msgid "Inactive" msgstr "非アクティブ" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Includes the first attempt." +msgstr "最初の試行を含みます。" + +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Info" +msgstr "情報" + #. Badge on an exclude pattern inherited from a lower scope #: src/renderer/views/SettingsOverlay/parts/SearchExcludeBody.tsx msgid "inherited" @@ -4337,6 +4525,14 @@ msgstr "継承された" msgid "Inheriting the global setting (currently {0})." msgstr "グローバル設定 (現在{0}) を継承します。" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Initial retry delay" +msgstr "初回の再試行遅延" + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Initial retry delay in seconds" +msgstr "初回の再試行遅延(秒)" + #: src/renderer/views/GitReviewOverlay/parts/GitReviewSidebar/GitReviewSidebar.tsx msgid "Initialize Repository" msgstr "リポジトリの初期化" @@ -4475,6 +4671,18 @@ msgstr "中断" msgid "Interrupted: agent session ended before completion." msgstr "中断されました: エージェントセッションが完了前に終了しました。" +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Interval" +msgstr "間隔" + +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Interval amount" +msgstr "間隔の値" + +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Interval unit" +msgstr "間隔の単位" + #: src/renderer/views/MainView/parts/RightPanel/parts/NotesPanel/NotesEditor.tsx msgid "Italic" msgstr "イタリック体" @@ -4559,6 +4767,14 @@ msgstr "起動中…" msgid "Leave a comment" msgstr "コメントを残す" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Leave blank for no run limit." +msgstr "実行回数を制限しない場合は空欄にします。" + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +#~ msgid "Leave blank to rely on the time limit." +#~ msgstr "空欄にすると時間制限のみが適用されます。" + #: src/renderer/views/ProfileOverlay/parts/ActivityHeatmap.tsx msgid "Less" msgstr "少ない" @@ -4639,6 +4855,10 @@ msgstr "エディターを読み込み中…" msgid "Loading file…" msgstr "ファイルをロード中…" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Loading findings" +msgstr "検出結果を読み込み中" + #: src/renderer/components/skills/SkillMarketplaceModal.tsx msgid "Loading marketplace…" msgstr "マーケットプレイスを読み込み中…" @@ -4863,6 +5083,14 @@ msgstr "完了としてマークする" msgid "Mark as not done" msgstr "未完了としてマークする" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Mark as read" +msgstr "既読にする" + +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Mark as unread" +msgstr "未読にする" + #: src/renderer/components/thread/ThreadView.tsx msgid "Mark done" msgstr "完了マークを付ける" @@ -4903,6 +5131,22 @@ msgstr "最大化する" msgid "Maximize browser" msgstr "ブラウザを最大化する" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Maximum attempts" +msgstr "最大試行回数" + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Maximum iterations" +msgstr "最大反復回数" + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Maximum retry delay" +msgstr "最大再試行遅延" + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Maximum retry delay in seconds" +msgstr "最大再試行遅延(秒)" + #: src/renderer/components/skills/SkillMarketplaceModal.tsx #~ msgid "MCP Market" #~ msgstr "MCP Market" @@ -5108,6 +5352,18 @@ msgstr "パネルに最小化する" msgid "Minute" msgstr "分" +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Minute, hour, day of month, month, and weekday." +msgstr "分、時、日、月、曜日。" + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "minutes" +msgstr "分" + +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Minutes" +msgstr "分" + #: src/mobile/views/BrowserView.tsx msgid "Mirrored desktop browser tab" msgstr "ミラーされたデスクトップブラウザタブ" @@ -5116,6 +5372,10 @@ msgstr "ミラーされたデスクトップブラウザタブ" msgid "Mirroring is unavailable." msgstr "ミラーリングは利用できません。" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Missed runs" +msgstr "実行できなかった回" + #: src/renderer/views/SettingsOverlay/parts/RemoteAccessSettings.tsx msgid "Mobile push notifications" msgstr "モバイルプッシュ通知" @@ -5467,6 +5727,10 @@ msgstr "次の一致" msgid "Next recently viewed chat" msgstr "次の最近表示したチャット" +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Next run" +msgstr "次回の実行" + #. placeholder {0}: dateTimeFormatter.format(new Date(task.nextRunAt)) #: src/renderer/views/SchedulesView/SchedulesView.tsx msgid "Next run {0}" @@ -5512,6 +5776,10 @@ msgstr "エージェントがインストールされていません。" msgid "No AI commits, PRs, or conflict resolutions tracked yet." msgstr "AIによるコミット、PR、競合解決はまだ記録されていません。" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "No archived findings." +msgstr "アーカイブ済みの検出結果はありません。" + #: src/renderer/views/SettingsOverlay/parts/ArchivedThreadsSettings.tsx msgid "No archived threads." msgstr "アーカイブされたスレッドはありません。" @@ -5608,6 +5876,10 @@ msgstr "{0}に利用できる差分はありません" msgid "No diff for {visiblePath}" msgstr "{visiblePath}の差分はありません" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "No eligible conversations in this project." +msgstr "このプロジェクトには対象となる会話がありません。" + #: src/renderer/components/skills/SkillImportModal.tsx msgid "No external skills were found in this scope." msgstr "このスコープには外部スキルが見つかりませんでした。" @@ -5623,6 +5895,10 @@ msgstr "このメッセージにはファイル チェックポイントは保 msgid "No files match \"{0}\"." msgstr "「{0}」に一致するファイルはありません。" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "No findings yet." +msgstr "検出結果はまだありません。" + #: src/renderer/views/MainView/parts/CreateProject/CloneProjectModal.tsx msgid "No GitHub CLI accounts found. Sign in with <0>gh auth login, or <1>paste a clone URL." msgstr "GitHub CLI アカウントが見つかりません。 <0>gh auth loginでサインインするか、<1>クローン URL を貼り付けます。" @@ -5635,6 +5911,10 @@ msgstr "履歴はまだありません" msgid "No Lightcode data was found." msgstr "Lightcode データが見つかりませんでした。" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "No limit" +msgstr "制限なし" + #: src/renderer/components/skills/SkillMarketplaceModal.tsx msgid "No marketplace skills match these filters." msgstr "これらのフィルターに一致するマーケットプレイススキルはありません。" @@ -5651,6 +5931,10 @@ msgstr "一致はありません。" msgid "No matching agents." msgstr "一致するエージェントはありません。" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "No matching findings." +msgstr "一致する検出結果はありません。" + #: src/renderer/views/PullRequestsView/PullRequestsView.tsx msgid "No matching pull requests." msgstr "条件に一致するプルリクエストはありません。" @@ -5760,6 +6044,10 @@ msgstr "リポジトリが見つかりません。" msgid "No results" msgstr "結果なし" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "No retries" +msgstr "再試行なし" + #: src/renderer/views/SchedulesView/parts/PreviousRunsModal.tsx msgid "No runs yet." msgstr "まだ実行はありません。" @@ -5796,6 +6084,10 @@ msgstr "音声が検出されませんでした。" msgid "No staged changes" msgstr "ステージされた変更はありません" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "No summary was provided." +msgstr "概要はありません。" + #: src/renderer/views/RemoteProjectModal/RemoteProjectModal.tsx msgid "No supported agents are installed on this remote machine. Install and sign in to an agent remotely before starting a thread." msgstr "このリモートマシンには対応エージェントがインストールされていません。スレッドを開始する前に、リモートでエージェントをインストールしてサインインしてください。" @@ -5825,6 +6117,10 @@ msgstr "まだスレッドはありません" msgid "No threads yet." msgstr "まだスレッドがありません。" +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "No upcoming run" +msgstr "今後の実行はありません" + #: src/renderer/components/providers/usageFormat.ts msgid "No windows reported" msgstr "ウィンドウは報告されませんでした" @@ -6040,6 +6336,11 @@ msgstr "GitHub でコミットを開く" msgid "Open conflict resolver in" msgstr "競合リゾルバーを開く" +#. placeholder {0}: props.scheduleName +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Open conversation for {0}" +msgstr "{0} の会話を開く" + #: src/renderer/views/SettingsOverlay/parts/settingsOptions.ts msgid "Open dialog" msgstr "ダイアログを開く" @@ -6675,6 +6976,10 @@ msgstr "プロジェクトフォルダーを更新しました。このプロジ msgid "Project name" msgstr "プロジェクト名" +#: src/renderer/i18n/sharedMessages.ts +msgid "Project no longer exists." +msgstr "プロジェクトは存在しません。" + #: src/renderer/views/MainView/parts/RightPanel/parts/NotesPanel/NotesEditor.tsx msgid "Project notes" msgstr "プロジェクトノート" @@ -7273,6 +7578,10 @@ msgstr "リクエストの詳細" msgid "requested changes" msgstr "要求された変更" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Required confidence before stopping." +msgstr "停止に必要な信頼度です。" + #: src/mobile/views/pr/PrOverviewPage.tsx #: src/renderer/views/GitReviewOverlay/parts/GitReviewSidebar/parts/PrSection.tsx msgid "Required reviews, conversations, or status checks not met." @@ -7344,6 +7653,10 @@ msgstr "ブラウザを復元する" msgid "Restore default worktree base folder" msgstr "デフォルトのワークツリーのベースフォルダーに戻す" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Restore finding" +msgstr "検出結果を復元" + #: src/mobile/settingsSections.ts msgid "Restore or delete" msgstr "復元または削除" @@ -7374,10 +7687,26 @@ msgstr "{serverName} の確認を再試行" msgid "Retry check" msgstr "確認を再試行" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Retry delay" +msgstr "再試行遅延" + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Retry delay in seconds" +msgstr "再試行遅延(秒)" + #: src/mobile/components.tsx msgid "Retry now" msgstr "今すぐ再試行" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Retry policy" +msgstr "再試行ポリシー" + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Retry when a run fails before it completes." +msgstr "完了前に実行が失敗した場合に再試行します。" + #: src/renderer/hooks/usePrWriteActions.ts msgid "Retry with admin" msgstr "管理者で再試行してください" @@ -7533,18 +7862,26 @@ msgstr "利用可能な場合は、GPU 上でローカル トランスクリプ msgid "Run now" msgstr "今すぐ実行" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Run once after reopening" +msgstr "再度開いた後に1回実行" + #: src/renderer/views/SchedulesView/SchedulesView.tsx #~ msgid "Run standalone tasks on this device without a project." #~ msgstr "プロジェクトなしで、このデバイス上の独立したタスクを実行します。" #: src/renderer/views/SchedulesView/SchedulesView.tsx -msgid "Run standalone tasks on this device. Schedules run while the device is awake and Poracode is open." -msgstr "このデバイスで単独タスクを実行します。スケジュールはデバイスが起動し、Poracodeが開いている間に実行されます。" +#~ msgid "Run standalone tasks on this device. Schedules run while the device is awake and Poracode is open." +#~ msgstr "このデバイスで単独タスクを実行します。スケジュールはデバイスが起動し、Poracodeが開いている間に実行されます。" #: src/renderer/commands/registry.ts msgid "Run Terminal Command" msgstr "ターミナルコマンドを実行する" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Run the latest missed run" +msgstr "実行できなかった最新の回を実行" + #: src/renderer/views/SchedulesView/ScheduleEditor.tsx #~ msgid "Run this schedule automatically at the times above." #~ msgstr "上記の時刻にこのスケジュールを自動的に実行します。" @@ -7560,6 +7897,7 @@ msgstr "実行中" #: src/renderer/utils/prStatus.ts #: src/renderer/views/SchedulesView/parts/PreviousRunsModal.tsx +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx msgid "Running" msgstr "実行中" @@ -7583,6 +7921,10 @@ msgstr "早めになくなります" msgid "Runs out in {runOut}" msgstr "あと{runOut}でなくなります" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Runs that need attention will appear here." +msgstr "対応が必要な実行がここに表示されます。" + #: src/renderer/views/MainView/parts/CreateProject/CloneProjectModal.tsx #: src/renderer/views/MainView/parts/CreateProject/CreateProjectModal.tsx msgid "Runtime" @@ -7659,6 +8001,10 @@ msgstr "Windows と WSL をスキャンして、インストールされてい msgid "Scanning your system for installed CLIs. This usually takes a couple of seconds." msgstr "システムをスキャンして、インストールされている CLI を探します。通常、これには数秒かかります。" +#: src/renderer/views/SchedulesView/SchedulesView.tsx +msgid "Schedule autonomous work and review results that need your attention. Automations run while this device is awake and Poracode is open." +msgstr "自律作業をスケジュールし、対応が必要な結果を確認します。自動化は、このデバイスが起動中で Poracode が開いている間に実行されます。" + #: src/renderer/views/SchedulesView/ScheduleEditor.tsx msgid "Schedule name" msgstr "スケジュール名" @@ -7667,20 +8013,31 @@ msgstr "スケジュール名" msgid "Schedule status" msgstr "スケジュールの状態" +#: src/renderer/i18n/sharedMessages.ts +msgid "Scheduled retry was cancelled." +msgstr "スケジュールされた再試行はキャンセルされました。" + +#: src/renderer/i18n/sharedMessages.ts +msgid "Scheduled task was deleted before retrying." +msgstr "再試行前にスケジュールタスクが削除されました。" + #: src/renderer/views/SchedulesView/SchedulesView.tsx -msgid "Scheduled tasks" -msgstr "スケジュールタスク" +#~ msgid "Scheduled tasks" +#~ msgstr "スケジュールタスク" #: src/mobile/settingsSections.ts -msgid "Scheduled tasks on this desktop" -msgstr "このデスクトップのスケジュールタスク" +#~ msgid "Scheduled tasks on this desktop" +#~ msgstr "このデスクトップのスケジュールタスク" #: src/renderer/views/SchedulesView/SchedulesView.tsx #~ msgid "Scheduled tasks run only while this device is awake and Poracode is open." #~ msgstr "スケジュールタスクは、このデバイスが起動中でPoracodeが開いている間のみ実行されます。" #: src/mobile/settingsSections.ts -#: src/renderer/views/MainView/parts/Sidebar/Sidebar.tsx +msgid "Scheduled work and triage on this desktop" +msgstr "このデスクトップのスケジュール作業とトリアージ" + +#: src/renderer/views/SchedulesView/SchedulesView.tsx msgid "Schedules" msgstr "スケジュール" @@ -7735,6 +8092,10 @@ msgstr "ブランチを検索..." msgid "Search files" msgstr "ファイルの検索" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Search findings" +msgstr "検出結果を検索" + #: src/renderer/components/skills/SkillMarketplaceModal.tsx msgid "Search marketplace skills" msgstr "マーケットプレイスのスキルを検索" @@ -7829,6 +8190,10 @@ msgstr "検索中..." msgid "Searching…" msgstr "検索中…" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "seconds" +msgstr "秒" + #: src/renderer/components/skills/SkillMarketplaceModal.tsx #~ msgid "Security-focused directory with verified skill metadata." #~ msgstr "検証済みのスキルメタデータを備えたセキュリティ重視のディレクトリ。" @@ -8219,6 +8584,10 @@ msgstr "{env}からサインアウトします。検出されたエージェン msgid "Signing out. Detected agents will refresh when it finishes." msgstr "サインアウトしています。検出されたエージェントは終了時に更新されます。" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Single pass" +msgstr "1回のみ実行" + #: src/renderer/components/skills/SkillImportModal.tsx #: src/renderer/components/skills/SkillMarketplaceModal.tsx msgid "Skill availability" @@ -8283,7 +8652,12 @@ msgstr "スキルマーケットプレイス" msgid "Skills.sh" msgstr "Skills.sh" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Skip missed runs" +msgstr "実行できなかった回をスキップ" + #: src/renderer/utils/prStatus.ts +#: src/renderer/views/SchedulesView/parts/PreviousRunsModal.tsx msgid "Skipped" msgstr "スキップ済み" @@ -8422,6 +8796,10 @@ msgstr "使用状況を見るには{appName}を起動してください" msgid "Start a dev server on your desktop, then tap refresh." msgstr "デスクトップで開発サーバーを起動し、更新をタップしてください。" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Start a new conversation for each run." +msgstr "実行ごとに新しい会話を開始します。" + #: src/renderer/commands/registry.ts msgid "Start a new thread as panel instead of page" msgstr "新しいスレッドをページではなくパネルとして開始する" @@ -8560,6 +8938,10 @@ msgstr "停止" msgid "Stop forwarding" msgstr "転送を停止" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Stop on error" +msgstr "エラー時に停止" + #: src/renderer/components/thread/ThreadComposer.tsx msgid "Stop response" msgstr "応答停止" @@ -8572,10 +8954,18 @@ msgstr "タスクの停止" msgid "Stop the project's running threads before changing its folder." msgstr "フォルダーを変更する前に、プロジェクトの実行中のスレッドを停止してください。" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Stop the run when this total time is reached." +msgstr "合計時間がこの値に達したら実行を停止します。" + #: src/renderer/components/composer/VoiceInputButton.tsx msgid "Stop voice input" msgstr "音声入力を停止する" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Stop when" +msgstr "停止条件" + #: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts #: src/renderer/views/SettingsOverlay/parts/WorktreeSettings.tsx msgid "Storage location" @@ -8920,6 +9310,22 @@ msgstr "エージェント" msgid "the app" msgstr "アプリ" +#: src/renderer/i18n/sharedMessages.ts +msgid "The automation conversation exited before the turn completed." +msgstr "自動化の会話はターンの完了前に終了しました。" + +#: src/renderer/i18n/sharedMessages.ts +msgid "The automation exceeded its time limit." +msgstr "自動化が時間制限を超えました。" + +#: src/renderer/i18n/sharedMessages.ts +msgid "The automation needs a reply before it can continue." +msgstr "自動化を続行するには返信が必要です。" + +#: src/renderer/i18n/sharedMessages.ts +msgid "The automation needs approval before it can continue." +msgstr "自動化を続行するには承認が必要です。" + #: src/renderer/views/MainView/parts/CreateProject/CloneProjectModal.tsx msgid "the chosen folder" msgstr "選択したフォルダー" @@ -8933,11 +9339,39 @@ msgstr "既定のバックグラウンド更新間隔です。下で独自の間 msgid "The desktop server is still coming online." msgstr "デスクトップサーバーはまだ起動中です。" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "The finding is no longer available." +msgstr "検出結果は利用できなくなりました。" + #. placeholder {0}: createTarget.wslDistro #: src/renderer/components/skills/SkillsManager.tsx msgid "the global {0} WSL scope" msgstr "{0} のグローバル WSL スコープ" +#: src/renderer/i18n/sharedMessages.ts +msgid "The heartbeat conversation belongs to a different project." +msgstr "ハートビートの会話は別のプロジェクトに属しています。" + +#: src/renderer/i18n/sharedMessages.ts +msgid "The heartbeat conversation cannot be resumed." +msgstr "ハートビートの会話を再開できません。" + +#: src/renderer/i18n/sharedMessages.ts +msgid "The heartbeat conversation is archived." +msgstr "ハートビートの会話はアーカイブされています。" + +#: src/renderer/i18n/sharedMessages.ts +msgid "The heartbeat conversation is currently busy." +msgstr "ハートビートの会話は現在使用中です。" + +#: src/renderer/i18n/sharedMessages.ts +msgid "The heartbeat conversation no longer exists." +msgstr "ハートビートの会話は存在しません。" + +#: src/renderer/i18n/sharedMessages.ts +msgid "The heartbeat conversation uses a different agent." +msgstr "ハートビートの会話では別のエージェントが使用されています。" + #: src/renderer/components/skills/SkillsManager.tsx msgid "the Linux user" msgstr "Linux ユーザー" @@ -8970,6 +9404,14 @@ msgstr "リモートサーバーからペアリング資格情報が返されま msgid "The repository location on disk. Update it if you moved the folder." msgstr "ディスク上のリポジトリの場所。フォルダーを移動した場合は更新してください。" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "The run could not be cancelled." +msgstr "実行をキャンセルできませんでした。" + +#: src/renderer/i18n/sharedMessages.ts +msgid "The scheduled automation failed." +msgstr "スケジュールされた自動化に失敗しました。" + #: src/renderer/components/mcp/McpServersManager.tsx #~ msgid "The selected file does not contain valid MCP server configurations." #~ msgstr "選択したファイルに有効なMCPサーバー設定が含まれていません。" @@ -9225,6 +9667,18 @@ msgstr "完了とマークされ、この日数タッチされていないスレ msgid "Time" msgstr "時刻" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Time limit" +msgstr "時間制限" + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Time limit in minutes" +msgstr "時間制限(分)" + +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Time zone" +msgstr "タイムゾーン" + #: src/renderer/components/mcp/McpServerEditor.tsx msgid "Timeout (ms)" msgstr "タイムアウト(ms)" @@ -9354,6 +9808,10 @@ msgstr "半透明のサイドバー" msgid "Trending now" msgstr "現在のトレンド" +#: src/renderer/views/SchedulesView/SchedulesView.tsx +msgid "Triage" +msgstr "トリアージ" + #: src/mobile/views/DesktopsView.tsx msgid "Trust and connect" msgstr "信頼して接続" @@ -9596,6 +10054,10 @@ msgstr "未割り当て" msgid "Unavailable" msgstr "利用不可" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Unavailable conversation" +msgstr "利用できない会話" + #: src/renderer/views/SchedulesView/ScheduleEditor.tsx msgid "Unavailable project" msgstr "利用できないプロジェクト" @@ -9674,6 +10136,10 @@ msgstr "フェーズなし:" msgid "Unpin" msgstr "固定を解除する" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Unread" +msgstr "未読" + #: src/mobile/views/GitActionSheet.tsx #: src/renderer/views/GitReviewOverlay/parts/GitReviewSidebar/parts/FileRow.tsx #: src/renderer/views/GitReviewOverlay/parts/GitStackedDiff.tsx @@ -10000,6 +10466,12 @@ msgstr "{methodName}認証を待機しています。検出されたエージェ msgid "waiting for agent to stop" msgstr "エージェントが停止するのを待っています" +#: src/renderer/views/SchedulesView/parts/PreviousRunsModal.tsx +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +#: src/renderer/views/SchedulesView/SchedulesView.tsx +msgid "Waiting for approval" +msgstr "承認待ち" + #: src/renderer/components/thread/ChatPane/parts/items/WorkflowOverlayBody.tsx msgid "Waiting for workflow to spawn agents…" msgstr "ワークフローがエージェントを生成するのを待っています…" @@ -10032,6 +10504,10 @@ msgstr "シェル環境をウォームアップしています..." msgid "Warming up WSL shell environment…" msgstr "WSL シェル環境をウォームアップしています…" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Warning" +msgstr "警告" + #: src/renderer/components/thread/ChatPane/parts/items/ToolCallGroup.tsx #: src/renderer/components/thread/ChatPane/parts/items/toolDisplay.ts #: src/renderer/components/thread/ChatPane/parts/items/WebSearchItem.tsx @@ -10324,6 +10800,10 @@ msgstr "WSL ベースフォルダー" #~ msgid "WSL user" #~ msgstr "WSL ユーザー" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "You’re all caught up." +msgstr "すべて確認済みです。" + #: src/renderer/views/ProfileOverlay/parts/EditProfileDialog.tsx msgid "Your name" msgstr "あなたの名前" diff --git a/src/renderer/locales/ko/messages.po b/src/renderer/locales/ko/messages.po index b0cec78ae..4bcda3021 100644 --- a/src/renderer/locales/ko/messages.po +++ b/src/renderer/locales/ko/messages.po @@ -288,6 +288,11 @@ msgstr "{agentLabel}: {statusLabel}. 상태 세부정보를 보려면 마우스 msgid "{agentLead} needs your input to continue." msgstr "{agentLead}가 계속하려면 입력이 필요합니다." +#. placeholder {0}: task.recurrence.timeZone +#: src/renderer/views/SchedulesView/SchedulesView.tsx +msgid "{cadence} in {0}" +msgstr "{cadence}({0})" + #: src/mobile/views/pr/PrOverviewPage.tsx msgid "{commitsCount, plural, one {# commit} other {# commits}}" msgstr "{commitsCount, plural, one {커밋 #개} other {커밋 #개}}" @@ -315,6 +320,18 @@ msgstr "{days}일 전" msgid "{envOrAgentLabel} needs authentication." msgstr "{envOrAgentLabel}에는 인증이 필요합니다." +#: src/renderer/views/SchedulesView/SchedulesView.tsx +msgid "{every, plural, one {Every day} other {Every # days}}" +msgstr "{every, plural, one {매일} other {#일마다}}" + +#: src/renderer/views/SchedulesView/SchedulesView.tsx +msgid "{every, plural, one {Every hour} other {Every # hours}}" +msgstr "{every, plural, one {매시간} other {#시간마다}}" + +#: src/renderer/views/SchedulesView/SchedulesView.tsx +msgid "{every, plural, one {Every minute} other {Every # minutes}}" +msgstr "{every, plural, one {매분} other {#분마다}}" + #: src/mobile/views/pr/PrOverviewPage.tsx msgid "{filesCount, plural, one {# file changed} other {# files changed}}" msgstr "{filesCount, plural, one {파일 #개 변경됨} other {파일 #개 변경됨}}" @@ -491,6 +508,10 @@ msgstr "~{money}{tokens} · {0} · 예상" msgid "≈{0}% by reset" msgstr "재설정 시 ≈{0}%" +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "0 9 * * 1-5" +msgstr "0 9 * * 1-5" + #: src/mobile/views/ThreadsView.tsx msgid "1 thread" msgstr "스레드 1개" @@ -840,6 +861,10 @@ msgstr "AI git 작업" msgid "AI providers" msgstr "AI 공급자" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "AI stop condition" +msgstr "AI 중지 조건" + #: src/mobile/views/MoreView.tsx #~ msgid "AI, agents, and archived threads on the paired desktop" #~ msgstr "페어링된 데스크톱의 AI, 에이전트 및 보관된 스레드" @@ -851,6 +876,7 @@ msgstr "스레드에 응답이 필요할 때 알림" #: src/renderer/commands/shortcutCatalog.ts #: src/renderer/components/skills/SkillsManager.tsx #: src/renderer/views/PullRequestsView/PullRequestsView.tsx +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx #: src/renderer/views/SchedulesView/SchedulesView.tsx #: src/renderer/views/SettingsOverlay/parts/ProfileSettings.tsx msgid "All" @@ -943,6 +969,10 @@ msgstr "항상 제외됨" msgid "An MCP server with this name already exists." msgstr "이 이름의 MCP 서버가 이미 있습니다." +#: src/renderer/i18n/sharedMessages.ts +msgid "Another automation is already using this conversation." +msgstr "다른 자동화가 이미 이 대화를 사용 중입니다." + #: src/renderer/components/thread/ChatPane/parts/CheckpointRevertControls.tsx msgid "Another chat uses this same tree. File restore could overwrite that chat's changes." msgstr "다른 채팅에서도 이 동일한 트리를 사용합니다. 파일 복원으로 인해 해당 채팅의 변경 사항을 덮어쓸 수 있습니다." @@ -1014,6 +1044,10 @@ msgstr "모두 보관" msgid "Archive all threads" msgstr "모든 스레드 보관" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Archive finding" +msgstr "발견 항목 보관" + #: src/renderer/commands/registry.ts msgid "Archive the current thread" msgstr "현재 스레드 보관" @@ -1028,6 +1062,10 @@ msgstr "스레드 보관" msgid "Archive Thread" msgstr "아카이브 스레드" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Archived" +msgstr "보관됨" + #: src/mobile/settingsSections.ts #: src/mobile/views/SettingsView.tsx #: src/renderer/views/SettingsOverlay/parts/ArchivedThreadsSettings.tsx @@ -1173,6 +1211,16 @@ msgstr "터미널 패널 자동 표시" msgid "Automatically show the terminal panel when running commands or creating worktrees." msgstr "명령을 실행하거나 작업 트리를 생성할 때 터미널 패널을 자동으로 표시합니다." +#: src/renderer/views/SchedulesView/SchedulesView.tsx +msgid "Automation sections" +msgstr "자동화 섹션" + +#: src/mobile/settingsSections.ts +#: src/renderer/views/MainView/parts/Sidebar/Sidebar.tsx +#: src/renderer/views/SchedulesView/SchedulesView.tsx +msgid "Automations" +msgstr "자동화" + #: src/renderer/components/skills/SkillImportModal.tsx msgid "Availability" msgstr "사용 범위" @@ -1459,6 +1507,10 @@ msgstr "브랜치 보호 규칙 우회(관리자 병합)" msgid "Cached only" msgstr "캐시만 있음" +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Calculated on desktop after saving" +msgstr "저장 후 데스크톱에서 계산됨" + #: src/mobile/QrScanner.tsx msgid "Camera access blocked" msgstr "카메라 접근이 차단됨" @@ -1513,11 +1565,16 @@ msgstr "선택기 취소" msgid "Cancel removing project" msgstr "프로젝트 제거 취소" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Cancel run" +msgstr "실행 취소" + #: src/renderer/components/thread/ChatPane/parts/items/WorkflowOverlayBody.tsx msgid "cancelled" msgstr "취소됨" #: src/renderer/utils/prStatus.ts +#: src/renderer/views/SchedulesView/parts/PreviousRunsModal.tsx msgid "Cancelled" msgstr "취소됨" @@ -1706,6 +1763,10 @@ msgstr "Poracode 인터페이스의 표시 언어를 선택하세요." msgid "Choose thread to attach to" msgstr "첨부할 스레드를 선택하세요." +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Choose what happens after a scheduled time was missed." +msgstr "예약된 시간을 놓쳤을 때 수행할 작업을 선택하세요." + #: src/renderer/views/SettingsOverlay/parts/BrowserSettings.tsx #: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts msgid "Choose whether links from Poracode and browser popups stay in Poracode or open externally." @@ -2185,6 +2246,14 @@ msgstr "완료" msgid "Completed" msgstr "완료됨" +#: src/renderer/i18n/sharedMessages.ts +msgid "Completion evaluation failed: {detail}" +msgstr "완료 평가 실패: {detail}" + +#: src/renderer/i18n/sharedMessages.ts +msgid "Completion evaluation is unavailable." +msgstr "완료 평가를 사용할 수 없습니다." + #: src/renderer/commands/shortcutCatalog.ts #: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx #: src/renderer/views/SettingsOverlay/parts/settingsOptions.ts @@ -2223,6 +2292,14 @@ msgstr "Computer Use 사용 중 — 대화형 작업이 데스크톱을 제어 #~ msgid "Computer Use enabled for this thread" #~ msgstr "이 스레드에 대해 컴퓨터 사용이 활성화되었습니다." +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Confidence" +msgstr "신뢰도" + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Confidence percent" +msgstr "신뢰도 백분율" + #: src/renderer/views/SettingsOverlay/parts/ClaudeProfileSettings.tsx msgid "Config directory" msgstr "설정 디렉터리" @@ -2386,6 +2463,14 @@ msgstr "다른 제공업체에서 계속" msgid "Continue in..." msgstr "다음에서 계속..." +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Continue one conversation until a stop condition or limit is reached." +msgstr "중지 조건이나 제한에 도달할 때까지 하나의 대화를 계속합니다." + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Control how each scheduled run continues and stops." +msgstr "예약된 각 실행이 계속되고 중지되는 방식을 제어합니다." + #: src/renderer/views/SettingsOverlay/parts/SearchSettings.tsx msgid "Control which files appear in the @file mention search. Per-project overrides live in each project's settings." msgstr "@file 멘션 검색에 표시되는 파일을 제어합니다. 프로젝트별 재정의는 각 프로젝트의 설정에 적용됩니다." @@ -2397,6 +2482,7 @@ msgstr "에이전트가 클릭하거나 입력하는 동안 페어링된 데스 #: src/mobile/views/pr/PrConversationPage.tsx #: src/mobile/views/pr/PrOverviewPage.tsx #: src/renderer/views/PrReviewOverlay/parts/PrTabsPill.tsx +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx msgid "Conversation" msgstr "대화" @@ -2697,6 +2783,24 @@ msgstr "자격 증명이 구성되었습니다." msgid "Credits" msgstr "크레딧" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Critical" +msgstr "심각" + +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Cron" +msgstr "Cron" + +#. placeholder {0}: task.recurrence.expression +#. placeholder {1}: task.recurrence.timeZone +#: src/renderer/views/SchedulesView/SchedulesView.tsx +msgid "Cron {0} in {1}" +msgstr "Cron {0}({1})" + +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Cron expression" +msgstr "Cron 식" + #: src/renderer/components/skills/SkillMarketplaceModal.tsx #~ msgid "Curated free and premium skills managed by MCP Market." #~ msgstr "MCP Market에서 관리하는 엄선된 무료 및 프리미엄 스킬입니다." @@ -2762,9 +2866,9 @@ msgstr "일일 브리핑" msgid "Dark" msgstr "다크" -#: src/renderer/views/SchedulesView/SchedulesView.tsx -#~ msgid "Days" -#~ msgstr "요일" +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Days" +msgstr "요일" #: src/renderer/components/thread/ThreadRuntimeRequestPanel/structuredElicitation.tsx msgid "Decline" @@ -2911,6 +3015,10 @@ msgstr "작업 트리 {0} 삭제" #~ msgid "Delete:" #~ msgstr "삭제:" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Deleted schedule" +msgstr "삭제된 일정" + #: src/renderer/views/SettingsOverlay/parts/AcpRegistrySettings.tsx msgid "Deleting" msgstr "삭제 중" @@ -2923,6 +3031,10 @@ msgstr "거부" msgid "Deny and tell the agent what to do differently…" msgstr "거부하고 에이전트에게 다르게 해야 할 일을 알려주세요…" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Describe the result that completes this heartbeat." +msgstr "이 하트비트를 완료하는 결과를 설명하세요." + #: src/renderer/views/SchedulesView/ScheduleEditor.tsx msgid "Describe what the agent should do" msgstr "에이전트가 수행할 작업을 설명하세요" @@ -2944,6 +3056,10 @@ msgstr "데스크톱 엔드포인트" msgid "Desktop is unreachable." msgstr "데스크톱에 연결할 수 없습니다." +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Desktop local time" +msgstr "데스크톱 현지 시간" + #: src/mobile/chrome.ts #: src/mobile/views/MoreView.tsx msgid "Desktop Settings" @@ -3056,6 +3172,10 @@ msgstr "프로젝트 비활성화" msgid "Disable Subagents" msgstr "하위 에이전트 비활성화" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Disable the automation after retries are exhausted." +msgstr "재시도 횟수를 모두 소진하면 자동화를 비활성화합니다." + #: src/renderer/views/SettingsOverlay/parts/ClaudeProfileSettings.tsx msgid "Disable tiers an external provider collapses (e.g. keep only High and Max)." msgstr "외부 제공자가 통합하는 등급을 비활성화합니다 (예: High와 Max만 유지)." @@ -3356,6 +3476,10 @@ msgstr "활성화된 서버는 새 스레드에서도 계속 켜져 있습니다 msgid "Enables <0>cookies and <1>storage. Cookies can contain session tokens and storage often holds auth state — only enable when you trust both the agent and the sites it visits." msgstr "<0>쿠키 및 <1>저장을 활성화합니다. 쿠키는 세션 토큰을 포함할 수 있으며 저장소는 종종 인증 상태를 유지합니다. 에이전트와 에이전트가 방문하는 사이트를 모두 신뢰할 때만 활성화됩니다." +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +#~ msgid "End the heartbeat after retries are exhausted." +#~ msgstr "재시도를 모두 소진하면 하트비트를 종료합니다." + #: src/mobile/views/DesktopsView.tsx #: src/renderer/views/SettingsOverlay/parts/RemoteServersSettings.tsx msgid "Endpoint" @@ -3393,6 +3517,10 @@ msgstr "올바른 데스크톱 엔드포인트를 입력하세요." msgid "Enter a valid HTTP or HTTPS URL." msgstr "유효한 HTTP 또는 HTTPS URL을 입력하세요." +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Enter a valid schedule" +msgstr "올바른 일정을 입력하세요" + #: src/mobile/views/DesktopsView.tsx msgid "Enter a valid SSH target and port." msgstr "올바른 SSH 대상과 포트를 입력하세요." @@ -3463,6 +3591,14 @@ msgstr "오류" msgid "Error · Agent encountered an error" msgstr "오류 · 에이전트에 오류가 발생했습니다." +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Evaluate the result after every iteration." +msgstr "각 반복 후 결과를 평가합니다." + +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Every" +msgstr "간격" + #: src/renderer/views/SchedulesView/SchedulesView.tsx msgid "Every day at {time}" msgstr "매일 {time}" @@ -3485,6 +3621,14 @@ msgstr "매시 {0}분" msgid "Exclude patterns" msgstr "패턴 제외" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Execution" +msgstr "실행" + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Execution mode" +msgstr "실행 모드" + #: src/renderer/components/thread/ChatPane/parts/items/toolDisplay.ts msgid "Exit plan mode" msgstr "계획 모드 종료" @@ -3534,6 +3678,10 @@ msgstr "펼쳐서 액세스를 검토하거나 취소합니다." msgid "Expand todo dock" msgstr "할 일 도크 확장" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Exponential backoff" +msgstr "지수 백오프" + #: src/renderer/components/mcp/McpServersManager.tsx msgid "Export MCP servers" msgstr "MCP 서버 내보내기" @@ -3716,6 +3864,10 @@ msgstr "diff에서 찾기" msgid "Find in terminal" msgstr "터미널에서 찾기" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Finding status" +msgstr "발견 항목 상태" + #: src/renderer/views/PrReviewOverlay/parts/SubmitReviewPopover.tsx msgid "Finish your review" msgstr "리뷰를 마무리하세요" @@ -3777,6 +3929,10 @@ msgstr "에이전트에서 수정" msgid "Fixed" msgstr "수정됨" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Fixed delay" +msgstr "고정 지연" + #: src/renderer/commands/registry.ts msgid "Focus browser address bar" msgstr "브라우저 주소 표시줄에 포커스" @@ -4097,6 +4253,26 @@ msgstr "보내지 않은 초안이 있습니다" msgid "Headers" msgstr "헤더" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Heartbeat" +msgstr "하트비트" + +#: src/renderer/i18n/sharedMessages.ts +msgid "Heartbeat automations require a native chat conversation." +msgstr "하트비트 자동화에는 네이티브 채팅 대화가 필요합니다." + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Heartbeat continues this conversation in the selected project." +msgstr "하트비트는 선택한 프로젝트에서 이 대화를 계속합니다." + +#: src/renderer/i18n/sharedMessages.ts +msgid "Heartbeat execution is unavailable." +msgstr "하트비트 실행을 사용할 수 없습니다." + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Heartbeats can continue making changes while you're away. Set hard limits below." +msgstr "자리를 비운 동안에도 하트비트가 계속 변경할 수 있습니다. 아래에서 엄격한 제한을 설정하세요." + #: src/renderer/views/SchedulesView/SchedulesView.tsx msgid "Help me create a schedule. Ask for any missing details, then use the Poracode schedule controls to create it for me." msgstr "일정 생성을 도와주세요. 누락된 세부 정보를 물어본 다음 Poracode 일정 제어를 사용하여 만들어 주세요." @@ -4198,6 +4374,10 @@ msgstr "host.com, 별칭 또는 user@host.com" msgid "Hourly" msgstr "매시간" +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Hours" +msgstr "시간" + #: src/renderer/components/mcp/McpServerEditor.tsx msgid "HTTP (streamable)" msgstr "HTTP(스트리밍 가능)" @@ -4328,6 +4508,14 @@ msgstr "앱 내 카메라 스캔은 HTTPS에서만 작동합니다. 휴대폰의 msgid "Inactive" msgstr "비활성" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Includes the first attempt." +msgstr "첫 번째 시도를 포함합니다." + +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Info" +msgstr "정보" + #. Badge on an exclude pattern inherited from a lower scope #: src/renderer/views/SettingsOverlay/parts/SearchExcludeBody.tsx msgid "inherited" @@ -4338,6 +4526,14 @@ msgstr "물려받은" msgid "Inheriting the global setting (currently {0})." msgstr "전역 설정 상속(현재 {0})" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Initial retry delay" +msgstr "초기 재시도 지연" + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Initial retry delay in seconds" +msgstr "초기 재시도 지연(초)" + #: src/renderer/views/GitReviewOverlay/parts/GitReviewSidebar/GitReviewSidebar.tsx msgid "Initialize Repository" msgstr "저장소 초기화" @@ -4476,6 +4672,18 @@ msgstr "중단됨" msgid "Interrupted: agent session ended before completion." msgstr "중단됨: 에이전트 세션이 완료되기 전에 종료되었습니다." +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Interval" +msgstr "간격" + +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Interval amount" +msgstr "간격 값" + +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Interval unit" +msgstr "간격 단위" + #: src/renderer/views/MainView/parts/RightPanel/parts/NotesPanel/NotesEditor.tsx msgid "Italic" msgstr "이탤릭체" @@ -4560,6 +4768,14 @@ msgstr "실행 중…" msgid "Leave a comment" msgstr "댓글 남기기" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Leave blank for no run limit." +msgstr "실행 횟수를 제한하지 않으려면 비워 두세요." + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +#~ msgid "Leave blank to rely on the time limit." +#~ msgstr "비워 두면 시간 제한만 적용됩니다." + #: src/renderer/views/ProfileOverlay/parts/ActivityHeatmap.tsx msgid "Less" msgstr "적음" @@ -4640,6 +4856,10 @@ msgstr "편집기 로드 중…" msgid "Loading file…" msgstr "파일 로드 중…" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Loading findings" +msgstr "발견 항목 불러오는 중" + #: src/renderer/components/skills/SkillMarketplaceModal.tsx msgid "Loading marketplace…" msgstr "마켓플레이스 로드 중…" @@ -4864,6 +5084,14 @@ msgstr "완료로 표시" msgid "Mark as not done" msgstr "완료되지 않음으로 표시" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Mark as read" +msgstr "읽음으로 표시" + +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Mark as unread" +msgstr "읽지 않음으로 표시" + #: src/renderer/components/thread/ThreadView.tsx msgid "Mark done" msgstr "완료로 표시" @@ -4904,6 +5132,22 @@ msgstr "최대화" msgid "Maximize browser" msgstr "브라우저 최대화" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Maximum attempts" +msgstr "최대 시도 횟수" + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Maximum iterations" +msgstr "최대 반복 횟수" + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Maximum retry delay" +msgstr "최대 재시도 지연" + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Maximum retry delay in seconds" +msgstr "최대 재시도 지연(초)" + #: src/renderer/components/skills/SkillMarketplaceModal.tsx #~ msgid "MCP Market" #~ msgstr "MCP Market" @@ -5110,6 +5354,18 @@ msgstr "패널로 최소화" msgid "Minute" msgstr "분" +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Minute, hour, day of month, month, and weekday." +msgstr "분, 시, 일, 월, 요일." + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "minutes" +msgstr "분" + +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Minutes" +msgstr "분" + #: src/mobile/views/BrowserView.tsx msgid "Mirrored desktop browser tab" msgstr "미러링된 데스크톱 브라우저 탭" @@ -5118,6 +5374,10 @@ msgstr "미러링된 데스크톱 브라우저 탭" msgid "Mirroring is unavailable." msgstr "미러링을 사용할 수 없습니다." +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Missed runs" +msgstr "놓친 실행" + #: src/renderer/views/SettingsOverlay/parts/RemoteAccessSettings.tsx msgid "Mobile push notifications" msgstr "모바일 푸시 알림" @@ -5469,6 +5729,10 @@ msgstr "다음 일치 항목" msgid "Next recently viewed chat" msgstr "최근 본 다음 채팅" +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Next run" +msgstr "다음 실행" + #. placeholder {0}: dateTimeFormatter.format(new Date(task.nextRunAt)) #: src/renderer/views/SchedulesView/SchedulesView.tsx msgid "Next run {0}" @@ -5514,6 +5778,10 @@ msgstr "설치된 에이전트가 없습니다." msgid "No AI commits, PRs, or conflict resolutions tracked yet." msgstr "아직 추적된 AI 커밋, PR, 충돌 해결이 없습니다." +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "No archived findings." +msgstr "보관된 발견 항목이 없습니다." + #: src/renderer/views/SettingsOverlay/parts/ArchivedThreadsSettings.tsx msgid "No archived threads." msgstr "보관된 스레드가 없습니다." @@ -5610,6 +5878,10 @@ msgstr "{0}에 대한 차이점이 없습니다." msgid "No diff for {visiblePath}" msgstr "{visiblePath}에는 차이가 없습니다." +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "No eligible conversations in this project." +msgstr "이 프로젝트에 적합한 대화가 없습니다." + #: src/renderer/components/skills/SkillImportModal.tsx msgid "No external skills were found in this scope." msgstr "이 범위에서 외부 스킬을 찾지 못했습니다." @@ -5625,6 +5897,10 @@ msgstr "이 메시지에 대해 저장된 파일 체크포인트가 없습니다 msgid "No files match \"{0}\"." msgstr "\"{0}\"과(와) 일치하는 파일이 없습니다." +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "No findings yet." +msgstr "아직 발견 항목이 없습니다." + #: src/renderer/views/MainView/parts/CreateProject/CloneProjectModal.tsx msgid "No GitHub CLI accounts found. Sign in with <0>gh auth login, or <1>paste a clone URL." msgstr "GitHub CLI 계정을 찾을 수 없습니다. <0>gh auth login으로 로그인하거나 <1>복제 URL을 붙여넣으세요." @@ -5637,6 +5913,10 @@ msgstr "아직 기록이 없습니다" msgid "No Lightcode data was found." msgstr "Lightcode 데이터를 찾을 수 없습니다." +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "No limit" +msgstr "제한 없음" + #: src/renderer/components/skills/SkillMarketplaceModal.tsx msgid "No marketplace skills match these filters." msgstr "이 필터와 일치하는 마켓플레이스 스킬이 없습니다." @@ -5653,6 +5933,10 @@ msgstr "일치하는 항목이 없습니다." msgid "No matching agents." msgstr "일치하는 에이전트가 없습니다." +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "No matching findings." +msgstr "일치하는 발견 항목이 없습니다." + #: src/renderer/views/PullRequestsView/PullRequestsView.tsx msgid "No matching pull requests." msgstr "일치하는 풀 리퀘스트가 없습니다." @@ -5762,6 +6046,10 @@ msgstr "저장소를 찾을 수 없습니다." msgid "No results" msgstr "결과 없음" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "No retries" +msgstr "재시도 없음" + #: src/renderer/views/SchedulesView/parts/PreviousRunsModal.tsx msgid "No runs yet." msgstr "아직 실행이 없습니다." @@ -5798,6 +6086,10 @@ msgstr "음성이 감지되지 않았습니다." msgid "No staged changes" msgstr "단계적 변경 없음" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "No summary was provided." +msgstr "제공된 요약이 없습니다." + #: src/renderer/views/RemoteProjectModal/RemoteProjectModal.tsx msgid "No supported agents are installed on this remote machine. Install and sign in to an agent remotely before starting a thread." msgstr "이 원격 머신에 지원되는 에이전트가 설치되어 있지 않습니다. 스레드를 시작하기 전에 원격으로 에이전트를 설치하고 로그인하세요." @@ -5827,6 +6119,10 @@ msgstr "아직 스레드 없음" msgid "No threads yet." msgstr "아직 스레드가 없습니다." +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "No upcoming run" +msgstr "예정된 실행 없음" + #: src/renderer/components/providers/usageFormat.ts msgid "No windows reported" msgstr "보고된 창 없음" @@ -6042,6 +6338,11 @@ msgstr "GitHub에서 커밋 열기" msgid "Open conflict resolver in" msgstr "충돌 해결 도구 열기 위치:" +#. placeholder {0}: props.scheduleName +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Open conversation for {0}" +msgstr "{0}의 대화 열기" + #: src/renderer/views/SettingsOverlay/parts/settingsOptions.ts msgid "Open dialog" msgstr "대화상자 열기" @@ -6677,6 +6978,10 @@ msgstr "프로젝트 폴더가 업데이트되었습니다. 이 프로젝트의 msgid "Project name" msgstr "프로젝트 이름" +#: src/renderer/i18n/sharedMessages.ts +msgid "Project no longer exists." +msgstr "프로젝트가 더 이상 존재하지 않습니다." + #: src/renderer/views/MainView/parts/RightPanel/parts/NotesPanel/NotesEditor.tsx msgid "Project notes" msgstr "프로젝트 노트" @@ -7275,6 +7580,10 @@ msgstr "요청 세부정보" msgid "requested changes" msgstr "변경을 요청했습니다" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Required confidence before stopping." +msgstr "중지에 필요한 신뢰도입니다." + #: src/mobile/views/pr/PrOverviewPage.tsx #: src/renderer/views/GitReviewOverlay/parts/GitReviewSidebar/parts/PrSection.tsx msgid "Required reviews, conversations, or status checks not met." @@ -7346,6 +7655,10 @@ msgstr "브라우저 복원" msgid "Restore default worktree base folder" msgstr "작업 트리 기본 폴더 복원" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Restore finding" +msgstr "발견 항목 복원" + #: src/mobile/settingsSections.ts msgid "Restore or delete" msgstr "복원 또는 삭제" @@ -7376,10 +7689,26 @@ msgstr "{serverName} 확인 재시도" msgid "Retry check" msgstr "확인 재시도" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Retry delay" +msgstr "재시도 지연" + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Retry delay in seconds" +msgstr "재시도 지연(초)" + #: src/mobile/components.tsx msgid "Retry now" msgstr "지금 다시 시도" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Retry policy" +msgstr "재시도 정책" + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Retry when a run fails before it completes." +msgstr "완료되기 전에 실행이 실패하면 다시 시도합니다." + #: src/renderer/hooks/usePrWriteActions.ts msgid "Retry with admin" msgstr "관리자 권한으로 다시 시도" @@ -7535,18 +7864,26 @@ msgstr "가능한 경우 GPU에서 로컬 전사를 실행합니다." msgid "Run now" msgstr "지금 실행" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Run once after reopening" +msgstr "다시 연 후 한 번 실행" + #: src/renderer/views/SchedulesView/SchedulesView.tsx #~ msgid "Run standalone tasks on this device without a project." #~ msgstr "프로젝트 없이 이 기기에서 독립 실행형 작업을 실행합니다." #: src/renderer/views/SchedulesView/SchedulesView.tsx -msgid "Run standalone tasks on this device. Schedules run while the device is awake and Poracode is open." -msgstr "이 기기에서 독립 실행형 작업을 실행합니다. 기기가 켜져 있고 Poracode가 열려 있을 때 일정이 실행됩니다." +#~ msgid "Run standalone tasks on this device. Schedules run while the device is awake and Poracode is open." +#~ msgstr "이 기기에서 독립 실행형 작업을 실행합니다. 기기가 켜져 있고 Poracode가 열려 있을 때 일정이 실행됩니다." #: src/renderer/commands/registry.ts msgid "Run Terminal Command" msgstr "터미널 명령 실행" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Run the latest missed run" +msgstr "가장 최근에 놓친 실행 수행" + #: src/renderer/views/SchedulesView/ScheduleEditor.tsx #~ msgid "Run this schedule automatically at the times above." #~ msgstr "위의 시간에 이 일정을 자동으로 실행합니다." @@ -7562,6 +7899,7 @@ msgstr "실행 중" #: src/renderer/utils/prStatus.ts #: src/renderer/views/SchedulesView/parts/PreviousRunsModal.tsx +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx msgid "Running" msgstr "실행 중" @@ -7585,6 +7923,10 @@ msgstr "조기 소진" msgid "Runs out in {runOut}" msgstr "{runOut} 후 소진" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Runs that need attention will appear here." +msgstr "주의가 필요한 실행이 여기에 표시됩니다." + #: src/renderer/views/MainView/parts/CreateProject/CloneProjectModal.tsx #: src/renderer/views/MainView/parts/CreateProject/CreateProjectModal.tsx msgid "Runtime" @@ -7661,6 +8003,10 @@ msgstr "설치된 CLI를 찾기 위해 Windows 및 WSL을 검색합니다. 이 msgid "Scanning your system for installed CLIs. This usually takes a couple of seconds." msgstr "설치된 CLI를 찾기 위해 시스템을 검색합니다. 이 작업은 일반적으로 몇 초 정도 걸립니다." +#: src/renderer/views/SchedulesView/SchedulesView.tsx +msgid "Schedule autonomous work and review results that need your attention. Automations run while this device is awake and Poracode is open." +msgstr "자율 작업을 예약하고 주의가 필요한 결과를 검토하세요. 자동화는 이 기기가 켜져 있고 Poracode가 열려 있는 동안 실행됩니다." + #: src/renderer/views/SchedulesView/ScheduleEditor.tsx msgid "Schedule name" msgstr "일정 이름" @@ -7669,20 +8015,31 @@ msgstr "일정 이름" msgid "Schedule status" msgstr "일정 상태" +#: src/renderer/i18n/sharedMessages.ts +msgid "Scheduled retry was cancelled." +msgstr "예약된 재시도가 취소되었습니다." + +#: src/renderer/i18n/sharedMessages.ts +msgid "Scheduled task was deleted before retrying." +msgstr "다시 시도하기 전에 예약된 작업이 삭제되었습니다." + #: src/renderer/views/SchedulesView/SchedulesView.tsx -msgid "Scheduled tasks" -msgstr "예약 작업" +#~ msgid "Scheduled tasks" +#~ msgstr "예약 작업" #: src/mobile/settingsSections.ts -msgid "Scheduled tasks on this desktop" -msgstr "이 데스크톱의 예약 작업" +#~ msgid "Scheduled tasks on this desktop" +#~ msgstr "이 데스크톱의 예약 작업" #: src/renderer/views/SchedulesView/SchedulesView.tsx #~ msgid "Scheduled tasks run only while this device is awake and Poracode is open." #~ msgstr "예약 작업은 이 기기가 켜져 있고 Poracode가 열려 있을 때만 실행됩니다." #: src/mobile/settingsSections.ts -#: src/renderer/views/MainView/parts/Sidebar/Sidebar.tsx +msgid "Scheduled work and triage on this desktop" +msgstr "이 데스크톱의 예약 작업 및 분류" + +#: src/renderer/views/SchedulesView/SchedulesView.tsx msgid "Schedules" msgstr "일정" @@ -7737,6 +8094,10 @@ msgstr "브랜치 검색..." msgid "Search files" msgstr "파일 검색" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Search findings" +msgstr "발견 항목 검색" + #: src/renderer/components/skills/SkillMarketplaceModal.tsx msgid "Search marketplace skills" msgstr "마켓플레이스 스킬 검색" @@ -7831,6 +8192,10 @@ msgstr "검색 중..." msgid "Searching…" msgstr "검색 중…" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "seconds" +msgstr "초" + #: src/renderer/components/skills/SkillMarketplaceModal.tsx #~ msgid "Security-focused directory with verified skill metadata." #~ msgstr "검증된 스킬 메타데이터를 제공하는 보안 중심 디렉터리입니다." @@ -8221,6 +8586,10 @@ msgstr "{env} 로그아웃 중입니다. 감지된 에이전트는 완료되면 msgid "Signing out. Detected agents will refresh when it finishes." msgstr "로그아웃합니다. 감지된 에이전트는 완료되면 새로 고쳐집니다." +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Single pass" +msgstr "단일 실행" + #: src/renderer/components/skills/SkillImportModal.tsx #: src/renderer/components/skills/SkillMarketplaceModal.tsx msgid "Skill availability" @@ -8285,7 +8654,12 @@ msgstr "스킬 마켓플레이스" msgid "Skills.sh" msgstr "Skills.sh" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Skip missed runs" +msgstr "놓친 실행 건너뛰기" + #: src/renderer/utils/prStatus.ts +#: src/renderer/views/SchedulesView/parts/PreviousRunsModal.tsx msgid "Skipped" msgstr "건너뜀" @@ -8424,6 +8798,10 @@ msgstr "사용량을 보려면 {appName}을(를) 시작하세요" msgid "Start a dev server on your desktop, then tap refresh." msgstr "데스크톱에서 개발 서버를 시작한 다음 새로고침을 탭하세요." +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Start a new conversation for each run." +msgstr "실행할 때마다 새 대화를 시작합니다." + #: src/renderer/commands/registry.ts msgid "Start a new thread as panel instead of page" msgstr "새 스레드를 페이지가 아닌 패널로 시작" @@ -8562,6 +8940,10 @@ msgstr "중지" msgid "Stop forwarding" msgstr "전달 중지" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Stop on error" +msgstr "오류 발생 시 중지" + #: src/renderer/components/thread/ThreadComposer.tsx msgid "Stop response" msgstr "응답 중지" @@ -8574,10 +8956,18 @@ msgstr "작업 중지" msgid "Stop the project's running threads before changing its folder." msgstr "폴더를 변경하기 전에 프로젝트에서 실행 중인 스레드를 중지하세요." +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Stop the run when this total time is reached." +msgstr "총 시간이 이 값에 도달하면 실행을 중지합니다." + #: src/renderer/components/composer/VoiceInputButton.tsx msgid "Stop voice input" msgstr "음성 입력 중지" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Stop when" +msgstr "중지 조건" + #: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts #: src/renderer/views/SettingsOverlay/parts/WorktreeSettings.tsx msgid "Storage location" @@ -8922,6 +9312,22 @@ msgstr "에이전트" msgid "the app" msgstr "앱" +#: src/renderer/i18n/sharedMessages.ts +msgid "The automation conversation exited before the turn completed." +msgstr "턴이 완료되기 전에 자동화 대화가 종료되었습니다." + +#: src/renderer/i18n/sharedMessages.ts +msgid "The automation exceeded its time limit." +msgstr "자동화가 시간 제한을 초과했습니다." + +#: src/renderer/i18n/sharedMessages.ts +msgid "The automation needs a reply before it can continue." +msgstr "자동화를 계속하려면 답변이 필요합니다." + +#: src/renderer/i18n/sharedMessages.ts +msgid "The automation needs approval before it can continue." +msgstr "자동화를 계속하려면 승인이 필요합니다." + #: src/renderer/views/MainView/parts/CreateProject/CloneProjectModal.tsx msgid "the chosen folder" msgstr "선택한 폴더" @@ -8935,11 +9341,39 @@ msgstr "아래에서 자체 간격이 설정되지 않은 모든 공급자에 msgid "The desktop server is still coming online." msgstr "데스크톱 서버가 아직 시작 중입니다." +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "The finding is no longer available." +msgstr "발견 항목을 더 이상 사용할 수 없습니다." + #. placeholder {0}: createTarget.wslDistro #: src/renderer/components/skills/SkillsManager.tsx msgid "the global {0} WSL scope" msgstr "{0} 전역 WSL 범위" +#: src/renderer/i18n/sharedMessages.ts +msgid "The heartbeat conversation belongs to a different project." +msgstr "하트비트 대화가 다른 프로젝트에 속해 있습니다." + +#: src/renderer/i18n/sharedMessages.ts +msgid "The heartbeat conversation cannot be resumed." +msgstr "하트비트 대화를 재개할 수 없습니다." + +#: src/renderer/i18n/sharedMessages.ts +msgid "The heartbeat conversation is archived." +msgstr "하트비트 대화가 보관되었습니다." + +#: src/renderer/i18n/sharedMessages.ts +msgid "The heartbeat conversation is currently busy." +msgstr "하트비트 대화가 현재 사용 중입니다." + +#: src/renderer/i18n/sharedMessages.ts +msgid "The heartbeat conversation no longer exists." +msgstr "하트비트 대화가 더 이상 존재하지 않습니다." + +#: src/renderer/i18n/sharedMessages.ts +msgid "The heartbeat conversation uses a different agent." +msgstr "하트비트 대화가 다른 에이전트를 사용합니다." + #: src/renderer/components/skills/SkillsManager.tsx msgid "the Linux user" msgstr "Linux 사용자" @@ -8972,6 +9406,14 @@ msgstr "원격 서버에서 페어링 자격 증명을 반환하지 않았습니 msgid "The repository location on disk. Update it if you moved the folder." msgstr "디스크에 있는 저장소 위치입니다. 폴더를 옮겼다면 업데이트하세요." +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "The run could not be cancelled." +msgstr "실행을 취소할 수 없습니다." + +#: src/renderer/i18n/sharedMessages.ts +msgid "The scheduled automation failed." +msgstr "예약된 자동화에 실패했습니다." + #: src/renderer/components/mcp/McpServersManager.tsx #~ msgid "The selected file does not contain valid MCP server configurations." #~ msgstr "선택한 파일에 유효한 MCP 서버 구성이 없습니다." @@ -9227,6 +9669,18 @@ msgstr "완료로 표시된 스레드 중 며칠 동안 건드리지 않은 스 msgid "Time" msgstr "시간" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Time limit" +msgstr "시간 제한" + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Time limit in minutes" +msgstr "시간 제한(분)" + +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Time zone" +msgstr "시간대" + #: src/renderer/components/mcp/McpServerEditor.tsx msgid "Timeout (ms)" msgstr "제한 시간(ms)" @@ -9356,6 +9810,10 @@ msgstr "반투명 사이드바" msgid "Trending now" msgstr "현재 인기" +#: src/renderer/views/SchedulesView/SchedulesView.tsx +msgid "Triage" +msgstr "분류" + #: src/mobile/views/DesktopsView.tsx msgid "Trust and connect" msgstr "신뢰하고 연결" @@ -9598,6 +10056,10 @@ msgstr "미지정" msgid "Unavailable" msgstr "사용할 수 없음" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Unavailable conversation" +msgstr "사용할 수 없는 대화" + #: src/renderer/views/SchedulesView/ScheduleEditor.tsx msgid "Unavailable project" msgstr "사용할 수 없는 프로젝트" @@ -9676,6 +10138,10 @@ msgstr "단계 미지정:" msgid "Unpin" msgstr "고정 해제" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Unread" +msgstr "읽지 않음" + #: src/mobile/views/GitActionSheet.tsx #: src/renderer/views/GitReviewOverlay/parts/GitReviewSidebar/parts/FileRow.tsx #: src/renderer/views/GitReviewOverlay/parts/GitStackedDiff.tsx @@ -10002,6 +10468,12 @@ msgstr "{methodName} 인증을 기다리는 중입니다. 감지된 에이전트 msgid "waiting for agent to stop" msgstr "에이전트가 중지되기를 기다리는 중" +#: src/renderer/views/SchedulesView/parts/PreviousRunsModal.tsx +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +#: src/renderer/views/SchedulesView/SchedulesView.tsx +msgid "Waiting for approval" +msgstr "승인 대기 중" + #: src/renderer/components/thread/ChatPane/parts/items/WorkflowOverlayBody.tsx msgid "Waiting for workflow to spawn agents…" msgstr "워크플로가 에이전트를 생성하기를 기다리는 중…" @@ -10034,6 +10506,10 @@ msgstr "쉘 환경 준비 중..." msgid "Warming up WSL shell environment…" msgstr "WSL 셸 환경 준비 중…" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Warning" +msgstr "경고" + #: src/renderer/components/thread/ChatPane/parts/items/ToolCallGroup.tsx #: src/renderer/components/thread/ChatPane/parts/items/toolDisplay.ts #: src/renderer/components/thread/ChatPane/parts/items/WebSearchItem.tsx @@ -10326,6 +10802,10 @@ msgstr "WSL 기본 폴더" #~ msgid "WSL user" #~ msgstr "WSL 사용자" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "You’re all caught up." +msgstr "모두 확인했습니다." + #: src/renderer/views/ProfileOverlay/parts/EditProfileDialog.tsx msgid "Your name" msgstr "이름" diff --git a/src/renderer/locales/pl/messages.po b/src/renderer/locales/pl/messages.po index a86673edd..01912cbf7 100644 --- a/src/renderer/locales/pl/messages.po +++ b/src/renderer/locales/pl/messages.po @@ -288,6 +288,11 @@ msgstr "{agentLabel}: {statusLabel}. Najedź kursorem, aby wyświetlić szczegó msgid "{agentLead} needs your input to continue." msgstr "{agentLead} potrzebuje Twojej odpowiedzi, aby kontynuować." +#. placeholder {0}: task.recurrence.timeZone +#: src/renderer/views/SchedulesView/SchedulesView.tsx +msgid "{cadence} in {0}" +msgstr "{cadence} — strefa {0}" + #: src/mobile/views/pr/PrOverviewPage.tsx msgid "{commitsCount, plural, one {# commit} other {# commits}}" msgstr "{commitsCount, plural, one {# commit} few {# commity} many {# commitów} other {# commita}}" @@ -315,6 +320,18 @@ msgstr "{days} dni temu" msgid "{envOrAgentLabel} needs authentication." msgstr "{envOrAgentLabel} wymaga uwierzytelnienia." +#: src/renderer/views/SchedulesView/SchedulesView.tsx +msgid "{every, plural, one {Every day} other {Every # days}}" +msgstr "{every, plural, one {Codziennie} few {Co # dni} many {Co # dni} other {Co # dnia}}" + +#: src/renderer/views/SchedulesView/SchedulesView.tsx +msgid "{every, plural, one {Every hour} other {Every # hours}}" +msgstr "{every, plural, one {Co godzinę} few {Co # godziny} many {Co # godzin} other {Co # godziny}}" + +#: src/renderer/views/SchedulesView/SchedulesView.tsx +msgid "{every, plural, one {Every minute} other {Every # minutes}}" +msgstr "{every, plural, one {Co minutę} few {Co # minuty} many {Co # minut} other {Co # minuty}}" + #: src/mobile/views/pr/PrOverviewPage.tsx msgid "{filesCount, plural, one {# file changed} other {# files changed}}" msgstr "{filesCount, plural, one {# plik zmieniony} few {# pliki zmienione} many {# plików zmienionych} other {# pliku zmienionego}}" @@ -491,6 +508,10 @@ msgstr "~{money}{tokens} · {0} · szac." msgid "≈{0}% by reset" msgstr "≈{0}% do resetu" +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "0 9 * * 1-5" +msgstr "0 9 * * 1-5" + #: src/mobile/views/ThreadsView.tsx msgid "1 thread" msgstr "1 wątek" @@ -840,6 +861,10 @@ msgstr "Akcje AI w git" msgid "AI providers" msgstr "Dostawcy AI" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "AI stop condition" +msgstr "Warunek zatrzymania przez AI" + #: src/mobile/views/MoreView.tsx #~ msgid "AI, agents, and archived threads on the paired desktop" #~ msgstr "AI, agenci i zarchiwizowane wątki na sparowanym pulpicie" @@ -851,6 +876,7 @@ msgstr "Alerty, gdy wątki wymagają Twojej uwagi" #: src/renderer/commands/shortcutCatalog.ts #: src/renderer/components/skills/SkillsManager.tsx #: src/renderer/views/PullRequestsView/PullRequestsView.tsx +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx #: src/renderer/views/SchedulesView/SchedulesView.tsx #: src/renderer/views/SettingsOverlay/parts/ProfileSettings.tsx msgid "All" @@ -943,6 +969,10 @@ msgstr "Zawsze wykluczone" msgid "An MCP server with this name already exists." msgstr "Serwer MCP o tej nazwie już istnieje." +#: src/renderer/i18n/sharedMessages.ts +msgid "Another automation is already using this conversation." +msgstr "Inna automatyzacja korzysta już z tej rozmowy." + #: src/renderer/components/thread/ChatPane/parts/CheckpointRevertControls.tsx msgid "Another chat uses this same tree. File restore could overwrite that chat's changes." msgstr "Inny czat korzysta z tego samego drzewa. Przywrócenie pliku może zastąpić zmiany wprowadzone w czacie." @@ -1014,6 +1044,10 @@ msgstr "Archiwizuj wszystko" msgid "Archive all threads" msgstr "Archiwizuj wszystkie wątki" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Archive finding" +msgstr "Archiwizuj ustalenie" + #: src/renderer/commands/registry.ts msgid "Archive the current thread" msgstr "Archiwizuj bieżący wątek" @@ -1028,6 +1062,10 @@ msgstr "Archiwizuj wątek" msgid "Archive Thread" msgstr "Archiwum wątku" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Archived" +msgstr "Zarchiwizowane" + #: src/mobile/settingsSections.ts #: src/mobile/views/SettingsView.tsx #: src/renderer/views/SettingsOverlay/parts/ArchivedThreadsSettings.tsx @@ -1173,6 +1211,16 @@ msgstr "Automatyczne wyświetlanie panelu terminali" msgid "Automatically show the terminal panel when running commands or creating worktrees." msgstr "Automatycznie pokazuj panel terminala podczas uruchamiania poleceń lub tworzenia drzew roboczych." +#: src/renderer/views/SchedulesView/SchedulesView.tsx +msgid "Automation sections" +msgstr "Sekcje automatyzacji" + +#: src/mobile/settingsSections.ts +#: src/renderer/views/MainView/parts/Sidebar/Sidebar.tsx +#: src/renderer/views/SchedulesView/SchedulesView.tsx +msgid "Automations" +msgstr "Automatyzacje" + #: src/renderer/components/skills/SkillImportModal.tsx msgid "Availability" msgstr "Dostępność" @@ -1459,6 +1507,10 @@ msgstr "Omiń reguły ochrony gałęzi (scalanie administracyjne)" msgid "Cached only" msgstr "Tylko z pamięci podręcznej" +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Calculated on desktop after saving" +msgstr "Obliczane na komputerze po zapisaniu" + #: src/mobile/QrScanner.tsx msgid "Camera access blocked" msgstr "Dostęp do kamery zablokowany" @@ -1513,11 +1565,16 @@ msgstr "Anuluj selektor" msgid "Cancel removing project" msgstr "Anuluj usuwanie projektu" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Cancel run" +msgstr "Anuluj uruchomienie" + #: src/renderer/components/thread/ChatPane/parts/items/WorkflowOverlayBody.tsx msgid "cancelled" msgstr "anulowane" #: src/renderer/utils/prStatus.ts +#: src/renderer/views/SchedulesView/parts/PreviousRunsModal.tsx msgid "Cancelled" msgstr "Anulowano" @@ -1706,6 +1763,10 @@ msgstr "Wybierz język wyświetlania interfejsu Poracode." msgid "Choose thread to attach to" msgstr "Wybierz wątek, do którego chcesz dołączyć" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Choose what happens after a scheduled time was missed." +msgstr "Wybierz, co ma się stać po pominięciu zaplanowanego terminu." + #: src/renderer/views/SettingsOverlay/parts/BrowserSettings.tsx #: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts msgid "Choose whether links from Poracode and browser popups stay in Poracode or open externally." @@ -2185,6 +2246,14 @@ msgstr "ukończone" msgid "Completed" msgstr "Ukończono" +#: src/renderer/i18n/sharedMessages.ts +msgid "Completion evaluation failed: {detail}" +msgstr "Ocena zakończenia nie powiodła się: {detail}" + +#: src/renderer/i18n/sharedMessages.ts +msgid "Completion evaluation is unavailable." +msgstr "Ocena zakończenia jest niedostępna." + #: src/renderer/commands/shortcutCatalog.ts #: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx #: src/renderer/views/SettingsOverlay/parts/settingsOptions.ts @@ -2223,6 +2292,14 @@ msgstr "Computer Use włączone — działania interaktywne przejmują pulpit; n #~ msgid "Computer Use enabled for this thread" #~ msgstr "Włączono obsługę komputera dla tego wątku" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Confidence" +msgstr "Pewność" + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Confidence percent" +msgstr "Procent pewności" + #: src/renderer/views/SettingsOverlay/parts/ClaudeProfileSettings.tsx msgid "Config directory" msgstr "Katalog konfiguracji" @@ -2386,6 +2463,14 @@ msgstr "Kontynuuj u innego dostawcy" msgid "Continue in..." msgstr "Kontynuuj w..." +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Continue one conversation until a stop condition or limit is reached." +msgstr "Kontynuuj jedną rozmowę, aż zostanie spełniony warunek zatrzymania lub osiągnięty limit." + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Control how each scheduled run continues and stops." +msgstr "Określ, jak każde zaplanowane uruchomienie ma być kontynuowane i zatrzymywane." + #: src/renderer/views/SettingsOverlay/parts/SearchSettings.tsx msgid "Control which files appear in the @file mention search. Per-project overrides live in each project's settings." msgstr "Kontroluj, które pliki pojawiają się w wyszukiwaniu wzmianek @plik. Zastąpienia poszczególnych projektów są dostępne w ustawieniach każdego projektu." @@ -2397,6 +2482,7 @@ msgstr "Steruje sparowanym pulpitem, gdy agent klika lub pisze" #: src/mobile/views/pr/PrConversationPage.tsx #: src/mobile/views/pr/PrOverviewPage.tsx #: src/renderer/views/PrReviewOverlay/parts/PrTabsPill.tsx +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx msgid "Conversation" msgstr "Rozmowa" @@ -2697,6 +2783,24 @@ msgstr "Poświadczenia są skonfigurowane." msgid "Credits" msgstr "Kredyty" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Critical" +msgstr "Krytyczne" + +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Cron" +msgstr "Cron" + +#. placeholder {0}: task.recurrence.expression +#. placeholder {1}: task.recurrence.timeZone +#: src/renderer/views/SchedulesView/SchedulesView.tsx +msgid "Cron {0} in {1}" +msgstr "Cron {0} — strefa {1}" + +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Cron expression" +msgstr "Wyrażenie Cron" + #: src/renderer/components/skills/SkillMarketplaceModal.tsx #~ msgid "Curated free and premium skills managed by MCP Market." #~ msgstr "Wyselekcjonowane bezpłatne i premium skille zarządzane przez MCP Market." @@ -2762,9 +2866,9 @@ msgstr "Codzienne podsumowanie" msgid "Dark" msgstr "Ciemny" -#: src/renderer/views/SchedulesView/SchedulesView.tsx -#~ msgid "Days" -#~ msgstr "Dni" +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Days" +msgstr "Dni" #: src/renderer/components/thread/ThreadRuntimeRequestPanel/structuredElicitation.tsx msgid "Decline" @@ -2911,6 +3015,10 @@ msgstr "Usuń drzewo robocze {0}" #~ msgid "Delete:" #~ msgstr "Usuń:" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Deleted schedule" +msgstr "Usunięty harmonogram" + #: src/renderer/views/SettingsOverlay/parts/AcpRegistrySettings.tsx msgid "Deleting" msgstr "Usuwanie" @@ -2923,6 +3031,10 @@ msgstr "Odmów" msgid "Deny and tell the agent what to do differently…" msgstr "Odmów i powiedz agentowi, co ma zrobić inaczej…" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Describe the result that completes this heartbeat." +msgstr "Opisz wynik, który kończy ten heartbeat." + #: src/renderer/views/SchedulesView/ScheduleEditor.tsx msgid "Describe what the agent should do" msgstr "Opisz, co agent powinien zrobić" @@ -2944,6 +3056,10 @@ msgstr "Punkt końcowy pulpitu" msgid "Desktop is unreachable." msgstr "Desktop jest niedostępny." +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Desktop local time" +msgstr "Czas lokalny komputera" + #: src/mobile/chrome.ts #: src/mobile/views/MoreView.tsx msgid "Desktop Settings" @@ -3056,6 +3172,10 @@ msgstr "Wyłącz projekt" msgid "Disable Subagents" msgstr "Wyłącz subagentów" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Disable the automation after retries are exhausted." +msgstr "Wyłącz automatyzację po wyczerpaniu wszystkich ponownych prób." + #: src/renderer/views/SettingsOverlay/parts/ClaudeProfileSettings.tsx msgid "Disable tiers an external provider collapses (e.g. keep only High and Max)." msgstr "Wyłącz poziomy, które zewnętrzny dostawca scala (np. zostaw tylko High i Max)." @@ -3356,6 +3476,10 @@ msgstr "Włączone serwery pozostają aktywne dla nowych wątków" msgid "Enables <0>cookies and <1>storage. Cookies can contain session tokens and storage often holds auth state — only enable when you trust both the agent and the sites it visits." msgstr "Włącza <0>pliki cookie i <1>przechowywanie. Pliki cookie mogą zawierać tokeny sesji, a pamięć często przechowuje stan uwierzytelnienia — włącz tę opcję tylko wtedy, gdy ufasz zarówno agentowi, jak i odwiedzanym przez niego witrynom." +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +#~ msgid "End the heartbeat after retries are exhausted." +#~ msgstr "Zakończ heartbeat po wyczerpaniu prób ponowienia." + #: src/mobile/views/DesktopsView.tsx #: src/renderer/views/SettingsOverlay/parts/RemoteServersSettings.tsx msgid "Endpoint" @@ -3393,6 +3517,10 @@ msgstr "Wpisz prawidłowy punkt końcowy desktopa." msgid "Enter a valid HTTP or HTTPS URL." msgstr "Wprowadź prawidłowy adres URL HTTP lub HTTPS." +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Enter a valid schedule" +msgstr "Wprowadź prawidłowy harmonogram" + #: src/mobile/views/DesktopsView.tsx msgid "Enter a valid SSH target and port." msgstr "Wprowadź prawidłowy cel SSH i port." @@ -3463,6 +3591,14 @@ msgstr "Błąd" msgid "Error · Agent encountered an error" msgstr "Błąd · Agent napotkał błąd" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Evaluate the result after every iteration." +msgstr "Oceniaj wynik po każdej iteracji." + +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Every" +msgstr "Co" + #: src/renderer/views/SchedulesView/SchedulesView.tsx msgid "Every day at {time}" msgstr "Codziennie o {time}" @@ -3485,6 +3621,14 @@ msgstr "Co godzinę, {0} minut po pełnej godzinie" msgid "Exclude patterns" msgstr "Wyklucz wzorce" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Execution" +msgstr "Wykonanie" + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Execution mode" +msgstr "Tryb wykonania" + #: src/renderer/components/thread/ChatPane/parts/items/toolDisplay.ts msgid "Exit plan mode" msgstr "Wyjdź z trybu planu" @@ -3534,6 +3678,10 @@ msgstr "Rozwiń, aby sprawdzić lub odebrać dostęp." msgid "Expand todo dock" msgstr "Rozwiń dok zadań do wykonania" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Exponential backoff" +msgstr "Wykładnicze wydłużanie opóźnienia" + #: src/renderer/components/mcp/McpServersManager.tsx msgid "Export MCP servers" msgstr "Eksportuj serwery MCP" @@ -3716,6 +3864,10 @@ msgstr "Znajdź w różnicach" msgid "Find in terminal" msgstr "Znajdź w terminalu" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Finding status" +msgstr "Stan ustalenia" + #: src/renderer/views/PrReviewOverlay/parts/SubmitReviewPopover.tsx msgid "Finish your review" msgstr "Zakończ swoją recenzję" @@ -3777,6 +3929,10 @@ msgstr "Napraw w Agencie" msgid "Fixed" msgstr "Naprawiono" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Fixed delay" +msgstr "Stałe opóźnienie" + #: src/renderer/commands/registry.ts msgid "Focus browser address bar" msgstr "Przejdź do paska adresu przeglądarki" @@ -4097,6 +4253,26 @@ msgstr "Zawiera niewysłaną wersję roboczą" msgid "Headers" msgstr "Nagłówki" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Heartbeat" +msgstr "Heartbeat" + +#: src/renderer/i18n/sharedMessages.ts +msgid "Heartbeat automations require a native chat conversation." +msgstr "Automatyzacje heartbeat wymagają natywnej rozmowy na czacie." + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Heartbeat continues this conversation in the selected project." +msgstr "Heartbeat kontynuuje tę rozmowę w wybranym projekcie." + +#: src/renderer/i18n/sharedMessages.ts +msgid "Heartbeat execution is unavailable." +msgstr "Wykonanie heartbeat jest niedostępne." + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Heartbeats can continue making changes while you're away. Set hard limits below." +msgstr "Automatyzacje heartbeat mogą nadal wprowadzać zmiany podczas Twojej nieobecności. Ustaw poniżej sztywne limity." + #: src/renderer/views/SchedulesView/SchedulesView.tsx msgid "Help me create a schedule. Ask for any missing details, then use the Poracode schedule controls to create it for me." msgstr "Pomóż mi utworzyć harmonogram. Zapytaj o brakujące szczegóły, a następnie użyj kontrolek harmonogramu Poracode, aby go utworzyć." @@ -4198,6 +4374,10 @@ msgstr "host.com, alias lub użytkownik@host.com" msgid "Hourly" msgstr "Co godzinę" +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Hours" +msgstr "Godziny" + #: src/renderer/components/mcp/McpServerEditor.tsx msgid "HTTP (streamable)" msgstr "HTTP (strumieniowy)" @@ -4328,6 +4508,14 @@ msgstr "Skanowanie kamerą w aplikacji działa tylko przez HTTPS. Użyj aplikacj msgid "Inactive" msgstr "Nieaktywny" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Includes the first attempt." +msgstr "Obejmuje pierwszą próbę." + +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Info" +msgstr "Informacje" + #. Badge on an exclude pattern inherited from a lower scope #: src/renderer/views/SettingsOverlay/parts/SearchExcludeBody.tsx msgid "inherited" @@ -4338,6 +4526,14 @@ msgstr "odziedziczone" msgid "Inheriting the global setting (currently {0})." msgstr "Dziedziczenie ustawienia globalnego (obecnie {0})." +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Initial retry delay" +msgstr "Początkowe opóźnienie ponowienia" + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Initial retry delay in seconds" +msgstr "Początkowe opóźnienie ponowienia w sekundach" + #: src/renderer/views/GitReviewOverlay/parts/GitReviewSidebar/GitReviewSidebar.tsx msgid "Initialize Repository" msgstr "Zainicjuj repozytorium" @@ -4476,6 +4672,18 @@ msgstr "Przerwano" msgid "Interrupted: agent session ended before completion." msgstr "Przerwano: sesja agenta zakończyła się przed jej ukończeniem." +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Interval" +msgstr "Interwał" + +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Interval amount" +msgstr "Wartość interwału" + +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Interval unit" +msgstr "Jednostka interwału" + #: src/renderer/views/MainView/parts/RightPanel/parts/NotesPanel/NotesEditor.tsx msgid "Italic" msgstr "Kursywa" @@ -4560,6 +4768,14 @@ msgstr "Uruchamiam…" msgid "Leave a comment" msgstr "Zostaw komentarz" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Leave blank for no run limit." +msgstr "Pozostaw puste, aby nie ograniczać liczby uruchomień." + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +#~ msgid "Leave blank to rely on the time limit." +#~ msgstr "Pozostaw puste, aby polegać na limicie czasu." + #: src/renderer/views/ProfileOverlay/parts/ActivityHeatmap.tsx msgid "Less" msgstr "Mniej" @@ -4640,6 +4856,10 @@ msgstr "Ładowanie edytora…" msgid "Loading file…" msgstr "Ładowanie pliku…" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Loading findings" +msgstr "Wczytywanie ustaleń" + #: src/renderer/components/skills/SkillMarketplaceModal.tsx msgid "Loading marketplace…" msgstr "Ładowanie marketplace…" @@ -4864,6 +5084,14 @@ msgstr "Oznacz jako gotowe" msgid "Mark as not done" msgstr "Oznacz jako niezrobione" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Mark as read" +msgstr "Oznacz jako przeczytane" + +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Mark as unread" +msgstr "Oznacz jako nieprzeczytane" + #: src/renderer/components/thread/ThreadView.tsx msgid "Mark done" msgstr "Oznacz gotowe" @@ -4904,6 +5132,22 @@ msgstr "Maksymalizuj" msgid "Maximize browser" msgstr "Zmaksymalizuj przeglądarkę" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Maximum attempts" +msgstr "Maksymalna liczba prób" + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Maximum iterations" +msgstr "Maksymalna liczba iteracji" + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Maximum retry delay" +msgstr "Maksymalne opóźnienie ponowienia" + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Maximum retry delay in seconds" +msgstr "Maksymalne opóźnienie ponowienia w sekundach" + #: src/renderer/components/skills/SkillMarketplaceModal.tsx #~ msgid "MCP Market" #~ msgstr "MCP Market" @@ -5110,6 +5354,18 @@ msgstr "Minimalizuj do panelu" msgid "Minute" msgstr "Minuta" +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Minute, hour, day of month, month, and weekday." +msgstr "Minuta, godzina, dzień miesiąca, miesiąc i dzień tygodnia." + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "minutes" +msgstr "minuty" + +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Minutes" +msgstr "Minuty" + #: src/mobile/views/BrowserView.tsx msgid "Mirrored desktop browser tab" msgstr "Lustrzana karta przeglądarki desktopa" @@ -5118,6 +5374,10 @@ msgstr "Lustrzana karta przeglądarki desktopa" msgid "Mirroring is unavailable." msgstr "Kopia lustrzana jest niedostępna." +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Missed runs" +msgstr "Pominięte uruchomienia" + #: src/renderer/views/SettingsOverlay/parts/RemoteAccessSettings.tsx msgid "Mobile push notifications" msgstr "Mobilne powiadomienia push" @@ -5469,6 +5729,10 @@ msgstr "Następne dopasowanie" msgid "Next recently viewed chat" msgstr "Następny ostatnio wyświetlany czat" +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Next run" +msgstr "Następne uruchomienie" + #. placeholder {0}: dateTimeFormatter.format(new Date(task.nextRunAt)) #: src/renderer/views/SchedulesView/SchedulesView.tsx msgid "Next run {0}" @@ -5514,6 +5778,10 @@ msgstr "Brak zainstalowanych agentów." msgid "No AI commits, PRs, or conflict resolutions tracked yet." msgstr "Nie zarejestrowano jeszcze żadnych commitów AI, PR ani rozwiązanych konfliktów." +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "No archived findings." +msgstr "Brak zarchiwizowanych ustaleń." + #: src/renderer/views/SettingsOverlay/parts/ArchivedThreadsSettings.tsx msgid "No archived threads." msgstr "Brak zarchiwizowanych wątków." @@ -5610,6 +5878,10 @@ msgstr "Brak dostępnych różnic dla {0}" msgid "No diff for {visiblePath}" msgstr "Brak różnicy dla {visiblePath}" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "No eligible conversations in this project." +msgstr "Brak odpowiednich rozmów w tym projekcie." + #: src/renderer/components/skills/SkillImportModal.tsx msgid "No external skills were found in this scope." msgstr "Nie znaleziono zewnętrznych umiejętności w tym zakresie." @@ -5625,6 +5897,10 @@ msgstr "Dla tej wiadomości nie jest przechowywany żaden punkt kontrolny pliku. msgid "No files match \"{0}\"." msgstr "Żadne pliki nie pasują do „{0}”." +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "No findings yet." +msgstr "Nie ma jeszcze żadnych ustaleń." + #: src/renderer/views/MainView/parts/CreateProject/CloneProjectModal.tsx msgid "No GitHub CLI accounts found. Sign in with <0>gh auth login, or <1>paste a clone URL." msgstr "Nie znaleziono kont GitHub CLI. Zaloguj się za pomocą <0>gh auth login lub <1>wklej sklonowany adres URL." @@ -5637,6 +5913,10 @@ msgstr "Brak historii" msgid "No Lightcode data was found." msgstr "Nie znaleziono danych Lightcode." +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "No limit" +msgstr "Bez limitu" + #: src/renderer/components/skills/SkillMarketplaceModal.tsx msgid "No marketplace skills match these filters." msgstr "Żadne umiejętności z marketplace nie pasują do tych filtrów." @@ -5653,6 +5933,10 @@ msgstr "Brak dopasowań." msgid "No matching agents." msgstr "Brak pasujących agentów." +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "No matching findings." +msgstr "Brak pasujących ustaleń." + #: src/renderer/views/PullRequestsView/PullRequestsView.tsx msgid "No matching pull requests." msgstr "Brak pasujących żądań ściągnięcia." @@ -5762,6 +6046,10 @@ msgstr "Nie znaleziono repozytoriów." msgid "No results" msgstr "Brak wyników" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "No retries" +msgstr "Bez ponowień" + #: src/renderer/views/SchedulesView/parts/PreviousRunsModal.tsx msgid "No runs yet." msgstr "Brak uruchomień." @@ -5798,6 +6086,10 @@ msgstr "Nie wykryto mowy." msgid "No staged changes" msgstr "Żadnych zmian etapowych" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "No summary was provided." +msgstr "Nie podano podsumowania." + #: src/renderer/views/RemoteProjectModal/RemoteProjectModal.tsx msgid "No supported agents are installed on this remote machine. Install and sign in to an agent remotely before starting a thread." msgstr "Na tym komputerze zdalnym nie zainstalowano obsługiwanych agentów. Zainstaluj agenta i zaloguj się zdalnie przed rozpoczęciem wątku." @@ -5827,6 +6119,10 @@ msgstr "Nie ma jeszcze wątków" msgid "No threads yet." msgstr "Brak wątków." +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "No upcoming run" +msgstr "Brak zaplanowanego uruchomienia" + #: src/renderer/components/providers/usageFormat.ts msgid "No windows reported" msgstr "Nie zgłoszono żadnych okien" @@ -6042,6 +6338,11 @@ msgstr "Otwórz commit na GitHubie" msgid "Open conflict resolver in" msgstr "Otwórz narzędzie do rozwiązywania konfliktów w" +#. placeholder {0}: props.scheduleName +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Open conversation for {0}" +msgstr "Otwórz rozmowę dla {0}" + #: src/renderer/views/SettingsOverlay/parts/settingsOptions.ts msgid "Open dialog" msgstr "Otwórz okno dialogowe" @@ -6677,6 +6978,10 @@ msgstr "Zaktualizowano folder projektu. Otwórz ponownie wszystkie terminale w t msgid "Project name" msgstr "Nazwa projektu" +#: src/renderer/i18n/sharedMessages.ts +msgid "Project no longer exists." +msgstr "Projekt już nie istnieje." + #: src/renderer/views/MainView/parts/RightPanel/parts/NotesPanel/NotesEditor.tsx msgid "Project notes" msgstr "Notatki projektowe" @@ -7275,6 +7580,10 @@ msgstr "Szczegóły żądania" msgid "requested changes" msgstr "żądane zmiany" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Required confidence before stopping." +msgstr "Wymagany poziom pewności przed zatrzymaniem." + #: src/mobile/views/pr/PrOverviewPage.tsx #: src/renderer/views/GitReviewOverlay/parts/GitReviewSidebar/parts/PrSection.tsx msgid "Required reviews, conversations, or status checks not met." @@ -7346,6 +7655,10 @@ msgstr "Przywróć przeglądarkę" msgid "Restore default worktree base folder" msgstr "Przywróć domyślny folder bazowy drzew roboczych" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Restore finding" +msgstr "Przywróć ustalenie" + #: src/mobile/settingsSections.ts msgid "Restore or delete" msgstr "Przywróć lub usuń" @@ -7376,10 +7689,26 @@ msgstr "Ponów sprawdzanie {serverName}" msgid "Retry check" msgstr "Ponów sprawdzanie" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Retry delay" +msgstr "Opóźnienie ponowienia" + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Retry delay in seconds" +msgstr "Opóźnienie ponowienia w sekundach" + #: src/mobile/components.tsx msgid "Retry now" msgstr "Spróbuj teraz" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Retry policy" +msgstr "Zasady ponawiania" + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Retry when a run fails before it completes." +msgstr "Ponów, gdy uruchomienie nie powiedzie się przed zakończeniem." + #: src/renderer/hooks/usePrWriteActions.ts msgid "Retry with admin" msgstr "Spróbuj ponownie z administratorem" @@ -7535,18 +7864,26 @@ msgstr "Uruchom lokalną transkrypcję na GPU, jeśli jest dostępna." msgid "Run now" msgstr "Uruchom teraz" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Run once after reopening" +msgstr "Uruchom raz po ponownym otwarciu" + #: src/renderer/views/SchedulesView/SchedulesView.tsx #~ msgid "Run standalone tasks on this device without a project." #~ msgstr "Uruchamiaj samodzielne zadania na tym urządzeniu bez projektu." #: src/renderer/views/SchedulesView/SchedulesView.tsx -msgid "Run standalone tasks on this device. Schedules run while the device is awake and Poracode is open." -msgstr "Uruchamiaj niezależne zadania na tym urządzeniu. Harmonogramy działają, gdy urządzenie jest aktywne, a Poracode otwarte." +#~ msgid "Run standalone tasks on this device. Schedules run while the device is awake and Poracode is open." +#~ msgstr "Uruchamiaj niezależne zadania na tym urządzeniu. Harmonogramy działają, gdy urządzenie jest aktywne, a Poracode otwarte." #: src/renderer/commands/registry.ts msgid "Run Terminal Command" msgstr "Uruchom polecenie terminala" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Run the latest missed run" +msgstr "Wykonaj ostatnie pominięte uruchomienie" + #: src/renderer/views/SchedulesView/ScheduleEditor.tsx #~ msgid "Run this schedule automatically at the times above." #~ msgstr "Automatycznie uruchamiaj ten harmonogram w powyższych godzinach." @@ -7562,6 +7899,7 @@ msgstr "uruchomiony" #: src/renderer/utils/prStatus.ts #: src/renderer/views/SchedulesView/parts/PreviousRunsModal.tsx +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx msgid "Running" msgstr "W trakcie" @@ -7585,6 +7923,10 @@ msgstr "Wyczerpie się wcześnie" msgid "Runs out in {runOut}" msgstr "Wyczerpie się za {runOut}" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Runs that need attention will appear here." +msgstr "Uruchomienia wymagające uwagi pojawią się tutaj." + #: src/renderer/views/MainView/parts/CreateProject/CloneProjectModal.tsx #: src/renderer/views/MainView/parts/CreateProject/CreateProjectModal.tsx msgid "Runtime" @@ -7661,6 +8003,10 @@ msgstr "Skanowanie systemu Windows i WSL w poszukiwaniu zainstalowanych interfej msgid "Scanning your system for installed CLIs. This usually takes a couple of seconds." msgstr "Skanowanie systemu w poszukiwaniu zainstalowanych interfejsów CLI. Zwykle zajmuje to kilka sekund." +#: src/renderer/views/SchedulesView/SchedulesView.tsx +msgid "Schedule autonomous work and review results that need your attention. Automations run while this device is awake and Poracode is open." +msgstr "Planuj autonomiczną pracę i przeglądaj wyniki wymagające Twojej uwagi. Automatyzacje działają, gdy to urządzenie jest aktywne, a Poracode otwarte." + #: src/renderer/views/SchedulesView/ScheduleEditor.tsx msgid "Schedule name" msgstr "Nazwa harmonogramu" @@ -7669,20 +8015,31 @@ msgstr "Nazwa harmonogramu" msgid "Schedule status" msgstr "Stan harmonogramu" +#: src/renderer/i18n/sharedMessages.ts +msgid "Scheduled retry was cancelled." +msgstr "Zaplanowane ponowienie zostało anulowane." + +#: src/renderer/i18n/sharedMessages.ts +msgid "Scheduled task was deleted before retrying." +msgstr "Zaplanowane zadanie zostało usunięte przed ponowieniem." + #: src/renderer/views/SchedulesView/SchedulesView.tsx -msgid "Scheduled tasks" -msgstr "Zaplanowane zadania" +#~ msgid "Scheduled tasks" +#~ msgstr "Zaplanowane zadania" #: src/mobile/settingsSections.ts -msgid "Scheduled tasks on this desktop" -msgstr "Zaplanowane zadania na tym komputerze" +#~ msgid "Scheduled tasks on this desktop" +#~ msgstr "Zaplanowane zadania na tym komputerze" #: src/renderer/views/SchedulesView/SchedulesView.tsx #~ msgid "Scheduled tasks run only while this device is awake and Poracode is open." #~ msgstr "Zaplanowane zadania są uruchamiane tylko wtedy, gdy urządzenie jest aktywne, a Poracode jest otwarty." #: src/mobile/settingsSections.ts -#: src/renderer/views/MainView/parts/Sidebar/Sidebar.tsx +msgid "Scheduled work and triage on this desktop" +msgstr "Zaplanowana praca i weryfikacja na tym komputerze" + +#: src/renderer/views/SchedulesView/SchedulesView.tsx msgid "Schedules" msgstr "Harmonogramy" @@ -7737,6 +8094,10 @@ msgstr "Szukaj gałęzi..." msgid "Search files" msgstr "Wyszukaj pliki" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Search findings" +msgstr "Szukaj ustaleń" + #: src/renderer/components/skills/SkillMarketplaceModal.tsx msgid "Search marketplace skills" msgstr "Przeszukaj umiejętności w marketplace" @@ -7831,6 +8192,10 @@ msgstr "Wyszukiwanie..." msgid "Searching…" msgstr "Wyszukiwanie…" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "seconds" +msgstr "sekundy" + #: src/renderer/components/skills/SkillMarketplaceModal.tsx #~ msgid "Security-focused directory with verified skill metadata." #~ msgstr "Katalog ukierunkowany na bezpieczeństwo ze zweryfikowanymi metadanymi skilli." @@ -8221,6 +8586,10 @@ msgstr "Wylogowywanie z {env}. Wykryci agenci zostaną odświeżeni po zakończe msgid "Signing out. Detected agents will refresh when it finishes." msgstr "Wylogowanie. Wykryci agenci zostaną odświeżeni po zakończeniu." +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Single pass" +msgstr "Pojedyncze wykonanie" + #: src/renderer/components/skills/SkillImportModal.tsx #: src/renderer/components/skills/SkillMarketplaceModal.tsx msgid "Skill availability" @@ -8285,7 +8654,12 @@ msgstr "Marketplace umiejętności" msgid "Skills.sh" msgstr "Skills.sh" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Skip missed runs" +msgstr "Pomijaj nieodbyte uruchomienia" + #: src/renderer/utils/prStatus.ts +#: src/renderer/views/SchedulesView/parts/PreviousRunsModal.tsx msgid "Skipped" msgstr "Pominięto" @@ -8424,6 +8798,10 @@ msgstr "Uruchom {appName}, aby zobaczyć użycie" msgid "Start a dev server on your desktop, then tap refresh." msgstr "Uruchom serwer deweloperski na komputerze, a następnie dotknij Odśwież." +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Start a new conversation for each run." +msgstr "Rozpocznij nową rozmowę dla każdego uruchomienia." + #: src/renderer/commands/registry.ts msgid "Start a new thread as panel instead of page" msgstr "Otwórz nowy wątek jako panel zamiast strony" @@ -8562,6 +8940,10 @@ msgstr "Zatrzymaj" msgid "Stop forwarding" msgstr "Zatrzymaj przekierowywanie" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Stop on error" +msgstr "Zatrzymaj po błędzie" + #: src/renderer/components/thread/ThreadComposer.tsx msgid "Stop response" msgstr "Zatrzymaj odpowiedź" @@ -8574,10 +8956,18 @@ msgstr "Zatrzymaj zadanie" msgid "Stop the project's running threads before changing its folder." msgstr "Zatrzymaj uruchomione wątki projektu przed zmianą jego folderu." +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Stop the run when this total time is reached." +msgstr "Zatrzymaj uruchomienie po osiągnięciu tego łącznego czasu." + #: src/renderer/components/composer/VoiceInputButton.tsx msgid "Stop voice input" msgstr "Zatrzymaj wprowadzanie głosowe" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Stop when" +msgstr "Zatrzymaj, gdy" + #: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts #: src/renderer/views/SettingsOverlay/parts/WorktreeSettings.tsx msgid "Storage location" @@ -8922,6 +9312,22 @@ msgstr "Agent" msgid "the app" msgstr "aplikacja" +#: src/renderer/i18n/sharedMessages.ts +msgid "The automation conversation exited before the turn completed." +msgstr "Rozmowa automatyzacji zakończyła się przed ukończeniem tury." + +#: src/renderer/i18n/sharedMessages.ts +msgid "The automation exceeded its time limit." +msgstr "Automatyzacja przekroczyła limit czasu." + +#: src/renderer/i18n/sharedMessages.ts +msgid "The automation needs a reply before it can continue." +msgstr "Automatyzacja wymaga odpowiedzi, zanim będzie mogła kontynuować." + +#: src/renderer/i18n/sharedMessages.ts +msgid "The automation needs approval before it can continue." +msgstr "Automatyzacja wymaga zatwierdzenia, zanim będzie mogła kontynuować." + #: src/renderer/views/MainView/parts/CreateProject/CloneProjectModal.tsx msgid "the chosen folder" msgstr "wybrany folder" @@ -8935,11 +9341,39 @@ msgstr "Domyślna częstotliwość odświeżania w tle, używana dla każdego do msgid "The desktop server is still coming online." msgstr "Serwer komputera nadal się uruchamia." +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "The finding is no longer available." +msgstr "Ustalenie nie jest już dostępne." + #. placeholder {0}: createTarget.wslDistro #: src/renderer/components/skills/SkillsManager.tsx msgid "the global {0} WSL scope" msgstr "globalny zakres WSL {0}" +#: src/renderer/i18n/sharedMessages.ts +msgid "The heartbeat conversation belongs to a different project." +msgstr "Rozmowa heartbeat należy do innego projektu." + +#: src/renderer/i18n/sharedMessages.ts +msgid "The heartbeat conversation cannot be resumed." +msgstr "Rozmowy heartbeat nie można wznowić." + +#: src/renderer/i18n/sharedMessages.ts +msgid "The heartbeat conversation is archived." +msgstr "Konwersacja heartbeat jest zarchiwizowana." + +#: src/renderer/i18n/sharedMessages.ts +msgid "The heartbeat conversation is currently busy." +msgstr "Rozmowa heartbeat jest obecnie zajęta." + +#: src/renderer/i18n/sharedMessages.ts +msgid "The heartbeat conversation no longer exists." +msgstr "Rozmowa heartbeat już nie istnieje." + +#: src/renderer/i18n/sharedMessages.ts +msgid "The heartbeat conversation uses a different agent." +msgstr "Rozmowa heartbeat używa innego agenta." + #: src/renderer/components/skills/SkillsManager.tsx msgid "the Linux user" msgstr "użytkownika systemu Linux" @@ -8972,6 +9406,14 @@ msgstr "Serwer zdalny nie zwrócił danych uwierzytelniających parowania." msgid "The repository location on disk. Update it if you moved the folder." msgstr "Lokalizacja repozytorium na dysku. Zaktualizuj ją, jeśli przeniesiono folder." +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "The run could not be cancelled." +msgstr "Nie udało się anulować uruchomienia." + +#: src/renderer/i18n/sharedMessages.ts +msgid "The scheduled automation failed." +msgstr "Zaplanowana automatyzacja nie powiodła się." + #: src/renderer/components/mcp/McpServersManager.tsx #~ msgid "The selected file does not contain valid MCP server configurations." #~ msgstr "Wybrany plik nie zawiera prawidłowych konfiguracji serwerów MCP." @@ -9227,6 +9669,18 @@ msgstr "Wątki oznaczone jako zakończone, które nie były poruszane przez tyle msgid "Time" msgstr "Godzina" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Time limit" +msgstr "Limit czasu" + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Time limit in minutes" +msgstr "Limit czasu w minutach" + +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Time zone" +msgstr "Strefa czasowa" + #: src/renderer/components/mcp/McpServerEditor.tsx msgid "Timeout (ms)" msgstr "Limit czasu (ms)" @@ -9356,6 +9810,10 @@ msgstr "Półprzezroczysty pasek boczny" msgid "Trending now" msgstr "Popularne teraz" +#: src/renderer/views/SchedulesView/SchedulesView.tsx +msgid "Triage" +msgstr "Weryfikacja" + #: src/mobile/views/DesktopsView.tsx msgid "Trust and connect" msgstr "Zaufaj i połącz" @@ -9598,6 +10056,10 @@ msgstr "Nieprzypisany" msgid "Unavailable" msgstr "Niedostępny" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Unavailable conversation" +msgstr "Niedostępna rozmowa" + #: src/renderer/views/SchedulesView/ScheduleEditor.tsx msgid "Unavailable project" msgstr "Niedostępny projekt" @@ -9676,6 +10138,10 @@ msgstr "Bez fazy:" msgid "Unpin" msgstr "Odepnij" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Unread" +msgstr "Nieprzeczytane" + #: src/mobile/views/GitActionSheet.tsx #: src/renderer/views/GitReviewOverlay/parts/GitReviewSidebar/parts/FileRow.tsx #: src/renderer/views/GitReviewOverlay/parts/GitStackedDiff.tsx @@ -10002,6 +10468,12 @@ msgstr "Oczekiwanie na uwierzytelnienie {methodName}. Wykryci agenci zostaną od msgid "waiting for agent to stop" msgstr "czekanie, aż agent się zatrzyma" +#: src/renderer/views/SchedulesView/parts/PreviousRunsModal.tsx +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +#: src/renderer/views/SchedulesView/SchedulesView.tsx +msgid "Waiting for approval" +msgstr "Oczekiwanie na zatwierdzenie" + #: src/renderer/components/thread/ChatPane/parts/items/WorkflowOverlayBody.tsx msgid "Waiting for workflow to spawn agents…" msgstr "Oczekiwanie, aż przepływ pracy utworzy agentów…" @@ -10034,6 +10506,10 @@ msgstr "Rozgrzewanie środowisk powłoki..." msgid "Warming up WSL shell environment…" msgstr "Rozgrzewanie środowiska powłoki WSL…" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Warning" +msgstr "Ostrzeżenie" + #: src/renderer/components/thread/ChatPane/parts/items/ToolCallGroup.tsx #: src/renderer/components/thread/ChatPane/parts/items/toolDisplay.ts #: src/renderer/components/thread/ChatPane/parts/items/WebSearchItem.tsx @@ -10326,6 +10802,10 @@ msgstr "Folder bazowy WSL" #~ msgid "WSL user" #~ msgstr "Użytkownik WSL" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "You’re all caught up." +msgstr "Wszystko gotowe." + #: src/renderer/views/ProfileOverlay/parts/EditProfileDialog.tsx msgid "Your name" msgstr "Twoje imię" diff --git a/src/renderer/locales/pt-BR/messages.po b/src/renderer/locales/pt-BR/messages.po index 001bc8cd7..89e657be6 100644 --- a/src/renderer/locales/pt-BR/messages.po +++ b/src/renderer/locales/pt-BR/messages.po @@ -288,6 +288,11 @@ msgstr "{agentLabel}: {statusLabel}. Passe o mouse para ver os detalhes do statu msgid "{agentLead} needs your input to continue." msgstr "{agentLead} precisa da sua resposta para continuar." +#. placeholder {0}: task.recurrence.timeZone +#: src/renderer/views/SchedulesView/SchedulesView.tsx +msgid "{cadence} in {0}" +msgstr "{cadence} em {0}" + #: src/mobile/views/pr/PrOverviewPage.tsx msgid "{commitsCount, plural, one {# commit} other {# commits}}" msgstr "{commitsCount, plural, one {# commit} other {# commits}}" @@ -315,6 +320,18 @@ msgstr "há {days}d" msgid "{envOrAgentLabel} needs authentication." msgstr "{envOrAgentLabel} precisa de autenticação." +#: src/renderer/views/SchedulesView/SchedulesView.tsx +msgid "{every, plural, one {Every day} other {Every # days}}" +msgstr "{every, plural, one {Todos os dias} other {A cada # dias}}" + +#: src/renderer/views/SchedulesView/SchedulesView.tsx +msgid "{every, plural, one {Every hour} other {Every # hours}}" +msgstr "{every, plural, one {A cada hora} other {A cada # horas}}" + +#: src/renderer/views/SchedulesView/SchedulesView.tsx +msgid "{every, plural, one {Every minute} other {Every # minutes}}" +msgstr "{every, plural, one {A cada minuto} other {A cada # minutos}}" + #: src/mobile/views/pr/PrOverviewPage.tsx msgid "{filesCount, plural, one {# file changed} other {# files changed}}" msgstr "{filesCount, plural, one {# arquivo alterado} other {# arquivos alterados}}" @@ -491,6 +508,10 @@ msgstr "~{money}{tokens} · {0} · est." msgid "≈{0}% by reset" msgstr "≈{0}% até a redefinição" +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "0 9 * * 1-5" +msgstr "0 9 * * 1-5" + #: src/mobile/views/ThreadsView.tsx msgid "1 thread" msgstr "1 thread" @@ -840,6 +861,10 @@ msgstr "Ações de git com IA" msgid "AI providers" msgstr "Provedores de IA" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "AI stop condition" +msgstr "Condição de parada por IA" + #: src/mobile/views/MoreView.tsx #~ msgid "AI, agents, and archived threads on the paired desktop" #~ msgstr "IA, agentes e tópicos arquivados no desktop pareado" @@ -851,6 +876,7 @@ msgstr "Alertas quando threads precisam de você" #: src/renderer/commands/shortcutCatalog.ts #: src/renderer/components/skills/SkillsManager.tsx #: src/renderer/views/PullRequestsView/PullRequestsView.tsx +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx #: src/renderer/views/SchedulesView/SchedulesView.tsx #: src/renderer/views/SettingsOverlay/parts/ProfileSettings.tsx msgid "All" @@ -943,6 +969,10 @@ msgstr "Sempre excluído" msgid "An MCP server with this name already exists." msgstr "Já existe um servidor MCP com este nome." +#: src/renderer/i18n/sharedMessages.ts +msgid "Another automation is already using this conversation." +msgstr "Outra automação já está usando esta conversa." + #: src/renderer/components/thread/ChatPane/parts/CheckpointRevertControls.tsx msgid "Another chat uses this same tree. File restore could overwrite that chat's changes." msgstr "Outro chat usa esta mesma árvore. A restauração de arquivos pode substituir as alterações do bate-papo." @@ -1014,6 +1044,10 @@ msgstr "Arquivar tudo" msgid "Archive all threads" msgstr "Arquivar todas as threads" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Archive finding" +msgstr "Arquivar resultado" + #: src/renderer/commands/registry.ts msgid "Archive the current thread" msgstr "Arquivar o tópico atual" @@ -1028,6 +1062,10 @@ msgstr "Arquivar tópico" msgid "Archive Thread" msgstr "Arquivar Tópico" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Archived" +msgstr "Arquivados" + #: src/mobile/settingsSections.ts #: src/mobile/views/SettingsView.tsx #: src/renderer/views/SettingsOverlay/parts/ArchivedThreadsSettings.tsx @@ -1173,6 +1211,16 @@ msgstr "Mostrar painel do terminal automaticamente" msgid "Automatically show the terminal panel when running commands or creating worktrees." msgstr "Mostrar automaticamente o painel do terminal ao executar comandos ou criar árvores de trabalho." +#: src/renderer/views/SchedulesView/SchedulesView.tsx +msgid "Automation sections" +msgstr "Seções de automação" + +#: src/mobile/settingsSections.ts +#: src/renderer/views/MainView/parts/Sidebar/Sidebar.tsx +#: src/renderer/views/SchedulesView/SchedulesView.tsx +msgid "Automations" +msgstr "Automações" + #: src/renderer/components/skills/SkillImportModal.tsx msgid "Availability" msgstr "Disponibilidade" @@ -1459,6 +1507,10 @@ msgstr "Ignorar regras de proteção de branch (mesclagem de administrador)" msgid "Cached only" msgstr "Somente em cache" +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Calculated on desktop after saving" +msgstr "Calculado no desktop após salvar" + #: src/mobile/QrScanner.tsx msgid "Camera access blocked" msgstr "Acesso à câmera bloqueado" @@ -1513,11 +1565,16 @@ msgstr "Cancelar seletor" msgid "Cancel removing project" msgstr "Cancelar remoção do projeto" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Cancel run" +msgstr "Cancelar execução" + #: src/renderer/components/thread/ChatPane/parts/items/WorkflowOverlayBody.tsx msgid "cancelled" msgstr "cancelado" #: src/renderer/utils/prStatus.ts +#: src/renderer/views/SchedulesView/parts/PreviousRunsModal.tsx msgid "Cancelled" msgstr "Cancelado" @@ -1706,6 +1763,10 @@ msgstr "Escolha o idioma de exibição da interface do Poracode." msgid "Choose thread to attach to" msgstr "Escolha o tópico ao qual anexar" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Choose what happens after a scheduled time was missed." +msgstr "Escolha o que acontece quando um horário agendado é perdido." + #: src/renderer/views/SettingsOverlay/parts/BrowserSettings.tsx #: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts msgid "Choose whether links from Poracode and browser popups stay in Poracode or open externally." @@ -2185,6 +2246,14 @@ msgstr "concluído" msgid "Completed" msgstr "Concluído" +#: src/renderer/i18n/sharedMessages.ts +msgid "Completion evaluation failed: {detail}" +msgstr "Falha na avaliação de conclusão: {detail}" + +#: src/renderer/i18n/sharedMessages.ts +msgid "Completion evaluation is unavailable." +msgstr "A avaliação de conclusão não está disponível." + #: src/renderer/commands/shortcutCatalog.ts #: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx #: src/renderer/views/SettingsOverlay/parts/settingsOptions.ts @@ -2223,6 +2292,14 @@ msgstr "Computer Use ativado — ações interativas assumem o controle da área #~ msgid "Computer Use enabled for this thread" #~ msgstr "Uso do computador ativado para este tópico" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Confidence" +msgstr "Confiança" + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Confidence percent" +msgstr "Percentual de confiança" + #: src/renderer/views/SettingsOverlay/parts/ClaudeProfileSettings.tsx msgid "Config directory" msgstr "Diretório de configuração" @@ -2386,6 +2463,14 @@ msgstr "Continuar em outro provedor" msgid "Continue in..." msgstr "Continuar em..." +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Continue one conversation until a stop condition or limit is reached." +msgstr "Continue uma conversa até que uma condição de parada ou um limite seja atingido." + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Control how each scheduled run continues and stops." +msgstr "Controle como cada execução agendada continua e para." + #: src/renderer/views/SettingsOverlay/parts/SearchSettings.tsx msgid "Control which files appear in the @file mention search. Per-project overrides live in each project's settings." msgstr "Controle quais arquivos aparecem na pesquisa de menção @file. As substituições por projeto estão disponíveis nas configurações de cada projeto." @@ -2397,6 +2482,7 @@ msgstr "Controla a área de trabalho emparelhada enquanto o agente clica ou digi #: src/mobile/views/pr/PrConversationPage.tsx #: src/mobile/views/pr/PrOverviewPage.tsx #: src/renderer/views/PrReviewOverlay/parts/PrTabsPill.tsx +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx msgid "Conversation" msgstr "Conversa" @@ -2697,6 +2783,24 @@ msgstr "As credenciais estão configuradas." msgid "Credits" msgstr "Créditos" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Critical" +msgstr "Crítico" + +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Cron" +msgstr "Cron" + +#. placeholder {0}: task.recurrence.expression +#. placeholder {1}: task.recurrence.timeZone +#: src/renderer/views/SchedulesView/SchedulesView.tsx +msgid "Cron {0} in {1}" +msgstr "Cron {0} em {1}" + +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Cron expression" +msgstr "Expressão cron" + #: src/renderer/components/skills/SkillMarketplaceModal.tsx #~ msgid "Curated free and premium skills managed by MCP Market." #~ msgstr "Skills gratuitas e premium selecionadas e gerenciadas pelo MCP Market." @@ -2762,9 +2866,9 @@ msgstr "Resumo diário" msgid "Dark" msgstr "Escuro" -#: src/renderer/views/SchedulesView/SchedulesView.tsx -#~ msgid "Days" -#~ msgstr "Dias" +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Days" +msgstr "Dias" #: src/renderer/components/thread/ThreadRuntimeRequestPanel/structuredElicitation.tsx msgid "Decline" @@ -2911,6 +3015,10 @@ msgstr "Excluir árvore de trabalho {0}" #~ msgid "Delete:" #~ msgstr "Excluir:" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Deleted schedule" +msgstr "Agendamento excluído" + #: src/renderer/views/SettingsOverlay/parts/AcpRegistrySettings.tsx msgid "Deleting" msgstr "Excluindo" @@ -2923,6 +3031,10 @@ msgstr "Negar" msgid "Deny and tell the agent what to do differently…" msgstr "Negue e diga ao agente o que fazer de diferente…" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Describe the result that completes this heartbeat." +msgstr "Descreva o resultado que conclui este heartbeat." + #: src/renderer/views/SchedulesView/ScheduleEditor.tsx msgid "Describe what the agent should do" msgstr "Descreva o que o agente deve fazer" @@ -2944,6 +3056,10 @@ msgstr "Endpoint do desktop" msgid "Desktop is unreachable." msgstr "O desktop está inacessível." +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Desktop local time" +msgstr "Hora local do desktop" + #: src/mobile/chrome.ts #: src/mobile/views/MoreView.tsx msgid "Desktop Settings" @@ -3056,6 +3172,10 @@ msgstr "Desativar projeto" msgid "Disable Subagents" msgstr "Desativar subagentes" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Disable the automation after retries are exhausted." +msgstr "Desative a automação depois que todas as tentativas forem esgotadas." + #: src/renderer/views/SettingsOverlay/parts/ClaudeProfileSettings.tsx msgid "Disable tiers an external provider collapses (e.g. keep only High and Max)." msgstr "Desative níveis que um provedor externo agrupa (ex.: manter apenas High e Max)." @@ -3356,6 +3476,10 @@ msgstr "Os servidores ativados permanecem ativos para novos tópicos" msgid "Enables <0>cookies and <1>storage. Cookies can contain session tokens and storage often holds auth state — only enable when you trust both the agent and the sites it visits." msgstr "Ativa <0>cookies e <1>armazenamento. Os cookies podem conter tokens de sessão e o armazenamento geralmente mantém o estado de autenticação – ativado apenas quando você confia no agente e nos sites que ele visita." +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +#~ msgid "End the heartbeat after retries are exhausted." +#~ msgstr "Encerre o heartbeat após esgotar as tentativas." + #: src/mobile/views/DesktopsView.tsx #: src/renderer/views/SettingsOverlay/parts/RemoteServersSettings.tsx msgid "Endpoint" @@ -3393,6 +3517,10 @@ msgstr "Insira um endpoint de desktop válido." msgid "Enter a valid HTTP or HTTPS URL." msgstr "Insira uma URL HTTP ou HTTPS válida." +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Enter a valid schedule" +msgstr "Insira um agendamento válido" + #: src/mobile/views/DesktopsView.tsx msgid "Enter a valid SSH target and port." msgstr "Insira um destino SSH e uma porta válidos." @@ -3463,6 +3591,14 @@ msgstr "Erro" msgid "Error · Agent encountered an error" msgstr "Erro · O agente encontrou um erro" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Evaluate the result after every iteration." +msgstr "Avalie o resultado após cada iteração." + +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Every" +msgstr "A cada" + #: src/renderer/views/SchedulesView/SchedulesView.tsx msgid "Every day at {time}" msgstr "Todos os dias às {time}" @@ -3485,6 +3621,14 @@ msgstr "A cada hora, aos {0} minutos" msgid "Exclude patterns" msgstr "Padrões de exclusão" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Execution" +msgstr "Execução" + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Execution mode" +msgstr "Modo de execução" + #: src/renderer/components/thread/ChatPane/parts/items/toolDisplay.ts msgid "Exit plan mode" msgstr "Sair do modo de plano" @@ -3534,6 +3678,10 @@ msgstr "Expanda para revisar ou revogar o acesso." msgid "Expand todo dock" msgstr "Expandir dock de tarefas" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Exponential backoff" +msgstr "Atraso exponencial" + #: src/renderer/components/mcp/McpServersManager.tsx msgid "Export MCP servers" msgstr "Exportar servidores MCP" @@ -3716,6 +3864,10 @@ msgstr "Localizar na comparação" msgid "Find in terminal" msgstr "Localizar no terminal" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Finding status" +msgstr "Status do resultado" + #: src/renderer/views/PrReviewOverlay/parts/SubmitReviewPopover.tsx msgid "Finish your review" msgstr "Conclua sua avaliação" @@ -3777,6 +3929,10 @@ msgstr "Correção no agente" msgid "Fixed" msgstr "Corrigido" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Fixed delay" +msgstr "Atraso fixo" + #: src/renderer/commands/registry.ts msgid "Focus browser address bar" msgstr "Acessar barra de endereços do navegador" @@ -4097,6 +4253,26 @@ msgstr "Há um rascunho não enviado" msgid "Headers" msgstr "Cabeçalhos" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Heartbeat" +msgstr "Heartbeat" + +#: src/renderer/i18n/sharedMessages.ts +msgid "Heartbeat automations require a native chat conversation." +msgstr "As automações de heartbeat exigem uma conversa de chat nativa." + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Heartbeat continues this conversation in the selected project." +msgstr "O heartbeat continua esta conversa no projeto selecionado." + +#: src/renderer/i18n/sharedMessages.ts +msgid "Heartbeat execution is unavailable." +msgstr "A execução de heartbeat não está disponível." + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Heartbeats can continue making changes while you're away. Set hard limits below." +msgstr "Os heartbeats podem continuar fazendo alterações enquanto você estiver ausente. Defina limites rígidos abaixo." + #: src/renderer/views/SchedulesView/SchedulesView.tsx msgid "Help me create a schedule. Ask for any missing details, then use the Poracode schedule controls to create it for me." msgstr "Ajude-me a criar um agendamento. Pergunte os detalhes que faltarem e use os controles de agendamento do Poracode para criá-lo." @@ -4198,6 +4374,10 @@ msgstr "host.com, alias ou usuário@host.com" msgid "Hourly" msgstr "A cada hora" +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Hours" +msgstr "Horas" + #: src/renderer/components/mcp/McpServerEditor.tsx msgid "HTTP (streamable)" msgstr "HTTP (com streaming)" @@ -4328,6 +4508,14 @@ msgstr "A leitura pela câmera dentro do app só funciona por HTTPS. Use o app d msgid "Inactive" msgstr "Inativo" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Includes the first attempt." +msgstr "Inclui a primeira tentativa." + +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Info" +msgstr "Informações" + #. Badge on an exclude pattern inherited from a lower scope #: src/renderer/views/SettingsOverlay/parts/SearchExcludeBody.tsx msgid "inherited" @@ -4338,6 +4526,14 @@ msgstr "herdado" msgid "Inheriting the global setting (currently {0})." msgstr "Herdando a configuração global (atualmente {0})." +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Initial retry delay" +msgstr "Atraso inicial da nova tentativa" + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Initial retry delay in seconds" +msgstr "Atraso inicial da nova tentativa em segundos" + #: src/renderer/views/GitReviewOverlay/parts/GitReviewSidebar/GitReviewSidebar.tsx msgid "Initialize Repository" msgstr "Inicializar repositório" @@ -4476,6 +4672,18 @@ msgstr "Interrompida" msgid "Interrupted: agent session ended before completion." msgstr "Interrompida: a sessão do agente terminou antes da conclusão." +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Interval" +msgstr "Intervalo" + +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Interval amount" +msgstr "Valor do intervalo" + +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Interval unit" +msgstr "Unidade do intervalo" + #: src/renderer/views/MainView/parts/RightPanel/parts/NotesPanel/NotesEditor.tsx msgid "Italic" msgstr "Itálico" @@ -4560,6 +4768,14 @@ msgstr "Iniciando…" msgid "Leave a comment" msgstr "Deixe um comentário" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Leave blank for no run limit." +msgstr "Deixe em branco para não limitar o número de execuções." + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +#~ msgid "Leave blank to rely on the time limit." +#~ msgstr "Deixe em branco para usar o limite de tempo." + #: src/renderer/views/ProfileOverlay/parts/ActivityHeatmap.tsx msgid "Less" msgstr "Menos" @@ -4640,6 +4856,10 @@ msgstr "Carregando editor…" msgid "Loading file…" msgstr "Carregando arquivo…" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Loading findings" +msgstr "Carregando resultados" + #: src/renderer/components/skills/SkillMarketplaceModal.tsx msgid "Loading marketplace…" msgstr "Carregando marketplace…" @@ -4864,6 +5084,14 @@ msgstr "Marcar como concluído" msgid "Mark as not done" msgstr "Marcar como não concluído" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Mark as read" +msgstr "Marcar como lido" + +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Mark as unread" +msgstr "Marcar como não lido" + #: src/renderer/components/thread/ThreadView.tsx msgid "Mark done" msgstr "Marcar como concluído" @@ -4904,6 +5132,22 @@ msgstr "Maximizar" msgid "Maximize browser" msgstr "Maximizar o navegador" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Maximum attempts" +msgstr "Máximo de tentativas" + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Maximum iterations" +msgstr "Máximo de iterações" + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Maximum retry delay" +msgstr "Atraso máximo da nova tentativa" + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Maximum retry delay in seconds" +msgstr "Atraso máximo da nova tentativa em segundos" + #: src/renderer/components/skills/SkillMarketplaceModal.tsx #~ msgid "MCP Market" #~ msgstr "MCP Market" @@ -5110,6 +5354,18 @@ msgstr "Minimizar para painel" msgid "Minute" msgstr "Minuto" +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Minute, hour, day of month, month, and weekday." +msgstr "Minuto, hora, dia do mês, mês e dia da semana." + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "minutes" +msgstr "minutos" + +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Minutes" +msgstr "Minutos" + #: src/mobile/views/BrowserView.tsx msgid "Mirrored desktop browser tab" msgstr "Aba espelhada do navegador do desktop" @@ -5118,6 +5374,10 @@ msgstr "Aba espelhada do navegador do desktop" msgid "Mirroring is unavailable." msgstr "O espelhamento está indisponível." +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Missed runs" +msgstr "Execuções perdidas" + #: src/renderer/views/SettingsOverlay/parts/RemoteAccessSettings.tsx msgid "Mobile push notifications" msgstr "Notificações push móveis" @@ -5469,6 +5729,10 @@ msgstr "Próxima ocorrência" msgid "Next recently viewed chat" msgstr "Próximo chat visualizado recentemente" +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Next run" +msgstr "Próxima execução" + #. placeholder {0}: dateTimeFormatter.format(new Date(task.nextRunAt)) #: src/renderer/views/SchedulesView/SchedulesView.tsx msgid "Next run {0}" @@ -5514,6 +5778,10 @@ msgstr "Nenhum agente instalado." msgid "No AI commits, PRs, or conflict resolutions tracked yet." msgstr "Nenhum commit, PR ou resolução de conflito por IA registrado ainda." +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "No archived findings." +msgstr "Nenhum resultado arquivado." + #: src/renderer/views/SettingsOverlay/parts/ArchivedThreadsSettings.tsx msgid "No archived threads." msgstr "Nenhum tópico arquivado." @@ -5610,6 +5878,10 @@ msgstr "Nenhuma diferença disponível para {0}" msgid "No diff for {visiblePath}" msgstr "Sem diferença para {visiblePath}" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "No eligible conversations in this project." +msgstr "Nenhuma conversa qualificada neste projeto." + #: src/renderer/components/skills/SkillImportModal.tsx msgid "No external skills were found in this scope." msgstr "Nenhuma skill externa foi encontrada neste escopo." @@ -5625,6 +5897,10 @@ msgstr "Nenhum ponto de verificação de arquivo é armazenado para esta mensage msgid "No files match \"{0}\"." msgstr "Nenhum arquivo corresponde a \"{0}\"." +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "No findings yet." +msgstr "Ainda não há resultados." + #: src/renderer/views/MainView/parts/CreateProject/CloneProjectModal.tsx msgid "No GitHub CLI accounts found. Sign in with <0>gh auth login, or <1>paste a clone URL." msgstr "Nenhuma conta GitHub CLI encontrada. Faça login com <0>gh auth login ou <1>cole um URL clone." @@ -5637,6 +5913,10 @@ msgstr "Ainda não há histórico" msgid "No Lightcode data was found." msgstr "Nenhum dado do Lightcode foi encontrado." +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "No limit" +msgstr "Sem limite" + #: src/renderer/components/skills/SkillMarketplaceModal.tsx msgid "No marketplace skills match these filters." msgstr "Nenhuma skill do marketplace corresponde a estes filtros." @@ -5653,6 +5933,10 @@ msgstr "Nenhuma correspondência." msgid "No matching agents." msgstr "Nenhum agente correspondente." +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "No matching findings." +msgstr "Nenhum resultado correspondente." + #: src/renderer/views/PullRequestsView/PullRequestsView.tsx msgid "No matching pull requests." msgstr "Nenhum pull request correspondente." @@ -5762,6 +6046,10 @@ msgstr "Nenhum repositório encontrado." msgid "No results" msgstr "Nenhum resultado" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "No retries" +msgstr "Sem novas tentativas" + #: src/renderer/views/SchedulesView/parts/PreviousRunsModal.tsx msgid "No runs yet." msgstr "Ainda não há execuções." @@ -5798,6 +6086,10 @@ msgstr "Nenhuma fala detectada." msgid "No staged changes" msgstr "Nenhuma alteração no stage" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "No summary was provided." +msgstr "Nenhum resumo foi fornecido." + #: src/renderer/views/RemoteProjectModal/RemoteProjectModal.tsx msgid "No supported agents are installed on this remote machine. Install and sign in to an agent remotely before starting a thread." msgstr "Nenhum agente compatível está instalado nesta máquina remota. Instale um agente e faça login remotamente antes de iniciar uma conversa." @@ -5827,6 +6119,10 @@ msgstr "Ainda não há threads" msgid "No threads yet." msgstr "Nenhuma thread ainda." +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "No upcoming run" +msgstr "Nenhuma execução futura" + #: src/renderer/components/providers/usageFormat.ts msgid "No windows reported" msgstr "Nenhuma janela relatada" @@ -6042,6 +6338,11 @@ msgstr "Abrir commit no GitHub" msgid "Open conflict resolver in" msgstr "Abrir resolvedor de conflitos em" +#. placeholder {0}: props.scheduleName +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Open conversation for {0}" +msgstr "Abrir conversa para {0}" + #: src/renderer/views/SettingsOverlay/parts/settingsOptions.ts msgid "Open dialog" msgstr "Abrir caixa de diálogo" @@ -6677,6 +6978,10 @@ msgstr "Pasta do projeto atualizada. Reabra os terminais neste projeto." msgid "Project name" msgstr "Nome do projeto" +#: src/renderer/i18n/sharedMessages.ts +msgid "Project no longer exists." +msgstr "O projeto não existe mais." + #: src/renderer/views/MainView/parts/RightPanel/parts/NotesPanel/NotesEditor.tsx msgid "Project notes" msgstr "Notas do projeto" @@ -7275,6 +7580,10 @@ msgstr "Solicitar detalhes" msgid "requested changes" msgstr "alterações solicitadas" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Required confidence before stopping." +msgstr "Confiança necessária antes de parar." + #: src/mobile/views/pr/PrOverviewPage.tsx #: src/renderer/views/GitReviewOverlay/parts/GitReviewSidebar/parts/PrSection.tsx msgid "Required reviews, conversations, or status checks not met." @@ -7346,6 +7655,10 @@ msgstr "Restaurar navegador" msgid "Restore default worktree base folder" msgstr "Redefinir pasta base da árvore de trabalho para o padrão" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Restore finding" +msgstr "Restaurar resultado" + #: src/mobile/settingsSections.ts msgid "Restore or delete" msgstr "Restaurar ou excluir" @@ -7376,10 +7689,26 @@ msgstr "Tentar {serverName} novamente" msgid "Retry check" msgstr "Tentar verificar novamente" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Retry delay" +msgstr "Atraso da nova tentativa" + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Retry delay in seconds" +msgstr "Atraso da nova tentativa em segundos" + #: src/mobile/components.tsx msgid "Retry now" msgstr "Tentar agora" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Retry policy" +msgstr "Política de novas tentativas" + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Retry when a run fails before it completes." +msgstr "Tente novamente quando uma execução falhar antes de ser concluída." + #: src/renderer/hooks/usePrWriteActions.ts msgid "Retry with admin" msgstr "Tentar novamente como administrador" @@ -7535,18 +7864,26 @@ msgstr "Execute a transcrição local na GPU quando disponível." msgid "Run now" msgstr "Executar agora" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Run once after reopening" +msgstr "Executar uma vez após reabrir" + #: src/renderer/views/SchedulesView/SchedulesView.tsx #~ msgid "Run standalone tasks on this device without a project." #~ msgstr "Execute tarefas independentes neste dispositivo sem um projeto." #: src/renderer/views/SchedulesView/SchedulesView.tsx -msgid "Run standalone tasks on this device. Schedules run while the device is awake and Poracode is open." -msgstr "Execute tarefas independentes neste dispositivo. Os agendamentos são executados enquanto o dispositivo está ativo e o Poracode está aberto." +#~ msgid "Run standalone tasks on this device. Schedules run while the device is awake and Poracode is open." +#~ msgstr "Execute tarefas independentes neste dispositivo. Os agendamentos são executados enquanto o dispositivo está ativo e o Poracode está aberto." #: src/renderer/commands/registry.ts msgid "Run Terminal Command" msgstr "Execute o comando do terminal" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Run the latest missed run" +msgstr "Executar a ocorrência perdida mais recente" + #: src/renderer/views/SchedulesView/ScheduleEditor.tsx #~ msgid "Run this schedule automatically at the times above." #~ msgstr "Executar este agendamento automaticamente nos horários acima." @@ -7562,6 +7899,7 @@ msgstr "em execução" #: src/renderer/utils/prStatus.ts #: src/renderer/views/SchedulesView/parts/PreviousRunsModal.tsx +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx msgid "Running" msgstr "Em execução" @@ -7585,6 +7923,10 @@ msgstr "Esgota antes" msgid "Runs out in {runOut}" msgstr "Esgota em {runOut}" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Runs that need attention will appear here." +msgstr "As execuções que precisam de atenção aparecerão aqui." + #: src/renderer/views/MainView/parts/CreateProject/CloneProjectModal.tsx #: src/renderer/views/MainView/parts/CreateProject/CreateProjectModal.tsx msgid "Runtime" @@ -7661,6 +8003,10 @@ msgstr "Verificando Windows e WSL em busca de CLIs instaladas. Isso geralmente l msgid "Scanning your system for installed CLIs. This usually takes a couple of seconds." msgstr "Verificando seu sistema em busca de CLIs instaladas. Isso geralmente leva alguns segundos." +#: src/renderer/views/SchedulesView/SchedulesView.tsx +msgid "Schedule autonomous work and review results that need your attention. Automations run while this device is awake and Poracode is open." +msgstr "Agende trabalho autônomo e revise os resultados que precisam da sua atenção. As automações são executadas enquanto este dispositivo estiver ativo e o Poracode estiver aberto." + #: src/renderer/views/SchedulesView/ScheduleEditor.tsx msgid "Schedule name" msgstr "Nome do agendamento" @@ -7669,20 +8015,31 @@ msgstr "Nome do agendamento" msgid "Schedule status" msgstr "Status do agendamento" +#: src/renderer/i18n/sharedMessages.ts +msgid "Scheduled retry was cancelled." +msgstr "A nova tentativa agendada foi cancelada." + +#: src/renderer/i18n/sharedMessages.ts +msgid "Scheduled task was deleted before retrying." +msgstr "A tarefa agendada foi excluída antes da nova tentativa." + #: src/renderer/views/SchedulesView/SchedulesView.tsx -msgid "Scheduled tasks" -msgstr "Tarefas agendadas" +#~ msgid "Scheduled tasks" +#~ msgstr "Tarefas agendadas" #: src/mobile/settingsSections.ts -msgid "Scheduled tasks on this desktop" -msgstr "Tarefas agendadas neste desktop" +#~ msgid "Scheduled tasks on this desktop" +#~ msgstr "Tarefas agendadas neste desktop" #: src/renderer/views/SchedulesView/SchedulesView.tsx #~ msgid "Scheduled tasks run only while this device is awake and Poracode is open." #~ msgstr "As tarefas agendadas só são executadas enquanto este dispositivo está ativo e o Poracode está aberto." #: src/mobile/settingsSections.ts -#: src/renderer/views/MainView/parts/Sidebar/Sidebar.tsx +msgid "Scheduled work and triage on this desktop" +msgstr "Trabalho agendado e triagem neste computador" + +#: src/renderer/views/SchedulesView/SchedulesView.tsx msgid "Schedules" msgstr "Agendamentos" @@ -7737,6 +8094,10 @@ msgstr "Pesquisar branches..." msgid "Search files" msgstr "Pesquisar arquivos" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Search findings" +msgstr "Pesquisar resultados" + #: src/renderer/components/skills/SkillMarketplaceModal.tsx msgid "Search marketplace skills" msgstr "Pesquisar skills no marketplace" @@ -7831,6 +8192,10 @@ msgstr "Procurando..." msgid "Searching…" msgstr "Procurando…" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "seconds" +msgstr "segundos" + #: src/renderer/components/skills/SkillMarketplaceModal.tsx #~ msgid "Security-focused directory with verified skill metadata." #~ msgstr "Diretório focado em segurança com metadados de skills verificados." @@ -8221,6 +8586,10 @@ msgstr "Saindo de {env}. Os agentes detectados serão atualizados quando termina msgid "Signing out. Detected agents will refresh when it finishes." msgstr "Saindo. Os agentes detectados serão atualizados quando terminar." +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Single pass" +msgstr "Execução única" + #: src/renderer/components/skills/SkillImportModal.tsx #: src/renderer/components/skills/SkillMarketplaceModal.tsx msgid "Skill availability" @@ -8285,7 +8654,12 @@ msgstr "Marketplace de skills" msgid "Skills.sh" msgstr "Skills.sh" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Skip missed runs" +msgstr "Ignorar execuções perdidas" + #: src/renderer/utils/prStatus.ts +#: src/renderer/views/SchedulesView/parts/PreviousRunsModal.tsx msgid "Skipped" msgstr "Ignorado" @@ -8424,6 +8798,10 @@ msgstr "Inicie o {appName} para ver o uso" msgid "Start a dev server on your desktop, then tap refresh." msgstr "Inicie um servidor de desenvolvimento no seu desktop e toque em atualizar." +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Start a new conversation for each run." +msgstr "Inicie uma nova conversa para cada execução." + #: src/renderer/commands/registry.ts msgid "Start a new thread as panel instead of page" msgstr "Iniciar um novo tópico como painel em vez de página" @@ -8562,6 +8940,10 @@ msgstr "Parar" msgid "Stop forwarding" msgstr "Parar encaminhamento" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Stop on error" +msgstr "Parar em caso de erro" + #: src/renderer/components/thread/ThreadComposer.tsx msgid "Stop response" msgstr "Parar resposta" @@ -8574,10 +8956,18 @@ msgstr "Parar tarefa" msgid "Stop the project's running threads before changing its folder." msgstr "Pare os tópicos em execução do projeto antes de alterar sua pasta." +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Stop the run when this total time is reached." +msgstr "Pare a execução quando esse tempo total for atingido." + #: src/renderer/components/composer/VoiceInputButton.tsx msgid "Stop voice input" msgstr "Parar a entrada de voz" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Stop when" +msgstr "Parar quando" + #: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts #: src/renderer/views/SettingsOverlay/parts/WorktreeSettings.tsx msgid "Storage location" @@ -8922,6 +9312,22 @@ msgstr "o agente" msgid "the app" msgstr "o aplicativo" +#: src/renderer/i18n/sharedMessages.ts +msgid "The automation conversation exited before the turn completed." +msgstr "A conversa da automação foi encerrada antes da conclusão do turno." + +#: src/renderer/i18n/sharedMessages.ts +msgid "The automation exceeded its time limit." +msgstr "A automação excedeu o limite de tempo." + +#: src/renderer/i18n/sharedMessages.ts +msgid "The automation needs a reply before it can continue." +msgstr "A automação precisa de uma resposta antes de continuar." + +#: src/renderer/i18n/sharedMessages.ts +msgid "The automation needs approval before it can continue." +msgstr "A automação precisa de aprovação antes de continuar." + #: src/renderer/views/MainView/parts/CreateProject/CloneProjectModal.tsx msgid "the chosen folder" msgstr "a pasta escolhida" @@ -8935,11 +9341,39 @@ msgstr "A cadência padrão de atualização em segundo plano, usada para qualqu msgid "The desktop server is still coming online." msgstr "O servidor do desktop ainda está iniciando." +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "The finding is no longer available." +msgstr "O resultado não está mais disponível." + #. placeholder {0}: createTarget.wslDistro #: src/renderer/components/skills/SkillsManager.tsx msgid "the global {0} WSL scope" msgstr "o escopo WSL global de {0}" +#: src/renderer/i18n/sharedMessages.ts +msgid "The heartbeat conversation belongs to a different project." +msgstr "A conversa de heartbeat pertence a outro projeto." + +#: src/renderer/i18n/sharedMessages.ts +msgid "The heartbeat conversation cannot be resumed." +msgstr "A conversa de heartbeat não pode ser retomada." + +#: src/renderer/i18n/sharedMessages.ts +msgid "The heartbeat conversation is archived." +msgstr "A conversa de heartbeat está arquivada." + +#: src/renderer/i18n/sharedMessages.ts +msgid "The heartbeat conversation is currently busy." +msgstr "A conversa de heartbeat está ocupada no momento." + +#: src/renderer/i18n/sharedMessages.ts +msgid "The heartbeat conversation no longer exists." +msgstr "A conversa de heartbeat não existe mais." + +#: src/renderer/i18n/sharedMessages.ts +msgid "The heartbeat conversation uses a different agent." +msgstr "A conversa de heartbeat usa outro agente." + #: src/renderer/components/skills/SkillsManager.tsx msgid "the Linux user" msgstr "o usuário do Linux" @@ -8972,6 +9406,14 @@ msgstr "O servidor remoto não retornou uma credencial de emparelhamento." msgid "The repository location on disk. Update it if you moved the folder." msgstr "A localização do repositório no disco. Atualize-a se você moveu a pasta." +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "The run could not be cancelled." +msgstr "Não foi possível cancelar a execução." + +#: src/renderer/i18n/sharedMessages.ts +msgid "The scheduled automation failed." +msgstr "A automação agendada falhou." + #: src/renderer/components/mcp/McpServersManager.tsx #~ msgid "The selected file does not contain valid MCP server configurations." #~ msgstr "O arquivo selecionado não contém configurações válidas de servidores MCP." @@ -9227,6 +9669,18 @@ msgstr "Tópicos marcados como concluídos que não foram tocados por tantos dia msgid "Time" msgstr "Horário" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Time limit" +msgstr "Limite de tempo" + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Time limit in minutes" +msgstr "Limite de tempo em minutos" + +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Time zone" +msgstr "Fuso horário" + #: src/renderer/components/mcp/McpServerEditor.tsx msgid "Timeout (ms)" msgstr "Tempo limite (ms)" @@ -9356,6 +9810,10 @@ msgstr "Barra lateral translúcida" msgid "Trending now" msgstr "Em alta agora" +#: src/renderer/views/SchedulesView/SchedulesView.tsx +msgid "Triage" +msgstr "Triagem" + #: src/mobile/views/DesktopsView.tsx msgid "Trust and connect" msgstr "Confiar e conectar" @@ -9598,6 +10056,10 @@ msgstr "Não atribuído" msgid "Unavailable" msgstr "Indisponível" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Unavailable conversation" +msgstr "Conversa indisponível" + #: src/renderer/views/SchedulesView/ScheduleEditor.tsx msgid "Unavailable project" msgstr "Projeto indisponível" @@ -9676,6 +10138,10 @@ msgstr "Sem fase:" msgid "Unpin" msgstr "Desafixar" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Unread" +msgstr "Não lido" + #: src/mobile/views/GitActionSheet.tsx #: src/renderer/views/GitReviewOverlay/parts/GitReviewSidebar/parts/FileRow.tsx #: src/renderer/views/GitReviewOverlay/parts/GitStackedDiff.tsx @@ -10002,6 +10468,12 @@ msgstr "Aguardando autenticação {methodName}. Os agentes detectados serão atu msgid "waiting for agent to stop" msgstr "esperando o agente parar" +#: src/renderer/views/SchedulesView/parts/PreviousRunsModal.tsx +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +#: src/renderer/views/SchedulesView/SchedulesView.tsx +msgid "Waiting for approval" +msgstr "Aguardando aprovação" + #: src/renderer/components/thread/ChatPane/parts/items/WorkflowOverlayBody.tsx msgid "Waiting for workflow to spawn agents…" msgstr "Aguardando o fluxo de trabalho gerar agentes…" @@ -10034,6 +10506,10 @@ msgstr "Aquecendo ambientes shell..." msgid "Warming up WSL shell environment…" msgstr "Aquecendo o ambiente shell WSL…" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Warning" +msgstr "Aviso" + #: src/renderer/components/thread/ChatPane/parts/items/ToolCallGroup.tsx #: src/renderer/components/thread/ChatPane/parts/items/toolDisplay.ts #: src/renderer/components/thread/ChatPane/parts/items/WebSearchItem.tsx @@ -10326,6 +10802,10 @@ msgstr "Pasta base do WSL" #~ msgid "WSL user" #~ msgstr "Usuário do WSL" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "You’re all caught up." +msgstr "Tudo em dia." + #: src/renderer/views/ProfileOverlay/parts/EditProfileDialog.tsx msgid "Your name" msgstr "Seu nome" diff --git a/src/renderer/locales/ru/messages.po b/src/renderer/locales/ru/messages.po index d91f436c6..924985b2a 100644 --- a/src/renderer/locales/ru/messages.po +++ b/src/renderer/locales/ru/messages.po @@ -288,6 +288,11 @@ msgstr "{agentLabel}: {statusLabel}. Наведите для подробнос msgid "{agentLead} needs your input to continue." msgstr "{agentLead} требуется ваш ввод, чтобы продолжить." +#. placeholder {0}: task.recurrence.timeZone +#: src/renderer/views/SchedulesView/SchedulesView.tsx +msgid "{cadence} in {0}" +msgstr "{cadence} — часовой пояс {0}" + #: src/mobile/views/pr/PrOverviewPage.tsx msgid "{commitsCount, plural, one {# commit} other {# commits}}" msgstr "{commitsCount, plural, one {# коммит} few {# коммита} many {# коммитов} other {# коммита}}" @@ -315,6 +320,18 @@ msgstr "{days}д назад" msgid "{envOrAgentLabel} needs authentication." msgstr "{envOrAgentLabel} требует аутентификации." +#: src/renderer/views/SchedulesView/SchedulesView.tsx +msgid "{every, plural, one {Every day} other {Every # days}}" +msgstr "{every, plural, one {Каждый день} few {Каждые # дня} many {Каждые # дней} other {Каждые # дня}}" + +#: src/renderer/views/SchedulesView/SchedulesView.tsx +msgid "{every, plural, one {Every hour} other {Every # hours}}" +msgstr "{every, plural, one {Каждый час} few {Каждые # часа} many {Каждые # часов} other {Каждые # часа}}" + +#: src/renderer/views/SchedulesView/SchedulesView.tsx +msgid "{every, plural, one {Every minute} other {Every # minutes}}" +msgstr "{every, plural, one {Каждую минуту} few {Каждые # минуты} many {Каждые # минут} other {Каждые # минуты}}" + #: src/mobile/views/pr/PrOverviewPage.tsx msgid "{filesCount, plural, one {# file changed} other {# files changed}}" msgstr "{filesCount, plural, one {# файл изменён} few {# файла изменено} many {# файлов изменено} other {# файла изменено}}" @@ -491,6 +508,10 @@ msgstr "~{money}{tokens} · {0} · прибл." msgid "≈{0}% by reset" msgstr "≈{0}% к сбросу" +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "0 9 * * 1-5" +msgstr "0 9 * * 1-5" + #: src/mobile/views/ThreadsView.tsx msgid "1 thread" msgstr "1 поток" @@ -840,6 +861,10 @@ msgstr "Действия ИИ в Git" msgid "AI providers" msgstr "Провайдеры ИИ" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "AI stop condition" +msgstr "Условие остановки ИИ" + #: src/mobile/views/MoreView.tsx #~ msgid "AI, agents, and archived threads on the paired desktop" #~ msgstr "ИИ, агенты и архивные треды на сопряжённом десктопе" @@ -851,6 +876,7 @@ msgstr "Оповещения, когда потокам нужно ваше вн #: src/renderer/commands/shortcutCatalog.ts #: src/renderer/components/skills/SkillsManager.tsx #: src/renderer/views/PullRequestsView/PullRequestsView.tsx +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx #: src/renderer/views/SchedulesView/SchedulesView.tsx #: src/renderer/views/SettingsOverlay/parts/ProfileSettings.tsx msgid "All" @@ -943,6 +969,10 @@ msgstr "Всегда исключено" msgid "An MCP server with this name already exists." msgstr "Сервер MCP с таким именем уже существует." +#: src/renderer/i18n/sharedMessages.ts +msgid "Another automation is already using this conversation." +msgstr "Этот диалог уже используется другой автоматизацией." + #: src/renderer/components/thread/ChatPane/parts/CheckpointRevertControls.tsx msgid "Another chat uses this same tree. File restore could overwrite that chat's changes." msgstr "Другой чат использует это же дерево. Восстановление файлов может перезаписать изменения этого чата." @@ -1014,6 +1044,10 @@ msgstr "Архивировать всё" msgid "Archive all threads" msgstr "Архивировать все потоки" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Archive finding" +msgstr "Архивировать результат" + #: src/renderer/commands/registry.ts msgid "Archive the current thread" msgstr "Архивировать текущий тред" @@ -1028,6 +1062,10 @@ msgstr "Архивировать тред" msgid "Archive Thread" msgstr "Архивировать тред" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Archived" +msgstr "В архиве" + #: src/mobile/settingsSections.ts #: src/mobile/views/SettingsView.tsx #: src/renderer/views/SettingsOverlay/parts/ArchivedThreadsSettings.tsx @@ -1173,6 +1211,16 @@ msgstr "Автопоказ панели терминала" msgid "Automatically show the terminal panel when running commands or creating worktrees." msgstr "Автоматически показывать панель терминала при выполнении команд или создании рабочих деревьев." +#: src/renderer/views/SchedulesView/SchedulesView.tsx +msgid "Automation sections" +msgstr "Разделы автоматизации" + +#: src/mobile/settingsSections.ts +#: src/renderer/views/MainView/parts/Sidebar/Sidebar.tsx +#: src/renderer/views/SchedulesView/SchedulesView.tsx +msgid "Automations" +msgstr "Автоматизация" + #: src/renderer/components/skills/SkillImportModal.tsx msgid "Availability" msgstr "Доступность" @@ -1459,6 +1507,10 @@ msgstr "Обойти правила защиты ветки (слияние ад msgid "Cached only" msgstr "Только кэш" +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Calculated on desktop after saving" +msgstr "Рассчитывается на компьютере после сохранения" + #: src/mobile/QrScanner.tsx msgid "Camera access blocked" msgstr "Доступ к камере заблокирован" @@ -1513,11 +1565,16 @@ msgstr "Отменить выбор" msgid "Cancel removing project" msgstr "Отменить удаление проекта" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Cancel run" +msgstr "Отменить запуск" + #: src/renderer/components/thread/ChatPane/parts/items/WorkflowOverlayBody.tsx msgid "cancelled" msgstr "отменено" #: src/renderer/utils/prStatus.ts +#: src/renderer/views/SchedulesView/parts/PreviousRunsModal.tsx msgid "Cancelled" msgstr "Отменено" @@ -1706,6 +1763,10 @@ msgstr "Выберите язык интерфейса Poracode." msgid "Choose thread to attach to" msgstr "Выберите тред для прикрепления" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Choose what happens after a scheduled time was missed." +msgstr "Выберите, что делать, если запланированное время было пропущено." + #: src/renderer/views/SettingsOverlay/parts/BrowserSettings.tsx #: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts msgid "Choose whether links from Poracode and browser popups stay in Poracode or open externally." @@ -2185,6 +2246,14 @@ msgstr "завершено" msgid "Completed" msgstr "Завершено" +#: src/renderer/i18n/sharedMessages.ts +msgid "Completion evaluation failed: {detail}" +msgstr "Ошибка оценки завершения: {detail}" + +#: src/renderer/i18n/sharedMessages.ts +msgid "Completion evaluation is unavailable." +msgstr "Оценка завершения недоступна." + #: src/renderer/commands/shortcutCatalog.ts #: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx #: src/renderer/views/SettingsOverlay/parts/settingsOptions.ts @@ -2223,6 +2292,14 @@ msgstr "Computer Use включён — интерактивные действ #~ msgid "Computer Use enabled for this thread" #~ msgstr "Управление компьютером включено для этого треда" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Confidence" +msgstr "Уверенность" + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Confidence percent" +msgstr "Уверенность в процентах" + #: src/renderer/views/SettingsOverlay/parts/ClaudeProfileSettings.tsx msgid "Config directory" msgstr "Каталог конфигурации" @@ -2386,6 +2463,14 @@ msgstr "Продолжить в другом провайдере" msgid "Continue in..." msgstr "Продолжить в..." +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Continue one conversation until a stop condition or limit is reached." +msgstr "Продолжать один диалог, пока не будет выполнено условие остановки или достигнут лимит." + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Control how each scheduled run continues and stops." +msgstr "Настройте, как продолжается и останавливается каждый запланированный запуск." + #: src/renderer/views/SettingsOverlay/parts/SearchSettings.tsx msgid "Control which files appear in the @file mention search. Per-project overrides live in each project's settings." msgstr "Управляйте тем, какие файлы появляются в поиске по упоминанию @file. Переопределения для каждого проекта находятся в настройках соответствующего проекта." @@ -2397,6 +2482,7 @@ msgstr "Управляет сопряжённым рабочим столом, #: src/mobile/views/pr/PrConversationPage.tsx #: src/mobile/views/pr/PrOverviewPage.tsx #: src/renderer/views/PrReviewOverlay/parts/PrTabsPill.tsx +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx msgid "Conversation" msgstr "Разговор" @@ -2697,6 +2783,24 @@ msgstr "Учётные данные настроены." msgid "Credits" msgstr "Кредиты" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Critical" +msgstr "Критический" + +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Cron" +msgstr "Cron" + +#. placeholder {0}: task.recurrence.expression +#. placeholder {1}: task.recurrence.timeZone +#: src/renderer/views/SchedulesView/SchedulesView.tsx +msgid "Cron {0} in {1}" +msgstr "Cron {0} — часовой пояс {1}" + +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Cron expression" +msgstr "Выражение Cron" + #: src/renderer/components/skills/SkillMarketplaceModal.tsx #~ msgid "Curated free and premium skills managed by MCP Market." #~ msgstr "Отобранные бесплатные и премиальные навыки под управлением MCP Market." @@ -2762,9 +2866,9 @@ msgstr "Ежедневная сводка" msgid "Dark" msgstr "Тёмная" -#: src/renderer/views/SchedulesView/SchedulesView.tsx -#~ msgid "Days" -#~ msgstr "Дни" +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Days" +msgstr "Дни" #: src/renderer/components/thread/ThreadRuntimeRequestPanel/structuredElicitation.tsx msgid "Decline" @@ -2911,6 +3015,10 @@ msgstr "Удалить worktree {0}" #~ msgid "Delete:" #~ msgstr "Удалить:" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Deleted schedule" +msgstr "Удалённое расписание" + #: src/renderer/views/SettingsOverlay/parts/AcpRegistrySettings.tsx msgid "Deleting" msgstr "Удаление" @@ -2923,6 +3031,10 @@ msgstr "Запретить" msgid "Deny and tell the agent what to do differently…" msgstr "Запретить и сказать агенту, что сделать иначе…" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Describe the result that completes this heartbeat." +msgstr "Опишите результат, при котором этот пульс будет завершён." + #: src/renderer/views/SchedulesView/ScheduleEditor.tsx msgid "Describe what the agent should do" msgstr "Опишите, что должен сделать агент" @@ -2944,6 +3056,10 @@ msgstr "Конечная точка рабочего стола" msgid "Desktop is unreachable." msgstr "Десктоп недоступен." +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Desktop local time" +msgstr "Локальное время компьютера" + #: src/mobile/chrome.ts #: src/mobile/views/MoreView.tsx msgid "Desktop Settings" @@ -3056,6 +3172,10 @@ msgstr "Отключить проект" msgid "Disable Subagents" msgstr "Отключить субагентов" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Disable the automation after retries are exhausted." +msgstr "Отключить автоматизацию после исчерпания всех попыток." + #: src/renderer/views/SettingsOverlay/parts/ClaudeProfileSettings.tsx msgid "Disable tiers an external provider collapses (e.g. keep only High and Max)." msgstr "Отключите уровни, которые внешний провайдер объединяет (например, оставьте только High и Max)." @@ -3356,6 +3476,10 @@ msgstr "Включённые серверы остаются активными msgid "Enables <0>cookies and <1>storage. Cookies can contain session tokens and storage often holds auth state — only enable when you trust both the agent and the sites it visits." msgstr "Включает <0>cookie и <1>хранилище. Cookie могут содержать токены сессии, а в хранилище часто хранится состояние аутентификации — включайте, только если доверяете и агенту, и сайтам, которые он посещает." +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +#~ msgid "End the heartbeat after retries are exhausted." +#~ msgstr "Завершить пульс после исчерпания повторных попыток." + #: src/mobile/views/DesktopsView.tsx #: src/renderer/views/SettingsOverlay/parts/RemoteServersSettings.tsx msgid "Endpoint" @@ -3393,6 +3517,10 @@ msgstr "Введите действительный эндпоинт рабоч msgid "Enter a valid HTTP or HTTPS URL." msgstr "Введите допустимый URL-адрес с протоколом HTTP или HTTPS." +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Enter a valid schedule" +msgstr "Введите корректное расписание" + #: src/mobile/views/DesktopsView.tsx msgid "Enter a valid SSH target and port." msgstr "Введите допустимый SSH-адрес и порт." @@ -3463,6 +3591,14 @@ msgstr "Ошибка" msgid "Error · Agent encountered an error" msgstr "Ошибка · Агент столкнулся с ошибкой" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Evaluate the result after every iteration." +msgstr "Оценивать результат после каждой итерации." + +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Every" +msgstr "Каждые" + #: src/renderer/views/SchedulesView/SchedulesView.tsx msgid "Every day at {time}" msgstr "Каждый день в {time}" @@ -3485,6 +3621,14 @@ msgstr "Каждый час в {0} мин." msgid "Exclude patterns" msgstr "Шаблоны исключения" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Execution" +msgstr "Выполнение" + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Execution mode" +msgstr "Режим выполнения" + #: src/renderer/components/thread/ChatPane/parts/items/toolDisplay.ts msgid "Exit plan mode" msgstr "Выйти из режима плана" @@ -3534,6 +3678,10 @@ msgstr "Разверните, чтобы проверить или отозва msgid "Expand todo dock" msgstr "Развернуть панель задач" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Exponential backoff" +msgstr "Экспоненциальная задержка" + #: src/renderer/components/mcp/McpServersManager.tsx msgid "Export MCP servers" msgstr "Экспортировать серверы MCP" @@ -3716,6 +3864,10 @@ msgstr "Найти в diff" msgid "Find in terminal" msgstr "Найти в терминале" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Finding status" +msgstr "Состояние результата" + #: src/renderer/views/PrReviewOverlay/parts/SubmitReviewPopover.tsx msgid "Finish your review" msgstr "Завершите проверку" @@ -3777,6 +3929,10 @@ msgstr "Исправить в агенте" msgid "Fixed" msgstr "Исправлено" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Fixed delay" +msgstr "Фиксированная задержка" + #: src/renderer/commands/registry.ts msgid "Focus browser address bar" msgstr "Перейти на адресную строку браузера" @@ -4097,6 +4253,26 @@ msgstr "Есть неотправленный черновик" msgid "Headers" msgstr "Заголовки" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Heartbeat" +msgstr "Пульс" + +#: src/renderer/i18n/sharedMessages.ts +msgid "Heartbeat automations require a native chat conversation." +msgstr "Для автоматизации пульса требуется диалог во встроенном чате." + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Heartbeat continues this conversation in the selected project." +msgstr "Пульс продолжает этот диалог в выбранном проекте." + +#: src/renderer/i18n/sharedMessages.ts +msgid "Heartbeat execution is unavailable." +msgstr "Выполнение пульса недоступно." + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Heartbeats can continue making changes while you're away. Set hard limits below." +msgstr "Пульс может продолжать вносить изменения в ваше отсутствие. Задайте ниже жёсткие ограничения." + #: src/renderer/views/SchedulesView/SchedulesView.tsx msgid "Help me create a schedule. Ask for any missing details, then use the Poracode schedule controls to create it for me." msgstr "Помоги мне создать расписание. Спроси недостающие детали, а затем создай его с помощью элементов управления расписаниями Poracode." @@ -4198,6 +4374,10 @@ msgstr "host.com, псевдоним или пользователь@host.com" msgid "Hourly" msgstr "Ежечасно" +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Hours" +msgstr "Часы" + #: src/renderer/components/mcp/McpServerEditor.tsx msgid "HTTP (streamable)" msgstr "HTTP (потоковый)" @@ -4328,6 +4508,14 @@ msgstr "Сканирование камерой внутри приложени msgid "Inactive" msgstr "Неактивно" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Includes the first attempt." +msgstr "Учитывает первую попытку." + +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Info" +msgstr "Информация" + #. Badge on an exclude pattern inherited from a lower scope #: src/renderer/views/SettingsOverlay/parts/SearchExcludeBody.tsx msgid "inherited" @@ -4338,6 +4526,14 @@ msgstr "наследовано" msgid "Inheriting the global setting (currently {0})." msgstr "Наследуется глобальная настройка (сейчас {0})." +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Initial retry delay" +msgstr "Начальная задержка повтора" + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Initial retry delay in seconds" +msgstr "Начальная задержка повтора в секундах" + #: src/renderer/views/GitReviewOverlay/parts/GitReviewSidebar/GitReviewSidebar.tsx msgid "Initialize Repository" msgstr "Инициализировать репозиторий" @@ -4476,6 +4672,18 @@ msgstr "Прервано" msgid "Interrupted: agent session ended before completion." msgstr "Прервано: сессия агента завершилась до окончания." +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Interval" +msgstr "Интервал" + +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Interval amount" +msgstr "Значение интервала" + +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Interval unit" +msgstr "Единица интервала" + #: src/renderer/views/MainView/parts/RightPanel/parts/NotesPanel/NotesEditor.tsx msgid "Italic" msgstr "Курсив" @@ -4560,6 +4768,14 @@ msgstr "Запуск…" msgid "Leave a comment" msgstr "Оставить комментарий" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Leave blank for no run limit." +msgstr "Оставьте поле пустым, чтобы не ограничивать число запусков." + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +#~ msgid "Leave blank to rely on the time limit." +#~ msgstr "Оставьте пустым, чтобы использовать только ограничение времени." + #: src/renderer/views/ProfileOverlay/parts/ActivityHeatmap.tsx msgid "Less" msgstr "Меньше" @@ -4640,6 +4856,10 @@ msgstr "Загрузка редактора…" msgid "Loading file…" msgstr "Загрузка файла…" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Loading findings" +msgstr "Загрузка результатов" + #: src/renderer/components/skills/SkillMarketplaceModal.tsx msgid "Loading marketplace…" msgstr "Загрузка маркетплейса…" @@ -4864,6 +5084,14 @@ msgstr "Отметить как выполненное" msgid "Mark as not done" msgstr "Отметить как невыполненное" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Mark as read" +msgstr "Отметить как прочитанное" + +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Mark as unread" +msgstr "Отметить как непрочитанное" + #: src/renderer/components/thread/ThreadView.tsx msgid "Mark done" msgstr "Отметить выполненным" @@ -4904,6 +5132,22 @@ msgstr "Развернуть" msgid "Maximize browser" msgstr "Развернуть браузер" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Maximum attempts" +msgstr "Максимум попыток" + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Maximum iterations" +msgstr "Максимум итераций" + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Maximum retry delay" +msgstr "Максимальная задержка повтора" + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Maximum retry delay in seconds" +msgstr "Максимальная задержка повтора в секундах" + #: src/renderer/components/skills/SkillMarketplaceModal.tsx #~ msgid "MCP Market" #~ msgstr "MCP Market" @@ -5110,6 +5354,18 @@ msgstr "Свернуть в панель" msgid "Minute" msgstr "Минута" +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Minute, hour, day of month, month, and weekday." +msgstr "Минута, час, день месяца, месяц и день недели." + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "minutes" +msgstr "минут" + +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Minutes" +msgstr "Минуты" + #: src/mobile/views/BrowserView.tsx msgid "Mirrored desktop browser tab" msgstr "Зеркальная вкладка браузера десктопа" @@ -5118,6 +5374,10 @@ msgstr "Зеркальная вкладка браузера десктопа" msgid "Mirroring is unavailable." msgstr "Зеркалирование недоступно." +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Missed runs" +msgstr "Пропущенные запуски" + #: src/renderer/views/SettingsOverlay/parts/RemoteAccessSettings.tsx msgid "Mobile push notifications" msgstr "Мобильные push-уведомления" @@ -5469,6 +5729,10 @@ msgstr "Следующее совпадение" msgid "Next recently viewed chat" msgstr "Следующий недавно просмотренный чат" +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Next run" +msgstr "Следующий запуск" + #. placeholder {0}: dateTimeFormatter.format(new Date(task.nextRunAt)) #: src/renderer/views/SchedulesView/SchedulesView.tsx msgid "Next run {0}" @@ -5514,6 +5778,10 @@ msgstr "Нет установленных агентов." msgid "No AI commits, PRs, or conflict resolutions tracked yet." msgstr "Пока нет отслеженных коммитов, PR или разрешений конфликтов от ИИ." +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "No archived findings." +msgstr "Нет результатов в архиве." + #: src/renderer/views/SettingsOverlay/parts/ArchivedThreadsSettings.tsx msgid "No archived threads." msgstr "Нет архивированных тредов." @@ -5610,6 +5878,10 @@ msgstr "Нет доступного diff для {0}" msgid "No diff for {visiblePath}" msgstr "Нет diff для {visiblePath}" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "No eligible conversations in this project." +msgstr "В этом проекте нет подходящих диалогов." + #: src/renderer/components/skills/SkillImportModal.tsx msgid "No external skills were found in this scope." msgstr "В этой области не найдено внешних навыков." @@ -5625,6 +5897,10 @@ msgstr "Для этого сообщения не сохранена контр msgid "No files match \"{0}\"." msgstr "Нет файлов, соответствующих \"{0}\"." +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "No findings yet." +msgstr "Результатов пока нет." + #: src/renderer/views/MainView/parts/CreateProject/CloneProjectModal.tsx msgid "No GitHub CLI accounts found. Sign in with <0>gh auth login, or <1>paste a clone URL." msgstr "Учётные записи GitHub CLI не найдены. Войдите с помощью <0>gh auth login или <1>вставьте URL для клонирования." @@ -5637,6 +5913,10 @@ msgstr "Истории пока нет" msgid "No Lightcode data was found." msgstr "Данные Lightcode не найдены." +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "No limit" +msgstr "Без ограничений" + #: src/renderer/components/skills/SkillMarketplaceModal.tsx msgid "No marketplace skills match these filters." msgstr "Нет навыков маркетплейса, соответствующих этим фильтрам." @@ -5653,6 +5933,10 @@ msgstr "Совпадений нет." msgid "No matching agents." msgstr "Подходящих агентов нет." +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "No matching findings." +msgstr "Нет подходящих результатов." + #: src/renderer/views/PullRequestsView/PullRequestsView.tsx msgid "No matching pull requests." msgstr "Нет подходящих pull request." @@ -5762,6 +6046,10 @@ msgstr "Репозитории не найдены." msgid "No results" msgstr "Нет результатов" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "No retries" +msgstr "Без повторных попыток" + #: src/renderer/views/SchedulesView/parts/PreviousRunsModal.tsx msgid "No runs yet." msgstr "Запусков ещё нет." @@ -5798,6 +6086,10 @@ msgstr "Речь не обнаружена." msgid "No staged changes" msgstr "Нет подготовленных изменений" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "No summary was provided." +msgstr "Сводка не предоставлена." + #: src/renderer/views/RemoteProjectModal/RemoteProjectModal.tsx msgid "No supported agents are installed on this remote machine. Install and sign in to an agent remotely before starting a thread." msgstr "На этом удалённом компьютере не установлены поддерживаемые агенты. Установите агент и войдите в него удалённо перед запуском потока." @@ -5827,6 +6119,10 @@ msgstr "Пока нет потоков" msgid "No threads yet." msgstr "Тредов пока нет." +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "No upcoming run" +msgstr "Предстоящих запусков нет" + #: src/renderer/components/providers/usageFormat.ts msgid "No windows reported" msgstr "Окна не сообщены" @@ -6042,6 +6338,11 @@ msgstr "Открыть коммит на GitHub" msgid "Open conflict resolver in" msgstr "Открыть средство разрешения конфликтов в" +#. placeholder {0}: props.scheduleName +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Open conversation for {0}" +msgstr "Открыть диалог для {0}" + #: src/renderer/views/SettingsOverlay/parts/settingsOptions.ts msgid "Open dialog" msgstr "Открывать диалог" @@ -6677,6 +6978,10 @@ msgstr "Папка проекта обновлена. Откройте зано msgid "Project name" msgstr "Название проекта" +#: src/renderer/i18n/sharedMessages.ts +msgid "Project no longer exists." +msgstr "Проект больше не существует." + #: src/renderer/views/MainView/parts/RightPanel/parts/NotesPanel/NotesEditor.tsx msgid "Project notes" msgstr "Заметки проекта" @@ -7275,6 +7580,10 @@ msgstr "Сведения о запросе" msgid "requested changes" msgstr "запрошенные изменения" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Required confidence before stopping." +msgstr "Необходимая уверенность для остановки." + #: src/mobile/views/pr/PrOverviewPage.tsx #: src/renderer/views/GitReviewOverlay/parts/GitReviewSidebar/parts/PrSection.tsx msgid "Required reviews, conversations, or status checks not met." @@ -7346,6 +7655,10 @@ msgstr "Восстановить браузер" msgid "Restore default worktree base folder" msgstr "Восстановить базовую папку worktree по умолчанию" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Restore finding" +msgstr "Восстановить результат" + #: src/mobile/settingsSections.ts msgid "Restore or delete" msgstr "Восстановить или удалить" @@ -7376,10 +7689,26 @@ msgstr "Повторить проверку {serverName}" msgid "Retry check" msgstr "Повторить проверку" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Retry delay" +msgstr "Задержка повтора" + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Retry delay in seconds" +msgstr "Задержка повтора в секундах" + #: src/mobile/components.tsx msgid "Retry now" msgstr "Повторить сейчас" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Retry policy" +msgstr "Политика повторов" + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Retry when a run fails before it completes." +msgstr "Повторить, если запуск завершится ошибкой до окончания." + #: src/renderer/hooks/usePrWriteActions.ts msgid "Retry with admin" msgstr "Повторить с правами администратора" @@ -7535,18 +7864,26 @@ msgstr "Выполнять локальную транскрипцию на GPU, msgid "Run now" msgstr "Запустить сейчас" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Run once after reopening" +msgstr "Выполнить один раз после повторного открытия" + #: src/renderer/views/SchedulesView/SchedulesView.tsx #~ msgid "Run standalone tasks on this device without a project." #~ msgstr "Запускайте автономные задачи на этом устройстве без проекта." #: src/renderer/views/SchedulesView/SchedulesView.tsx -msgid "Run standalone tasks on this device. Schedules run while the device is awake and Poracode is open." -msgstr "Запускайте автономные задачи на этом устройстве. Расписания выполняются, пока устройство активно и Poracode открыт." +#~ msgid "Run standalone tasks on this device. Schedules run while the device is awake and Poracode is open." +#~ msgstr "Запускайте автономные задачи на этом устройстве. Расписания выполняются, пока устройство активно и Poracode открыт." #: src/renderer/commands/registry.ts msgid "Run Terminal Command" msgstr "Выполнить команду терминала" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Run the latest missed run" +msgstr "Выполнить последний пропущенный запуск" + #: src/renderer/views/SchedulesView/ScheduleEditor.tsx #~ msgid "Run this schedule automatically at the times above." #~ msgstr "Автоматически запускать это расписание в указанное выше время." @@ -7562,6 +7899,7 @@ msgstr "выполняется" #: src/renderer/utils/prStatus.ts #: src/renderer/views/SchedulesView/parts/PreviousRunsModal.tsx +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx msgid "Running" msgstr "Выполняется" @@ -7585,6 +7923,10 @@ msgstr "Закончится раньше" msgid "Runs out in {runOut}" msgstr "Закончится через {runOut}" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Runs that need attention will appear here." +msgstr "Здесь появятся запуски, требующие внимания." + #: src/renderer/views/MainView/parts/CreateProject/CloneProjectModal.tsx #: src/renderer/views/MainView/parts/CreateProject/CreateProjectModal.tsx msgid "Runtime" @@ -7661,6 +8003,10 @@ msgstr "Сканирование Windows и WSL на наличие устано msgid "Scanning your system for installed CLIs. This usually takes a couple of seconds." msgstr "Сканирование вашей системы на наличие установленных CLI. Обычно это занимает пару секунд." +#: src/renderer/views/SchedulesView/SchedulesView.tsx +msgid "Schedule autonomous work and review results that need your attention. Automations run while this device is awake and Poracode is open." +msgstr "Планируйте автономную работу и просматривайте результаты, требующие внимания. Автоматизация выполняется, пока устройство активно и Poracode открыт." + #: src/renderer/views/SchedulesView/ScheduleEditor.tsx msgid "Schedule name" msgstr "Название расписания" @@ -7669,20 +8015,31 @@ msgstr "Название расписания" msgid "Schedule status" msgstr "Состояние расписания" +#: src/renderer/i18n/sharedMessages.ts +msgid "Scheduled retry was cancelled." +msgstr "Запланированная повторная попытка отменена." + +#: src/renderer/i18n/sharedMessages.ts +msgid "Scheduled task was deleted before retrying." +msgstr "Запланированная задача была удалена до повторной попытки." + #: src/renderer/views/SchedulesView/SchedulesView.tsx -msgid "Scheduled tasks" -msgstr "Запланированные задачи" +#~ msgid "Scheduled tasks" +#~ msgstr "Запланированные задачи" #: src/mobile/settingsSections.ts -msgid "Scheduled tasks on this desktop" -msgstr "Запланированные задачи на этом компьютере" +#~ msgid "Scheduled tasks on this desktop" +#~ msgstr "Запланированные задачи на этом компьютере" #: src/renderer/views/SchedulesView/SchedulesView.tsx #~ msgid "Scheduled tasks run only while this device is awake and Poracode is open." #~ msgstr "Запланированные задачи выполняются только когда устройство активно и Poracode открыт." #: src/mobile/settingsSections.ts -#: src/renderer/views/MainView/parts/Sidebar/Sidebar.tsx +msgid "Scheduled work and triage on this desktop" +msgstr "Запланированная работа и разбор на этом компьютере" + +#: src/renderer/views/SchedulesView/SchedulesView.tsx msgid "Schedules" msgstr "Расписания" @@ -7737,6 +8094,10 @@ msgstr "Поиск веток..." msgid "Search files" msgstr "Поиск файлов" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Search findings" +msgstr "Поиск результатов" + #: src/renderer/components/skills/SkillMarketplaceModal.tsx msgid "Search marketplace skills" msgstr "Поиск навыков в маркетплейсе" @@ -7831,6 +8192,10 @@ msgstr "Поиск..." msgid "Searching…" msgstr "Поиск…" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "seconds" +msgstr "секунд" + #: src/renderer/components/skills/SkillMarketplaceModal.tsx #~ msgid "Security-focused directory with verified skill metadata." #~ msgstr "Каталог с акцентом на безопасность и проверенными метаданными навыков." @@ -8221,6 +8586,10 @@ msgstr "Выход из {env}. Обнаруженные агенты обнов msgid "Signing out. Detected agents will refresh when it finishes." msgstr "Выход. Обнаруженные агенты обновятся по завершении." +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Single pass" +msgstr "Один проход" + #: src/renderer/components/skills/SkillImportModal.tsx #: src/renderer/components/skills/SkillMarketplaceModal.tsx msgid "Skill availability" @@ -8285,7 +8654,12 @@ msgstr "Маркетплейс навыков" msgid "Skills.sh" msgstr "Skills.sh" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Skip missed runs" +msgstr "Пропускать пропущенные запуски" + #: src/renderer/utils/prStatus.ts +#: src/renderer/views/SchedulesView/parts/PreviousRunsModal.tsx msgid "Skipped" msgstr "Пропущено" @@ -8424,6 +8798,10 @@ msgstr "Запустите {appName}, чтобы увидеть статисти msgid "Start a dev server on your desktop, then tap refresh." msgstr "Запустите сервер разработки на десктопе, затем нажмите «Обновить»." +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Start a new conversation for each run." +msgstr "Начинать новый диалог при каждом запуске." + #: src/renderer/commands/registry.ts msgid "Start a new thread as panel instead of page" msgstr "Открыть новый тред в виде панели, а не страницы" @@ -8562,6 +8940,10 @@ msgstr "Остановить" msgid "Stop forwarding" msgstr "Остановить перенаправление" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Stop on error" +msgstr "Останавливать при ошибке" + #: src/renderer/components/thread/ThreadComposer.tsx msgid "Stop response" msgstr "Остановить ответ" @@ -8574,10 +8956,18 @@ msgstr "Остановить задачу" msgid "Stop the project's running threads before changing its folder." msgstr "Остановите запущенные треды проекта перед изменением его папки." +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Stop the run when this total time is reached." +msgstr "Остановить запуск, когда будет достигнуто это общее время." + #: src/renderer/components/composer/VoiceInputButton.tsx msgid "Stop voice input" msgstr "Остановить голосовой ввод" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Stop when" +msgstr "Условие остановки" + #: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts #: src/renderer/views/SettingsOverlay/parts/WorktreeSettings.tsx msgid "Storage location" @@ -8922,6 +9312,22 @@ msgstr "Агент" msgid "the app" msgstr "приложение" +#: src/renderer/i18n/sharedMessages.ts +msgid "The automation conversation exited before the turn completed." +msgstr "Диалог автоматизации завершился до окончания хода." + +#: src/renderer/i18n/sharedMessages.ts +msgid "The automation exceeded its time limit." +msgstr "Автоматизация превысила ограничение времени." + +#: src/renderer/i18n/sharedMessages.ts +msgid "The automation needs a reply before it can continue." +msgstr "Для продолжения автоматизации требуется ответ." + +#: src/renderer/i18n/sharedMessages.ts +msgid "The automation needs approval before it can continue." +msgstr "Для продолжения автоматизации требуется одобрение." + #: src/renderer/views/MainView/parts/CreateProject/CloneProjectModal.tsx msgid "the chosen folder" msgstr "выбранная папка" @@ -8935,11 +9341,39 @@ msgstr "Частота фонового обновления по умолчан msgid "The desktop server is still coming online." msgstr "Сервер рабочего стола все еще запускается." +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "The finding is no longer available." +msgstr "Результат больше недоступен." + #. placeholder {0}: createTarget.wslDistro #: src/renderer/components/skills/SkillsManager.tsx msgid "the global {0} WSL scope" msgstr "глобальную область WSL {0}" +#: src/renderer/i18n/sharedMessages.ts +msgid "The heartbeat conversation belongs to a different project." +msgstr "Диалог пульса относится к другому проекту." + +#: src/renderer/i18n/sharedMessages.ts +msgid "The heartbeat conversation cannot be resumed." +msgstr "Диалог пульса невозможно возобновить." + +#: src/renderer/i18n/sharedMessages.ts +msgid "The heartbeat conversation is archived." +msgstr "Диалог пульса архивирован." + +#: src/renderer/i18n/sharedMessages.ts +msgid "The heartbeat conversation is currently busy." +msgstr "Диалог пульса сейчас занят." + +#: src/renderer/i18n/sharedMessages.ts +msgid "The heartbeat conversation no longer exists." +msgstr "Диалог пульса больше не существует." + +#: src/renderer/i18n/sharedMessages.ts +msgid "The heartbeat conversation uses a different agent." +msgstr "Диалог пульса использует другого агента." + #: src/renderer/components/skills/SkillsManager.tsx msgid "the Linux user" msgstr "пользователя Linux" @@ -8972,6 +9406,14 @@ msgstr "Удалённый сервер не вернул учётные дан msgid "The repository location on disk. Update it if you moved the folder." msgstr "Расположение репозитория на диске. Обновите его, если вы переместили папку." +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "The run could not be cancelled." +msgstr "Не удалось отменить запуск." + +#: src/renderer/i18n/sharedMessages.ts +msgid "The scheduled automation failed." +msgstr "Запланированная автоматизация завершилась с ошибкой." + #: src/renderer/components/mcp/McpServersManager.tsx #~ msgid "The selected file does not contain valid MCP server configurations." #~ msgstr "Выбранный файл не содержит допустимых конфигураций серверов MCP." @@ -9227,6 +9669,18 @@ msgstr "Треды, помеченные как завершённые и не msgid "Time" msgstr "Время" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Time limit" +msgstr "Ограничение времени" + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Time limit in minutes" +msgstr "Ограничение времени в минутах" + +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Time zone" +msgstr "Часовой пояс" + #: src/renderer/components/mcp/McpServerEditor.tsx msgid "Timeout (ms)" msgstr "Тайм-аут (мс)" @@ -9356,6 +9810,10 @@ msgstr "Полупрозрачная боковая панель" msgid "Trending now" msgstr "Сейчас в тренде" +#: src/renderer/views/SchedulesView/SchedulesView.tsx +msgid "Triage" +msgstr "Разбор" + #: src/mobile/views/DesktopsView.tsx msgid "Trust and connect" msgstr "Доверять и подключиться" @@ -9598,6 +10056,10 @@ msgstr "Не назначено" msgid "Unavailable" msgstr "Недоступно" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Unavailable conversation" +msgstr "Недоступный диалог" + #: src/renderer/views/SchedulesView/ScheduleEditor.tsx msgid "Unavailable project" msgstr "Недоступный проект" @@ -9676,6 +10138,10 @@ msgstr "Без фазы:" msgid "Unpin" msgstr "Открепить" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Unread" +msgstr "Непрочитанное" + #: src/mobile/views/GitActionSheet.tsx #: src/renderer/views/GitReviewOverlay/parts/GitReviewSidebar/parts/FileRow.tsx #: src/renderer/views/GitReviewOverlay/parts/GitStackedDiff.tsx @@ -10002,6 +10468,12 @@ msgstr "Ожидание аутентификации {methodName}. Обнару msgid "waiting for agent to stop" msgstr "ожидание остановки агента" +#: src/renderer/views/SchedulesView/parts/PreviousRunsModal.tsx +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +#: src/renderer/views/SchedulesView/SchedulesView.tsx +msgid "Waiting for approval" +msgstr "Ожидает одобрения" + #: src/renderer/components/thread/ChatPane/parts/items/WorkflowOverlayBody.tsx msgid "Waiting for workflow to spawn agents…" msgstr "Ожидание создания агентов рабочим процессом…" @@ -10034,6 +10506,10 @@ msgstr "Подготовка окружений оболочки..." msgid "Warming up WSL shell environment…" msgstr "Подготовка окружения оболочки WSL…" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Warning" +msgstr "Предупреждение" + #: src/renderer/components/thread/ChatPane/parts/items/ToolCallGroup.tsx #: src/renderer/components/thread/ChatPane/parts/items/toolDisplay.ts #: src/renderer/components/thread/ChatPane/parts/items/WebSearchItem.tsx @@ -10326,6 +10802,10 @@ msgstr "Базовая папка WSL" #~ msgid "WSL user" #~ msgstr "Пользователь WSL" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "You’re all caught up." +msgstr "Всё просмотрено." + #: src/renderer/views/ProfileOverlay/parts/EditProfileDialog.tsx msgid "Your name" msgstr "Ваше имя" diff --git a/src/renderer/locales/tr/messages.po b/src/renderer/locales/tr/messages.po index a786d5715..ca6828cee 100644 --- a/src/renderer/locales/tr/messages.po +++ b/src/renderer/locales/tr/messages.po @@ -288,6 +288,11 @@ msgstr "{agentLabel}: {statusLabel}. Durum ayrıntıları için fareyle üzerine msgid "{agentLead} needs your input to continue." msgstr "{agentLead} devam etmek için girişinizi bekliyor." +#. placeholder {0}: task.recurrence.timeZone +#: src/renderer/views/SchedulesView/SchedulesView.tsx +msgid "{cadence} in {0}" +msgstr "{cadence} ({0})" + #: src/mobile/views/pr/PrOverviewPage.tsx msgid "{commitsCount, plural, one {# commit} other {# commits}}" msgstr "{commitsCount, plural, one {# commit} other {# commit}}" @@ -315,6 +320,18 @@ msgstr "{days} gün önce" msgid "{envOrAgentLabel} needs authentication." msgstr "{envOrAgentLabel} kimlik doğrulaması gerektiriyor." +#: src/renderer/views/SchedulesView/SchedulesView.tsx +msgid "{every, plural, one {Every day} other {Every # days}}" +msgstr "{every, plural, one {Her gün} other {# günde bir}}" + +#: src/renderer/views/SchedulesView/SchedulesView.tsx +msgid "{every, plural, one {Every hour} other {Every # hours}}" +msgstr "{every, plural, one {Her saat} other {# saatte bir}}" + +#: src/renderer/views/SchedulesView/SchedulesView.tsx +msgid "{every, plural, one {Every minute} other {Every # minutes}}" +msgstr "{every, plural, one {Her dakika} other {# dakikada bir}}" + #: src/mobile/views/pr/PrOverviewPage.tsx msgid "{filesCount, plural, one {# file changed} other {# files changed}}" msgstr "{filesCount, plural, one {# dosya değişti} other {# dosya değişti}}" @@ -491,6 +508,10 @@ msgstr "~{money}{tokens} · {0} · tahmini" msgid "≈{0}% by reset" msgstr "sıfırlamaya kadar ≈%{0}" +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "0 9 * * 1-5" +msgstr "0 9 * * 1-5" + #: src/mobile/views/ThreadsView.tsx msgid "1 thread" msgstr "1 iş parçacığı" @@ -840,6 +861,10 @@ msgstr "Yapay zeka git işlemleri" msgid "AI providers" msgstr "Yapay zeka sağlayıcıları" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "AI stop condition" +msgstr "Yapay zekâ durdurma koşulu" + #: src/mobile/views/MoreView.tsx #~ msgid "AI, agents, and archived threads on the paired desktop" #~ msgstr "Eşleştirilen masaüstündeki AI, ajanlar ve arşivlenmiş konular" @@ -851,6 +876,7 @@ msgstr "İş parçacıkları size ihtiyaç duyduğunda uyarılar" #: src/renderer/commands/shortcutCatalog.ts #: src/renderer/components/skills/SkillsManager.tsx #: src/renderer/views/PullRequestsView/PullRequestsView.tsx +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx #: src/renderer/views/SchedulesView/SchedulesView.tsx #: src/renderer/views/SettingsOverlay/parts/ProfileSettings.tsx msgid "All" @@ -943,6 +969,10 @@ msgstr "Her zaman hariç tutuldu" msgid "An MCP server with this name already exists." msgstr "Bu ada sahip bir MCP sunucusu zaten var." +#: src/renderer/i18n/sharedMessages.ts +msgid "Another automation is already using this conversation." +msgstr "Başka bir otomasyon bu konuşmayı zaten kullanıyor." + #: src/renderer/components/thread/ChatPane/parts/CheckpointRevertControls.tsx msgid "Another chat uses this same tree. File restore could overwrite that chat's changes." msgstr "Başka bir sohbet de aynı ağacı kullanıyor. Dosya geri yükleme, sohbetteki değişikliklerin üzerine yazabilir." @@ -1014,6 +1044,10 @@ msgstr "Tümünü Arşivle" msgid "Archive all threads" msgstr "Tüm iş parçacıklarını arşivle" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Archive finding" +msgstr "Bulguyu arşivle" + #: src/renderer/commands/registry.ts msgid "Archive the current thread" msgstr "Geçerli konuyu arşivle" @@ -1028,6 +1062,10 @@ msgstr "Konuyu arşivle" msgid "Archive Thread" msgstr "İleti Dizisini Arşivle" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Archived" +msgstr "Arşivlenenler" + #: src/mobile/settingsSections.ts #: src/mobile/views/SettingsView.tsx #: src/renderer/views/SettingsOverlay/parts/ArchivedThreadsSettings.tsx @@ -1173,6 +1211,16 @@ msgstr "Terminal panelini otomatik göster" msgid "Automatically show the terminal panel when running commands or creating worktrees." msgstr "Komutları çalıştırırken veya çalışma ağaçları oluştururken terminal panelini otomatik olarak gösterin." +#: src/renderer/views/SchedulesView/SchedulesView.tsx +msgid "Automation sections" +msgstr "Otomasyon bölümleri" + +#: src/mobile/settingsSections.ts +#: src/renderer/views/MainView/parts/Sidebar/Sidebar.tsx +#: src/renderer/views/SchedulesView/SchedulesView.tsx +msgid "Automations" +msgstr "Otomasyonlar" + #: src/renderer/components/skills/SkillImportModal.tsx msgid "Availability" msgstr "Kullanılabilirlik" @@ -1459,6 +1507,10 @@ msgstr "Şube koruma kurallarını atla (yönetici birleştirme)" msgid "Cached only" msgstr "Yalnızca önbellekte" +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Calculated on desktop after saving" +msgstr "Kaydettikten sonra masaüstünde hesaplanır" + #: src/mobile/QrScanner.tsx msgid "Camera access blocked" msgstr "Kamera erişimi engellendi" @@ -1513,11 +1565,16 @@ msgstr "Seçiciyi iptal et" msgid "Cancel removing project" msgstr "Projeyi kaldırmayı iptal et" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Cancel run" +msgstr "Çalıştırmayı iptal et" + #: src/renderer/components/thread/ChatPane/parts/items/WorkflowOverlayBody.tsx msgid "cancelled" msgstr "iptal edildi" #: src/renderer/utils/prStatus.ts +#: src/renderer/views/SchedulesView/parts/PreviousRunsModal.tsx msgid "Cancelled" msgstr "İptal edildi" @@ -1706,6 +1763,10 @@ msgstr "Poracode'un arayüzü için görüntüleme dilini seçin." msgid "Choose thread to attach to" msgstr "Eklenecek konuyu seçin" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Choose what happens after a scheduled time was missed." +msgstr "Planlanan bir zaman kaçırıldığında ne olacağını seçin." + #: src/renderer/views/SettingsOverlay/parts/BrowserSettings.tsx #: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts msgid "Choose whether links from Poracode and browser popups stay in Poracode or open externally." @@ -2185,6 +2246,14 @@ msgstr "tamamlandı" msgid "Completed" msgstr "Tamamlandı" +#: src/renderer/i18n/sharedMessages.ts +msgid "Completion evaluation failed: {detail}" +msgstr "Tamamlanma değerlendirmesi başarısız oldu: {detail}" + +#: src/renderer/i18n/sharedMessages.ts +msgid "Completion evaluation is unavailable." +msgstr "Tamamlanma değerlendirmesi kullanılamıyor." + #: src/renderer/commands/shortcutCatalog.ts #: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx #: src/renderer/views/SettingsOverlay/parts/settingsOptions.ts @@ -2223,6 +2292,14 @@ msgstr "Computer Use etkin — etkileşimli eylemler masaüstünü kontrol eder; #~ msgid "Computer Use enabled for this thread" #~ msgstr "Bu konu için Bilgisayar Kullanımı etkinleştirildi" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Confidence" +msgstr "Güven" + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Confidence percent" +msgstr "Güven yüzdesi" + #: src/renderer/views/SettingsOverlay/parts/ClaudeProfileSettings.tsx msgid "Config directory" msgstr "Yapılandırma dizini" @@ -2386,6 +2463,14 @@ msgstr "Başka bir sağlayıcıda devam et" msgid "Continue in..." msgstr "Şurada devam et..." +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Continue one conversation until a stop condition or limit is reached." +msgstr "Durdurma koşuluna veya sınıra ulaşılana kadar tek bir konuşmayı sürdürün." + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Control how each scheduled run continues and stops." +msgstr "Planlanan her çalıştırmanın nasıl devam edeceğini ve duracağını belirleyin." + #: src/renderer/views/SettingsOverlay/parts/SearchSettings.tsx msgid "Control which files appear in the @file mention search. Per-project overrides live in each project's settings." msgstr "@file bahsetme aramasında hangi dosyaların görüneceğini kontrol edin. Projeye özel geçersiz kılmalar her projenin ayarlarında bulunur." @@ -2397,6 +2482,7 @@ msgstr "Ajan tıklarken veya yazarken eşleştirilmiş masaüstünü kontrol ede #: src/mobile/views/pr/PrConversationPage.tsx #: src/mobile/views/pr/PrOverviewPage.tsx #: src/renderer/views/PrReviewOverlay/parts/PrTabsPill.tsx +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx msgid "Conversation" msgstr "Konuşma" @@ -2697,6 +2783,24 @@ msgstr "Kimlik bilgileri yapılandırıldı." msgid "Credits" msgstr "Krediler" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Critical" +msgstr "Kritik" + +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Cron" +msgstr "Cron" + +#. placeholder {0}: task.recurrence.expression +#. placeholder {1}: task.recurrence.timeZone +#: src/renderer/views/SchedulesView/SchedulesView.tsx +msgid "Cron {0} in {1}" +msgstr "Cron {0} ({1})" + +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Cron expression" +msgstr "Cron ifadesi" + #: src/renderer/components/skills/SkillMarketplaceModal.tsx #~ msgid "Curated free and premium skills managed by MCP Market." #~ msgstr "MCP Market tarafından yönetilen seçilmiş ücretsiz ve premium beceriler." @@ -2762,9 +2866,9 @@ msgstr "Günlük özet" msgid "Dark" msgstr "Karanlık" -#: src/renderer/views/SchedulesView/SchedulesView.tsx -#~ msgid "Days" -#~ msgstr "Günler" +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Days" +msgstr "Günler" #: src/renderer/components/thread/ThreadRuntimeRequestPanel/structuredElicitation.tsx msgid "Decline" @@ -2911,6 +3015,10 @@ msgstr "{0} çalışma ağacını sil" #~ msgid "Delete:" #~ msgstr "Sil:" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Deleted schedule" +msgstr "Silinen zamanlama" + #: src/renderer/views/SettingsOverlay/parts/AcpRegistrySettings.tsx msgid "Deleting" msgstr "Siliniyor" @@ -2923,6 +3031,10 @@ msgstr "Reddet" msgid "Deny and tell the agent what to do differently…" msgstr "Reddet ve aracıya neyi farklı yapması gerektiğini söyle…" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Describe the result that completes this heartbeat." +msgstr "Bu heartbeat'i tamamlayan sonucu açıklayın." + #: src/renderer/views/SchedulesView/ScheduleEditor.tsx msgid "Describe what the agent should do" msgstr "Ajanın ne yapması gerektiğini açıklayın" @@ -2944,6 +3056,10 @@ msgstr "Masaüstü uç noktası" msgid "Desktop is unreachable." msgstr "Masaüstüne ulaşılamıyor." +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Desktop local time" +msgstr "Masaüstünün yerel saati" + #: src/mobile/chrome.ts #: src/mobile/views/MoreView.tsx msgid "Desktop Settings" @@ -3056,6 +3172,10 @@ msgstr "Projeyi Devre Dışı Bırak" msgid "Disable Subagents" msgstr "Alt aracıları Devre Dışı Bırak" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Disable the automation after retries are exhausted." +msgstr "Yeniden deneme hakları tükendiğinde otomasyonu devre dışı bırakır." + #: src/renderer/views/SettingsOverlay/parts/ClaudeProfileSettings.tsx msgid "Disable tiers an external provider collapses (e.g. keep only High and Max)." msgstr "Harici bir sağlayıcının birleştirdiği düzeyleri devre dışı bırakın (ör. yalnızca High ve Max'i tutun)." @@ -3356,6 +3476,10 @@ msgstr "Etkinleştirilen sunucular yeni konular için açık kalır" msgid "Enables <0>cookies and <1>storage. Cookies can contain session tokens and storage often holds auth state — only enable when you trust both the agent and the sites it visits." msgstr "<0>Çerezler'i ve <1>depolamayı etkinleştirir. Çerezler oturum belirteçleri içerebilir ve depolama genellikle kimlik doğrulama durumunu tutar; yalnızca hem aracıya hem de onun ziyaret ettiği sitelere güvendiğinizde etkinleştirilir." +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +#~ msgid "End the heartbeat after retries are exhausted." +#~ msgstr "Yeniden denemeler tükendikten sonra heartbeat'i sonlandırın." + #: src/mobile/views/DesktopsView.tsx #: src/renderer/views/SettingsOverlay/parts/RemoteServersSettings.tsx msgid "Endpoint" @@ -3393,6 +3517,10 @@ msgstr "Geçerli bir masaüstü uç noktası girin." msgid "Enter a valid HTTP or HTTPS URL." msgstr "Geçerli bir HTTP veya HTTPS URL'si girin." +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Enter a valid schedule" +msgstr "Geçerli bir zamanlama girin" + #: src/mobile/views/DesktopsView.tsx msgid "Enter a valid SSH target and port." msgstr "Geçerli bir SSH hedefi ve bağlantı noktası girin." @@ -3463,6 +3591,14 @@ msgstr "Hata" msgid "Error · Agent encountered an error" msgstr "Hata · Temsilci bir hatayla karşılaştı" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Evaluate the result after every iteration." +msgstr "Her yinelemeden sonra sonucu değerlendirin." + +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Every" +msgstr "Her" + #: src/renderer/views/SchedulesView/SchedulesView.tsx msgid "Every day at {time}" msgstr "Her gün saat {time}" @@ -3485,6 +3621,14 @@ msgstr "Her saat {0} geçe" msgid "Exclude patterns" msgstr "Kalıpları hariç tut" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Execution" +msgstr "Çalıştırma" + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Execution mode" +msgstr "Çalıştırma modu" + #: src/renderer/components/thread/ChatPane/parts/items/toolDisplay.ts msgid "Exit plan mode" msgstr "Plan modundan çık" @@ -3534,6 +3678,10 @@ msgstr "Erişimi incelemek veya iptal etmek için genişletin." msgid "Expand todo dock" msgstr "Yapılacaklar iskelesini genişlet" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Exponential backoff" +msgstr "Üstel gecikme" + #: src/renderer/components/mcp/McpServersManager.tsx msgid "Export MCP servers" msgstr "MCP sunucularını dışa aktar" @@ -3716,6 +3864,10 @@ msgstr "Farkta bul" msgid "Find in terminal" msgstr "Terminalde bul" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Finding status" +msgstr "Bulgu durumu" + #: src/renderer/views/PrReviewOverlay/parts/SubmitReviewPopover.tsx msgid "Finish your review" msgstr "İncelemenizi tamamlayın" @@ -3777,6 +3929,10 @@ msgstr "Aracıda Düzelt" msgid "Fixed" msgstr "Düzeltildi" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Fixed delay" +msgstr "Sabit gecikme" + #: src/renderer/commands/registry.ts msgid "Focus browser address bar" msgstr "Tarayıcı adres çubuğuna odakla" @@ -4097,6 +4253,26 @@ msgstr "Gönderilmemiş taslak var" msgid "Headers" msgstr "Üstbilgiler" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Heartbeat" +msgstr "Heartbeat" + +#: src/renderer/i18n/sharedMessages.ts +msgid "Heartbeat automations require a native chat conversation." +msgstr "Heartbeat otomasyonları yerel bir sohbet konuşması gerektirir." + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Heartbeat continues this conversation in the selected project." +msgstr "Heartbeat, seçilen projede bu konuşmayı sürdürür." + +#: src/renderer/i18n/sharedMessages.ts +msgid "Heartbeat execution is unavailable." +msgstr "Heartbeat çalıştırması kullanılamıyor." + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Heartbeats can continue making changes while you're away. Set hard limits below." +msgstr "Heartbeat'ler siz uzaktayken değişiklik yapmaya devam edebilir. Aşağıda kesin sınırlar belirleyin." + #: src/renderer/views/SchedulesView/SchedulesView.tsx msgid "Help me create a schedule. Ask for any missing details, then use the Poracode schedule controls to create it for me." msgstr "Bir zamanlama oluşturmama yardım et. Eksik ayrıntıları sor, ardından Poracode zamanlama kontrollerini kullanarak benim için oluştur." @@ -4198,6 +4374,10 @@ msgstr "host.com, takma ad veya kullanıcı@host.com" msgid "Hourly" msgstr "Saatlik" +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Hours" +msgstr "Saat" + #: src/renderer/components/mcp/McpServerEditor.tsx msgid "HTTP (streamable)" msgstr "HTTP (akış destekli)" @@ -4328,6 +4508,14 @@ msgstr "Uygulama içi kamera taraması yalnızca HTTPS üzerinden çalışır. M msgid "Inactive" msgstr "Etkin değil" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Includes the first attempt." +msgstr "İlk denemeyi içerir." + +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Info" +msgstr "Bilgi" + #. Badge on an exclude pattern inherited from a lower scope #: src/renderer/views/SettingsOverlay/parts/SearchExcludeBody.tsx msgid "inherited" @@ -4338,6 +4526,14 @@ msgstr "miras alınan" msgid "Inheriting the global setting (currently {0})." msgstr "Genel ayar devralınıyor (şu anda {0})." +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Initial retry delay" +msgstr "İlk yeniden deneme gecikmesi" + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Initial retry delay in seconds" +msgstr "Saniye cinsinden ilk yeniden deneme gecikmesi" + #: src/renderer/views/GitReviewOverlay/parts/GitReviewSidebar/GitReviewSidebar.tsx msgid "Initialize Repository" msgstr "Depoyu Başlat" @@ -4476,6 +4672,18 @@ msgstr "Kesintiye uğradı" msgid "Interrupted: agent session ended before completion." msgstr "Kesintiye uğradı: Ajan oturumu tamamlanmadan sona erdi." +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Interval" +msgstr "Aralık" + +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Interval amount" +msgstr "Aralık değeri" + +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Interval unit" +msgstr "Aralık birimi" + #: src/renderer/views/MainView/parts/RightPanel/parts/NotesPanel/NotesEditor.tsx msgid "Italic" msgstr "italik" @@ -4560,6 +4768,14 @@ msgstr "Başlatılıyor…" msgid "Leave a comment" msgstr "Yorum bırak" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Leave blank for no run limit." +msgstr "Çalıştırma sayısını sınırlamamak için boş bırakın." + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +#~ msgid "Leave blank to rely on the time limit." +#~ msgstr "Zaman sınırını kullanmak için boş bırakın." + #: src/renderer/views/ProfileOverlay/parts/ActivityHeatmap.tsx msgid "Less" msgstr "Az" @@ -4640,6 +4856,10 @@ msgstr "Düzenleyici yükleniyor…" msgid "Loading file…" msgstr "Dosya yükleniyor…" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Loading findings" +msgstr "Bulgular yükleniyor" + #: src/renderer/components/skills/SkillMarketplaceModal.tsx msgid "Loading marketplace…" msgstr "Marketplace yükleniyor…" @@ -4864,6 +5084,14 @@ msgstr "Tamamlandı olarak işaretle" msgid "Mark as not done" msgstr "Tamamlanmadı olarak işaretle" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Mark as read" +msgstr "Okundu olarak işaretle" + +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Mark as unread" +msgstr "Okunmadı olarak işaretle" + #: src/renderer/components/thread/ThreadView.tsx msgid "Mark done" msgstr "Tamamlandı olarak işaretle" @@ -4904,6 +5132,22 @@ msgstr "Büyüt" msgid "Maximize browser" msgstr "Tarayıcıyı büyüt" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Maximum attempts" +msgstr "En fazla deneme" + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Maximum iterations" +msgstr "En fazla yineleme" + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Maximum retry delay" +msgstr "En uzun yeniden deneme gecikmesi" + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Maximum retry delay in seconds" +msgstr "Saniye cinsinden en uzun yeniden deneme gecikmesi" + #: src/renderer/components/skills/SkillMarketplaceModal.tsx #~ msgid "MCP Market" #~ msgstr "MCP Market" @@ -5110,6 +5354,18 @@ msgstr "Panele küçült" msgid "Minute" msgstr "Dakika" +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Minute, hour, day of month, month, and weekday." +msgstr "Dakika, saat, ayın günü, ay ve haftanın günü." + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "minutes" +msgstr "dakika" + +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Minutes" +msgstr "Dakika" + #: src/mobile/views/BrowserView.tsx msgid "Mirrored desktop browser tab" msgstr "Yansıtılan masaüstü tarayıcı sekmesi" @@ -5118,6 +5374,10 @@ msgstr "Yansıtılan masaüstü tarayıcı sekmesi" msgid "Mirroring is unavailable." msgstr "Yansıtma kullanılamıyor." +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Missed runs" +msgstr "Kaçırılan çalıştırmalar" + #: src/renderer/views/SettingsOverlay/parts/RemoteAccessSettings.tsx msgid "Mobile push notifications" msgstr "Mobil push bildirimleri" @@ -5469,6 +5729,10 @@ msgstr "Sonraki eşleşme" msgid "Next recently viewed chat" msgstr "Sonraki son görüntülenen sohbet" +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Next run" +msgstr "Sonraki çalıştırma" + #. placeholder {0}: dateTimeFormatter.format(new Date(task.nextRunAt)) #: src/renderer/views/SchedulesView/SchedulesView.tsx msgid "Next run {0}" @@ -5514,6 +5778,10 @@ msgstr "Hiçbir aracı yüklü değil." msgid "No AI commits, PRs, or conflict resolutions tracked yet." msgstr "Henüz yapay zeka commit'leri, PR'ları veya çakışma çözümleri izlenmedi." +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "No archived findings." +msgstr "Arşivlenmiş bulgu yok." + #: src/renderer/views/SettingsOverlay/parts/ArchivedThreadsSettings.tsx msgid "No archived threads." msgstr "Arşivlenmiş konu yok." @@ -5610,6 +5878,10 @@ msgstr "{0} için fark mevcut değil" msgid "No diff for {visiblePath}" msgstr "{visiblePath} için fark yok" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "No eligible conversations in this project." +msgstr "Bu projede uygun konuşma yok." + #: src/renderer/components/skills/SkillImportModal.tsx msgid "No external skills were found in this scope." msgstr "Bu kapsamda harici beceri bulunamadı." @@ -5625,6 +5897,10 @@ msgstr "Bu mesaj için hiçbir dosya kontrol noktası saklanmadı." msgid "No files match \"{0}\"." msgstr "\"{0}\" ile eşleşen dosya yok." +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "No findings yet." +msgstr "Henüz bulgu yok." + #: src/renderer/views/MainView/parts/CreateProject/CloneProjectModal.tsx msgid "No GitHub CLI accounts found. Sign in with <0>gh auth login, or <1>paste a clone URL." msgstr "GitHub CLI hesabı bulunamadı. <0>gh auth login ile oturum açın veya <1>bir klon URL'si yapıştırın." @@ -5637,6 +5913,10 @@ msgstr "Henüz geçmiş yok" msgid "No Lightcode data was found." msgstr "Lightcode verisi bulunamadı." +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "No limit" +msgstr "Sınır yok" + #: src/renderer/components/skills/SkillMarketplaceModal.tsx msgid "No marketplace skills match these filters." msgstr "Bu filtrelerle eşleşen marketplace becerisi yok." @@ -5653,6 +5933,10 @@ msgstr "Eşleşme yok." msgid "No matching agents." msgstr "Eşleşen temsilci yok." +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "No matching findings." +msgstr "Eşleşen bulgu yok." + #: src/renderer/views/PullRequestsView/PullRequestsView.tsx msgid "No matching pull requests." msgstr "Eşleşen çekme isteği yok." @@ -5762,6 +6046,10 @@ msgstr "Hiçbir depo bulunamadı." msgid "No results" msgstr "Sonuç yok" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "No retries" +msgstr "Yeniden deneme yok" + #: src/renderer/views/SchedulesView/parts/PreviousRunsModal.tsx msgid "No runs yet." msgstr "Henüz çalıştırma yok." @@ -5798,6 +6086,10 @@ msgstr "Konuşma algılanmadı." msgid "No staged changes" msgstr "Aşamalı değişiklik yok" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "No summary was provided." +msgstr "Özet sağlanmadı." + #: src/renderer/views/RemoteProjectModal/RemoteProjectModal.tsx msgid "No supported agents are installed on this remote machine. Install and sign in to an agent remotely before starting a thread." msgstr "Bu uzak makinede desteklenen bir aracı yüklü değil. Bir iş parçacığı başlatmadan önce uzaktan bir aracı yükleyip oturum açın." @@ -5827,6 +6119,10 @@ msgstr "Henüz iş parçacığı yok" msgid "No threads yet." msgstr "Henüz konuşma yok." +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "No upcoming run" +msgstr "Yaklaşan çalıştırma yok" + #: src/renderer/components/providers/usageFormat.ts msgid "No windows reported" msgstr "Hiçbir pencere bildirilmedi" @@ -6042,6 +6338,11 @@ msgstr "Commit'i GitHub'da aç" msgid "Open conflict resolver in" msgstr "Çakışma çözümleyiciyi şurada açın" +#. placeholder {0}: props.scheduleName +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Open conversation for {0}" +msgstr "{0} için konuşmayı aç" + #: src/renderer/views/SettingsOverlay/parts/settingsOptions.ts msgid "Open dialog" msgstr "İletişim kutusunu aç" @@ -6677,6 +6978,10 @@ msgstr "Proje klasörü güncellendi. Bu projedeki terminalleri yeniden açın." msgid "Project name" msgstr "Proje adı" +#: src/renderer/i18n/sharedMessages.ts +msgid "Project no longer exists." +msgstr "Proje artık mevcut değil." + #: src/renderer/views/MainView/parts/RightPanel/parts/NotesPanel/NotesEditor.tsx msgid "Project notes" msgstr "Proje notları" @@ -7275,6 +7580,10 @@ msgstr "Ayrıntıları talep et" msgid "requested changes" msgstr "talep edilen değişiklikler" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Required confidence before stopping." +msgstr "Durdurmadan önce gereken güven düzeyi." + #: src/mobile/views/pr/PrOverviewPage.tsx #: src/renderer/views/GitReviewOverlay/parts/GitReviewSidebar/parts/PrSection.tsx msgid "Required reviews, conversations, or status checks not met." @@ -7346,6 +7655,10 @@ msgstr "Tarayıcıyı geri yükle" msgid "Restore default worktree base folder" msgstr "Varsayılan çalışma ağacı temel klasörünü geri yükle" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Restore finding" +msgstr "Bulguyu geri yükle" + #: src/mobile/settingsSections.ts msgid "Restore or delete" msgstr "Geri yükle veya sil" @@ -7376,10 +7689,26 @@ msgstr "{serverName} sunucusunu yeniden dene" msgid "Retry check" msgstr "Kontrolü yeniden dene" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Retry delay" +msgstr "Yeniden deneme gecikmesi" + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Retry delay in seconds" +msgstr "Saniye cinsinden yeniden deneme gecikmesi" + #: src/mobile/components.tsx msgid "Retry now" msgstr "Şimdi tekrar dene" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Retry policy" +msgstr "Yeniden deneme ilkesi" + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Retry when a run fails before it completes." +msgstr "Bir çalıştırma tamamlanmadan önce başarısız olursa yeniden deneyin." + #: src/renderer/hooks/usePrWriteActions.ts msgid "Retry with admin" msgstr "Yönetici ile tekrar dene" @@ -7535,18 +7864,26 @@ msgstr "Mümkün olduğunda GPU'da yerel transkripsiyonu çalıştırın." msgid "Run now" msgstr "Şimdi çalıştır" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Run once after reopening" +msgstr "Yeniden açtıktan sonra bir kez çalıştır" + #: src/renderer/views/SchedulesView/SchedulesView.tsx #~ msgid "Run standalone tasks on this device without a project." #~ msgstr "Bu cihazda proje olmadan bağımsız görevler çalıştırın." #: src/renderer/views/SchedulesView/SchedulesView.tsx -msgid "Run standalone tasks on this device. Schedules run while the device is awake and Poracode is open." -msgstr "Bu cihazda bağımsız görevler çalıştırın. Zamanlamalar cihaz açıkken ve Poracode açıkken çalışır." +#~ msgid "Run standalone tasks on this device. Schedules run while the device is awake and Poracode is open." +#~ msgstr "Bu cihazda bağımsız görevler çalıştırın. Zamanlamalar cihaz açıkken ve Poracode açıkken çalışır." #: src/renderer/commands/registry.ts msgid "Run Terminal Command" msgstr "Terminal Komutunu Çalıştır" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Run the latest missed run" +msgstr "Kaçırılan en son çalıştırmayı gerçekleştir" + #: src/renderer/views/SchedulesView/ScheduleEditor.tsx #~ msgid "Run this schedule automatically at the times above." #~ msgstr "Bu zamanlamayı yukarıdaki saatlerde otomatik olarak çalıştır." @@ -7562,6 +7899,7 @@ msgstr "çalışıyor" #: src/renderer/utils/prStatus.ts #: src/renderer/views/SchedulesView/parts/PreviousRunsModal.tsx +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx msgid "Running" msgstr "Çalışıyor" @@ -7585,6 +7923,10 @@ msgstr "Erken tükeniyor" msgid "Runs out in {runOut}" msgstr "{runOut} içinde biter" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Runs that need attention will appear here." +msgstr "İlgilenmeniz gereken çalıştırmalar burada görünür." + #: src/renderer/views/MainView/parts/CreateProject/CloneProjectModal.tsx #: src/renderer/views/MainView/parts/CreateProject/CreateProjectModal.tsx msgid "Runtime" @@ -7661,6 +8003,10 @@ msgstr "Yüklü CLI'ler için Windows ve WSL taranıyor. Bu genellikle birkaç s msgid "Scanning your system for installed CLIs. This usually takes a couple of seconds." msgstr "Kurulu CLI'ler için sisteminiz taranıyor. Bu genellikle birkaç saniye sürer." +#: src/renderer/views/SchedulesView/SchedulesView.tsx +msgid "Schedule autonomous work and review results that need your attention. Automations run while this device is awake and Poracode is open." +msgstr "Otonom çalışmaları planlayın ve ilgilenmeniz gereken sonuçları gözden geçirin. Otomasyonlar, bu cihaz uyanık ve Poracode açık olduğu sürece çalışır." + #: src/renderer/views/SchedulesView/ScheduleEditor.tsx msgid "Schedule name" msgstr "Zamanlama adı" @@ -7669,20 +8015,31 @@ msgstr "Zamanlama adı" msgid "Schedule status" msgstr "Zamanlama durumu" +#: src/renderer/i18n/sharedMessages.ts +msgid "Scheduled retry was cancelled." +msgstr "Planlanan yeniden deneme iptal edildi." + +#: src/renderer/i18n/sharedMessages.ts +msgid "Scheduled task was deleted before retrying." +msgstr "Planlanan görev yeniden denenmeden önce silindi." + #: src/renderer/views/SchedulesView/SchedulesView.tsx -msgid "Scheduled tasks" -msgstr "Zamanlanmış görevler" +#~ msgid "Scheduled tasks" +#~ msgstr "Zamanlanmış görevler" #: src/mobile/settingsSections.ts -msgid "Scheduled tasks on this desktop" -msgstr "Bu masaüstündeki zamanlanmış görevler" +#~ msgid "Scheduled tasks on this desktop" +#~ msgstr "Bu masaüstündeki zamanlanmış görevler" #: src/renderer/views/SchedulesView/SchedulesView.tsx #~ msgid "Scheduled tasks run only while this device is awake and Poracode is open." #~ msgstr "Zamanlanmış görevler yalnızca bu cihaz açıkken ve Poracode çalışırken yürütülür." #: src/mobile/settingsSections.ts -#: src/renderer/views/MainView/parts/Sidebar/Sidebar.tsx +msgid "Scheduled work and triage on this desktop" +msgstr "Bu masaüstündeki planlanan çalışmalar ve triyaj" + +#: src/renderer/views/SchedulesView/SchedulesView.tsx msgid "Schedules" msgstr "Zamanlamalar" @@ -7737,6 +8094,10 @@ msgstr "Şube ara..." msgid "Search files" msgstr "Dosyaları arayın" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Search findings" +msgstr "Bulgularda ara" + #: src/renderer/components/skills/SkillMarketplaceModal.tsx msgid "Search marketplace skills" msgstr "Marketplace becerilerinde ara" @@ -7831,6 +8192,10 @@ msgstr "Aranıyor..." msgid "Searching…" msgstr "Aranıyor…" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "seconds" +msgstr "saniye" + #: src/renderer/components/skills/SkillMarketplaceModal.tsx #~ msgid "Security-focused directory with verified skill metadata." #~ msgstr "Doğrulanmış beceri meta verileri sunan güvenlik odaklı dizin." @@ -8221,6 +8586,10 @@ msgstr "{env} oturumu kapatılıyor. Algılanan aracılar tamamlandığında yen msgid "Signing out. Detected agents will refresh when it finishes." msgstr "Çıkış yapılıyor. Algılanan aracılar tamamlandığında yenilenecektir." +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Single pass" +msgstr "Tek geçiş" + #: src/renderer/components/skills/SkillImportModal.tsx #: src/renderer/components/skills/SkillMarketplaceModal.tsx msgid "Skill availability" @@ -8285,7 +8654,12 @@ msgstr "Beceri marketplace'i" msgid "Skills.sh" msgstr "Skills.sh" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Skip missed runs" +msgstr "Kaçırılan çalıştırmaları atla" + #: src/renderer/utils/prStatus.ts +#: src/renderer/views/SchedulesView/parts/PreviousRunsModal.tsx msgid "Skipped" msgstr "Atlandı" @@ -8424,6 +8798,10 @@ msgstr "Kullanımı görmek için {appName} uygulamasını başlatın" msgid "Start a dev server on your desktop, then tap refresh." msgstr "Masaüstünüzde bir geliştirme sunucusu başlatın, ardından yenile'ye dokunun." +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Start a new conversation for each run." +msgstr "Her çalıştırma için yeni bir konuşma başlatın." + #: src/renderer/commands/registry.ts msgid "Start a new thread as panel instead of page" msgstr "Yeni bir konuyu sayfa yerine panel olarak başlatın" @@ -8562,6 +8940,10 @@ msgstr "Durdur" msgid "Stop forwarding" msgstr "Yönlendirmeyi durdur" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Stop on error" +msgstr "Hata durumunda durdur" + #: src/renderer/components/thread/ThreadComposer.tsx msgid "Stop response" msgstr "Yanıtı durdur" @@ -8574,10 +8956,18 @@ msgstr "Görevi durdur" msgid "Stop the project's running threads before changing its folder." msgstr "Klasörünü değiştirmeden önce projenin çalışan konularını durdurun." +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Stop the run when this total time is reached." +msgstr "Bu toplam süreye ulaşıldığında çalıştırmayı durdurun." + #: src/renderer/components/composer/VoiceInputButton.tsx msgid "Stop voice input" msgstr "Ses girişini durdur" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Stop when" +msgstr "Şu durumda durdur" + #: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts #: src/renderer/views/SettingsOverlay/parts/WorktreeSettings.tsx msgid "Storage location" @@ -8922,6 +9312,22 @@ msgstr "Temsilci" msgid "the app" msgstr "uygulama" +#: src/renderer/i18n/sharedMessages.ts +msgid "The automation conversation exited before the turn completed." +msgstr "Otomasyon konuşması tur tamamlanmadan önce sonlandı." + +#: src/renderer/i18n/sharedMessages.ts +msgid "The automation exceeded its time limit." +msgstr "Otomasyon zaman sınırını aştı." + +#: src/renderer/i18n/sharedMessages.ts +msgid "The automation needs a reply before it can continue." +msgstr "Otomasyonun devam edebilmesi için bir yanıt gerekiyor." + +#: src/renderer/i18n/sharedMessages.ts +msgid "The automation needs approval before it can continue." +msgstr "Otomasyonun devam edebilmesi için onay gerekiyor." + #: src/renderer/views/MainView/parts/CreateProject/CloneProjectModal.tsx msgid "the chosen folder" msgstr "seçilen klasör" @@ -8935,11 +9341,39 @@ msgstr "Aşağıda kendi aralığı ayarlanmamış sağlayıcılar için kullan msgid "The desktop server is still coming online." msgstr "Masaüstü sunucusu hâlâ başlatılıyor." +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "The finding is no longer available." +msgstr "Bulgu artık kullanılamıyor." + #. placeholder {0}: createTarget.wslDistro #: src/renderer/components/skills/SkillsManager.tsx msgid "the global {0} WSL scope" msgstr "genel {0} WSL kapsamı" +#: src/renderer/i18n/sharedMessages.ts +msgid "The heartbeat conversation belongs to a different project." +msgstr "Heartbeat konuşması farklı bir projeye ait." + +#: src/renderer/i18n/sharedMessages.ts +msgid "The heartbeat conversation cannot be resumed." +msgstr "Heartbeat konuşması sürdürülemiyor." + +#: src/renderer/i18n/sharedMessages.ts +msgid "The heartbeat conversation is archived." +msgstr "Heartbeat konuşması arşivlenmiş." + +#: src/renderer/i18n/sharedMessages.ts +msgid "The heartbeat conversation is currently busy." +msgstr "Heartbeat konuşması şu anda meşgul." + +#: src/renderer/i18n/sharedMessages.ts +msgid "The heartbeat conversation no longer exists." +msgstr "Heartbeat konuşması artık mevcut değil." + +#: src/renderer/i18n/sharedMessages.ts +msgid "The heartbeat conversation uses a different agent." +msgstr "Heartbeat konuşması farklı bir ajan kullanıyor." + #: src/renderer/components/skills/SkillsManager.tsx msgid "the Linux user" msgstr "Linux kullanıcısı" @@ -8972,6 +9406,14 @@ msgstr "Uzak sunucu eşleştirme kimlik bilgisi döndürmedi." msgid "The repository location on disk. Update it if you moved the folder." msgstr "Deponun diskteki konumu. Klasörü taşıdıysanız güncelleyin." +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "The run could not be cancelled." +msgstr "Çalıştırma iptal edilemedi." + +#: src/renderer/i18n/sharedMessages.ts +msgid "The scheduled automation failed." +msgstr "Planlanan otomasyon başarısız oldu." + #: src/renderer/components/mcp/McpServersManager.tsx #~ msgid "The selected file does not contain valid MCP server configurations." #~ msgstr "Seçilen dosyada geçerli MCP sunucusu yapılandırmaları yok." @@ -9227,6 +9669,18 @@ msgstr "Bu kadar gün boyunca dokunulmayan ve tamamlandı olarak işaretlenen ko msgid "Time" msgstr "Saat" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Time limit" +msgstr "Zaman sınırı" + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Time limit in minutes" +msgstr "Dakika cinsinden zaman sınırı" + +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Time zone" +msgstr "Saat dilimi" + #: src/renderer/components/mcp/McpServerEditor.tsx msgid "Timeout (ms)" msgstr "Zaman aşımı (ms)" @@ -9356,6 +9810,10 @@ msgstr "Yarı saydam kenar çubuğu" msgid "Trending now" msgstr "Şu anda trend" +#: src/renderer/views/SchedulesView/SchedulesView.tsx +msgid "Triage" +msgstr "Triyaj" + #: src/mobile/views/DesktopsView.tsx msgid "Trust and connect" msgstr "Güven ve bağlan" @@ -9598,6 +10056,10 @@ msgstr "Atanmamış" msgid "Unavailable" msgstr "Kullanılamıyor" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Unavailable conversation" +msgstr "Kullanılamayan konuşma" + #: src/renderer/views/SchedulesView/ScheduleEditor.tsx msgid "Unavailable project" msgstr "Kullanılamayan proje" @@ -9676,6 +10138,10 @@ msgstr "Aşamasız:" msgid "Unpin" msgstr "Sabitlemeyi kaldır" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Unread" +msgstr "Okunmadı" + #: src/mobile/views/GitActionSheet.tsx #: src/renderer/views/GitReviewOverlay/parts/GitReviewSidebar/parts/FileRow.tsx #: src/renderer/views/GitReviewOverlay/parts/GitStackedDiff.tsx @@ -10002,6 +10468,12 @@ msgstr "{methodName} kimlik doğrulaması bekleniyor. Tamamlandığında algıla msgid "waiting for agent to stop" msgstr "aracının durması bekleniyor" +#: src/renderer/views/SchedulesView/parts/PreviousRunsModal.tsx +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +#: src/renderer/views/SchedulesView/SchedulesView.tsx +msgid "Waiting for approval" +msgstr "Onay bekleniyor" + #: src/renderer/components/thread/ChatPane/parts/items/WorkflowOverlayBody.tsx msgid "Waiting for workflow to spawn agents…" msgstr "İş akışının aracıları oluşturması bekleniyor…" @@ -10034,6 +10506,10 @@ msgstr "Kabuk ortamları ısınıyor..." msgid "Warming up WSL shell environment…" msgstr "WSL kabuk ortamı ısınıyor…" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Warning" +msgstr "Uyarı" + #: src/renderer/components/thread/ChatPane/parts/items/ToolCallGroup.tsx #: src/renderer/components/thread/ChatPane/parts/items/toolDisplay.ts #: src/renderer/components/thread/ChatPane/parts/items/WebSearchItem.tsx @@ -10326,6 +10802,10 @@ msgstr "WSL temel klasörü" #~ msgid "WSL user" #~ msgstr "WSL kullanıcısı" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "You’re all caught up." +msgstr "Her şey tamam." + #: src/renderer/views/ProfileOverlay/parts/EditProfileDialog.tsx msgid "Your name" msgstr "Adınız" diff --git a/src/renderer/locales/uk/messages.po b/src/renderer/locales/uk/messages.po index f89153719..ae6ef3c27 100644 --- a/src/renderer/locales/uk/messages.po +++ b/src/renderer/locales/uk/messages.po @@ -288,6 +288,11 @@ msgstr "{agentLabel}: {statusLabel}. Наведіть для деталей ст msgid "{agentLead} needs your input to continue." msgstr "{agentLead} потребує вашого введення, щоб продовжити." +#. placeholder {0}: task.recurrence.timeZone +#: src/renderer/views/SchedulesView/SchedulesView.tsx +msgid "{cadence} in {0}" +msgstr "{cadence} — часовий пояс {0}" + #: src/mobile/views/pr/PrOverviewPage.tsx msgid "{commitsCount, plural, one {# commit} other {# commits}}" msgstr "{commitsCount, plural, one {# коміт} few {# коміти} many {# комітів} other {# коміта}}" @@ -315,6 +320,18 @@ msgstr "{days}д тому" msgid "{envOrAgentLabel} needs authentication." msgstr "{envOrAgentLabel} потребує автентифікації." +#: src/renderer/views/SchedulesView/SchedulesView.tsx +msgid "{every, plural, one {Every day} other {Every # days}}" +msgstr "{every, plural, one {Щодня} few {Кожні # дні} many {Кожні # днів} other {Кожні # дня}}" + +#: src/renderer/views/SchedulesView/SchedulesView.tsx +msgid "{every, plural, one {Every hour} other {Every # hours}}" +msgstr "{every, plural, one {Щогодини} few {Кожні # години} many {Кожні # годин} other {Кожні # години}}" + +#: src/renderer/views/SchedulesView/SchedulesView.tsx +msgid "{every, plural, one {Every minute} other {Every # minutes}}" +msgstr "{every, plural, one {Щохвилини} few {Кожні # хвилини} many {Кожні # хвилин} other {Кожні # хвилини}}" + #: src/mobile/views/pr/PrOverviewPage.tsx msgid "{filesCount, plural, one {# file changed} other {# files changed}}" msgstr "{filesCount, plural, one {# файл змінено} few {# файли змінено} many {# файлів змінено} other {# файла змінено}}" @@ -491,6 +508,10 @@ msgstr "~{money}{tokens} · {0} · прибл." msgid "≈{0}% by reset" msgstr "≈{0}% до скидання" +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "0 9 * * 1-5" +msgstr "0 9 * * 1-5" + #: src/mobile/views/ThreadsView.tsx msgid "1 thread" msgstr "1 потік" @@ -840,6 +861,10 @@ msgstr "Дії AI у git" msgid "AI providers" msgstr "Постачальники AI" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "AI stop condition" +msgstr "Умова зупинки ШІ" + #: src/mobile/views/MoreView.tsx #~ msgid "AI, agents, and archived threads on the paired desktop" #~ msgstr "ШІ, агенти й архівовані треди на спареному робочому столі" @@ -851,6 +876,7 @@ msgstr "Сповіщення, коли потокам потрібна ваша #: src/renderer/commands/shortcutCatalog.ts #: src/renderer/components/skills/SkillsManager.tsx #: src/renderer/views/PullRequestsView/PullRequestsView.tsx +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx #: src/renderer/views/SchedulesView/SchedulesView.tsx #: src/renderer/views/SettingsOverlay/parts/ProfileSettings.tsx msgid "All" @@ -943,6 +969,10 @@ msgstr "Завжди виключено" msgid "An MCP server with this name already exists." msgstr "Сервер MCP із такою назвою вже існує." +#: src/renderer/i18n/sharedMessages.ts +msgid "Another automation is already using this conversation." +msgstr "Цю розмову вже використовує інша автоматизація." + #: src/renderer/components/thread/ChatPane/parts/CheckpointRevertControls.tsx msgid "Another chat uses this same tree. File restore could overwrite that chat's changes." msgstr "Інший чат використовує це саме дерево. Відновлення файлів може перезаписати зміни цього чату." @@ -1014,6 +1044,10 @@ msgstr "Архівувати все" msgid "Archive all threads" msgstr "Архівувати всі потоки" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Archive finding" +msgstr "Архівувати результат" + #: src/renderer/commands/registry.ts msgid "Archive the current thread" msgstr "Архівувати поточний тред" @@ -1028,6 +1062,10 @@ msgstr "Архівувати тред" msgid "Archive Thread" msgstr "Архівувати тред" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Archived" +msgstr "В архіві" + #: src/mobile/settingsSections.ts #: src/mobile/views/SettingsView.tsx #: src/renderer/views/SettingsOverlay/parts/ArchivedThreadsSettings.tsx @@ -1173,6 +1211,16 @@ msgstr "Автоматично показувати панель терміна msgid "Automatically show the terminal panel when running commands or creating worktrees." msgstr "Автоматично показувати панель термінала під час виконання команд або створення робочих дерев." +#: src/renderer/views/SchedulesView/SchedulesView.tsx +msgid "Automation sections" +msgstr "Розділи автоматизації" + +#: src/mobile/settingsSections.ts +#: src/renderer/views/MainView/parts/Sidebar/Sidebar.tsx +#: src/renderer/views/SchedulesView/SchedulesView.tsx +msgid "Automations" +msgstr "Автоматизації" + #: src/renderer/components/skills/SkillImportModal.tsx msgid "Availability" msgstr "Доступність" @@ -1459,6 +1507,10 @@ msgstr "Обійти правила захисту гілки (злиття ад msgid "Cached only" msgstr "Лише кеш" +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Calculated on desktop after saving" +msgstr "Обчислюється на комп’ютері після збереження" + #: src/mobile/QrScanner.tsx msgid "Camera access blocked" msgstr "Доступ до камери заблоковано" @@ -1513,11 +1565,16 @@ msgstr "Скасувати вибір" msgid "Cancel removing project" msgstr "Скасувати видалення проєкту" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Cancel run" +msgstr "Скасувати запуск" + #: src/renderer/components/thread/ChatPane/parts/items/WorkflowOverlayBody.tsx msgid "cancelled" msgstr "скасовано" #: src/renderer/utils/prStatus.ts +#: src/renderer/views/SchedulesView/parts/PreviousRunsModal.tsx msgid "Cancelled" msgstr "Скасовано" @@ -1706,6 +1763,10 @@ msgstr "Виберіть мову відображення інтерфейсу msgid "Choose thread to attach to" msgstr "Виберіть тред для прикріплення" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Choose what happens after a scheduled time was missed." +msgstr "Виберіть, що робити, якщо запланований час було пропущено." + #: src/renderer/views/SettingsOverlay/parts/BrowserSettings.tsx #: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts msgid "Choose whether links from Poracode and browser popups stay in Poracode or open externally." @@ -2185,6 +2246,14 @@ msgstr "завершено" msgid "Completed" msgstr "Завершено" +#: src/renderer/i18n/sharedMessages.ts +msgid "Completion evaluation failed: {detail}" +msgstr "Не вдалося оцінити завершення: {detail}" + +#: src/renderer/i18n/sharedMessages.ts +msgid "Completion evaluation is unavailable." +msgstr "Оцінювання завершення недоступне." + #: src/renderer/commands/shortcutCatalog.ts #: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx #: src/renderer/views/SettingsOverlay/parts/settingsOptions.ts @@ -2223,6 +2292,14 @@ msgstr "Computer Use увімкнено — інтерактивні дії за #~ msgid "Computer Use enabled for this thread" #~ msgstr "Керування комп'ютером увімкнено для цього треду" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Confidence" +msgstr "Впевненість" + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Confidence percent" +msgstr "Впевненість у відсотках" + #: src/renderer/views/SettingsOverlay/parts/ClaudeProfileSettings.tsx msgid "Config directory" msgstr "Каталог конфігурації" @@ -2386,6 +2463,14 @@ msgstr "Продовжити в іншому провайдері" msgid "Continue in..." msgstr "Продовжити в..." +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Continue one conversation until a stop condition or limit is reached." +msgstr "Продовжувати одну розмову, доки не буде виконано умову зупинки або досягнуто обмеження." + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Control how each scheduled run continues and stops." +msgstr "Налаштуйте, як продовжується та зупиняється кожен запланований запуск." + #: src/renderer/views/SettingsOverlay/parts/SearchSettings.tsx msgid "Control which files appear in the @file mention search. Per-project overrides live in each project's settings." msgstr "Керуйте тим, які файли з'являються у пошуку згадок @file. Перевизначення для окремих проєктів зберігаються в налаштуваннях кожного проєкту." @@ -2397,6 +2482,7 @@ msgstr "Керує спареним робочим столом, поки аге #: src/mobile/views/pr/PrConversationPage.tsx #: src/mobile/views/pr/PrOverviewPage.tsx #: src/renderer/views/PrReviewOverlay/parts/PrTabsPill.tsx +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx msgid "Conversation" msgstr "Розмова" @@ -2697,6 +2783,24 @@ msgstr "Облікові дані налаштовано." msgid "Credits" msgstr "Кредити" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Critical" +msgstr "Критичний" + +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Cron" +msgstr "Cron" + +#. placeholder {0}: task.recurrence.expression +#. placeholder {1}: task.recurrence.timeZone +#: src/renderer/views/SchedulesView/SchedulesView.tsx +msgid "Cron {0} in {1}" +msgstr "Cron {0} — часовий пояс {1}" + +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Cron expression" +msgstr "Вираз Cron" + #: src/renderer/components/skills/SkillMarketplaceModal.tsx #~ msgid "Curated free and premium skills managed by MCP Market." #~ msgstr "Відібрані безкоштовні та преміальні навички під керуванням MCP Market." @@ -2762,9 +2866,9 @@ msgstr "Щоденний огляд" msgid "Dark" msgstr "Темна" -#: src/renderer/views/SchedulesView/SchedulesView.tsx -#~ msgid "Days" -#~ msgstr "Дні" +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Days" +msgstr "Дні" #: src/renderer/components/thread/ThreadRuntimeRequestPanel/structuredElicitation.tsx msgid "Decline" @@ -2911,6 +3015,10 @@ msgstr "Видалити worktree {0}" #~ msgid "Delete:" #~ msgstr "Видалити:" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Deleted schedule" +msgstr "Видалений розклад" + #: src/renderer/views/SettingsOverlay/parts/AcpRegistrySettings.tsx msgid "Deleting" msgstr "Видалення" @@ -2923,6 +3031,10 @@ msgstr "Заборонити" msgid "Deny and tell the agent what to do differently…" msgstr "Заборонити й сказати агенту, що зробити інакше…" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Describe the result that completes this heartbeat." +msgstr "Опишіть результат, за якого цей пульс буде завершено." + #: src/renderer/views/SchedulesView/ScheduleEditor.tsx msgid "Describe what the agent should do" msgstr "Опишіть, що має зробити агент" @@ -2944,6 +3056,10 @@ msgstr "Кінцева точка робочого стола" msgid "Desktop is unreachable." msgstr "Десктоп недоступний." +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Desktop local time" +msgstr "Локальний час комп’ютера" + #: src/mobile/chrome.ts #: src/mobile/views/MoreView.tsx msgid "Desktop Settings" @@ -3056,6 +3172,10 @@ msgstr "Вимкнути проект" msgid "Disable Subagents" msgstr "Вимкнути субагентів" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Disable the automation after retries are exhausted." +msgstr "Вимкнути автоматизацію після вичерпання всіх повторних спроб." + #: src/renderer/views/SettingsOverlay/parts/ClaudeProfileSettings.tsx msgid "Disable tiers an external provider collapses (e.g. keep only High and Max)." msgstr "Вимкніть рівні, які зовнішній провайдер об'єднує (наприклад, залиште лише High і Max)." @@ -3356,6 +3476,10 @@ msgstr "Увімкнені сервери залишаються активни msgid "Enables <0>cookies and <1>storage. Cookies can contain session tokens and storage often holds auth state — only enable when you trust both the agent and the sites it visits." msgstr "Вмикає <0>файли cookie та <1>сховище. Файли cookie можуть містити сеансові токени, а сховище часто зберігає стан авторизації — вмикайте лише тоді, коли довіряєте і агенту, і сайтам, які він відвідує." +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +#~ msgid "End the heartbeat after retries are exhausted." +#~ msgstr "Завершити пульс після вичерпання повторних спроб." + #: src/mobile/views/DesktopsView.tsx #: src/renderer/views/SettingsOverlay/parts/RemoteServersSettings.tsx msgid "Endpoint" @@ -3393,6 +3517,10 @@ msgstr "Введіть дійсну кінцеву точку десктопа." msgid "Enter a valid HTTP or HTTPS URL." msgstr "Введіть допустиму URL-адресу з протоколом HTTP або HTTPS." +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Enter a valid schedule" +msgstr "Введіть коректний розклад" + #: src/mobile/views/DesktopsView.tsx msgid "Enter a valid SSH target and port." msgstr "Введіть дійсну SSH-адресу та порт." @@ -3463,6 +3591,14 @@ msgstr "Помилка" msgid "Error · Agent encountered an error" msgstr "Помилка · Агент зіткнувся з помилкою" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Evaluate the result after every iteration." +msgstr "Оцінювати результат після кожної ітерації." + +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Every" +msgstr "Кожні" + #: src/renderer/views/SchedulesView/SchedulesView.tsx msgid "Every day at {time}" msgstr "Щодня о {time}" @@ -3485,6 +3621,14 @@ msgstr "Щогодини о {0} хв." msgid "Exclude patterns" msgstr "Шаблони виключення" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Execution" +msgstr "Виконання" + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Execution mode" +msgstr "Режим виконання" + #: src/renderer/components/thread/ChatPane/parts/items/toolDisplay.ts msgid "Exit plan mode" msgstr "Вийти з режиму плану" @@ -3534,6 +3678,10 @@ msgstr "Розгорніть, щоб переглянути або відкли msgid "Expand todo dock" msgstr "Розгорнути панель завдань" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Exponential backoff" +msgstr "Експоненційна затримка" + #: src/renderer/components/mcp/McpServersManager.tsx msgid "Export MCP servers" msgstr "Експортувати сервери MCP" @@ -3716,6 +3864,10 @@ msgstr "Пошук у diff" msgid "Find in terminal" msgstr "Пошук у терміналі" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Finding status" +msgstr "Стан результату" + #: src/renderer/views/PrReviewOverlay/parts/SubmitReviewPopover.tsx msgid "Finish your review" msgstr "Завершіть перевірку" @@ -3777,6 +3929,10 @@ msgstr "Виправити в агенті" msgid "Fixed" msgstr "Виправлено" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Fixed delay" +msgstr "Фіксована затримка" + #: src/renderer/commands/registry.ts msgid "Focus browser address bar" msgstr "Встановити фокус на адресний рядок браузера" @@ -4097,6 +4253,26 @@ msgstr "Є невідправлена чернетка" msgid "Headers" msgstr "Заголовки" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Heartbeat" +msgstr "Пульс" + +#: src/renderer/i18n/sharedMessages.ts +msgid "Heartbeat automations require a native chat conversation." +msgstr "Для автоматизації пульсу потрібна розмова у вбудованому чаті." + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Heartbeat continues this conversation in the selected project." +msgstr "Пульс продовжує цю розмову у вибраному проєкті." + +#: src/renderer/i18n/sharedMessages.ts +msgid "Heartbeat execution is unavailable." +msgstr "Виконання пульсу недоступне." + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Heartbeats can continue making changes while you're away. Set hard limits below." +msgstr "Пульс може продовжувати вносити зміни за вашої відсутності. Установіть нижче жорсткі обмеження." + #: src/renderer/views/SchedulesView/SchedulesView.tsx msgid "Help me create a schedule. Ask for any missing details, then use the Poracode schedule controls to create it for me." msgstr "Допоможи мені створити розклад. Запитай відсутні деталі, а потім створи його за допомогою елементів керування розкладами Poracode." @@ -4198,6 +4374,10 @@ msgstr "host.com, псевдонім або користувач@host.com" msgid "Hourly" msgstr "Щогодини" +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Hours" +msgstr "Години" + #: src/renderer/components/mcp/McpServerEditor.tsx msgid "HTTP (streamable)" msgstr "HTTP (потоковий)" @@ -4328,6 +4508,14 @@ msgstr "Сканування камерою в застосунку працює msgid "Inactive" msgstr "Неактивно" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Includes the first attempt." +msgstr "Ураховує першу спробу." + +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Info" +msgstr "Інформація" + #. Badge on an exclude pattern inherited from a lower scope #: src/renderer/views/SettingsOverlay/parts/SearchExcludeBody.tsx msgid "inherited" @@ -4338,6 +4526,14 @@ msgstr "успадковано" msgid "Inheriting the global setting (currently {0})." msgstr "Успадковується глобальне налаштування (зараз {0})." +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Initial retry delay" +msgstr "Початкова затримка повтору" + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Initial retry delay in seconds" +msgstr "Початкова затримка повтору в секундах" + #: src/renderer/views/GitReviewOverlay/parts/GitReviewSidebar/GitReviewSidebar.tsx msgid "Initialize Repository" msgstr "Ініціалізувати репозиторій" @@ -4476,6 +4672,18 @@ msgstr "Перервано" msgid "Interrupted: agent session ended before completion." msgstr "Перервано: сесія агента завершилася до завершення." +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Interval" +msgstr "Інтервал" + +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Interval amount" +msgstr "Значення інтервалу" + +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Interval unit" +msgstr "Одиниця інтервалу" + #: src/renderer/views/MainView/parts/RightPanel/parts/NotesPanel/NotesEditor.tsx msgid "Italic" msgstr "Курсив" @@ -4560,6 +4768,14 @@ msgstr "Запуск…" msgid "Leave a comment" msgstr "Залишити коментар" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Leave blank for no run limit." +msgstr "Залиште поле порожнім, щоб не обмежувати кількість запусків." + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +#~ msgid "Leave blank to rely on the time limit." +#~ msgstr "Залиште порожнім, щоб використовувати лише обмеження часу." + #: src/renderer/views/ProfileOverlay/parts/ActivityHeatmap.tsx msgid "Less" msgstr "Менше" @@ -4640,6 +4856,10 @@ msgstr "Завантаження редактора…" msgid "Loading file…" msgstr "Завантаження файлу…" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Loading findings" +msgstr "Завантаження результатів" + #: src/renderer/components/skills/SkillMarketplaceModal.tsx msgid "Loading marketplace…" msgstr "Завантаження маркетплейсу…" @@ -4864,6 +5084,14 @@ msgstr "Позначити як виконане" msgid "Mark as not done" msgstr "Позначити як невиконане" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Mark as read" +msgstr "Позначити як прочитане" + +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Mark as unread" +msgstr "Позначити як непрочитане" + #: src/renderer/components/thread/ThreadView.tsx msgid "Mark done" msgstr "Позначити виконаним" @@ -4904,6 +5132,22 @@ msgstr "Розгорнути" msgid "Maximize browser" msgstr "Розгорнути браузер" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Maximum attempts" +msgstr "Максимум спроб" + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Maximum iterations" +msgstr "Максимум ітерацій" + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Maximum retry delay" +msgstr "Максимальна затримка повтору" + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Maximum retry delay in seconds" +msgstr "Максимальна затримка повтору в секундах" + #: src/renderer/components/skills/SkillMarketplaceModal.tsx #~ msgid "MCP Market" #~ msgstr "MCP Market" @@ -5110,6 +5354,18 @@ msgstr "Згорнути в панель" msgid "Minute" msgstr "Хвилина" +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Minute, hour, day of month, month, and weekday." +msgstr "Хвилина, година, день місяця, місяць і день тижня." + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "minutes" +msgstr "хвилин" + +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Minutes" +msgstr "Хвилини" + #: src/mobile/views/BrowserView.tsx msgid "Mirrored desktop browser tab" msgstr "Дзеркальна вкладка браузера десктопа" @@ -5118,6 +5374,10 @@ msgstr "Дзеркальна вкладка браузера десктопа" msgid "Mirroring is unavailable." msgstr "Дзеркалювання недоступне." +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Missed runs" +msgstr "Пропущені запуски" + #: src/renderer/views/SettingsOverlay/parts/RemoteAccessSettings.tsx msgid "Mobile push notifications" msgstr "Мобільні push-сповіщення" @@ -5469,6 +5729,10 @@ msgstr "Наступний збіг" msgid "Next recently viewed chat" msgstr "Наступний нещодавно переглянутий чат" +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Next run" +msgstr "Наступний запуск" + #. placeholder {0}: dateTimeFormatter.format(new Date(task.nextRunAt)) #: src/renderer/views/SchedulesView/SchedulesView.tsx msgid "Next run {0}" @@ -5514,6 +5778,10 @@ msgstr "Немає встановлених агентів." msgid "No AI commits, PRs, or conflict resolutions tracked yet." msgstr "Ще не відстежено жодних комітів, PR чи розв'язань конфліктів від AI." +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "No archived findings." +msgstr "В архіві немає результатів." + #: src/renderer/views/SettingsOverlay/parts/ArchivedThreadsSettings.tsx msgid "No archived threads." msgstr "Немає архівованих тредів." @@ -5610,6 +5878,10 @@ msgstr "Немає доступного diff для {0}" msgid "No diff for {visiblePath}" msgstr "Немає diff для {visiblePath}" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "No eligible conversations in this project." +msgstr "У цьому проєкті немає придатних розмов." + #: src/renderer/components/skills/SkillImportModal.tsx msgid "No external skills were found in this scope." msgstr "У цій області не знайдено зовнішніх навичок." @@ -5625,6 +5897,10 @@ msgstr "Для цього повідомлення не збережено ко msgid "No files match \"{0}\"." msgstr "Немає файлів, що відповідають \"{0}\"." +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "No findings yet." +msgstr "Результатів ще немає." + #: src/renderer/views/MainView/parts/CreateProject/CloneProjectModal.tsx msgid "No GitHub CLI accounts found. Sign in with <0>gh auth login, or <1>paste a clone URL." msgstr "Облікові записи GitHub CLI не знайдено. Увійдіть за допомогою <0>gh auth login або <1>вставте URL для клонування." @@ -5637,6 +5913,10 @@ msgstr "Історії ще немає" msgid "No Lightcode data was found." msgstr "Дані Lightcode не знайдено." +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "No limit" +msgstr "Без обмежень" + #: src/renderer/components/skills/SkillMarketplaceModal.tsx msgid "No marketplace skills match these filters." msgstr "Немає навичок маркетплейсу, що відповідають цим фільтрам." @@ -5653,6 +5933,10 @@ msgstr "Збігів немає." msgid "No matching agents." msgstr "Відповідних агентів немає." +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "No matching findings." +msgstr "Немає відповідних результатів." + #: src/renderer/views/PullRequestsView/PullRequestsView.tsx msgid "No matching pull requests." msgstr "Немає відповідних pull request." @@ -5762,6 +6046,10 @@ msgstr "Репозиторії не знайдено." msgid "No results" msgstr "Немає результатів" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "No retries" +msgstr "Без повторних спроб" + #: src/renderer/views/SchedulesView/parts/PreviousRunsModal.tsx msgid "No runs yet." msgstr "Запусків ще немає." @@ -5798,6 +6086,10 @@ msgstr "Мовлення не виявлено." msgid "No staged changes" msgstr "Немає підготовлених змін" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "No summary was provided." +msgstr "Підсумок не надано." + #: src/renderer/views/RemoteProjectModal/RemoteProjectModal.tsx msgid "No supported agents are installed on this remote machine. Install and sign in to an agent remotely before starting a thread." msgstr "На цьому віддаленому комп’ютері не встановлено підтримуваних агентів. Установіть агент і ввійдіть у нього віддалено перед запуском потоку." @@ -5827,6 +6119,10 @@ msgstr "Потоків ще немає" msgid "No threads yet." msgstr "Гілок ще немає." +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "No upcoming run" +msgstr "Немає запланованих запусків" + #: src/renderer/components/providers/usageFormat.ts msgid "No windows reported" msgstr "Вікна не повідомлені" @@ -6042,6 +6338,11 @@ msgstr "Відкрити коміт на GitHub" msgid "Open conflict resolver in" msgstr "Відкрити засіб розв'язання конфліктів у" +#. placeholder {0}: props.scheduleName +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Open conversation for {0}" +msgstr "Відкрити розмову для {0}" + #: src/renderer/views/SettingsOverlay/parts/settingsOptions.ts msgid "Open dialog" msgstr "Відкрити діалог" @@ -6677,6 +6978,10 @@ msgstr "Папку проєкту оновлено. Повторно відкр msgid "Project name" msgstr "Назва проєкту" +#: src/renderer/i18n/sharedMessages.ts +msgid "Project no longer exists." +msgstr "Проєкт більше не існує." + #: src/renderer/views/MainView/parts/RightPanel/parts/NotesPanel/NotesEditor.tsx msgid "Project notes" msgstr "Нотатки проєкту" @@ -7275,6 +7580,10 @@ msgstr "Деталі запиту" msgid "requested changes" msgstr "запитані зміни" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Required confidence before stopping." +msgstr "Необхідна впевненість для зупинки." + #: src/mobile/views/pr/PrOverviewPage.tsx #: src/renderer/views/GitReviewOverlay/parts/GitReviewSidebar/parts/PrSection.tsx msgid "Required reviews, conversations, or status checks not met." @@ -7346,6 +7655,10 @@ msgstr "Відновити браузер" msgid "Restore default worktree base folder" msgstr "Відновити базову папку worktree за замовчуванням" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Restore finding" +msgstr "Відновити результат" + #: src/mobile/settingsSections.ts msgid "Restore or delete" msgstr "Восстановить или удалить" @@ -7376,10 +7689,26 @@ msgstr "Повторити перевірку {serverName}" msgid "Retry check" msgstr "Повторити перевірку" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Retry delay" +msgstr "Затримка повтору" + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Retry delay in seconds" +msgstr "Затримка повтору в секундах" + #: src/mobile/components.tsx msgid "Retry now" msgstr "Повторить сейчас" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Retry policy" +msgstr "Політика повторів" + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Retry when a run fails before it completes." +msgstr "Повторити, якщо запуск завершиться помилкою до закінчення." + #: src/renderer/hooks/usePrWriteActions.ts msgid "Retry with admin" msgstr "Повторити з правами адміністратора" @@ -7535,18 +7864,26 @@ msgstr "Виконувати локальне транскрибування н msgid "Run now" msgstr "Запустити зараз" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Run once after reopening" +msgstr "Виконати один раз після повторного відкриття" + #: src/renderer/views/SchedulesView/SchedulesView.tsx #~ msgid "Run standalone tasks on this device without a project." #~ msgstr "Запускайте автономні завдання на цьому пристрої без проєкту." #: src/renderer/views/SchedulesView/SchedulesView.tsx -msgid "Run standalone tasks on this device. Schedules run while the device is awake and Poracode is open." -msgstr "Запускайте автономні завдання на цьому пристрої. Розклади виконуються, доки пристрій активний і Poracode відкрито." +#~ msgid "Run standalone tasks on this device. Schedules run while the device is awake and Poracode is open." +#~ msgstr "Запускайте автономні завдання на цьому пристрої. Розклади виконуються, доки пристрій активний і Poracode відкрито." #: src/renderer/commands/registry.ts msgid "Run Terminal Command" msgstr "Виконати команду терміналу" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Run the latest missed run" +msgstr "Виконати останній пропущений запуск" + #: src/renderer/views/SchedulesView/ScheduleEditor.tsx #~ msgid "Run this schedule automatically at the times above." #~ msgstr "Автоматично запускати цей розклад у вказаний вище час." @@ -7562,6 +7899,7 @@ msgstr "виконується" #: src/renderer/utils/prStatus.ts #: src/renderer/views/SchedulesView/parts/PreviousRunsModal.tsx +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx msgid "Running" msgstr "Виконується" @@ -7585,6 +7923,10 @@ msgstr "Закінчиться раніше" msgid "Runs out in {runOut}" msgstr "Закінчиться через {runOut}" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Runs that need attention will appear here." +msgstr "Тут з’являться запуски, що потребують уваги." + #: src/renderer/views/MainView/parts/CreateProject/CloneProjectModal.tsx #: src/renderer/views/MainView/parts/CreateProject/CreateProjectModal.tsx msgid "Runtime" @@ -7661,6 +8003,10 @@ msgstr "Сканування Windows та WSL на наявність встан msgid "Scanning your system for installed CLIs. This usually takes a couple of seconds." msgstr "Сканування вашої системи на наявність встановлених CLI. Зазвичай це триває кілька секунд." +#: src/renderer/views/SchedulesView/SchedulesView.tsx +msgid "Schedule autonomous work and review results that need your attention. Automations run while this device is awake and Poracode is open." +msgstr "Плануйте автономну роботу та переглядайте результати, що потребують уваги. Автоматизації виконуються, поки пристрій активний і Poracode відкрито." + #: src/renderer/views/SchedulesView/ScheduleEditor.tsx msgid "Schedule name" msgstr "Назва розкладу" @@ -7669,20 +8015,31 @@ msgstr "Назва розкладу" msgid "Schedule status" msgstr "Стан розкладу" +#: src/renderer/i18n/sharedMessages.ts +msgid "Scheduled retry was cancelled." +msgstr "Заплановану повторну спробу скасовано." + +#: src/renderer/i18n/sharedMessages.ts +msgid "Scheduled task was deleted before retrying." +msgstr "Заплановане завдання було видалено до повторної спроби." + #: src/renderer/views/SchedulesView/SchedulesView.tsx -msgid "Scheduled tasks" -msgstr "Заплановані завдання" +#~ msgid "Scheduled tasks" +#~ msgstr "Заплановані завдання" #: src/mobile/settingsSections.ts -msgid "Scheduled tasks on this desktop" -msgstr "Заплановані завдання на цьому комп’ютері" +#~ msgid "Scheduled tasks on this desktop" +#~ msgstr "Заплановані завдання на цьому комп’ютері" #: src/renderer/views/SchedulesView/SchedulesView.tsx #~ msgid "Scheduled tasks run only while this device is awake and Poracode is open." #~ msgstr "Заплановані завдання виконуються лише коли пристрій активний і Poracode відкрито." #: src/mobile/settingsSections.ts -#: src/renderer/views/MainView/parts/Sidebar/Sidebar.tsx +msgid "Scheduled work and triage on this desktop" +msgstr "Запланована робота та опрацювання на цьому комп’ютері" + +#: src/renderer/views/SchedulesView/SchedulesView.tsx msgid "Schedules" msgstr "Розклади" @@ -7737,6 +8094,10 @@ msgstr "Пошук гілок..." msgid "Search files" msgstr "Пошук файлів" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Search findings" +msgstr "Пошук результатів" + #: src/renderer/components/skills/SkillMarketplaceModal.tsx msgid "Search marketplace skills" msgstr "Пошук навичок у маркетплейсі" @@ -7831,6 +8192,10 @@ msgstr "Пошук..." msgid "Searching…" msgstr "Пошук…" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "seconds" +msgstr "секунд" + #: src/renderer/components/skills/SkillMarketplaceModal.tsx #~ msgid "Security-focused directory with verified skill metadata." #~ msgstr "Каталог із фокусом на безпеці та перевіреними метаданими навичок." @@ -8221,6 +8586,10 @@ msgstr "Вихід із {env}. Виявлені агенти оновлятьс msgid "Signing out. Detected agents will refresh when it finishes." msgstr "Вихід. Виявлені агенти оновляться після завершення." +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Single pass" +msgstr "Один прохід" + #: src/renderer/components/skills/SkillImportModal.tsx #: src/renderer/components/skills/SkillMarketplaceModal.tsx msgid "Skill availability" @@ -8285,7 +8654,12 @@ msgstr "Маркетплейс навичок" msgid "Skills.sh" msgstr "Skills.sh" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Skip missed runs" +msgstr "Пропускати пропущені запуски" + #: src/renderer/utils/prStatus.ts +#: src/renderer/views/SchedulesView/parts/PreviousRunsModal.tsx msgid "Skipped" msgstr "Пропущено" @@ -8424,6 +8798,10 @@ msgstr "Запустіть {appName}, щоб побачити використа msgid "Start a dev server on your desktop, then tap refresh." msgstr "Запустіть сервер розробки на комп'ютері, потім торкніться «Оновити»." +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Start a new conversation for each run." +msgstr "Починати нову розмову для кожного запуску." + #: src/renderer/commands/registry.ts msgid "Start a new thread as panel instead of page" msgstr "Почати новий тред як панель, а не сторінку" @@ -8562,6 +8940,10 @@ msgstr "Зупинити" msgid "Stop forwarding" msgstr "Зупинити переспрямування" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Stop on error" +msgstr "Зупиняти в разі помилки" + #: src/renderer/components/thread/ThreadComposer.tsx msgid "Stop response" msgstr "Зупинити відповідь" @@ -8574,10 +8956,18 @@ msgstr "Зупинити завдання" msgid "Stop the project's running threads before changing its folder." msgstr "Зупиніть запущені треди проєкту перед зміною його папки." +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Stop the run when this total time is reached." +msgstr "Зупинити запуск, коли буде досягнуто цього загального часу." + #: src/renderer/components/composer/VoiceInputButton.tsx msgid "Stop voice input" msgstr "Зупинити голосове введення" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Stop when" +msgstr "Умова зупинки" + #: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts #: src/renderer/views/SettingsOverlay/parts/WorktreeSettings.tsx msgid "Storage location" @@ -8922,6 +9312,22 @@ msgstr "Агент" msgid "the app" msgstr "програму" +#: src/renderer/i18n/sharedMessages.ts +msgid "The automation conversation exited before the turn completed." +msgstr "Розмова автоматизації завершилася до закінчення ходу." + +#: src/renderer/i18n/sharedMessages.ts +msgid "The automation exceeded its time limit." +msgstr "Автоматизація перевищила обмеження часу." + +#: src/renderer/i18n/sharedMessages.ts +msgid "The automation needs a reply before it can continue." +msgstr "Для продовження автоматизації потрібна відповідь." + +#: src/renderer/i18n/sharedMessages.ts +msgid "The automation needs approval before it can continue." +msgstr "Для продовження автоматизації потрібне схвалення." + #: src/renderer/views/MainView/parts/CreateProject/CloneProjectModal.tsx msgid "the chosen folder" msgstr "обрана папка" @@ -8935,11 +9341,39 @@ msgstr "Періодичність фонового оновлення за за msgid "The desktop server is still coming online." msgstr "Сервер робочого стола ще запускається." +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "The finding is no longer available." +msgstr "Результат більше недоступний." + #. placeholder {0}: createTarget.wslDistro #: src/renderer/components/skills/SkillsManager.tsx msgid "the global {0} WSL scope" msgstr "глобальну область WSL {0}" +#: src/renderer/i18n/sharedMessages.ts +msgid "The heartbeat conversation belongs to a different project." +msgstr "Розмова пульсу належить до іншого проєкту." + +#: src/renderer/i18n/sharedMessages.ts +msgid "The heartbeat conversation cannot be resumed." +msgstr "Розмову пульсу неможливо відновити." + +#: src/renderer/i18n/sharedMessages.ts +msgid "The heartbeat conversation is archived." +msgstr "Діалог пульсу заархівовано." + +#: src/renderer/i18n/sharedMessages.ts +msgid "The heartbeat conversation is currently busy." +msgstr "Розмова пульсу зараз зайнята." + +#: src/renderer/i18n/sharedMessages.ts +msgid "The heartbeat conversation no longer exists." +msgstr "Розмова пульсу більше не існує." + +#: src/renderer/i18n/sharedMessages.ts +msgid "The heartbeat conversation uses a different agent." +msgstr "Розмова пульсу використовує іншого агента." + #: src/renderer/components/skills/SkillsManager.tsx msgid "the Linux user" msgstr "користувача Linux" @@ -8972,6 +9406,14 @@ msgstr "Віддалений сервер не повернув облікові msgid "The repository location on disk. Update it if you moved the folder." msgstr "Розташування репозиторію на диску. Оновіть його, якщо ви перемістили папку." +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "The run could not be cancelled." +msgstr "Не вдалося скасувати запуск." + +#: src/renderer/i18n/sharedMessages.ts +msgid "The scheduled automation failed." +msgstr "Запланована автоматизація завершилася помилкою." + #: src/renderer/components/mcp/McpServersManager.tsx #~ msgid "The selected file does not contain valid MCP server configurations." #~ msgstr "Вибраний файл не містить допустимих конфігурацій серверів MCP." @@ -9227,6 +9669,18 @@ msgstr "Треди, позначені як завершені, до яких н msgid "Time" msgstr "Час" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Time limit" +msgstr "Обмеження часу" + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Time limit in minutes" +msgstr "Обмеження часу у хвилинах" + +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Time zone" +msgstr "Часовий пояс" + #: src/renderer/components/mcp/McpServerEditor.tsx msgid "Timeout (ms)" msgstr "Тайм-аут (мс)" @@ -9356,6 +9810,10 @@ msgstr "Напівпрозора бічна панель" msgid "Trending now" msgstr "Зараз у тренді" +#: src/renderer/views/SchedulesView/SchedulesView.tsx +msgid "Triage" +msgstr "Опрацювання" + #: src/mobile/views/DesktopsView.tsx msgid "Trust and connect" msgstr "Довіряти та підключитися" @@ -9598,6 +10056,10 @@ msgstr "Не призначено" msgid "Unavailable" msgstr "Недоступно" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Unavailable conversation" +msgstr "Недоступна розмова" + #: src/renderer/views/SchedulesView/ScheduleEditor.tsx msgid "Unavailable project" msgstr "Недоступний проєкт" @@ -9676,6 +10138,10 @@ msgstr "Без фази:" msgid "Unpin" msgstr "Відкріпити" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Unread" +msgstr "Непрочитане" + #: src/mobile/views/GitActionSheet.tsx #: src/renderer/views/GitReviewOverlay/parts/GitReviewSidebar/parts/FileRow.tsx #: src/renderer/views/GitReviewOverlay/parts/GitStackedDiff.tsx @@ -10002,6 +10468,12 @@ msgstr "Очікування автентифікації {methodName}. Вияв msgid "waiting for agent to stop" msgstr "очікування зупинки агента" +#: src/renderer/views/SchedulesView/parts/PreviousRunsModal.tsx +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +#: src/renderer/views/SchedulesView/SchedulesView.tsx +msgid "Waiting for approval" +msgstr "Очікує на схвалення" + #: src/renderer/components/thread/ChatPane/parts/items/WorkflowOverlayBody.tsx msgid "Waiting for workflow to spawn agents…" msgstr "Очікування створення агентів робочим процесом…" @@ -10034,6 +10506,10 @@ msgstr "Підготовка середовищ оболонки..." msgid "Warming up WSL shell environment…" msgstr "Підготовка середовища оболонки WSL…" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Warning" +msgstr "Попередження" + #: src/renderer/components/thread/ChatPane/parts/items/ToolCallGroup.tsx #: src/renderer/components/thread/ChatPane/parts/items/toolDisplay.ts #: src/renderer/components/thread/ChatPane/parts/items/WebSearchItem.tsx @@ -10326,6 +10802,10 @@ msgstr "Базова папка WSL" #~ msgid "WSL user" #~ msgstr "Користувач WSL" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "You’re all caught up." +msgstr "Усе переглянуто." + #: src/renderer/views/ProfileOverlay/parts/EditProfileDialog.tsx msgid "Your name" msgstr "Ваше ім'я" diff --git a/src/renderer/locales/vi/messages.po b/src/renderer/locales/vi/messages.po index 8f8afbaee..92db4d28b 100644 --- a/src/renderer/locales/vi/messages.po +++ b/src/renderer/locales/vi/messages.po @@ -288,6 +288,11 @@ msgstr "{agentLabel}: {statusLabel}. Di chuột để biết chi tiết trạng msgid "{agentLead} needs your input to continue." msgstr "{agentLead} cần bạn nhập thông tin để tiếp tục." +#. placeholder {0}: task.recurrence.timeZone +#: src/renderer/views/SchedulesView/SchedulesView.tsx +msgid "{cadence} in {0}" +msgstr "{cadence} theo múi giờ {0}" + #: src/mobile/views/pr/PrOverviewPage.tsx msgid "{commitsCount, plural, one {# commit} other {# commits}}" msgstr "{commitsCount, plural, one {# commit} other {# commit}}" @@ -315,6 +320,18 @@ msgstr "{days} ngày trước" msgid "{envOrAgentLabel} needs authentication." msgstr "{envOrAgentLabel} cần xác thực." +#: src/renderer/views/SchedulesView/SchedulesView.tsx +msgid "{every, plural, one {Every day} other {Every # days}}" +msgstr "{every, plural, one {Hằng ngày} other {Mỗi # ngày}}" + +#: src/renderer/views/SchedulesView/SchedulesView.tsx +msgid "{every, plural, one {Every hour} other {Every # hours}}" +msgstr "{every, plural, one {Mỗi giờ} other {Mỗi # giờ}}" + +#: src/renderer/views/SchedulesView/SchedulesView.tsx +msgid "{every, plural, one {Every minute} other {Every # minutes}}" +msgstr "{every, plural, one {Mỗi phút} other {Mỗi # phút}}" + #: src/mobile/views/pr/PrOverviewPage.tsx msgid "{filesCount, plural, one {# file changed} other {# files changed}}" msgstr "{filesCount, plural, one {# tệp đã đổi} other {# tệp đã đổi}}" @@ -491,6 +508,10 @@ msgstr "~{money}{tokens} · {0} · ước tính." msgid "≈{0}% by reset" msgstr "≈{0}% khi đặt lại" +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "0 9 * * 1-5" +msgstr "0 9 * * 1-5" + #: src/mobile/views/ThreadsView.tsx msgid "1 thread" msgstr "1 luồng" @@ -840,6 +861,10 @@ msgstr "Thao tác git bằng AI" msgid "AI providers" msgstr "Nhà cung cấp AI" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "AI stop condition" +msgstr "Điều kiện dừng của AI" + #: src/mobile/views/MoreView.tsx #~ msgid "AI, agents, and archived threads on the paired desktop" #~ msgstr "AI, tác nhân và các luồng đã lưu trữ trên máy tính đã ghép nối" @@ -851,6 +876,7 @@ msgstr "Cảnh báo khi luồng cần bạn" #: src/renderer/commands/shortcutCatalog.ts #: src/renderer/components/skills/SkillsManager.tsx #: src/renderer/views/PullRequestsView/PullRequestsView.tsx +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx #: src/renderer/views/SchedulesView/SchedulesView.tsx #: src/renderer/views/SettingsOverlay/parts/ProfileSettings.tsx msgid "All" @@ -943,6 +969,10 @@ msgstr "Luôn bị loại trừ" msgid "An MCP server with this name already exists." msgstr "Máy chủ MCP có tên này đã tồn tại." +#: src/renderer/i18n/sharedMessages.ts +msgid "Another automation is already using this conversation." +msgstr "Một quy trình tự động khác đang sử dụng cuộc trò chuyện này." + #: src/renderer/components/thread/ChatPane/parts/CheckpointRevertControls.tsx msgid "Another chat uses this same tree. File restore could overwrite that chat's changes." msgstr "Một cuộc trò chuyện khác cũng sử dụng cây này. Khôi phục tệp có thể ghi đè lên các thay đổi của cuộc trò chuyện đó." @@ -1014,6 +1044,10 @@ msgstr "Lưu trữ tất cả" msgid "Archive all threads" msgstr "Lưu trữ tất cả luồng" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Archive finding" +msgstr "Lưu trữ kết quả" + #: src/renderer/commands/registry.ts msgid "Archive the current thread" msgstr "Lưu trữ luồng hiện tại" @@ -1028,6 +1062,10 @@ msgstr "Lưu trữ luồng" msgid "Archive Thread" msgstr "Lưu trữ luồng" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Archived" +msgstr "Đã lưu trữ" + #: src/mobile/settingsSections.ts #: src/mobile/views/SettingsView.tsx #: src/renderer/views/SettingsOverlay/parts/ArchivedThreadsSettings.tsx @@ -1173,6 +1211,16 @@ msgstr "Tự động hiển thị bảng điều khiển thiết bị đầu cu msgid "Automatically show the terminal panel when running commands or creating worktrees." msgstr "Tự động hiển thị bảng terminal khi chạy lệnh hoặc tạo cây làm việc." +#: src/renderer/views/SchedulesView/SchedulesView.tsx +msgid "Automation sections" +msgstr "Các mục tự động hóa" + +#: src/mobile/settingsSections.ts +#: src/renderer/views/MainView/parts/Sidebar/Sidebar.tsx +#: src/renderer/views/SchedulesView/SchedulesView.tsx +msgid "Automations" +msgstr "Tự động hóa" + #: src/renderer/components/skills/SkillImportModal.tsx msgid "Availability" msgstr "Phạm vi khả dụng" @@ -1459,6 +1507,10 @@ msgstr "Bỏ qua các quy tắc bảo vệ nhánh (hợp nhất với quyền qu msgid "Cached only" msgstr "Chỉ có trong bộ nhớ đệm" +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Calculated on desktop after saving" +msgstr "Được tính trên desktop sau khi lưu" + #: src/mobile/QrScanner.tsx msgid "Camera access blocked" msgstr "Quyền truy cập camera bị chặn" @@ -1513,11 +1565,16 @@ msgstr "Hủy bộ chọn" msgid "Cancel removing project" msgstr "Hủy xóa dự án" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Cancel run" +msgstr "Hủy lượt chạy" + #: src/renderer/components/thread/ChatPane/parts/items/WorkflowOverlayBody.tsx msgid "cancelled" msgstr "đã hủy" #: src/renderer/utils/prStatus.ts +#: src/renderer/views/SchedulesView/parts/PreviousRunsModal.tsx msgid "Cancelled" msgstr "Đã hủy" @@ -1706,6 +1763,10 @@ msgstr "Chọn ngôn ngữ hiển thị cho giao diện của Poracode." msgid "Choose thread to attach to" msgstr "Chọn chủ đề để đính kèm" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Choose what happens after a scheduled time was missed." +msgstr "Chọn hành động khi bỏ lỡ thời điểm đã lên lịch." + #: src/renderer/views/SettingsOverlay/parts/BrowserSettings.tsx #: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts msgid "Choose whether links from Poracode and browser popups stay in Poracode or open externally." @@ -2185,6 +2246,14 @@ msgstr "hoàn thành" msgid "Completed" msgstr "Đã hoàn tất" +#: src/renderer/i18n/sharedMessages.ts +msgid "Completion evaluation failed: {detail}" +msgstr "Đánh giá hoàn thành thất bại: {detail}" + +#: src/renderer/i18n/sharedMessages.ts +msgid "Completion evaluation is unavailable." +msgstr "Không thể đánh giá hoàn thành." + #: src/renderer/commands/shortcutCatalog.ts #: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx #: src/renderer/views/SettingsOverlay/parts/settingsOptions.ts @@ -2223,6 +2292,14 @@ msgstr "Computer Use đã bật — thao tác tương tác chiếm quyền đi #~ msgid "Computer Use enabled for this thread" #~ msgstr "Đã bật sử dụng máy tính cho chủ đề này" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Confidence" +msgstr "Độ tin cậy" + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Confidence percent" +msgstr "Phần trăm độ tin cậy" + #: src/renderer/views/SettingsOverlay/parts/ClaudeProfileSettings.tsx msgid "Config directory" msgstr "Thư mục cấu hình" @@ -2386,6 +2463,14 @@ msgstr "Tiếp tục ở nhà cung cấp khác" msgid "Continue in..." msgstr "Tiếp tục trong..." +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Continue one conversation until a stop condition or limit is reached." +msgstr "Tiếp tục một cuộc trò chuyện cho đến khi đạt điều kiện dừng hoặc giới hạn." + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Control how each scheduled run continues and stops." +msgstr "Kiểm soát cách mỗi lượt chạy đã lên lịch tiếp tục và dừng lại." + #: src/renderer/views/SettingsOverlay/parts/SearchSettings.tsx msgid "Control which files appear in the @file mention search. Per-project overrides live in each project's settings." msgstr "Kiểm soát những tập tin nào xuất hiện trong tìm kiếm đề cập đến @file. Ghi đè cho mỗi dự án trực tiếp trong cài đặt của từng dự án." @@ -2397,6 +2482,7 @@ msgstr "Điều khiển máy tính đã ghép nối khi agent nhấp hoặc gõ" #: src/mobile/views/pr/PrConversationPage.tsx #: src/mobile/views/pr/PrOverviewPage.tsx #: src/renderer/views/PrReviewOverlay/parts/PrTabsPill.tsx +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx msgid "Conversation" msgstr "Cuộc trò chuyện" @@ -2697,6 +2783,24 @@ msgstr "Thông tin xác thực được cấu hình." msgid "Credits" msgstr "Số dư tín dụng" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Critical" +msgstr "Nghiêm trọng" + +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Cron" +msgstr "Cron" + +#. placeholder {0}: task.recurrence.expression +#. placeholder {1}: task.recurrence.timeZone +#: src/renderer/views/SchedulesView/SchedulesView.tsx +msgid "Cron {0} in {1}" +msgstr "Cron {0} theo múi giờ {1}" + +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Cron expression" +msgstr "Biểu thức Cron" + #: src/renderer/components/skills/SkillMarketplaceModal.tsx #~ msgid "Curated free and premium skills managed by MCP Market." #~ msgstr "Các skill miễn phí và cao cấp được tuyển chọn, do MCP Market quản lý." @@ -2762,9 +2866,9 @@ msgstr "Bản tóm tắt hằng ngày" msgid "Dark" msgstr "Tối" -#: src/renderer/views/SchedulesView/SchedulesView.tsx -#~ msgid "Days" -#~ msgstr "Ngày" +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Days" +msgstr "Ngày" #: src/renderer/components/thread/ThreadRuntimeRequestPanel/structuredElicitation.tsx msgid "Decline" @@ -2911,6 +3015,10 @@ msgstr "Xóa worktree {0}" #~ msgid "Delete:" #~ msgstr "Xóa:" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Deleted schedule" +msgstr "Lịch đã xóa" + #: src/renderer/views/SettingsOverlay/parts/AcpRegistrySettings.tsx msgid "Deleting" msgstr "Đang xóa" @@ -2923,6 +3031,10 @@ msgstr "Từ chối" msgid "Deny and tell the agent what to do differently…" msgstr "Từ chối và cho tác nhân biết cần làm gì khác đi…" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Describe the result that completes this heartbeat." +msgstr "Mô tả kết quả sẽ hoàn thành nhịp kiểm tra này." + #: src/renderer/views/SchedulesView/ScheduleEditor.tsx msgid "Describe what the agent should do" msgstr "Mô tả việc tác nhân cần làm" @@ -2944,6 +3056,10 @@ msgstr "Điểm cuối máy tính" msgid "Desktop is unreachable." msgstr "Không thể kết nối tới desktop." +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Desktop local time" +msgstr "Giờ địa phương của desktop" + #: src/mobile/chrome.ts #: src/mobile/views/MoreView.tsx msgid "Desktop Settings" @@ -3056,6 +3172,10 @@ msgstr "Vô hiệu hóa dự án" msgid "Disable Subagents" msgstr "Tắt tác nhân phụ" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Disable the automation after retries are exhausted." +msgstr "Tắt tác vụ tự động sau khi đã dùng hết các lần thử lại." + #: src/renderer/views/SettingsOverlay/parts/ClaudeProfileSettings.tsx msgid "Disable tiers an external provider collapses (e.g. keep only High and Max)." msgstr "Tắt các mức mà nhà cung cấp bên ngoài gộp lại (ví dụ chỉ giữ High và Max)." @@ -3356,6 +3476,10 @@ msgstr "Các máy chủ đã bật vẫn hoạt động cho các luồng mới" msgid "Enables <0>cookies and <1>storage. Cookies can contain session tokens and storage often holds auth state — only enable when you trust both the agent and the sites it visits." msgstr "Bật <0>cookie và <1>bộ nhớ. Cookie có thể chứa mã thông báo phiên và bộ lưu trữ thường giữ trạng thái xác thực — chỉ bật khi bạn tin cậy cả tác nhân và các trang web mà nó truy cập." +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +#~ msgid "End the heartbeat after retries are exhausted." +#~ msgstr "Kết thúc nhịp kiểm tra sau khi hết số lần thử lại." + #: src/mobile/views/DesktopsView.tsx #: src/renderer/views/SettingsOverlay/parts/RemoteServersSettings.tsx msgid "Endpoint" @@ -3393,6 +3517,10 @@ msgstr "Nhập endpoint desktop hợp lệ." msgid "Enter a valid HTTP or HTTPS URL." msgstr "Nhập URL HTTP hoặc HTTPS hợp lệ." +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Enter a valid schedule" +msgstr "Nhập lịch hợp lệ" + #: src/mobile/views/DesktopsView.tsx msgid "Enter a valid SSH target and port." msgstr "Nhập đích SSH và cổng hợp lệ." @@ -3463,6 +3591,14 @@ msgstr "Lỗi" msgid "Error · Agent encountered an error" msgstr "Lỗi · Tác nhân gặp lỗi" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Evaluate the result after every iteration." +msgstr "Đánh giá kết quả sau mỗi lần lặp." + +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Every" +msgstr "Mỗi" + #: src/renderer/views/SchedulesView/SchedulesView.tsx msgid "Every day at {time}" msgstr "Hằng ngày lúc {time}" @@ -3485,6 +3621,14 @@ msgstr "Mỗi giờ vào phút thứ {0}" msgid "Exclude patterns" msgstr "Loại trừ mẫu" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Execution" +msgstr "Thực thi" + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Execution mode" +msgstr "Chế độ thực thi" + #: src/renderer/components/thread/ChatPane/parts/items/toolDisplay.ts msgid "Exit plan mode" msgstr "Thoát khỏi chế độ kế hoạch" @@ -3534,6 +3678,10 @@ msgstr "Mở rộng để xem xét hoặc thu hồi quyền truy cập." msgid "Expand todo dock" msgstr "Mở rộng dock việc cần làm" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Exponential backoff" +msgstr "Thời gian chờ lũy thừa" + #: src/renderer/components/mcp/McpServersManager.tsx msgid "Export MCP servers" msgstr "Xuất máy chủ MCP" @@ -3716,6 +3864,10 @@ msgstr "Tìm trong diff" msgid "Find in terminal" msgstr "Tìm trong terminal" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Finding status" +msgstr "Trạng thái kết quả" + #: src/renderer/views/PrReviewOverlay/parts/SubmitReviewPopover.tsx msgid "Finish your review" msgstr "Kết thúc bài đánh giá của bạn" @@ -3777,6 +3929,10 @@ msgstr "Sửa trong Tác nhân" msgid "Fixed" msgstr "Đã sửa" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Fixed delay" +msgstr "Độ trễ cố định" + #: src/renderer/commands/registry.ts msgid "Focus browser address bar" msgstr "Tập trung vào thanh địa chỉ trình duyệt" @@ -4097,6 +4253,26 @@ msgstr "Có bản nháp chưa gửi" msgid "Headers" msgstr "Header" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Heartbeat" +msgstr "Nhịp kiểm tra" + +#: src/renderer/i18n/sharedMessages.ts +msgid "Heartbeat automations require a native chat conversation." +msgstr "Tự động hóa nhịp kiểm tra yêu cầu một cuộc trò chuyện trong giao diện chat gốc." + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Heartbeat continues this conversation in the selected project." +msgstr "Nhịp kiểm tra tiếp tục cuộc trò chuyện này trong dự án đã chọn." + +#: src/renderer/i18n/sharedMessages.ts +msgid "Heartbeat execution is unavailable." +msgstr "Không thể thực thi nhịp kiểm tra." + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Heartbeats can continue making changes while you're away. Set hard limits below." +msgstr "Nhịp kiểm tra có thể tiếp tục thay đổi khi bạn vắng mặt. Hãy đặt giới hạn cứng bên dưới." + #: src/renderer/views/SchedulesView/SchedulesView.tsx msgid "Help me create a schedule. Ask for any missing details, then use the Poracode schedule controls to create it for me." msgstr "Hãy giúp tôi tạo lịch. Hỏi những chi tiết còn thiếu, sau đó dùng các điều khiển lịch của Poracode để tạo giúp tôi." @@ -4198,6 +4374,10 @@ msgstr "host.com, bí danh hoặc người_dùng@host.com" msgid "Hourly" msgstr "Hằng giờ" +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Hours" +msgstr "Giờ" + #: src/renderer/components/mcp/McpServerEditor.tsx msgid "HTTP (streamable)" msgstr "HTTP (hỗ trợ truyền phát)" @@ -4328,6 +4508,14 @@ msgstr "Quét bằng camera trong ứng dụng chỉ hoạt động qua HTTPS. D msgid "Inactive" msgstr "Không hoạt động" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Includes the first attempt." +msgstr "Bao gồm lần thử đầu tiên." + +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Info" +msgstr "Thông tin" + #. Badge on an exclude pattern inherited from a lower scope #: src/renderer/views/SettingsOverlay/parts/SearchExcludeBody.tsx msgid "inherited" @@ -4338,6 +4526,14 @@ msgstr "kế thừa" msgid "Inheriting the global setting (currently {0})." msgstr "Kế thừa cài đặt chung (hiện tại {0})." +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Initial retry delay" +msgstr "Độ trễ thử lại ban đầu" + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Initial retry delay in seconds" +msgstr "Độ trễ thử lại ban đầu tính bằng giây" + #: src/renderer/views/GitReviewOverlay/parts/GitReviewSidebar/GitReviewSidebar.tsx msgid "Initialize Repository" msgstr "Khởi tạo kho lưu trữ" @@ -4476,6 +4672,18 @@ msgstr "Bị gián đoạn" msgid "Interrupted: agent session ended before completion." msgstr "Bị gián đoạn: phiên tác nhân đã kết thúc trước khi hoàn thành." +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Interval" +msgstr "Khoảng thời gian" + +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Interval amount" +msgstr "Giá trị khoảng thời gian" + +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Interval unit" +msgstr "Đơn vị khoảng thời gian" + #: src/renderer/views/MainView/parts/RightPanel/parts/NotesPanel/NotesEditor.tsx msgid "Italic" msgstr "Nghiêng" @@ -4560,6 +4768,14 @@ msgstr "Đang khởi chạy…" msgid "Leave a comment" msgstr "Để lại bình luận" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Leave blank for no run limit." +msgstr "Để trống nếu không muốn giới hạn số lần chạy." + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +#~ msgid "Leave blank to rely on the time limit." +#~ msgstr "Để trống để chỉ dựa vào giới hạn thời gian." + #: src/renderer/views/ProfileOverlay/parts/ActivityHeatmap.tsx msgid "Less" msgstr "Ít" @@ -4640,6 +4856,10 @@ msgstr "Đang tải trình chỉnh sửa…" msgid "Loading file…" msgstr "Đang tải tập tin…" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Loading findings" +msgstr "Đang tải kết quả" + #: src/renderer/components/skills/SkillMarketplaceModal.tsx msgid "Loading marketplace…" msgstr "Đang tải marketplace…" @@ -4864,6 +5084,14 @@ msgstr "Đánh dấu là xong" msgid "Mark as not done" msgstr "Đánh dấu là chưa xong" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Mark as read" +msgstr "Đánh dấu đã đọc" + +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Mark as unread" +msgstr "Đánh dấu chưa đọc" + #: src/renderer/components/thread/ThreadView.tsx msgid "Mark done" msgstr "Đánh dấu là xong" @@ -4904,6 +5132,22 @@ msgstr "Tối đa hóa" msgid "Maximize browser" msgstr "Tối đa hóa trình duyệt" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Maximum attempts" +msgstr "Số lần thử tối đa" + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Maximum iterations" +msgstr "Số lần lặp tối đa" + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Maximum retry delay" +msgstr "Độ trễ thử lại tối đa" + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Maximum retry delay in seconds" +msgstr "Độ trễ thử lại tối đa tính bằng giây" + #: src/renderer/components/skills/SkillMarketplaceModal.tsx #~ msgid "MCP Market" #~ msgstr "MCP Market" @@ -5110,6 +5354,18 @@ msgstr "Thu nhỏ vào bảng điều khiển" msgid "Minute" msgstr "Phút" +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Minute, hour, day of month, month, and weekday." +msgstr "Phút, giờ, ngày trong tháng, tháng và ngày trong tuần." + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "minutes" +msgstr "phút" + +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Minutes" +msgstr "Phút" + #: src/mobile/views/BrowserView.tsx msgid "Mirrored desktop browser tab" msgstr "Thẻ trình duyệt desktop được phản chiếu" @@ -5118,6 +5374,10 @@ msgstr "Thẻ trình duyệt desktop được phản chiếu" msgid "Mirroring is unavailable." msgstr "Không thể phản chiếu." +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Missed runs" +msgstr "Lượt chạy bị bỏ lỡ" + #: src/renderer/views/SettingsOverlay/parts/RemoteAccessSettings.tsx msgid "Mobile push notifications" msgstr "Thông báo đẩy trên di động" @@ -5469,6 +5729,10 @@ msgstr "Kết quả tiếp theo" msgid "Next recently viewed chat" msgstr "Cuộc trò chuyện đã xem gần đây tiếp theo" +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Next run" +msgstr "Lần chạy tiếp theo" + #. placeholder {0}: dateTimeFormatter.format(new Date(task.nextRunAt)) #: src/renderer/views/SchedulesView/SchedulesView.tsx msgid "Next run {0}" @@ -5514,6 +5778,10 @@ msgstr "Không có tác nhân nào được cài đặt." msgid "No AI commits, PRs, or conflict resolutions tracked yet." msgstr "Chưa ghi nhận commit, PR hay giải quyết xung đột nào bằng AI." +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "No archived findings." +msgstr "Không có kết quả đã lưu trữ." + #: src/renderer/views/SettingsOverlay/parts/ArchivedThreadsSettings.tsx msgid "No archived threads." msgstr "Không có luồng nào đã lưu trữ." @@ -5610,6 +5878,10 @@ msgstr "Không có sự khác biệt nào cho {0}" msgid "No diff for {visiblePath}" msgstr "Không có sự khác biệt đối với {visiblePath}" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "No eligible conversations in this project." +msgstr "Không có cuộc trò chuyện phù hợp trong dự án này." + #: src/renderer/components/skills/SkillImportModal.tsx msgid "No external skills were found in this scope." msgstr "Không tìm thấy skill bên ngoài trong phạm vi này." @@ -5625,6 +5897,10 @@ msgstr "Không có điểm kiểm tra tập tin nào được lưu trữ cho tin msgid "No files match \"{0}\"." msgstr "Không có tệp nào khớp với \"{0}\"." +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "No findings yet." +msgstr "Chưa có kết quả." + #: src/renderer/views/MainView/parts/CreateProject/CloneProjectModal.tsx msgid "No GitHub CLI accounts found. Sign in with <0>gh auth login, or <1>paste a clone URL." msgstr "Không tìm thấy tài khoản GitHub CLI nào. Đăng nhập bằng <0>gh auth login hoặc <1>dán URL sao chép." @@ -5637,6 +5913,10 @@ msgstr "Chưa có lịch sử" msgid "No Lightcode data was found." msgstr "Không tìm thấy dữ liệu Lightcode." +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "No limit" +msgstr "Không giới hạn" + #: src/renderer/components/skills/SkillMarketplaceModal.tsx msgid "No marketplace skills match these filters." msgstr "Không có skill nào trên marketplace khớp với các bộ lọc này." @@ -5653,6 +5933,10 @@ msgstr "Không tìm thấy kết quả phù hợp." msgid "No matching agents." msgstr "Không có tác nhân nào phù hợp." +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "No matching findings." +msgstr "Không có kết quả phù hợp." + #: src/renderer/views/PullRequestsView/PullRequestsView.tsx msgid "No matching pull requests." msgstr "Không có pull request nào phù hợp." @@ -5762,6 +6046,10 @@ msgstr "Không tìm thấy kho lưu trữ nào." msgid "No results" msgstr "Không có kết quả" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "No retries" +msgstr "Không thử lại" + #: src/renderer/views/SchedulesView/parts/PreviousRunsModal.tsx msgid "No runs yet." msgstr "Chưa có lần chạy nào." @@ -5798,6 +6086,10 @@ msgstr "Không phát hiện thấy giọng nói nào." msgid "No staged changes" msgstr "Không có thay đổi nào được đưa vào staging" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "No summary was provided." +msgstr "Không có bản tóm tắt." + #: src/renderer/views/RemoteProjectModal/RemoteProjectModal.tsx msgid "No supported agents are installed on this remote machine. Install and sign in to an agent remotely before starting a thread." msgstr "Không có tác tử được hỗ trợ nào được cài đặt trên máy từ xa này. Hãy cài đặt và đăng nhập vào tác tử từ xa trước khi bắt đầu một luồng." @@ -5827,6 +6119,10 @@ msgstr "Chưa có luồng nào" msgid "No threads yet." msgstr "Chưa có luồng nào." +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "No upcoming run" +msgstr "Không có lần chạy sắp tới" + #: src/renderer/components/providers/usageFormat.ts msgid "No windows reported" msgstr "Không có cửa sổ nào được báo cáo" @@ -6042,6 +6338,11 @@ msgstr "Mở commit trên GitHub" msgid "Open conflict resolver in" msgstr "Mở trình giải quyết xung đột trong" +#. placeholder {0}: props.scheduleName +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Open conversation for {0}" +msgstr "Mở cuộc trò chuyện cho {0}" + #: src/renderer/views/SettingsOverlay/parts/settingsOptions.ts msgid "Open dialog" msgstr "Mở hộp thoại" @@ -6677,6 +6978,10 @@ msgstr "Đã cập nhật thư mục dự án. Hãy mở lại bất kỳ termin msgid "Project name" msgstr "Tên dự án" +#: src/renderer/i18n/sharedMessages.ts +msgid "Project no longer exists." +msgstr "Dự án không còn tồn tại." + #: src/renderer/views/MainView/parts/RightPanel/parts/NotesPanel/NotesEditor.tsx msgid "Project notes" msgstr "ghi chú dự án" @@ -7275,6 +7580,10 @@ msgstr "Yêu cầu chi tiết" msgid "requested changes" msgstr "yêu cầu thay đổi" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Required confidence before stopping." +msgstr "Độ tin cậy cần thiết trước khi dừng." + #: src/mobile/views/pr/PrOverviewPage.tsx #: src/renderer/views/GitReviewOverlay/parts/GitReviewSidebar/parts/PrSection.tsx msgid "Required reviews, conversations, or status checks not met." @@ -7346,6 +7655,10 @@ msgstr "Khôi phục trình duyệt" msgid "Restore default worktree base folder" msgstr "Khôi phục thư mục gốc mặc định của cây làm việc" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Restore finding" +msgstr "Khôi phục kết quả" + #: src/mobile/settingsSections.ts msgid "Restore or delete" msgstr "Khôi phục hoặc xóa" @@ -7376,10 +7689,26 @@ msgstr "Thử lại {serverName}" msgid "Retry check" msgstr "Thử kiểm tra lại" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Retry delay" +msgstr "Độ trễ thử lại" + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Retry delay in seconds" +msgstr "Độ trễ thử lại tính bằng giây" + #: src/mobile/components.tsx msgid "Retry now" msgstr "Thử lại ngay" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Retry policy" +msgstr "Chính sách thử lại" + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Retry when a run fails before it completes." +msgstr "Thử lại khi một lượt chạy thất bại trước khi hoàn thành." + #: src/renderer/hooks/usePrWriteActions.ts msgid "Retry with admin" msgstr "Thử lại với quản trị viên" @@ -7535,18 +7864,26 @@ msgstr "Chạy phiên âm cục bộ trên GPU khi có sẵn." msgid "Run now" msgstr "Chạy ngay" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Run once after reopening" +msgstr "Chạy một lần sau khi mở lại" + #: src/renderer/views/SchedulesView/SchedulesView.tsx #~ msgid "Run standalone tasks on this device without a project." #~ msgstr "Chạy các tác vụ độc lập trên thiết bị này mà không cần dự án." #: src/renderer/views/SchedulesView/SchedulesView.tsx -msgid "Run standalone tasks on this device. Schedules run while the device is awake and Poracode is open." -msgstr "Chạy các tác vụ độc lập trên thiết bị này. Lịch chạy khi thiết bị đang hoạt động và Poracode đang mở." +#~ msgid "Run standalone tasks on this device. Schedules run while the device is awake and Poracode is open." +#~ msgstr "Chạy các tác vụ độc lập trên thiết bị này. Lịch chạy khi thiết bị đang hoạt động và Poracode đang mở." #: src/renderer/commands/registry.ts msgid "Run Terminal Command" msgstr "Chạy lệnh Terminal" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Run the latest missed run" +msgstr "Chạy lượt bị bỏ lỡ gần nhất" + #: src/renderer/views/SchedulesView/ScheduleEditor.tsx #~ msgid "Run this schedule automatically at the times above." #~ msgstr "Tự động chạy lịch này vào các thời điểm ở trên." @@ -7562,6 +7899,7 @@ msgstr "đang chạy" #: src/renderer/utils/prStatus.ts #: src/renderer/views/SchedulesView/parts/PreviousRunsModal.tsx +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx msgid "Running" msgstr "Đang chạy" @@ -7585,6 +7923,10 @@ msgstr "Hết sớm" msgid "Runs out in {runOut}" msgstr "Sẽ hết sau {runOut}" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Runs that need attention will appear here." +msgstr "Các lượt chạy cần chú ý sẽ xuất hiện ở đây." + #: src/renderer/views/MainView/parts/CreateProject/CloneProjectModal.tsx #: src/renderer/views/MainView/parts/CreateProject/CreateProjectModal.tsx msgid "Runtime" @@ -7661,6 +8003,10 @@ msgstr "Quét Windows và WSL để tìm CLI đã cài đặt. Việc này thư msgid "Scanning your system for installed CLIs. This usually takes a couple of seconds." msgstr "Đang quét hệ thống của bạn để tìm CLI đã cài đặt. Việc này thường mất vài giây." +#: src/renderer/views/SchedulesView/SchedulesView.tsx +msgid "Schedule autonomous work and review results that need your attention. Automations run while this device is awake and Poracode is open." +msgstr "Lên lịch công việc tự chủ và xem lại các kết quả cần bạn chú ý. Tự động hóa chạy khi thiết bị này đang hoạt động và Poracode đang mở." + #: src/renderer/views/SchedulesView/ScheduleEditor.tsx msgid "Schedule name" msgstr "Tên lịch" @@ -7669,20 +8015,31 @@ msgstr "Tên lịch" msgid "Schedule status" msgstr "Trạng thái lịch" +#: src/renderer/i18n/sharedMessages.ts +msgid "Scheduled retry was cancelled." +msgstr "Lần thử lại theo lịch đã bị hủy." + +#: src/renderer/i18n/sharedMessages.ts +msgid "Scheduled task was deleted before retrying." +msgstr "Tác vụ đã lên lịch đã bị xóa trước khi thử lại." + #: src/renderer/views/SchedulesView/SchedulesView.tsx -msgid "Scheduled tasks" -msgstr "Tác vụ đã lên lịch" +#~ msgid "Scheduled tasks" +#~ msgstr "Tác vụ đã lên lịch" #: src/mobile/settingsSections.ts -msgid "Scheduled tasks on this desktop" -msgstr "Tác vụ đã lên lịch trên máy tính này" +#~ msgid "Scheduled tasks on this desktop" +#~ msgstr "Tác vụ đã lên lịch trên máy tính này" #: src/renderer/views/SchedulesView/SchedulesView.tsx #~ msgid "Scheduled tasks run only while this device is awake and Poracode is open." #~ msgstr "Tác vụ đã lên lịch chỉ chạy khi thiết bị này đang hoạt động và Poracode đang mở." #: src/mobile/settingsSections.ts -#: src/renderer/views/MainView/parts/Sidebar/Sidebar.tsx +msgid "Scheduled work and triage on this desktop" +msgstr "Công việc theo lịch và phân loại trên máy tính này" + +#: src/renderer/views/SchedulesView/SchedulesView.tsx msgid "Schedules" msgstr "Lịch biểu" @@ -7737,6 +8094,10 @@ msgstr "Tìm kiếm nhánh..." msgid "Search files" msgstr "Tìm kiếm tập tin" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Search findings" +msgstr "Tìm kiếm kết quả" + #: src/renderer/components/skills/SkillMarketplaceModal.tsx msgid "Search marketplace skills" msgstr "Tìm kiếm skill trên marketplace" @@ -7831,6 +8192,10 @@ msgstr "Đang tìm kiếm..." msgid "Searching…" msgstr "Đang tìm kiếm…" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "seconds" +msgstr "giây" + #: src/renderer/components/skills/SkillMarketplaceModal.tsx #~ msgid "Security-focused directory with verified skill metadata." #~ msgstr "Danh mục tập trung vào bảo mật với siêu dữ liệu skill đã được xác minh." @@ -8221,6 +8586,10 @@ msgstr "Đang đăng xuất {env}. Các tác nhân được phát hiện sẽ l msgid "Signing out. Detected agents will refresh when it finishes." msgstr "Đang đăng xuất. Các tác nhân được phát hiện sẽ làm mới khi nó kết thúc." +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Single pass" +msgstr "Một lượt" + #: src/renderer/components/skills/SkillImportModal.tsx #: src/renderer/components/skills/SkillMarketplaceModal.tsx msgid "Skill availability" @@ -8285,7 +8654,12 @@ msgstr "Marketplace skill" msgid "Skills.sh" msgstr "Skills.sh" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Skip missed runs" +msgstr "Bỏ qua các lượt chạy bị lỡ" + #: src/renderer/utils/prStatus.ts +#: src/renderer/views/SchedulesView/parts/PreviousRunsModal.tsx msgid "Skipped" msgstr "Đã bỏ qua" @@ -8424,6 +8798,10 @@ msgstr "Khởi động {appName} để xem mức sử dụng" msgid "Start a dev server on your desktop, then tap refresh." msgstr "Khởi động một máy chủ phát triển trên máy tính của bạn, sau đó nhấn làm mới." +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Start a new conversation for each run." +msgstr "Bắt đầu cuộc trò chuyện mới cho mỗi lượt chạy." + #: src/renderer/commands/registry.ts msgid "Start a new thread as panel instead of page" msgstr "Mở luồng mới dưới dạng bảng thay vì trang" @@ -8562,6 +8940,10 @@ msgstr "Dừng lại" msgid "Stop forwarding" msgstr "Dừng chuyển tiếp" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Stop on error" +msgstr "Dừng khi có lỗi" + #: src/renderer/components/thread/ThreadComposer.tsx msgid "Stop response" msgstr "Dừng phản hồi" @@ -8574,10 +8956,18 @@ msgstr "Dừng tác vụ" msgid "Stop the project's running threads before changing its folder." msgstr "Dừng các luồng đang chạy của dự án trước khi thay đổi thư mục của nó." +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Stop the run when this total time is reached." +msgstr "Dừng lượt chạy khi đạt tổng thời gian này." + #: src/renderer/components/composer/VoiceInputButton.tsx msgid "Stop voice input" msgstr "Dừng nhập bằng giọng nói" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Stop when" +msgstr "Dừng khi" + #: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts #: src/renderer/views/SettingsOverlay/parts/WorktreeSettings.tsx msgid "Storage location" @@ -8922,6 +9312,22 @@ msgstr "Tác nhân" msgid "the app" msgstr "ứng dụng" +#: src/renderer/i18n/sharedMessages.ts +msgid "The automation conversation exited before the turn completed." +msgstr "Cuộc trò chuyện tự động hóa đã thoát trước khi lượt tương tác hoàn tất." + +#: src/renderer/i18n/sharedMessages.ts +msgid "The automation exceeded its time limit." +msgstr "Tự động hóa đã vượt quá giới hạn thời gian." + +#: src/renderer/i18n/sharedMessages.ts +msgid "The automation needs a reply before it can continue." +msgstr "Tự động hóa cần câu trả lời trước khi có thể tiếp tục." + +#: src/renderer/i18n/sharedMessages.ts +msgid "The automation needs approval before it can continue." +msgstr "Tự động hóa cần được phê duyệt trước khi có thể tiếp tục." + #: src/renderer/views/MainView/parts/CreateProject/CloneProjectModal.tsx msgid "the chosen folder" msgstr "thư mục đã chọn" @@ -8935,11 +9341,39 @@ msgstr "Nhịp làm mới nền mặc định, được dùng cho mọi nhà cun msgid "The desktop server is still coming online." msgstr "Máy chủ trên máy tính vẫn đang khởi động." +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "The finding is no longer available." +msgstr "Kết quả không còn khả dụng." + #. placeholder {0}: createTarget.wslDistro #: src/renderer/components/skills/SkillsManager.tsx msgid "the global {0} WSL scope" msgstr "phạm vi WSL toàn cục {0}" +#: src/renderer/i18n/sharedMessages.ts +msgid "The heartbeat conversation belongs to a different project." +msgstr "Cuộc trò chuyện nhịp kiểm tra thuộc một dự án khác." + +#: src/renderer/i18n/sharedMessages.ts +msgid "The heartbeat conversation cannot be resumed." +msgstr "Không thể tiếp tục cuộc trò chuyện nhịp kiểm tra." + +#: src/renderer/i18n/sharedMessages.ts +msgid "The heartbeat conversation is archived." +msgstr "Cuộc trò chuyện nhịp kiểm tra đã được lưu trữ." + +#: src/renderer/i18n/sharedMessages.ts +msgid "The heartbeat conversation is currently busy." +msgstr "Cuộc trò chuyện nhịp kiểm tra hiện đang bận." + +#: src/renderer/i18n/sharedMessages.ts +msgid "The heartbeat conversation no longer exists." +msgstr "Cuộc trò chuyện nhịp kiểm tra không còn tồn tại." + +#: src/renderer/i18n/sharedMessages.ts +msgid "The heartbeat conversation uses a different agent." +msgstr "Cuộc trò chuyện nhịp kiểm tra sử dụng một tác nhân khác." + #: src/renderer/components/skills/SkillsManager.tsx msgid "the Linux user" msgstr "người dùng Linux" @@ -8972,6 +9406,14 @@ msgstr "Máy chủ từ xa không trả về thông tin xác thực ghép nối. msgid "The repository location on disk. Update it if you moved the folder." msgstr "Vị trí của kho lưu trữ trên đĩa. Hãy cập nhật nếu bạn đã di chuyển thư mục." +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "The run could not be cancelled." +msgstr "Không thể hủy lượt chạy." + +#: src/renderer/i18n/sharedMessages.ts +msgid "The scheduled automation failed." +msgstr "Tự động hóa theo lịch đã thất bại." + #: src/renderer/components/mcp/McpServersManager.tsx #~ msgid "The selected file does not contain valid MCP server configurations." #~ msgstr "Tệp đã chọn không chứa cấu hình máy chủ MCP hợp lệ." @@ -9227,6 +9669,18 @@ msgstr "Các luồng được đánh dấu hoàn thành mà không được đ msgid "Time" msgstr "Thời gian" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Time limit" +msgstr "Giới hạn thời gian" + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Time limit in minutes" +msgstr "Giới hạn thời gian tính bằng phút" + +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Time zone" +msgstr "Múi giờ" + #: src/renderer/components/mcp/McpServerEditor.tsx msgid "Timeout (ms)" msgstr "Thời gian chờ (ms)" @@ -9356,6 +9810,10 @@ msgstr "Thanh bên trong suốt" msgid "Trending now" msgstr "Đang thịnh hành" +#: src/renderer/views/SchedulesView/SchedulesView.tsx +msgid "Triage" +msgstr "Phân loại" + #: src/mobile/views/DesktopsView.tsx msgid "Trust and connect" msgstr "Tin cậy và kết nối" @@ -9598,6 +10056,10 @@ msgstr "Chưa gán" msgid "Unavailable" msgstr "Không khả dụng" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Unavailable conversation" +msgstr "Cuộc trò chuyện không khả dụng" + #: src/renderer/views/SchedulesView/ScheduleEditor.tsx msgid "Unavailable project" msgstr "Dự án không khả dụng" @@ -9676,6 +10138,10 @@ msgstr "Không phân giai đoạn:" msgid "Unpin" msgstr "Bỏ ghim" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Unread" +msgstr "Chưa đọc" + #: src/mobile/views/GitActionSheet.tsx #: src/renderer/views/GitReviewOverlay/parts/GitReviewSidebar/parts/FileRow.tsx #: src/renderer/views/GitReviewOverlay/parts/GitStackedDiff.tsx @@ -10002,6 +10468,12 @@ msgstr "Đang chờ xác thực {methodName}. Các tác nhân được phát hi msgid "waiting for agent to stop" msgstr "đang chờ tác nhân dừng lại" +#: src/renderer/views/SchedulesView/parts/PreviousRunsModal.tsx +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +#: src/renderer/views/SchedulesView/SchedulesView.tsx +msgid "Waiting for approval" +msgstr "Đang chờ phê duyệt" + #: src/renderer/components/thread/ChatPane/parts/items/WorkflowOverlayBody.tsx msgid "Waiting for workflow to spawn agents…" msgstr "Đang chờ quy trình làm việc sinh ra các tác nhân…" @@ -10034,6 +10506,10 @@ msgstr "Đang khởi động các môi trường shell..." msgid "Warming up WSL shell environment…" msgstr "Đang khởi động môi trường shell WSL…" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Warning" +msgstr "Cảnh báo" + #: src/renderer/components/thread/ChatPane/parts/items/ToolCallGroup.tsx #: src/renderer/components/thread/ChatPane/parts/items/toolDisplay.ts #: src/renderer/components/thread/ChatPane/parts/items/WebSearchItem.tsx @@ -10326,6 +10802,10 @@ msgstr "Thư mục gốc WSL" #~ msgid "WSL user" #~ msgstr "Người dùng WSL" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "You’re all caught up." +msgstr "Bạn đã xem hết." + #: src/renderer/views/ProfileOverlay/parts/EditProfileDialog.tsx msgid "Your name" msgstr "Tên của bạn" diff --git a/src/renderer/locales/zh-CN/messages.po b/src/renderer/locales/zh-CN/messages.po index 50dd3bfaf..f0777b6ee 100644 --- a/src/renderer/locales/zh-CN/messages.po +++ b/src/renderer/locales/zh-CN/messages.po @@ -288,6 +288,11 @@ msgstr "{agentLabel}:{statusLabel}。将鼠标悬停以查看状态详细信 msgid "{agentLead} needs your input to continue." msgstr "{agentLead} 需要你的输入才能继续。" +#. placeholder {0}: task.recurrence.timeZone +#: src/renderer/views/SchedulesView/SchedulesView.tsx +msgid "{cadence} in {0}" +msgstr "{cadence}({0})" + #: src/mobile/views/pr/PrOverviewPage.tsx msgid "{commitsCount, plural, one {# commit} other {# commits}}" msgstr "{commitsCount, plural, one {# 个提交} other {# 个提交}}" @@ -315,6 +320,18 @@ msgstr "{days}天前" msgid "{envOrAgentLabel} needs authentication." msgstr "{envOrAgentLabel}需要身份验证。" +#: src/renderer/views/SchedulesView/SchedulesView.tsx +msgid "{every, plural, one {Every day} other {Every # days}}" +msgstr "{every, plural, one {每天} other {每 # 天}}" + +#: src/renderer/views/SchedulesView/SchedulesView.tsx +msgid "{every, plural, one {Every hour} other {Every # hours}}" +msgstr "{every, plural, one {每小时} other {每 # 小时}}" + +#: src/renderer/views/SchedulesView/SchedulesView.tsx +msgid "{every, plural, one {Every minute} other {Every # minutes}}" +msgstr "{every, plural, one {每分钟} other {每 # 分钟}}" + #: src/mobile/views/pr/PrOverviewPage.tsx msgid "{filesCount, plural, one {# file changed} other {# files changed}}" msgstr "{filesCount, plural, one {# 个文件已更改} other {# 个文件已更改}}" @@ -491,6 +508,10 @@ msgstr "~{money}{tokens} · {0} · 预计" msgid "≈{0}% by reset" msgstr "≈{0}% 重置时" +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "0 9 * * 1-5" +msgstr "0 9 * * 1-5" + #: src/mobile/views/ThreadsView.tsx msgid "1 thread" msgstr "1 个线程" @@ -840,6 +861,10 @@ msgstr "AI git操作" msgid "AI providers" msgstr "AI 提供商" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "AI stop condition" +msgstr "AI 停止条件" + #: src/mobile/views/MoreView.tsx #~ msgid "AI, agents, and archived threads on the paired desktop" #~ msgstr "配对桌面上的 AI、代理和已存档线程" @@ -851,6 +876,7 @@ msgstr "线程需要你时提醒" #: src/renderer/commands/shortcutCatalog.ts #: src/renderer/components/skills/SkillsManager.tsx #: src/renderer/views/PullRequestsView/PullRequestsView.tsx +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx #: src/renderer/views/SchedulesView/SchedulesView.tsx #: src/renderer/views/SettingsOverlay/parts/ProfileSettings.tsx msgid "All" @@ -943,6 +969,10 @@ msgstr "总是被排除在外" msgid "An MCP server with this name already exists." msgstr "已存在同名的 MCP 服务器。" +#: src/renderer/i18n/sharedMessages.ts +msgid "Another automation is already using this conversation." +msgstr "另一个自动化任务已在使用此对话。" + #: src/renderer/components/thread/ChatPane/parts/CheckpointRevertControls.tsx msgid "Another chat uses this same tree. File restore could overwrite that chat's changes." msgstr "另一个聊天使用同一棵树。文件恢复可能会覆盖该聊天的更改。" @@ -1014,6 +1044,10 @@ msgstr "全部存档" msgid "Archive all threads" msgstr "归档所有线程" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Archive finding" +msgstr "归档发现项" + #: src/renderer/commands/registry.ts msgid "Archive the current thread" msgstr "归档当前线程" @@ -1028,6 +1062,10 @@ msgstr "归档线程" msgid "Archive Thread" msgstr "存档线程" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Archived" +msgstr "已归档" + #: src/mobile/settingsSections.ts #: src/mobile/views/SettingsView.tsx #: src/renderer/views/SettingsOverlay/parts/ArchivedThreadsSettings.tsx @@ -1173,6 +1211,16 @@ msgstr "自动显示终端面板" msgid "Automatically show the terminal panel when running commands or creating worktrees." msgstr "运行命令或创建工作树时自动显示终端面板。" +#: src/renderer/views/SchedulesView/SchedulesView.tsx +msgid "Automation sections" +msgstr "自动化分区" + +#: src/mobile/settingsSections.ts +#: src/renderer/views/MainView/parts/Sidebar/Sidebar.tsx +#: src/renderer/views/SchedulesView/SchedulesView.tsx +msgid "Automations" +msgstr "自动化" + #: src/renderer/components/skills/SkillImportModal.tsx msgid "Availability" msgstr "可用范围" @@ -1459,6 +1507,10 @@ msgstr "绕过分支保护规则(管理合并)" msgid "Cached only" msgstr "仅缓存" +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Calculated on desktop after saving" +msgstr "保存后在桌面端计算" + #: src/mobile/QrScanner.tsx msgid "Camera access blocked" msgstr "摄像头访问已被阻止" @@ -1513,11 +1565,16 @@ msgstr "取消选择器" msgid "Cancel removing project" msgstr "取消移除项目" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Cancel run" +msgstr "取消运行" + #: src/renderer/components/thread/ChatPane/parts/items/WorkflowOverlayBody.tsx msgid "cancelled" msgstr "已取消" #: src/renderer/utils/prStatus.ts +#: src/renderer/views/SchedulesView/parts/PreviousRunsModal.tsx msgid "Cancelled" msgstr "已取消" @@ -1706,6 +1763,10 @@ msgstr "选择 Poracode 界面的显示语言。" msgid "Choose thread to attach to" msgstr "选择要附加到的线程" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Choose what happens after a scheduled time was missed." +msgstr "选择错过计划时间后的处理方式。" + #: src/renderer/views/SettingsOverlay/parts/BrowserSettings.tsx #: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts msgid "Choose whether links from Poracode and browser popups stay in Poracode or open externally." @@ -2185,6 +2246,14 @@ msgstr "已完成" msgid "Completed" msgstr "已完成" +#: src/renderer/i18n/sharedMessages.ts +msgid "Completion evaluation failed: {detail}" +msgstr "完成情况评估失败:{detail}" + +#: src/renderer/i18n/sharedMessages.ts +msgid "Completion evaluation is unavailable." +msgstr "无法进行完成情况评估。" + #: src/renderer/commands/shortcutCatalog.ts #: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx #: src/renderer/views/SettingsOverlay/parts/settingsOptions.ts @@ -2223,6 +2292,14 @@ msgstr "已启用 Computer Use — 交互操作会接管桌面;代理控制期 #~ msgid "Computer Use enabled for this thread" #~ msgstr "为此线程启用计算机操作" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Confidence" +msgstr "置信度" + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Confidence percent" +msgstr "置信度百分比" + #: src/renderer/views/SettingsOverlay/parts/ClaudeProfileSettings.tsx msgid "Config directory" msgstr "配置目录" @@ -2386,6 +2463,14 @@ msgstr "继续使用另一个提供商" msgid "Continue in..." msgstr "在其他工具中继续..." +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Continue one conversation until a stop condition or limit is reached." +msgstr "持续使用同一个对话,直到满足停止条件或达到限制。" + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Control how each scheduled run continues and stops." +msgstr "控制每次计划运行如何继续和停止。" + #: src/renderer/views/SettingsOverlay/parts/SearchSettings.tsx msgid "Control which files appear in the @file mention search. Per-project overrides live in each project's settings." msgstr "控制哪些文件出现在 @file 提及搜索中。可在各项目的设置中进行项目级覆盖。" @@ -2397,6 +2482,7 @@ msgstr "代理点击或输入时控制已配对的桌面" #: src/mobile/views/pr/PrConversationPage.tsx #: src/mobile/views/pr/PrOverviewPage.tsx #: src/renderer/views/PrReviewOverlay/parts/PrTabsPill.tsx +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx msgid "Conversation" msgstr "对话" @@ -2697,6 +2783,24 @@ msgstr "凭证已配置。" msgid "Credits" msgstr "鸣谢" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Critical" +msgstr "严重" + +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Cron" +msgstr "Cron" + +#. placeholder {0}: task.recurrence.expression +#. placeholder {1}: task.recurrence.timeZone +#: src/renderer/views/SchedulesView/SchedulesView.tsx +msgid "Cron {0} in {1}" +msgstr "Cron {0}({1})" + +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Cron expression" +msgstr "Cron 表达式" + #: src/renderer/components/skills/SkillMarketplaceModal.tsx #~ msgid "Curated free and premium skills managed by MCP Market." #~ msgstr "由 MCP Market 管理的精选免费和高级技能。" @@ -2762,9 +2866,9 @@ msgstr "每日简报" msgid "Dark" msgstr "深色" -#: src/renderer/views/SchedulesView/SchedulesView.tsx -#~ msgid "Days" -#~ msgstr "星期" +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Days" +msgstr "星期" #: src/renderer/components/thread/ThreadRuntimeRequestPanel/structuredElicitation.tsx msgid "Decline" @@ -2911,6 +3015,10 @@ msgstr "删除工作树{0}" #~ msgid "Delete:" #~ msgstr "删除:" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Deleted schedule" +msgstr "已删除的计划" + #: src/renderer/views/SettingsOverlay/parts/AcpRegistrySettings.tsx msgid "Deleting" msgstr "正在删除" @@ -2923,6 +3031,10 @@ msgstr "拒绝" msgid "Deny and tell the agent what to do differently…" msgstr "拒绝并告诉代理换一种做法……" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Describe the result that completes this heartbeat." +msgstr "描述完成此心跳所需的结果。" + #: src/renderer/views/SchedulesView/ScheduleEditor.tsx msgid "Describe what the agent should do" msgstr "描述代理应执行的操作" @@ -2944,6 +3056,10 @@ msgstr "桌面端点" msgid "Desktop is unreachable." msgstr "无法访问桌面。" +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Desktop local time" +msgstr "桌面端本地时间" + #: src/mobile/chrome.ts #: src/mobile/views/MoreView.tsx msgid "Desktop Settings" @@ -3056,6 +3172,10 @@ msgstr "禁用项目" msgid "Disable Subagents" msgstr "禁用子代理" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Disable the automation after retries are exhausted." +msgstr "重试次数用尽后停用自动化。" + #: src/renderer/views/SettingsOverlay/parts/ClaudeProfileSettings.tsx msgid "Disable tiers an external provider collapses (e.g. keep only High and Max)." msgstr "禁用外部服务商合并的级别(例如仅保留High和Max)。" @@ -3356,6 +3476,10 @@ msgstr "已启用的服务器会在新线程中保持开启" msgid "Enables <0>cookies and <1>storage. Cookies can contain session tokens and storage often holds auth state — only enable when you trust both the agent and the sites it visits." msgstr "启用<0>cookie和<1>存储。Cookie 可以包含会话令牌,并且存储通常保存身份验证状态——仅当您信任代理及其访问的站点时才启用。" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +#~ msgid "End the heartbeat after retries are exhausted." +#~ msgstr "重试次数用尽后结束心跳。" + #: src/mobile/views/DesktopsView.tsx #: src/renderer/views/SettingsOverlay/parts/RemoteServersSettings.tsx msgid "Endpoint" @@ -3393,6 +3517,10 @@ msgstr "请输入有效的桌面端点。" msgid "Enter a valid HTTP or HTTPS URL." msgstr "请输入有效的 HTTP 或 HTTPS URL。" +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Enter a valid schedule" +msgstr "请输入有效的计划" + #: src/mobile/views/DesktopsView.tsx msgid "Enter a valid SSH target and port." msgstr "请输入有效的 SSH 目标和端口。" @@ -3463,6 +3591,14 @@ msgstr "错误" msgid "Error · Agent encountered an error" msgstr "错误 · 代理遇到错误" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Evaluate the result after every iteration." +msgstr "每次迭代后评估结果。" + +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Every" +msgstr "每" + #: src/renderer/views/SchedulesView/SchedulesView.tsx msgid "Every day at {time}" msgstr "每天 {time}" @@ -3485,6 +3621,14 @@ msgstr "每小时过 {0} 分钟" msgid "Exclude patterns" msgstr "排除模式" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Execution" +msgstr "执行" + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Execution mode" +msgstr "执行模式" + #: src/renderer/components/thread/ChatPane/parts/items/toolDisplay.ts msgid "Exit plan mode" msgstr "退出计划模式" @@ -3534,6 +3678,10 @@ msgstr "展开以查看或撤销访问权限。" msgid "Expand todo dock" msgstr "展开待办事项停靠栏" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Exponential backoff" +msgstr "指数退避" + #: src/renderer/components/mcp/McpServersManager.tsx msgid "Export MCP servers" msgstr "导出 MCP 服务器" @@ -3716,6 +3864,10 @@ msgstr "在差异中查找" msgid "Find in terminal" msgstr "在终端中查找" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Finding status" +msgstr "发现项状态" + #: src/renderer/views/PrReviewOverlay/parts/SubmitReviewPopover.tsx msgid "Finish your review" msgstr "完成您的审查" @@ -3777,6 +3929,10 @@ msgstr "在代理中修复" msgid "Fixed" msgstr "已修复" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Fixed delay" +msgstr "固定延迟" + #: src/renderer/commands/registry.ts msgid "Focus browser address bar" msgstr "聚焦浏览器地址栏" @@ -4097,6 +4253,26 @@ msgstr "有未发送的草稿" msgid "Headers" msgstr "请求头" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Heartbeat" +msgstr "心跳" + +#: src/renderer/i18n/sharedMessages.ts +msgid "Heartbeat automations require a native chat conversation." +msgstr "心跳自动化需要原生聊天对话。" + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Heartbeat continues this conversation in the selected project." +msgstr "心跳将在所选项目中继续此对话。" + +#: src/renderer/i18n/sharedMessages.ts +msgid "Heartbeat execution is unavailable." +msgstr "无法执行心跳。" + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Heartbeats can continue making changes while you're away. Set hard limits below." +msgstr "你离开后,心跳仍可继续进行更改。请在下方设置硬性限制。" + #: src/renderer/views/SchedulesView/SchedulesView.tsx msgid "Help me create a schedule. Ask for any missing details, then use the Poracode schedule controls to create it for me." msgstr "帮助我创建计划。询问缺失的详细信息,然后使用 Poracode 计划控件为我创建。" @@ -4198,6 +4374,10 @@ msgstr "host.com、别名或 user@host.com" msgid "Hourly" msgstr "每小时" +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Hours" +msgstr "小时" + #: src/renderer/components/mcp/McpServerEditor.tsx msgid "HTTP (streamable)" msgstr "HTTP(流式)" @@ -4328,6 +4508,14 @@ msgstr "应用内摄像头扫描仅支持 HTTPS。请使用手机相机应用扫 msgid "Inactive" msgstr "不活跃" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Includes the first attempt." +msgstr "包括首次尝试。" + +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Info" +msgstr "信息" + #. Badge on an exclude pattern inherited from a lower scope #: src/renderer/views/SettingsOverlay/parts/SearchExcludeBody.tsx msgid "inherited" @@ -4338,6 +4526,14 @@ msgstr "继承的" msgid "Inheriting the global setting (currently {0})." msgstr "继承全局设置(当前为{0})。" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Initial retry delay" +msgstr "初始重试延迟" + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Initial retry delay in seconds" +msgstr "初始重试延迟(秒)" + #: src/renderer/views/GitReviewOverlay/parts/GitReviewSidebar/GitReviewSidebar.tsx msgid "Initialize Repository" msgstr "初始化存储库" @@ -4476,6 +4672,18 @@ msgstr "已中断" msgid "Interrupted: agent session ended before completion." msgstr "已中断:代理会话在完成之前结束。" +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Interval" +msgstr "间隔" + +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Interval amount" +msgstr "间隔数值" + +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Interval unit" +msgstr "间隔单位" + #: src/renderer/views/MainView/parts/RightPanel/parts/NotesPanel/NotesEditor.tsx msgid "Italic" msgstr "斜体" @@ -4560,6 +4768,14 @@ msgstr "正在启动…" msgid "Leave a comment" msgstr "发表评论" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Leave blank for no run limit." +msgstr "留空表示不限制运行次数。" + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +#~ msgid "Leave blank to rely on the time limit." +#~ msgstr "留空则仅依赖时间限制。" + #: src/renderer/views/ProfileOverlay/parts/ActivityHeatmap.tsx msgid "Less" msgstr "少" @@ -4640,6 +4856,10 @@ msgstr "正在加载编辑器..." msgid "Loading file…" msgstr "正在加载文件..." +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Loading findings" +msgstr "正在加载发现项" + #: src/renderer/components/skills/SkillMarketplaceModal.tsx msgid "Loading marketplace…" msgstr "正在加载市场…" @@ -4864,6 +5084,14 @@ msgstr "标记为已完成" msgid "Mark as not done" msgstr "标记为未完成" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Mark as read" +msgstr "标记为已读" + +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Mark as unread" +msgstr "标记为未读" + #: src/renderer/components/thread/ThreadView.tsx msgid "Mark done" msgstr "标记完成" @@ -4904,6 +5132,22 @@ msgstr "最大化" msgid "Maximize browser" msgstr "最大化浏览器" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Maximum attempts" +msgstr "最大尝试次数" + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Maximum iterations" +msgstr "最大迭代次数" + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Maximum retry delay" +msgstr "最大重试延迟" + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Maximum retry delay in seconds" +msgstr "最大重试延迟(秒)" + #: src/renderer/components/skills/SkillMarketplaceModal.tsx #~ msgid "MCP Market" #~ msgstr "MCP Market" @@ -5109,6 +5353,18 @@ msgstr "最小化到面板" msgid "Minute" msgstr "分钟" +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Minute, hour, day of month, month, and weekday." +msgstr "分钟、小时、日期、月份和星期。" + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "minutes" +msgstr "分钟" + +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Minutes" +msgstr "分钟" + #: src/mobile/views/BrowserView.tsx msgid "Mirrored desktop browser tab" msgstr "镜像的桌面浏览器标签页" @@ -5117,6 +5373,10 @@ msgstr "镜像的桌面浏览器标签页" msgid "Mirroring is unavailable." msgstr "镜像不可用。" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Missed runs" +msgstr "错过的运行" + #: src/renderer/views/SettingsOverlay/parts/RemoteAccessSettings.tsx msgid "Mobile push notifications" msgstr "移动推送通知" @@ -5468,6 +5728,10 @@ msgstr "下一个匹配项" msgid "Next recently viewed chat" msgstr "下一个最近查看的聊天" +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Next run" +msgstr "下次运行" + #. placeholder {0}: dateTimeFormatter.format(new Date(task.nextRunAt)) #: src/renderer/views/SchedulesView/SchedulesView.tsx msgid "Next run {0}" @@ -5513,6 +5777,10 @@ msgstr "没有安装代理。" msgid "No AI commits, PRs, or conflict resolutions tracked yet." msgstr "暂未记录任何AI提交、PR或冲突解决。" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "No archived findings." +msgstr "没有已归档的发现项。" + #: src/renderer/views/SettingsOverlay/parts/ArchivedThreadsSettings.tsx msgid "No archived threads." msgstr "没有存档的线程。" @@ -5609,6 +5877,10 @@ msgstr "{0}没有可用的差异" msgid "No diff for {visiblePath}" msgstr "{visiblePath}没有差异" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "No eligible conversations in this project." +msgstr "此项目中没有符合条件的对话。" + #: src/renderer/components/skills/SkillImportModal.tsx msgid "No external skills were found in this scope." msgstr "在此范围内未找到外部技能。" @@ -5624,6 +5896,10 @@ msgstr "没有为此消息存储文件检查点。" msgid "No files match \"{0}\"." msgstr "没有文件匹配“{0}”。" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "No findings yet." +msgstr "暂无发现项。" + #: src/renderer/views/MainView/parts/CreateProject/CloneProjectModal.tsx msgid "No GitHub CLI accounts found. Sign in with <0>gh auth login, or <1>paste a clone URL." msgstr "未找到 GitHub CLI 帐户。使用<0>gh auth login登录,或<1>粘贴克隆网址。" @@ -5636,6 +5912,10 @@ msgstr "暂无历史记录" msgid "No Lightcode data was found." msgstr "未找到 Lightcode 数据。" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "No limit" +msgstr "无限制" + #: src/renderer/components/skills/SkillMarketplaceModal.tsx msgid "No marketplace skills match these filters." msgstr "没有符合这些筛选条件的市场技能。" @@ -5652,6 +5932,10 @@ msgstr "没有匹配项。" msgid "No matching agents." msgstr "没有匹配的代理。" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "No matching findings." +msgstr "没有匹配的发现项。" + #: src/renderer/views/PullRequestsView/PullRequestsView.tsx msgid "No matching pull requests." msgstr "没有匹配的拉取请求。" @@ -5761,6 +6045,10 @@ msgstr "未找到存储库。" msgid "No results" msgstr "没有结果" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "No retries" +msgstr "不重试" + #: src/renderer/views/SchedulesView/parts/PreviousRunsModal.tsx msgid "No runs yet." msgstr "尚无运行记录。" @@ -5797,6 +6085,10 @@ msgstr "未检测到语音。" msgid "No staged changes" msgstr "没有暂存的更改" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "No summary was provided." +msgstr "未提供摘要。" + #: src/renderer/views/RemoteProjectModal/RemoteProjectModal.tsx msgid "No supported agents are installed on this remote machine. Install and sign in to an agent remotely before starting a thread." msgstr "此远程计算机上未安装受支持的代理。请先在远程安装代理并登录,然后再启动线程。" @@ -5826,6 +6118,10 @@ msgstr "还没有线程" msgid "No threads yet." msgstr "暂无对话。" +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "No upcoming run" +msgstr "暂无后续运行" + #: src/renderer/components/providers/usageFormat.ts msgid "No windows reported" msgstr "没有报告窗口" @@ -6041,6 +6337,11 @@ msgstr "在 GitHub 上打开提交" msgid "Open conflict resolver in" msgstr "在以下位置打开冲突解决器" +#. placeholder {0}: props.scheduleName +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Open conversation for {0}" +msgstr "打开 {0} 的对话" + #: src/renderer/views/SettingsOverlay/parts/settingsOptions.ts msgid "Open dialog" msgstr "打开对话框" @@ -6676,6 +6977,10 @@ msgstr "项目文件夹已更新。请重新打开此项目中的所有终端。 msgid "Project name" msgstr "项目名称" +#: src/renderer/i18n/sharedMessages.ts +msgid "Project no longer exists." +msgstr "项目已不存在。" + #: src/renderer/views/MainView/parts/RightPanel/parts/NotesPanel/NotesEditor.tsx msgid "Project notes" msgstr "项目笔记" @@ -7274,6 +7579,10 @@ msgstr "请求详情" msgid "requested changes" msgstr "要求更改" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Required confidence before stopping." +msgstr "停止前所需的置信度。" + #: src/mobile/views/pr/PrOverviewPage.tsx #: src/renderer/views/GitReviewOverlay/parts/GitReviewSidebar/parts/PrSection.tsx msgid "Required reviews, conversations, or status checks not met." @@ -7345,6 +7654,10 @@ msgstr "恢复浏览器" msgid "Restore default worktree base folder" msgstr "恢复默认工作树基础文件夹" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Restore finding" +msgstr "恢复发现项" + #: src/mobile/settingsSections.ts msgid "Restore or delete" msgstr "恢复或删除" @@ -7375,10 +7688,26 @@ msgstr "重试 {serverName}" msgid "Retry check" msgstr "重试检查" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Retry delay" +msgstr "重试延迟" + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Retry delay in seconds" +msgstr "重试延迟(秒)" + #: src/mobile/components.tsx msgid "Retry now" msgstr "立即重试" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Retry policy" +msgstr "重试策略" + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Retry when a run fails before it completes." +msgstr "如果运行在完成前失败,则进行重试。" + #: src/renderer/hooks/usePrWriteActions.ts msgid "Retry with admin" msgstr "使用管理员重试" @@ -7534,18 +7863,26 @@ msgstr "如果可用,请在 GPU 上运行本地转录。" msgid "Run now" msgstr "立即运行" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Run once after reopening" +msgstr "重新打开后运行一次" + #: src/renderer/views/SchedulesView/SchedulesView.tsx #~ msgid "Run standalone tasks on this device without a project." #~ msgstr "在此设备上运行不依赖项目的独立任务。" #: src/renderer/views/SchedulesView/SchedulesView.tsx -msgid "Run standalone tasks on this device. Schedules run while the device is awake and Poracode is open." -msgstr "在此设备上运行独立任务。设备唤醒且 Poracode 打开时,计划会运行。" +#~ msgid "Run standalone tasks on this device. Schedules run while the device is awake and Poracode is open." +#~ msgstr "在此设备上运行独立任务。设备唤醒且 Poracode 打开时,计划会运行。" #: src/renderer/commands/registry.ts msgid "Run Terminal Command" msgstr "运行终端命令" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Run the latest missed run" +msgstr "运行最近一次错过的运行" + #: src/renderer/views/SchedulesView/ScheduleEditor.tsx #~ msgid "Run this schedule automatically at the times above." #~ msgstr "在上述时间自动运行此计划。" @@ -7561,6 +7898,7 @@ msgstr "运行中" #: src/renderer/utils/prStatus.ts #: src/renderer/views/SchedulesView/parts/PreviousRunsModal.tsx +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx msgid "Running" msgstr "正在运行" @@ -7584,6 +7922,10 @@ msgstr "提早用完" msgid "Runs out in {runOut}" msgstr "在{runOut}中用完" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Runs that need attention will appear here." +msgstr "需要关注的运行将显示在此处。" + #: src/renderer/views/MainView/parts/CreateProject/CloneProjectModal.tsx #: src/renderer/views/MainView/parts/CreateProject/CreateProjectModal.tsx msgid "Runtime" @@ -7660,6 +8002,10 @@ msgstr "扫描 Windows 和 WSL 以查找已安装的 CLI。这通常需要几秒 msgid "Scanning your system for installed CLIs. This usually takes a couple of seconds." msgstr "扫描系统中已安装的 CLI。这通常需要几秒钟。" +#: src/renderer/views/SchedulesView/SchedulesView.tsx +msgid "Schedule autonomous work and review results that need your attention. Automations run while this device is awake and Poracode is open." +msgstr "安排自主工作,并查看需要你关注的结果。自动化仅在此设备处于唤醒状态且 Poracode 已打开时运行。" + #: src/renderer/views/SchedulesView/ScheduleEditor.tsx msgid "Schedule name" msgstr "计划名称" @@ -7668,20 +8014,31 @@ msgstr "计划名称" msgid "Schedule status" msgstr "计划状态" +#: src/renderer/i18n/sharedMessages.ts +msgid "Scheduled retry was cancelled." +msgstr "已取消计划的重试。" + +#: src/renderer/i18n/sharedMessages.ts +msgid "Scheduled task was deleted before retrying." +msgstr "计划任务在重试前已被删除。" + #: src/renderer/views/SchedulesView/SchedulesView.tsx -msgid "Scheduled tasks" -msgstr "计划任务" +#~ msgid "Scheduled tasks" +#~ msgstr "计划任务" #: src/mobile/settingsSections.ts -msgid "Scheduled tasks on this desktop" -msgstr "此桌面上的计划任务" +#~ msgid "Scheduled tasks on this desktop" +#~ msgstr "此桌面上的计划任务" #: src/renderer/views/SchedulesView/SchedulesView.tsx #~ msgid "Scheduled tasks run only while this device is awake and Poracode is open." #~ msgstr "计划任务仅在此设备处于唤醒状态且 Poracode 已打开时运行。" #: src/mobile/settingsSections.ts -#: src/renderer/views/MainView/parts/Sidebar/Sidebar.tsx +msgid "Scheduled work and triage on this desktop" +msgstr "此桌面上的计划工作和分类处理" + +#: src/renderer/views/SchedulesView/SchedulesView.tsx msgid "Schedules" msgstr "计划" @@ -7736,6 +8093,10 @@ msgstr "搜索分支..." msgid "Search files" msgstr "搜索文件" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Search findings" +msgstr "搜索发现项" + #: src/renderer/components/skills/SkillMarketplaceModal.tsx msgid "Search marketplace skills" msgstr "搜索市场技能" @@ -7830,6 +8191,10 @@ msgstr "正在搜索..." msgid "Searching…" msgstr "正在搜索…" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "seconds" +msgstr "秒" + #: src/renderer/components/skills/SkillMarketplaceModal.tsx #~ msgid "Security-focused directory with verified skill metadata." #~ msgstr "注重安全并提供已验证技能元数据的目录。" @@ -8220,6 +8585,10 @@ msgstr "注销{env}。检测到的代理将在完成后刷新。" msgid "Signing out. Detected agents will refresh when it finishes." msgstr "正在退出。检测到的代理将在完成后刷新。" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Single pass" +msgstr "单次执行" + #: src/renderer/components/skills/SkillImportModal.tsx #: src/renderer/components/skills/SkillMarketplaceModal.tsx msgid "Skill availability" @@ -8284,7 +8653,12 @@ msgstr "技能市场" msgid "Skills.sh" msgstr "Skills.sh" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Skip missed runs" +msgstr "跳过错过的运行" + #: src/renderer/utils/prStatus.ts +#: src/renderer/views/SchedulesView/parts/PreviousRunsModal.tsx msgid "Skipped" msgstr "已跳过" @@ -8423,6 +8797,10 @@ msgstr "启动{appName}以查看用量" msgid "Start a dev server on your desktop, then tap refresh." msgstr "在桌面上启动一个开发服务器,然后点击刷新。" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Start a new conversation for each run." +msgstr "每次运行都启动一个新对话。" + #: src/renderer/commands/registry.ts msgid "Start a new thread as panel instead of page" msgstr "以面板而非页面形式开始一个新线程" @@ -8561,6 +8939,10 @@ msgstr "停止" msgid "Stop forwarding" msgstr "停止转发" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Stop on error" +msgstr "出错时停止" + #: src/renderer/components/thread/ThreadComposer.tsx msgid "Stop response" msgstr "停止响应" @@ -8573,10 +8955,18 @@ msgstr "停止任务" msgid "Stop the project's running threads before changing its folder." msgstr "在更改项目文件夹之前,请停止该项目正在运行的线程。" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Stop the run when this total time is reached." +msgstr "达到此总时长时停止运行。" + #: src/renderer/components/composer/VoiceInputButton.tsx msgid "Stop voice input" msgstr "停止语音输入" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Stop when" +msgstr "停止条件" + #: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts #: src/renderer/views/SettingsOverlay/parts/WorktreeSettings.tsx msgid "Storage location" @@ -8921,6 +9311,22 @@ msgstr "代理" msgid "the app" msgstr "该应用程序" +#: src/renderer/i18n/sharedMessages.ts +msgid "The automation conversation exited before the turn completed." +msgstr "自动化对话在本轮完成前已退出。" + +#: src/renderer/i18n/sharedMessages.ts +msgid "The automation exceeded its time limit." +msgstr "自动化超出了时间限制。" + +#: src/renderer/i18n/sharedMessages.ts +msgid "The automation needs a reply before it can continue." +msgstr "自动化需要回复才能继续。" + +#: src/renderer/i18n/sharedMessages.ts +msgid "The automation needs approval before it can continue." +msgstr "自动化需要批准才能继续。" + #: src/renderer/views/MainView/parts/CreateProject/CloneProjectModal.tsx msgid "the chosen folder" msgstr "所选文件夹" @@ -8934,11 +9340,39 @@ msgstr "默认的后台刷新频率,适用于下方未单独设置间隔的任 msgid "The desktop server is still coming online." msgstr "桌面服务器仍在启动。" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "The finding is no longer available." +msgstr "该发现项已不可用。" + #. placeholder {0}: createTarget.wslDistro #: src/renderer/components/skills/SkillsManager.tsx msgid "the global {0} WSL scope" msgstr "全局 {0} WSL 范围" +#: src/renderer/i18n/sharedMessages.ts +msgid "The heartbeat conversation belongs to a different project." +msgstr "心跳对话属于其他项目。" + +#: src/renderer/i18n/sharedMessages.ts +msgid "The heartbeat conversation cannot be resumed." +msgstr "无法恢复心跳对话。" + +#: src/renderer/i18n/sharedMessages.ts +msgid "The heartbeat conversation is archived." +msgstr "心跳对话已归档。" + +#: src/renderer/i18n/sharedMessages.ts +msgid "The heartbeat conversation is currently busy." +msgstr "心跳对话当前正忙。" + +#: src/renderer/i18n/sharedMessages.ts +msgid "The heartbeat conversation no longer exists." +msgstr "心跳对话已不存在。" + +#: src/renderer/i18n/sharedMessages.ts +msgid "The heartbeat conversation uses a different agent." +msgstr "心跳对话使用了其他代理。" + #: src/renderer/components/skills/SkillsManager.tsx msgid "the Linux user" msgstr "Linux 用户" @@ -8971,6 +9405,14 @@ msgstr "远程服务器未返回配对凭据。" msgid "The repository location on disk. Update it if you moved the folder." msgstr "存储库在磁盘上的位置。如果您移动了该文件夹,请更新此位置。" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "The run could not be cancelled." +msgstr "无法取消运行。" + +#: src/renderer/i18n/sharedMessages.ts +msgid "The scheduled automation failed." +msgstr "计划的自动化运行失败。" + #: src/renderer/components/mcp/McpServersManager.tsx #~ msgid "The selected file does not contain valid MCP server configurations." #~ msgstr "所选文件不包含有效的 MCP 服务器配置。" @@ -9226,6 +9668,18 @@ msgstr "标记为“已完成”且已多日未触及的线程将在应用程序 msgid "Time" msgstr "时间" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Time limit" +msgstr "时间限制" + +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Time limit in minutes" +msgstr "时间限制(分钟)" + +#: src/renderer/views/SchedulesView/ScheduleEditor.tsx +msgid "Time zone" +msgstr "时区" + #: src/renderer/components/mcp/McpServerEditor.tsx msgid "Timeout (ms)" msgstr "超时(毫秒)" @@ -9355,6 +9809,10 @@ msgstr "半透明侧边栏" msgid "Trending now" msgstr "当前热门" +#: src/renderer/views/SchedulesView/SchedulesView.tsx +msgid "Triage" +msgstr "分类处理" + #: src/mobile/views/DesktopsView.tsx msgid "Trust and connect" msgstr "信任并连接" @@ -9597,6 +10055,10 @@ msgstr "未分配" msgid "Unavailable" msgstr "不可用" +#: src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx +msgid "Unavailable conversation" +msgstr "不可用的对话" + #: src/renderer/views/SchedulesView/ScheduleEditor.tsx msgid "Unavailable project" msgstr "不可用的项目" @@ -9675,6 +10137,10 @@ msgstr "未分阶段:" msgid "Unpin" msgstr "取消固定" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Unread" +msgstr "未读" + #: src/mobile/views/GitActionSheet.tsx #: src/renderer/views/GitReviewOverlay/parts/GitReviewSidebar/parts/FileRow.tsx #: src/renderer/views/GitReviewOverlay/parts/GitStackedDiff.tsx @@ -10001,6 +10467,12 @@ msgstr "等待{methodName}身份验证。检测到的代理将在完成后刷新 msgid "waiting for agent to stop" msgstr "等待代理停止" +#: src/renderer/views/SchedulesView/parts/PreviousRunsModal.tsx +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +#: src/renderer/views/SchedulesView/SchedulesView.tsx +msgid "Waiting for approval" +msgstr "正在等待批准" + #: src/renderer/components/thread/ChatPane/parts/items/WorkflowOverlayBody.tsx msgid "Waiting for workflow to spawn agents…" msgstr "正在等待工作流生成代理..." @@ -10033,6 +10505,10 @@ msgstr "正在预热 shell 环境..." msgid "Warming up WSL shell environment…" msgstr "正在预热 WSL shell 环境..." +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "Warning" +msgstr "警告" + #: src/renderer/components/thread/ChatPane/parts/items/ToolCallGroup.tsx #: src/renderer/components/thread/ChatPane/parts/items/toolDisplay.ts #: src/renderer/components/thread/ChatPane/parts/items/WebSearchItem.tsx @@ -10325,6 +10801,10 @@ msgstr "WSL 基础文件夹" #~ msgid "WSL user" #~ msgstr "WSL 用户" +#: src/renderer/views/SchedulesView/parts/TriagePanel.tsx +msgid "You’re all caught up." +msgstr "已全部处理完毕。" + #: src/renderer/views/ProfileOverlay/parts/EditProfileDialog.tsx msgid "Your name" msgstr "你的名字" diff --git a/src/renderer/state/remoteServersStore.test.ts b/src/renderer/state/remoteServersStore.test.ts index 419e9a1d2..e99d4735e 100644 --- a/src/renderer/state/remoteServersStore.test.ts +++ b/src/renderer/state/remoteServersStore.test.ts @@ -1,6 +1,7 @@ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; import type { Project, Thread } from "@/shared/contracts"; import type { RemoteDesktopClient } from "@/shared/remote/client"; +import { PORACODE_REMOTE_PROTOCOL_VERSION } from "@/shared/remote/protocol"; import { __resetRemoteServersStoreForTest, filterRemoteThreadEvent, @@ -117,7 +118,7 @@ function makeClient(opts?: { scopes: ["session:read", "projects:manage"], }), environment: async () => ({ - protocolVersion: 1, + protocolVersion: PORACODE_REMOTE_PROTOCOL_VERSION, desktopId: "d1", label: "Server One", appVersion: "1.0", diff --git a/src/renderer/views/MainView/parts/Sidebar/Sidebar.tsx b/src/renderer/views/MainView/parts/Sidebar/Sidebar.tsx index 0c90804aa..b44d07619 100644 --- a/src/renderer/views/MainView/parts/Sidebar/Sidebar.tsx +++ b/src/renderer/views/MainView/parts/Sidebar/Sidebar.tsx @@ -356,7 +356,7 @@ export function Sidebar() { } - label={t`Schedules`} + label={t`Automations`} isActive={appView.kind === "schedules"} onPress={() => startTransition(() => openSchedules())} /> @@ -457,7 +457,7 @@ export function Sidebar() { /> } - label={t`Schedules`} + label={t`Automations`} isActive={appView.kind === "schedules"} onPress={() => startTransition(() => openSchedules())} /> diff --git a/src/renderer/views/PrReviewOverlay/parts/PrTabsPill.tsx b/src/renderer/views/PrReviewOverlay/parts/PrTabsPill.tsx index 7d205224a..52d61f8aa 100644 --- a/src/renderer/views/PrReviewOverlay/parts/PrTabsPill.tsx +++ b/src/renderer/views/PrReviewOverlay/parts/PrTabsPill.tsx @@ -2,7 +2,11 @@ import { FileDiff, GitCommit, MessageSquare, ShieldCheck } from "lucide-react"; import { msg } from "@lingui/core/macro"; import { useLingui } from "@lingui/react/macro"; import type { MessageDescriptor } from "@lingui/core"; -import { LightballTabs, type LightballTab } from "@/renderer/components/common"; +import { + LightballTabs, + makeLightballCountTrailing, + type LightballTab, +} from "@/renderer/components/common"; import { getChecksStatusTone, type PrChecksStatus, @@ -35,24 +39,6 @@ const CHECKS_ICON_TONE_CLASS: Record = { danger: "text-danger", }; -function CountChip(props: { value: number; active: boolean }) { - return ( - - {props.value} - - ); -} - -/** Builds the `trailing` render function for a tab's count chip, capturing - * `count` as a parameter instead of a render-time closure. */ -function makeCountTrailing(count: number) { - return (isActive: boolean) => ; -} - export function PrTabsPill(props: { active: PrTabKey; onChange: (key: PrTabKey) => void; @@ -74,7 +60,7 @@ export function PrTabsPill(props: { id: def.id, label: t(def.label), icon: , - ...(count > 0 ? { trailing: makeCountTrailing(count) } : {}), + ...(count > 0 ? { trailing: makeLightballCountTrailing(count) } : {}), }; }); diff --git a/src/renderer/views/SchedulesView/ScheduleEditor.tsx b/src/renderer/views/SchedulesView/ScheduleEditor.tsx index f38c87085..8a5452496 100644 --- a/src/renderer/views/SchedulesView/ScheduleEditor.tsx +++ b/src/renderer/views/SchedulesView/ScheduleEditor.tsx @@ -12,15 +12,21 @@ import { buildProviderModelMenuProviders, } from "@/renderer/components/thread/buildModelPickerControls"; import { ThreadComposer } from "@/renderer/components/thread/ThreadComposer"; +import { ScheduleExecutionSection } from "./parts/ScheduleExecutionSection"; import { + DEVICE_LOCAL_TIME_ZONE, + deviceTimeZone, + type IntervalUnit, + isHeartbeatTargetThread, type RepeatMode, type ScheduleDraft, scheduleDraftIsValid, + scheduleDraftPreview, weekdayShortNames, } from "./scheduleDraft"; -// Scheduled tasks always run as one-shot GUI (structured runtime) jobs, so the -// model picker mirrors the Chat presentation surface. +// Schedule execution uses the GUI structured runtime, so the model picker +// mirrors the Chat presentation surface. const PRESENTATION_MODE: ThreadPresentationMode = "gui"; interface ScheduleEditorProps { @@ -60,7 +66,14 @@ function FieldRow(props: { label: ReactNode; description?: ReactNode; children: export function ScheduleEditor(props: ScheduleEditorProps) { const { t, i18n } = useLingui(); const projects = useAppStore((state) => state.projects); + const threads = useAppStore((state) => state.threads); const draft = props.draft; + const heartbeatTargetIsValid = + draft?.automationMode !== "heartbeat" || + threads.some( + (thread) => + thread.id === draft.heartbeatTargetThreadId && isHeartbeatTargetThread(thread, draft), + ); const projectOptions = [ { id: HOME_PROJECT_ID, label: t`Home` }, ...projects @@ -96,6 +109,28 @@ export function ScheduleEditor(props: ScheduleEditorProps) { id: `00:${String(minute).padStart(2, "0")}`, label: minute === 0 ? t`On the hour` : t`${minute} minutes past the hour`, })); + const timeZoneOptions = [ + ...new Set([ + draft?.timeZone ?? deviceTimeZone(), + deviceTimeZone(), + "UTC", + ...(typeof Intl.supportedValuesOf === "function" ? Intl.supportedValuesOf("timeZone") : []), + ]), + ] + .filter((timeZone) => draft?.repeatMode !== "cron" || timeZone !== DEVICE_LOCAL_TIME_ZONE) + .map((timeZone) => ({ + id: timeZone, + label: + timeZone === DEVICE_LOCAL_TIME_ZONE ? t`Desktop local time` : timeZone.replaceAll("_", " "), + })); + const preview = draft ? scheduleDraftPreview(draft) : null; + const nextRunAt = preview?.nextRunAt ?? null; + const nextRunIsDesktopCalculated = preview?.nextRunIsDesktopCalculated ?? false; + const recurrenceIsValid = preview?.recurrenceIsValid ?? false; + const dateTimeFormatter = new Intl.DateTimeFormat(i18n.locale, { + dateStyle: "medium", + timeStyle: "short", + }); function set(next: Partial) { if (draft) props.onChange({ ...draft, ...next }); @@ -143,6 +178,9 @@ export function ScheduleEditor(props: ScheduleEditorProps) { model, effort: keepEffort ? draft.effort : defaultEffort, fast: resolveFastValue(presented, model, draft.fast), + ...(nextSelection.agentKind !== draft.agentKind + ? { heartbeatTargetThreadId: "" } + : {}), }); }, onConfigPatch: (patch) => { @@ -204,9 +242,13 @@ export function ScheduleEditor(props: ScheduleEditorProps) { className={CONTROL_WIDTH} options={projectSelectOptions} value={draft.projectId ?? HOME_PROJECT_ID} - onChange={(value) => - set({ projectId: value === HOME_PROJECT_ID ? null : value }) - } + onChange={(value) => { + const projectId = value === HOME_PROJECT_ID ? null : value; + set({ + projectId, + heartbeatTargetThreadId: "", + }); + }} /> @@ -237,10 +279,12 @@ export function ScheduleEditor(props: ScheduleEditorProps) { className={CONTROL_WIDTH} options={[ { id: "hourly", label: t`Hourly` }, + { id: "interval", label: t`Interval` }, { id: "daily", label: t`Daily` }, { id: "weekdays", label: t`Weekdays` }, { id: "weekly", label: t`Weekly` }, { id: "custom", label: t`Custom` }, + { id: "cron", label: t`Cron` }, { id: "once", label: t`One time` }, ]} value={draft.repeatMode} @@ -288,6 +332,47 @@ export function ScheduleEditor(props: ScheduleEditorProps) { + ) : draft.repeatMode === "interval" ? ( + Every}> +
+ set({ intervalEvery })} + > + + + + + ) : ( )} + {draft.repeatMode === "daily" || + draft.repeatMode === "weekdays" || + draft.repeatMode === "weekly" || + draft.repeatMode === "custom" || + draft.repeatMode === "cron" ? ( + Time zone}> + - - - tabs={[ - { id: "all", label: t`All` }, - { id: "active", label: t`Active` }, - { id: "paused", label: t`Paused` }, - ]} - active={filter} - onChange={setFilter} - ariaLabel={t`Schedule status`} - /> -
+ + className="w-fit" + tabs={[ + { id: "schedules", label: t`Schedules` }, + { + id: "triage", + label: t`Triage`, + ...(unreadCount > 0 + ? { + trailing: makeLightballCountTrailing(unreadCount), + } + : {}), + }, + ]} + active={section} + onChange={setSection} + ariaLabel={t`Automation sections`} + /> {error ?

{error}

: null} - {loading ? ( -
- -
+ {section === "triage" ? ( + dateTimeFormatter.format(new Date(iso))} + onOpenRunThread={openRunThread} + onFilterChange={(nextFilter) => { + setTriageRuns(null); + setTriageFilter(nextFilter); + }} + onRefresh={refreshAutomations} + onError={setError} + /> ) : ( <> - {tasks.length === 0 ? ( -
- -

- Start with a schedule -

-

- Create a useful routine with one click, then adjust it anytime. -

-
- ) : visibleTasks.length === 0 ? ( -
- -

- No matching schedules. -

+
+ + + + + tabs={[ + { id: "all", label: t`All` }, + { id: "active", label: t`Active` }, + { id: "paused", label: t`Paused` }, + ]} + active={filter} + onChange={setFilter} + ariaLabel={t`Schedule status`} + /> +
+ + {loading ? ( +
+
) : ( -
- {visibleTasks.map((task) => ( - setDraft(taskScheduleDraft(target))} - onDelete={setDeleteTask} - onShowRuns={(target) => setRunsTaskId(target.id)} - /> - ))} -
- )} + <> + {tasks.length === 0 ? ( +
+ +

+ Start with a schedule +

+

+ Create a useful routine with one click, then adjust it anytime. +

+
+ ) : visibleTasks.length === 0 ? ( +
+ +

+ No matching schedules. +

+
+ ) : ( +
+ {visibleTasks.map((task) => ( + setDraft(taskScheduleDraft(target))} + onDelete={setDeleteTask} + onShowRuns={(target) => setRunsTaskId(target.id)} + /> + ))} +
+ )} - {suggestions} + {suggestions} - {agents.length === 0 ? ( -

- Connect an agent to create schedules. -

- ) : null} - - )} + {agents.length === 0 ? ( +

+ Connect an agent to create schedules. +

+ ) : null} + + )} - setDraft(null)} - onSave={() => void saveDraft()} - /> + setDraft(null)} + onSave={() => void saveDraft()} + /> - dateTimeFormatter.format(new Date(iso))} - onOpenRunThread={openRunThread} - onClose={() => setRunsTaskId(null)} - /> + dateTimeFormatter.format(new Date(iso))} + onOpenRunThread={openRunThread} + onClose={() => setRunsTaskId(null)} + /> - This removes the schedule and its latest result from this device.} - confirmLabel={t`Delete`} - onClose={() => setDeleteTask(null)} - onConfirm={() => { - if (!deleteTask) return; - const id = deleteTask.id; - setDeleteTask(null); - void readBridge() - .deleteSchedule({ id }) - .then(() => setTasks((current) => current.filter((task) => task.id !== id))) - .catch((deleteError: unknown) => - setError(deleteError instanceof Error ? deleteError.message : String(deleteError)), - ); - }} - /> + This removes the schedule and its latest result from this device.} + confirmLabel={t`Delete`} + onClose={() => setDeleteTask(null)} + onConfirm={() => { + if (!deleteTask) return; + const id = deleteTask.id; + setDeleteTask(null); + void readBridge() + .deleteSchedule({ id }) + .then(() => setTasks((current) => current.filter((task) => task.id !== id))) + .catch((deleteError: unknown) => + setError( + deleteError instanceof Error ? deleteError.message : String(deleteError), + ), + ); + }} + /> + + )} ); } diff --git a/src/renderer/views/SchedulesView/parts/PreviousRunsModal.tsx b/src/renderer/views/SchedulesView/parts/PreviousRunsModal.tsx index 2f67a27ab..bba5a0a12 100644 --- a/src/renderer/views/SchedulesView/parts/PreviousRunsModal.tsx +++ b/src/renderer/views/SchedulesView/parts/PreviousRunsModal.tsx @@ -1,7 +1,7 @@ import { useEffect, useState } from "react"; import { Modal } from "@heroui/react"; import { Trans, useLingui } from "@lingui/react/macro"; -import { CheckCircle2, CircleSlash, Loader2, XCircle } from "lucide-react"; +import { CheckCircle2, CircleSlash, Clock3, Loader2, XCircle } from "lucide-react"; import type { ScheduledTask, ScheduledTaskRun } from "@/shared/contracts"; import { readBridge } from "@/renderer/bridge"; import { ThreadProviderIcon } from "@/renderer/components/providers/ThreadProviderIcon"; @@ -21,6 +21,9 @@ function RunStatusIcon({ status, label }: { status: ScheduledTaskRun["status"]; if (status === "running") { return ; } + if (status === "waiting-for-approval") { + return ; + } if (status === "succeeded") { return ; } @@ -65,6 +68,10 @@ function RunRow({ const errorLine = run.error ? (

{run.error}

) : null; + const summary = run.result?.summary ?? run.summary; + const summaryLine = summary ? ( +

{summary}

+ ) : null; if (!thread) { // The linked thread was deleted: nothing to navigate to (openRunThread @@ -73,6 +80,7 @@ function RunRow({
{trailing}
{errorLine} + {summaryLine}
); } @@ -89,6 +97,7 @@ function RunRow({ {trailing}
{errorLine} + {summaryLine} ); } @@ -143,11 +152,17 @@ export function PreviousRunsModal({ switch (status) { case "running": return t`Running`; + case "waiting-for-approval": + return t`Waiting for approval`; case "succeeded": return t`Succeeded`; case "failed": return t`Failed`; - default: + case "cancelled": + return t`Cancelled`; + case "skipped": + return t`Skipped`; + case "interrupted": return t`Interrupted`; } } diff --git a/src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.test.tsx b/src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.test.tsx new file mode 100644 index 000000000..76d72b8a1 --- /dev/null +++ b/src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.test.tsx @@ -0,0 +1,117 @@ +// @vitest-environment jsdom +import { fireEvent, screen } from "@testing-library/react"; +import { describe, expect, it, vi } from "vitest"; +import type { Thread } from "@/shared/contracts"; +import { HOME_PROJECT_ID } from "@/shared/homeScope"; +import { renderWithI18n as render } from "@/renderer/testUtils/i18n"; +import { newScheduleDraft, type ScheduleDraft } from "../scheduleDraft"; +import { ScheduleExecutionSection } from "./ScheduleExecutionSection"; + +function thread(overrides: Partial = {}): Thread { + return { + id: "thread-1", + projectId: HOME_PROJECT_ID, + title: "Release preparation", + agentKind: "claude:home", + config: { model: "claude-fable-5" }, + status: "idle", + attention: "none", + canResumeWithConfig: false, + archived: false, + done: false, + starred: false, + presentationMode: "gui", + createdAt: "2026-07-10T08:00:00.000Z", + updatedAt: "2026-07-10T09:00:00.000Z", + ...overrides, + }; +} + +function draft(overrides: Partial = {}): ScheduleDraft { + return { + ...newScheduleDraft(undefined), + agentKind: "claude:home", + ...overrides, + }; +} + +describe("ScheduleExecutionSection", () => { + it("shows common single-pass guardrails without heartbeat-only completion controls", () => { + render( + undefined} />, + ); + + expect(screen.getByLabelText("Execution mode")).toBeInTheDocument(); + expect(screen.getByLabelText("Time limit in minutes")).toBeInTheDocument(); + expect(screen.getByLabelText("Missed runs")).toBeInTheDocument(); + expect(screen.getByLabelText("Retry policy")).toBeInTheDocument(); + expect(screen.queryByLabelText("Conversation")).not.toBeInTheDocument(); + expect(screen.getByLabelText("Maximum iterations")).toBeInTheDocument(); + expect(screen.getByLabelText("Stop on error")).toBeInTheDocument(); + expect(screen.queryByLabelText("AI stop condition")).not.toBeInTheDocument(); + }); + + it("shows the scoped conversation and every configured heartbeat policy", () => { + render( + undefined} + />, + ); + + expect(screen.getByLabelText("Conversation")).toHaveTextContent("Release preparation"); + expect(screen.getByLabelText("Maximum attempts")).toBeInTheDocument(); + expect(screen.getByLabelText("Initial retry delay in seconds")).toBeInTheDocument(); + expect(screen.getByLabelText("Maximum retry delay in seconds")).toBeInTheDocument(); + expect(screen.getByLabelText("Maximum iterations")).toBeInTheDocument(); + expect(screen.getByLabelText("Stop on error")).toBeInTheDocument(); + expect(screen.getByLabelText("Stop when")).toHaveValue("The release is ready."); + expect(screen.getByLabelText("Confidence percent")).toBeInTheDocument(); + }); + + it("selects the newest eligible conversation when heartbeat is enabled", async () => { + const onChange = vi.fn<(patch: Partial) => void>(); + render( + , + ); + + fireEvent.click(screen.getByLabelText("Execution mode")); + fireEvent.click(await screen.findByRole("option", { name: "Heartbeat" })); + + expect(onChange).toHaveBeenCalledWith({ + automationMode: "heartbeat", + heartbeatTargetThreadId: "newer", + }); + }); + + it("explains when no compatible conversation exists", () => { + render( + undefined} + />, + ); + + expect(screen.getByText("No eligible conversations in this project.")).toBeInTheDocument(); + }); +}); diff --git a/src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx b/src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx new file mode 100644 index 000000000..8dfb63728 --- /dev/null +++ b/src/renderer/views/SchedulesView/parts/ScheduleExecutionSection.tsx @@ -0,0 +1,335 @@ +import type { ReactNode } from "react"; +import { Input, TextArea, TextField } from "@heroui/react"; +import { Trans, useLingui } from "@lingui/react/macro"; +import type { Thread } from "@/shared/contracts"; +import { Select, ToggleSwitch } from "@/renderer/components/common"; +import { + isHeartbeatTargetThread, + type ScheduleAutomationMode, + type ScheduleCompletionKind, + type ScheduleDraft, + type ScheduleRetryKind, +} from "../scheduleDraft"; + +const CONTROL_WIDTH = "w-[280px] max-w-[60%] shrink-0"; + +function ExecutionRow(props: { label: ReactNode; description?: ReactNode; children: ReactNode }) { + return ( +
+
+

{props.label}

+ {props.description ?

{props.description}

: null} +
+
{props.children}
+
+ ); +} + +/** A numeric input paired with a fixed unit suffix (minutes / seconds / %). */ +function NumberWithSuffix(props: { + ariaLabel: string; + value: string; + onChange: (value: string) => void; + min: string; + max: string; + step?: string; + suffix: ReactNode; +}) { + return ( +
+ + + + {props.suffix} +
+ ); +} + +export function ScheduleExecutionSection(props: { + draft: ScheduleDraft; + threads: Thread[]; + onChange: (patch: Partial) => void; +}) { + const { t } = useLingui(); + const { draft } = props; + const conversationOptions = props.threads + .filter((thread) => isHeartbeatTargetThread(thread, draft)) + .toSorted((left, right) => right.updatedAt.localeCompare(left.updatedAt)) + .map((thread) => ({ id: thread.id, label: thread.title })); + const targetIsUnavailable = + draft.heartbeatTargetThreadId !== "" && + !conversationOptions.some((option) => option.id === draft.heartbeatTargetThreadId); + const targetOptions = targetIsUnavailable + ? [ + ...conversationOptions, + { id: draft.heartbeatTargetThreadId, label: t`Unavailable conversation` }, + ] + : conversationOptions; + const heartbeat = draft.automationMode === "heartbeat"; + + return ( +
+
+

+ Execution +

+

+ {heartbeat ? ( + + Heartbeats can continue making changes while you're away. Set hard limits below. + + ) : ( + Control how each scheduled run continues and stops. + )} +

+
+
+ Execution mode} + description={ + heartbeat + ? t`Continue one conversation until a stop condition or limit is reached.` + : t`Start a new conversation for each run.` + } + > + props.onChange({ heartbeatTargetThreadId })} + /> + ) : ( +

+ No eligible conversations in this project. +

+ )} +
+ ) : null} + + Time limit} + description={Stop the run when this total time is reached.} + > + props.onChange({ maxRuntimeMinutes })} + min="1" + max="1440" + step="any" + suffix={minutes} + /> + + + Missed runs} + description={Choose what happens after a scheduled time was missed.} + > + props.onChange({ retryKind: retryKind as ScheduleRetryKind })} + /> + + + {draft.retryKind !== "none" ? ( + Maximum attempts} + description={Includes the first attempt.} + > + props.onChange({ retryMaxAttempts })} + > + + + + ) : null} + + {draft.retryKind === "fixed" ? ( + Retry delay}> + props.onChange({ retryDelaySeconds })} + min="1" + max="3600" + suffix={seconds} + /> + + ) : draft.retryKind === "exponential" ? ( + <> + Initial retry delay}> + + props.onChange({ retryInitialDelaySeconds }) + } + min="1" + max="3600" + suffix={seconds} + /> + + Maximum retry delay}> + props.onChange({ retryMaxDelaySeconds })} + min="1" + max="3600" + suffix={seconds} + /> + + + ) : null} + + Maximum iterations} + description={Leave blank for no run limit.} + > + props.onChange({ maxIterations })} + > + + + + Stop on error} + description={Disable the automation after retries are exhausted.} + > + props.onChange({ stopOnError })} + /> + + + {heartbeat ? ( + <> + AI stop condition} + description={Evaluate the result after every iteration.} + > + + props.onChange({ + completionKind: (selected ? "ai-evaluated" : "none") as ScheduleCompletionKind, + }) + } + /> + + {draft.completionKind === "ai-evaluated" ? ( + <> + Stop when} + description={Describe the result that completes this heartbeat.} + > + props.onChange({ stopWhen })} + > +