diff --git a/apps/extension/entrypoints/sidepanel/agents-new-session.test.ts b/apps/extension/entrypoints/sidepanel/agents-new-session.test.ts
index 77ad8b2d87..5c88e09614 100644
--- a/apps/extension/entrypoints/sidepanel/agents-new-session.test.ts
+++ b/apps/extension/entrypoints/sidepanel/agents-new-session.test.ts
@@ -1,3 +1,4 @@
+import { CLOUD_AGENT_PROMPT_MAX_LENGTH } from '@kilocode/cloud-agent-sdk/limits';
import { describe, expect, it, vi } from 'vitest';
import {
@@ -73,8 +74,8 @@ describe('constants', () => {
expect(PROMPT_MIN_LENGTH).toBe(3);
});
- it('promptMaxLength is 4000', () => {
- expect(PROMPT_MAX_LENGTH).toBe(4000);
+ it('promptMaxLength is the shared cloud agent prompt cap', () => {
+ expect(PROMPT_MAX_LENGTH).toBe(CLOUD_AGENT_PROMPT_MAX_LENGTH);
});
it('mode is "code"', () => {
diff --git a/apps/extension/entrypoints/sidepanel/agents-new-session.tsx b/apps/extension/entrypoints/sidepanel/agents-new-session.tsx
index 96869881d5..2395304f52 100644
--- a/apps/extension/entrypoints/sidepanel/agents-new-session.tsx
+++ b/apps/extension/entrypoints/sidepanel/agents-new-session.tsx
@@ -32,6 +32,7 @@ import { fetchModelPreferences } from '@/src/shared/model-preferences-client';
import { isGatewayModelId } from '@/src/shared/model-picker-rows';
import { getModelPreferencesQueryKey } from '@/src/shared/side-panel-query-options';
import { thinkingEffortLabel } from '@/src/shared/kilo-api-client';
+import { CLOUD_AGENT_PROMPT_MAX_LENGTH } from '@kilocode/cloud-agent-sdk/limits';
import type { KiloGatewayModelOption } from '@/src/shared/kilo-api-client';
import { useExtensionAgents } from './agents-provider';
import { activeSessionsQueryKey, sessionHistoryQueryKey } from './agents-session-list';
@@ -43,7 +44,7 @@ import { useGatewayModels } from './use-gateway-models';
// ---------------------------------------------------------------------------
const PROMPT_MIN_LENGTH = 3;
-const PROMPT_MAX_LENGTH = 4000;
+const PROMPT_MAX_LENGTH = CLOUD_AGENT_PROMPT_MAX_LENGTH;
const MODE = 'code' as const;
/**
diff --git a/apps/mobile/AGENTS.md b/apps/mobile/AGENTS.md
index 5e259f6f74..36d657321f 100644
--- a/apps/mobile/AGENTS.md
+++ b/apps/mobile/AGENTS.md
@@ -68,6 +68,7 @@ git diff --check
- iOS: never control text with `value` plus state. Store text in a ref via `onChangeText`, use state only for derived UI, read the ref on submit.
- Use `defaultValue` only for initial content.
- Single-line inputs: use `leading-[normal]`. A `lineHeight` above the font's natural one (which `text-sm`/`text-base` set on their own) makes iOS draw the placeholder lower than the typed text and clip it. Multi-line inputs keep an explicit `leading-*`.
+- Single-line inputs: set the height with `min-h-*`, not `py-*`. iOS insets the already-centered text rect by the padding, so vertical padding draws the text and the placeholder low.
- Put input screens in a `ScrollView` with `automaticallyAdjustKeyboardInsets`.
## UI and UX Rules
diff --git a/apps/mobile/src/components/agents/chat-composer-input-row.tsx b/apps/mobile/src/components/agents/chat-composer-input-row.tsx
index edbe988e10..9b878c3949 100644
--- a/apps/mobile/src/components/agents/chat-composer-input-row.tsx
+++ b/apps/mobile/src/components/agents/chat-composer-input-row.tsx
@@ -1,4 +1,5 @@
import { ArrowUp, Paperclip, Square } from '@/components/ui/icons';
+import { CLOUD_AGENT_PROMPT_MAX_LENGTH } from '@kilocode/cloud-agent-sdk/limits';
import { type RefObject } from 'react';
import { useTranslation } from 'react-i18next';
import {
@@ -119,7 +120,7 @@ export function ChatComposerInputRow({
placeholder={placeholder}
placeholderTextColor={colors.mutedForeground}
multiline
- maxLength={4000}
+ maxLength={CLOUD_AGENT_PROMPT_MAX_LENGTH}
onChangeText={onChangeText}
onFocus={onInputFocus}
onBlur={onInputBlur}
diff --git a/apps/mobile/src/components/agents/chat-composer.tsx b/apps/mobile/src/components/agents/chat-composer.tsx
index 21bcbd5863..cb90212fa9 100644
--- a/apps/mobile/src/components/agents/chat-composer.tsx
+++ b/apps/mobile/src/components/agents/chat-composer.tsx
@@ -6,6 +6,7 @@
import * as Haptics from 'expo-haptics';
import { useActionSheet } from '@expo/react-native-action-sheet';
import { type SlashCommandInfo } from '@kilocode/cloud-agent-sdk';
+import { CLOUD_AGENT_PROMPT_MAX_LENGTH } from '@kilocode/cloud-agent-sdk/limits';
import { type RemoteCommandState } from '@kilocode/cloud-agent-sdk/remote-command-catalog';
import {
type Ref,
@@ -474,7 +475,7 @@ export function ChatComposer({
useSharePrefill({
shareId,
inputRef,
- maxLength: 4000,
+ maxLength: CLOUD_AGENT_PROMPT_MAX_LENGTH,
onChangeText: handleChangeText,
addCandidates,
onDelivered: () => {
@@ -500,7 +501,7 @@ export function ChatComposer({
applyVoiceDraftToInput({
input: inputRef.current,
draft,
- maxLength: 4000,
+ maxLength: CLOUD_AGENT_PROMPT_MAX_LENGTH,
onChangeText: handleChangeText,
});
},
@@ -537,7 +538,7 @@ export function ChatComposer({
input: inputRef.current,
draft: textRef.current,
selection: selectionRef.current,
- maxLength: 4000,
+ maxLength: CLOUD_AGENT_PROMPT_MAX_LENGTH,
onChangeText: handleChangeText,
});
},
diff --git a/apps/mobile/src/components/agents/new-session-configure-form.test.ts b/apps/mobile/src/components/agents/new-session-configure-form.test.ts
index 48aefec66a..a296fdac63 100644
--- a/apps/mobile/src/components/agents/new-session-configure-form.test.ts
+++ b/apps/mobile/src/components/agents/new-session-configure-form.test.ts
@@ -548,4 +548,29 @@ describe('NewSessionConfigureForm', () => {
expect(findElementByType(element, 'SegmentedControl')).toBeNull();
expect(findTextContent(element, t => t === 'Changes')).toBe(false);
});
+
+ // ── Case 12: kilo remote hint ──
+ it('names both `kilo remote` and `/remote` for cloud and remote targets', async () => {
+ const { NewSessionConfigureForm } = await import('./new-session-configure-form');
+
+ // eslint-disable-next-line new-cap -- plain function call, matching repo test convention
+ const cloud = NewSessionConfigureForm({
+ ...defaultProps(),
+ runOnInstance: null,
+ showRunOnSelector: true,
+ }) as Node;
+ expect(findTextContent(cloud, t => t.includes('kilo remote') && t.includes('/remote'))).toBe(
+ true
+ );
+
+ // eslint-disable-next-line new-cap -- plain function call, matching repo test convention
+ const remote = NewSessionConfigureForm({
+ ...defaultProps(),
+ runOnInstance: INSTANCE,
+ showRunOnSelector: false,
+ }) as Node;
+ expect(findTextContent(remote, t => t.includes('kilo remote') && t.includes('/remote'))).toBe(
+ true
+ );
+ });
});
diff --git a/apps/mobile/src/components/agents/new-session-configure-form.tsx b/apps/mobile/src/components/agents/new-session-configure-form.tsx
index 7652de02ea..f5677b4c9c 100644
--- a/apps/mobile/src/components/agents/new-session-configure-form.tsx
+++ b/apps/mobile/src/components/agents/new-session-configure-form.tsx
@@ -252,6 +252,10 @@ export function NewSessionConfigureForm({
{runTargetBlock}
+
+ {t('agentChat.newSession.remoteHint')}
+
+
{showInstanceDisconnectedNote ? (
{remoteSpawnInstanceDisconnectedNote()}
diff --git a/apps/mobile/src/components/agents/new-session-prompt.tsx b/apps/mobile/src/components/agents/new-session-prompt.tsx
index b1247b2d67..54abe70388 100644
--- a/apps/mobile/src/components/agents/new-session-prompt.tsx
+++ b/apps/mobile/src/components/agents/new-session-prompt.tsx
@@ -1,3 +1,4 @@
+import { CLOUD_AGENT_PROMPT_MAX_LENGTH } from '@kilocode/cloud-agent-sdk/limits';
import { useCallback, useEffect, useRef, useState } from 'react';
import {
type LayoutChangeEvent,
@@ -45,7 +46,7 @@ const PROMPT_INPUT_LINE_HEIGHT = 24;
const PROMPT_INPUT_VERTICAL_PADDING = 16;
const PROMPT_INPUT_HORIZONTAL_PADDING = Platform.OS === 'android' ? 48 : 16;
const PROMPT_INPUT_ANDROID_HORIZONTAL_INSET = 24;
-const PROMPT_INPUT_MAX_CHARS = 4000;
+const PROMPT_INPUT_MAX_CHARS = CLOUD_AGENT_PROMPT_MAX_LENGTH;
const PROMPT_INPUT_MIN_HEIGHT =
PROMPT_INPUT_LINE_HEIGHT * PROMPT_INPUT_DEFAULT_LINES + PROMPT_INPUT_VERTICAL_PADDING;
const PROMPT_INPUT_MAX_HEIGHT =
diff --git a/apps/mobile/src/components/agents/use-remote-spawn-dispatch.test.ts b/apps/mobile/src/components/agents/use-remote-spawn-dispatch.test.ts
index 3a0d649907..5ad374de1a 100644
--- a/apps/mobile/src/components/agents/use-remote-spawn-dispatch.test.ts
+++ b/apps/mobile/src/components/agents/use-remote-spawn-dispatch.test.ts
@@ -1,7 +1,7 @@
/* eslint-disable max-lines -- spawn-input, navigation, and admission suites share the hook harness. */
import * as React from 'react';
import { beforeEach, describe, expect, it, vi } from 'vitest';
-import { type ModelSelection } from '@kilocode/cloud-agent-sdk';
+import { type KiloSessionId, type ModelSelection } from '@kilocode/cloud-agent-sdk';
import { type InstancePickerInstance } from '@/lib/picker-bridge';
import {
@@ -9,17 +9,21 @@ import {
peekSharePayload,
type SharePayload,
} from '@/lib/share-payload';
-import { buildCreateRemoteSessionInput } from '@/lib/hooks/remote-instance-spawn-classifier';
+import {
+ buildCreateRemoteSessionInput,
+ type CreateSessionOutcome,
+} from '@/lib/hooks/remote-instance-spawn-classifier';
import { remoteSpawnFilesNotSupportedToast } from '@/lib/remote-spawn-admission';
+import { remoteSpawnRetryableToast } from '@/lib/remote-submit-outcome';
import { useRemoteSpawnDispatch } from './use-remote-spawn-dispatch';
const spawnMock = vi.hoisted(() =>
- vi.fn(async () => {
+ vi.fn(async (): Promise => {
await Promise.resolve();
return {
status: 'ready' as const,
- sessionID: 'ses_12345678901234567890123456',
+ sessionID: 'ses_12345678901234567890123456' as KiloSessionId,
};
})
);
@@ -125,7 +129,11 @@ function runHook(args: {
selection?: ModelSelection;
getSubmitPayload?: () => SharePayload | null;
onSpawnAdmitted?: () => void;
+ onSpawnFailed?: () => void;
runOnInstance?: InstancePickerInstance | null;
+ setRunOnInstance?: (next: InstancePickerInstance | null) => void;
+ refetchInstances?: () => Promise<{ data: { instances: InstancePickerInstance[] } | undefined }>;
+ instanceList?: InstancePickerInstance[];
}) {
const reactInternals = React as typeof React & ReactInternals;
const hookState: unknown[] = [];
@@ -170,30 +178,50 @@ function runHook(args: {
},
};
- const previousDispatcher =
- reactInternals.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE.H;
- hookIndex = 0;
- refIndex = 0;
- reactInternals.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE.H = dispatcher;
- try {
- const mountDispatch = useRemoteSpawnDispatch;
- return mountDispatch({
- organizationId: args.organizationId,
- mode: args.mode,
- selection: args.selection,
- runOnInstance: args.runOnInstance === undefined ? INSTANCE : args.runOnInstance,
- // eslint-disable-next-line no-empty-function -- no-op setter for harness
- setRunOnInstance: (_next: InstancePickerInstance | null) => {},
- // eslint-disable-next-line promise-function-async, prefer-await-to-then -- tension between lint rules
- refetchInstances: () => Promise.resolve({ data: { instances: [INSTANCE] } }),
- instanceList: [INSTANCE],
- getSubmitPayload: args.getSubmitPayload,
- onSpawnAdmitted: args.onSpawnAdmitted,
- });
- } finally {
- reactInternals.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE.H =
- previousDispatcher;
- }
+ // `runOnInstance` is parent state in the real route: `setRunOnInstance`
+ // re-renders the hook with the new value so the `runOnInstanceRef` effect
+ // sees it. Mirror that here; otherwise the async tail's remap would leave
+ // the ref on the stale press-time id and the reset guard (which reads the
+ // ref) could never be exercised by a remap test.
+ let currentRunOnInstance: InstancePickerInstance | null =
+ args.runOnInstance === undefined ? INSTANCE : args.runOnInstance;
+
+ const render = () => {
+ hookIndex = 0;
+ refIndex = 0;
+ const previousDispatcher =
+ reactInternals.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE.H;
+ reactInternals.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE.H = dispatcher;
+ try {
+ const mountDispatch = useRemoteSpawnDispatch;
+ return mountDispatch({
+ organizationId: args.organizationId,
+ mode: args.mode,
+ selection: args.selection,
+ runOnInstance: currentRunOnInstance,
+ setRunOnInstance: next => {
+ args.setRunOnInstance?.(next);
+ if (next !== currentRunOnInstance) {
+ currentRunOnInstance = next;
+ render();
+ }
+ },
+ refetchInstances:
+ args.refetchInstances ??
+ // eslint-disable-next-line promise-function-async, prefer-await-to-then -- tension between lint rules
+ (() => Promise.resolve({ data: { instances: [INSTANCE] } })),
+ instanceList: args.instanceList ?? [INSTANCE],
+ getSubmitPayload: args.getSubmitPayload,
+ onSpawnAdmitted: args.onSpawnAdmitted,
+ onSpawnFailed: args.onSpawnFailed,
+ });
+ } finally {
+ reactInternals.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE.H =
+ previousDispatcher;
+ }
+ };
+
+ return render();
}
describe('useRemoteSpawnDispatch spawn input chain', () => {
@@ -428,3 +456,131 @@ describe('useRemoteSpawnDispatch spawn input chain', () => {
expect(spawnMock).not.toHaveBeenCalled();
});
});
+
+describe('useRemoteSpawnDispatch live-instance remap', () => {
+ const LIVE_INSTANCE: InstancePickerInstance = {
+ connectionId: 'conn-live',
+ name: 'laptop',
+ projectName: 'kilo',
+ };
+
+ beforeEach(() => {
+ spawnMock.mockClear();
+ useRemoteInstanceSpawnMock.mockClear();
+ routerReplace.mockClear();
+ toastErrorMock.mockClear();
+ __resetSharePayloadStoreForTests();
+ });
+
+ it('spawns with the same connectionId when the refetched list still has it', async () => {
+ const { onStart } = runHook({
+ organizationId: 'org-xyz',
+ // eslint-disable-next-line promise-function-async, prefer-await-to-then -- tension between lint rules
+ refetchInstances: () => Promise.resolve({ data: { instances: [INSTANCE] } }),
+ });
+
+ expect(await captureSpawnCall(onStart)).toEqual([
+ 'conn-abc',
+ { orgId: 'org-xyz' },
+ { operationKey: expect.any(String) },
+ ]);
+ });
+
+ it('remaps to the live connectionId when the id changed but name + project match', async () => {
+ const setRunOnInstanceMock = vi.fn();
+ const { onStart } = runHook({
+ organizationId: 'org-xyz',
+ setRunOnInstance: next => {
+ setRunOnInstanceMock(next);
+ },
+ // eslint-disable-next-line promise-function-async, prefer-await-to-then -- tension between lint rules
+ refetchInstances: () => Promise.resolve({ data: { instances: [LIVE_INSTANCE] } }),
+ });
+
+ expect(await captureSpawnCall(onStart)).toEqual([
+ 'conn-live',
+ { orgId: 'org-xyz' },
+ { operationKey: expect.any(String) },
+ ]);
+ expect(setRunOnInstanceMock).toHaveBeenCalledWith(LIVE_INSTANCE);
+ });
+
+ it('falls back to the last-known instanceList when the refetch throws', async () => {
+ const { onStart } = runHook({
+ organizationId: 'org-xyz',
+ // eslint-disable-next-line promise-function-async, prefer-await-to-then -- tension between lint rules
+ refetchInstances: () => Promise.reject(new Error('network down')),
+ instanceList: [INSTANCE],
+ });
+
+ expect(await captureSpawnCall(onStart)).toEqual([
+ 'conn-abc',
+ { orgId: 'org-xyz' },
+ { operationKey: expect.any(String) },
+ ]);
+ });
+
+ it('keeps the live selection when a remap is followed by a failing post-spawn refetch', async () => {
+ const setRunOnInstanceMock = vi.fn();
+ // First (pre-spawn) refetch resolves the live row so the id remaps; the
+ // second (post-spawn) refetch fails.
+ const refetchInstancesMock = vi
+ .fn()
+ .mockResolvedValueOnce({ data: { instances: [LIVE_INSTANCE] } })
+ .mockRejectedValueOnce(new Error('network down'));
+ spawnMock.mockResolvedValueOnce({
+ status: 'retryable',
+ reason: 'transport failure',
+ cause: new Error('socket gone'),
+ });
+
+ const { onStart } = runHook({
+ organizationId: 'org-xyz',
+ setRunOnInstance: next => {
+ setRunOnInstanceMock(next);
+ },
+ refetchInstances: refetchInstancesMock,
+ instanceList: [INSTANCE],
+ });
+
+ onStart();
+ await vi.waitFor(() => {
+ expect(refetchInstancesMock).toHaveBeenCalledTimes(2);
+ });
+ // Flush the rejected-refetch continuation (outcome classification and the
+ // reset guard) before asserting the selection did not move to null.
+ await new Promise(resolve => {
+ setTimeout(resolve, 0);
+ });
+
+ // The remap applied the live row...
+ expect(setRunOnInstanceMock).toHaveBeenCalledWith(LIVE_INSTANCE);
+ // ...and the failing refetch must not reset the selection to Cloud Agent.
+ expect(setRunOnInstanceMock).toHaveBeenCalledTimes(1);
+ expect(setRunOnInstanceMock).not.toHaveBeenCalledWith(null);
+ });
+
+ it('toasts the retryable copy and calls onSpawnFailed when no live instance resolves', async () => {
+ const onSpawnFailedMock = vi.fn();
+ const setRunOnInstanceMock = vi.fn();
+ const { onStart } = runHook({
+ organizationId: 'org-xyz',
+ setRunOnInstance: next => {
+ setRunOnInstanceMock(next);
+ },
+ // eslint-disable-next-line promise-function-async, prefer-await-to-then -- tension between lint rules
+ refetchInstances: () => Promise.resolve({ data: { instances: [] } }),
+ onSpawnFailed: () => {
+ onSpawnFailedMock();
+ },
+ });
+
+ onStart();
+ await vi.waitFor(() => {
+ expect(onSpawnFailedMock).toHaveBeenCalledTimes(1);
+ });
+ expect(toastErrorMock).toHaveBeenCalledWith(remoteSpawnRetryableToast());
+ expect(spawnMock).not.toHaveBeenCalled();
+ expect(setRunOnInstanceMock).not.toHaveBeenCalled();
+ });
+});
diff --git a/apps/mobile/src/components/agents/use-remote-spawn-dispatch.ts b/apps/mobile/src/components/agents/use-remote-spawn-dispatch.ts
index 904c4b9b72..75b4359d27 100644
--- a/apps/mobile/src/components/agents/use-remote-spawn-dispatch.ts
+++ b/apps/mobile/src/components/agents/use-remote-spawn-dispatch.ts
@@ -14,6 +14,7 @@ import {
useRemoteInstanceSpawn,
} from '@/lib/hooks/use-remote-instance-spawn';
import { useHoistedOperationKey } from '@/lib/operation-key';
+import { resolveLiveInstance } from '@/lib/resolve-live-instance';
import {
remoteSpawnNonRetryableToast,
remoteSpawnRetryableToast,
@@ -158,6 +159,10 @@ export function useRemoteSpawnDispatch({
) => Promise;
} = useRemoteInstanceSpawn(organizationId ?? null);
const [showInstanceDisconnectedNote, setShowInstanceDisconnectedNote] = useState(false);
+ // `true` while `onStart`'s async head refetches the instance list and
+ // resolves the live instance (a rebooted host's new connectionId). Surfaced
+ // so the route keeps the Start button disabled during that window.
+ const [isResolvingInstance, setIsResolvingInstance] = useState(false);
// P1-A-08b: one `operationKey` per spawn intent, so a retryable failure keeps
// the key and the relay dedupes the retry.
const { getKey, rotateKey } = useHoistedOperationKey();
@@ -193,7 +198,6 @@ export function useRemoteSpawnDispatch({
if (runOnInstance === null) {
return;
}
- const selectedConnectionId = runOnInstance.connectionId;
const fields = spawnFieldsRef.current;
// Press-time snapshot. Read once, here, before any await.
const submitPayload = getSubmitPayloadRef.current?.() ?? null;
@@ -214,76 +218,114 @@ export function useRemoteSpawnDispatch({
selection: fields.selection,
organizationId: fields.organizationId,
});
- const operationKey = getKey(
- JSON.stringify({
- connectionId: selectedConnectionId,
- mode: fields.mode,
- selection: fields.selection,
- organizationId: fields.organizationId,
- })
- );
void (async () => {
- const outcome = await remoteSpawn.spawn(selectedConnectionId, createInput, { operationKey });
- if (outcome.status === 'ready') {
- // The spawn settled; the next submit is a fresh intent.
- rotateKey();
- const spawnedPath = getSpawnedAgentSessionPath(outcome.sessionID, organizationId);
- if (submitPayload === null) {
- router.replace(spawnedPath);
+ setIsResolvingInstance(true);
+ try {
+ // Refetch the live instance list so a rebooted host's new
+ // connectionId replaces the stale selection before spawn.
+ let freshList = instanceList;
+ try {
+ const result = await refetchInstances();
+ freshList = result.data?.instances ?? instanceList;
+ } catch {
+ // Refetch failed; continue with the last-known list.
+ }
+ const live = resolveLiveInstance(runOnInstance, freshList);
+ if (live === null) {
+ // No live row matches the selection (neither the connectionId nor
+ // the name + projectName pair). Surface the retryable copy and let
+ // the next Start tap re-resolve against a refreshed list.
+ toast.error(remoteSpawnRetryableToast());
+ onSpawnFailedRef.current?.();
return;
}
- const shareId = putSharePayload(submitPayload);
- router.replace(
- appendShareParams(spawnedPath as string, shareId, {
- autoSend: true,
+ const selectedConnectionId = live.connectionId;
+ // A rebooted host advertises the same name + projectName on a new
+ // connectionId. Remap the selection to the live row so the spawn and
+ // a later refetch agree. The unchanged-id case keeps the same id and
+ // the same hoisted operation key.
+ if (live.connectionId !== runOnInstance.connectionId) {
+ setRunOnInstance(live);
+ }
+ const operationKey = getKey(
+ JSON.stringify({
+ connectionId: selectedConnectionId,
mode: fields.mode,
- }) as Href
+ selection: fields.selection,
+ organizationId: fields.organizationId,
+ })
);
- return;
- }
- // Not ready: the spawn settled without navigating. Re-arm the caller's
- // abandon guard so a later back/swipe still confirms.
- onSpawnFailedRef.current?.();
- if (outcome.status === 'nonRetryable') {
- // A typed non-retryable rejection ends the intent.
- rotateKey();
- toast.error(remoteSpawnNonRetryableToast());
- return;
- }
- // outcome.status === 'retryable': refetch the instance list and
- // re-evaluate whether the previously-selected instance is still
- // present.
- toast.error(remoteSpawnRetryableToast());
- let refetchedInstances: InstancePickerInstance[] = instanceList;
- try {
- const result = await refetchInstances();
- refetchedInstances = result.data?.instances ?? instanceList;
- } catch {
- // Refetch failed; fall through with the last-known list. The
- // mapping helper treats an empty list as "disconnected", which
- // is the right conservative default for a network blip.
- }
- const action = resolveRemoteSubmitOutcome({
- outcome,
- refetchedInstances,
- selectedConnectionId,
- });
- if (action.kind !== 'retryable') {
- // Defensive: outcome.status === 'retryable' must produce a
- // retryable action. If this ever changes we'll want to know.
- return;
- }
- // kilocode_change - only apply the reset if the selection this
- // dispatch was FOR is still the CURRENT one (read from the ref, not
- // the closure-captured `runOnInstance` — see the ref's comment
- // above). Without this check, a stale tail's reset could clobber a
- // newer, unrelated selection the user already made.
- if (
- action.shouldResetSelectionToCloudAgent &&
- runOnInstanceRef.current?.connectionId === selectedConnectionId
- ) {
- setRunOnInstance(null);
- setShowInstanceDisconnectedNote(action.showInstanceDisconnectedNote);
+ const outcome = await remoteSpawn.spawn(selectedConnectionId, createInput, {
+ operationKey,
+ });
+ if (outcome.status === 'ready') {
+ // The spawn settled; the next submit is a fresh intent.
+ rotateKey();
+ const spawnedPath = getSpawnedAgentSessionPath(outcome.sessionID, organizationId);
+ if (submitPayload === null) {
+ router.replace(spawnedPath);
+ return;
+ }
+ const shareId = putSharePayload(submitPayload);
+ router.replace(
+ appendShareParams(spawnedPath as string, shareId, {
+ autoSend: true,
+ mode: fields.mode,
+ }) as Href
+ );
+ return;
+ }
+ // Not ready: the spawn settled without navigating. Re-arm the caller's
+ // abandon guard so a later back/swipe still confirms.
+ onSpawnFailedRef.current?.();
+ if (outcome.status === 'nonRetryable') {
+ // A typed non-retryable rejection ends the intent.
+ rotateKey();
+ toast.error(remoteSpawnNonRetryableToast());
+ return;
+ }
+ // outcome.status === 'retryable': refetch the instance list and
+ // re-evaluate whether the previously-selected instance is still
+ // present.
+ toast.error(remoteSpawnRetryableToast());
+ // Seed from the fresh pre-spawn list, not the press-time
+ // `instanceList`: if the spawn remapped the selection to a live
+ // connectionId above, the press-time list still holds the stale id. A
+ // post-spawn refetch throw would then make the live id look missing
+ // and reset the selection to Cloud Agent even though the host is live.
+ let refetchedInstances: InstancePickerInstance[] = freshList;
+ try {
+ const result = await refetchInstances();
+ refetchedInstances = result.data?.instances ?? freshList;
+ } catch {
+ // Refetch failed; fall through with the fresh pre-spawn list. The
+ // mapping helper treats an empty list as "disconnected", which
+ // is the right conservative default for a network blip.
+ }
+ const action = resolveRemoteSubmitOutcome({
+ outcome,
+ refetchedInstances,
+ selectedConnectionId,
+ });
+ if (action.kind !== 'retryable') {
+ // Defensive: outcome.status === 'retryable' must produce a
+ // retryable action. If this ever changes we'll want to know.
+ return;
+ }
+ // kilocode_change - only apply the reset if the selection this
+ // dispatch was FOR is still the CURRENT one (read from the ref, not
+ // the closure-captured `runOnInstance` — see the ref's comment
+ // above). Without this check, a stale tail's reset could clobber a
+ // newer, unrelated selection the user already made.
+ if (
+ action.shouldResetSelectionToCloudAgent &&
+ runOnInstanceRef.current?.connectionId === selectedConnectionId
+ ) {
+ setRunOnInstance(null);
+ setShowInstanceDisconnectedNote(action.showInstanceDisconnectedNote);
+ }
+ } finally {
+ setIsResolvingInstance(false);
}
})();
}, [
@@ -309,7 +351,7 @@ export function useRemoteSpawnDispatch({
);
return {
- isSpawningRemote: remoteSpawn.status.status === 'inFlight',
+ isSpawningRemote: remoteSpawn.status.status === 'inFlight' || isResolvingInstance,
showInstanceDisconnectedNote,
onStart,
onChangeRunOnInstance,
diff --git a/apps/mobile/src/components/home/agent-sessions-section.test.ts b/apps/mobile/src/components/home/agent-sessions-section.test.ts
index be0a804419..c2e25dc057 100644
--- a/apps/mobile/src/components/home/agent-sessions-section.test.ts
+++ b/apps/mobile/src/components/home/agent-sessions-section.test.ts
@@ -1,6 +1,6 @@
import { describe, expect, it, vi } from 'vitest';
-import { hasDisplayableAgentSessions } from '@/components/home/agent-sessions-section';
+import { buildRows } from '@/components/home/agent-sessions-section';
import { type ActiveSession, type StoredSession } from '@/lib/hooks/use-agent-sessions';
vi.mock('expo-router', () => ({
@@ -20,14 +20,14 @@ vi.mock('@/components/agents/remote-session-row', () => ({
RemoteSessionRow: () => null,
}));
-vi.mock('@/components/agents/session-row', () => ({
- StoredSessionRow: () => null,
-}));
-
vi.mock('@/components/ui/text', () => ({
Text: () => null,
}));
+vi.mock('@/components/agents/session-row', () => ({
+ StoredSessionRow: () => null,
+}));
+
vi.mock('@/lib/hooks/use-agent-sessions', () => ({
useAgentSessions: () => ({
activeSessions: [],
@@ -68,27 +68,59 @@ function makeStored(over: Partial = {}): StoredSession {
};
}
-describe('hasDisplayableAgentSessions', () => {
- it('returns true when there is at least one active session', () => {
- expect(hasDisplayableAgentSessions([], [makeActive()])).toBe(true);
+describe('buildRows', () => {
+ it('yields no rows when there are no live sessions', () => {
+ const rows = buildRows({
+ activeSessions: [],
+ storedSessions: [],
+ activeSessionIds: new Set(),
+ });
+ expect(rows).toEqual([]);
+ });
+
+ it('yields one row for one active session', () => {
+ const active = makeActive();
+ const rows = buildRows({
+ activeSessions: [active],
+ storedSessions: [],
+ activeSessionIds: new Set([active.id]),
+ });
+ expect(rows.map(row => row.key)).toEqual(['active:a1']);
});
- it('returns true when a cloud-agent stored session exists', () => {
- expect(
- hasDisplayableAgentSessions([makeStored({ created_on_platform: 'cloud-agent' })], [])
- ).toBe(true);
- expect(
- hasDisplayableAgentSessions([makeStored({ created_on_platform: 'cloud-agent-web' })], [])
- ).toBe(true);
+ it('caps the rows at three live sessions', () => {
+ const activeSessions = [
+ makeActive({ id: 'a1' }),
+ makeActive({ id: 'a2' }),
+ makeActive({ id: 'a3' }),
+ makeActive({ id: 'a4' }),
+ ];
+ const rows = buildRows({
+ activeSessions,
+ storedSessions: [],
+ activeSessionIds: new Set(['a1', 'a2', 'a3', 'a4']),
+ });
+ expect(rows).toHaveLength(3);
+ expect(rows.every(row => row.kind === 'active')).toBe(true);
});
- it('returns false when only non-cloud-agent stored sessions exist', () => {
- expect(hasDisplayableAgentSessions([makeStored({ created_on_platform: 'cli' })], [])).toBe(
- false
- );
+ it('drops an offline stored session', () => {
+ const offline = makeStored({ session_id: 'off1', created_on_platform: 'cloud-agent' });
+ const rows = buildRows({
+ activeSessions: [],
+ storedSessions: [offline],
+ activeSessionIds: new Set(),
+ });
+ expect(rows).toEqual([]);
});
- it('returns false when both arrays are empty', () => {
- expect(hasDisplayableAgentSessions([], [])).toBe(false);
+ it('keeps a live cloud-agent stored session', () => {
+ const live = makeStored({ session_id: 'on1', created_on_platform: 'cloud-agent' });
+ const rows = buildRows({
+ activeSessions: [],
+ storedSessions: [live],
+ activeSessionIds: new Set(['on1']),
+ });
+ expect(rows.map(row => row.key)).toEqual(['stored:on1']);
});
});
diff --git a/apps/mobile/src/components/home/agent-sessions-section.tsx b/apps/mobile/src/components/home/agent-sessions-section.tsx
index 9778dfe142..c6368f60bf 100644
--- a/apps/mobile/src/components/home/agent-sessions-section.tsx
+++ b/apps/mobile/src/components/home/agent-sessions-section.tsx
@@ -3,9 +3,9 @@ import { useTranslation } from 'react-i18next';
import { View } from 'react-native';
import { RemoteSessionRow } from '@/components/agents/remote-session-row';
-import { useAgentSessionNavigator } from '@/components/agents/use-agent-session-navigator';
import { expandPlatformFilter } from '@/components/agents/session-list-helpers';
import { StoredSessionRow } from '@/components/agents/session-row';
+import { useAgentSessionNavigator } from '@/components/agents/use-agent-session-navigator';
import { SectionHeader } from '@/components/home/section-header';
import { Text } from '@/components/ui/text';
import {
@@ -13,7 +13,9 @@ import {
type StoredSession,
useAgentSessions,
} from '@/lib/hooks/use-agent-sessions';
-import { parseTimestamp } from '@/lib/utils';
+import { cn, parseTimestamp } from '@/lib/utils';
+
+export const HOME_LIVE_SLOT_MIN_CLASS = 'min-h-[72px]';
const MAX_ROWS = 3;
const CLOUD_AGENT_PLATFORMS = new Set(expandPlatformFilter(['cloud-agent']));
@@ -30,7 +32,7 @@ type Row =
session: StoredSession;
};
-function buildRows(params: {
+export function buildRows(params: {
activeSessions: ActiveSession[];
storedSessions: StoredSession[];
activeSessionIds: Set;
@@ -51,7 +53,6 @@ function buildRows(params: {
CLOUD_AGENT_PLATFORMS.has(s.created_on_platform)
);
const live = cloudAgentStored.filter(s => activeSessionIds.has(s.session_id));
- const offline = cloudAgentStored.filter(s => !activeSessionIds.has(s.session_id));
const sortByUpdated = (a: StoredSession, b: StoredSession) =>
parseTimestamp(b.status_updated_at ?? b.updated_at).getTime() -
@@ -68,35 +69,9 @@ function buildRows(params: {
}
}
- // eslint-disable-next-line unicorn/no-array-sort -- Hermes does not implement Array.prototype.toSorted; spread already prevents mutation of the source
- for (const session of [...offline].sort(sortByUpdated)) {
- if (rows.length >= MAX_ROWS) {
- break;
- }
- if (!seenSessionIds.has(session.session_id)) {
- rows.push({ key: `stored:${session.session_id}`, kind: 'stored', session });
- seenSessionIds.add(session.session_id);
- }
- }
-
return rows;
}
-// Whether the Home "Agent sessions" section has anything to render — mirrors
-// buildRows' inclusion rule (any active session, or a cloud-agent stored
-// session; stored CLI/other-platform sessions live on the Agents tab, not
-// Home). The Home screen gates its section/promo/new-task button on this so a
-// CLI-only account shows the first-use promo instead of an empty section.
-export function hasDisplayableAgentSessions(
- storedSessions: StoredSession[],
- activeSessions: ActiveSession[]
-): boolean {
- return (
- activeSessions.length > 0 ||
- storedSessions.some(s => CLOUD_AGENT_PLATFORMS.has(s.created_on_platform))
- );
-}
-
type AgentSessionsSectionProps = {
organizationId: string | null;
};
@@ -104,17 +79,13 @@ type AgentSessionsSectionProps = {
export function AgentSessionsSection({ organizationId }: Readonly) {
const router = useRouter();
const { t } = useTranslation();
- const { activeSessions, storedSessions, activeSessionIds, activeIsError } = useAgentSessions({
+ const { activeSessions, storedSessions, activeSessionIds } = useAgentSessions({
organizationId,
});
const navigateToSession = useAgentSessionNavigator();
const rows = buildRows({ activeSessions, storedSessions, activeSessionIds });
- if (rows.length === 0) {
- return null;
- }
-
return (
- {activeIsError ? (
-
- {t('home.showingSavedSessions')}
-
- ) : null}
+ {rows.length === 0 && }
{rows.map(row => {
if (row.kind === 'active') {
const { session } = row;
return (
);
}
+
+function LiveNowEmpty() {
+ const { t } = useTranslation();
+
+ return (
+
+
+ {t('home.noLiveSessions')}
+
+
+ );
+}
diff --git a/apps/mobile/src/components/home/agents-promo-card.tsx b/apps/mobile/src/components/home/agents-promo-card.tsx
deleted file mode 100644
index 19210df4be..0000000000
--- a/apps/mobile/src/components/home/agents-promo-card.tsx
+++ /dev/null
@@ -1,62 +0,0 @@
-import { type Href, useRouter } from 'expo-router';
-import { useTranslation } from 'react-i18next';
-import { Bot } from '@/components/ui/icons';
-import { DirectionalChevronRight } from '@/components/ui/directional-icons';
-import { Pressable, View } from 'react-native';
-
-import { Text } from '@/components/ui/text';
-import { agentColor } from '@/lib/agent-color';
-import { useThemeColors } from '@/lib/hooks/use-theme-colors';
-import { cn } from '@/lib/utils';
-
-type AgentsPromoCardProps = {
- organizationId: string | null;
-};
-
-export function AgentsPromoCard({ organizationId }: Readonly) {
- const router = useRouter();
- const { t } = useTranslation();
- const colors = useThemeColors();
- const title = t('home.kiloAgents');
- const tint = agentColor('Kilo Agents');
-
- return (
- {
- const path = organizationId
- ? `/(app)/agent-chat/new?organizationId=${organizationId}`
- : '/(app)/agent-chat/new';
- router.push(path as Href);
- }}
- className="mx-4 gap-3 rounded-2xl border border-border bg-card p-4 active:opacity-80"
- accessibilityLabel={t('home.startNewAgentSession')}
- >
-
-
-
-
-
- {title}
-
- {t('home.aiCodingSessions')}
-
-
-
-
- {t('home.startCodingTaskFromPhone')}
-
-
-
- {t('home.tryIt')}
-
-
-
-
- );
-}
diff --git a/apps/mobile/src/components/home/home-screen.mounted.test.tsx b/apps/mobile/src/components/home/home-screen.mounted.test.tsx
index dddb23b39d..7ca7508536 100644
--- a/apps/mobile/src/components/home/home-screen.mounted.test.tsx
+++ b/apps/mobile/src/components/home/home-screen.mounted.test.tsx
@@ -6,10 +6,8 @@ import { describe, expect, it, vi } from 'vitest';
import '@/i18n';
import { HomeScreen } from '@/components/home/home-screen';
-const hasSessions = vi.hoisted(() => ({ value: true }));
const activeIsError = vi.hoisted(() => ({ value: false }));
const storedIsError = vi.hoisted(() => ({ value: false }));
-const storedIsSuccess = vi.hoisted(() => ({ value: true }));
const sessionsLoading = vi.hoisted(() => ({ value: false }));
const orgLoaded = vi.hoisted(() => ({ value: true }));
@@ -29,10 +27,7 @@ vi.mock('react-native-reanimated', () => ({
}));
vi.mock('@/components/home/agent-sessions-section', () => ({
AgentSessionsSection: 'AgentSessionsSection',
- hasDisplayableAgentSessions: () => hasSessions.value,
-}));
-vi.mock('@/components/home/agents-promo-card', () => ({
- AgentsPromoCard: 'AgentsPromoCard',
+ HOME_LIVE_SLOT_MIN_CLASS: 'min-h-[72px]',
}));
vi.mock('@/components/home/greeting', () => ({
buildTimedGreeting: () => 'Good morning',
@@ -61,7 +56,7 @@ vi.mock('@/lib/hooks/use-agent-sessions', () => ({
isLoading: sessionsLoading.value,
storedSessions: [{}],
storedIsError: storedIsError.value,
- storedIsSuccess: storedIsSuccess.value,
+ storedIsSuccess: true,
activeIsError: activeIsError.value,
refetch: vi.fn(),
}),
@@ -98,14 +93,16 @@ async function mountHome(): Promise {
}
describe('HomeScreen composition', () => {
- it('renders the sessions section and new-task button when sessions are present', async () => {
- hasSessions.value = true;
+ it('renders the sessions section and new-task button on an empty load', async () => {
+ storedIsError.value = false;
+ activeIsError.value = false;
sessionsLoading.value = false;
orgLoaded.value = true;
const renderer = await mountHome();
expect(nodeCount(renderer.root, 'AgentSessionsSection')).toBe(1);
expect(nodeCount(renderer.root, 'NewTaskButton')).toBe(1);
expect(nodeCount(renderer.root, 'ProductChoices')).toBe(1);
+ expect(nodeCount(renderer.root, 'AgentsPromoCard')).toBe(0);
expect(nodeCount(renderer.root, 'Skeleton')).toBe(0);
await act(async () => {
@@ -114,19 +111,16 @@ describe('HomeScreen composition', () => {
});
});
- it('renders only the agents promo card when there are no sessions', async () => {
- hasSessions.value = false;
+ it('renders the sessions section and new-task button when sessions are present', async () => {
storedIsError.value = false;
- storedIsSuccess.value = true;
activeIsError.value = false;
sessionsLoading.value = false;
orgLoaded.value = true;
const renderer = await mountHome();
- expect(nodeCount(renderer.root, 'AgentsPromoCard')).toBe(1);
- expect(nodeCount(renderer.root, 'QueryError')).toBe(0);
- expect(nodeCount(renderer.root, 'AgentSessionsSection')).toBe(0);
- expect(nodeCount(renderer.root, 'NewTaskButton')).toBe(0);
+ expect(nodeCount(renderer.root, 'AgentSessionsSection')).toBe(1);
+ expect(nodeCount(renderer.root, 'NewTaskButton')).toBe(1);
expect(nodeCount(renderer.root, 'ProductChoices')).toBe(1);
+ expect(nodeCount(renderer.root, 'Skeleton')).toBe(0);
await act(async () => {
await Promise.resolve();
@@ -134,10 +128,8 @@ describe('HomeScreen composition', () => {
});
});
- it('shows unavailable, not the promo, on active error with zero rows', async () => {
- hasSessions.value = false;
+ it('shows the active-sessions error, not the section, on active error', async () => {
storedIsError.value = false;
- storedIsSuccess.value = true;
activeIsError.value = true;
sessionsLoading.value = false;
orgLoaded.value = true;
@@ -146,9 +138,28 @@ describe('HomeScreen composition', () => {
expect(queryError).toBeDefined();
expect(queryError?.props.title).toBe("Couldn't load active sessions");
expect(typeof queryError?.props.onRetry).toBe('function');
- expect(nodeCount(renderer.root, 'AgentsPromoCard')).toBe(0);
expect(nodeCount(renderer.root, 'AgentSessionsSection')).toBe(0);
- expect(nodeCount(renderer.root, 'NewTaskButton')).toBe(0);
+ expect(nodeCount(renderer.root, 'NewTaskButton')).toBe(1);
+ expect(nodeCount(renderer.root, 'ProductChoices')).toBe(1);
+
+ await act(async () => {
+ await Promise.resolve();
+ renderer.unmount();
+ });
+ });
+
+ it('shows the stored-sessions error, not the section, on stored error', async () => {
+ storedIsError.value = true;
+ activeIsError.value = false;
+ sessionsLoading.value = false;
+ orgLoaded.value = true;
+ const renderer = await mountHome();
+ const queryError = findNode(renderer.root, 'QueryError');
+ expect(queryError).toBeDefined();
+ expect(queryError?.props.title).toBe("Couldn't load sessions");
+ expect(typeof queryError?.props.onRetry).toBe('function');
+ expect(nodeCount(renderer.root, 'AgentSessionsSection')).toBe(0);
+ expect(nodeCount(renderer.root, 'NewTaskButton')).toBe(1);
expect(nodeCount(renderer.root, 'ProductChoices')).toBe(1);
await act(async () => {
diff --git a/apps/mobile/src/components/home/home-screen.tsx b/apps/mobile/src/components/home/home-screen.tsx
index f3cec1887f..589c529046 100644
--- a/apps/mobile/src/components/home/home-screen.tsx
+++ b/apps/mobile/src/components/home/home-screen.tsx
@@ -9,9 +9,8 @@ import { TabScreenScrollView } from '@/components/tab-screen';
import {
AgentSessionsSection,
- hasDisplayableAgentSessions,
+ HOME_LIVE_SLOT_MIN_CLASS,
} from '@/components/home/agent-sessions-section';
-import { AgentsPromoCard } from '@/components/home/agents-promo-card';
import { buildTimedGreeting } from '@/components/home/greeting';
import { NewTaskButton } from '@/components/home/new-task-button';
import { ProductChoices } from '@/components/home/product-choices';
@@ -20,6 +19,7 @@ import { ScreenHeader } from '@/components/screen-header';
import { Skeleton } from '@/components/ui/skeleton';
import { useAgentSessions } from '@/lib/hooks/use-agent-sessions';
import { useOrganization } from '@/lib/organization-context';
+import { cn } from '@/lib/utils';
export function HomeScreen() {
const queryClient = useQueryClient();
@@ -29,11 +29,8 @@ export function HomeScreen() {
const { organizationId, isLoaded: orgLoaded } = useOrganization();
const {
- storedSessions,
- activeSessions,
isLoading: sessionsLoading,
storedIsError,
- storedIsSuccess,
activeIsError,
refetch: refetchSessions,
} = useAgentSessions({
@@ -42,11 +39,6 @@ export function HomeScreen() {
});
const isLoading = sessionsLoading || !orgLoaded;
-
- // Match what the Home Agent-sessions section actually renders (cloud-agent
- // stored + any active), so a CLI-only account shows the first-use promo
- // instead of an empty section + orphaned "New coding task" button.
- const hasAnySession = hasDisplayableAgentSessions(storedSessions, activeSessions);
const headerTitle = buildTimedGreeting();
const handleRefresh = useCallback(() => {
@@ -75,27 +67,24 @@ export function HomeScreen() {
-
-
+ {/* One slot: the loaded state is one row per live session, or a
+ single empty card, so a single skeleton avoids a jump. */}
+
) : (
- {renderSessionsOrPromo({
- hasAnySession,
+ {renderSessionsOrError({
organizationId,
- sessionsError: storedIsError,
- sessionsLoadedEmpty: storedIsSuccess && !hasAnySession,
+ storedIsError,
activeIsError,
handleRetrySessions: () => void refetchSessions(),
t,
})}
- {hasAnySession ? (
-
-
-
- ) : null}
+
+
+
@@ -106,23 +95,18 @@ export function HomeScreen() {
);
}
-function renderSessionsOrPromo(params: {
- hasAnySession: boolean;
+function renderSessionsOrError(params: {
organizationId: string | null;
- sessionsError: boolean;
- sessionsLoadedEmpty: boolean;
+ storedIsError: boolean;
activeIsError: boolean;
handleRetrySessions: () => void;
t: TFunction;
}) {
- // Stale stored history always wins over an error (e.g. a live-poll blip
- // on the active-sessions query) — never blank out sessions we already
- // have. The first-use promo only appears after a confirmed empty
- // response, never merely because the fetch hasn't succeeded yet.
- if (params.hasAnySession) {
- return ;
- }
- if (params.sessionsError) {
+ // A stored-list failure blocks all sessions, so it wins. A cold active poll
+ // failure is retryable but still hides the section until it recovers.
+ // Otherwise Home always renders the section, which shows an empty card when
+ // nothing is live.
+ if (params.storedIsError) {
return (
);
}
- // Cold active-only failure: the stored query succeeded empty but the active
- // poll failed before any data loaded. Retryable, so never claim first-use.
if (params.activeIsError) {
return (
);
}
- if (params.sessionsLoadedEmpty) {
- return ;
- }
- return null;
+ return ;
}
diff --git a/apps/mobile/src/components/pr-review/pr-review-pending-comment-row.tsx b/apps/mobile/src/components/pr-review/pr-review-pending-comment-row.tsx
index d011b952f2..180bda2726 100644
--- a/apps/mobile/src/components/pr-review/pr-review-pending-comment-row.tsx
+++ b/apps/mobile/src/components/pr-review/pr-review-pending-comment-row.tsx
@@ -2,7 +2,7 @@
// location label, 2-line body excerpt, trash → confirm-delete, and a
// pressable body that opens the comment composer in edit mode.
-import { type RefObject } from 'react';
+import { type RefObject, useRef } from 'react';
import { useTranslation } from 'react-i18next';
import { Trash2 } from '@/components/ui/icons';
import { Pressable, TextInput, View } from 'react-native';
@@ -138,19 +138,25 @@ export function ReviewSummaryField({
inputRef,
isDisabled,
onChange,
+ defaultValue = '',
}: {
bodyRef: RefObject;
inputRef: RefObject;
isDisabled: boolean;
onChange: () => void;
+ /** Initial summary content (e.g. the attribution footer). Empty by default. */
+ defaultValue?: string;
}) {
const colors = useThemeColors();
const { t } = useTranslation();
const keyboardVisible = useFormSheetKeyboardVisible();
+ // Place the caret at the start of a prefilled summary once, so the user
+ // begins editing at the top instead of after the footer.
+ const placedCaretRef = useRef(false);
return (
{
+ if (!placedCaretRef.current && defaultValue.length > 0) {
+ placedCaretRef.current = true;
+ inputRef.current?.setNativeProps({ selection: { start: 0, end: 0 } });
+ }
+ }}
multiline
textAlignVertical="top"
// Compact so half-detent and keyboard-open keep footer CTAs at y=0.
className={cn(
'rounded-md border border-input bg-background px-3 py-2 text-sm leading-5 text-foreground',
'focus:border-ring',
- keyboardVisible ? 'max-h-16 min-h-12' : 'min-h-14 max-h-24'
+ keyboardVisible ? 'max-h-16 min-h-12' : 'min-h-14 max-h-32'
)}
/>
);
diff --git a/apps/mobile/src/components/pr-review/pr-review-submit.test.tsx b/apps/mobile/src/components/pr-review/pr-review-submit.test.tsx
index 51421b73be..e7db25ebab 100644
--- a/apps/mobile/src/components/pr-review/pr-review-submit.test.tsx
+++ b/apps/mobile/src/components/pr-review/pr-review-submit.test.tsx
@@ -22,6 +22,15 @@ vi.mock('@/lib/pr-review/use-pr-review-mutations', () => ({
}),
}));
+const footerPreferenceMock = vi.hoisted(() => ({
+ hasLoaded: true,
+ prReviewFooter: false,
+}));
+
+vi.mock('@/lib/hooks/use-pr-review-footer-preference', () => ({
+ usePrReviewFooterPreference: () => footerPreferenceMock,
+}));
+
vi.mock('@/components/pr-review/discussion/reply-input', () => ({
ensureTermsAcceptedOutcome: vi.fn(async () => ({ kind: 'accepted' as const })),
}));
@@ -58,6 +67,7 @@ vi.mock('expo-router', () => ({
vi.mock('react-native', () => ({
Alert: { alert: vi.fn() },
Keyboard: { addListener: () => ({ remove: vi.fn() }) },
+ Platform: { OS: 'ios' },
ScrollView: 'ScrollView',
TextInput: 'TextInput',
View: 'View',
@@ -73,6 +83,7 @@ vi.mock('@/components/pr-review/review-event-chips', () => ({
}));
vi.mock('@/components/ui/button', () => ({ Button: 'Button' }));
vi.mock('@/components/ui/accessible-status', () => ({ AccessibleStatus: 'AccessibleStatus' }));
+vi.mock('@/components/ui/skeleton', () => ({ Skeleton: 'Skeleton' }));
vi.mock('@/components/ui/text', () => ({ Text: 'Text' }));
vi.mock('@/components/pr-review/pr-review-pending-comment-row', () => ({
focusAfterPendingCommentRemoval: vi.fn(),
@@ -164,11 +175,29 @@ function submitOnPress(renderer: TestRenderer.ReactTestRenderer): () => void {
return button.props.onPress as () => void;
}
+function findSubmitButton(renderer: TestRenderer.ReactTestRenderer): Record {
+ const button = renderer.root.findAll(node => Object.hasOwn(node.props, 'loading'))[0];
+ if (!button) {
+ throw new Error('Submit button not found');
+ }
+ return button.props as Record;
+}
+
+function findSummaryField(renderer: TestRenderer.ReactTestRenderer): Record {
+ const summary = renderer.root.findAll(node => Object.hasOwn(node.props, 'defaultValue'))[0];
+ if (!summary) {
+ throw new Error('Summary field not found');
+ }
+ return summary.props as Record;
+}
+
beforeEach(() => {
latestItems = [];
addCommentFn = null;
submitMutationMock.mutateAsync.mockReset();
submitMutationMock.mutateAsync.mockResolvedValue(undefined);
+ footerPreferenceMock.hasLoaded = true;
+ footerPreferenceMock.prReviewFooter = false;
});
describe('PrReviewSubmit queue retention', () => {
@@ -213,3 +242,29 @@ describe('PrReviewSubmit queue retention', () => {
expect(latestItems.map(item => item.id)).toEqual(['stale-c']);
});
});
+
+describe('PrReviewSubmit footer preference', () => {
+ it('prefills the platform footer and enables submit when the setting is on', () => {
+ footerPreferenceMock.prReviewFooter = true;
+ const renderer = mount();
+
+ expect(findSummaryField(renderer).defaultValue).toBe(
+ '\n\n---\nReviewed via the [Kilo iOS app](https://apps.apple.com/app/id6761193135)'
+ );
+
+ // hasSummary was set from the prefilled footer, so a comment review with no
+ // queued comments is not blocked: the submit button is enabled.
+ expect(findSubmitButton(renderer).disabled).toBe(false);
+ });
+
+ it('leaves the body empty and blocks submit when the setting is off', () => {
+ footerPreferenceMock.prReviewFooter = false;
+ const renderer = mount();
+
+ expect(findSummaryField(renderer).defaultValue).toBe('');
+
+ // No prefilled footer and no queued comments: the comment review is
+ // blocked, so the submit button is disabled.
+ expect(findSubmitButton(renderer).disabled).toBe(true);
+ });
+});
diff --git a/apps/mobile/src/components/pr-review/pr-review-submit.tsx b/apps/mobile/src/components/pr-review/pr-review-submit.tsx
index ba9309d548..d14a8b8c8d 100644
--- a/apps/mobile/src/components/pr-review/pr-review-submit.tsx
+++ b/apps/mobile/src/components/pr-review/pr-review-submit.tsx
@@ -12,7 +12,7 @@ import * as Haptics from 'expo-haptics';
import { type Href, useRouter } from 'expo-router';
import { type ReactNode, useEffect, useRef, useState } from 'react';
import { useTranslation } from 'react-i18next';
-import { Alert, Keyboard, ScrollView, type TextInput, View } from 'react-native';
+import { Alert, Keyboard, Platform, ScrollView, type TextInput, View } from 'react-native';
import {
PrFormSheetFooter,
@@ -22,6 +22,7 @@ import {
import { ReviewEventChips } from '@/components/pr-review/review-event-chips';
import { Button } from '@/components/ui/button';
import { AccessibleStatus } from '@/components/ui/accessible-status';
+import { Skeleton } from '@/components/ui/skeleton';
import { Text } from '@/components/ui/text';
import {
focusAfterPendingCommentRemoval,
@@ -43,6 +44,8 @@ import { mutationErrorDisplay } from '@/lib/pr-review/mutation-error-display';
import { type PendingReviewItem, usePendingReview } from '@/lib/pr-review/pending-review-provider';
import { partitionPendingItems } from '@/lib/pr-review/partition-pending-items';
import { useSubmitReviewMutation } from '@/lib/pr-review/use-pr-review-mutations';
+import { usePrReviewFooterPreference } from '@/lib/hooks/use-pr-review-footer-preference';
+import { buildReviewFooter } from '@/lib/pr-review/review-footer';
import {
selectPartialSubmitMessage,
selectSubmitCtaLabel,
@@ -66,6 +69,7 @@ export function PrReviewSubmit(props: PrReviewSubmitProps) {
const pending = usePendingReview();
const { t } = useTranslation();
const submitReview = useSubmitReviewMutation({ owner, repo, number });
+ const { prReviewFooter, hasLoaded: prReviewFooterLoaded } = usePrReviewFooterPreference();
const [event, setEvent] = useState('COMMENT');
const [hasSummary, setHasSummary] = useState(false);
@@ -79,6 +83,18 @@ export function PrReviewSubmit(props: PrReviewSubmitProps) {
const bodyInputRef = useRef(null);
const scrollRef = useRef(null);
+ // Seed the summary refs from the default-on footer preference once it
+ // resolves, before the summary field mounts, so a prefilled footer survives
+ // the async load without flashing an empty input.
+ const footerSeededRef = useRef(false);
+ const initialFooter =
+ prReviewFooterLoaded && prReviewFooter ? buildReviewFooter(Platform.OS) : '';
+ if (prReviewFooterLoaded && !footerSeededRef.current) {
+ footerSeededRef.current = true;
+ bodyRef.current = initialFooter;
+ setHasSummary(initialFooter.trim().length > 0);
+ }
+
const isSubmitting = submitReview.isPending;
const queuedCount = pending.items.length;
const { fresh, stale } = partitionPendingItems(pending.items, headSha);
@@ -267,15 +283,20 @@ export function PrReviewSubmit(props: PrReviewSubmitProps) {
{t('prReview.submit.summaryOptional')}
- {
- setHasSummary(bodyRef.current.trim().length > 0);
- clearRecoverableError();
- }}
- />
+ {prReviewFooterLoaded ? (
+ {
+ setHasSummary(bodyRef.current.trim().length > 0);
+ clearRecoverableError();
+ }}
+ />
+ ) : (
+
+ )}
diff --git a/apps/mobile/src/components/preferences-screen.mounted.test.tsx b/apps/mobile/src/components/preferences-screen.mounted.test.tsx
index 2eaebc9f68..399a1c0321 100644
--- a/apps/mobile/src/components/preferences-screen.mounted.test.tsx
+++ b/apps/mobile/src/components/preferences-screen.mounted.test.tsx
@@ -17,6 +17,7 @@ vi.mock('@/components/ui/icons', () => ({
Bell: 'Bell',
Brain: 'Brain',
Globe: 'Globe',
+ MessageSquare: 'MessageSquare',
Smartphone: 'Smartphone',
}));
vi.mock('@/components/language-picker-sheet', () => ({
@@ -44,6 +45,13 @@ vi.mock('@/lib/hooks/use-keep-screen-on-preference', () => ({
setKeepScreenOn: vi.fn(),
}),
}));
+vi.mock('@/lib/hooks/use-pr-review-footer-preference', () => ({
+ usePrReviewFooterPreference: () => ({
+ prReviewFooter: true,
+ hasLoaded: true,
+ setPrReviewFooter: vi.fn(),
+ }),
+}));
vi.mock('@/lib/hooks/use-reasoning-preference', () => ({
useReasoningPreference: () => ({
defaultExpanded: false,
diff --git a/apps/mobile/src/components/preferences-screen.tsx b/apps/mobile/src/components/preferences-screen.tsx
index f7a642f20b..4e098c6f4f 100644
--- a/apps/mobile/src/components/preferences-screen.tsx
+++ b/apps/mobile/src/components/preferences-screen.tsx
@@ -1,5 +1,12 @@
import { type Href, useRouter } from 'expo-router';
-import { Bell, Brain, Globe, type LucideIcon, Smartphone } from '@/components/ui/icons';
+import {
+ Bell,
+ Brain,
+ Globe,
+ type LucideIcon,
+ MessageSquare,
+ Smartphone,
+} from '@/components/ui/icons';
import { useState } from 'react';
import { Switch, View } from 'react-native';
import { useTranslation } from 'react-i18next';
@@ -14,6 +21,7 @@ import { attemptPushRegistrationReconciliation } from '@/lib/auth/push-registrat
import { useCurrentUserId } from '@/lib/hooks/use-current-user-id';
import { getResolvedLanguage, useLanguagePreference } from '@/lib/hooks/use-language-preference';
import { useKeepScreenOnPreference } from '@/lib/hooks/use-keep-screen-on-preference';
+import { usePrReviewFooterPreference } from '@/lib/hooks/use-pr-review-footer-preference';
import { useReasoningPreference } from '@/lib/hooks/use-reasoning-preference';
import { cn } from '@/lib/utils';
import { LANGUAGE_ENDONYMS } from '@/i18n/languages';
@@ -80,6 +88,11 @@ export function PreferencesScreen() {
hasLoaded: keepScreenOnLoaded,
setKeepScreenOn,
} = useKeepScreenOnPreference();
+ const {
+ prReviewFooter,
+ hasLoaded: prReviewFooterLoaded,
+ setPrReviewFooter,
+ } = usePrReviewFooterPreference();
const { t } = useTranslation();
const { userId } = useCurrentUserId();
const { preference: languagePreference } = useLanguagePreference();
@@ -114,6 +127,14 @@ export function PreferencesScreen() {
disabled={!keepScreenOnLoaded}
onValueChange={setKeepScreenOn}
/>
+
{/* Appearance */}
diff --git a/apps/mobile/src/components/ui/form-field.tsx b/apps/mobile/src/components/ui/form-field.tsx
index bf52634398..fa89f4633f 100644
--- a/apps/mobile/src/components/ui/form-field.tsx
+++ b/apps/mobile/src/components/ui/form-field.tsx
@@ -77,7 +77,11 @@ function FormField({
}
}}
className={cn(
- 'rounded-md border border-input bg-background px-3 py-2.5 text-sm leading-[normal] text-foreground',
+ // min-h-[44px] with no vertical padding: the 44pt height meets the
+ // Apple HIG touch floor and centers the text, while the padding
+ // draws the single-line text below the middle. min-h (not h) still
+ // lets Dynamic Type grow the field past the floor.
+ 'min-h-[44px] rounded-md border border-input bg-background px-3 text-sm leading-[normal] text-foreground',
'focus:border-ring',
displayedError && 'border-destructive',
disabled && 'opacity-50',
diff --git a/apps/mobile/src/i18n/locales/af.json b/apps/mobile/src/i18n/locales/af.json
index 179eb5574f..e425398a4e 100644
--- a/apps/mobile/src/i18n/locales/af.json
+++ b/apps/mobile/src/i18n/locales/af.json
@@ -148,7 +148,9 @@
"appearanceSystem": "Stelsel",
"appearanceLight": "Lig",
"appearanceDark": "Donker",
- "account": "Rekening"
+ "account": "Rekening",
+ "prReviewAttribution": "Add app attribution to PR reviews",
+ "prReviewAttributionSubtitle": "Append a Reviewed via Kilo footer when you submit a review."
},
"prReview": {
"pullRequestUnavailable": "Trekversoek onbeskikbaar",
@@ -2176,7 +2178,8 @@
"discardDraftMessage": "Jou aansporing sal verlore gaan.",
"keepEditing": "Bly redigeer",
"discard": "Gooi weg",
- "discardFailed": "Kon die konsep nie weggooi nie. Probeer asseblief weer."
+ "discardFailed": "Kon die konsep nie weggooi nie. Probeer asseblief weer.",
+ "remoteHint": "Run `kilo remote` on your computer, or `/remote` in a running CLI session, to control a local kilo process."
},
"partRenderer": {
"updatedFileCount_one": "{{displayCount}} lêer bygewerk",
@@ -2662,15 +2665,10 @@
"couldNotLoadSessions": "Kon nie sessies laai nie",
"couldNotLoadActiveSessions": "Kon nie aktiewe sessies laai nie",
"agentSessions": "Agentsessies",
- "showingSavedSessions": "Wys gestoorde sessies — lewende status mag verouderd wees",
- "startNewAgentSession": "Begin 'n nuwe Kilo Agent-sessie",
- "aiCodingSessions": "AI-koderingsessies",
- "startCodingTaskFromPhone": "Begin 'n koderingstaak van jou foon af of gaan voort met 'n sessie vanaf jou CLI.",
- "tryIt": "Probeer dit",
"newCodingTask": "Nuwe koderingstaak",
"explore": "Verken",
"seeAll": "Sien alles",
- "kiloAgents": "Kilo Agents"
+ "noLiveSessions": "Nothing running right now"
},
"imageViewer": {
"close": "Maak {{filename}} toe",
diff --git a/apps/mobile/src/i18n/locales/am.json b/apps/mobile/src/i18n/locales/am.json
index 1f3a1d7709..d63b554ba1 100644
--- a/apps/mobile/src/i18n/locales/am.json
+++ b/apps/mobile/src/i18n/locales/am.json
@@ -148,7 +148,9 @@
"appearanceSystem": "ስርዓት",
"appearanceLight": "ብርሃን",
"appearanceDark": "ጨለማ",
- "account": "መለያ"
+ "account": "መለያ",
+ "prReviewAttribution": "Add app attribution to PR reviews",
+ "prReviewAttributionSubtitle": "Append a Reviewed via Kilo footer when you submit a review."
},
"prReview": {
"pullRequestUnavailable": "የጎተራ ጥያቄ የለም",
@@ -2176,7 +2178,8 @@
"discardDraftMessage": "ጥያቄዎ ይጠፋል።",
"keepEditing": "ማስተካከል ይቀጥሉ",
"discard": "ያስወግዱ",
- "discardFailed": "ረቂቁን ማስወገድ አልተቻለም። እባክዎ እንደገና ይሞክሩ።"
+ "discardFailed": "ረቂቁን ማስወገድ አልተቻለም። እባክዎ እንደገና ይሞክሩ።",
+ "remoteHint": "Run `kilo remote` on your computer, or `/remote` in a running CLI session, to control a local kilo process."
},
"partRenderer": {
"updatedFileCount_one": "{{displayCount}} ፋይል ተዘምኗል",
@@ -2662,15 +2665,10 @@
"couldNotLoadSessions": "ክፍለ-ጊዜዎችን መጫን አልተቻለም",
"couldNotLoadActiveSessions": "ንቁ ክፍለ-ጊዜዎችን መጫን አልተቻለም",
"agentSessions": "የወኪል ክፍለ-ጊዜዎች",
- "showingSavedSessions": "የተቀመጡ ክፍለ-ጊዜዎችን በማሳየት ላይ — የቀጥታ ሁኔታ ጊዜው ያለፈ ሊሆን ይችላል",
- "startNewAgentSession": "አዲስ የKilo Agent ክፍለ-ጊዜ ይጀምሩ",
- "aiCodingSessions": "የAI ኮዲንግ ክፍለ-ጊዜዎች",
- "startCodingTaskFromPhone": "ከስልክዎ የኮዲንግ ተግባር ይጀምሩ ወይም ከCLIዎ ክፍለ-ጊዜ ይቀጥሉ።",
- "tryIt": "ይሞክሩት",
"newCodingTask": "አዲስ የኮዲንግ ተግባር",
"explore": "ይቃኙ",
"seeAll": "ሁሉንም ይመልከቱ",
- "kiloAgents": "Kilo Agents"
+ "noLiveSessions": "Nothing running right now"
},
"imageViewer": {
"close": "{{filename}}ን ይዝጉ",
diff --git a/apps/mobile/src/i18n/locales/ar.json b/apps/mobile/src/i18n/locales/ar.json
index 0fdea59424..c377e80be4 100644
--- a/apps/mobile/src/i18n/locales/ar.json
+++ b/apps/mobile/src/i18n/locales/ar.json
@@ -148,7 +148,9 @@
"appearanceSystem": "النظام",
"appearanceLight": "فاتح",
"appearanceDark": "داكن",
- "account": "الحساب"
+ "account": "الحساب",
+ "prReviewAttribution": "Add app attribution to PR reviews",
+ "prReviewAttributionSubtitle": "Append a Reviewed via Kilo footer when you submit a review."
},
"notifications": {
"title": "الإشعارات",
@@ -1754,7 +1756,8 @@
"discardDraftMessage": "ستفقد مطالبتك.",
"discardDraftTitle": "تجاهل المسودة؟",
"discardFailed": "تعذّر تجاهل المسودة. يرجى المحاولة مرة أخرى.",
- "keepEditing": "متابعة التعديل"
+ "keepEditing": "متابعة التعديل",
+ "remoteHint": "Run `kilo remote` on your computer, or `/remote` in a running CLI session, to control a local kilo process."
},
"partRenderer": {
"updatedFileCount_one": "تم تحديث {{displayCount}} ملف",
@@ -2260,15 +2263,10 @@
"couldNotLoadSessions": "تعذّر تحميل الجلسات",
"couldNotLoadActiveSessions": "تعذّر تحميل الجلسات النشطة",
"agentSessions": "جلسات الوكيل",
- "showingSavedSessions": "عرض الجلسات المحفوظة — قد تكون الحالة المباشرة قديمة",
- "startNewAgentSession": "بدء جلسة Kilo Agent جديدة",
- "aiCodingSessions": "جلسات البرمجة بالذكاء الاصطناعي",
- "startCodingTaskFromPhone": "ابدأ مهمة برمجة من هاتفك أو تابع جلسة من CLI.",
- "tryIt": "جرّبه",
"newCodingTask": "مهمة برمجة جديدة",
"explore": "استكشف",
"seeAll": "عرض الكل",
- "kiloAgents": "وكلاء Kilo"
+ "noLiveSessions": "Nothing running right now"
},
"imageViewer": {
"close": "إغلاق {{filename}}",
diff --git a/apps/mobile/src/i18n/locales/az.json b/apps/mobile/src/i18n/locales/az.json
index 2a098b38f8..1e95f491c2 100644
--- a/apps/mobile/src/i18n/locales/az.json
+++ b/apps/mobile/src/i18n/locales/az.json
@@ -148,7 +148,9 @@
"appearanceSystem": "Sistem",
"appearanceLight": "İşıq",
"appearanceDark": "Qaranlıq",
- "account": "Hesab"
+ "account": "Hesab",
+ "prReviewAttribution": "Add app attribution to PR reviews",
+ "prReviewAttributionSubtitle": "Append a Reviewed via Kilo footer when you submit a review."
},
"prReview": {
"pullRequestUnavailable": "Pull request əlçatan deyil",
@@ -2176,7 +2178,8 @@
"discardDraftMessage": "İstəyiniz itiriləcək.",
"keepEditing": "Redaktəyə davam et",
"discard": "Ləğv et",
- "discardFailed": "Qaralama ləğv edilə bilmədi. Zəhmət olmasa yenidən cəhd edin."
+ "discardFailed": "Qaralama ləğv edilə bilmədi. Zəhmət olmasa yenidən cəhd edin.",
+ "remoteHint": "Run `kilo remote` on your computer, or `/remote` in a running CLI session, to control a local kilo process."
},
"partRenderer": {
"updatedFileCount_one": "{{displayCount}} fayl yeniləndi",
@@ -2662,15 +2665,10 @@
"couldNotLoadSessions": "Sessiyalar yüklənə bilmədi",
"couldNotLoadActiveSessions": "Aktiv sessiyalar yüklənə bilmədi",
"agentSessions": "Agent sessiyaları",
- "showingSavedSessions": "Saxlanılmış sessiyalar göstərilir — canlı status köhnəlmiş ola bilər",
- "startNewAgentSession": "Yeni Kilo Agent sessiyasına başla",
- "aiCodingSessions": "AI kodlaşdırma sessiyaları",
- "startCodingTaskFromPhone": "Telefonunuzdan kodlaşdırma tapşırığı başlayın və ya CLI-nizdən sessiyanı davam etdirin.",
- "tryIt": "Cəhd edin",
"newCodingTask": "Yeni kodlaşdırma tapşırığı",
"explore": "Kəşf et",
"seeAll": "Hamısına bax",
- "kiloAgents": "Kilo Agentlər"
+ "noLiveSessions": "Nothing running right now"
},
"imageViewer": {
"close": "{{filename}} bağla",
diff --git a/apps/mobile/src/i18n/locales/be.json b/apps/mobile/src/i18n/locales/be.json
index 682d9f8275..7509d4c404 100644
--- a/apps/mobile/src/i18n/locales/be.json
+++ b/apps/mobile/src/i18n/locales/be.json
@@ -148,7 +148,9 @@
"appearanceSystem": "Сістэма",
"appearanceLight": "Светлая",
"appearanceDark": "Цёмная",
- "account": "Уліковы запіс"
+ "account": "Уліковы запіс",
+ "prReviewAttribution": "Add app attribution to PR reviews",
+ "prReviewAttributionSubtitle": "Append a Reviewed via Kilo footer when you submit a review."
},
"prReview": {
"pullRequestUnavailable": "Pull request недаступны",
@@ -2206,7 +2208,8 @@
"discardDraftMessage": "Ваш запыт будзе страчаны.",
"keepEditing": "Працягваць рэдагаванне",
"discard": "Адхіліць",
- "discardFailed": "Не атрымалася адхіліць чарнавік. Паспрабуйце зноў."
+ "discardFailed": "Не атрымалася адхіліць чарнавік. Паспрабуйце зноў.",
+ "remoteHint": "Run `kilo remote` on your computer, or `/remote` in a running CLI session, to control a local kilo process."
},
"partRenderer": {
"updatedFileCount_one": "Абноўлены {{displayCount}} файл",
@@ -2702,15 +2705,10 @@
"couldNotLoadSessions": "Не ўдалося загрузіць сеансы",
"couldNotLoadActiveSessions": "Не ўдалося загрузіць актыўныя сеансы",
"agentSessions": "Сеансы агента",
- "showingSavedSessions": "Паказаныя захаваныя сеансы — жывы статус можа быць састарэлым",
- "startNewAgentSession": "Пачаць новы сеанс агента Kilo",
- "aiCodingSessions": "Сеансы AI-праграмавання",
- "startCodingTaskFromPhone": "Пачніце задачу праграмавання з тэлефона або працягніце сеанс з вашага CLI.",
- "tryIt": "Паспрабаваць",
"newCodingTask": "Новая задача праграмавання",
"explore": "Даследаваць",
"seeAll": "Паказаць усё",
- "kiloAgents": "Агенты Kilo"
+ "noLiveSessions": "Nothing running right now"
},
"imageViewer": {
"close": "Закрыць {{filename}}",
diff --git a/apps/mobile/src/i18n/locales/bg.json b/apps/mobile/src/i18n/locales/bg.json
index 7f41626925..208cc99f7a 100644
--- a/apps/mobile/src/i18n/locales/bg.json
+++ b/apps/mobile/src/i18n/locales/bg.json
@@ -148,7 +148,9 @@
"appearanceSystem": "Система",
"appearanceLight": "Светъл",
"appearanceDark": "Тъмен",
- "account": "Акаунт"
+ "account": "Акаунт",
+ "prReviewAttribution": "Add app attribution to PR reviews",
+ "prReviewAttributionSubtitle": "Append a Reviewed via Kilo footer when you submit a review."
},
"prReview": {
"pullRequestUnavailable": "Pull request-ът е недостъпен",
@@ -2176,7 +2178,8 @@
"discardDraftMessage": "Твоята подкана ще бъде загубена.",
"keepEditing": "Продължи редактирането",
"discard": "Отхвърли",
- "discardFailed": "Не можа да се отхвърли черновата. Моля, опитай отново."
+ "discardFailed": "Не можа да се отхвърли черновата. Моля, опитай отново.",
+ "remoteHint": "Run `kilo remote` on your computer, or `/remote` in a running CLI session, to control a local kilo process."
},
"partRenderer": {
"updatedFileCount_one": "Актуализиран {{displayCount}} файл",
@@ -2662,15 +2665,10 @@
"couldNotLoadSessions": "Не можаха да се заредят сесиите",
"couldNotLoadActiveSessions": "Не можаха да се заредят активните сесии",
"agentSessions": "Агентни сесии",
- "showingSavedSessions": "Показване на запазените сесии — актуалният статус може да е остарял",
- "startNewAgentSession": "Започнете нова сесия на Kilo Agent",
- "aiCodingSessions": "AI сесии за кодиране",
- "startCodingTaskFromPhone": "Започнете задача за кодиране от телефона си или продължете сесия от вашия CLI.",
- "tryIt": "Опитайте",
"newCodingTask": "Нова задача за кодиране",
"explore": "Разгледайте",
"seeAll": "Вижте всички",
- "kiloAgents": "Kilo Agents"
+ "noLiveSessions": "Nothing running right now"
},
"imageViewer": {
"close": "Затворете {{filename}}",
diff --git a/apps/mobile/src/i18n/locales/bn.json b/apps/mobile/src/i18n/locales/bn.json
index 08204183f5..268fa20f15 100644
--- a/apps/mobile/src/i18n/locales/bn.json
+++ b/apps/mobile/src/i18n/locales/bn.json
@@ -148,7 +148,9 @@
"appearanceSystem": "সিস্টেম",
"appearanceLight": "লাইট",
"appearanceDark": "ডার্ক",
- "account": "অ্যাকাউন্ট"
+ "account": "অ্যাকাউন্ট",
+ "prReviewAttribution": "Add app attribution to PR reviews",
+ "prReviewAttributionSubtitle": "Append a Reviewed via Kilo footer when you submit a review."
},
"prReview": {
"pullRequestUnavailable": "পুল রিকোয়েস্ট অনুপলব্ধ",
@@ -2176,7 +2178,8 @@
"discardDraftMessage": "আপনার প্রম্পট হারিয়ে যাবে।",
"keepEditing": "সম্পাদনা চালিয়ে যান",
"discard": "বাতিল করুন",
- "discardFailed": "ড্রাফ্টটি বাতিল করা যায়নি। আবার চেষ্টা করুন।"
+ "discardFailed": "ড্রাফ্টটি বাতিল করা যায়নি। আবার চেষ্টা করুন।",
+ "remoteHint": "Run `kilo remote` on your computer, or `/remote` in a running CLI session, to control a local kilo process."
},
"partRenderer": {
"updatedFileCount_one": "{{displayCount}}টি ফাইল আপডেট হয়েছে",
@@ -2662,15 +2665,10 @@
"couldNotLoadSessions": "সেশন লোড করা যায়নি",
"couldNotLoadActiveSessions": "সক্রিয় সেশন লোড করা যায়নি",
"agentSessions": "এজেন্ট সেশন",
- "showingSavedSessions": "সংরক্ষিত সেশন দেখানো হচ্ছে — লাইভ স্ট্যাটাস পুরানো হতে পারে",
- "startNewAgentSession": "একটি নতুন Kilo Agent সেশন শুরু করুন",
- "aiCodingSessions": "AI কোডিং সেশন",
- "startCodingTaskFromPhone": "আপনার ফোন থেকে একটি কোডিং কাজ শুরু করুন বা আপনার CLI থেকে একটি সেশন চালিয়ে যান।",
- "tryIt": "চেষ্টা করুন",
"newCodingTask": "নতুন কোডিং কাজ",
"explore": "অন্বেষণ",
"seeAll": "সব দেখুন",
- "kiloAgents": "Kilo Agents"
+ "noLiveSessions": "Nothing running right now"
},
"imageViewer": {
"close": "{{filename}} বন্ধ করুন",
diff --git a/apps/mobile/src/i18n/locales/bs.json b/apps/mobile/src/i18n/locales/bs.json
index b1af1fd817..0cb33253ec 100644
--- a/apps/mobile/src/i18n/locales/bs.json
+++ b/apps/mobile/src/i18n/locales/bs.json
@@ -148,7 +148,9 @@
"appearanceSystem": "Sistem",
"appearanceLight": "Svijetlo",
"appearanceDark": "Tamno",
- "account": "Nalog"
+ "account": "Nalog",
+ "prReviewAttribution": "Add app attribution to PR reviews",
+ "prReviewAttributionSubtitle": "Append a Reviewed via Kilo footer when you submit a review."
},
"prReview": {
"pullRequestUnavailable": "Pull request nedostupan",
@@ -2191,7 +2193,8 @@
"discardDraftMessage": "Vaš upit bit će izgubljen.",
"keepEditing": "Nastavi uređivati",
"discard": "Odbaci",
- "discardFailed": "Nije moguće odbaciti nacrt. Pokušajte ponovo."
+ "discardFailed": "Nije moguće odbaciti nacrt. Pokušajte ponovo.",
+ "remoteHint": "Run `kilo remote` on your computer, or `/remote` in a running CLI session, to control a local kilo process."
},
"partRenderer": {
"updatedFileCount_one": "Ažurirano {{displayCount}} datoteka",
@@ -2682,15 +2685,10 @@
"couldNotLoadSessions": "Sesije nisu mogle biti učitane",
"couldNotLoadActiveSessions": "Aktivne sesije nisu mogle biti učitane",
"agentSessions": "Sesije agenta",
- "showingSavedSessions": "Prikazuju se sačuvane sesije — status uživo može biti zastario",
- "startNewAgentSession": "Započni novu sesiju Kilo Agenta",
- "aiCodingSessions": "AI sesije kodiranja",
- "startCodingTaskFromPhone": "Započnite zadatak kodiranja sa svog telefona ili nastavite sesiju sa svog CLI-ja.",
- "tryIt": "Isprobaj",
"newCodingTask": "Novi zadatak kodiranja",
"explore": "Istraži",
"seeAll": "Pogledaj sve",
- "kiloAgents": "Kilo Agenti"
+ "noLiveSessions": "Nothing running right now"
},
"imageViewer": {
"close": "Zatvori {{filename}}",
diff --git a/apps/mobile/src/i18n/locales/ca.json b/apps/mobile/src/i18n/locales/ca.json
index 45ca358412..fb585caf6b 100644
--- a/apps/mobile/src/i18n/locales/ca.json
+++ b/apps/mobile/src/i18n/locales/ca.json
@@ -148,7 +148,9 @@
"appearanceSystem": "Sistema",
"appearanceLight": "Clar",
"appearanceDark": "Fosc",
- "account": "Compte"
+ "account": "Compte",
+ "prReviewAttribution": "Add app attribution to PR reviews",
+ "prReviewAttributionSubtitle": "Append a Reviewed via Kilo footer when you submit a review."
},
"prReview": {
"pullRequestUnavailable": "Pull request no disponible",
@@ -2191,7 +2193,8 @@
"discardDraftMessage": "El teu missatge es perdrà.",
"keepEditing": "Continua editant",
"discard": "Descarta",
- "discardFailed": "No s'ha pogut descartar l'esborrany. Torna-ho a provar."
+ "discardFailed": "No s'ha pogut descartar l'esborrany. Torna-ho a provar.",
+ "remoteHint": "Run `kilo remote` on your computer, or `/remote` in a running CLI session, to control a local kilo process."
},
"partRenderer": {
"updatedFileCount_one": "{{displayCount}} fitxer actualitzat",
@@ -2682,15 +2685,10 @@
"couldNotLoadSessions": "No s'han pogut carregar les sessions",
"couldNotLoadActiveSessions": "No s'han pogut carregar les sessions actives",
"agentSessions": "Sessions d'agent",
- "showingSavedSessions": "S'estan mostrant les sessions desades: l'estat en directe pot estar desactualitzat",
- "startNewAgentSession": "Inicia una nova sessió d'agent Kilo",
- "aiCodingSessions": "Sessions de programació d'IA",
- "startCodingTaskFromPhone": "Inicia una tasca de programació des del teu telèfon o continua una sessió des del teu CLI.",
- "tryIt": "Prova-ho",
"newCodingTask": "Nova tasca de programació",
"explore": "Explora",
"seeAll": "Veure-ho tot",
- "kiloAgents": "Agents de Kilo"
+ "noLiveSessions": "Nothing running right now"
},
"imageViewer": {
"close": "Tanca {{filename}}",
diff --git a/apps/mobile/src/i18n/locales/ckb.json b/apps/mobile/src/i18n/locales/ckb.json
index a9f94bb7ce..f43d78275e 100644
--- a/apps/mobile/src/i18n/locales/ckb.json
+++ b/apps/mobile/src/i18n/locales/ckb.json
@@ -148,7 +148,9 @@
"appearanceSystem": "سیستەم",
"appearanceLight": "ڕووناک",
"appearanceDark": "تاریک",
- "account": "هەژمار"
+ "account": "هەژمار",
+ "prReviewAttribution": "Add app attribution to PR reviews",
+ "prReviewAttributionSubtitle": "Append a Reviewed via Kilo footer when you submit a review."
},
"prReview": {
"pullRequestUnavailable": "داواکاری ڕاکێشان بەردەست نییە",
@@ -2176,7 +2178,8 @@
"discardDraftMessage": "نووسینەکەت لەدەست دەچێت.",
"keepEditing": "بەردەوام بە لە دەستکاری",
"discard": "وازلێهێنان",
- "discardFailed": "نەتوانرا لە نوسینەکە وازبهێنرێت. تکایە دووبارە هەوڵ بدە."
+ "discardFailed": "نەتوانرا لە نوسینەکە وازبهێنرێت. تکایە دووبارە هەوڵ بدە.",
+ "remoteHint": "Run `kilo remote` on your computer, or `/remote` in a running CLI session, to control a local kilo process."
},
"partRenderer": {
"updatedFileCount_one": "{{displayCount}} پەڕگە نوێکرایەوە",
@@ -2662,15 +2665,10 @@
"couldNotLoadSessions": "نەتوانرا دانیشتنەکان باربکرێن",
"couldNotLoadActiveSessions": "نەتوانرا دانیشتنە چالاکەکان باربکرێن",
"agentSessions": "دانیشتنەکانی ئەجێنت",
- "showingSavedSessions": "نیشاندانی دانیشتنە پاشەکەوتکراوەکان — دۆخی ڕاستەوخۆ لەوانەیە کۆن بێت",
- "startNewAgentSession": "دەستپێکردنی دانیشتنێکی نوێی ئەجێنتی Kilo",
- "aiCodingSessions": "دانیشتنەکانی کۆدکردنی AI",
- "startCodingTaskFromPhone": "ئەرکێکی کۆدکردن لە مۆبایلەکەتەوە دەستپێبکە یان لە CLIـی خۆتەوە دانیشتنێک بەردەوام بکە.",
- "tryIt": "تاقی بکەرەوە",
"newCodingTask": "ئەرکی کۆدکردنی نوێ",
"explore": "گەڕان",
"seeAll": "بینینی هەموو",
- "kiloAgents": "ئەجێنتەکانی Kilo"
+ "noLiveSessions": "Nothing running right now"
},
"imageViewer": {
"close": "داخستنی {{filename}}",
diff --git a/apps/mobile/src/i18n/locales/cs.json b/apps/mobile/src/i18n/locales/cs.json
index 9d1353bec0..2309480e45 100644
--- a/apps/mobile/src/i18n/locales/cs.json
+++ b/apps/mobile/src/i18n/locales/cs.json
@@ -148,7 +148,9 @@
"appearanceSystem": "Systém",
"appearanceLight": "Světlý",
"appearanceDark": "Tmavý",
- "account": "Účet"
+ "account": "Účet",
+ "prReviewAttribution": "Add app attribution to PR reviews",
+ "prReviewAttributionSubtitle": "Append a Reviewed via Kilo footer when you submit a review."
},
"prReview": {
"pullRequestUnavailable": "Pull request není dostupný",
@@ -2206,7 +2208,8 @@
"discardDraftMessage": "Váš dotaz bude ztracen.",
"keepEditing": "Pokračovat v úpravách",
"discard": "Zahodit",
- "discardFailed": "Koncept se nepodařilo zahodit. Zkuste to znovu."
+ "discardFailed": "Koncept se nepodařilo zahodit. Zkuste to znovu.",
+ "remoteHint": "Run `kilo remote` on your computer, or `/remote` in a running CLI session, to control a local kilo process."
},
"partRenderer": {
"updatedFileCount_one": "Aktualizován {{displayCount}} soubor",
@@ -2702,15 +2705,10 @@
"couldNotLoadSessions": "Relace se nepodařilo načíst",
"couldNotLoadActiveSessions": "Aktivní relace se nepodařilo načíst",
"agentSessions": "Relace agenta",
- "showingSavedSessions": "Zobrazují se uložené relace — živý stav může být zastaralý",
- "startNewAgentSession": "Zahájit novou relaci Kilo Agent",
- "aiCodingSessions": "AI programovací relace",
- "startCodingTaskFromPhone": "Spusťte programovací úkol z telefonu nebo pokračujte v relaci z CLI.",
- "tryIt": "Vyzkoušet",
"newCodingTask": "Nový programovací úkol",
"explore": "Prozkoumat",
"seeAll": "Zobrazit vše",
- "kiloAgents": "Kilo Agents"
+ "noLiveSessions": "Nothing running right now"
},
"imageViewer": {
"close": "Zavřít {{filename}}",
diff --git a/apps/mobile/src/i18n/locales/cy.json b/apps/mobile/src/i18n/locales/cy.json
index ec08d0a88a..9919239e69 100644
--- a/apps/mobile/src/i18n/locales/cy.json
+++ b/apps/mobile/src/i18n/locales/cy.json
@@ -148,7 +148,9 @@
"appearanceSystem": "System",
"appearanceLight": "Golau",
"appearanceDark": "Tywyll",
- "account": "Cyfrif"
+ "account": "Cyfrif",
+ "prReviewAttribution": "Add app attribution to PR reviews",
+ "prReviewAttributionSubtitle": "Append a Reviewed via Kilo footer when you submit a review."
},
"prReview": {
"pullRequestUnavailable": "Ni ellir cael y cais tynnu",
@@ -2236,7 +2238,8 @@
"discardDraftMessage": "Bydd eich anogiad yn cael ei golli.",
"keepEditing": "Parhau i olygu",
"discard": "Taflu",
- "discardFailed": "Methwyd taflu'r drafft. Ceisiwch eto."
+ "discardFailed": "Methwyd taflu'r drafft. Ceisiwch eto.",
+ "remoteHint": "Run `kilo remote` on your computer, or `/remote` in a running CLI session, to control a local kilo process."
},
"partRenderer": {
"updatedFileCount_one": "Diweddarwyd {{displayCount}} ffeil",
@@ -2742,15 +2745,10 @@
"couldNotLoadSessions": "Methwyd llwytho sesiynau",
"couldNotLoadActiveSessions": "Methwyd llwytho sesiynau gweithredol",
"agentSessions": "Sesiynau asiant",
- "showingSavedSessions": "Yn dangos sesiynau wedi'u cadw — gall y statws byw fod yn hen",
- "startNewAgentSession": "Dechrau sesiwn Kilo Agent newydd",
- "aiCodingSessions": "Sesiynau codio AI",
- "startCodingTaskFromPhone": "Dechreuwch dasg codio o'ch ffôn neu barhewch â sesiwn o'ch CLI.",
- "tryIt": "Rhoi cynnig arno",
"newCodingTask": "Tasg codio newydd",
"explore": "Archwilio",
"seeAll": "Gweld y cyfan",
- "kiloAgents": "Kilo Agents"
+ "noLiveSessions": "Nothing running right now"
},
"imageViewer": {
"close": "Cau {{filename}}",
diff --git a/apps/mobile/src/i18n/locales/da.json b/apps/mobile/src/i18n/locales/da.json
index 610558c4a3..df65fc86d1 100644
--- a/apps/mobile/src/i18n/locales/da.json
+++ b/apps/mobile/src/i18n/locales/da.json
@@ -148,7 +148,9 @@
"appearanceSystem": "System",
"appearanceLight": "Lys",
"appearanceDark": "Mørk",
- "account": "Konto"
+ "account": "Konto",
+ "prReviewAttribution": "Add app attribution to PR reviews",
+ "prReviewAttributionSubtitle": "Append a Reviewed via Kilo footer when you submit a review."
},
"prReview": {
"pullRequestUnavailable": "Pull request utilgængelig",
@@ -2176,7 +2178,8 @@
"discardDraftMessage": "Din prompt vil gå tabt.",
"keepEditing": "Fortsæt med at redigere",
"discard": "Kassér",
- "discardFailed": "Kunne ikke kassere kladden. Prøv igen."
+ "discardFailed": "Kunne ikke kassere kladden. Prøv igen.",
+ "remoteHint": "Run `kilo remote` on your computer, or `/remote` in a running CLI session, to control a local kilo process."
},
"partRenderer": {
"updatedFileCount_one": "Opdaterede {{displayCount}} fil",
@@ -2662,15 +2665,10 @@
"couldNotLoadSessions": "Kunne ikke indlæse sessioner",
"couldNotLoadActiveSessions": "Kunne ikke indlæse aktive sessioner",
"agentSessions": "Agentsessioner",
- "showingSavedSessions": "Viser gemte sessioner — live-status kan være forældet",
- "startNewAgentSession": "Start en ny Kilo Agent-session",
- "aiCodingSessions": "AI-kodningssessioner",
- "startCodingTaskFromPhone": "Start en kodningsopgave fra din telefon eller fortsæt en session fra din CLI.",
- "tryIt": "Prøv det",
"newCodingTask": "Ny kodningsopgave",
"explore": "Udforsk",
"seeAll": "Se alle",
- "kiloAgents": "Kilo Agents"
+ "noLiveSessions": "Nothing running right now"
},
"imageViewer": {
"close": "Luk {{filename}}",
diff --git a/apps/mobile/src/i18n/locales/de.json b/apps/mobile/src/i18n/locales/de.json
index 20587c6f96..0f89fba067 100644
--- a/apps/mobile/src/i18n/locales/de.json
+++ b/apps/mobile/src/i18n/locales/de.json
@@ -148,7 +148,9 @@
"appearanceSystem": "System",
"appearanceLight": "Hell",
"appearanceDark": "Dunkel",
- "account": "Konto"
+ "account": "Konto",
+ "prReviewAttribution": "Add app attribution to PR reviews",
+ "prReviewAttributionSubtitle": "Append a Reviewed via Kilo footer when you submit a review."
},
"notifications": {
"title": "Benachrichtigungen",
@@ -1722,7 +1724,8 @@
"discardDraftMessage": "Dein Prompt geht verloren.",
"discardDraftTitle": "Entwurf verwerfen?",
"discardFailed": "Der Entwurf konnte nicht verworfen werden. Bitte versuche es erneut.",
- "keepEditing": "Weiter bearbeiten"
+ "keepEditing": "Weiter bearbeiten",
+ "remoteHint": "Run `kilo remote` on your computer, or `/remote` in a running CLI session, to control a local kilo process."
},
"partRenderer": {
"updatedFileCount_one": "{{displayCount}} Datei aktualisiert",
@@ -2208,15 +2211,10 @@
"couldNotLoadSessions": "Sitzungen konnten nicht geladen werden",
"couldNotLoadActiveSessions": "Aktive Sitzungen konnten nicht geladen werden",
"agentSessions": "Agentensitzungen",
- "showingSavedSessions": "Gespeicherte Sitzungen werden angezeigt — der Live-Status kann veraltet sein",
- "startNewAgentSession": "Neue Kilo-Agent-Sitzung starten",
- "aiCodingSessions": "KI-Codiersitzungen",
- "startCodingTaskFromPhone": "Starte eine Codieraufgabe von deinem Telefon oder setze eine Sitzung von deiner CLI fort.",
- "tryIt": "Ausprobieren",
"newCodingTask": "Neue Codieraufgabe",
"explore": "Entdecken",
"seeAll": "Alle ansehen",
- "kiloAgents": "Kilo-Agenten"
+ "noLiveSessions": "Nothing running right now"
},
"imageViewer": {
"close": "{{filename}} schließen",
diff --git a/apps/mobile/src/i18n/locales/el.json b/apps/mobile/src/i18n/locales/el.json
index 3187e81a0a..276971f50c 100644
--- a/apps/mobile/src/i18n/locales/el.json
+++ b/apps/mobile/src/i18n/locales/el.json
@@ -148,7 +148,9 @@
"appearanceSystem": "Σύστημα",
"appearanceLight": "Ανοιχτό",
"appearanceDark": "Σκούρο",
- "account": "Λογαριασμός"
+ "account": "Λογαριασμός",
+ "prReviewAttribution": "Add app attribution to PR reviews",
+ "prReviewAttributionSubtitle": "Append a Reviewed via Kilo footer when you submit a review."
},
"prReview": {
"pullRequestUnavailable": "Το pull request δεν είναι διαθέσιμο",
@@ -2176,7 +2178,8 @@
"discardDraftMessage": "Το μήνυμά σας θα χαθεί.",
"keepEditing": "Συνέχιση επεξεργασίας",
"discard": "Απόρριψη",
- "discardFailed": "Δεν ήταν δυνατή η απόρριψη του πρόχειρου. Δοκιμάστε ξανά."
+ "discardFailed": "Δεν ήταν δυνατή η απόρριψη του πρόχειρου. Δοκιμάστε ξανά.",
+ "remoteHint": "Run `kilo remote` on your computer, or `/remote` in a running CLI session, to control a local kilo process."
},
"partRenderer": {
"updatedFileCount_one": "Ενημερώθηκε {{displayCount}} αρχείο",
@@ -2662,15 +2665,10 @@
"couldNotLoadSessions": "Δεν ήταν δυνατή η φόρτωση συνεδριών",
"couldNotLoadActiveSessions": "Δεν ήταν δυνατή η φόρτωση ενεργών συνεδριών",
"agentSessions": "Συνεδρίες πράκτορα",
- "showingSavedSessions": "Εμφάνιση αποθηκευμένων συνεδριών — η ζωντανή κατάσταση ενδέχεται να είναι ξεπερασμένη",
- "startNewAgentSession": "Έναρξη νέας συνεδρίας Kilo Agent",
- "aiCodingSessions": "Συνεδρίες προγραμματισμού με AI",
- "startCodingTaskFromPhone": "Ξεκινήστε μια εργασία προγραμματισμού από το τηλέφωνό σας ή συνεχίστε μια συνεδρία από το CLI σας.",
- "tryIt": "Δοκιμάστε το",
"newCodingTask": "Νέα εργασία προγραμματισμού",
"explore": "Εξερεύνηση",
"seeAll": "Προβολή όλων",
- "kiloAgents": "Kilo Agents"
+ "noLiveSessions": "Nothing running right now"
},
"imageViewer": {
"close": "Κλείσιμο {{filename}}",
diff --git a/apps/mobile/src/i18n/locales/en.json b/apps/mobile/src/i18n/locales/en.json
index 4306062a21..3275ef0d6b 100644
--- a/apps/mobile/src/i18n/locales/en.json
+++ b/apps/mobile/src/i18n/locales/en.json
@@ -148,7 +148,9 @@
"appearanceSystem": "System",
"appearanceLight": "Light",
"appearanceDark": "Dark",
- "account": "Account"
+ "account": "Account",
+ "prReviewAttribution": "Add app attribution to PR reviews",
+ "prReviewAttributionSubtitle": "Append a Reviewed via Kilo footer when you submit a review."
},
"prReview": {
"pullRequestUnavailable": "Pull request unavailable",
@@ -2176,7 +2178,8 @@
"discardDraftMessage": "Your prompt will be lost.",
"keepEditing": "Keep editing",
"discard": "Discard",
- "discardFailed": "Could not discard the draft. Please try again."
+ "discardFailed": "Could not discard the draft. Please try again.",
+ "remoteHint": "Run `kilo remote` on your computer, or `/remote` in a running CLI session, to control a local kilo process."
},
"partRenderer": {
"updatedFileCount_one": "Updated {{displayCount}} file",
@@ -2661,16 +2664,11 @@
"home": {
"couldNotLoadSessions": "Couldn't load sessions",
"couldNotLoadActiveSessions": "Couldn't load active sessions",
- "agentSessions": "Agent sessions",
- "showingSavedSessions": "Showing saved sessions — live status may be out of date",
- "startNewAgentSession": "Start a new Kilo Agent session",
- "aiCodingSessions": "AI coding sessions",
- "startCodingTaskFromPhone": "Start a coding task from your phone or continue a session from your CLI.",
- "tryIt": "Try it",
+ "agentSessions": "Live now",
"newCodingTask": "New coding task",
"explore": "Explore",
"seeAll": "See all",
- "kiloAgents": "Kilo Agents"
+ "noLiveSessions": "Nothing running right now"
},
"imageViewer": {
"close": "Close {{filename}}",
diff --git a/apps/mobile/src/i18n/locales/es.json b/apps/mobile/src/i18n/locales/es.json
index 62ca5ce446..64f2c479fb 100644
--- a/apps/mobile/src/i18n/locales/es.json
+++ b/apps/mobile/src/i18n/locales/es.json
@@ -148,7 +148,9 @@
"appearanceSystem": "Sistema",
"appearanceLight": "Claro",
"appearanceDark": "Oscuro",
- "account": "Cuenta"
+ "account": "Cuenta",
+ "prReviewAttribution": "Add app attribution to PR reviews",
+ "prReviewAttributionSubtitle": "Append a Reviewed via Kilo footer when you submit a review."
},
"notifications": {
"channel": {
@@ -1730,7 +1732,8 @@
"discardDraftMessage": "Tu prompt se perderá.",
"discardDraftTitle": "¿Descartar borrador?",
"discardFailed": "No se pudo descartar el borrador. Inténtalo de nuevo.",
- "keepEditing": "Seguir editando"
+ "keepEditing": "Seguir editando",
+ "remoteHint": "Run `kilo remote` on your computer, or `/remote` in a running CLI session, to control a local kilo process."
},
"partRenderer": {
"updatedFileCount_one": "{{displayCount}} archivo actualizado",
@@ -2221,15 +2224,10 @@
"couldNotLoadSessions": "No se pudieron cargar las sesiones",
"couldNotLoadActiveSessions": "No se pudieron cargar las sesiones activas",
"agentSessions": "Sesiones de agentes",
- "showingSavedSessions": "Mostrando sesiones guardadas: el estado en vivo puede estar desactualizado",
- "startNewAgentSession": "Iniciar una nueva sesión de Kilo Agent",
- "aiCodingSessions": "Sesiones de codificación con IA",
- "startCodingTaskFromPhone": "Inicia una tarea de codificación desde tu teléfono o continúa una sesión desde tu CLI.",
- "tryIt": "Pruébalo",
"newCodingTask": "Nueva tarea de codificación",
"explore": "Explorar",
"seeAll": "Ver todo",
- "kiloAgents": "Agentes de Kilo"
+ "noLiveSessions": "Nothing running right now"
},
"imageViewer": {
"close": "Cerrar {{filename}}",
diff --git a/apps/mobile/src/i18n/locales/et.json b/apps/mobile/src/i18n/locales/et.json
index 8b84b06de0..8447eddd15 100644
--- a/apps/mobile/src/i18n/locales/et.json
+++ b/apps/mobile/src/i18n/locales/et.json
@@ -148,7 +148,9 @@
"appearanceSystem": "Süsteem",
"appearanceLight": "Heledas",
"appearanceDark": "Tumedas",
- "account": "Konto"
+ "account": "Konto",
+ "prReviewAttribution": "Add app attribution to PR reviews",
+ "prReviewAttributionSubtitle": "Append a Reviewed via Kilo footer when you submit a review."
},
"prReview": {
"pullRequestUnavailable": "Pull request ei ole saadaval",
@@ -2176,7 +2178,8 @@
"discardDraftMessage": "Sinu päring läheb kaotsi.",
"keepEditing": "Jätka muutmist",
"discard": "Loobu",
- "discardFailed": "Mustandist loobumine ebaõnnestus. Proovi uuesti."
+ "discardFailed": "Mustandist loobumine ebaõnnestus. Proovi uuesti.",
+ "remoteHint": "Run `kilo remote` on your computer, or `/remote` in a running CLI session, to control a local kilo process."
},
"partRenderer": {
"updatedFileCount_one": "Uuendatud {{displayCount}} fail",
@@ -2662,15 +2665,10 @@
"couldNotLoadSessions": "Seansse ei õnnestunud laadida",
"couldNotLoadActiveSessions": "Aktiivseid seansse ei õnnestunud laadida",
"agentSessions": "Agendi seansid",
- "showingSavedSessions": "Kuvatakse salvestatud seansid — otseolek võib olla aegunud",
- "startNewAgentSession": "Alusta uut Kilo Agent seanssi",
- "aiCodingSessions": "AI kodeerimisseansid",
- "startCodingTaskFromPhone": "Alustage kodeerimisülesannet telefonist või jätkake seanssi CLI-st.",
- "tryIt": "Proovi",
"newCodingTask": "Uus kodeerimisülesanne",
"explore": "Avasta",
"seeAll": "Vaata kõiki",
- "kiloAgents": "Kilo Agents"
+ "noLiveSessions": "Nothing running right now"
},
"imageViewer": {
"close": "Sulge {{filename}}",
diff --git a/apps/mobile/src/i18n/locales/eu.json b/apps/mobile/src/i18n/locales/eu.json
index 7147fe6c11..9420fa4d32 100644
--- a/apps/mobile/src/i18n/locales/eu.json
+++ b/apps/mobile/src/i18n/locales/eu.json
@@ -148,7 +148,9 @@
"appearanceSystem": "Sistema",
"appearanceLight": "Argia",
"appearanceDark": "Iluna",
- "account": "Kontua"
+ "account": "Kontua",
+ "prReviewAttribution": "Add app attribution to PR reviews",
+ "prReviewAttributionSubtitle": "Append a Reviewed via Kilo footer when you submit a review."
},
"prReview": {
"pullRequestUnavailable": "Pull request-a ez dago eskuragarri",
@@ -2176,7 +2178,8 @@
"discardDraftMessage": "Zure proposamena galduko da.",
"keepEditing": "Editatzen jarraitu",
"discard": "Baztertu",
- "discardFailed": "Ezin da zirriborroa baztertu. Saiatu berriro."
+ "discardFailed": "Ezin da zirriborroa baztertu. Saiatu berriro.",
+ "remoteHint": "Run `kilo remote` on your computer, or `/remote` in a running CLI session, to control a local kilo process."
},
"partRenderer": {
"updatedFileCount_one": "{{displayCount}} fitxategi eguneratu da",
@@ -2662,15 +2665,10 @@
"couldNotLoadSessions": "Ezin izan dira saioak kargatu",
"couldNotLoadActiveSessions": "Ezin izan dira saio aktiboak kargatu",
"agentSessions": "Agentearen saioak",
- "showingSavedSessions": "Gordetako saioak erakusten — egoera zuzena ez egon daiteke",
- "startNewAgentSession": "Hasi Kilo Agent saio berri bat",
- "aiCodingSessions": "AI kodetze-saioak",
- "startCodingTaskFromPhone": "Hasi kodetze-lan bat zure telefonotik edo jarraitu saio bat zure CLI-tik.",
- "tryIt": "Probatu",
"newCodingTask": "Kodetze-lan berria",
"explore": "Arakatu",
"seeAll": "Ikusi guztiak",
- "kiloAgents": "Kilo Agents"
+ "noLiveSessions": "Nothing running right now"
},
"imageViewer": {
"close": "Itxi {{filename}}",
diff --git a/apps/mobile/src/i18n/locales/fa.json b/apps/mobile/src/i18n/locales/fa.json
index 4842f3291e..c84b933cb7 100644
--- a/apps/mobile/src/i18n/locales/fa.json
+++ b/apps/mobile/src/i18n/locales/fa.json
@@ -148,7 +148,9 @@
"appearanceSystem": "سیستم",
"appearanceLight": "روشن",
"appearanceDark": "تیره",
- "account": "حساب"
+ "account": "حساب",
+ "prReviewAttribution": "Add app attribution to PR reviews",
+ "prReviewAttributionSubtitle": "Append a Reviewed via Kilo footer when you submit a review."
},
"prReview": {
"pullRequestUnavailable": "درخواست pull در دسترس نیست",
@@ -2176,7 +2178,8 @@
"discardDraftMessage": "پیام شما از بین خواهد رفت.",
"keepEditing": "ادامه ویرایش",
"discard": "دور انداختن",
- "discardFailed": "دور انداختن پیشنویس ممکن نشد. لطفاً دوباره تلاش کنید."
+ "discardFailed": "دور انداختن پیشنویس ممکن نشد. لطفاً دوباره تلاش کنید.",
+ "remoteHint": "Run `kilo remote` on your computer, or `/remote` in a running CLI session, to control a local kilo process."
},
"partRenderer": {
"updatedFileCount_one": "{{displayCount}} فایل بهروزرسانی شد",
@@ -2662,15 +2665,10 @@
"couldNotLoadSessions": "جلسات بارگذاری نشدند",
"couldNotLoadActiveSessions": "جلسات فعال بارگذاری نشدند",
"agentSessions": "جلسات عامل",
- "showingSavedSessions": "نمایش جلسات ذخیرهشده — وضعیت زنده ممکن است بهروز نباشد",
- "startNewAgentSession": "شروع یک جلسه جدید Kilo Agent",
- "aiCodingSessions": "جلسات کدنویسی هوش مصنوعی",
- "startCodingTaskFromPhone": "از تلفن خود یک کار کدنویسی را شروع کنید یا جلسه را از CLI ادامه دهید.",
- "tryIt": "امتحان کنید",
"newCodingTask": "کار کدنویسی جدید",
"explore": "کاوش",
"seeAll": "مشاهده همه",
- "kiloAgents": "Kilo Agents"
+ "noLiveSessions": "Nothing running right now"
},
"imageViewer": {
"close": "بستن {{filename}}",
diff --git a/apps/mobile/src/i18n/locales/fi.json b/apps/mobile/src/i18n/locales/fi.json
index 5e80ef31c4..7ea3d16800 100644
--- a/apps/mobile/src/i18n/locales/fi.json
+++ b/apps/mobile/src/i18n/locales/fi.json
@@ -148,7 +148,9 @@
"appearanceSystem": "Järjestelmä",
"appearanceLight": "Vaalea",
"appearanceDark": "Tumma",
- "account": "Tili"
+ "account": "Tili",
+ "prReviewAttribution": "Add app attribution to PR reviews",
+ "prReviewAttributionSubtitle": "Append a Reviewed via Kilo footer when you submit a review."
},
"prReview": {
"pullRequestUnavailable": "Pull request ei ole käytettävissä",
@@ -2176,7 +2178,8 @@
"discardDraftMessage": "Kehotteesi menetetään.",
"keepEditing": "Jatka muokkausta",
"discard": "Hylkää",
- "discardFailed": "Luonnosta ei voitu hylätä. Yritä uudelleen."
+ "discardFailed": "Luonnosta ei voitu hylätä. Yritä uudelleen.",
+ "remoteHint": "Run `kilo remote` on your computer, or `/remote` in a running CLI session, to control a local kilo process."
},
"partRenderer": {
"updatedFileCount_one": "Päivitetty {{displayCount}} tiedosto",
@@ -2662,15 +2665,10 @@
"couldNotLoadSessions": "Istuntoja ei voitu ladata",
"couldNotLoadActiveSessions": "Aktiivisia istuntoja ei voitu ladata",
"agentSessions": "Agentti-istunnot",
- "showingSavedSessions": "Näytetään tallennetut istunnot — reaaliaikainen tila voi olla vanhentunut",
- "startNewAgentSession": "Aloita uusi Kilo Agent -istunto",
- "aiCodingSessions": "AI-koodausistunnot",
- "startCodingTaskFromPhone": "Aloita koodaustehtävä puhelimestasi tai jatka istuntoa CLI:stäsi.",
- "tryIt": "Kokeile",
"newCodingTask": "Uusi koodaustehtävä",
"explore": "Tutustu",
"seeAll": "Näytä kaikki",
- "kiloAgents": "Kilo Agentit"
+ "noLiveSessions": "Nothing running right now"
},
"imageViewer": {
"close": "Sulje {{filename}}",
diff --git a/apps/mobile/src/i18n/locales/fil.json b/apps/mobile/src/i18n/locales/fil.json
index 5b4b0890c4..6a49e56200 100644
--- a/apps/mobile/src/i18n/locales/fil.json
+++ b/apps/mobile/src/i18n/locales/fil.json
@@ -148,7 +148,9 @@
"appearanceSystem": "System",
"appearanceLight": "Light",
"appearanceDark": "Dark",
- "account": "Account"
+ "account": "Account",
+ "prReviewAttribution": "Add app attribution to PR reviews",
+ "prReviewAttributionSubtitle": "Append a Reviewed via Kilo footer when you submit a review."
},
"prReview": {
"pullRequestUnavailable": "Hindi available ang pull request",
@@ -2176,7 +2178,8 @@
"discardDraftMessage": "Mawawala ang iyong prompt.",
"keepEditing": "Patuloy na mag-edit",
"discard": "I-discard",
- "discardFailed": "Hindi ma-discard ang draft. Pakisubukang muli."
+ "discardFailed": "Hindi ma-discard ang draft. Pakisubukang muli.",
+ "remoteHint": "Run `kilo remote` on your computer, or `/remote` in a running CLI session, to control a local kilo process."
},
"partRenderer": {
"updatedFileCount_one": "Na-update ang {{displayCount}} file",
@@ -2662,15 +2665,10 @@
"couldNotLoadSessions": "Hindi ma-load ang mga session",
"couldNotLoadActiveSessions": "Hindi ma-load ang mga aktibong session",
"agentSessions": "Mga agent session",
- "showingSavedSessions": "Ipinapakita ang mga naka-save na session — maaaring luma na ang live status",
- "startNewAgentSession": "Magsimula ng bagong Kilo Agent session",
- "aiCodingSessions": "Mga AI coding session",
- "startCodingTaskFromPhone": "Magsimula ng coding task mula sa iyong telepono o magpatuloy ng session mula sa iyong CLI.",
- "tryIt": "Subukan ito",
"newCodingTask": "Bagong coding task",
"explore": "Mag-explore",
"seeAll": "Tingnan lahat",
- "kiloAgents": "Kilo Agents"
+ "noLiveSessions": "Nothing running right now"
},
"imageViewer": {
"close": "Isara ang {{filename}}",
diff --git a/apps/mobile/src/i18n/locales/fr.json b/apps/mobile/src/i18n/locales/fr.json
index 0bf00bcac6..f4e27261b1 100644
--- a/apps/mobile/src/i18n/locales/fr.json
+++ b/apps/mobile/src/i18n/locales/fr.json
@@ -1648,7 +1648,8 @@
"discardDraftMessage": "Votre prompt sera perdu.",
"discardDraftTitle": "Abandonner le brouillon ?",
"discardFailed": "Impossible d'abandonner le brouillon. Veuillez réessayer.",
- "keepEditing": "Continuer à modifier"
+ "keepEditing": "Continuer à modifier",
+ "remoteHint": "Run `kilo remote` on your computer, or `/remote` in a running CLI session, to control a local kilo process."
},
"partRenderer": {
"updatedFileCount_one": "{{displayCount}} fichier mis à jour",
@@ -2114,7 +2115,9 @@
"appearanceSystem": "Système",
"appearanceLight": "Clair",
"appearanceDark": "Sombre",
- "account": "Compte"
+ "account": "Compte",
+ "prReviewAttribution": "Add app attribution to PR reviews",
+ "prReviewAttributionSubtitle": "Append a Reviewed via Kilo footer when you submit a review."
},
"addCredits": {
"cta": "Ajouter des crédits",
@@ -2153,15 +2156,10 @@
"couldNotLoadSessions": "Impossible de charger les sessions",
"couldNotLoadActiveSessions": "Impossible de charger les sessions actives",
"agentSessions": "Sessions d'agents",
- "showingSavedSessions": "Affichage des sessions enregistrées — le statut en direct peut être obsolète",
- "startNewAgentSession": "Démarrer une nouvelle session Kilo Agent",
- "aiCodingSessions": "Sessions de codage IA",
- "startCodingTaskFromPhone": "Démarrez une tâche de codage depuis votre téléphone ou continuez une session depuis votre CLI.",
- "tryIt": "Essayer",
"newCodingTask": "Nouvelle tâche de codage",
"explore": "Explorer",
"seeAll": "Tout voir",
- "kiloAgents": "Agents Kilo"
+ "noLiveSessions": "Nothing running right now"
},
"imageViewer": {
"close": "Fermer {{filename}}",
diff --git a/apps/mobile/src/i18n/locales/ga.json b/apps/mobile/src/i18n/locales/ga.json
index 603abe730b..2aaab158d1 100644
--- a/apps/mobile/src/i18n/locales/ga.json
+++ b/apps/mobile/src/i18n/locales/ga.json
@@ -148,7 +148,9 @@
"appearanceSystem": "Córas",
"appearanceLight": "Geal",
"appearanceDark": "Dorcha",
- "account": "Cuntas"
+ "account": "Cuntas",
+ "prReviewAttribution": "Add app attribution to PR reviews",
+ "prReviewAttributionSubtitle": "Append a Reviewed via Kilo footer when you submit a review."
},
"prReview": {
"pullRequestUnavailable": "Iarratas tarraingthe ar fáil",
@@ -2221,7 +2223,8 @@
"discardDraftMessage": "Caillfear do leid.",
"keepEditing": "Coinnigh ag eagarthóireacht",
"discard": "Caith ar lár",
- "discardFailed": "Níorbh fhéidir an dréacht a chaitheamh ar lár. Bain triail as arís le do thoil."
+ "discardFailed": "Níorbh fhéidir an dréacht a chaitheamh ar lár. Bain triail as arís le do thoil.",
+ "remoteHint": "Run `kilo remote` on your computer, or `/remote` in a running CLI session, to control a local kilo process."
},
"partRenderer": {
"updatedFileCount_one": "Nuashonraíodh {{displayCount}} comhad",
@@ -2722,15 +2725,10 @@
"couldNotLoadSessions": "Níorbh fhéidir seisiúin a lódáil",
"couldNotLoadActiveSessions": "Níorbh fhéidir seisiúin ghníomhacha a lódáil",
"agentSessions": "Seisiúin ghníomhaire",
- "showingSavedSessions": "Ag taispeáint seisiúin shábháilte — b'fhéidir go bhfuil an stádas beo as dáta",
- "startNewAgentSession": "Tosaigh seisiún Kilo Agent nua",
- "aiCodingSessions": "Seisiúin chódaithe AI",
- "startCodingTaskFromPhone": "Tosaigh tasc códaithe ó do ghuthán nó lean ar aghaidh le seisiún ó do CLI.",
- "tryIt": "Bain triail as",
"newCodingTask": "Tasc códaithe nua",
"explore": "Taiscéal",
"seeAll": "Féach ar gach ceann",
- "kiloAgents": "Kilo Agents"
+ "noLiveSessions": "Nothing running right now"
},
"imageViewer": {
"close": "Dún {{filename}}",
diff --git a/apps/mobile/src/i18n/locales/gl.json b/apps/mobile/src/i18n/locales/gl.json
index 866a18691c..a1ed5184f4 100644
--- a/apps/mobile/src/i18n/locales/gl.json
+++ b/apps/mobile/src/i18n/locales/gl.json
@@ -148,7 +148,9 @@
"appearanceSystem": "Sistema",
"appearanceLight": "Claro",
"appearanceDark": "Escuro",
- "account": "Conta"
+ "account": "Conta",
+ "prReviewAttribution": "Add app attribution to PR reviews",
+ "prReviewAttributionSubtitle": "Append a Reviewed via Kilo footer when you submit a review."
},
"prReview": {
"pullRequestUnavailable": "Pull request non dispoñible",
@@ -2176,7 +2178,8 @@
"discardDraftMessage": "Perderase o teu indicación.",
"keepEditing": "Continuar editando",
"discard": "Descartar",
- "discardFailed": "Non se puido descartar o borrador. Téntao de novo."
+ "discardFailed": "Non se puido descartar o borrador. Téntao de novo.",
+ "remoteHint": "Run `kilo remote` on your computer, or `/remote` in a running CLI session, to control a local kilo process."
},
"partRenderer": {
"updatedFileCount_one": "Actualizouse {{displayCount}} ficheiro",
@@ -2662,15 +2665,10 @@
"couldNotLoadSessions": "Non se puideron cargar as sesións",
"couldNotLoadActiveSessions": "Non se puideron cargar as sesións activas",
"agentSessions": "Sesións de axente",
- "showingSavedSessions": "Mostrando sesións gardadas — o estado en directo pode estar desactualizado",
- "startNewAgentSession": "Iniciar unha nova sesión de Kilo Agent",
- "aiCodingSessions": "Sesións de codificación con IA",
- "startCodingTaskFromPhone": "Inicia unha tarefa de codificación desde o teu teléfono ou continúa unha sesión desde o teu CLI.",
- "tryIt": "Probala",
"newCodingTask": "Nova tarefa de codificación",
"explore": "Explorar",
"seeAll": "Ver todo",
- "kiloAgents": "Kilo Agents"
+ "noLiveSessions": "Nothing running right now"
},
"imageViewer": {
"close": "Pechar {{filename}}",
diff --git a/apps/mobile/src/i18n/locales/gu.json b/apps/mobile/src/i18n/locales/gu.json
index c3a428ca02..fc93eb503e 100644
--- a/apps/mobile/src/i18n/locales/gu.json
+++ b/apps/mobile/src/i18n/locales/gu.json
@@ -148,7 +148,9 @@
"appearanceSystem": "સિસ્ટમ",
"appearanceLight": "લાઇટ",
"appearanceDark": "ડાર્ક",
- "account": "એકાઉન્ટ"
+ "account": "એકાઉન્ટ",
+ "prReviewAttribution": "Add app attribution to PR reviews",
+ "prReviewAttributionSubtitle": "Append a Reviewed via Kilo footer when you submit a review."
},
"prReview": {
"pullRequestUnavailable": "પુલ રિક્વેસ્ટ ઉપલબ્ધ નથી",
@@ -2176,7 +2178,8 @@
"discardDraftMessage": "તમારો પ્રોમ્પ્ટ ખોવાઈ જશે.",
"keepEditing": "સંપાદન ચાલુ રાખો",
"discard": "કાઢી નાખો",
- "discardFailed": "ડ્રાફ્ટ કાઢી નાખી શકાયો નથી. કૃપા કરીને ફરી પ્રયાસ કરો."
+ "discardFailed": "ડ્રાફ્ટ કાઢી નાખી શકાયો નથી. કૃપા કરીને ફરી પ્રયાસ કરો.",
+ "remoteHint": "Run `kilo remote` on your computer, or `/remote` in a running CLI session, to control a local kilo process."
},
"partRenderer": {
"updatedFileCount_one": "{{displayCount}} ફાઇલ અપડેટ કરેલ",
@@ -2662,15 +2665,10 @@
"couldNotLoadSessions": "સત્રો લોડ કરી શકાયા નહીં",
"couldNotLoadActiveSessions": "સક્રિય સત્રો લોડ કરી શકાયા નહીં",
"agentSessions": "એજન્ટ સત્રો",
- "showingSavedSessions": "સાચવેલા સત્રો બતાવી રહ્યા છીએ — લાઇવ સ્થિતિ જૂની હોઈ શકે છે",
- "startNewAgentSession": "નવું Kilo એજન્ટ સત્ર શરૂ કરો",
- "aiCodingSessions": "AI કોડિંગ સત્રો",
- "startCodingTaskFromPhone": "તમારા ફોનથી કોડિંગ કાર્ય શરૂ કરો અથવા તમારા CLI માંથી સત્ર ચાલુ રાખો.",
- "tryIt": "અજમાવો",
"newCodingTask": "નવું કોડિંગ કાર્ય",
"explore": "શોધો",
"seeAll": "બધા જુઓ",
- "kiloAgents": "Kilo એજન્ટ્સ"
+ "noLiveSessions": "Nothing running right now"
},
"imageViewer": {
"close": "{{filename}} બંધ કરો",
diff --git a/apps/mobile/src/i18n/locales/ha.json b/apps/mobile/src/i18n/locales/ha.json
index 388ed226fd..d6b2757baf 100644
--- a/apps/mobile/src/i18n/locales/ha.json
+++ b/apps/mobile/src/i18n/locales/ha.json
@@ -148,7 +148,9 @@
"appearanceSystem": "Tsarin",
"appearanceLight": "Haske",
"appearanceDark": "Duhu",
- "account": "Asusu"
+ "account": "Asusu",
+ "prReviewAttribution": "Add app attribution to PR reviews",
+ "prReviewAttributionSubtitle": "Append a Reviewed via Kilo footer when you submit a review."
},
"prReview": {
"pullRequestUnavailable": "Buƙatar jan ba ta samuwa",
@@ -2176,7 +2178,8 @@
"discardDraftMessage": "Za a ɓata bayaninka.",
"keepEditing": "Ci gaba da gyarawa",
"discard": "Watsi",
- "discardFailed": "An kasa watsi da daftarin. Da fatan za a sake gwadawa."
+ "discardFailed": "An kasa watsi da daftarin. Da fatan za a sake gwadawa.",
+ "remoteHint": "Run `kilo remote` on your computer, or `/remote` in a running CLI session, to control a local kilo process."
},
"partRenderer": {
"updatedFileCount_one": "An sabunta {{displayCount}} fayil",
@@ -2662,15 +2665,10 @@
"couldNotLoadSessions": "An kasa ɗora zaman",
"couldNotLoadActiveSessions": "An kasa ɗora zaman aiki",
"agentSessions": "Zaman wakilai",
- "showingSavedSessions": "Ana nuna zaman da aka adana — matsayin kai tsaye na iya zama tsoho",
- "startNewAgentSession": "Fara sabon zaman Kilo Agent",
- "aiCodingSessions": "Zaman shirye-shiryen AI",
- "startCodingTaskFromPhone": "Fara aikin shirye-shirye daga wayarka ko ci gaba da zama daga CLI ɗinka.",
- "tryIt": "Gwada shi",
"newCodingTask": "Sabon aikin shirye-shirye",
"explore": "Bincika",
"seeAll": "Duba duka",
- "kiloAgents": "Kilo Agents"
+ "noLiveSessions": "Nothing running right now"
},
"imageViewer": {
"close": "Rufe {{filename}}",
diff --git a/apps/mobile/src/i18n/locales/he.json b/apps/mobile/src/i18n/locales/he.json
index 9fca20e1be..2cc596b63d 100644
--- a/apps/mobile/src/i18n/locales/he.json
+++ b/apps/mobile/src/i18n/locales/he.json
@@ -148,7 +148,9 @@
"appearanceSystem": "מערכת",
"appearanceLight": "בהיר",
"appearanceDark": "כהה",
- "account": "חשבון"
+ "account": "חשבון",
+ "prReviewAttribution": "Add app attribution to PR reviews",
+ "prReviewAttributionSubtitle": "Append a Reviewed via Kilo footer when you submit a review."
},
"notifications": {
"title": "התראות",
@@ -1730,7 +1732,8 @@
"discardDraftMessage": "ההנחיה שלך תאבד.",
"discardDraftTitle": "לבטל את הטיוטה?",
"discardFailed": "לא ניתן היה לבטל את הטיוטה. נסה שוב.",
- "keepEditing": "המשך לערוך"
+ "keepEditing": "המשך לערוך",
+ "remoteHint": "Run `kilo remote` on your computer, or `/remote` in a running CLI session, to control a local kilo process."
},
"partRenderer": {
"updatedFileCount_one": "עודכן {{displayCount}} קובץ",
@@ -2221,15 +2224,10 @@
"couldNotLoadSessions": "לא ניתן לטעון הפעלות",
"couldNotLoadActiveSessions": "לא ניתן לטעון הפעלות פעילות",
"agentSessions": "הפעלות סוכן",
- "showingSavedSessions": "מציג הפעלות שמורות — המצב החי עשוי להיות לא מעודכן",
- "startNewAgentSession": "התחל הפעלת Kilo Agent חדשה",
- "aiCodingSessions": "הפעלות קידוד AI",
- "startCodingTaskFromPhone": "התחל משימת קידוד מהטלפון שלך או המשך הפעלה מה-CLI שלך.",
- "tryIt": "נסה זאת",
"newCodingTask": "משימת קידוד חדשה",
"explore": "חקור",
"seeAll": "ראה הכל",
- "kiloAgents": "סוכני Kilo"
+ "noLiveSessions": "Nothing running right now"
},
"imageViewer": {
"close": "סגור את {{filename}}",
diff --git a/apps/mobile/src/i18n/locales/hi.json b/apps/mobile/src/i18n/locales/hi.json
index 94107c0c25..abda782006 100644
--- a/apps/mobile/src/i18n/locales/hi.json
+++ b/apps/mobile/src/i18n/locales/hi.json
@@ -148,7 +148,9 @@
"appearanceSystem": "सिस्टम",
"appearanceLight": "हल्का",
"appearanceDark": "गहरा",
- "account": "खाता"
+ "account": "खाता",
+ "prReviewAttribution": "Add app attribution to PR reviews",
+ "prReviewAttributionSubtitle": "Append a Reviewed via Kilo footer when you submit a review."
},
"notifications": {
"title": "सूचनाएँ",
@@ -1722,7 +1724,8 @@
"discardDraftMessage": "आपका प्रॉम्प्ट खो जाएगा।",
"discardDraftTitle": "ड्राफ़्ट छोड़ें?",
"discardFailed": "ड्राफ़्ट छोड़ा नहीं जा सका। कृपया फिर से कोशिश करें।",
- "keepEditing": "संपादन जारी रखें"
+ "keepEditing": "संपादन जारी रखें",
+ "remoteHint": "Run `kilo remote` on your computer, or `/remote` in a running CLI session, to control a local kilo process."
},
"partRenderer": {
"updatedFileCount_one": "{{displayCount}} फ़ाइल अपडेट की गई",
@@ -2208,15 +2211,10 @@
"couldNotLoadSessions": "सत्र लोड नहीं हो सके",
"couldNotLoadActiveSessions": "सक्रिय सत्र लोड नहीं हो सके",
"agentSessions": "एजेंट सत्र",
- "showingSavedSessions": "सहेजे गए सत्र दिखाए जा रहे हैं — लाइव स्थिति पुरानी हो सकती है",
- "startNewAgentSession": "नया Kilo एजेंट सत्र शुरू करें",
- "aiCodingSessions": "AI कोडिंग सत्र",
- "startCodingTaskFromPhone": "अपने फ़ोन से कोडिंग कार्य शुरू करें या अपने CLI से सत्र जारी रखें।",
- "tryIt": "इसे आज़माएँ",
"newCodingTask": "नया कोडिंग कार्य",
"explore": "एक्सप्लोर करें",
"seeAll": "सभी देखें",
- "kiloAgents": "Kilo एजेंट"
+ "noLiveSessions": "Nothing running right now"
},
"imageViewer": {
"close": "{{filename}} बंद करें",
diff --git a/apps/mobile/src/i18n/locales/hr.json b/apps/mobile/src/i18n/locales/hr.json
index a326f7c7f8..c5062788d7 100644
--- a/apps/mobile/src/i18n/locales/hr.json
+++ b/apps/mobile/src/i18n/locales/hr.json
@@ -148,7 +148,9 @@
"appearanceSystem": "Sustav",
"appearanceLight": "Svijetlo",
"appearanceDark": "Tamno",
- "account": "Račun"
+ "account": "Račun",
+ "prReviewAttribution": "Add app attribution to PR reviews",
+ "prReviewAttributionSubtitle": "Append a Reviewed via Kilo footer when you submit a review."
},
"prReview": {
"pullRequestUnavailable": "Pull request nedostupan",
@@ -2191,7 +2193,8 @@
"discardDraftMessage": "Vaš će upit biti izgubljen.",
"keepEditing": "Nastavi s uređivanjem",
"discard": "Odbaci",
- "discardFailed": "Nije moguće odbaciti nacrt. Pokušajte ponovno."
+ "discardFailed": "Nije moguće odbaciti nacrt. Pokušajte ponovno.",
+ "remoteHint": "Run `kilo remote` on your computer, or `/remote` in a running CLI session, to control a local kilo process."
},
"partRenderer": {
"updatedFileCount_one": "Ažurirana {{displayCount}} datoteka",
@@ -2682,15 +2685,10 @@
"couldNotLoadSessions": "Nije moguće učitati sesije",
"couldNotLoadActiveSessions": "Nije moguće učitati aktivne sesije",
"agentSessions": "Sesije agenata",
- "showingSavedSessions": "Prikazuju se spremljene sesije — živi status može biti zastario",
- "startNewAgentSession": "Pokreni novu Kilo Agent sesiju",
- "aiCodingSessions": "AI sesije kodiranja",
- "startCodingTaskFromPhone": "Pokrenite zadatak kodiranja s telefona ili nastavite sesiju sa svog CLI-ja.",
- "tryIt": "Isprobaj",
"newCodingTask": "Novi zadatak kodiranja",
"explore": "Istraži",
"seeAll": "Prikaži sve",
- "kiloAgents": "Kilo Agenti"
+ "noLiveSessions": "Nothing running right now"
},
"imageViewer": {
"close": "Zatvori {{filename}}",
diff --git a/apps/mobile/src/i18n/locales/ht.json b/apps/mobile/src/i18n/locales/ht.json
index 1623abeae8..a40618b668 100644
--- a/apps/mobile/src/i18n/locales/ht.json
+++ b/apps/mobile/src/i18n/locales/ht.json
@@ -148,7 +148,9 @@
"appearanceSystem": "Sistèm",
"appearanceLight": "Limye",
"appearanceDark": "Fènwa",
- "account": "Kont"
+ "account": "Kont",
+ "prReviewAttribution": "Add app attribution to PR reviews",
+ "prReviewAttributionSubtitle": "Append a Reviewed via Kilo footer when you submit a review."
},
"prReview": {
"pullRequestUnavailable": "Demand rale pa disponib",
@@ -2176,7 +2178,8 @@
"discardDraftMessage": "Pwòp prompt ou a pral pèdi.",
"keepEditing": "Kontinye Editè",
"discard": "Jete",
- "discardFailed": "Pa t 'kapab jete bouyon an. Tanpri eseye ankò."
+ "discardFailed": "Pa t 'kapab jete bouyon an. Tanpri eseye ankò.",
+ "remoteHint": "Run `kilo remote` on your computer, or `/remote` in a running CLI session, to control a local kilo process."
},
"partRenderer": {
"updatedFileCount_one": "Miz ajou {{displayCount}} fichye",
@@ -2662,15 +2665,10 @@
"couldNotLoadSessions": "Pa t ka chaje sesyon",
"couldNotLoadActiveSessions": "Pa t ka chaje sesyon aktif",
"agentSessions": "Sesyon ajant",
- "showingSavedSessions": "Ap montre sesyon sove — estati vivan ka pa fèt rive",
- "startNewAgentSession": "Kòmanse yon nouvo sesyon Kilo Ajant",
- "aiCodingSessions": "Sesyon kodaj AI",
- "startCodingTaskFromPhone": "Kòmanse yon travay kodaj soti nan telefòn ou oswa kontinye yon sesyon soti nan CLI ou.",
- "tryIt": "Eseye li",
"newCodingTask": "Nouvo travay kodaj",
"explore": "Eksplore",
"seeAll": "Wè tout",
- "kiloAgents": "Kilo Ajant"
+ "noLiveSessions": "Nothing running right now"
},
"imageViewer": {
"close": "Fèmen {{filename}}",
diff --git a/apps/mobile/src/i18n/locales/hu.json b/apps/mobile/src/i18n/locales/hu.json
index 68344e07ca..a0b7f54735 100644
--- a/apps/mobile/src/i18n/locales/hu.json
+++ b/apps/mobile/src/i18n/locales/hu.json
@@ -148,7 +148,9 @@
"appearanceSystem": "Rendszer",
"appearanceLight": "Világos",
"appearanceDark": "Sötét",
- "account": "Fiók"
+ "account": "Fiók",
+ "prReviewAttribution": "Add app attribution to PR reviews",
+ "prReviewAttributionSubtitle": "Append a Reviewed via Kilo footer when you submit a review."
},
"prReview": {
"pullRequestUnavailable": "Pull request nem érhető el",
@@ -2176,7 +2178,8 @@
"discardDraftMessage": "A promptja el fog veszni.",
"keepEditing": "Szerkesztés folytatása",
"discard": "Elvetés",
- "discardFailed": "A piszkozat elvetése nem sikerült. Próbálja újra."
+ "discardFailed": "A piszkozat elvetése nem sikerült. Próbálja újra.",
+ "remoteHint": "Run `kilo remote` on your computer, or `/remote` in a running CLI session, to control a local kilo process."
},
"partRenderer": {
"updatedFileCount_one": "{{displayCount}} fájl frissítve",
@@ -2662,15 +2665,10 @@
"couldNotLoadSessions": "A munkameneteket nem sikerült betölteni",
"couldNotLoadActiveSessions": "Az aktív munkameneteket nem sikerült betölteni",
"agentSessions": "Ügynök munkamenetek",
- "showingSavedSessions": "Mentett munkamenetek megjelenítése — az élő állapot elavult lehet",
- "startNewAgentSession": "Új Kilo Agent munkamenet indítása",
- "aiCodingSessions": "AI kódolási munkamenetek",
- "startCodingTaskFromPhone": "Indíts kódolási feladatot a telefonodról, vagy folytass egy munkamenetet a CLI-dből.",
- "tryIt": "Kipróbálom",
"newCodingTask": "Új kódolási feladat",
"explore": "Felfedezés",
"seeAll": "Összes megtekintése",
- "kiloAgents": "Kilo Agents"
+ "noLiveSessions": "Nothing running right now"
},
"imageViewer": {
"close": "{{filename}} bezárása",
diff --git a/apps/mobile/src/i18n/locales/hy.json b/apps/mobile/src/i18n/locales/hy.json
index 1ef4ba1003..7efc2b9fcd 100644
--- a/apps/mobile/src/i18n/locales/hy.json
+++ b/apps/mobile/src/i18n/locales/hy.json
@@ -148,7 +148,9 @@
"appearanceSystem": "Համակարգ",
"appearanceLight": "Բաց",
"appearanceDark": "Մուգ",
- "account": "Հաշիվ"
+ "account": "Հաշիվ",
+ "prReviewAttribution": "Add app attribution to PR reviews",
+ "prReviewAttributionSubtitle": "Append a Reviewed via Kilo footer when you submit a review."
},
"prReview": {
"pullRequestUnavailable": "Pull request-ը հասանելի չէ",
@@ -2176,7 +2178,8 @@
"discardDraftMessage": "Ձեր հուշումը կկորչի։",
"keepEditing": "Շարունակել խմբագրել",
"discard": "Մերժել",
- "discardFailed": "Չհաջողվեց մերժել սևագիրը։ Խնդրում ենք կրկին փորձել։"
+ "discardFailed": "Չհաջողվեց մերժել սևագիրը։ Խնդրում ենք կրկին փորձել։",
+ "remoteHint": "Run `kilo remote` on your computer, or `/remote` in a running CLI session, to control a local kilo process."
},
"partRenderer": {
"updatedFileCount_one": "Թարմացվել է {{displayCount}} ֆայլ",
@@ -2662,15 +2665,10 @@
"couldNotLoadSessions": "Հնարավոր չեղավ բեռնել նիստերը",
"couldNotLoadActiveSessions": "Հնարավոր չեղավ բեռնել ակտիվ նիստերը",
"agentSessions": "Գործակալի նիստեր",
- "showingSavedSessions": "Ցուցադրվում են պահված նիստերը — կենդանի կարգավիճակը կարող է հնացած լինել",
- "startNewAgentSession": "Սկսել նոր Kilo Agent նիստ",
- "aiCodingSessions": "AI ծրագրավորման նիստեր",
- "startCodingTaskFromPhone": "Սկսեք ծրագրավորման առաջադրանք ձեր հեռախոսից կամ շարունակեք նիստը ձեր CLI-ից:",
- "tryIt": "Փորձեք",
"newCodingTask": "Նոր ծրագրավորման առաջադրանք",
"explore": "Ուսումնասիրել",
"seeAll": "Տեսնել բոլորը",
- "kiloAgents": "Kilo Agents"
+ "noLiveSessions": "Nothing running right now"
},
"imageViewer": {
"close": "Փակել {{filename}}-ը",
diff --git a/apps/mobile/src/i18n/locales/id.json b/apps/mobile/src/i18n/locales/id.json
index a37c7dabea..c7747e0c6b 100644
--- a/apps/mobile/src/i18n/locales/id.json
+++ b/apps/mobile/src/i18n/locales/id.json
@@ -148,7 +148,9 @@
"appearanceSystem": "Sistem",
"appearanceLight": "Terang",
"appearanceDark": "Gelap",
- "account": "Akun"
+ "account": "Akun",
+ "prReviewAttribution": "Add app attribution to PR reviews",
+ "prReviewAttributionSubtitle": "Append a Reviewed via Kilo footer when you submit a review."
},
"notifications": {
"title": "Notifikasi",
@@ -1722,7 +1724,8 @@
"discardDraftMessage": "Prompt Anda akan hilang.",
"discardDraftTitle": "Buang draf?",
"discardFailed": "Tidak dapat membuang draf. Silakan coba lagi.",
- "keepEditing": "Tetap mengedit"
+ "keepEditing": "Tetap mengedit",
+ "remoteHint": "Run `kilo remote` on your computer, or `/remote` in a running CLI session, to control a local kilo process."
},
"partRenderer": {
"updatedFileCount_one": "Memperbarui {{displayCount}} file",
@@ -2208,15 +2211,10 @@
"couldNotLoadSessions": "Tidak dapat memuat sesi",
"couldNotLoadActiveSessions": "Tidak dapat memuat sesi aktif",
"agentSessions": "Sesi agen",
- "showingSavedSessions": "Menampilkan sesi tersimpan — status langsung mungkin kedaluwarsa",
- "startNewAgentSession": "Mulai sesi Agen Kilo baru",
- "aiCodingSessions": "Sesi coding AI",
- "startCodingTaskFromPhone": "Mulai tugas coding dari ponsel Anda atau lanjutkan sesi dari CLI Anda.",
- "tryIt": "Coba",
"newCodingTask": "Tugas coding baru",
"explore": "Jelajahi",
"seeAll": "Lihat semua",
- "kiloAgents": "Agen Kilo"
+ "noLiveSessions": "Nothing running right now"
},
"imageViewer": {
"close": "Tutup {{filename}}",
diff --git a/apps/mobile/src/i18n/locales/ig.json b/apps/mobile/src/i18n/locales/ig.json
index 6648d92eaa..9bd05e1fd4 100644
--- a/apps/mobile/src/i18n/locales/ig.json
+++ b/apps/mobile/src/i18n/locales/ig.json
@@ -148,7 +148,9 @@
"appearanceSystem": "Sistemụ",
"appearanceLight": "Ìhè",
"appearanceDark": "Ọchịchịrị",
- "account": "Akaụntụ"
+ "account": "Akaụntụ",
+ "prReviewAttribution": "Add app attribution to PR reviews",
+ "prReviewAttributionSubtitle": "Append a Reviewed via Kilo footer when you submit a review."
},
"prReview": {
"pullRequestUnavailable": "Arịrịọ dọrọ adịghị",
@@ -2176,7 +2178,8 @@
"discardDraftMessage": "Ihe ị dere ga-efu.",
"keepEditing": "Nọgide na-edezi",
"discard": "Tụfuo",
- "discardFailed": "Enweghị ike ịtụfu akwụkwọ a na-ede. Biko nwaa ọzọ."
+ "discardFailed": "Enweghị ike ịtụfu akwụkwọ a na-ede. Biko nwaa ọzọ.",
+ "remoteHint": "Run `kilo remote` on your computer, or `/remote` in a running CLI session, to control a local kilo process."
},
"partRenderer": {
"updatedFileCount_one": "Emelitere {{displayCount}} faịlụ",
@@ -2662,15 +2665,10 @@
"couldNotLoadSessions": "Enweghị ike ibutu nnọkọ",
"couldNotLoadActiveSessions": "Enweghị ike ibutu nnọkọ na-arụ ọrụ",
"agentSessions": "Nnọkọ onye nnọchite",
- "showingSavedSessions": "Na-egosi nnọkọ echekwara — ọnọdụ ndụ nwere ike ịgafe oge",
- "startNewAgentSession": "Malite nnọkọ Kilo Agent ọhụrụ",
- "aiCodingSessions": "Nnọkọ ịde koodu AI",
- "startCodingTaskFromPhone": "Malite ọrụ ịde koodu site na ekwentị gị ma ọ bụ gaa n'ihu na nnọkọ site na CLI gị.",
- "tryIt": "Nwaa ya",
"newCodingTask": "Ọrụ ịde koodu ọhụrụ",
"explore": "Chọpụta",
"seeAll": "Hụ niile",
- "kiloAgents": "Ndị nnọchite Kilo"
+ "noLiveSessions": "Nothing running right now"
},
"imageViewer": {
"close": "Mechie {{filename}}",
diff --git a/apps/mobile/src/i18n/locales/is.json b/apps/mobile/src/i18n/locales/is.json
index 0edb0a5e81..b231258f38 100644
--- a/apps/mobile/src/i18n/locales/is.json
+++ b/apps/mobile/src/i18n/locales/is.json
@@ -148,7 +148,9 @@
"appearanceSystem": "Kerfi",
"appearanceLight": "Ljóst",
"appearanceDark": "Dökkt",
- "account": "Reikningur"
+ "account": "Reikningur",
+ "prReviewAttribution": "Add app attribution to PR reviews",
+ "prReviewAttributionSubtitle": "Append a Reviewed via Kilo footer when you submit a review."
},
"prReview": {
"pullRequestUnavailable": "Pull request ótiltækur",
@@ -2176,7 +2178,8 @@
"discardDraftMessage": "Skilaboðin þín glatast.",
"keepEditing": "Halda áfram að breyta",
"discard": "Farga",
- "discardFailed": "Ekki tókst að farga drögunum. Reyndu aftur."
+ "discardFailed": "Ekki tókst að farga drögunum. Reyndu aftur.",
+ "remoteHint": "Run `kilo remote` on your computer, or `/remote` in a running CLI session, to control a local kilo process."
},
"partRenderer": {
"updatedFileCount_one": "Uppfærði {{displayCount}} skrá",
@@ -2662,15 +2665,10 @@
"couldNotLoadSessions": "Ekki tókst að hlaða lotur",
"couldNotLoadActiveSessions": "Ekki tókst að hlaða virkar lotur",
"agentSessions": "Umboðslotur",
- "showingSavedSessions": "Sýni vistaðar lotur — rauntímastaða getur verið úrelt",
- "startNewAgentSession": "Byrja nýja Kilo-umboðslotu",
- "aiCodingSessions": "AI-forritunarlotur",
- "startCodingTaskFromPhone": "Byrjaðu forritunarverkefni úr símanum þínum eða haltu áfram lotu frá CLI.",
- "tryIt": "Prófaðu það",
"newCodingTask": "Nýtt forritunarverkefni",
"explore": "Kanna",
"seeAll": "Sjá allt",
- "kiloAgents": "Kilo-umboð"
+ "noLiveSessions": "Nothing running right now"
},
"imageViewer": {
"close": "Loka {{filename}}",
diff --git a/apps/mobile/src/i18n/locales/it.json b/apps/mobile/src/i18n/locales/it.json
index a79bcc768d..7cb64b5d5b 100644
--- a/apps/mobile/src/i18n/locales/it.json
+++ b/apps/mobile/src/i18n/locales/it.json
@@ -1716,7 +1716,8 @@
"discardDraftMessage": "Il tuo prompt andrà perso.",
"discardDraftTitle": "Scartare la bozza?",
"discardFailed": "Impossibile scartare la bozza. Riprova.",
- "keepEditing": "Continua a modificare"
+ "keepEditing": "Continua a modificare",
+ "remoteHint": "Run `kilo remote` on your computer, or `/remote` in a running CLI session, to control a local kilo process."
},
"partRenderer": {
"updatedFileCount_one": "Aggiornato {{displayCount}} file",
@@ -2182,7 +2183,9 @@
"appearanceSystem": "Sistema",
"appearanceLight": "Chiaro",
"appearanceDark": "Scuro",
- "account": "Account"
+ "account": "Account",
+ "prReviewAttribution": "Add app attribution to PR reviews",
+ "prReviewAttributionSubtitle": "Append a Reviewed via Kilo footer when you submit a review."
},
"addCredits": {
"cta": "Aggiungi crediti",
@@ -2221,15 +2224,10 @@
"couldNotLoadSessions": "Impossibile caricare le sessioni",
"couldNotLoadActiveSessions": "Impossibile caricare le sessioni attive",
"agentSessions": "Sessioni agente",
- "showingSavedSessions": "Visualizzazione delle sessioni salvate — lo stato live potrebbe non essere aggiornato",
- "startNewAgentSession": "Avvia una nuova sessione Kilo Agent",
- "aiCodingSessions": "Sessioni di codifica IA",
- "startCodingTaskFromPhone": "Avvia un'attività di codifica dal telefono o continua una sessione dalla CLI.",
- "tryIt": "Provalo",
"newCodingTask": "Nuova attività di codifica",
"explore": "Esplora",
"seeAll": "Vedi tutto",
- "kiloAgents": "Agenti Kilo"
+ "noLiveSessions": "Nothing running right now"
},
"imageViewer": {
"close": "Chiudi {{filename}}",
diff --git a/apps/mobile/src/i18n/locales/ja.json b/apps/mobile/src/i18n/locales/ja.json
index 86643aa019..a74bf2be2e 100644
--- a/apps/mobile/src/i18n/locales/ja.json
+++ b/apps/mobile/src/i18n/locales/ja.json
@@ -148,7 +148,9 @@
"appearanceSystem": "システム",
"appearanceLight": "ライト",
"appearanceDark": "ダーク",
- "account": "アカウント"
+ "account": "アカウント",
+ "prReviewAttribution": "Add app attribution to PR reviews",
+ "prReviewAttributionSubtitle": "Append a Reviewed via Kilo footer when you submit a review."
},
"notifications": {
"title": "通知",
@@ -1722,7 +1724,8 @@
"discardDraftMessage": "プロンプトは失われます。",
"discardDraftTitle": "下書きを破棄しますか?",
"discardFailed": "下書きを破棄できませんでした。もう一度お試しください。",
- "keepEditing": "編集を続ける"
+ "keepEditing": "編集を続ける",
+ "remoteHint": "Run `kilo remote` on your computer, or `/remote` in a running CLI session, to control a local kilo process."
},
"partRenderer": {
"updatedFileCount_one": "{{displayCount}}件のファイルを更新しました",
@@ -2208,15 +2211,10 @@
"couldNotLoadSessions": "セッションを読み込めませんでした",
"couldNotLoadActiveSessions": "アクティブなセッションを読み込めませんでした",
"agentSessions": "エージェントセッション",
- "showingSavedSessions": "保存されたセッションを表示中 — ライブステータスが古い場合があります",
- "startNewAgentSession": "新しいKiloエージェントセッションを開始",
- "aiCodingSessions": "AIコーディングセッション",
- "startCodingTaskFromPhone": "スマートフォンからコーディングタスクを開始するか、CLIからセッションを続行します。",
- "tryIt": "試す",
"newCodingTask": "新しいコーディングタスク",
"explore": "探索",
"seeAll": "すべて表示",
- "kiloAgents": "Kiloエージェント"
+ "noLiveSessions": "Nothing running right now"
},
"imageViewer": {
"close": "{{filename}}を閉じる",
diff --git a/apps/mobile/src/i18n/locales/ka.json b/apps/mobile/src/i18n/locales/ka.json
index 6e5b5e15b9..be67cb3713 100644
--- a/apps/mobile/src/i18n/locales/ka.json
+++ b/apps/mobile/src/i18n/locales/ka.json
@@ -148,7 +148,9 @@
"appearanceSystem": "სისტემა",
"appearanceLight": "ღია",
"appearanceDark": "მუქი",
- "account": "ანგარიში"
+ "account": "ანგარიში",
+ "prReviewAttribution": "Add app attribution to PR reviews",
+ "prReviewAttributionSubtitle": "Append a Reviewed via Kilo footer when you submit a review."
},
"prReview": {
"pullRequestUnavailable": "პულ-რექვესთი მიუწვდომელია",
@@ -2176,7 +2178,8 @@
"discardDraftMessage": "თქვენი შეტყობინება დაიკარგება.",
"keepEditing": "რედაქტირების გაგრძელება",
"discard": "გაუქმება",
- "discardFailed": "დრაფტის გაუქმება ვერ მოხერხდა. გთხოვთ, სცადეთ ხელახლა."
+ "discardFailed": "დრაფტის გაუქმება ვერ მოხერხდა. გთხოვთ, სცადეთ ხელახლა.",
+ "remoteHint": "Run `kilo remote` on your computer, or `/remote` in a running CLI session, to control a local kilo process."
},
"partRenderer": {
"updatedFileCount_one": "განახლდა {{displayCount}} ფაილი",
@@ -2662,15 +2665,10 @@
"couldNotLoadSessions": "სესიების ჩატვირთვა ვერ მოხერხდა",
"couldNotLoadActiveSessions": "აქტიური სესიების ჩატვირთვა ვერ მოხერხდა",
"agentSessions": "აგენტის სესიები",
- "showingSavedSessions": "ნაჩვენებია შენახული სესიები — პირდაპირი სტატუსი შეიძლება მოძველებული იყოს",
- "startNewAgentSession": "ახალი Kilo აგენტის სესიის დაწყება",
- "aiCodingSessions": "AI კოდირების სესიები",
- "startCodingTaskFromPhone": "დაიწყეთ კოდირების ამოცანა ტელეფონიდან ან გააგრძელეთ სესია CLI-დან.",
- "tryIt": "სცადეთ",
"newCodingTask": "ახალი კოდირების ამოცანა",
"explore": "გამოკვლევა",
"seeAll": "ყველას ნახვა",
- "kiloAgents": "Kilo აგენტები"
+ "noLiveSessions": "Nothing running right now"
},
"imageViewer": {
"close": "{{filename}} დახურვა",
diff --git a/apps/mobile/src/i18n/locales/kk.json b/apps/mobile/src/i18n/locales/kk.json
index 3de9aff0e1..5872837111 100644
--- a/apps/mobile/src/i18n/locales/kk.json
+++ b/apps/mobile/src/i18n/locales/kk.json
@@ -148,7 +148,9 @@
"appearanceSystem": "Жүйе",
"appearanceLight": "Жарық",
"appearanceDark": "Қараңғы",
- "account": "Тіркелгі"
+ "account": "Тіркелгі",
+ "prReviewAttribution": "Add app attribution to PR reviews",
+ "prReviewAttributionSubtitle": "Append a Reviewed via Kilo footer when you submit a review."
},
"prReview": {
"pullRequestUnavailable": "Pull request қолжетімсіз",
@@ -2176,7 +2178,8 @@
"discardDraftMessage": "Сұрағыңыз жоғалады.",
"keepEditing": "Өңдеуді жалғастыру",
"discard": "Жою",
- "discardFailed": "Жобаны жою мүмкін болмады. Қайталап көріңіз."
+ "discardFailed": "Жобаны жою мүмкін болмады. Қайталап көріңіз.",
+ "remoteHint": "Run `kilo remote` on your computer, or `/remote` in a running CLI session, to control a local kilo process."
},
"partRenderer": {
"updatedFileCount_one": "{{displayCount}} файл жаңартылды",
@@ -2662,15 +2665,10 @@
"couldNotLoadSessions": "Сессияларды жүктеу мүмкін болмады",
"couldNotLoadActiveSessions": "Белсенді сессияларды жүктеу мүмкін болмады",
"agentSessions": "Агент сессиялары",
- "showingSavedSessions": "Сақталған сессиялар көрсетілуде — тірі күй ескіруі мүмкін",
- "startNewAgentSession": "Жаңа Kilo Agent сессиясын бастау",
- "aiCodingSessions": "AI бағдарламалау сессиялары",
- "startCodingTaskFromPhone": "Телефоннан бағдарламалау тапсырмасын бастаңыз немесе CLI-ден сессияны жалғастырыңыз.",
- "tryIt": "Көру",
"newCodingTask": "Жаңа бағдарламалау тапсырмасы",
"explore": "Зерттеу",
"seeAll": "Барлығын қарау",
- "kiloAgents": "Kilo Agent"
+ "noLiveSessions": "Nothing running right now"
},
"imageViewer": {
"close": "{{filename}} жабу",
diff --git a/apps/mobile/src/i18n/locales/km.json b/apps/mobile/src/i18n/locales/km.json
index 5a0f3fe509..18872d2a18 100644
--- a/apps/mobile/src/i18n/locales/km.json
+++ b/apps/mobile/src/i18n/locales/km.json
@@ -148,7 +148,9 @@
"appearanceSystem": "ប្រព័ន្ធ",
"appearanceLight": "ភ្លឺ",
"appearanceDark": "ងងឹត",
- "account": "គណនី"
+ "account": "គណនី",
+ "prReviewAttribution": "Add app attribution to PR reviews",
+ "prReviewAttributionSubtitle": "Append a Reviewed via Kilo footer when you submit a review."
},
"prReview": {
"pullRequestUnavailable": "សំណើទាញ (pull request) មិនអាចប្រើបានទេ",
@@ -2176,7 +2178,8 @@
"discardDraftMessage": "ប្រអប់បញ្ចូលរបស់អ្នកនឹងត្រូវបាត់បង់។",
"keepEditing": "បន្តកែសម្រួល",
"discard": "បោះបង់",
- "discardFailed": "មិនអាចបោះបង់សេចក្តីព្រាងបានទេ។ សូមព្យាយាមម្តងទៀត។"
+ "discardFailed": "មិនអាចបោះបង់សេចក្តីព្រាងបានទេ។ សូមព្យាយាមម្តងទៀត។",
+ "remoteHint": "Run `kilo remote` on your computer, or `/remote` in a running CLI session, to control a local kilo process."
},
"partRenderer": {
"updatedFileCount_one": "បានធ្វើបច្ចុប្បន្នភាពឯកសារ {{displayCount}}",
@@ -2662,15 +2665,10 @@
"couldNotLoadSessions": "មិនអាចផ្ទុកវគ្គបានទេ",
"couldNotLoadActiveSessions": "មិនអាចផ្ទុកវគ្គសកម្មបានទេ",
"agentSessions": "វគ្គភ្នាក់ងារ",
- "showingSavedSessions": "កំពុងបង្ហាញវគ្គដែលបានរក្សាទុក — ស្ថានភាពបន្តផ្ទាល់អាចហួសសម័យ",
- "startNewAgentSession": "ចាប់ផ្តើមវគ្គ Kilo Agent ថ្មី",
- "aiCodingSessions": "វគ្គសរសេរកូដ AI",
- "startCodingTaskFromPhone": "ចាប់ផ្តើមកិច្ចការសរសេរកូដពីទូរសព្ទរបស់អ្នក ឬបន្តវគ្គពី CLI របស់អ្នក។",
- "tryIt": "សាកល្បង",
"newCodingTask": "កិច្ចការសរសេរកូដថ្មី",
"explore": "ស្វែងយល់",
"seeAll": "មើលទាំងអស់",
- "kiloAgents": "Kilo Agents"
+ "noLiveSessions": "Nothing running right now"
},
"imageViewer": {
"close": "បិទ {{filename}}",
diff --git a/apps/mobile/src/i18n/locales/kn.json b/apps/mobile/src/i18n/locales/kn.json
index 8418878554..82aaa5f329 100644
--- a/apps/mobile/src/i18n/locales/kn.json
+++ b/apps/mobile/src/i18n/locales/kn.json
@@ -148,7 +148,9 @@
"appearanceSystem": "ಸಿಸ್ಟಮ್",
"appearanceLight": "ಲೈಟ್",
"appearanceDark": "ಡಾರ್ಕ್",
- "account": "ಖಾತೆ"
+ "account": "ಖಾತೆ",
+ "prReviewAttribution": "Add app attribution to PR reviews",
+ "prReviewAttributionSubtitle": "Append a Reviewed via Kilo footer when you submit a review."
},
"prReview": {
"pullRequestUnavailable": "ಪುಲ್ ರಿಕ್ವೆಸ್ಟ್ ಲಭ್ಯವಿಲ್ಲ",
@@ -2176,7 +2178,8 @@
"discardDraftMessage": "ನಿಮ್ಮ ಪ್ರಾಂಪ್ಟ್ ಕಳೆದುಹೋಗುತ್ತದೆ.",
"keepEditing": "ಸಂಪಾದನೆಯನ್ನು ಮುಂದುವರಿಸಿ",
"discard": "ತೆಗೆದುಹಾಕಿ",
- "discardFailed": "ಡ್ರಾಫ್ಟ್ ತೆಗೆದುಹಾಕಲು ಸಾಧ್ಯವಾಗಲಿಲ್ಲ. ದಯವಿಟ್ಟು ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ."
+ "discardFailed": "ಡ್ರಾಫ್ಟ್ ತೆಗೆದುಹಾಕಲು ಸಾಧ್ಯವಾಗಲಿಲ್ಲ. ದಯವಿಟ್ಟು ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ.",
+ "remoteHint": "Run `kilo remote` on your computer, or `/remote` in a running CLI session, to control a local kilo process."
},
"partRenderer": {
"updatedFileCount_one": "{{displayCount}} ಫೈಲ್ ನವೀಕರಿಸಲಾಗಿದೆ",
@@ -2662,15 +2665,10 @@
"couldNotLoadSessions": "ಸೆಷನ್ಗಳನ್ನು ಲೋಡ್ ಮಾಡಲು ಸಾಧ್ಯವಾಗಲಿಲ್ಲ",
"couldNotLoadActiveSessions": "ಸಕ್ರಿಯ ಸೆಷನ್ಗಳನ್ನು ಲೋಡ್ ಮಾಡಲು ಸಾಧ್ಯವಾಗಲಿಲ್ಲ",
"agentSessions": "ಏಜೆಂಟ್ ಸೆಷನ್ಗಳು",
- "showingSavedSessions": "ಉಳಿಸಿದ ಸೆಷನ್ಗಳನ್ನು ತೋರಿಸುತ್ತಿದೆ — ಲೈವ್ ಸ್ಥಿತಿ ಹಳೆಯದಾಗಿರಬಹುದು",
- "startNewAgentSession": "ಹೊಸ Kilo Agent ಸೆಷನ್ ಪ್ರಾರಂಭಿಸಿ",
- "aiCodingSessions": "AI ಕೋಡಿಂಗ್ ಸೆಷನ್ಗಳು",
- "startCodingTaskFromPhone": "ನಿಮ್ಮ ಫೋನ್ನಿಂದ ಕೋಡಿಂಗ್ ಕಾರ್ಯ ಪ್ರಾರಂಭಿಸಿ ಅಥವಾ ನಿಮ್ಮ CLI ಯಿಂದ ಸೆಷನ್ ಮುಂದುವರಿಸಿ.",
- "tryIt": "ಪ್ರಯತ್ನಿಸಿ",
"newCodingTask": "ಹೊಸ ಕೋಡಿಂಗ್ ಕಾರ್ಯ",
"explore": "ಅನ್ವೇಷಿಸಿ",
"seeAll": "ಎಲ್ಲವನ್ನೂ ನೋಡಿ",
- "kiloAgents": "Kilo Agents"
+ "noLiveSessions": "Nothing running right now"
},
"imageViewer": {
"close": "{{filename}} ಮುಚ್ಚಿ",
diff --git a/apps/mobile/src/i18n/locales/ko.json b/apps/mobile/src/i18n/locales/ko.json
index a4e9241094..80153760f0 100644
--- a/apps/mobile/src/i18n/locales/ko.json
+++ b/apps/mobile/src/i18n/locales/ko.json
@@ -148,7 +148,9 @@
"appearanceSystem": "시스템",
"appearanceLight": "밝음",
"appearanceDark": "어두움",
- "account": "계정"
+ "account": "계정",
+ "prReviewAttribution": "Add app attribution to PR reviews",
+ "prReviewAttributionSubtitle": "Append a Reviewed via Kilo footer when you submit a review."
},
"notifications": {
"title": "알림",
@@ -1722,7 +1724,8 @@
"discardDraftMessage": "프롬프트가 사라집니다.",
"discardDraftTitle": "초안을 삭제할까요?",
"discardFailed": "초안을 삭제할 수 없습니다. 다시 시도하세요.",
- "keepEditing": "계속 수정"
+ "keepEditing": "계속 수정",
+ "remoteHint": "Run `kilo remote` on your computer, or `/remote` in a running CLI session, to control a local kilo process."
},
"partRenderer": {
"updatedFileCount_one": "{{displayCount}}개 파일 업데이트됨",
@@ -2208,15 +2211,10 @@
"couldNotLoadSessions": "세션을 불러올 수 없습니다",
"couldNotLoadActiveSessions": "활성 세션을 불러올 수 없습니다",
"agentSessions": "에이전트 세션",
- "showingSavedSessions": "저장된 세션 표시 중 — 실시간 상태가 오래되었을 수 있습니다",
- "startNewAgentSession": "새 Kilo 에이전트 세션 시작",
- "aiCodingSessions": "AI 코딩 세션",
- "startCodingTaskFromPhone": "휴대폰에서 코딩 작업을 시작하거나 CLI에서 세션을 계속하세요.",
- "tryIt": "사용해 보기",
"newCodingTask": "새 코딩 작업",
"explore": "탐색",
"seeAll": "모두 보기",
- "kiloAgents": "Kilo 에이전트"
+ "noLiveSessions": "Nothing running right now"
},
"imageViewer": {
"close": "{{filename}} 닫기",
diff --git a/apps/mobile/src/i18n/locales/lo.json b/apps/mobile/src/i18n/locales/lo.json
index 9e49fa8614..dcace57225 100644
--- a/apps/mobile/src/i18n/locales/lo.json
+++ b/apps/mobile/src/i18n/locales/lo.json
@@ -148,7 +148,9 @@
"appearanceSystem": "ລະບົບ",
"appearanceLight": "ສະຫວ່າງ",
"appearanceDark": "ມືດ",
- "account": "ບັນຊີ"
+ "account": "ບັນຊີ",
+ "prReviewAttribution": "Add app attribution to PR reviews",
+ "prReviewAttributionSubtitle": "Append a Reviewed via Kilo footer when you submit a review."
},
"prReview": {
"pullRequestUnavailable": "pull request ບໍ່ພ້ອມໃຊ້",
@@ -2176,7 +2178,8 @@
"discardDraftMessage": "ຂໍ້ຄວາມຂອງທ່ານຈະຖືກລຶບ.",
"keepEditing": "ແກ້ໄຂຕໍ່ໄປ",
"discard": "ລະເລີຍ",
- "discardFailed": "ບໍ່ສາມາດລະເລີຍຮ່າງ. ກະລຸນາລອງໃໝ່."
+ "discardFailed": "ບໍ່ສາມາດລະເລີຍຮ່າງ. ກະລຸນາລອງໃໝ່.",
+ "remoteHint": "Run `kilo remote` on your computer, or `/remote` in a running CLI session, to control a local kilo process."
},
"partRenderer": {
"updatedFileCount_one": "ອັບເດດ {{displayCount}} ໄຟລ໌",
@@ -2662,15 +2665,10 @@
"couldNotLoadSessions": "ບໍ່ສາມາດໂຫລດເຊດຊັນ",
"couldNotLoadActiveSessions": "ບໍ່ສາມາດໂຫລດເຊດຊັນທີ່ໃຊ້ງານ",
"agentSessions": "ເຊດຊັນຕົວແທນ",
- "showingSavedSessions": "ສະແດງເຊດຊັນທີ່ບັນທຶກ — ສະຖານະສົດອາດລ້າສະໄຫມ",
- "startNewAgentSession": "ເລີ່ມເຊດຊັນ Kilo Agent ໃໝ່",
- "aiCodingSessions": "ເຊດຊັນການຂຽນໂຄ້ດ AI",
- "startCodingTaskFromPhone": "ເລີ່ມວຽກການຂຽນໂຄ້ດຈາກໂທລະສັບຂອງທ່ານ ຫຼື ສືບຕໍ່ເຊດຊັນຈາກ CLI ຂອງທ່ານ.",
- "tryIt": "ລອງໃຊ້",
"newCodingTask": "ວຽກການຂຽນໂຄ້ດໃໝ່",
"explore": "ສຳຫຼວດ",
"seeAll": "ເບິ່ງທັງໝົດ",
- "kiloAgents": "Kilo Agents"
+ "noLiveSessions": "Nothing running right now"
},
"imageViewer": {
"close": "ປິດ {{filename}}",
diff --git a/apps/mobile/src/i18n/locales/lt.json b/apps/mobile/src/i18n/locales/lt.json
index 7fc514cef3..58f6148de3 100644
--- a/apps/mobile/src/i18n/locales/lt.json
+++ b/apps/mobile/src/i18n/locales/lt.json
@@ -148,7 +148,9 @@
"appearanceSystem": "Sistema",
"appearanceLight": "Šviesi",
"appearanceDark": "Tamsi",
- "account": "Paskyra"
+ "account": "Paskyra",
+ "prReviewAttribution": "Add app attribution to PR reviews",
+ "prReviewAttributionSubtitle": "Append a Reviewed via Kilo footer when you submit a review."
},
"prReview": {
"pullRequestUnavailable": "Pull request nepasiekiamas",
@@ -2206,7 +2208,8 @@
"discardDraftMessage": "Jūsų užklausa bus prarasta.",
"keepEditing": "Tęsti redagavimą",
"discard": "Atmesti",
- "discardFailed": "Nepavyko atmesti juodraščio. Bandykite dar kartą."
+ "discardFailed": "Nepavyko atmesti juodraščio. Bandykite dar kartą.",
+ "remoteHint": "Run `kilo remote` on your computer, or `/remote` in a running CLI session, to control a local kilo process."
},
"partRenderer": {
"updatedFileCount_one": "Atnaujinta {{displayCount}} rinkmena",
@@ -2702,15 +2705,10 @@
"couldNotLoadSessions": "Nepavyko įkelti sesijų",
"couldNotLoadActiveSessions": "Nepavyko įkelti aktyvių sesijų",
"agentSessions": "Agentų sesijos",
- "showingSavedSessions": "Rodyti išsaugotos sesijos — tiesioginis statusas gali būti pasenęs",
- "startNewAgentSession": "Pradėti naują Kilo agento sesiją",
- "aiCodingSessions": "AI kodavimo sesijos",
- "startCodingTaskFromPhone": "Pradėkite kodavimo užduotį iš savo telefono arba tęskite sesiją iš savo CLI.",
- "tryIt": "Išbandyti",
"newCodingTask": "Nauja kodavimo užduotis",
"explore": "Naršyti",
"seeAll": "Rodyti viską",
- "kiloAgents": "Kilo agentai"
+ "noLiveSessions": "Nothing running right now"
},
"imageViewer": {
"close": "Uždaryti {{filename}}",
diff --git a/apps/mobile/src/i18n/locales/lv.json b/apps/mobile/src/i18n/locales/lv.json
index a3cecd5137..7f3da3ecc4 100644
--- a/apps/mobile/src/i18n/locales/lv.json
+++ b/apps/mobile/src/i18n/locales/lv.json
@@ -148,7 +148,9 @@
"appearanceSystem": "Sistēma",
"appearanceLight": "Gaišs",
"appearanceDark": "Tumšs",
- "account": "Konts"
+ "account": "Konts",
+ "prReviewAttribution": "Add app attribution to PR reviews",
+ "prReviewAttributionSubtitle": "Append a Reviewed via Kilo footer when you submit a review."
},
"prReview": {
"pullRequestUnavailable": "Pull request nav pieejams",
@@ -2191,7 +2193,8 @@
"discardDraftMessage": "Tavs jautājums tiks zaudēts.",
"keepEditing": "Turpināt rediģēšanu",
"discard": "Atmest",
- "discardFailed": "Neizdevās atmest melnrakstu. Lūdzu, mēģini vēlreiz."
+ "discardFailed": "Neizdevās atmest melnrakstu. Lūdzu, mēģini vēlreiz.",
+ "remoteHint": "Run `kilo remote` on your computer, or `/remote` in a running CLI session, to control a local kilo process."
},
"partRenderer": {
"updatedFileCount_one": "Atjaunināts {{displayCount}} fails",
@@ -2682,15 +2685,10 @@
"couldNotLoadSessions": "Neizdevās ielādēt sesijas",
"couldNotLoadActiveSessions": "Neizdevās ielādēt aktīvās sesijas",
"agentSessions": "Aģenta sesijas",
- "showingSavedSessions": "Tiek rādītas saglabātās sesijas — tiešais statuss var būt novecojis",
- "startNewAgentSession": "Sākt jaunu Kilo Agent sesiju",
- "aiCodingSessions": "AI kodēšanas sesijas",
- "startCodingTaskFromPhone": "Sāc kodēšanas uzdevumu no tālruņa vai turpini sesiju no sava CLI.",
- "tryIt": "Izmēģini",
"newCodingTask": "Jauns kodēšanas uzdevums",
"explore": "Izpētīt",
"seeAll": "Skatīt visus",
- "kiloAgents": "Kilo Agents"
+ "noLiveSessions": "Nothing running right now"
},
"imageViewer": {
"close": "Aizvērt {{filename}}",
diff --git a/apps/mobile/src/i18n/locales/mg.json b/apps/mobile/src/i18n/locales/mg.json
index 146db4af7b..dd5f9508a9 100644
--- a/apps/mobile/src/i18n/locales/mg.json
+++ b/apps/mobile/src/i18n/locales/mg.json
@@ -148,7 +148,9 @@
"appearanceSystem": "Rafitra",
"appearanceLight": "Mazava",
"appearanceDark": "Maizina",
- "account": "Kaonty"
+ "account": "Kaonty",
+ "prReviewAttribution": "Add app attribution to PR reviews",
+ "prReviewAttributionSubtitle": "Append a Reviewed via Kilo footer when you submit a review."
},
"prReview": {
"pullRequestUnavailable": "Tsy misy ny pull request",
@@ -2176,7 +2178,8 @@
"discardDraftMessage": "Ho very ny hafatrao.",
"keepEditing": "Tohizo ny fanitsiana",
"discard": "Ario",
- "discardFailed": "Tsy afaka nandao ny draft. Andramo indray azafady."
+ "discardFailed": "Tsy afaka nandao ny draft. Andramo indray azafady.",
+ "remoteHint": "Run `kilo remote` on your computer, or `/remote` in a running CLI session, to control a local kilo process."
},
"partRenderer": {
"updatedFileCount_one": "Nohavaozina ny rakitra {{displayCount}}",
@@ -2662,15 +2665,10 @@
"couldNotLoadSessions": "Tsy afaka nampidirina ny session",
"couldNotLoadActiveSessions": "Tsy afaka nampidirina ny session mavitrika",
"agentSessions": "Session agent",
- "showingSavedSessions": "Maneho ny session voatahiry — mety tsy manaraka fotoana ny toerana velona",
- "startNewAgentSession": "Atombohy session Kilo Agent vaovao",
- "aiCodingSessions": "Session coding AI",
- "startCodingTaskFromPhone": "Atombohy asa coding avy amin'ny findainao na tohizo session avy amin'ny CLI-nao.",
- "tryIt": "Andramo",
"newCodingTask": "Asa coding vaovao",
"explore": "Mijerena",
"seeAll": "Jereo daholo",
- "kiloAgents": "Kilo Agents"
+ "noLiveSessions": "Nothing running right now"
},
"imageViewer": {
"close": "Hanidy {{filename}}",
diff --git a/apps/mobile/src/i18n/locales/mi.json b/apps/mobile/src/i18n/locales/mi.json
index b95694790f..a309025f98 100644
--- a/apps/mobile/src/i18n/locales/mi.json
+++ b/apps/mobile/src/i18n/locales/mi.json
@@ -148,7 +148,9 @@
"appearanceSystem": "Pūnaha",
"appearanceLight": "Mārama",
"appearanceDark": "Pōuri",
- "account": "Pūkete"
+ "account": "Pūkete",
+ "prReviewAttribution": "Add app attribution to PR reviews",
+ "prReviewAttributionSubtitle": "Append a Reviewed via Kilo footer when you submit a review."
},
"prReview": {
"pullRequestUnavailable": "Kāore i te wātea te tono huna",
@@ -2176,7 +2178,8 @@
"discardDraftMessage": "Ka ngaro tō pātai.",
"keepEditing": "Me whakatika tonu",
"discard": "Whakarere",
- "discardFailed": "Kāore i taea te whakarere i te tauira. Tēnā whakamātau anō."
+ "discardFailed": "Kāore i taea te whakarere i te tauira. Tēnā whakamātau anō.",
+ "remoteHint": "Run `kilo remote` on your computer, or `/remote` in a running CLI session, to control a local kilo process."
},
"partRenderer": {
"updatedFileCount_one": "Kua whakahoutia {{displayCount}} kōnae",
@@ -2662,15 +2665,10 @@
"couldNotLoadSessions": "Kāore i taea te uta ngā wātū",
"couldNotLoadActiveSessions": "Kāore i taea te uta ngā wātū mahi",
"agentSessions": "Ngā wātū kaihoko",
- "showingSavedSessions": "E whakaatu ana i ngā wātū kua tiakina — kua tawhito pea te tūnga ora",
- "startNewAgentSession": "Tīmata he wātū Kaihoko Kilo hōu",
- "aiCodingSessions": "Ngā wātū whakawaehere AI",
- "startCodingTaskFromPhone": "Tīmata he mahi whakawaehere mai i tō waea, haere tonu rānei i tētahi wātū mai i tō CLI.",
- "tryIt": "Whakamātau",
"newCodingTask": "Mahi whakawaehere hōu",
"explore": "Torotoro",
"seeAll": "Tirohia katoa",
- "kiloAgents": "Ngā Kaihoko Kilo"
+ "noLiveSessions": "Nothing running right now"
},
"imageViewer": {
"close": "Katia {{filename}}",
diff --git a/apps/mobile/src/i18n/locales/mk.json b/apps/mobile/src/i18n/locales/mk.json
index 575c19ec55..2efb6c5730 100644
--- a/apps/mobile/src/i18n/locales/mk.json
+++ b/apps/mobile/src/i18n/locales/mk.json
@@ -148,7 +148,9 @@
"appearanceSystem": "Системски",
"appearanceLight": "Светло",
"appearanceDark": "Темно",
- "account": "Сметка"
+ "account": "Сметка",
+ "prReviewAttribution": "Add app attribution to PR reviews",
+ "prReviewAttributionSubtitle": "Append a Reviewed via Kilo footer when you submit a review."
},
"prReview": {
"pullRequestUnavailable": "Барањето за повлекување е недостапно",
@@ -2176,7 +2178,8 @@
"discardDraftMessage": "Твојот предлог ќе биде изгубен.",
"keepEditing": "Продолжи со уредување",
"discard": "Отфрли",
- "discardFailed": "Не можеше да се отфрли нацртот. Обиди се повторно."
+ "discardFailed": "Не можеше да се отфрли нацртот. Обиди се повторно.",
+ "remoteHint": "Run `kilo remote` on your computer, or `/remote` in a running CLI session, to control a local kilo process."
},
"partRenderer": {
"updatedFileCount_one": "Ажурирана {{displayCount}} датотека",
@@ -2662,15 +2665,10 @@
"couldNotLoadSessions": "Не можев да ги вчитам сесиите",
"couldNotLoadActiveSessions": "Не можев да ги вчитам активните сесии",
"agentSessions": "Сесии на агенти",
- "showingSavedSessions": "Прикажани се зачуваните сесии — живиот статус може да е застарен",
- "startNewAgentSession": "Започни нова сесија на Kilo Agent",
- "aiCodingSessions": "AI сесии за кодирање",
- "startCodingTaskFromPhone": "Започнете задача за кодирање од вашиот телефон или продолжете сесија од вашиот CLI.",
- "tryIt": "Пробај",
"newCodingTask": "Нова задача за кодирање",
"explore": "Истражувај",
"seeAll": "Види ги сите",
- "kiloAgents": "Kilo Agents"
+ "noLiveSessions": "Nothing running right now"
},
"imageViewer": {
"close": "Затвори {{filename}}",
diff --git a/apps/mobile/src/i18n/locales/ml.json b/apps/mobile/src/i18n/locales/ml.json
index b61686c9e5..42bfa8ba61 100644
--- a/apps/mobile/src/i18n/locales/ml.json
+++ b/apps/mobile/src/i18n/locales/ml.json
@@ -148,7 +148,9 @@
"appearanceSystem": "സിസ്റ്റം",
"appearanceLight": "ലൈറ്റ്",
"appearanceDark": "ഡാർക്ക്",
- "account": "അക്കൗണ്ട്"
+ "account": "അക്കൗണ്ട്",
+ "prReviewAttribution": "Add app attribution to PR reviews",
+ "prReviewAttributionSubtitle": "Append a Reviewed via Kilo footer when you submit a review."
},
"prReview": {
"pullRequestUnavailable": "പുൾ റിക്വസ്റ്റ് ലഭ്യമല്ല",
@@ -2176,7 +2178,8 @@
"discardDraftMessage": "നിങ്ങളുടെ പ്രോംപ്റ്റ് നഷ്ടപ്പെടും.",
"keepEditing": "എഡിറ്റിംഗ് തുടരുക",
"discard": "ഉപേക്ഷിക്കുക",
- "discardFailed": "ഡ്രാഫ്റ്റ് ഉപേക്ഷിക്കാൻ കഴിഞ്ഞില്ല. വീണ്ടും ശ്രമിക്കുക."
+ "discardFailed": "ഡ്രാഫ്റ്റ് ഉപേക്ഷിക്കാൻ കഴിഞ്ഞില്ല. വീണ്ടും ശ്രമിക്കുക.",
+ "remoteHint": "Run `kilo remote` on your computer, or `/remote` in a running CLI session, to control a local kilo process."
},
"partRenderer": {
"updatedFileCount_one": "{{displayCount}} ഫയൽ അപ്ഡേറ്റ് ചെയ്തു",
@@ -2662,15 +2665,10 @@
"couldNotLoadSessions": "സെഷനുകൾ ലോഡ് ചെയ്യാൻ കഴിഞ്ഞില്ല",
"couldNotLoadActiveSessions": "സജീവ സെഷനുകൾ ലോഡ് ചെയ്യാൻ കഴിഞ്ഞില്ല",
"agentSessions": "ഏജന്റ് സെഷനുകൾ",
- "showingSavedSessions": "സംരക്ഷിച്ച സെഷനുകൾ കാണിക്കുന്നു — തത്സമയ നില കാലഹരണപ്പെട്ടതായിരിക്കാം",
- "startNewAgentSession": "ഒരു പുതിയ Kilo ഏജന്റ് സെഷൻ ആരംഭിക്കുക",
- "aiCodingSessions": "AI കോഡിംഗ് സെഷനുകൾ",
- "startCodingTaskFromPhone": "നിങ്ങളുടെ ഫോണിൽ നിന്ന് ഒരു കോഡിംഗ് ടാസ്ക് ആരംഭിക്കുക അല്ലെങ്കിൽ നിങ്ങളുടെ CLI-യിൽ നിന്ന് ഒരു സെഷൻ തുടരുക.",
- "tryIt": "പരീക്ഷിച്ചുനോക്കൂ",
"newCodingTask": "പുതിയ കോഡിംഗ് ടാസ്ക്",
"explore": "പര്യവേക്ഷണം ചെയ്യുക",
"seeAll": "എല്ലാം കാണുക",
- "kiloAgents": "Kilo ഏജന്റുകൾ"
+ "noLiveSessions": "Nothing running right now"
},
"imageViewer": {
"close": "{{filename}} അടയ്ക്കുക",
diff --git a/apps/mobile/src/i18n/locales/mn.json b/apps/mobile/src/i18n/locales/mn.json
index 416206c11e..3d1d664f8d 100644
--- a/apps/mobile/src/i18n/locales/mn.json
+++ b/apps/mobile/src/i18n/locales/mn.json
@@ -148,7 +148,9 @@
"appearanceSystem": "Систем",
"appearanceLight": "Гэрэлтэй",
"appearanceDark": "Харанхуй",
- "account": "Бүртгэл"
+ "account": "Бүртгэл",
+ "prReviewAttribution": "Add app attribution to PR reviews",
+ "prReviewAttributionSubtitle": "Append a Reviewed via Kilo footer when you submit a review."
},
"prReview": {
"pullRequestUnavailable": "Pull request боломжгүй",
@@ -2176,7 +2178,8 @@
"discardDraftMessage": "Таны заавар алдагдах болно.",
"keepEditing": "Засварлахыг үргэлжлүүлэх",
"discard": "Хаях",
- "discardFailed": "Нооргийг хаях боломжгүй. Дахин оролдоно уу."
+ "discardFailed": "Нооргийг хаях боломжгүй. Дахин оролдоно уу.",
+ "remoteHint": "Run `kilo remote` on your computer, or `/remote` in a running CLI session, to control a local kilo process."
},
"partRenderer": {
"updatedFileCount_one": "{{displayCount}} файл шинэчлэгдсэн",
@@ -2662,15 +2665,10 @@
"couldNotLoadSessions": "Сессийг ачаалж чадсангүй",
"couldNotLoadActiveSessions": "Идэвхтэй сессийг ачаалж чадсангүй",
"agentSessions": "Агентын сессий",
- "showingSavedSessions": "Хадгалсан сессийг харуулж байна — шууд статус хуучирсан байж болно",
- "startNewAgentSession": "Шинэ Kilo Agent сесси эхлүүлэх",
- "aiCodingSessions": "AI кодчилолын сессий",
- "startCodingTaskFromPhone": "Утаснаасаа кодчилолын даалгавар эхлүүлэх эсвэл CLI-ээсээ сессийг үргэлжлүүлэх.",
- "tryIt": "Оролдоод үзэх",
"newCodingTask": "Шинэ кодчилолын даалгавар",
"explore": "Судлах",
"seeAll": "Бүгдийг үзэх",
- "kiloAgents": "Kilo Agents"
+ "noLiveSessions": "Nothing running right now"
},
"imageViewer": {
"close": "{{filename}} хаах",
diff --git a/apps/mobile/src/i18n/locales/mr.json b/apps/mobile/src/i18n/locales/mr.json
index 94fff6def3..12971529c3 100644
--- a/apps/mobile/src/i18n/locales/mr.json
+++ b/apps/mobile/src/i18n/locales/mr.json
@@ -148,7 +148,9 @@
"appearanceSystem": "सिस्टम",
"appearanceLight": "लाइट",
"appearanceDark": "डार्क",
- "account": "खाते"
+ "account": "खाते",
+ "prReviewAttribution": "Add app attribution to PR reviews",
+ "prReviewAttributionSubtitle": "Append a Reviewed via Kilo footer when you submit a review."
},
"prReview": {
"pullRequestUnavailable": "पुल रिक्वेस्ट अनुपलब्ध",
@@ -2176,7 +2178,8 @@
"discardDraftMessage": "तुमचा प्रॉम्प्ट गमावला जाईल.",
"keepEditing": "संपादन सुरू ठेवा",
"discard": "रद्द करा",
- "discardFailed": "मसुदा रद्द करता आला नाही. कृपया पुन्हा प्रयत्न करा."
+ "discardFailed": "मसुदा रद्द करता आला नाही. कृपया पुन्हा प्रयत्न करा.",
+ "remoteHint": "Run `kilo remote` on your computer, or `/remote` in a running CLI session, to control a local kilo process."
},
"partRenderer": {
"updatedFileCount_one": "{{displayCount}} फाइल अद्ययावत केली",
@@ -2662,15 +2665,10 @@
"couldNotLoadSessions": "सत्रे लोड करता आली नाहीत",
"couldNotLoadActiveSessions": "सक्रिय सत्रे लोड करता आली नाहीत",
"agentSessions": "एजंट सत्रे",
- "showingSavedSessions": "जतन केलेली सत्रे दाखवत आहे — लाइव्ह स्थिती कालबाह्य असू शकते",
- "startNewAgentSession": "नवीन Kilo एजंट सत्र सुरू करा",
- "aiCodingSessions": "AI कोडिंग सत्रे",
- "startCodingTaskFromPhone": "तुमच्या फोनवरून कोडिंग कार्य सुरू करा किंवा तुमच्या CLI वरून सत्र सुरू ठेवा.",
- "tryIt": "वापरून पहा",
"newCodingTask": "नवीन कोडिंग कार्य",
"explore": "एक्सप्लोर करा",
"seeAll": "सर्व पहा",
- "kiloAgents": "Kilo एजंट्स"
+ "noLiveSessions": "Nothing running right now"
},
"imageViewer": {
"close": "{{filename}} बंद करा",
diff --git a/apps/mobile/src/i18n/locales/ms.json b/apps/mobile/src/i18n/locales/ms.json
index 24685b4c3a..da26a624da 100644
--- a/apps/mobile/src/i18n/locales/ms.json
+++ b/apps/mobile/src/i18n/locales/ms.json
@@ -148,7 +148,9 @@
"appearanceSystem": "Sistem",
"appearanceLight": "Cerah",
"appearanceDark": "Gelap",
- "account": "Akaun"
+ "account": "Akaun",
+ "prReviewAttribution": "Add app attribution to PR reviews",
+ "prReviewAttributionSubtitle": "Append a Reviewed via Kilo footer when you submit a review."
},
"prReview": {
"pullRequestUnavailable": "Permintaan tarik tidak tersedia",
@@ -2176,7 +2178,8 @@
"discardDraftMessage": "Prompt anda akan hilang.",
"keepEditing": "Teruskan mengedit",
"discard": "Buang",
- "discardFailed": "Tidak dapat membuang draf. Sila cuba lagi."
+ "discardFailed": "Tidak dapat membuang draf. Sila cuba lagi.",
+ "remoteHint": "Run `kilo remote` on your computer, or `/remote` in a running CLI session, to control a local kilo process."
},
"partRenderer": {
"updatedFileCount_one": "{{displayCount}} fail dikemas kini",
@@ -2662,15 +2665,10 @@
"couldNotLoadSessions": "Tidak dapat memuatkan sesi",
"couldNotLoadActiveSessions": "Tidak dapat memuatkan sesi aktif",
"agentSessions": "Sesi ejen",
- "showingSavedSessions": "Menunjukkan sesi tersimpan — status langsung mungkin sudah lapuk",
- "startNewAgentSession": "Mulakan sesi Kilo Agent baharu",
- "aiCodingSessions": "Sesi pengekodan AI",
- "startCodingTaskFromPhone": "Mulakan tugas pengekodan daripada telefon anda atau teruskan sesi daripada CLI anda.",
- "tryIt": "Cubalah",
"newCodingTask": "Tugas pengekodan baharu",
"explore": "Teroka",
"seeAll": "Lihat semua",
- "kiloAgents": "Ejen Kilo"
+ "noLiveSessions": "Nothing running right now"
},
"imageViewer": {
"close": "Tutup {{filename}}",
diff --git a/apps/mobile/src/i18n/locales/mt.json b/apps/mobile/src/i18n/locales/mt.json
index 91adac54cd..7ab175605f 100644
--- a/apps/mobile/src/i18n/locales/mt.json
+++ b/apps/mobile/src/i18n/locales/mt.json
@@ -148,7 +148,9 @@
"appearanceSystem": "Sistema",
"appearanceLight": "Dawl",
"appearanceDark": "Skur",
- "account": "Kont"
+ "account": "Kont",
+ "prReviewAttribution": "Add app attribution to PR reviews",
+ "prReviewAttributionSubtitle": "Append a Reviewed via Kilo footer when you submit a review."
},
"prReview": {
"pullRequestUnavailable": "Pull request mhux disponibbli",
@@ -2221,7 +2223,8 @@
"discardDraftMessage": "Il-prompt tiegħek se jintilef.",
"keepEditing": "Kompli ipproċessa",
"discard": "Warrab",
- "discardFailed": "Ma setax jintrema l-abbozz. Jekk jogħġbok erġa' pprova."
+ "discardFailed": "Ma setax jintrema l-abbozz. Jekk jogħġbok erġa' pprova.",
+ "remoteHint": "Run `kilo remote` on your computer, or `/remote` in a running CLI session, to control a local kilo process."
},
"partRenderer": {
"updatedFileCount_one": "Aġġornat {{displayCount}} fajl",
@@ -2722,15 +2725,10 @@
"couldNotLoadSessions": "Ma setgħux jitgħabbew is-sessjonijiet",
"couldNotLoadActiveSessions": "Ma setgħux jitgħabbew is-sessjonijiet attivi",
"agentSessions": "Sessjonijiet tal-aġent",
- "showingSavedSessions": "Qed juri s-sessjonijiet salvati — l-istatus dirett jista' jkun skadut",
- "startNewAgentSession": "Ibda sessjoni ġdida ta' Kilo Agent",
- "aiCodingSessions": "Sessjonijiet ta' kodifikazzjoni bl-AI",
- "startCodingTaskFromPhone": "Ibda kompitu ta' kodifikazzjoni mit-telefon tiegħek jew kompli sessjoni mill-CLI tiegħek.",
- "tryIt": "Ipprova",
"newCodingTask": "Kompitu ġdid ta' kodifikazzjoni",
"explore": "Esplora",
"seeAll": "Ara kollha",
- "kiloAgents": "Kilo Agents"
+ "noLiveSessions": "Nothing running right now"
},
"imageViewer": {
"close": "Agħlaq {{filename}}",
diff --git a/apps/mobile/src/i18n/locales/my.json b/apps/mobile/src/i18n/locales/my.json
index 0a45c4f612..d794b3b67e 100644
--- a/apps/mobile/src/i18n/locales/my.json
+++ b/apps/mobile/src/i18n/locales/my.json
@@ -148,7 +148,9 @@
"appearanceSystem": "System",
"appearanceLight": "Light",
"appearanceDark": "Dark",
- "account": "အကောင့်"
+ "account": "အကောင့်",
+ "prReviewAttribution": "Add app attribution to PR reviews",
+ "prReviewAttributionSubtitle": "Append a Reviewed via Kilo footer when you submit a review."
},
"prReview": {
"pullRequestUnavailable": "Pull request မရနိုင်ပါ",
@@ -2176,7 +2178,8 @@
"discardDraftMessage": "သင့်မေးမြန်းချက် ပျောက်သွားမည်။",
"keepEditing": "ဆက်လက်တည်းဖြတ်ပါ",
"discard": "ပယ်ဖျက်ပါ",
- "discardFailed": "မူကြမ်းကို ပယ်ဖျက်၍မရခဲ့ပါ။ ထပ်ကြိုးစားပါ။"
+ "discardFailed": "မူကြမ်းကို ပယ်ဖျက်၍မရခဲ့ပါ။ ထပ်ကြိုးစားပါ။",
+ "remoteHint": "Run `kilo remote` on your computer, or `/remote` in a running CLI session, to control a local kilo process."
},
"partRenderer": {
"updatedFileCount_one": "ဖိုင် {{displayCount}} ခု မွမ်းမံပြီး",
@@ -2662,15 +2665,10 @@
"couldNotLoadSessions": "session များကို မတင်နိုင်ပါ",
"couldNotLoadActiveSessions": "လက်ရှိ session များကို မတင်နိုင်ပါ",
"agentSessions": "Agent session များ",
- "showingSavedSessions": "သိမ်းထားသော session များ ပြနေသည် — တိုက်ရိုက် အခြေအနေ နောက်ကျနိုင်သည်",
- "startNewAgentSession": "Kilo Agent session အသစ် စတင်ရန်",
- "aiCodingSessions": "AI coding session များ",
- "startCodingTaskFromPhone": "သင့်ဖုန်းမှ coding အလုပ်တစ်ခု စတင်ပါ သို့မဟုတ် သင့် CLI မှ session တစ်ခု ဆက်ပါ။",
- "tryIt": "စမ်းကြည့်ပါ",
"newCodingTask": "coding အလုပ်အသစ်",
"explore": "ရှာဖွေပါ",
"seeAll": "အားလုံး ကြည့်ရန်",
- "kiloAgents": "Kilo Agents"
+ "noLiveSessions": "Nothing running right now"
},
"imageViewer": {
"close": "{{filename}} ပိတ်ရန်",
diff --git a/apps/mobile/src/i18n/locales/nb.json b/apps/mobile/src/i18n/locales/nb.json
index d5943f515b..e428693202 100644
--- a/apps/mobile/src/i18n/locales/nb.json
+++ b/apps/mobile/src/i18n/locales/nb.json
@@ -148,7 +148,9 @@
"appearanceSystem": "System",
"appearanceLight": "Lys",
"appearanceDark": "Mørk",
- "account": "Konto"
+ "account": "Konto",
+ "prReviewAttribution": "Add app attribution to PR reviews",
+ "prReviewAttributionSubtitle": "Append a Reviewed via Kilo footer when you submit a review."
},
"prReview": {
"pullRequestUnavailable": "Pull request utilgjengelig",
@@ -2176,7 +2178,8 @@
"discardDraftMessage": "Forespørselen din vil gå tapt.",
"keepEditing": "Fortsett å redigere",
"discard": "Forkast",
- "discardFailed": "Kunne ikke forkaste utkastet. Prøv igjen."
+ "discardFailed": "Kunne ikke forkaste utkastet. Prøv igjen.",
+ "remoteHint": "Run `kilo remote` on your computer, or `/remote` in a running CLI session, to control a local kilo process."
},
"partRenderer": {
"updatedFileCount_one": "Oppdaterte {{displayCount}} fil",
@@ -2662,15 +2665,10 @@
"couldNotLoadSessions": "Kunne ikke laste økter",
"couldNotLoadActiveSessions": "Kunne ikke laste aktive økter",
"agentSessions": "Agentøkter",
- "showingSavedSessions": "Viser lagrede økter — sanntidsstatus kan være utdatert",
- "startNewAgentSession": "Start en ny Kilo Agent-økt",
- "aiCodingSessions": "AI-kodeøkter",
- "startCodingTaskFromPhone": "Start en kodeoppgave fra telefonen din eller fortsett en økt fra CLI-en din.",
- "tryIt": "Prøv det",
"newCodingTask": "Ny kodeoppgave",
"explore": "Utforsk",
"seeAll": "Se alle",
- "kiloAgents": "Kilo Agents"
+ "noLiveSessions": "Nothing running right now"
},
"imageViewer": {
"close": "Lukk {{filename}}",
diff --git a/apps/mobile/src/i18n/locales/ne.json b/apps/mobile/src/i18n/locales/ne.json
index 0903b6966c..7f32a1c3af 100644
--- a/apps/mobile/src/i18n/locales/ne.json
+++ b/apps/mobile/src/i18n/locales/ne.json
@@ -148,7 +148,9 @@
"appearanceSystem": "प्रणाली",
"appearanceLight": "हल्का",
"appearanceDark": "गाढा",
- "account": "खाता"
+ "account": "खाता",
+ "prReviewAttribution": "Add app attribution to PR reviews",
+ "prReviewAttributionSubtitle": "Append a Reviewed via Kilo footer when you submit a review."
},
"prReview": {
"pullRequestUnavailable": "पुल अनुरोध उपलब्ध छैन",
@@ -2176,7 +2178,8 @@
"discardDraftMessage": "तपाईंको प्रम्प्ट हराउनेछ।",
"keepEditing": "सम्पादन जारी राख्नुहोस्",
"discard": "खारेज गर्नुहोस्",
- "discardFailed": "ड्राफ्ट खारेज गर्न सकिएन। फेरि प्रयास गर्नुहोस्।"
+ "discardFailed": "ड्राफ्ट खारेज गर्न सकिएन। फेरि प्रयास गर्नुहोस्।",
+ "remoteHint": "Run `kilo remote` on your computer, or `/remote` in a running CLI session, to control a local kilo process."
},
"partRenderer": {
"updatedFileCount_one": "{{displayCount}} फाइल अद्यावधिक गरियो",
@@ -2662,15 +2665,10 @@
"couldNotLoadSessions": "सत्रहरू लोड गर्न सकिएन",
"couldNotLoadActiveSessions": "सक्रिय सत्रहरू लोड गर्न सकिएन",
"agentSessions": "एजेन्ट सत्रहरू",
- "showingSavedSessions": "सुरक्षित सत्रहरू देखाइँदै — लाइभ स्थिति पुरानो हुन सक्छ",
- "startNewAgentSession": "नयाँ Kilo Agent सत्र सुरु गर्नुहोस्",
- "aiCodingSessions": "AI कोडिङ सत्रहरू",
- "startCodingTaskFromPhone": "आफ्नो फोनबाट कोडिङ कार्य सुरु गर्नुहोस् वा आफ्नो CLI बाट सत्र जारी गर्नुहोस्।",
- "tryIt": "प्रयास गर्नुहोस्",
"newCodingTask": "नयाँ कोडिङ कार्य",
"explore": "अन्वेषण",
"seeAll": "सबै हेर्नुहोस्",
- "kiloAgents": "Kilo Agents"
+ "noLiveSessions": "Nothing running right now"
},
"imageViewer": {
"close": "{{filename}} बन्द गर्नुहोस्",
diff --git a/apps/mobile/src/i18n/locales/nl.json b/apps/mobile/src/i18n/locales/nl.json
index 7a0dcc79ab..4314075ee9 100644
--- a/apps/mobile/src/i18n/locales/nl.json
+++ b/apps/mobile/src/i18n/locales/nl.json
@@ -148,7 +148,9 @@
"appearanceSystem": "Systeem",
"appearanceLight": "Licht",
"appearanceDark": "Donker",
- "account": "Account"
+ "account": "Account",
+ "prReviewAttribution": "Add app attribution to PR reviews",
+ "prReviewAttributionSubtitle": "Append a Reviewed via Kilo footer when you submit a review."
},
"notifications": {
"channel": {
@@ -1722,7 +1724,8 @@
"discardDraftMessage": "Je prompt gaat verloren.",
"discardDraftTitle": "Concept weggooien?",
"discardFailed": "Kon het concept niet weggooien. Probeer het opnieuw.",
- "keepEditing": "Blijven bewerken"
+ "keepEditing": "Blijven bewerken",
+ "remoteHint": "Run `kilo remote` on your computer, or `/remote` in a running CLI session, to control a local kilo process."
},
"partRenderer": {
"updatedFileCount_one": "{{displayCount}} bestand bijgewerkt",
@@ -2208,15 +2211,10 @@
"couldNotLoadSessions": "Sessies konden niet worden geladen",
"couldNotLoadActiveSessions": "Actieve sessies konden niet worden geladen",
"agentSessions": "Agentsessies",
- "showingSavedSessions": "Opgeslagen sessies worden getoond — de live status kan verouderd zijn",
- "startNewAgentSession": "Een nieuwe Kilo Agent-sessie starten",
- "aiCodingSessions": "AI-codeersessies",
- "startCodingTaskFromPhone": "Start een codeertaak vanaf je telefoon of ga verder met een sessie vanaf je CLI.",
- "tryIt": "Probeer het",
"newCodingTask": "Nieuwe codeertaak",
"explore": "Verkennen",
"seeAll": "Alles bekijken",
- "kiloAgents": "Kilo Agents"
+ "noLiveSessions": "Nothing running right now"
},
"imageViewer": {
"close": "{{filename}} sluiten",
diff --git a/apps/mobile/src/i18n/locales/om.json b/apps/mobile/src/i18n/locales/om.json
index 0395e03a59..f99cb992a7 100644
--- a/apps/mobile/src/i18n/locales/om.json
+++ b/apps/mobile/src/i18n/locales/om.json
@@ -148,7 +148,9 @@
"appearanceSystem": "Sirna",
"appearanceLight": "Ifa",
"appearanceDark": "Dukkana",
- "account": "Herrega"
+ "account": "Herrega",
+ "prReviewAttribution": "Add app attribution to PR reviews",
+ "prReviewAttributionSubtitle": "Append a Reviewed via Kilo footer when you submit a review."
},
"prReview": {
"pullRequestUnavailable": "Pull request hin jiraatu",
@@ -2176,7 +2178,8 @@
"discardDraftMessage": "Prompt kee dhabama.",
"keepEditing": "Gulaaluu itti fufi",
"discard": "Haqi",
- "discardFailed": "Daaftarii haquu hin dandeenye. Mee deebi'ee yaali."
+ "discardFailed": "Daaftarii haquu hin dandeenye. Mee deebi'ee yaali.",
+ "remoteHint": "Run `kilo remote` on your computer, or `/remote` in a running CLI session, to control a local kilo process."
},
"partRenderer": {
"updatedFileCount_one": "Faayilii {{displayCount}} haaromfame",
@@ -2662,15 +2665,10 @@
"couldNotLoadSessions": "Shumarra fudhachuu hin danda'ine",
"couldNotLoadActiveSessions": "Shumarra hojii fudhachuu hin danda'ine",
"agentSessions": "Shumarra agent",
- "showingSavedSessions": "Shumarra kuusame agarsiisaa jira — haalli lubbuu yeroo ittiin gadi aanaa ta'uu danda'a",
- "startNewAgentSession": "Shumarra Kilo Agent haaraa jalqabi",
- "aiCodingSessions": "Shumarra code AI",
- "startCodingTaskFromPhone": "Hojii code bilbilaa kee irraa jalqabi ykn shumarra CLI kee itti fufi.",
- "tryIt": "Yaali",
"newCodingTask": "Hojii code haaraa",
"explore": "Qoradhu",
"seeAll": "Hunda ilaali",
- "kiloAgents": "Kilo Agents"
+ "noLiveSessions": "Nothing running right now"
},
"imageViewer": {
"close": "{{filename}} cufi",
diff --git a/apps/mobile/src/i18n/locales/or.json b/apps/mobile/src/i18n/locales/or.json
index d8557abb26..cb637a0576 100644
--- a/apps/mobile/src/i18n/locales/or.json
+++ b/apps/mobile/src/i18n/locales/or.json
@@ -148,7 +148,9 @@
"appearanceSystem": "ସିଷ୍ଟମ୍",
"appearanceLight": "ହାଲୁକା",
"appearanceDark": "ଗାଢ଼",
- "account": "ଆକାଉଣ୍ଟ"
+ "account": "ଆକାଉଣ୍ଟ",
+ "prReviewAttribution": "Add app attribution to PR reviews",
+ "prReviewAttributionSubtitle": "Append a Reviewed via Kilo footer when you submit a review."
},
"prReview": {
"pullRequestUnavailable": "ପୁଲ୍ ରିକ୍ୱେଷ୍ଟ ଉପଲବ୍ଧ ନାହିଁ",
@@ -2176,7 +2178,8 @@
"discardDraftMessage": "ଆପଣଙ୍କ ପ୍ରମ୍ପ୍ଟ ହଜିଯିବ।",
"keepEditing": "ସମ୍ପାଦନ ଜାରି ରଖନ୍ତୁ",
"discard": "ପରିତ୍ୟାଗ କରନ୍ତୁ",
- "discardFailed": "ଡ୍ରାଫ୍ଟ ପରିତ୍ୟାଗ ହୋଇପାରିଲା ନାହିଁ। ଦୟାକରି ପୁନଃଚେଷ୍ଟା କରନ୍ତୁ।"
+ "discardFailed": "ଡ୍ରାଫ୍ଟ ପରିତ୍ୟାଗ ହୋଇପାରିଲା ନାହିଁ। ଦୟାକରି ପୁନଃଚେଷ୍ଟା କରନ୍ତୁ।",
+ "remoteHint": "Run `kilo remote` on your computer, or `/remote` in a running CLI session, to control a local kilo process."
},
"partRenderer": {
"updatedFileCount_one": "{{displayCount}}ଟି ଫାଇଲ୍ ଅଦ୍ୟତନ ହୋଇଛି",
@@ -2662,15 +2665,10 @@
"couldNotLoadSessions": "ସେସନ୍ ଲୋଡ୍ ହୋଇପାରିଲା ନାହିଁ",
"couldNotLoadActiveSessions": "ସକ୍ରିୟ ସେସନ୍ ଲୋଡ୍ ହୋଇପାରିଲା ନାହିଁ",
"agentSessions": "ଏଜେଣ୍ଟ ସେସନ୍",
- "showingSavedSessions": "ସେଭ୍ ହୋଇଥିବା ସେସନ୍ ଦେଖାଉଛି — ଲାଇଭ୍ ସ୍ଥିତି ଅପଡେଟ୍ ନହୋଇପାରେ",
- "startNewAgentSession": "ନୂତନ Kilo Agent ସେସନ୍ ଆରମ୍ଭ କରନ୍ତୁ",
- "aiCodingSessions": "AI କୋଡିଂ ସେସନ୍",
- "startCodingTaskFromPhone": "ଆପଣଙ୍କ ଫୋନରୁ କୋଡିଂ କାର୍ଯ୍ୟ ଆରମ୍ଭ କରନ୍ତୁ କିମ୍ବା ଆପଣଙ୍କ CLI ରୁ ସେସନ୍ ଜାରି କରନ୍ତୁ।",
- "tryIt": "ଚେଷ୍ଟା କରନ୍ତୁ",
"newCodingTask": "ନୂତନ କୋଡିଂ କାର୍ଯ୍ୟ",
"explore": "ଅନୁସନ୍ଧାନ",
"seeAll": "ସବୁ ଦେଖନ୍ତୁ",
- "kiloAgents": "Kilo Agents"
+ "noLiveSessions": "Nothing running right now"
},
"imageViewer": {
"close": "{{filename}} ବନ୍ଦ କରନ୍ତୁ",
diff --git a/apps/mobile/src/i18n/locales/pa.json b/apps/mobile/src/i18n/locales/pa.json
index f3a5f5c699..4304204b24 100644
--- a/apps/mobile/src/i18n/locales/pa.json
+++ b/apps/mobile/src/i18n/locales/pa.json
@@ -148,7 +148,9 @@
"appearanceSystem": "ਸਿਸਟਮ",
"appearanceLight": "ਹਲਕਾ",
"appearanceDark": "ਗੂੜ੍ਹਾ",
- "account": "ਖਾਤਾ"
+ "account": "ਖਾਤਾ",
+ "prReviewAttribution": "Add app attribution to PR reviews",
+ "prReviewAttributionSubtitle": "Append a Reviewed via Kilo footer when you submit a review."
},
"prReview": {
"pullRequestUnavailable": "ਪੁੱਲ ਰਿਕਵੈਸਟ ਉਪਲਬਧ ਨਹੀਂ ਹੈ",
@@ -2176,7 +2178,8 @@
"discardDraftMessage": "ਤੁਹਾਡਾ ਪ੍ਰੋਂਪਟ ਗੁਆਚ ਜਾਵੇਗਾ।",
"keepEditing": "ਸੰਪਾਦਨ ਜਾਰੀ ਰੱਖੋ",
"discard": "ਰੱਦ ਕਰੋ",
- "discardFailed": "ਡਰਾਫਟ ਰੱਦ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਿਆ। ਕਿਰਪਾ ਕਰਕੇ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"
+ "discardFailed": "ਡਰਾਫਟ ਰੱਦ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਿਆ। ਕਿਰਪਾ ਕਰਕੇ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।",
+ "remoteHint": "Run `kilo remote` on your computer, or `/remote` in a running CLI session, to control a local kilo process."
},
"partRenderer": {
"updatedFileCount_one": "{{displayCount}} ਫਾਈਲ ਅੱਪਡੇਟ ਕੀਤੀ ਗਈ",
@@ -2662,15 +2665,10 @@
"couldNotLoadSessions": "ਸੈਸ਼ਨ ਲੋਡ ਨਹੀਂ ਹੋ ਸਕੇ",
"couldNotLoadActiveSessions": "ਸਰਗਰਮ ਸੈਸ਼ਨ ਲੋਡ ਨਹੀਂ ਹੋ ਸਕੇ",
"agentSessions": "ਏਜੰਟ ਸੈਸ਼ਨ",
- "showingSavedSessions": "ਸੇਵ ਕੀਤੇ ਸੈਸ਼ਨ ਦਿਖਾਏ ਜਾ ਰਹੇ ਹਨ — ਲਾਈਵ ਸਥਿਤੀ ਪੁਰਾਣੀ ਹੋ ਸਕਦੀ ਹੈ",
- "startNewAgentSession": "ਨਵਾਂ Kilo ਏਜੰਟ ਸੈਸ਼ਨ ਸ਼ੁਰੂ ਕਰੋ",
- "aiCodingSessions": "AI ਕੋਡਿੰਗ ਸੈਸ਼ਨ",
- "startCodingTaskFromPhone": "ਆਪਣੇ ਫ਼ੋਨ ਤੋਂ ਕੋਡਿੰਗ ਕੰਮ ਸ਼ੁਰੂ ਕਰੋ ਜਾਂ ਆਪਣੇ CLI ਤੋਂ ਸੈਸ਼ਨ ਜਾਰੀ ਰੱਖੋ।",
- "tryIt": "ਕੋਸ਼ਿਸ਼ ਕਰੋ",
"newCodingTask": "ਨਵਾਂ ਕੋਡਿੰਗ ਕੰਮ",
"explore": "ਪੜਚੋਲ ਕਰੋ",
"seeAll": "ਸਭ ਵੇਖੋ",
- "kiloAgents": "Kilo ਏਜੰਟ"
+ "noLiveSessions": "Nothing running right now"
},
"imageViewer": {
"close": "{{filename}} ਬੰਦ ਕਰੋ",
diff --git a/apps/mobile/src/i18n/locales/pl.json b/apps/mobile/src/i18n/locales/pl.json
index 5da88aa35e..f4d8bca627 100644
--- a/apps/mobile/src/i18n/locales/pl.json
+++ b/apps/mobile/src/i18n/locales/pl.json
@@ -148,7 +148,9 @@
"appearanceSystem": "System",
"appearanceLight": "Jasny",
"appearanceDark": "Ciemny",
- "account": "Konto"
+ "account": "Konto",
+ "prReviewAttribution": "Add app attribution to PR reviews",
+ "prReviewAttributionSubtitle": "Append a Reviewed via Kilo footer when you submit a review."
},
"notifications": {
"title": "Powiadomienia",
@@ -1738,7 +1740,8 @@
"discardDraftMessage": "Twoje polecenie zostanie utracone.",
"discardDraftTitle": "Odrzucić szkic?",
"discardFailed": "Nie udało się odrzucić szkicu. Spróbuj ponownie.",
- "keepEditing": "Kontynuuj edycję"
+ "keepEditing": "Kontynuuj edycję",
+ "remoteHint": "Run `kilo remote` on your computer, or `/remote` in a running CLI session, to control a local kilo process."
},
"partRenderer": {
"updatedFileCount_one": "Zaktualizowano {{displayCount}} plik",
@@ -2234,15 +2237,10 @@
"couldNotLoadSessions": "Nie można załadować sesji",
"couldNotLoadActiveSessions": "Nie można załadować aktywnych sesji",
"agentSessions": "Sesje agenta",
- "showingSavedSessions": "Wyświetlanie zapisanych sesji — status na żywo może być nieaktualny",
- "startNewAgentSession": "Rozpocznij nową sesję agenta Kilo",
- "aiCodingSessions": "Sesje kodowania AI",
- "startCodingTaskFromPhone": "Rozpocznij zadanie kodowania z telefonu lub kontynuuj sesję z CLI.",
- "tryIt": "Wypróbuj",
"newCodingTask": "Nowe zadanie kodowania",
"explore": "Odkrywaj",
"seeAll": "Zobacz wszystkie",
- "kiloAgents": "Agenci Kilo"
+ "noLiveSessions": "Nothing running right now"
},
"imageViewer": {
"close": "Zamknij {{filename}}",
diff --git a/apps/mobile/src/i18n/locales/ps.json b/apps/mobile/src/i18n/locales/ps.json
index 739206755a..e05dae1dca 100644
--- a/apps/mobile/src/i18n/locales/ps.json
+++ b/apps/mobile/src/i18n/locales/ps.json
@@ -148,7 +148,9 @@
"appearanceSystem": "سیسټم",
"appearanceLight": "روښانه",
"appearanceDark": "تیاره",
- "account": "حساب"
+ "account": "حساب",
+ "prReviewAttribution": "Add app attribution to PR reviews",
+ "prReviewAttributionSubtitle": "Append a Reviewed via Kilo footer when you submit a review."
},
"prReview": {
"pullRequestUnavailable": "پل ریکویسټ شتون نلري",
@@ -2176,7 +2178,8 @@
"discardDraftMessage": "ستاسو پرامپټ به له لاسه ورکړل شي.",
"keepEditing": "سمون ته دوام ورکړئ",
"discard": "لغوه کړئ",
- "discardFailed": "مسوده لغوه نه شوه. مهرباني وکړئ بیا هڅه وکړئ."
+ "discardFailed": "مسوده لغوه نه شوه. مهرباني وکړئ بیا هڅه وکړئ.",
+ "remoteHint": "Run `kilo remote` on your computer, or `/remote` in a running CLI session, to control a local kilo process."
},
"partRenderer": {
"updatedFileCount_one": "{{displayCount}} فایل تازه شو",
@@ -2662,15 +2665,10 @@
"couldNotLoadSessions": "غونډې نه شول پورته کېدلای",
"couldNotLoadActiveSessions": "فعالې غونډې نه شول پورته کېدلای",
"agentSessions": "د اجنټ غونډې",
- "showingSavedSessions": "خوندي شوې غونډې ښودل کېږي — ژوندی حالت ممکن زوړ وي",
- "startNewAgentSession": "د Kilo اجنټ نوې غونډه پیل کړئ",
- "aiCodingSessions": "د AI کوډ کولو غونډې",
- "startCodingTaskFromPhone": "له خپل تلیفون څخه د کوډ کولو دنده پیل کړئ یا له خپل CLI څخه یوه غونډه دوام ورکړئ.",
- "tryIt": "هڅه یې وکړئ",
"newCodingTask": "د کوډ کولو نوې دنده",
"explore": "وپلټئ",
"seeAll": "ټول وګورئ",
- "kiloAgents": "د Kilo اجنټان"
+ "noLiveSessions": "Nothing running right now"
},
"imageViewer": {
"close": "{{filename}} وتړئ",
diff --git a/apps/mobile/src/i18n/locales/pt-BR.json b/apps/mobile/src/i18n/locales/pt-BR.json
index 1c9d7ba94d..7a7a0d76e5 100644
--- a/apps/mobile/src/i18n/locales/pt-BR.json
+++ b/apps/mobile/src/i18n/locales/pt-BR.json
@@ -1716,7 +1716,8 @@
"discardDraftMessage": "Seu prompt será perdido.",
"discardDraftTitle": "Descartar rascunho?",
"discardFailed": "Não foi possível descartar o rascunho. Tente novamente.",
- "keepEditing": "Continuar editando"
+ "keepEditing": "Continuar editando",
+ "remoteHint": "Run `kilo remote` on your computer, or `/remote` in a running CLI session, to control a local kilo process."
},
"partRenderer": {
"updatedFileCount_one": "{{displayCount}} arquivo atualizado",
@@ -2182,7 +2183,9 @@
"appearanceSystem": "Sistema",
"appearanceLight": "Claro",
"appearanceDark": "Escuro",
- "account": "Conta"
+ "account": "Conta",
+ "prReviewAttribution": "Add app attribution to PR reviews",
+ "prReviewAttributionSubtitle": "Append a Reviewed via Kilo footer when you submit a review."
},
"addCredits": {
"cta": "Adicionar créditos",
@@ -2221,15 +2224,10 @@
"couldNotLoadSessions": "Não foi possível carregar as sessões",
"couldNotLoadActiveSessions": "Não foi possível carregar as sessões ativas",
"agentSessions": "Sessões de agentes",
- "showingSavedSessions": "Mostrando sessões salvas — o status ao vivo pode estar desatualizado",
- "startNewAgentSession": "Iniciar uma nova sessão do Kilo Agent",
- "aiCodingSessions": "Sessões de codificação com IA",
- "startCodingTaskFromPhone": "Inicie uma tarefa de codificação pelo celular ou continue uma sessão pela CLI.",
- "tryIt": "Experimente",
"newCodingTask": "Nova tarefa de codificação",
"explore": "Explorar",
"seeAll": "Ver tudo",
- "kiloAgents": "Agentes Kilo"
+ "noLiveSessions": "Nothing running right now"
},
"imageViewer": {
"close": "Fechar {{filename}}",
diff --git a/apps/mobile/src/i18n/locales/pt.json b/apps/mobile/src/i18n/locales/pt.json
index 60a4d727b9..f73cdf79eb 100644
--- a/apps/mobile/src/i18n/locales/pt.json
+++ b/apps/mobile/src/i18n/locales/pt.json
@@ -148,7 +148,9 @@
"appearanceSystem": "Sistema",
"appearanceLight": "Claro",
"appearanceDark": "Escuro",
- "account": "Conta"
+ "account": "Conta",
+ "prReviewAttribution": "Add app attribution to PR reviews",
+ "prReviewAttributionSubtitle": "Append a Reviewed via Kilo footer when you submit a review."
},
"prReview": {
"pullRequestUnavailable": "Pull request indisponível",
@@ -2191,7 +2193,8 @@
"discardDraftMessage": "O seu prompt será perdido.",
"keepEditing": "Continuar a editar",
"discard": "Descartar",
- "discardFailed": "Não foi possível descartar o rascunho. Tente novamente."
+ "discardFailed": "Não foi possível descartar o rascunho. Tente novamente.",
+ "remoteHint": "Run `kilo remote` on your computer, or `/remote` in a running CLI session, to control a local kilo process."
},
"partRenderer": {
"updatedFileCount_one": "{{displayCount}} ficheiro atualizado",
@@ -2682,15 +2685,10 @@
"couldNotLoadSessions": "Não foi possível carregar as sessões",
"couldNotLoadActiveSessions": "Não foi possível carregar as sessões ativas",
"agentSessions": "Sessões de agente",
- "showingSavedSessions": "A mostrar sessões guardadas — o estado ao vivo pode estar desatualizado",
- "startNewAgentSession": "Iniciar uma nova sessão do Kilo Agent",
- "aiCodingSessions": "Sessões de programação com IA",
- "startCodingTaskFromPhone": "Inicie uma tarefa de programação a partir do seu telemóvel ou continue uma sessão a partir da sua CLI.",
- "tryIt": "Experimentar",
"newCodingTask": "Nova tarefa de programação",
"explore": "Explorar",
"seeAll": "Ver tudo",
- "kiloAgents": "Kilo Agents"
+ "noLiveSessions": "Nothing running right now"
},
"imageViewer": {
"close": "Fechar {{filename}}",
diff --git a/apps/mobile/src/i18n/locales/ro.json b/apps/mobile/src/i18n/locales/ro.json
index 3557f51480..3b62249aaf 100644
--- a/apps/mobile/src/i18n/locales/ro.json
+++ b/apps/mobile/src/i18n/locales/ro.json
@@ -148,7 +148,9 @@
"appearanceSystem": "Sistem",
"appearanceLight": "Luminos",
"appearanceDark": "Întunecat",
- "account": "Cont"
+ "account": "Cont",
+ "prReviewAttribution": "Add app attribution to PR reviews",
+ "prReviewAttributionSubtitle": "Append a Reviewed via Kilo footer when you submit a review."
},
"prReview": {
"pullRequestUnavailable": "Pull request indisponibil",
@@ -2191,7 +2193,8 @@
"discardDraftMessage": "Mesajul tău va fi pierdut.",
"keepEditing": "Continuă editarea",
"discard": "Renunță",
- "discardFailed": "Nu s-a putut renunța la ciornă. Încearcă din nou."
+ "discardFailed": "Nu s-a putut renunța la ciornă. Încearcă din nou.",
+ "remoteHint": "Run `kilo remote` on your computer, or `/remote` in a running CLI session, to control a local kilo process."
},
"partRenderer": {
"updatedFileCount_one": "Actualizat {{displayCount}} fișier",
@@ -2682,15 +2685,10 @@
"couldNotLoadSessions": "Sesiunile nu au putut fi încărcate",
"couldNotLoadActiveSessions": "Sesiunile active nu au putut fi încărcate",
"agentSessions": "Sesiuni de agent",
- "showingSavedSessions": "Se afișează sesiunile salvate — starea live poate fi neactualizată",
- "startNewAgentSession": "Începe o sesiune nouă de Kilo Agent",
- "aiCodingSessions": "Sesiuni de codare AI",
- "startCodingTaskFromPhone": "Începe o sarcină de codare de pe telefon sau continuă o sesiune de pe CLI.",
- "tryIt": "Încearcă",
"newCodingTask": "Sarcină de codare nouă",
"explore": "Explorează",
"seeAll": "Vezi tot",
- "kiloAgents": "Kilo Agents"
+ "noLiveSessions": "Nothing running right now"
},
"imageViewer": {
"close": "Închide {{filename}}",
diff --git a/apps/mobile/src/i18n/locales/ru.json b/apps/mobile/src/i18n/locales/ru.json
index 66bc2eeb13..3b198e2a52 100644
--- a/apps/mobile/src/i18n/locales/ru.json
+++ b/apps/mobile/src/i18n/locales/ru.json
@@ -148,7 +148,9 @@
"appearanceSystem": "Системная",
"appearanceLight": "Светлая",
"appearanceDark": "Темная",
- "account": "Аккаунт"
+ "account": "Аккаунт",
+ "prReviewAttribution": "Add app attribution to PR reviews",
+ "prReviewAttributionSubtitle": "Append a Reviewed via Kilo footer when you submit a review."
},
"notifications": {
"title": "Уведомления",
@@ -1738,7 +1740,8 @@
"discardDraftMessage": "Ваш запрос будет потерян.",
"discardDraftTitle": "Отменить черновик?",
"discardFailed": "Не удалось отменить черновик. Попробуйте снова.",
- "keepEditing": "Продолжить редактирование"
+ "keepEditing": "Продолжить редактирование",
+ "remoteHint": "Run `kilo remote` on your computer, or `/remote` in a running CLI session, to control a local kilo process."
},
"partRenderer": {
"updatedFileCount_one": "Обновлен {{displayCount}} файл",
@@ -2234,15 +2237,10 @@
"couldNotLoadSessions": "Не удалось загрузить сеансы",
"couldNotLoadActiveSessions": "Не удалось загрузить активные сеансы",
"agentSessions": "Сеансы агента",
- "showingSavedSessions": "Показаны сохранённые сеансы — актуальный статус может быть устаревшим",
- "startNewAgentSession": "Начать новый сеанс агента Kilo",
- "aiCodingSessions": "Сеансы ИИ-кодирования",
- "startCodingTaskFromPhone": "Начните задачу кодирования с телефона или продолжите сеанс из CLI.",
- "tryIt": "Попробовать",
"newCodingTask": "Новая задача кодирования",
"explore": "Исследовать",
"seeAll": "Смотреть все",
- "kiloAgents": "Агенты Kilo"
+ "noLiveSessions": "Nothing running right now"
},
"imageViewer": {
"close": "Закрыть {{filename}}",
diff --git a/apps/mobile/src/i18n/locales/si.json b/apps/mobile/src/i18n/locales/si.json
index 20e21e0903..d22f98f226 100644
--- a/apps/mobile/src/i18n/locales/si.json
+++ b/apps/mobile/src/i18n/locales/si.json
@@ -148,7 +148,9 @@
"appearanceSystem": "පද්ධතිය",
"appearanceLight": "ආලෝකය",
"appearanceDark": "අඳුරු",
- "account": "ගිණුම"
+ "account": "ගිණුම",
+ "prReviewAttribution": "Add app attribution to PR reviews",
+ "prReviewAttributionSubtitle": "Append a Reviewed via Kilo footer when you submit a review."
},
"prReview": {
"pullRequestUnavailable": "Pull request ලබා ගත නොහැක",
@@ -2176,7 +2178,8 @@
"discardDraftMessage": "ඔබේ ඉල්ලීම අහිමි වනු ඇත.",
"keepEditing": "දිගටම සංස්කරණය කරන්න",
"discard": "ඉවතලන්න",
- "discardFailed": "කටු සටහන ඉවතලිය නොහැක. කරුණාකර නැවත උත්සාහ කරන්න."
+ "discardFailed": "කටු සටහන ඉවතලිය නොහැක. කරුණාකර නැවත උත්සාහ කරන්න.",
+ "remoteHint": "Run `kilo remote` on your computer, or `/remote` in a running CLI session, to control a local kilo process."
},
"partRenderer": {
"updatedFileCount_one": "{{displayCount}} ගොනුවක් යාවත්කාලීන කර ඇත",
@@ -2662,15 +2665,10 @@
"couldNotLoadSessions": "සැසි පූරණය කළ නොහැකි විය",
"couldNotLoadActiveSessions": "ක්රියාකාරී සැසි පූරණය කළ නොහැකි විය",
"agentSessions": "ඒජන්ත සැසි",
- "showingSavedSessions": "සුරැකි සැසි පෙන්වමින් — සජීවී තත්ත්වය කල් ඉකුත් විය හැක",
- "startNewAgentSession": "නව Kilo Agent සැසියක් ආරම්භ කරන්න",
- "aiCodingSessions": "AI කේතීකරණ සැසි",
- "startCodingTaskFromPhone": "ඔබගේ දුරකථනයෙන් කේතීකරණ කාර්යයක් ආරම්භ කරන්න හෝ ඔබගේ CLI වෙතින් සැසියක් දිගටම කරගෙන යන්න.",
- "tryIt": "උත්සාහ කරන්න",
"newCodingTask": "නව කේතීකරණ කාර්යය",
"explore": "ගවේෂණය",
"seeAll": "සියල්ල බලන්න",
- "kiloAgents": "Kilo Agents"
+ "noLiveSessions": "Nothing running right now"
},
"imageViewer": {
"close": "{{filename}} වසන්න",
diff --git a/apps/mobile/src/i18n/locales/sk.json b/apps/mobile/src/i18n/locales/sk.json
index d24ddeeb9a..1c7d3bb019 100644
--- a/apps/mobile/src/i18n/locales/sk.json
+++ b/apps/mobile/src/i18n/locales/sk.json
@@ -148,7 +148,9 @@
"appearanceSystem": "Systémový",
"appearanceLight": "Svetlý",
"appearanceDark": "Tmavý",
- "account": "Účet"
+ "account": "Účet",
+ "prReviewAttribution": "Add app attribution to PR reviews",
+ "prReviewAttributionSubtitle": "Append a Reviewed via Kilo footer when you submit a review."
},
"prReview": {
"pullRequestUnavailable": "Pull request nie je dostupný",
@@ -2206,7 +2208,8 @@
"discardDraftMessage": "Váš prompt sa stratí.",
"keepEditing": "Pokračovať v úpravách",
"discard": "Zahodiť",
- "discardFailed": "Koncept sa nepodarilo zahodiť. Skúste to znova."
+ "discardFailed": "Koncept sa nepodarilo zahodiť. Skúste to znova.",
+ "remoteHint": "Run `kilo remote` on your computer, or `/remote` in a running CLI session, to control a local kilo process."
},
"partRenderer": {
"updatedFileCount_one": "Aktualizovaný {{displayCount}} súbor",
@@ -2702,15 +2705,10 @@
"couldNotLoadSessions": "Relácie sa nepodarilo načítať",
"couldNotLoadActiveSessions": "Aktívne relácie sa nepodarilo načítať",
"agentSessions": "Relácie agenta",
- "showingSavedSessions": "Zobrazujú sa uložené relácie — živý stav môže byť zastaraný",
- "startNewAgentSession": "Spustiť novú reláciu agenta Kilo",
- "aiCodingSessions": "AI programovacie relácie",
- "startCodingTaskFromPhone": "Spustite programovaciu úlohu z telefónu alebo pokračujte v relácii z CLI.",
- "tryIt": "Vyskúšať",
"newCodingTask": "Nová programovacia úloha",
"explore": "Preskúmať",
"seeAll": "Zobraziť všetko",
- "kiloAgents": "Agenti Kilo"
+ "noLiveSessions": "Nothing running right now"
},
"imageViewer": {
"close": "Zavrieť {{filename}}",
diff --git a/apps/mobile/src/i18n/locales/sl.json b/apps/mobile/src/i18n/locales/sl.json
index 2d75260db9..2627387638 100644
--- a/apps/mobile/src/i18n/locales/sl.json
+++ b/apps/mobile/src/i18n/locales/sl.json
@@ -148,7 +148,9 @@
"appearanceSystem": "Sistem",
"appearanceLight": "Svetlo",
"appearanceDark": "Temno",
- "account": "Račun"
+ "account": "Račun",
+ "prReviewAttribution": "Add app attribution to PR reviews",
+ "prReviewAttributionSubtitle": "Append a Reviewed via Kilo footer when you submit a review."
},
"prReview": {
"pullRequestUnavailable": "Pull request ni na voljo",
@@ -2206,7 +2208,8 @@
"discardDraftMessage": "Tvoja zahteva bo izgubljena.",
"keepEditing": "Nadaljuj z urejanjem",
"discard": "Zavrzi",
- "discardFailed": "Osnutka ni bilo mogoče zavreči. Poskusi znova."
+ "discardFailed": "Osnutka ni bilo mogoče zavreči. Poskusi znova.",
+ "remoteHint": "Run `kilo remote` on your computer, or `/remote` in a running CLI session, to control a local kilo process."
},
"partRenderer": {
"updatedFileCount_one": "Posodobljena {{displayCount}} datoteka",
@@ -2702,15 +2705,10 @@
"couldNotLoadSessions": "Sej ni bilo mogoče naložiti",
"couldNotLoadActiveSessions": "Aktivnih sej ni bilo mogoče naložiti",
"agentSessions": "Seje agenta",
- "showingSavedSessions": "Prikaz shranjenih sej — živi status je morda zastarel",
- "startNewAgentSession": "Začni novo sejo Kilo Agenta",
- "aiCodingSessions": "Seje kodiranja z umetno inteligenco",
- "startCodingTaskFromPhone": "Začni nalogo kodiranja s telefona ali nadaljuj sejo s svojega CLI.",
- "tryIt": "Preizkusi",
"newCodingTask": "Nova naloga kodiranja",
"explore": "Razišči",
"seeAll": "Prikaži vse",
- "kiloAgents": "Kilo Agenti"
+ "noLiveSessions": "Nothing running right now"
},
"imageViewer": {
"close": "Zapri {{filename}}",
diff --git a/apps/mobile/src/i18n/locales/so.json b/apps/mobile/src/i18n/locales/so.json
index d164157755..d909e0c1c3 100644
--- a/apps/mobile/src/i18n/locales/so.json
+++ b/apps/mobile/src/i18n/locales/so.json
@@ -148,7 +148,9 @@
"appearanceSystem": "Nidaamka",
"appearanceLight": "Iftiin",
"appearanceDark": "Madow",
- "account": "Xisaabta"
+ "account": "Xisaabta",
+ "prReviewAttribution": "Add app attribution to PR reviews",
+ "prReviewAttributionSubtitle": "Append a Reviewed via Kilo footer when you submit a review."
},
"prReview": {
"pullRequestUnavailable": "Pull request ma heli karo",
@@ -2176,7 +2178,8 @@
"discardDraftMessage": "Wax-soo-galkaaga wuu lumi doonaa.",
"keepEditing": "Si wad wax ku tafatir",
"discard": "Isku tuur",
- "discardFailed": "Qabyada lama tuuri karin. Fadlan mar kale isku day."
+ "discardFailed": "Qabyada lama tuuri karin. Fadlan mar kale isku day.",
+ "remoteHint": "Run `kilo remote` on your computer, or `/remote` in a running CLI session, to control a local kilo process."
},
"partRenderer": {
"updatedFileCount_one": "{{displayCount}} fayl ayaa la cusboonaysiiyay",
@@ -2662,15 +2665,10 @@
"couldNotLoadSessions": "Kalfadhiyada lama soo dejin karin",
"couldNotLoadActiveSessions": "Kalfadhiyada firfircoon lama soo dejin karin",
"agentSessions": "Kalfadhiyada wakiilka",
- "showingSavedSessions": "Waxaa la tusi doonaa kalfadhiyo la kaydiyay — xaaladda tooska ah waxaa laga yaabaa inay ka da'do",
- "startNewAgentSession": "Bilow kalfadhi cusub oo Kilo Agent",
- "aiCodingSessions": "Kalfadhiyada codeynta AI",
- "startCodingTaskFromPhone": "Ka bilow hawshooda codeynta taleefankaaga ama sii wad kalfadhi CLI-gaaga.",
- "tryIt": "Isku day",
"newCodingTask": "Hawshooda cusub ee codeynta",
"explore": "Sahan",
"seeAll": "Fiiri dhammaan",
- "kiloAgents": "Kilo Agents"
+ "noLiveSessions": "Nothing running right now"
},
"imageViewer": {
"close": "Xidh {{filename}}",
diff --git a/apps/mobile/src/i18n/locales/sq.json b/apps/mobile/src/i18n/locales/sq.json
index a7c6d60719..779ed0066d 100644
--- a/apps/mobile/src/i18n/locales/sq.json
+++ b/apps/mobile/src/i18n/locales/sq.json
@@ -148,7 +148,9 @@
"appearanceSystem": "Sistemi",
"appearanceLight": "E çelët",
"appearanceDark": "E errët",
- "account": "Llogaria"
+ "account": "Llogaria",
+ "prReviewAttribution": "Add app attribution to PR reviews",
+ "prReviewAttributionSubtitle": "Append a Reviewed via Kilo footer when you submit a review."
},
"prReview": {
"pullRequestUnavailable": "Kërkesa e tërheqjes e padisponueshme",
@@ -2176,7 +2178,8 @@
"discardDraftMessage": "Mesazhi juaj do të humbasë.",
"keepEditing": "Vazhdo redaktimin",
"discard": "Hiq",
- "discardFailed": "Nuk u hoq drafti. Ju lutemi provoni përsëri."
+ "discardFailed": "Nuk u hoq drafti. Ju lutemi provoni përsëri.",
+ "remoteHint": "Run `kilo remote` on your computer, or `/remote` in a running CLI session, to control a local kilo process."
},
"partRenderer": {
"updatedFileCount_one": "U përditësua {{displayCount}} skedar",
@@ -2662,15 +2665,10 @@
"couldNotLoadSessions": "Seancat nuk u ngarkuan",
"couldNotLoadActiveSessions": "Seancat aktive nuk u ngarkuan",
"agentSessions": "Seancat e agjentit",
- "showingSavedSessions": "Duke shfaqur seancat e ruajtura — statusi i drejtpërdrejtë mund të jetë i vjetëruar",
- "startNewAgentSession": "Filloni një seancë të re Kilo Agent",
- "aiCodingSessions": "Seancat e kodimit me AI",
- "startCodingTaskFromPhone": "Filloni një detyrë kodimi nga telefoni juaj ose vazhdoni një seancë nga CLI juaj.",
- "tryIt": "Provojeni",
"newCodingTask": "Detyrë e re kodimi",
"explore": "Eksploro",
"seeAll": "Shiko të gjitha",
- "kiloAgents": "Kilo Agents"
+ "noLiveSessions": "Nothing running right now"
},
"imageViewer": {
"close": "Mbyll {{filename}}",
diff --git a/apps/mobile/src/i18n/locales/sr.json b/apps/mobile/src/i18n/locales/sr.json
index 417d06e9c5..90df4ea8db 100644
--- a/apps/mobile/src/i18n/locales/sr.json
+++ b/apps/mobile/src/i18n/locales/sr.json
@@ -148,7 +148,9 @@
"appearanceSystem": "Sistem",
"appearanceLight": "Svetlo",
"appearanceDark": "Tamno",
- "account": "Nalog"
+ "account": "Nalog",
+ "prReviewAttribution": "Add app attribution to PR reviews",
+ "prReviewAttributionSubtitle": "Append a Reviewed via Kilo footer when you submit a review."
},
"prReview": {
"pullRequestUnavailable": "Pull request nije dostupan",
@@ -2191,7 +2193,8 @@
"discardDraftMessage": "Tvoj upit će biti izgubljen.",
"keepEditing": "Nastavi sa uređivanjem",
"discard": "Odbaci",
- "discardFailed": "Nacrt se ne može odbaciti. Pokušaj ponovo."
+ "discardFailed": "Nacrt se ne može odbaciti. Pokušaj ponovo.",
+ "remoteHint": "Run `kilo remote` on your computer, or `/remote` in a running CLI session, to control a local kilo process."
},
"partRenderer": {
"updatedFileCount_one": "Ažuriran {{displayCount}} fajl",
@@ -2682,15 +2685,10 @@
"couldNotLoadSessions": "Učitavanje sesija nije uspelo",
"couldNotLoadActiveSessions": "Učitavanje aktivnih sesija nije uspelo",
"agentSessions": "Agentske sesije",
- "showingSavedSessions": "Prikazuju se sačuvane sesije — status uživo može biti zastareo",
- "startNewAgentSession": "Pokreni novu Kilo Agent sesiju",
- "aiCodingSessions": "AI sesije kodiranja",
- "startCodingTaskFromPhone": "Pokrenite zadatak kodiranja sa telefona ili nastavite sesiju sa vašeg CLI-ja.",
- "tryIt": "Probaj",
"newCodingTask": "Novi zadatak kodiranja",
"explore": "Istraži",
"seeAll": "Vidi sve",
- "kiloAgents": "Kilo Agenti"
+ "noLiveSessions": "Nothing running right now"
},
"imageViewer": {
"close": "Zatvori {{filename}}",
diff --git a/apps/mobile/src/i18n/locales/sv.json b/apps/mobile/src/i18n/locales/sv.json
index 78b40dc984..620cef8021 100644
--- a/apps/mobile/src/i18n/locales/sv.json
+++ b/apps/mobile/src/i18n/locales/sv.json
@@ -148,7 +148,9 @@
"appearanceSystem": "System",
"appearanceLight": "Ljust",
"appearanceDark": "Mörkt",
- "account": "Konto"
+ "account": "Konto",
+ "prReviewAttribution": "Add app attribution to PR reviews",
+ "prReviewAttributionSubtitle": "Append a Reviewed via Kilo footer when you submit a review."
},
"prReview": {
"pullRequestUnavailable": "Pull request inte tillgänglig",
@@ -2176,7 +2178,8 @@
"discardDraftMessage": "Din prompt går förlorad.",
"keepEditing": "Fortsätt redigera",
"discard": "Ignorera",
- "discardFailed": "Kunde inte ignorera utkastet. Försök igen."
+ "discardFailed": "Kunde inte ignorera utkastet. Försök igen.",
+ "remoteHint": "Run `kilo remote` on your computer, or `/remote` in a running CLI session, to control a local kilo process."
},
"partRenderer": {
"updatedFileCount_one": "Uppdaterade {{displayCount}} fil",
@@ -2662,15 +2665,10 @@
"couldNotLoadSessions": "Det gick inte att läsa in sessioner",
"couldNotLoadActiveSessions": "Det gick inte att läsa in aktiva sessioner",
"agentSessions": "Agentsessioner",
- "showingSavedSessions": "Visar sparade sessioner — live-status kan vara inaktuell",
- "startNewAgentSession": "Starta en ny Kilo Agent-session",
- "aiCodingSessions": "AI-kodningssessioner",
- "startCodingTaskFromPhone": "Starta en kodningsuppgift från din telefon eller fortsätt en session från din CLI.",
- "tryIt": "Prova",
"newCodingTask": "Ny kodningsuppgift",
"explore": "Utforska",
"seeAll": "Visa alla",
- "kiloAgents": "Kilo-agenter"
+ "noLiveSessions": "Nothing running right now"
},
"imageViewer": {
"close": "Stäng {{filename}}",
diff --git a/apps/mobile/src/i18n/locales/sw.json b/apps/mobile/src/i18n/locales/sw.json
index 2a1845532c..e5bed7b6f7 100644
--- a/apps/mobile/src/i18n/locales/sw.json
+++ b/apps/mobile/src/i18n/locales/sw.json
@@ -148,7 +148,9 @@
"appearanceSystem": "Mfumo",
"appearanceLight": "Nyepesi",
"appearanceDark": "Nyeusi",
- "account": "Akaunti"
+ "account": "Akaunti",
+ "prReviewAttribution": "Add app attribution to PR reviews",
+ "prReviewAttributionSubtitle": "Append a Reviewed via Kilo footer when you submit a review."
},
"prReview": {
"pullRequestUnavailable": "Pull request haipatikani",
@@ -2176,7 +2178,8 @@
"discardDraftMessage": "Maagizo yako yatapotea.",
"keepEditing": "Endelea kuhariri",
"discard": "Tupa",
- "discardFailed": "Haikuweza kutupa rasimu. Jaribu tena."
+ "discardFailed": "Haikuweza kutupa rasimu. Jaribu tena.",
+ "remoteHint": "Run `kilo remote` on your computer, or `/remote` in a running CLI session, to control a local kilo process."
},
"partRenderer": {
"updatedFileCount_one": "Imesasisha faili {{displayCount}}",
@@ -2662,15 +2665,10 @@
"couldNotLoadSessions": "Haikuweza kupakia vikao",
"couldNotLoadActiveSessions": "Haikuweza kupakia vikao vya sasa",
"agentSessions": "Vikao vya wakala",
- "showingSavedSessions": "Inaonyesha vikao vilivyohifadhiwa — hali ya moja kwa moja inaweza kuwa imepitwa na wakati",
- "startNewAgentSession": "Anza kikao kipya cha Kilo Agent",
- "aiCodingSessions": "Vikao vya kuandika msimbo kwa AI",
- "startCodingTaskFromPhone": "Anza kazi ya kuandika msimbo kutoka kwenye simu yako au endelea kikao kutoka kwenye CLI yako.",
- "tryIt": "Jaribu",
"newCodingTask": "Kazi mpya ya kuandika msimbo",
"explore": "Chunguza",
"seeAll": "Ona zote",
- "kiloAgents": "Kilo Agents"
+ "noLiveSessions": "Nothing running right now"
},
"imageViewer": {
"close": "Funga {{filename}}",
diff --git a/apps/mobile/src/i18n/locales/ta.json b/apps/mobile/src/i18n/locales/ta.json
index c6bf6952f0..95793a1aae 100644
--- a/apps/mobile/src/i18n/locales/ta.json
+++ b/apps/mobile/src/i18n/locales/ta.json
@@ -148,7 +148,9 @@
"appearanceSystem": "கணினி",
"appearanceLight": "வெளிச்சம்",
"appearanceDark": "இருள்",
- "account": "கணக்கு"
+ "account": "கணக்கு",
+ "prReviewAttribution": "Add app attribution to PR reviews",
+ "prReviewAttributionSubtitle": "Append a Reviewed via Kilo footer when you submit a review."
},
"prReview": {
"pullRequestUnavailable": "இழுப்பு கோரிக்கை கிடைக்கவில்லை",
@@ -2176,7 +2178,8 @@
"discardDraftMessage": "உங்கள் வினவல் இழக்கப்படும்.",
"keepEditing": "தொடர்ந்து திருத்து",
"discard": "நிராகரி",
- "discardFailed": "வரைவை நிராகரிக்க முடியவில்லை. மீண்டும் முயற்சிக்கவும்."
+ "discardFailed": "வரைவை நிராகரிக்க முடியவில்லை. மீண்டும் முயற்சிக்கவும்.",
+ "remoteHint": "Run `kilo remote` on your computer, or `/remote` in a running CLI session, to control a local kilo process."
},
"partRenderer": {
"updatedFileCount_one": "{{displayCount}} கோப்பு புதுப்பிக்கப்பட்டது",
@@ -2662,15 +2665,10 @@
"couldNotLoadSessions": "அமர்வுகளை ஏற்ற முடியவில்லை",
"couldNotLoadActiveSessions": "செயலில் உள்ள அமர்வுகளை ஏற்ற முடியவில்லை",
"agentSessions": "முகவர் அமர்வுகள்",
- "showingSavedSessions": "சேமித்த அமர்வுகளைக் காட்டுகிறது — நேரடி நிலை காலாவதியானதாக இருக்கலாம்",
- "startNewAgentSession": "புதிய Kilo முகவர் அமர்வைத் தொடங்கு",
- "aiCodingSessions": "AI குறியீட்டு அமர்வுகள்",
- "startCodingTaskFromPhone": "உங்கள் தொலைபேசியிலிருந்து குறியீட்டு பணியைத் தொடங்கவும் அல்லது உங்கள் CLIயிலிருந்து ஒரு அமர்வைத் தொடரவும்.",
- "tryIt": "முயற்சிக்கவும்",
"newCodingTask": "புதிய குறியீட்டு பணி",
"explore": "ஆராய்க",
"seeAll": "அனைத்தையும் காண்க",
- "kiloAgents": "Kilo முகவர்கள்"
+ "noLiveSessions": "Nothing running right now"
},
"imageViewer": {
"close": "{{filename}} மூடு",
diff --git a/apps/mobile/src/i18n/locales/te.json b/apps/mobile/src/i18n/locales/te.json
index cfe5ee6d6c..34a0ac702d 100644
--- a/apps/mobile/src/i18n/locales/te.json
+++ b/apps/mobile/src/i18n/locales/te.json
@@ -148,7 +148,9 @@
"appearanceSystem": "సిస్టమ్",
"appearanceLight": "లైట్",
"appearanceDark": "డార్క్",
- "account": "ఖాతా"
+ "account": "ఖాతా",
+ "prReviewAttribution": "Add app attribution to PR reviews",
+ "prReviewAttributionSubtitle": "Append a Reviewed via Kilo footer when you submit a review."
},
"prReview": {
"pullRequestUnavailable": "పుల్ రిక్వెస్ట్ అందుబాటులో లేదు",
@@ -2176,7 +2178,8 @@
"discardDraftMessage": "మీ ప్రాంప్ట్ కోల్పోతుంది.",
"keepEditing": "ఎడిటింగ్ కొనసాగించండి",
"discard": "విస్మరించండి",
- "discardFailed": "డ్రాఫ్ట్ను విస్మరించలేకపోయింది. దయచేసి మళ్ళీ ప్రయత్నించండి."
+ "discardFailed": "డ్రాఫ్ట్ను విస్మరించలేకపోయింది. దయచేసి మళ్ళీ ప్రయత్నించండి.",
+ "remoteHint": "Run `kilo remote` on your computer, or `/remote` in a running CLI session, to control a local kilo process."
},
"partRenderer": {
"updatedFileCount_one": "{{displayCount}} ఫైల్ నవీకరించబడింది",
@@ -2662,15 +2665,10 @@
"couldNotLoadSessions": "సెషన్లను లోడ్ చేయలేకపోయాము",
"couldNotLoadActiveSessions": "యాక్టివ్ సెషన్లను లోడ్ చేయలేకపోయాము",
"agentSessions": "ఏజెంట్ సెషన్లు",
- "showingSavedSessions": "సేవ్ చేసిన సెషన్లను చూపిస్తోంది — లైవ్ స్థితి పాతది కావచ్చు",
- "startNewAgentSession": "కొత్త Kilo ఏజెంట్ సెషన్ను ప్రారంభించండి",
- "aiCodingSessions": "AI కోడింగ్ సెషన్లు",
- "startCodingTaskFromPhone": "మీ ఫోన్ నుండి కోడింగ్ పనిని ప్రారంభించండి లేదా మీ CLI నుండి సెషన్ను కొనసాగించండి.",
- "tryIt": "ప్రయత్నించండి",
"newCodingTask": "కొత్త కోడింగ్ పని",
"explore": "అన్వేషించండి",
"seeAll": "అన్నీ చూడండి",
- "kiloAgents": "Kilo ఏజెంట్లు"
+ "noLiveSessions": "Nothing running right now"
},
"imageViewer": {
"close": "{{filename}} మూసివేయండి",
diff --git a/apps/mobile/src/i18n/locales/th.json b/apps/mobile/src/i18n/locales/th.json
index 6f4ba0c805..8484d75a7c 100644
--- a/apps/mobile/src/i18n/locales/th.json
+++ b/apps/mobile/src/i18n/locales/th.json
@@ -148,7 +148,9 @@
"appearanceSystem": "ระบบ",
"appearanceLight": "สว่าง",
"appearanceDark": "มืด",
- "account": "บัญชี"
+ "account": "บัญชี",
+ "prReviewAttribution": "Add app attribution to PR reviews",
+ "prReviewAttributionSubtitle": "Append a Reviewed via Kilo footer when you submit a review."
},
"prReview": {
"pullRequestUnavailable": "ไม่สามารถใช้ pull request ได้",
@@ -2176,7 +2178,8 @@
"discardDraftMessage": "ข้อความของคุณจะสูญหาย",
"keepEditing": "แก้ไขต่อไป",
"discard": "ทิ้ง",
- "discardFailed": "ไม่สามารถทิ้งฉบับร่างได้ กรุณาลองอีกครั้ง"
+ "discardFailed": "ไม่สามารถทิ้งฉบับร่างได้ กรุณาลองอีกครั้ง",
+ "remoteHint": "Run `kilo remote` on your computer, or `/remote` in a running CLI session, to control a local kilo process."
},
"partRenderer": {
"updatedFileCount_one": "อัปเดต {{displayCount}} ไฟล์",
@@ -2662,15 +2665,10 @@
"couldNotLoadSessions": "โหลดเซสชันไม่สำเร็จ",
"couldNotLoadActiveSessions": "โหลดเซสชันที่ใช้งานอยู่ไม่สำเร็จ",
"agentSessions": "เซสชันเอเจนต์",
- "showingSavedSessions": "กำลังแสดงเซสชันที่บันทึกไว้ — สถานะสดอาจไม่เป็นปัจจุบัน",
- "startNewAgentSession": "เริ่มเซสชัน Kilo Agent ใหม่",
- "aiCodingSessions": "เซสชันการเขียนโค้ด AI",
- "startCodingTaskFromPhone": "เริ่มงานการเขียนโค้ดจากโทรศัพท์ของคุณ หรือดำเนินการต่อจากเซสชันใน CLI ของคุณ",
- "tryIt": "ลองเลย",
"newCodingTask": "งานการเขียนโค้ดใหม่",
"explore": "สำรวจ",
"seeAll": "ดูทั้งหมด",
- "kiloAgents": "Kilo Agents"
+ "noLiveSessions": "Nothing running right now"
},
"imageViewer": {
"close": "ปิด {{filename}}",
diff --git a/apps/mobile/src/i18n/locales/tr.json b/apps/mobile/src/i18n/locales/tr.json
index 47e56220c7..8cf83558cf 100644
--- a/apps/mobile/src/i18n/locales/tr.json
+++ b/apps/mobile/src/i18n/locales/tr.json
@@ -148,7 +148,9 @@
"appearanceSystem": "Sistem",
"appearanceLight": "Açık",
"appearanceDark": "Koyu",
- "account": "Hesap"
+ "account": "Hesap",
+ "prReviewAttribution": "Add app attribution to PR reviews",
+ "prReviewAttributionSubtitle": "Append a Reviewed via Kilo footer when you submit a review."
},
"notifications": {
"title": "Bildirimler",
@@ -1722,7 +1724,8 @@
"discardDraftMessage": "İsteminiz kaybolacak.",
"discardDraftTitle": "Taslak silinsin mi?",
"discardFailed": "Taslak silinemedi. Lütfen tekrar deneyin.",
- "keepEditing": "Düzenlemeye devam et"
+ "keepEditing": "Düzenlemeye devam et",
+ "remoteHint": "Run `kilo remote` on your computer, or `/remote` in a running CLI session, to control a local kilo process."
},
"partRenderer": {
"updatedFileCount_one": "{{displayCount}} dosya güncellendi",
@@ -2208,15 +2211,10 @@
"couldNotLoadSessions": "Oturumlar yüklenemedi",
"couldNotLoadActiveSessions": "Etkin oturumlar yüklenemedi",
"agentSessions": "Ajan oturumları",
- "showingSavedSessions": "Kayıtlı oturumlar gösteriliyor — canlı durum güncel olmayabilir",
- "startNewAgentSession": "Yeni bir Kilo Ajanı oturumu başlat",
- "aiCodingSessions": "Yapay zeka kodlama oturumları",
- "startCodingTaskFromPhone": "Telefonunuzdan bir kodlama görevi başlatın veya CLI'nizden bir oturuma devam edin.",
- "tryIt": "Dene",
"newCodingTask": "Yeni kodlama görevi",
"explore": "Keşfet",
"seeAll": "Tümünü gör",
- "kiloAgents": "Kilo Ajanları"
+ "noLiveSessions": "Nothing running right now"
},
"imageViewer": {
"close": "{{filename}} kapat",
diff --git a/apps/mobile/src/i18n/locales/uk.json b/apps/mobile/src/i18n/locales/uk.json
index 8cdac07bbf..a7fc262d56 100644
--- a/apps/mobile/src/i18n/locales/uk.json
+++ b/apps/mobile/src/i18n/locales/uk.json
@@ -148,7 +148,9 @@
"appearanceSystem": "Системна",
"appearanceLight": "Світла",
"appearanceDark": "Темна",
- "account": "Обліковий запис"
+ "account": "Обліковий запис",
+ "prReviewAttribution": "Add app attribution to PR reviews",
+ "prReviewAttributionSubtitle": "Append a Reviewed via Kilo footer when you submit a review."
},
"notifications": {
"title": "Сповіщення",
@@ -1738,7 +1740,8 @@
"discardDraftMessage": "Ваш запит буде втрачено.",
"discardDraftTitle": "Відкинути чернетку?",
"discardFailed": "Не вдалося відкинути чернетку. Спробуйте ще раз.",
- "keepEditing": "Продовжити редагування"
+ "keepEditing": "Продовжити редагування",
+ "remoteHint": "Run `kilo remote` on your computer, or `/remote` in a running CLI session, to control a local kilo process."
},
"partRenderer": {
"updatedFileCount_one": "Оновлено {{displayCount}} файл",
@@ -2234,15 +2237,10 @@
"couldNotLoadSessions": "Не вдалося завантажити сеанси",
"couldNotLoadActiveSessions": "Не вдалося завантажити активні сеанси",
"agentSessions": "Сеанси агента",
- "showingSavedSessions": "Показано збережені сеанси — живий статус може бути застарілим",
- "startNewAgentSession": "Розпочати новий сеанс Kilo Agent",
- "aiCodingSessions": "Сеанси кодування з ШІ",
- "startCodingTaskFromPhone": "Розпочніть завдання кодування з телефона або продовжте сеанс зі свого CLI.",
- "tryIt": "Спробувати",
"newCodingTask": "Нове завдання кодування",
"explore": "Дослідити",
"seeAll": "Показати всі",
- "kiloAgents": "Агенти Kilo"
+ "noLiveSessions": "Nothing running right now"
},
"imageViewer": {
"close": "Закрити {{filename}}",
diff --git a/apps/mobile/src/i18n/locales/ur.json b/apps/mobile/src/i18n/locales/ur.json
index 0e3729148d..83621b5946 100644
--- a/apps/mobile/src/i18n/locales/ur.json
+++ b/apps/mobile/src/i18n/locales/ur.json
@@ -148,7 +148,9 @@
"appearanceSystem": "سسٹم",
"appearanceLight": "روشنی",
"appearanceDark": "تاریک",
- "account": "اکاؤنٹ"
+ "account": "اکاؤنٹ",
+ "prReviewAttribution": "Add app attribution to PR reviews",
+ "prReviewAttributionSubtitle": "Append a Reviewed via Kilo footer when you submit a review."
},
"prReview": {
"pullRequestUnavailable": "پل ریکویسٹ دستیاب نہیں",
@@ -2176,7 +2178,8 @@
"discardDraftMessage": "آپ کا پرامپٹ ضائع ہو جائے گا۔",
"keepEditing": "ترمیم جاری رکھیں",
"discard": "خارج کریں",
- "discardFailed": "ڈرافٹ خارج نہیں ہو سکا۔ براہ کرم دوبارہ کوشش کریں۔"
+ "discardFailed": "ڈرافٹ خارج نہیں ہو سکا۔ براہ کرم دوبارہ کوشش کریں۔",
+ "remoteHint": "Run `kilo remote` on your computer, or `/remote` in a running CLI session, to control a local kilo process."
},
"partRenderer": {
"updatedFileCount_one": "{{displayCount}} فائل اپ ڈیٹ ہوئی",
@@ -2662,15 +2665,10 @@
"couldNotLoadSessions": "سیشنز لوڈ نہیں ہو سکے",
"couldNotLoadActiveSessions": "فعال سیشنز لوڈ نہیں ہو سکے",
"agentSessions": "ایجنٹ سیشنز",
- "showingSavedSessions": "محفوظ شدہ سیشن دکھا رہے ہیں — لائیو سٹیٹس پرانی ہو سکتی ہے",
- "startNewAgentSession": "نیا Kilo ایجنٹ سیشن شروع کریں",
- "aiCodingSessions": "AI کوڈنگ سیشنز",
- "startCodingTaskFromPhone": "اپنے فون سے کوڈنگ کا کام شروع کریں یا اپنے CLI سے سیشن جاری رکھیں۔",
- "tryIt": "آزمائیں",
"newCodingTask": "نیا کوڈنگ کام",
"explore": "دریافت کریں",
"seeAll": "سب دیکھیں",
- "kiloAgents": "Kilo ایجنٹس"
+ "noLiveSessions": "Nothing running right now"
},
"imageViewer": {
"close": "{{filename}} بند کریں",
diff --git a/apps/mobile/src/i18n/locales/uz.json b/apps/mobile/src/i18n/locales/uz.json
index 92f2916dad..c028c1b171 100644
--- a/apps/mobile/src/i18n/locales/uz.json
+++ b/apps/mobile/src/i18n/locales/uz.json
@@ -148,7 +148,9 @@
"appearanceSystem": "Tizim",
"appearanceLight": "Yorug'",
"appearanceDark": "Qorong'i",
- "account": "Hisob"
+ "account": "Hisob",
+ "prReviewAttribution": "Add app attribution to PR reviews",
+ "prReviewAttributionSubtitle": "Append a Reviewed via Kilo footer when you submit a review."
},
"prReview": {
"pullRequestUnavailable": "Pull request mavjud emas",
@@ -2176,7 +2178,8 @@
"discardDraftMessage": "Promptingiz yo'qoladi.",
"keepEditing": "Tahrirlashda davom etish",
"discard": "Bekor qilish",
- "discardFailed": "Qoralamani bekor qilib bo'lmadi. Iltimos, qayta urinib ko'ring."
+ "discardFailed": "Qoralamani bekor qilib bo'lmadi. Iltimos, qayta urinib ko'ring.",
+ "remoteHint": "Run `kilo remote` on your computer, or `/remote` in a running CLI session, to control a local kilo process."
},
"partRenderer": {
"updatedFileCount_one": "{{displayCount}} ta fayl yangilandi",
@@ -2662,15 +2665,10 @@
"couldNotLoadSessions": "Sessiyalarni yuklab bo'lmadi",
"couldNotLoadActiveSessions": "Faol sessiyalarni yuklab bo'lmadi",
"agentSessions": "Agent sessiyalari",
- "showingSavedSessions": "Saqlangan sessiyalar ko'rsatilmoqda — jonli holat eskirgan bo'lishi mumkin",
- "startNewAgentSession": "Yangi Kilo Agent sessiyasini boshlash",
- "aiCodingSessions": "AI kodlash sessiyalari",
- "startCodingTaskFromPhone": "Telefoningizdan kodlash vazifasini boshlang yoki CLI'ingizdan sessiyani davom ettiring.",
- "tryIt": "Sinab ko'ring",
"newCodingTask": "Yangi kodlash vazifasi",
"explore": "O'rganish",
"seeAll": "Barchasini ko'rish",
- "kiloAgents": "Kilo Agents"
+ "noLiveSessions": "Nothing running right now"
},
"imageViewer": {
"close": "{{filename}} ni yopish",
diff --git a/apps/mobile/src/i18n/locales/vi.json b/apps/mobile/src/i18n/locales/vi.json
index 455691db46..50651ac217 100644
--- a/apps/mobile/src/i18n/locales/vi.json
+++ b/apps/mobile/src/i18n/locales/vi.json
@@ -148,7 +148,9 @@
"appearanceSystem": "Hệ thống",
"appearanceLight": "Sáng",
"appearanceDark": "Tối",
- "account": "Tài khoản"
+ "account": "Tài khoản",
+ "prReviewAttribution": "Add app attribution to PR reviews",
+ "prReviewAttributionSubtitle": "Append a Reviewed via Kilo footer when you submit a review."
},
"notifications": {
"title": "Thông báo",
@@ -1722,7 +1724,8 @@
"discardDraftMessage": "Lời nhắc của bạn sẽ bị mất.",
"discardDraftTitle": "Hủy bản nháp?",
"discardFailed": "Không thể hủy bản nháp. Vui lòng thử lại.",
- "keepEditing": "Tiếp tục chỉnh sửa"
+ "keepEditing": "Tiếp tục chỉnh sửa",
+ "remoteHint": "Run `kilo remote` on your computer, or `/remote` in a running CLI session, to control a local kilo process."
},
"partRenderer": {
"updatedFileCount_one": "Đã cập nhật {{displayCount}} tệp",
@@ -2208,15 +2211,10 @@
"couldNotLoadSessions": "Không thể tải các phiên",
"couldNotLoadActiveSessions": "Không thể tải các phiên đang hoạt động",
"agentSessions": "Phiên tác nhân",
- "showingSavedSessions": "Đang hiển thị các phiên đã lưu — trạng thái trực tiếp có thể đã cũ",
- "startNewAgentSession": "Bắt đầu phiên Kilo Agent mới",
- "aiCodingSessions": "Phiên lập trình AI",
- "startCodingTaskFromPhone": "Bắt đầu tác vụ lập trình từ điện thoại hoặc tiếp tục phiên từ CLI của bạn.",
- "tryIt": "Thử ngay",
"newCodingTask": "Tác vụ lập trình mới",
"explore": "Khám phá",
"seeAll": "Xem tất cả",
- "kiloAgents": "Tác nhân Kilo"
+ "noLiveSessions": "Nothing running right now"
},
"imageViewer": {
"close": "Đóng {{filename}}",
diff --git a/apps/mobile/src/i18n/locales/yo.json b/apps/mobile/src/i18n/locales/yo.json
index e9e8b9b53a..1263060626 100644
--- a/apps/mobile/src/i18n/locales/yo.json
+++ b/apps/mobile/src/i18n/locales/yo.json
@@ -148,7 +148,9 @@
"appearanceSystem": "Eto",
"appearanceLight": "Imọlẹ",
"appearanceDark": "Dudu",
- "account": "Àkọọ́lẹ̀"
+ "account": "Àkọọ́lẹ̀",
+ "prReviewAttribution": "Add app attribution to PR reviews",
+ "prReviewAttributionSubtitle": "Append a Reviewed via Kilo footer when you submit a review."
},
"prReview": {
"pullRequestUnavailable": "Ibeere fifa ko si",
@@ -2176,7 +2178,8 @@
"discardDraftMessage": "A yoo padanu iyanilenu rẹ.",
"keepEditing": "Pa ṣatunkọ mọ",
"discard": "Jù silẹ",
- "discardFailed": "Ko le fi osere silẹ. Jọwọ gbiyanju lẹẹkansi."
+ "discardFailed": "Ko le fi osere silẹ. Jọwọ gbiyanju lẹẹkansi.",
+ "remoteHint": "Run `kilo remote` on your computer, or `/remote` in a running CLI session, to control a local kilo process."
},
"partRenderer": {
"updatedFileCount_one": "Ti ṣe imudojuiwọn {{displayCount}} faili",
@@ -2662,15 +2665,10 @@
"couldNotLoadSessions": "Ko le ṣagbewọ awọn igba-ijiroro",
"couldNotLoadActiveSessions": "Ko le ṣagbewọ awọn igba-ijiroro ti n ṣiṣẹ",
"agentSessions": "Awọn igba-ijiroro aṣoju",
- "showingSavedSessions": "Nfi awọn igba-ijiroro ti o ti fi pamọ han — ipo laaye le ti atijo",
- "startNewAgentSession": "Bẹrẹ igba-ijiroro Kilo Agent tuntun",
- "aiCodingSessions": "Awọn igba-ijiroro koodu AI",
- "startCodingTaskFromPhone": "Bẹrẹ iṣẹ-ṣiṣe koodu lati foonu rẹ tabi tẹsiwaju igba-ijiroro lati CLI rẹ.",
- "tryIt": "Gbiyanju",
"newCodingTask": "Iṣẹ-ṣiṣe koodu tuntun",
"explore": "Ṣàwárí",
"seeAll": "Wo gbogbo",
- "kiloAgents": "Kilo Agents"
+ "noLiveSessions": "Nothing running right now"
},
"imageViewer": {
"close": "Pa {{filename}}",
diff --git a/apps/mobile/src/i18n/locales/zh-Hans.json b/apps/mobile/src/i18n/locales/zh-Hans.json
index e6f7067bd6..aac301cdd8 100644
--- a/apps/mobile/src/i18n/locales/zh-Hans.json
+++ b/apps/mobile/src/i18n/locales/zh-Hans.json
@@ -148,7 +148,9 @@
"appearanceSystem": "跟随系统",
"appearanceLight": "浅色",
"appearanceDark": "深色",
- "account": "账户"
+ "account": "账户",
+ "prReviewAttribution": "Add app attribution to PR reviews",
+ "prReviewAttributionSubtitle": "Append a Reviewed via Kilo footer when you submit a review."
},
"notifications": {
"title": "通知",
@@ -1722,7 +1724,8 @@
"discardDraftMessage": "您的提示词将会丢失。",
"discardDraftTitle": "丢弃草稿?",
"discardFailed": "无法丢弃草稿。请重试。",
- "keepEditing": "继续编辑"
+ "keepEditing": "继续编辑",
+ "remoteHint": "Run `kilo remote` on your computer, or `/remote` in a running CLI session, to control a local kilo process."
},
"partRenderer": {
"updatedFileCount_one": "已更新 {{displayCount}} 个文件",
@@ -2208,15 +2211,10 @@
"couldNotLoadSessions": "无法加载会话",
"couldNotLoadActiveSessions": "无法加载活动会话",
"agentSessions": "智能体会话",
- "showingSavedSessions": "显示已保存的会话 — 实时状态可能已过时",
- "startNewAgentSession": "开始新的 Kilo Agent 会话",
- "aiCodingSessions": "AI 编程会话",
- "startCodingTaskFromPhone": "从手机开始编程任务,或从 CLI 继续会话。",
- "tryIt": "试一试",
"newCodingTask": "新编程任务",
"explore": "探索",
"seeAll": "查看全部",
- "kiloAgents": "Kilo 代理"
+ "noLiveSessions": "Nothing running right now"
},
"imageViewer": {
"close": "关闭 {{filename}}",
diff --git a/apps/mobile/src/i18n/locales/zh-Hant.json b/apps/mobile/src/i18n/locales/zh-Hant.json
index d05487d6ce..f49afa3883 100644
--- a/apps/mobile/src/i18n/locales/zh-Hant.json
+++ b/apps/mobile/src/i18n/locales/zh-Hant.json
@@ -148,7 +148,9 @@
"appearanceSystem": "系統",
"appearanceLight": "淺色",
"appearanceDark": "深色",
- "account": "帳戶"
+ "account": "帳戶",
+ "prReviewAttribution": "Add app attribution to PR reviews",
+ "prReviewAttributionSubtitle": "Append a Reviewed via Kilo footer when you submit a review."
},
"notifications": {
"title": "通知",
@@ -1722,7 +1724,8 @@
"discardDraftMessage": "您的提示將遺失。",
"discardDraftTitle": "捨棄草稿?",
"discardFailed": "無法捨棄草稿。請再試一次。",
- "keepEditing": "繼續編輯"
+ "keepEditing": "繼續編輯",
+ "remoteHint": "Run `kilo remote` on your computer, or `/remote` in a running CLI session, to control a local kilo process."
},
"partRenderer": {
"updatedFileCount_one": "已更新 {{displayCount}} 個檔案",
@@ -2208,15 +2211,10 @@
"couldNotLoadSessions": "無法載入工作階段",
"couldNotLoadActiveSessions": "無法載入使用中的工作階段",
"agentSessions": "代理工作階段",
- "showingSavedSessions": "顯示已儲存的工作階段 — 即時狀態可能已過時",
- "startNewAgentSession": "開始新的 Kilo Agent 工作階段",
- "aiCodingSessions": "AI 程式設計工作階段",
- "startCodingTaskFromPhone": "從手機開始程式設計任務,或從 CLI 繼續工作階段。",
- "tryIt": "試試看",
"newCodingTask": "新程式設計任務",
"explore": "探索",
"seeAll": "查看全部",
- "kiloAgents": "Kilo Agents"
+ "noLiveSessions": "Nothing running right now"
},
"imageViewer": {
"close": "關閉 {{filename}}",
diff --git a/apps/mobile/src/i18n/locales/zu.json b/apps/mobile/src/i18n/locales/zu.json
index af6c8cdbaf..07c3972877 100644
--- a/apps/mobile/src/i18n/locales/zu.json
+++ b/apps/mobile/src/i18n/locales/zu.json
@@ -148,7 +148,9 @@
"appearanceSystem": "Isistimu",
"appearanceLight": "Ukukhanya",
"appearanceDark": "Ubumnyama",
- "account": "Akhawunti"
+ "account": "Akhawunti",
+ "prReviewAttribution": "Add app attribution to PR reviews",
+ "prReviewAttributionSubtitle": "Append a Reviewed via Kilo footer when you submit a review."
},
"prReview": {
"pullRequestUnavailable": "Isicelo sokudonsa asitholakali",
@@ -2176,7 +2178,8 @@
"discardDraftMessage": "Umphakamo wakho uzolahleka.",
"keepEditing": "Qhubeka uhlela",
"discard": "Lahla",
- "discardFailed": "Akukwazanga ukulahla idrafuthi. Sicela uzame futhi."
+ "discardFailed": "Akukwazanga ukulahla idrafuthi. Sicela uzame futhi.",
+ "remoteHint": "Run `kilo remote` on your computer, or `/remote` in a running CLI session, to control a local kilo process."
},
"partRenderer": {
"updatedFileCount_one": "Kubuyekezwe ifayela eli-{{displayCount}}",
@@ -2662,15 +2665,10 @@
"couldNotLoadSessions": "Asikwazanga ukulayisha amaseshini",
"couldNotLoadActiveSessions": "Asikwazanga ukulayisha amaseshini asebenzayo",
"agentSessions": "Amaseshini e-agent",
- "showingSavedSessions": "Kuboniswa amaseshini agciniwe — isimo esibukhoma singase siphelelwe yisikhathi",
- "startNewAgentSession": "Qala iseshini entsha ye-Kilo Agent",
- "aiCodingSessions": "Amaseshini okubhala ikhodi e-AI",
- "startCodingTaskFromPhone": "Qala umsebenzi wokubhala ikhodi usuka kufoni yakho noma uqhubeke ngeseshini esuka ku-CLI yakho.",
- "tryIt": "Zama",
"newCodingTask": "Umsebenzi omusha wokubhala ikhodi",
"explore": "Hlola",
"seeAll": "Bona konke",
- "kiloAgents": "Ama-Kilo Agents"
+ "noLiveSessions": "Nothing running right now"
},
"imageViewer": {
"close": "Vala {{filename}}",
diff --git a/apps/mobile/src/lib/auth/auth-context.test.tsx b/apps/mobile/src/lib/auth/auth-context.test.tsx
index 9f67ed1c21..b5504300d3 100644
--- a/apps/mobile/src/lib/auth/auth-context.test.tsx
+++ b/apps/mobile/src/lib/auth/auth-context.test.tsx
@@ -147,14 +147,18 @@ vi.mock('@/lib/hooks/use-persisted-agent-model', () => ({
clearAgentModelPreference: vi.fn(),
}));
-const { clearKeepScreenOnPreference, clearReasoningPreference } = vi.hoisted(() => ({
- clearKeepScreenOnPreference: vi.fn(),
- clearReasoningPreference: vi.fn(),
-}));
+const { clearKeepScreenOnPreference, clearReasoningPreference, clearPrReviewFooterPreference } =
+ vi.hoisted(() => ({
+ clearKeepScreenOnPreference: vi.fn(),
+ clearReasoningPreference: vi.fn(),
+ clearPrReviewFooterPreference: vi.fn(),
+ }));
vi.mock('@/lib/hooks/use-keep-screen-on-preference', () => ({ clearKeepScreenOnPreference }));
vi.mock('@/lib/hooks/use-reasoning-preference', () => ({ clearReasoningPreference }));
+vi.mock('@/lib/hooks/use-pr-review-footer-preference', () => ({ clearPrReviewFooterPreference }));
+
vi.mock('@/lib/last-active-instance', () => ({
clearLastActiveInstance: vi.fn().mockResolvedValue(undefined),
}));
@@ -385,7 +389,7 @@ describe('sign-out teardown ordering', () => {
unmount();
});
- it('clears both local preferences on sign-out', async () => {
+ it('clears the local preferences on sign-out', async () => {
const { ctx } = await mountAndGetContext();
await act(async () => {
@@ -394,6 +398,7 @@ describe('sign-out teardown ordering', () => {
expect(clearKeepScreenOnPreference).toHaveBeenCalled();
expect(clearReasoningPreference).toHaveBeenCalled();
+ expect(clearPrReviewFooterPreference).toHaveBeenCalled();
});
it('closes the ownership gate before any await and blocks a late persist', async () => {
diff --git a/apps/mobile/src/lib/auth/auth-context.tsx b/apps/mobile/src/lib/auth/auth-context.tsx
index dec04a63a1..fdc87a2e29 100644
--- a/apps/mobile/src/lib/auth/auth-context.tsx
+++ b/apps/mobile/src/lib/auth/auth-context.tsx
@@ -37,6 +37,7 @@ import {
import { chainSave } from '@/lib/hooks/save-chain';
import { clearAgentModelPreference } from '@/lib/hooks/use-persisted-agent-model';
import { clearKeepScreenOnPreference } from '@/lib/hooks/use-keep-screen-on-preference';
+import { clearPrReviewFooterPreference } from '@/lib/hooks/use-pr-review-footer-preference';
import { clearReasoningPreference } from '@/lib/hooks/use-reasoning-preference';
import { clearKiloClawOwned, gateKiloClawOwned } from '@/lib/kiloclaw-tab-ownership';
import { clearLastActiveInstance } from '@/lib/last-active-instance';
@@ -337,6 +338,7 @@ export function AuthProvider({ children }: { readonly children: ReactNode }) {
clearAgentModelPreference();
clearReasoningPreference();
clearKeepScreenOnPreference();
+ clearPrReviewFooterPreference();
} finally {
queryClient.clear();
setSessionEnded(ended);
diff --git a/apps/mobile/src/lib/auth/credentials.test.ts b/apps/mobile/src/lib/auth/credentials.test.ts
index b8a572b75c..df7048efb2 100644
--- a/apps/mobile/src/lib/auth/credentials.test.ts
+++ b/apps/mobile/src/lib/auth/credentials.test.ts
@@ -55,6 +55,9 @@ vi.mock('@/lib/hooks/use-persisted-agent-model', () => ({ clearAgentModelPrefere
vi.mock('@/lib/hooks/use-keep-screen-on-preference', () => ({
clearKeepScreenOnPreference: vi.fn(),
}));
+vi.mock('@/lib/hooks/use-pr-review-footer-preference', () => ({
+ clearPrReviewFooterPreference: vi.fn(),
+}));
vi.mock('@/lib/hooks/use-reasoning-preference', () => ({ clearReasoningPreference: vi.fn() }));
vi.mock('@/lib/kiloclaw-tab-ownership', () => ({
gateKiloClawOwned: vi.fn(),
diff --git a/apps/mobile/src/lib/hooks/use-pr-review-footer-preference.test.ts b/apps/mobile/src/lib/hooks/use-pr-review-footer-preference.test.ts
new file mode 100644
index 0000000000..e43e357fb5
--- /dev/null
+++ b/apps/mobile/src/lib/hooks/use-pr-review-footer-preference.test.ts
@@ -0,0 +1,112 @@
+import { beforeEach, describe, expect, it, vi } from 'vitest';
+
+const { getItemAsync, setItemAsync, deleteItemAsync } = vi.hoisted(() => ({
+ getItemAsync: vi.fn(),
+ setItemAsync: vi.fn(),
+ deleteItemAsync: vi.fn(),
+}));
+vi.mock('expo-secure-store', () => ({ getItemAsync, setItemAsync, deleteItemAsync }));
+
+const { captureException } = vi.hoisted(() => ({ captureException: vi.fn() }));
+vi.mock('@sentry/react-native', () => ({ captureException }));
+
+const { toastError } = vi.hoisted(() => ({ toastError: vi.fn() }));
+vi.mock('sonner-native', () => ({ toast: { error: toastError } }));
+
+// eslint-disable-next-line typescript-eslint/promise-function-async -- conflicting require-await rule
+function flushMicrotasks(): Promise {
+ return new Promise(resolve => {
+ setImmediate(resolve);
+ });
+}
+
+// eslint-disable-next-line no-empty-function -- listener body is irrelevant, only subscribe()'s side effect (starting the load) is under test
+function noopListener(): void {}
+
+// eslint-disable-next-line typescript-eslint/promise-function-async -- conflicting require-await rule
+function makeStore() {
+ // Re-import lazily so the mock wiring above is in effect.
+ return import('./secure-store-preference').then(({ createSecureStorePreference }) =>
+ createSecureStorePreference({
+ key: 'pr-review-footer-enabled',
+ defaultValue: true,
+ parse: raw => raw !== 'false',
+ serialize: value => (value ? 'true' : 'false'),
+ })
+ );
+}
+
+describe('parsePrReviewFooter', () => {
+ it('defaults to on for a missing value (fresh install and unreadable read)', async () => {
+ const { parsePrReviewFooter } = await import('./use-pr-review-footer-preference');
+ expect(parsePrReviewFooter(null)).toBe(true);
+ });
+
+ it("reads 'true' as on", async () => {
+ const { parsePrReviewFooter } = await import('./use-pr-review-footer-preference');
+ expect(parsePrReviewFooter('true')).toBe(true);
+ });
+
+ it("reads 'false' as off — the only value that turns the preference off", async () => {
+ const { parsePrReviewFooter } = await import('./use-pr-review-footer-preference');
+ expect(parsePrReviewFooter('false')).toBe(false);
+ });
+
+ it('treats any other stored string as on', async () => {
+ const { parsePrReviewFooter } = await import('./use-pr-review-footer-preference');
+ expect(parsePrReviewFooter('')).toBe(true);
+ expect(parsePrReviewFooter('nonsense')).toBe(true);
+ });
+});
+
+describe('pr-review-footer store', () => {
+ beforeEach(() => {
+ getItemAsync.mockReset();
+ setItemAsync.mockReset();
+ deleteItemAsync.mockReset();
+ captureException.mockReset();
+ toastError.mockReset();
+ });
+
+ it('defaults to on when SecureStore returns null', async () => {
+ getItemAsync.mockResolvedValue(null);
+ const store = await makeStore();
+
+ const unsubscribe = store.subscribe(noopListener);
+ await flushMicrotasks();
+
+ expect(store.get()).toBe(true);
+ expect(store.getHasLoaded()).toBe(true);
+ unsubscribe();
+ });
+
+ it("turns off only for the stored string 'false'", async () => {
+ getItemAsync.mockResolvedValue('false');
+ const store = await makeStore();
+
+ const unsubscribe = store.subscribe(noopListener);
+ await flushMicrotasks();
+
+ expect(store.get()).toBe(false);
+ expect(store.getHasLoaded()).toBe(true);
+ unsubscribe();
+ });
+
+ it('persists a set value and clears back to the default on sign-out', async () => {
+ getItemAsync.mockResolvedValue(null);
+ const store = await makeStore();
+
+ store.set(false);
+ await flushMicrotasks();
+ expect(setItemAsync).toHaveBeenCalledWith('pr-review-footer-enabled', 'false');
+
+ store.set(true);
+ await flushMicrotasks();
+ expect(setItemAsync).toHaveBeenCalledWith('pr-review-footer-enabled', 'true');
+
+ store.clear();
+ await flushMicrotasks();
+ expect(deleteItemAsync).toHaveBeenCalledWith('pr-review-footer-enabled');
+ expect(store.get()).toBe(true);
+ });
+});
diff --git a/apps/mobile/src/lib/hooks/use-pr-review-footer-preference.ts b/apps/mobile/src/lib/hooks/use-pr-review-footer-preference.ts
new file mode 100644
index 0000000000..8fae001f02
--- /dev/null
+++ b/apps/mobile/src/lib/hooks/use-pr-review-footer-preference.ts
@@ -0,0 +1,34 @@
+import { useSyncExternalStore } from 'react';
+
+import { createSecureStorePreference } from '@/lib/hooks/secure-store-preference';
+import { PR_REVIEW_FOOTER_KEY } from '@/lib/storage-keys';
+
+/**
+ * Default-on preference: only the exact stored string 'false' turns it off, so a
+ * missing or unreadable value keeps the PR-review attribution footer the app
+ * ships with.
+ */
+export function parsePrReviewFooter(raw: string | null): boolean {
+ return raw !== 'false';
+}
+
+const store = createSecureStorePreference({
+ key: PR_REVIEW_FOOTER_KEY,
+ defaultValue: true,
+ parse: parsePrReviewFooter,
+ serialize: value => (value ? 'true' : 'false'),
+});
+
+export function clearPrReviewFooterPreference() {
+ store.clear();
+}
+
+function setPrReviewFooter(value: boolean) {
+ store.set(value);
+}
+
+export function usePrReviewFooterPreference() {
+ const prReviewFooter = useSyncExternalStore(store.subscribe, store.get);
+ const hasLoaded = useSyncExternalStore(store.subscribe, store.getHasLoaded);
+ return { prReviewFooter, hasLoaded, setPrReviewFooter };
+}
diff --git a/apps/mobile/src/lib/pr-review/review-footer.test.ts b/apps/mobile/src/lib/pr-review/review-footer.test.ts
new file mode 100644
index 0000000000..538e2f5d34
--- /dev/null
+++ b/apps/mobile/src/lib/pr-review/review-footer.test.ts
@@ -0,0 +1,24 @@
+import { describe, expect, it } from 'vitest';
+
+import { buildReviewFooter } from './review-footer';
+
+const IOS_URL = 'https://apps.apple.com/app/id6761193135';
+const ANDROID_URL = 'https://play.google.com/store/apps/details?id=com.kilocode.kiloapp';
+
+describe('buildReviewFooter', () => {
+ it('builds the iOS footer with the App Store link for the ios platform', () => {
+ expect(buildReviewFooter('ios')).toBe(`\n\n---\nReviewed via the [Kilo iOS app](${IOS_URL})`);
+ });
+
+ it('builds the Android footer with the Play Store link for the android platform', () => {
+ expect(buildReviewFooter('android')).toBe(
+ `\n\n---\nReviewed via the [Kilo Android app](${ANDROID_URL})`
+ );
+ });
+
+ it('builds the Android footer for any non-iOS platform string', () => {
+ expect(buildReviewFooter('windows')).toBe(
+ `\n\n---\nReviewed via the [Kilo Android app](${ANDROID_URL})`
+ );
+ });
+});
diff --git a/apps/mobile/src/lib/pr-review/review-footer.ts b/apps/mobile/src/lib/pr-review/review-footer.ts
new file mode 100644
index 0000000000..66d647aada
--- /dev/null
+++ b/apps/mobile/src/lib/pr-review/review-footer.ts
@@ -0,0 +1,14 @@
+// PR-review attribution footer appended to the review summary when the
+// default-on preference is enabled. The input is the running platform's OS,
+// so iOS gets the iOS App Store link and every other platform (Android
+// included) gets the Play Store link.
+
+const IOS_APP_URL = 'https://apps.apple.com/app/id6761193135';
+const ANDROID_APP_URL = 'https://play.google.com/store/apps/details?id=com.kilocode.kiloapp';
+
+export function buildReviewFooter(os: 'ios' | 'android' | string): string {
+ if (os === 'ios') {
+ return `\n\n---\nReviewed via the [Kilo iOS app](${IOS_APP_URL})`;
+ }
+ return `\n\n---\nReviewed via the [Kilo Android app](${ANDROID_APP_URL})`;
+}
diff --git a/apps/mobile/src/lib/resolve-live-instance.test.ts b/apps/mobile/src/lib/resolve-live-instance.test.ts
new file mode 100644
index 0000000000..0f00165318
--- /dev/null
+++ b/apps/mobile/src/lib/resolve-live-instance.test.ts
@@ -0,0 +1,45 @@
+import { describe, expect, it } from 'vitest';
+
+import { type InstancePickerInstance } from '@/lib/picker-bridge';
+
+import { resolveLiveInstance } from './resolve-live-instance';
+
+const SELECTED: InstancePickerInstance = {
+ connectionId: 'conn-stale',
+ name: 'host-a',
+ projectName: 'proj',
+};
+
+describe('resolveLiveInstance', () => {
+ it('returns the instance with the same connectionId', () => {
+ const live: InstancePickerInstance = {
+ connectionId: 'conn-stale',
+ name: 'host-a',
+ projectName: 'proj',
+ version: '1.2.3',
+ };
+
+ expect(resolveLiveInstance(SELECTED, [live])).toBe(live);
+ });
+
+ it('returns the instance with the same name and projectName when the id differs', () => {
+ const live: InstancePickerInstance = {
+ connectionId: 'conn-live',
+ name: 'host-a',
+ projectName: 'proj',
+ };
+
+ expect(resolveLiveInstance(SELECTED, [live])).toBe(live);
+ });
+
+ it('returns null when no instance matches the id or the name/project pair', () => {
+ const unrelated: InstancePickerInstance = {
+ connectionId: 'conn-other',
+ name: 'host-b',
+ projectName: 'other',
+ };
+
+ expect(resolveLiveInstance(SELECTED, [unrelated])).toBeNull();
+ expect(resolveLiveInstance(SELECTED, [])).toBeNull();
+ });
+});
diff --git a/apps/mobile/src/lib/resolve-live-instance.ts b/apps/mobile/src/lib/resolve-live-instance.ts
new file mode 100644
index 0000000000..37ae5705d0
--- /dev/null
+++ b/apps/mobile/src/lib/resolve-live-instance.ts
@@ -0,0 +1,31 @@
+import { type InstancePickerInstance } from '@/lib/picker-bridge';
+
+/**
+ * Resolve the live instance row for a press-time selection against a freshly
+ * refetched instance list.
+ *
+ * A host reboot reconnects its CLI with the same instance `name` and
+ * `projectName` but a new `connectionId`. The selector keeps the old
+ * `connectionId`; the refetched list carries the live one. This helper maps
+ * the selection onto the live row:
+ *
+ * - identical `connectionId` -> the live row for that id
+ * - same `name`+`projectName` -> the live row (connectionId remapped)
+ * - otherwise -> null (the host has fully disconnected)
+ */
+export function resolveLiveInstance(
+ selected: InstancePickerInstance,
+ instances: InstancePickerInstance[]
+): InstancePickerInstance | null {
+ const sameConnectionId = instances.find(
+ instance => instance.connectionId === selected.connectionId
+ );
+ if (sameConnectionId) {
+ return sameConnectionId;
+ }
+
+ const sameHost = instances.find(
+ instance => instance.name === selected.name && instance.projectName === selected.projectName
+ );
+ return sameHost ?? null;
+}
diff --git a/apps/mobile/src/lib/share-payload.ts b/apps/mobile/src/lib/share-payload.ts
index 595d4ad490..9a46e03901 100644
--- a/apps/mobile/src/lib/share-payload.ts
+++ b/apps/mobile/src/lib/share-payload.ts
@@ -1,3 +1,4 @@
+import { CLOUD_AGENT_PROMPT_MAX_LENGTH } from '@kilocode/cloud-agent-sdk/limits';
import * as Crypto from 'expo-crypto';
import { cacheDirectory, copyAsync, deleteAsync } from 'expo-file-system/legacy';
import { type ShareIntent } from 'expo-share-intent';
@@ -13,8 +14,8 @@ export type SharePayload = {
failedFiles: string[];
};
-/** Mirrors PROMPT_INPUT_MAX_CHARS in new-session-prompt.tsx (module-local; composer clamps again). */
-export const SHARE_TEXT_MAX_CHARS = 4000;
+/** The cloud agent prompt cap; the composer clamps again on delivery. */
+export const SHARE_TEXT_MAX_CHARS = CLOUD_AGENT_PROMPT_MAX_LENGTH;
export const SHARE_PAYLOAD_MAX_ENTRIES = 5;
diff --git a/apps/mobile/src/lib/storage-keys.ts b/apps/mobile/src/lib/storage-keys.ts
index 8896f725a7..b81a4c0de7 100644
--- a/apps/mobile/src/lib/storage-keys.ts
+++ b/apps/mobile/src/lib/storage-keys.ts
@@ -26,6 +26,7 @@ export const LOGIN_EMAIL_DRAFT_KEY = 'login-email-draft';
/** Login SSO-recovery banner draft, persisted before an RTL language reload. */
export const LOGIN_SSO_RECOVERY_DRAFT_KEY = 'login-sso-recovery-draft';
export const KEEP_SCREEN_ON_KEY = 'keep-session-screen-on';
+export const PR_REVIEW_FOOTER_KEY = 'pr-review-footer-enabled';
/** SQLCipher database key for the encrypted persistence store (DEC-01). */
export const PERSIST_DB_KEY = 'persist-db-key';
/**
diff --git a/apps/web/src/lib/cloud-agent/constants.ts b/apps/web/src/lib/cloud-agent/constants.ts
index 3e5c5fe9b9..cb88aea974 100644
--- a/apps/web/src/lib/cloud-agent/constants.ts
+++ b/apps/web/src/lib/cloud-agent/constants.ts
@@ -178,11 +178,7 @@ export function normalizeAttachmentExtension(extension: string | undefined | nul
export type { CloudAgentAttachments } from '@kilocode/app-shared/cloud-agent';
/**
- * Maximum prompt length (in characters) accepted by the cloud agent.
- *
- * Mirrors the server-side cap in `services/cloud-agent-next/src/schema.ts`
- * (`Limits.MAX_PROMPT_LENGTH`). Prompts exceeding this would be rejected by
- * the worker, so we enforce the same limit client-side to give users
- * immediate feedback.
+ * Maximum prompt length (in characters) accepted by the cloud agent. Defined
+ * once in the SDK so the web, mobile, and extension composers share it.
*/
-export const CLOUD_AGENT_PROMPT_MAX_LENGTH = 100_000;
+export { CLOUD_AGENT_PROMPT_MAX_LENGTH } from '@kilocode/cloud-agent-sdk/limits';
diff --git a/packages/cloud-agent-sdk/src/limits.ts b/packages/cloud-agent-sdk/src/limits.ts
new file mode 100644
index 0000000000..e41f2601a3
--- /dev/null
+++ b/packages/cloud-agent-sdk/src/limits.ts
@@ -0,0 +1,8 @@
+/**
+ * Maximum prompt length (in characters) accepted by the cloud agent.
+ *
+ * Mirrors the server-side cap in `services/cloud-agent-next/src/schema.ts`
+ * (`Limits.MAX_PROMPT_LENGTH`). Every client enforces the same limit so a
+ * composer never silently drops text the worker would have accepted.
+ */
+export const CLOUD_AGENT_PROMPT_MAX_LENGTH = 100_000;
diff --git a/services/session-ingest/src/dos/UserConnectionDO.test.ts b/services/session-ingest/src/dos/UserConnectionDO.test.ts
index eeb0571fd0..5b4714ed36 100644
--- a/services/session-ingest/src/dos/UserConnectionDO.test.ts
+++ b/services/session-ingest/src/dos/UserConnectionDO.test.ts
@@ -4117,6 +4117,140 @@ describe('UserConnectionDO', () => {
});
});
+ // -------------------------------------------------------------------------
+ // Same-host reconnect: a rebooted host advertises the same instance name and
+ // projectName on a fresh connectionId. The stale socket must be closed so
+ // `getConnectedInstances` lists the host exactly once.
+ // -------------------------------------------------------------------------
+
+ describe('same-host replace', () => {
+ it('closes the stale socket when a second connectionId heartbeats the same instance identity', async () => {
+ const { doInstance, mockCtx } = setup();
+ const first = addCliSocket(mockCtx, 'conn-1');
+ const second = addCliSocket(mockCtx, 'conn-2');
+
+ sendHeartbeat(doInstance, first, [], {
+ instance: { name: 'host-a', projectName: 'proj' },
+ });
+ sendHeartbeat(doInstance, second, [], {
+ instance: { name: 'host-a', projectName: 'proj' },
+ });
+
+ expect(first.close).toHaveBeenCalledWith(1000, 'replaced by same-host reconnect');
+ expect(second.close).not.toHaveBeenCalled();
+
+ // The mock close does not drop the socket; remove it to mirror the
+ // runtime close before asserting the live-instance scan.
+ mockCtx.removeSocket(first);
+
+ const { instances } = doInstance.getConnectedInstances();
+ expect(instances).toHaveLength(1);
+ expect(instances[0].connectionId).toBe('conn-2');
+ expect(instances[0]).toEqual({
+ connectionId: 'conn-2',
+ name: 'host-a',
+ projectName: 'proj',
+ });
+ });
+
+ it('keeps both sockets open when the projectName differs', async () => {
+ const { doInstance, mockCtx } = setup();
+ const first = addCliSocket(mockCtx, 'conn-1');
+ const second = addCliSocket(mockCtx, 'conn-2');
+
+ sendHeartbeat(doInstance, first, [], {
+ instance: { name: 'host-a', projectName: 'proj-1' },
+ });
+ sendHeartbeat(doInstance, second, [], {
+ instance: { name: 'host-a', projectName: 'proj-2' },
+ });
+
+ expect(first.close).not.toHaveBeenCalled();
+ expect(second.close).not.toHaveBeenCalled();
+ });
+
+ it('keeps both sockets open when the name differs', async () => {
+ const { doInstance, mockCtx } = setup();
+ const first = addCliSocket(mockCtx, 'conn-1');
+ const second = addCliSocket(mockCtx, 'conn-2');
+
+ sendHeartbeat(doInstance, first, [], {
+ instance: { name: 'host-a', projectName: 'proj' },
+ });
+ sendHeartbeat(doInstance, second, [], {
+ instance: { name: 'host-b', projectName: 'proj' },
+ });
+
+ expect(first.close).not.toHaveBeenCalled();
+ expect(second.close).not.toHaveBeenCalled();
+ });
+
+ it('does not broadcast cli.disconnected or overwrite the owner-change terminal result for a same-host replaced socket', async () => {
+ const { doInstance, mockCtx } = setup();
+ const first = addCliSocket(mockCtx, 'conn-1');
+ const webWs = addWebSocket(mockCtx, 'web-1');
+
+ sendHeartbeat(doInstance, first, [makeSession('s1')], {
+ instance: { name: 'host-a', projectName: 'proj' },
+ });
+
+ // An owner-fenced pending command targets the first socket.
+ await sendCommand(doInstance, webWs, {
+ id: 'cmd-1',
+ command: 'send_message',
+ sessionId: 's1',
+ connectionId: 'conn-1',
+ });
+ const correlationId = getCorrelationId(first);
+ webWs.send.mockClear();
+
+ // A second socket on a different connectionId claims the same host.
+ const second = addCliSocket(mockCtx, 'conn-2');
+ sendHeartbeat(doInstance, second, [], {
+ instance: { name: 'host-a', projectName: 'proj' },
+ });
+
+ expect(first.close).toHaveBeenCalledWith(1000, 'replaced by same-host reconnect');
+
+ // Drain the stale-close failPendingCommandsForSocket waitUntil so the
+ // owner-change terminal result settles before the close event runs.
+ await flushAsync();
+
+ // The stale close delivers the owner-change error, not 'CLI disconnected'.
+ const preClose = allSent(webWs);
+ expect(preClose.find(m => m.type === 'response' && m.id === 'cmd-1')).toEqual({
+ type: 'response',
+ id: 'cmd-1',
+ error: {
+ source: 'relay',
+ code: 'SESSION_OWNER_CHANGED',
+ message: 'Session owner changed',
+ },
+ });
+ webWs.send.mockClear();
+
+ // The close event for the stale first socket now fires.
+ mockCtx.removeSocket(first);
+ await disconnectCli(doInstance, first);
+
+ const msgs = allSent(webWs);
+ expect(msgs.some(m => m.type === 'system' && m.event === 'cli.disconnected')).toBe(false);
+ expect(msgs.filter(m => m.type === 'response' && m.id === 'cmd-1')).toHaveLength(0);
+
+ // Durable terminal entry keeps the owner-change error.
+ const durable = mockCtx.storage.store.get(`pendingCommand/${correlationId}`) as {
+ state: string;
+ error?: unknown;
+ };
+ expect(durable.state).toBe('done');
+ expect(durable.error).toEqual({
+ source: 'relay',
+ code: 'SESSION_OWNER_CHANGED',
+ message: 'Session owner changed',
+ });
+ });
+ });
+
// -------------------------------------------------------------------------
// WS attachment size guardrail (W3)
// -------------------------------------------------------------------------
diff --git a/services/session-ingest/src/dos/UserConnectionDO.ts b/services/session-ingest/src/dos/UserConnectionDO.ts
index 0f090233a6..3e33ec9a42 100644
--- a/services/session-ingest/src/dos/UserConnectionDO.ts
+++ b/services/session-ingest/src/dos/UserConnectionDO.ts
@@ -42,6 +42,11 @@ type WSAttachment =
role: 'cli';
connectionId: string;
sessions: HeartbeatSession[];
+ // Set on a stale same-host socket just before its close so
+ // `handleCliDisconnect` treats the close as a replacement (the new
+ // socket already heartbeated) and skips the `cliGone` pending-command
+ // sweep and the `cli.disconnected` broadcast.
+ replaced?: true;
// Undefined means no protocolVersion has been reported yet — either the
// CLI hasn't sent its first heartbeat, or it's a legacy build that
// predates this field entirely. Both cases fall back to legacy behavior.
@@ -575,6 +580,11 @@ export class UserConnectionDO extends DurableObject {
instance: Instance | undefined
): void {
const { connectionId } = attachment;
+ // Legacy CLIs omit `instance` entirely; only close a stale same-host
+ // socket when the heartbeat actually carries an instance identity.
+ if (instance) {
+ this.closeStaleSocketsForInstance(instance.name, instance.projectName, connectionId);
+ }
const now = Date.now();
this.lastHeartbeatAt.set(connectionId, now);
this.connectionProtocolVersion.set(connectionId, protocolVersion);
@@ -1731,11 +1741,16 @@ export class UserConnectionDO extends DurableObject {
// Exclude the closing socket: under wrangler/workerd, getWebSockets() still
// includes it during webSocketClose, so matching self would always look "replaced"
// and skip ownership cleanup + attention reset (DEF-5 E2E failure).
- const replaced = this.ctx.getWebSockets('cli').some(ws => {
- if (ws === disconnectedWs) return false;
- const att = ws.deserializeAttachment() as WSAttachment | null;
- return att?.role === 'cli' && att.connectionId === connectionId;
- });
+ // A same-host replacement sets the `replaced` marker on this socket's own
+ // attachment before closing (see closeStaleSocketsForInstance), because its
+ // replacement carries a different connectionId.
+ const replaced =
+ attachment.replaced ||
+ this.ctx.getWebSockets('cli').some(ws => {
+ if (ws === disconnectedWs) return false;
+ const att = ws.deserializeAttachment() as WSAttachment | null;
+ return att?.role === 'cli' && att.connectionId === connectionId;
+ });
// Fail pending commands that targeted this specific socket.
// Await so the durable terminal entries are persisted before we proceed
@@ -2025,6 +2040,41 @@ export class UserConnectionDO extends DurableObject {
return false;
}
+ // Old form: one live CLI socket per connectionId, including a rebooted host's stale socket. Remove when every CLI advertises a stable host id.
+ private closeStaleSocketsForInstance(
+ name: string,
+ projectName: string,
+ keepConnectionId: string
+ ): void {
+ if (!name || !projectName) return;
+
+ for (const ws of this.ctx.getWebSockets('cli')) {
+ const att = ws.deserializeAttachment() as WSAttachment | null;
+ if (att?.role !== 'cli' || att.connectionId === keepConnectionId) continue;
+ if (att.instance?.name !== name || att.instance?.projectName !== projectName) continue;
+
+ console.log('Closing stale CLI socket for same-host reconnect', {
+ connectionId: att.connectionId,
+ name,
+ projectName,
+ });
+ this.ctx.waitUntil(
+ this.failPendingCommandsForSocket(ws, false).catch((error: unknown) => {
+ console.error('Failed to persist terminal commands for stale socket', {
+ connectionId: att.connectionId,
+ error: error instanceof Error ? error.message : String(error),
+ });
+ })
+ );
+ // Preserve session ownership — the rebooting host's replacement socket
+ // re-claims the same sessions in its first heartbeat.
+ // Mark the attachment so `handleCliDisconnect` routes this close through
+ // the `replaced` early-return (the replacement already heartbeated).
+ ws.serializeAttachment({ ...att, replaced: true });
+ ws.close(1000, 'replaced by same-host reconnect');
+ }
+ }
+
private replaceWebSocket(connectionId: string): void {
for (const ws of this.ctx.getWebSockets('web')) {
const attachment = ws.deserializeAttachment() as WSAttachment | null;