mirror of
https://github.com/Kilo-Org/kilocode.git
synced 2026-10-24 23:13:35 +08:00
Merge branch 'main' into mark/nextedit-kilo-gateway
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"kilo-code": minor
|
||||
---
|
||||
|
||||
Add a "Not set (use server default)" option to the autocomplete model picker so users can follow the recommended default automatically. Users who previously had the default model pinned only because it was the only thing visible in the dropdown are migrated to "Not set" once.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"kilo-code": patch
|
||||
---
|
||||
|
||||
Center local session history delete buttons within their rows.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"kilo-code": patch
|
||||
---
|
||||
|
||||
Improve the size and readability of the local History session context menu.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"@kilocode/cli": patch
|
||||
---
|
||||
|
||||
Keep the extension responsive while semantic indexing processes large workspaces.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"kilo-code": minor
|
||||
---
|
||||
|
||||
Allow renaming sessions with a consistent inline editor in the active chat header and History, using safe bounded titles.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"kilo-code": patch
|
||||
---
|
||||
|
||||
Warn when a chat turn stops unexpectedly or ends while tracked to-dos remain unfinished.
|
||||
@@ -219,7 +219,7 @@ Changeset descriptions appear directly in release notes and are read by end user
|
||||
|
||||
## Pull Requests
|
||||
|
||||
PR descriptions should be 2-3 lines covering **what** changed and **why**. Focus on intent and context a reviewer can't get from the diff — skip file-by-file inventories, test result summaries, and anything obvious from the code itself.
|
||||
PR descriptions should explain **what** changed, **why** the change is needed, and the intent or constraints a reviewer cannot infer from the diff alone. Keep simple PRs brief, but give non-trivial changes enough context to stand on their own. Skip file-by-file inventories, test result summaries, and anything obvious from the code itself.
|
||||
|
||||
## GitHub Issues
|
||||
|
||||
|
||||
@@ -76,7 +76,7 @@ Other Mistral models do not get automatic reasoning variants, even if they appea
|
||||
|
||||
## Using Codestral
|
||||
|
||||
[Codestral](https://docs.mistral.ai/capabilities/code_generation/) is a model specifically designed for code generation and interaction.
|
||||
[Codestral](https://docs.mistral.ai/vibe/code/overview) is a model specifically designed for code generation and interaction.
|
||||
Only for Codestral you could use different endpoints (Default: codestral.mistral.ai).
|
||||
For the La Platforme API Key change the **Codestral Base Url** to: https://api.mistral.ai
|
||||
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:eee5f5d61cf2ac9ad0b987a8b220d76c503be0d11447766e6669da4684698c82
|
||||
size 6130
|
||||
oid sha256:bbdf3df267cb9c32febbaa486b7a63e8561e1d968bda24bb5278634307eac873
|
||||
size 5962
|
||||
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:e6d0ccfb86ad9a6eaab64e1afe455a96cd4c1443f12fbd47698a4730724712b6
|
||||
size 931
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:4544323cd000c4f43b88c420bbf2b7cb72317b6d40b0b0f3c690fb9deabaa27d
|
||||
size 3737
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:65686e2d0978adcf09ae504d9414e2d81f304eb18ff2275be7a33a9c3579a5e5
|
||||
size 18209
|
||||
oid sha256:32fa296aeee4f45f1cefe49d8eaca08099a8b3b8c23d4e9cdec803ce7fd1f0a1
|
||||
size 18207
|
||||
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:7338febdf802b5ce501773be164e9da152fb7903e9b16807bd8751fa38f208ed
|
||||
size 10310
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:f7e075b4961d3a62c8deda6b481f64cb8777d05183a9c10d0dd2373b7972d3ab
|
||||
size 53678
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:b0dd1dc26b28d354ecd14c53dd1b9e6158a161f47152f30299ba4c0827ce1674
|
||||
size 50904
|
||||
-3
@@ -1,3 +0,0 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:2c925148c349c6ab1f14190a2a379aa24869de35e5b77455fa15d8868eb08343
|
||||
size 5943
|
||||
-3
@@ -1,3 +0,0 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:5094e214a52bac4627f8fe280f4818c986753c49f160bf5295f21122054ea72f
|
||||
size 53684
|
||||
-3
@@ -1,3 +0,0 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:83a70ef1260f77c3017db90a918ee77c332c065bfc047e0f206948bb5dde83b9
|
||||
size 50888
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:e1a5dfe9704a74cbfa2da2a179ed995bcc31def156e798277dcfb568b25db58d
|
||||
size 35913
|
||||
oid sha256:bbfed6606c5e1ccd6a744bdadf34ee597007d5f82c436c8c53e189560e0837d4
|
||||
size 30244
|
||||
|
||||
@@ -96,7 +96,20 @@ const models: AutocompleteModelDef[] = [
|
||||
|
||||
export const AUTOCOMPLETE_MODELS: readonly AutocompleteModelDef[] = models
|
||||
|
||||
export const DEFAULT_AUTOCOMPLETE_MODEL: AutocompleteModelDef = models[0]!
|
||||
export const DEFAULT_AUTOCOMPLETE_PROVIDER_ID: AutocompleteProviderID = "kilo"
|
||||
export const DEFAULT_AUTOCOMPLETE_MODEL_ID = "mistralai/codestral-2508"
|
||||
|
||||
export const DEFAULT_AUTOCOMPLETE_MODEL: AutocompleteModelDef = (() => {
|
||||
const found = models.find(
|
||||
(m) => m.providerID === DEFAULT_AUTOCOMPLETE_PROVIDER_ID && m.modelID === DEFAULT_AUTOCOMPLETE_MODEL_ID,
|
||||
)
|
||||
if (!found) {
|
||||
throw new Error(
|
||||
`DEFAULT_AUTOCOMPLETE_MODEL not found: provider=${DEFAULT_AUTOCOMPLETE_PROVIDER_ID} model=${DEFAULT_AUTOCOMPLETE_MODEL_ID}`,
|
||||
)
|
||||
}
|
||||
return found
|
||||
})()
|
||||
|
||||
const aliases: Record<string, string> = {
|
||||
"inception/mercury-edit": "inception/mercury-edit-2",
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
import { describe, expect, test } from "bun:test"
|
||||
import {
|
||||
AUTOCOMPLETE_MODELS,
|
||||
DEFAULT_AUTOCOMPLETE_MODEL,
|
||||
DEFAULT_AUTOCOMPLETE_MODEL_ID,
|
||||
DEFAULT_AUTOCOMPLETE_PROVIDER_ID,
|
||||
} from "../src/autocomplete"
|
||||
|
||||
describe("DEFAULT_AUTOCOMPLETE_MODEL", () => {
|
||||
test("resolves to an entry that exists in AUTOCOMPLETE_MODELS", () => {
|
||||
const match = AUTOCOMPLETE_MODELS.find(
|
||||
(m) => m.providerID === DEFAULT_AUTOCOMPLETE_PROVIDER_ID && m.modelID === DEFAULT_AUTOCOMPLETE_MODEL_ID,
|
||||
)
|
||||
expect(match).toBeDefined()
|
||||
expect(DEFAULT_AUTOCOMPLETE_MODEL).toBe(match!)
|
||||
})
|
||||
})
|
||||
Generated
+5
-3
@@ -19,7 +19,6 @@ export const dict = {
|
||||
// Marketplace
|
||||
"marketplace.tab.skills": "المهارات",
|
||||
"marketplace.tab.mcpServers": "خوادم MCP",
|
||||
"marketplace.tab.modes": "الأوضاع",
|
||||
"marketplace.category.all": "الكل",
|
||||
"marketplace.placeholder": "سيتم تنفيذه لاحقاً",
|
||||
"marketplace.card.installed": "مثبت",
|
||||
@@ -45,6 +44,7 @@ export const dict = {
|
||||
"marketplace.remove.cancel": "إلغاء",
|
||||
"marketplace.remove.confirm.button": "إزالة",
|
||||
"marketplace.tab.mcp": "MCP",
|
||||
"marketplace.tab.agents": "وكلاء",
|
||||
"marketplace.search": "بحث...",
|
||||
"marketplace.filter.all": "جميع العناصر",
|
||||
"marketplace.filter.notInstalled": "غير مثبت",
|
||||
@@ -60,7 +60,7 @@ export const dict = {
|
||||
"marketplace.scope.global": "عام",
|
||||
"marketplace.remove.type.mcp": "خادم MCP",
|
||||
"marketplace.remove.type.skill": "مهارة",
|
||||
"marketplace.remove.type.mode": "وضع",
|
||||
"marketplace.remove.type.agent": "وكيل",
|
||||
"marketplace.remove.failed": "فشلت إزالة {{name}}",
|
||||
"marketplace.install": "تثبيت",
|
||||
"marketplace.filter.installed": "مثبت",
|
||||
@@ -69,8 +69,10 @@ export const dict = {
|
||||
"marketplace.warning.busyMany": "عدة جلسات تعمل وستتوقف",
|
||||
"marketplace.warning.installAnyway": "تثبيت على أي حال",
|
||||
"marketplace.warning.cancel": "إلغاء",
|
||||
"marketplace.contribute.prompt": "هل تفتقد مهارة أو وضعًا أو خادم MCP؟",
|
||||
"marketplace.contribute.prompt": "هل تفتقد مهارة أو وكيلاً أو خادم MCP؟",
|
||||
"marketplace.contribute.cta": "ساهم على GitHub",
|
||||
"marketplace.migration.notice":
|
||||
"تم استبدال الأوضاع بالوكلاء. إذا كنت قد قمت بتثبيت أوضاع السوق سابقاً، يرجى إزالتها وإعادة تثبيتها كوكلاء للانتقال إلى التنسيق الجديد.",
|
||||
|
||||
// Plan follow-up question shown after plan_exit
|
||||
"plan.followup.header": "نفّذ",
|
||||
|
||||
Generated
+5
-3
@@ -19,7 +19,6 @@ export const dict = {
|
||||
// Marketplace
|
||||
"marketplace.tab.skills": "Skills",
|
||||
"marketplace.tab.mcpServers": "Servidores MCP",
|
||||
"marketplace.tab.modes": "Modos",
|
||||
"marketplace.category.all": "Todos",
|
||||
"marketplace.placeholder": "A ser implementado",
|
||||
"marketplace.card.installed": "Instalado",
|
||||
@@ -45,6 +44,7 @@ export const dict = {
|
||||
"marketplace.remove.cancel": "Cancelar",
|
||||
"marketplace.remove.confirm.button": "Remover",
|
||||
"marketplace.tab.mcp": "MCP",
|
||||
"marketplace.tab.agents": "Agentes",
|
||||
"marketplace.search": "Pesquisar...",
|
||||
"marketplace.filter.all": "Todos os Itens",
|
||||
"marketplace.filter.notInstalled": "Não Instalado",
|
||||
@@ -60,7 +60,7 @@ export const dict = {
|
||||
"marketplace.scope.global": "global",
|
||||
"marketplace.remove.type.mcp": "servidor MCP",
|
||||
"marketplace.remove.type.skill": "habilidade",
|
||||
"marketplace.remove.type.mode": "modo",
|
||||
"marketplace.remove.type.agent": "agente",
|
||||
"marketplace.remove.failed": "Falha ao remover {{name}}",
|
||||
"marketplace.install": "Instalar",
|
||||
"marketplace.filter.installed": "Instalado",
|
||||
@@ -69,8 +69,10 @@ export const dict = {
|
||||
"marketplace.warning.busyMany": "Várias sessões estão em execução e serão interrompidas",
|
||||
"marketplace.warning.installAnyway": "Instalar mesmo assim",
|
||||
"marketplace.warning.cancel": "Cancelar",
|
||||
"marketplace.contribute.prompt": "Está faltando uma skill, modo ou servidor MCP?",
|
||||
"marketplace.contribute.prompt": "Está faltando uma skill, agente ou servidor MCP?",
|
||||
"marketplace.contribute.cta": "Contribuir no GitHub",
|
||||
"marketplace.migration.notice":
|
||||
"Os modos foram substituídos por agentes. Se você instalou modos do marketplace anteriormente, remova-os e reinstale-os como agentes para migrar para o novo formato.",
|
||||
|
||||
// Plan follow-up question shown after plan_exit
|
||||
"plan.followup.header": "Implementar",
|
||||
|
||||
Generated
+5
-3
@@ -24,7 +24,6 @@ export const dict = {
|
||||
// Marketplace
|
||||
"marketplace.tab.skills": "Vještine",
|
||||
"marketplace.tab.mcpServers": "MCP Serveri",
|
||||
"marketplace.tab.modes": "Modovi",
|
||||
"marketplace.category.all": "Sve",
|
||||
"marketplace.placeholder": "Biće implementirano",
|
||||
"marketplace.card.installed": "Instalirano",
|
||||
@@ -50,6 +49,7 @@ export const dict = {
|
||||
"marketplace.remove.cancel": "Otkaži",
|
||||
"marketplace.remove.confirm.button": "Ukloni",
|
||||
"marketplace.tab.mcp": "MCP",
|
||||
"marketplace.tab.agents": "Agenti",
|
||||
"marketplace.search": "Pretraži...",
|
||||
"marketplace.filter.all": "Sve stavke",
|
||||
"marketplace.filter.notInstalled": "Nije instalirano",
|
||||
@@ -65,7 +65,7 @@ export const dict = {
|
||||
"marketplace.scope.global": "globalno",
|
||||
"marketplace.remove.type.mcp": "MCP server",
|
||||
"marketplace.remove.type.skill": "vještina",
|
||||
"marketplace.remove.type.mode": "režim",
|
||||
"marketplace.remove.type.agent": "agent",
|
||||
"marketplace.remove.failed": "Uklanjanje {{name}} nije uspjelo",
|
||||
"marketplace.install": "Instaliraj",
|
||||
"marketplace.filter.installed": "Instalirano",
|
||||
@@ -74,8 +74,10 @@ export const dict = {
|
||||
"marketplace.warning.busyMany": "Nekoliko sesija je pokrenuto i bit će prekinuto",
|
||||
"marketplace.warning.installAnyway": "Instaliraj svejedno",
|
||||
"marketplace.warning.cancel": "Otkaži",
|
||||
"marketplace.contribute.prompt": "Nedostaje vještina, način rada ili MCP server?",
|
||||
"marketplace.contribute.prompt": "Nedostaje vještina, agent ili MCP server?",
|
||||
"marketplace.contribute.cta": "Doprinesi na GitHub-u",
|
||||
"marketplace.migration.notice":
|
||||
"Modovi su zamijenjeni agentima. Ako ste prethodno instalirali marketplace modove, uklonite ih i ponovo instalirajte kao agente da biste prešli na novi format.",
|
||||
|
||||
// Plan follow-up question shown after plan_exit
|
||||
"plan.followup.header": "Implementiraj",
|
||||
|
||||
Generated
+5
-3
@@ -19,7 +19,6 @@ export const dict = {
|
||||
// Marketplace
|
||||
"marketplace.tab.skills": "Skills",
|
||||
"marketplace.tab.mcpServers": "MCP-servere",
|
||||
"marketplace.tab.modes": "Tilstande",
|
||||
"marketplace.category.all": "Alle",
|
||||
"marketplace.placeholder": "Skal implementeres",
|
||||
"marketplace.card.installed": "Installeret",
|
||||
@@ -45,6 +44,7 @@ export const dict = {
|
||||
"marketplace.remove.cancel": "Annuller",
|
||||
"marketplace.remove.confirm.button": "Fjern",
|
||||
"marketplace.tab.mcp": "MCP",
|
||||
"marketplace.tab.agents": "Agenter",
|
||||
"marketplace.search": "Søg...",
|
||||
"marketplace.filter.all": "Alle elementer",
|
||||
"marketplace.filter.notInstalled": "Ikke installeret",
|
||||
@@ -60,7 +60,7 @@ export const dict = {
|
||||
"marketplace.scope.global": "global",
|
||||
"marketplace.remove.type.mcp": "MCP-server",
|
||||
"marketplace.remove.type.skill": "færdighed",
|
||||
"marketplace.remove.type.mode": "tilstand",
|
||||
"marketplace.remove.type.agent": "agent",
|
||||
"marketplace.remove.failed": "Kunne ikke fjerne {{name}}",
|
||||
"marketplace.install": "Installer",
|
||||
"marketplace.filter.installed": "Installeret",
|
||||
@@ -69,8 +69,10 @@ export const dict = {
|
||||
"marketplace.warning.busyMany": "Flere sessioner kører og vil blive afbrudt",
|
||||
"marketplace.warning.installAnyway": "Installer alligevel",
|
||||
"marketplace.warning.cancel": "Annuller",
|
||||
"marketplace.contribute.prompt": "Mangler du en skill, tilstand eller MCP-server?",
|
||||
"marketplace.contribute.prompt": "Mangler du en skill, agent eller MCP-server?",
|
||||
"marketplace.contribute.cta": "Bidrag på GitHub",
|
||||
"marketplace.migration.notice":
|
||||
"Tilstande er blevet erstattet af agenter. Hvis du tidligere har installeret marketplace-tilstande, skal du fjerne dem og geninstallere dem som agenter for at migrere til det nye format.",
|
||||
|
||||
// Plan follow-up question shown after plan_exit
|
||||
"plan.followup.header": "Implementér",
|
||||
|
||||
Generated
+5
-3
@@ -19,7 +19,6 @@ export const dict = {
|
||||
// Marketplace
|
||||
"marketplace.tab.skills": "Skills",
|
||||
"marketplace.tab.mcpServers": "MCP-Server",
|
||||
"marketplace.tab.modes": "Modi",
|
||||
"marketplace.category.all": "Alle",
|
||||
"marketplace.placeholder": "Noch nicht implementiert",
|
||||
"marketplace.card.installed": "Installiert",
|
||||
@@ -45,6 +44,7 @@ export const dict = {
|
||||
"marketplace.remove.cancel": "Abbrechen",
|
||||
"marketplace.remove.confirm.button": "Entfernen",
|
||||
"marketplace.tab.mcp": "MCP",
|
||||
"marketplace.tab.agents": "Agenten",
|
||||
"marketplace.search": "Suchen...",
|
||||
"marketplace.filter.all": "Alle Elemente",
|
||||
"marketplace.filter.notInstalled": "Nicht installiert",
|
||||
@@ -60,7 +60,7 @@ export const dict = {
|
||||
"marketplace.scope.global": "Global",
|
||||
"marketplace.remove.type.mcp": "MCP-Server",
|
||||
"marketplace.remove.type.skill": "Skill",
|
||||
"marketplace.remove.type.mode": "Modus",
|
||||
"marketplace.remove.type.agent": "Agent",
|
||||
"marketplace.remove.failed": "Fehler beim Entfernen von {{name}}",
|
||||
"marketplace.install": "Installieren",
|
||||
"marketplace.filter.installed": "Installiert",
|
||||
@@ -69,8 +69,10 @@ export const dict = {
|
||||
"marketplace.warning.busyMany": "Mehrere Sitzungen laufen und werden unterbrochen",
|
||||
"marketplace.warning.installAnyway": "Trotzdem installieren",
|
||||
"marketplace.warning.cancel": "Abbrechen",
|
||||
"marketplace.contribute.prompt": "Fehlt ein Skill, Modus oder MCP-Server?",
|
||||
"marketplace.contribute.prompt": "Fehlt ein Skill, Agent oder MCP-Server?",
|
||||
"marketplace.contribute.cta": "Auf GitHub beitragen",
|
||||
"marketplace.migration.notice":
|
||||
"Modi wurden durch Agenten ersetzt. Wenn Sie zuvor Marketplace-Modi installiert haben, entfernen Sie diese bitte und installieren Sie sie als Agenten neu, um zum neuen Format zu migrieren.",
|
||||
|
||||
// Plan follow-up question shown after plan_exit
|
||||
"plan.followup.header": "Umsetzen",
|
||||
|
||||
@@ -21,7 +21,6 @@ export const dict = {
|
||||
// Marketplace
|
||||
"marketplace.tab.skills": "Skills",
|
||||
"marketplace.tab.mcpServers": "MCP Servers",
|
||||
"marketplace.tab.modes": "Modes",
|
||||
"marketplace.category.all": "All",
|
||||
"marketplace.placeholder": "To be implemented",
|
||||
"marketplace.card.installed": "Installed",
|
||||
@@ -47,6 +46,7 @@ export const dict = {
|
||||
"marketplace.remove.cancel": "Cancel",
|
||||
"marketplace.remove.confirm.button": "Remove",
|
||||
"marketplace.tab.mcp": "MCP",
|
||||
"marketplace.tab.agents": "Agents",
|
||||
"marketplace.search": "Search...",
|
||||
"marketplace.filter.all": "All Items",
|
||||
"marketplace.filter.notInstalled": "Not Installed",
|
||||
@@ -62,7 +62,7 @@ export const dict = {
|
||||
"marketplace.scope.global": "global",
|
||||
"marketplace.remove.type.mcp": "MCP server",
|
||||
"marketplace.remove.type.skill": "skill",
|
||||
"marketplace.remove.type.mode": "mode",
|
||||
"marketplace.remove.type.agent": "agent",
|
||||
"marketplace.remove.failed": "Failed to remove {{name}}",
|
||||
"marketplace.install": "Install",
|
||||
"marketplace.filter.installed": "Installed",
|
||||
@@ -71,8 +71,10 @@ export const dict = {
|
||||
"marketplace.warning.busyMany": "Several sessions are running and will be interrupted",
|
||||
"marketplace.warning.installAnyway": "Install anyway",
|
||||
"marketplace.warning.cancel": "Cancel",
|
||||
"marketplace.contribute.prompt": "Missing a skill, mode, or MCP server?",
|
||||
"marketplace.contribute.prompt": "Missing a skill, agent, or MCP server?",
|
||||
"marketplace.contribute.cta": "Contribute on GitHub",
|
||||
"marketplace.migration.notice":
|
||||
"Modes have been replaced by agents. If you previously installed marketplace modes, please remove and reinstall them as agents to migrate to the new format.",
|
||||
|
||||
// Plan follow-up question shown after plan_exit. The English strings here must match
|
||||
// the canonical `label`/`header`/`question` sent by the backend — those canonical labels
|
||||
|
||||
Generated
+5
-3
@@ -19,7 +19,6 @@ export const dict = {
|
||||
// Marketplace
|
||||
"marketplace.tab.skills": "Skills",
|
||||
"marketplace.tab.mcpServers": "Servidores MCP",
|
||||
"marketplace.tab.modes": "Modos",
|
||||
"marketplace.category.all": "Todos",
|
||||
"marketplace.placeholder": "Por implementar",
|
||||
"marketplace.card.installed": "Instalado",
|
||||
@@ -45,6 +44,7 @@ export const dict = {
|
||||
"marketplace.remove.cancel": "Cancelar",
|
||||
"marketplace.remove.confirm.button": "Eliminar",
|
||||
"marketplace.tab.mcp": "MCP",
|
||||
"marketplace.tab.agents": "Agentes",
|
||||
"marketplace.search": "Buscar...",
|
||||
"marketplace.filter.all": "Todos los elementos",
|
||||
"marketplace.filter.notInstalled": "No instalado",
|
||||
@@ -60,7 +60,7 @@ export const dict = {
|
||||
"marketplace.scope.global": "global",
|
||||
"marketplace.remove.type.mcp": "servidor MCP",
|
||||
"marketplace.remove.type.skill": "habilidad",
|
||||
"marketplace.remove.type.mode": "modo",
|
||||
"marketplace.remove.type.agent": "agente",
|
||||
"marketplace.remove.failed": "Error al eliminar {{name}}",
|
||||
"marketplace.install": "Instalar",
|
||||
"marketplace.filter.installed": "Instalado",
|
||||
@@ -69,8 +69,10 @@ export const dict = {
|
||||
"marketplace.warning.busyMany": "Varias sesiones están en ejecución y se interrumpirán",
|
||||
"marketplace.warning.installAnyway": "Instalar de todas formas",
|
||||
"marketplace.warning.cancel": "Cancelar",
|
||||
"marketplace.contribute.prompt": "¿Falta una skill, modo o servidor MCP?",
|
||||
"marketplace.contribute.prompt": "¿Falta una skill, agente o servidor MCP?",
|
||||
"marketplace.contribute.cta": "Contribuir en GitHub",
|
||||
"marketplace.migration.notice":
|
||||
"Los modos han sido reemplazados por agentes. Si anteriormente instalaste modos del marketplace, elimínalos y reinstálalos como agentes para migrar al nuevo formato.",
|
||||
|
||||
// Plan follow-up question shown after plan_exit
|
||||
"plan.followup.header": "Implementar",
|
||||
|
||||
Generated
+5
-3
@@ -19,7 +19,6 @@ export const dict = {
|
||||
// Marketplace
|
||||
"marketplace.tab.skills": "Skills",
|
||||
"marketplace.tab.mcpServers": "Serveurs MCP",
|
||||
"marketplace.tab.modes": "Modes",
|
||||
"marketplace.category.all": "Tout",
|
||||
"marketplace.placeholder": "À implémenter",
|
||||
"marketplace.card.installed": "Installé",
|
||||
@@ -45,6 +44,7 @@ export const dict = {
|
||||
"marketplace.remove.cancel": "Annuler",
|
||||
"marketplace.remove.confirm.button": "Supprimer",
|
||||
"marketplace.tab.mcp": "MCP",
|
||||
"marketplace.tab.agents": "Agents",
|
||||
"marketplace.search": "Rechercher...",
|
||||
"marketplace.filter.all": "Tous les éléments",
|
||||
"marketplace.filter.notInstalled": "Non installé",
|
||||
@@ -60,7 +60,7 @@ export const dict = {
|
||||
"marketplace.scope.global": "global",
|
||||
"marketplace.remove.type.mcp": "serveur MCP",
|
||||
"marketplace.remove.type.skill": "compétence",
|
||||
"marketplace.remove.type.mode": "mode",
|
||||
"marketplace.remove.type.agent": "agent",
|
||||
"marketplace.remove.failed": "Échec de la suppression de {{name}}",
|
||||
"marketplace.install": "Installer",
|
||||
"marketplace.filter.installed": "Installé",
|
||||
@@ -69,8 +69,10 @@ export const dict = {
|
||||
"marketplace.warning.busyMany": "Plusieurs sessions sont en cours et seront interrompues",
|
||||
"marketplace.warning.installAnyway": "Installer quand même",
|
||||
"marketplace.warning.cancel": "Annuler",
|
||||
"marketplace.contribute.prompt": "Il manque une skill, un mode ou un serveur MCP ?",
|
||||
"marketplace.contribute.prompt": "Il manque une compétence, un agent ou un serveur MCP ?",
|
||||
"marketplace.contribute.cta": "Contribuer sur GitHub",
|
||||
"marketplace.migration.notice":
|
||||
"Les modes ont été remplacés par des agents. Si vous avez précédemment installé des modes depuis le marketplace, veuillez les supprimer et les réinstaller en tant qu'agents pour migrer vers le nouveau format.",
|
||||
|
||||
// Plan follow-up question shown after plan_exit
|
||||
"plan.followup.header": "Implémenter",
|
||||
|
||||
Generated
+5
-3
@@ -18,7 +18,6 @@ export const dict = {
|
||||
// Marketplace
|
||||
"marketplace.tab.skills": "スキル",
|
||||
"marketplace.tab.mcpServers": "MCPサーバー",
|
||||
"marketplace.tab.modes": "モード",
|
||||
"marketplace.category.all": "すべて",
|
||||
"marketplace.placeholder": "未実装",
|
||||
"marketplace.card.installed": "インストール済み",
|
||||
@@ -43,6 +42,7 @@ export const dict = {
|
||||
"marketplace.remove.cancel": "キャンセル",
|
||||
"marketplace.remove.confirm.button": "削除",
|
||||
"marketplace.tab.mcp": "MCP",
|
||||
"marketplace.tab.agents": "エージェント",
|
||||
"marketplace.search": "検索...",
|
||||
"marketplace.filter.all": "すべてのアイテム",
|
||||
"marketplace.filter.notInstalled": "未インストール",
|
||||
@@ -58,7 +58,7 @@ export const dict = {
|
||||
"marketplace.scope.global": "グローバル",
|
||||
"marketplace.remove.type.mcp": "MCPサーバー",
|
||||
"marketplace.remove.type.skill": "スキル",
|
||||
"marketplace.remove.type.mode": "モード",
|
||||
"marketplace.remove.type.agent": "エージェント",
|
||||
"marketplace.remove.failed": "{{name}} の削除に失敗しました",
|
||||
"marketplace.install": "インストール",
|
||||
"marketplace.filter.installed": "インストール済み",
|
||||
@@ -67,8 +67,10 @@ export const dict = {
|
||||
"marketplace.warning.busyMany": "複数のセッションが実行中で中断されます",
|
||||
"marketplace.warning.installAnyway": "それでもインストール",
|
||||
"marketplace.warning.cancel": "キャンセル",
|
||||
"marketplace.contribute.prompt": "スキル、モード、MCP サーバーが見つかりませんか?",
|
||||
"marketplace.contribute.prompt": "スキル、エージェント、またはMCPサーバーが見つかりませんか?",
|
||||
"marketplace.contribute.cta": "GitHub で貢献する",
|
||||
"marketplace.migration.notice":
|
||||
"モードはエージェントに置き換えられました。以前にマーケットプレイスのモードをインストールしていた場合は、新しい形式に移行するためにそれらを削除してエージェントとして再インストールしてください。",
|
||||
|
||||
// Plan follow-up question shown after plan_exit
|
||||
"plan.followup.header": "実装",
|
||||
|
||||
Generated
+5
-3
@@ -18,7 +18,6 @@ export const dict = {
|
||||
// Marketplace
|
||||
"marketplace.tab.skills": "스킬",
|
||||
"marketplace.tab.mcpServers": "MCP 서버",
|
||||
"marketplace.tab.modes": "모드",
|
||||
"marketplace.category.all": "전체",
|
||||
"marketplace.placeholder": "구현 예정",
|
||||
"marketplace.card.installed": "설치됨",
|
||||
@@ -43,6 +42,7 @@ export const dict = {
|
||||
"marketplace.remove.cancel": "취소",
|
||||
"marketplace.remove.confirm.button": "제거",
|
||||
"marketplace.tab.mcp": "MCP",
|
||||
"marketplace.tab.agents": "에이전트",
|
||||
"marketplace.search": "검색...",
|
||||
"marketplace.filter.all": "모든 항목",
|
||||
"marketplace.filter.notInstalled": "설치되지 않음",
|
||||
@@ -58,7 +58,7 @@ export const dict = {
|
||||
"marketplace.scope.global": "글로벌",
|
||||
"marketplace.remove.type.mcp": "MCP 서버",
|
||||
"marketplace.remove.type.skill": "스킬",
|
||||
"marketplace.remove.type.mode": "모드",
|
||||
"marketplace.remove.type.agent": "에이전트",
|
||||
"marketplace.remove.failed": "{{name}} 제거 실패",
|
||||
"marketplace.install": "설치",
|
||||
"marketplace.filter.installed": "설치됨",
|
||||
@@ -67,8 +67,10 @@ export const dict = {
|
||||
"marketplace.warning.busyMany": "여러 세션이 실행 중이며 중단됩니다",
|
||||
"marketplace.warning.installAnyway": "그래도 설치",
|
||||
"marketplace.warning.cancel": "취소",
|
||||
"marketplace.contribute.prompt": "스킬, 모드 또는 MCP 서버가 없나요?",
|
||||
"marketplace.contribute.prompt": "스킬, 에이전트 또는 MCP 서버가 없나요?",
|
||||
"marketplace.contribute.cta": "GitHub에서 기여하기",
|
||||
"marketplace.migration.notice":
|
||||
"모드가 에이전트로 대체되었습니다. 이전에 마켓플레이스 모드를 설치한 경우 새 형식으로 마이그레이션하려면 해당 모드를 제거하고 에이전트로 다시 설치하세요.",
|
||||
|
||||
// Plan follow-up question shown after plan_exit
|
||||
"plan.followup.header": "구현",
|
||||
|
||||
Generated
+5
-3
@@ -21,7 +21,6 @@ export const dict = {
|
||||
// Marketplace
|
||||
"marketplace.tab.skills": "Skills",
|
||||
"marketplace.tab.mcpServers": "MCP Servers",
|
||||
"marketplace.tab.modes": "Modi",
|
||||
"marketplace.category.all": "Alle",
|
||||
"marketplace.placeholder": "Nog te implementeren",
|
||||
"marketplace.card.installed": "Geïnstalleerd",
|
||||
@@ -47,6 +46,7 @@ export const dict = {
|
||||
"marketplace.remove.cancel": "Annuleren",
|
||||
"marketplace.remove.confirm.button": "Verwijderen",
|
||||
"marketplace.tab.mcp": "MCP",
|
||||
"marketplace.tab.agents": "Agenten",
|
||||
"marketplace.search": "Zoeken...",
|
||||
"marketplace.filter.all": "Alle items",
|
||||
"marketplace.filter.notInstalled": "Niet geïnstalleerd",
|
||||
@@ -62,7 +62,7 @@ export const dict = {
|
||||
"marketplace.scope.global": "globaal",
|
||||
"marketplace.remove.type.mcp": "MCP server",
|
||||
"marketplace.remove.type.skill": "skill",
|
||||
"marketplace.remove.type.mode": "modus",
|
||||
"marketplace.remove.type.agent": "agent",
|
||||
"marketplace.remove.failed": "Verwijderen van {{name}} mislukt",
|
||||
"marketplace.install": "Installeren",
|
||||
"marketplace.filter.installed": "Geïnstalleerd",
|
||||
@@ -71,8 +71,10 @@ export const dict = {
|
||||
"marketplace.warning.busyMany": "Er zijn meerdere sessies actief en deze zullen worden onderbroken",
|
||||
"marketplace.warning.installAnyway": "Toch installeren",
|
||||
"marketplace.warning.cancel": "Annuleren",
|
||||
"marketplace.contribute.prompt": "Mist er een skill, modus of MCP-server?",
|
||||
"marketplace.contribute.prompt": "Mist u een skill, agent of MCP-server?",
|
||||
"marketplace.contribute.cta": "Bijdragen op GitHub",
|
||||
"marketplace.migration.notice":
|
||||
"Modi zijn vervangen door agenten. Als u eerder marketplace-modi hebt geïnstalleerd, verwijder ze dan en installeer ze opnieuw als agenten om naar het nieuwe formaat te migreren.",
|
||||
|
||||
// Plan follow-up question shown after plan_exit
|
||||
"plan.followup.header": "Implementeren",
|
||||
|
||||
Generated
+5
-3
@@ -19,7 +19,6 @@ export const dict = {
|
||||
// Marketplace
|
||||
"marketplace.tab.skills": "Skills",
|
||||
"marketplace.tab.mcpServers": "MCP-servere",
|
||||
"marketplace.tab.modes": "Moduser",
|
||||
"marketplace.category.all": "Alle",
|
||||
"marketplace.placeholder": "Skal implementeres",
|
||||
"marketplace.card.installed": "Installert",
|
||||
@@ -45,6 +44,7 @@ export const dict = {
|
||||
"marketplace.remove.cancel": "Avbryt",
|
||||
"marketplace.remove.confirm.button": "Fjern",
|
||||
"marketplace.tab.mcp": "MCP",
|
||||
"marketplace.tab.agents": "Agenter",
|
||||
"marketplace.search": "Søk...",
|
||||
"marketplace.filter.all": "Alle elementer",
|
||||
"marketplace.filter.notInstalled": "Ikke installert",
|
||||
@@ -60,7 +60,7 @@ export const dict = {
|
||||
"marketplace.scope.global": "global",
|
||||
"marketplace.remove.type.mcp": "MCP-server",
|
||||
"marketplace.remove.type.skill": "ferdighet",
|
||||
"marketplace.remove.type.mode": "modus",
|
||||
"marketplace.remove.type.agent": "agent",
|
||||
"marketplace.remove.failed": "Kunne ikke fjerne {{name}}",
|
||||
"marketplace.install": "Installer",
|
||||
"marketplace.filter.installed": "Installert",
|
||||
@@ -69,8 +69,10 @@ export const dict = {
|
||||
"marketplace.warning.busyMany": "Flere økter kjører og vil bli avbrutt",
|
||||
"marketplace.warning.installAnyway": "Installer uansett",
|
||||
"marketplace.warning.cancel": "Avbryt",
|
||||
"marketplace.contribute.prompt": "Mangler du en skill, modus eller MCP-server?",
|
||||
"marketplace.contribute.prompt": "Mangler du en skill, agent eller MCP-server?",
|
||||
"marketplace.contribute.cta": "Bidra på GitHub",
|
||||
"marketplace.migration.notice":
|
||||
"Modi er erstattet av agenter. Hvis du tidligere har installert marketplace-modi, fjern dem og installer dem på nytt som agenter for å migrere til det nye formatet.",
|
||||
|
||||
// Plan follow-up question shown after plan_exit
|
||||
"plan.followup.header": "Implementer",
|
||||
|
||||
Generated
+5
-3
@@ -19,7 +19,6 @@ export const dict = {
|
||||
// Marketplace
|
||||
"marketplace.tab.skills": "Skills",
|
||||
"marketplace.tab.mcpServers": "Serwery MCP",
|
||||
"marketplace.tab.modes": "Tryby",
|
||||
"marketplace.category.all": "Wszystkie",
|
||||
"marketplace.placeholder": "Do zaimplementowania",
|
||||
"marketplace.card.installed": "Zainstalowano",
|
||||
@@ -45,6 +44,7 @@ export const dict = {
|
||||
"marketplace.remove.cancel": "Anuluj",
|
||||
"marketplace.remove.confirm.button": "Usuń",
|
||||
"marketplace.tab.mcp": "MCP",
|
||||
"marketplace.tab.agents": "Agenci",
|
||||
"marketplace.search": "Szukaj...",
|
||||
"marketplace.filter.all": "Wszystkie elementy",
|
||||
"marketplace.filter.notInstalled": "Nie zainstalowano",
|
||||
@@ -60,7 +60,7 @@ export const dict = {
|
||||
"marketplace.scope.global": "globalny",
|
||||
"marketplace.remove.type.mcp": "serwer MCP",
|
||||
"marketplace.remove.type.skill": "umiejętność",
|
||||
"marketplace.remove.type.mode": "tryb",
|
||||
"marketplace.remove.type.agent": "agent",
|
||||
"marketplace.remove.failed": "Nie udało się usunąć {{name}}",
|
||||
"marketplace.install": "Zainstaluj",
|
||||
"marketplace.filter.installed": "Zainstalowano",
|
||||
@@ -69,8 +69,10 @@ export const dict = {
|
||||
"marketplace.warning.busyMany": "Kilka sesji jest uruchomionych i zostanie przerwanych",
|
||||
"marketplace.warning.installAnyway": "Zainstaluj mimo to",
|
||||
"marketplace.warning.cancel": "Anuluj",
|
||||
"marketplace.contribute.prompt": "Brakuje skilla, trybu lub serwera MCP?",
|
||||
"marketplace.contribute.prompt": "Brakuje umiejętności, agenta lub serwera MCP?",
|
||||
"marketplace.contribute.cta": "Wnieś wkład na GitHubie",
|
||||
"marketplace.migration.notice":
|
||||
"Tryby zostały zastąpione przez agentów. Jeśli wcześniej instalowałeś tryby z marketplace, usuń je i zainstaluj ponownie jako agenty, aby przejść na nowy format.",
|
||||
|
||||
// Plan follow-up question shown after plan_exit
|
||||
"plan.followup.header": "Wdróż",
|
||||
|
||||
Generated
+5
-3
@@ -19,7 +19,6 @@ export const dict = {
|
||||
// Marketplace
|
||||
"marketplace.tab.skills": "Навыки",
|
||||
"marketplace.tab.mcpServers": "MCP-серверы",
|
||||
"marketplace.tab.modes": "Режимы",
|
||||
"marketplace.category.all": "Все",
|
||||
"marketplace.placeholder": "Будет реализовано",
|
||||
"marketplace.card.installed": "Установлено",
|
||||
@@ -45,6 +44,7 @@ export const dict = {
|
||||
"marketplace.remove.cancel": "Отмена",
|
||||
"marketplace.remove.confirm.button": "Удалить",
|
||||
"marketplace.tab.mcp": "MCP",
|
||||
"marketplace.tab.agents": "Агенты",
|
||||
"marketplace.search": "Поиск...",
|
||||
"marketplace.filter.all": "Все элементы",
|
||||
"marketplace.filter.notInstalled": "Не установлено",
|
||||
@@ -60,7 +60,7 @@ export const dict = {
|
||||
"marketplace.scope.global": "глобально",
|
||||
"marketplace.remove.type.mcp": "MCP-сервер",
|
||||
"marketplace.remove.type.skill": "навык",
|
||||
"marketplace.remove.type.mode": "режим",
|
||||
"marketplace.remove.type.agent": "агент",
|
||||
"marketplace.remove.failed": "Не удалось удалить {{name}}",
|
||||
"marketplace.install": "Установить",
|
||||
"marketplace.filter.installed": "Установлено",
|
||||
@@ -69,8 +69,10 @@ export const dict = {
|
||||
"marketplace.warning.busyMany": "Несколько сеансов выполняются и будут прерваны",
|
||||
"marketplace.warning.installAnyway": "Установить в любом случае",
|
||||
"marketplace.warning.cancel": "Отмена",
|
||||
"marketplace.contribute.prompt": "Не хватает навыка, режима или MCP-сервера?",
|
||||
"marketplace.contribute.prompt": "Не хватает навыка, агента или MCP-сервера?",
|
||||
"marketplace.contribute.cta": "Внести вклад на GitHub",
|
||||
"marketplace.migration.notice":
|
||||
"Режимы заменены агентами. Если вы ранее устанавливали режимы из магазина, удалите их и переустановите как агенты, чтобы перейти на новый формат.",
|
||||
|
||||
// Plan follow-up question shown after plan_exit
|
||||
"plan.followup.header": "Реализовать",
|
||||
|
||||
Generated
+5
-3
@@ -19,7 +19,6 @@ export const dict = {
|
||||
// Marketplace
|
||||
"marketplace.tab.skills": "ทักษะ",
|
||||
"marketplace.tab.mcpServers": "เซิร์ฟเวอร์ MCP",
|
||||
"marketplace.tab.modes": "โหมด",
|
||||
"marketplace.category.all": "ทั้งหมด",
|
||||
"marketplace.placeholder": "ยังไม่ได้ดำเนินการ",
|
||||
"marketplace.card.installed": "ติดตั้งแล้ว",
|
||||
@@ -45,6 +44,7 @@ export const dict = {
|
||||
"marketplace.remove.cancel": "ยกเลิก",
|
||||
"marketplace.remove.confirm.button": "ลบ",
|
||||
"marketplace.tab.mcp": "MCP",
|
||||
"marketplace.tab.agents": "เอเจนต์",
|
||||
"marketplace.search": "ค้นหา...",
|
||||
"marketplace.filter.all": "รายการทั้งหมด",
|
||||
"marketplace.filter.notInstalled": "ยังไม่ได้ติดตั้ง",
|
||||
@@ -60,7 +60,7 @@ export const dict = {
|
||||
"marketplace.scope.global": "โกลบอล",
|
||||
"marketplace.remove.type.mcp": "เซิร์ฟเวอร์ MCP",
|
||||
"marketplace.remove.type.skill": "ทักษะ",
|
||||
"marketplace.remove.type.mode": "โหมด",
|
||||
"marketplace.remove.type.agent": "เอเจนต์",
|
||||
"marketplace.remove.failed": "ไม่สามารถลบ {{name}} ได้",
|
||||
"marketplace.install": "ติดตั้ง",
|
||||
"marketplace.filter.installed": "ติดตั้งแล้ว",
|
||||
@@ -69,8 +69,10 @@ export const dict = {
|
||||
"marketplace.warning.busyMany": "มีหลายเซสชันกำลังทำงานและจะถูกขัดจังหวะ",
|
||||
"marketplace.warning.installAnyway": "ติดตั้งต่อไป",
|
||||
"marketplace.warning.cancel": "ยกเลิก",
|
||||
"marketplace.contribute.prompt": "ไม่พบทักษะ โหมด หรือเซิร์ฟเวอร์ MCP ที่ต้องการ?",
|
||||
"marketplace.contribute.prompt": "ขาดสกิล เอเจนต์ หรือเซิร์ฟเวอร์ MCP?",
|
||||
"marketplace.contribute.cta": "ร่วมสมทบบน GitHub",
|
||||
"marketplace.migration.notice":
|
||||
"โหมดถูกแทนที่ด้วยเอเจนต์แล้ว หากคุณเคยติดตั้งโหมดจาก marketplace กรุณาลบและติดตั้งใหม่เป็นเอเจนต์เพื่อย้ายไปยังรูปแบบใหม่",
|
||||
|
||||
// Plan follow-up question shown after plan_exit
|
||||
"plan.followup.header": "ดำเนินการ",
|
||||
|
||||
Generated
+5
-3
@@ -19,7 +19,6 @@ export const dict = {
|
||||
// Marketplace
|
||||
"marketplace.tab.skills": "Yetenekler",
|
||||
"marketplace.tab.mcpServers": "MCP Sunucuları",
|
||||
"marketplace.tab.modes": "Modlar",
|
||||
"marketplace.category.all": "Tümü",
|
||||
"marketplace.placeholder": "Uygulanacak",
|
||||
"marketplace.card.installed": "Yüklendi",
|
||||
@@ -45,6 +44,7 @@ export const dict = {
|
||||
"marketplace.remove.cancel": "İptal",
|
||||
"marketplace.remove.confirm.button": "Kaldır",
|
||||
"marketplace.tab.mcp": "MCP",
|
||||
"marketplace.tab.agents": "Ajanlar",
|
||||
"marketplace.search": "Ara...",
|
||||
"marketplace.filter.all": "Tüm Öğeler",
|
||||
"marketplace.filter.notInstalled": "Yüklü Değil",
|
||||
@@ -60,7 +60,7 @@ export const dict = {
|
||||
"marketplace.scope.global": "genel",
|
||||
"marketplace.remove.type.mcp": "MCP sunucusu",
|
||||
"marketplace.remove.type.skill": "yetenek",
|
||||
"marketplace.remove.type.mode": "mod",
|
||||
"marketplace.remove.type.agent": "ajan",
|
||||
"marketplace.remove.failed": "{{name}} kaldırılamadı",
|
||||
"marketplace.install": "Yükle",
|
||||
"marketplace.filter.installed": "Yüklendi",
|
||||
@@ -69,8 +69,10 @@ export const dict = {
|
||||
"marketplace.warning.busyMany": "Birden fazla oturum çalışıyor ve kesintiye uğrayacak",
|
||||
"marketplace.warning.installAnyway": "Yine de yükle",
|
||||
"marketplace.warning.cancel": "İptal",
|
||||
"marketplace.contribute.prompt": "Bir yetenek, mod veya MCP sunucusu mu eksik?",
|
||||
"marketplace.contribute.prompt": "Bir yetenek, ajan veya MCP sunucusu mu eksik?",
|
||||
"marketplace.contribute.cta": "GitHub'da katkıda bulun",
|
||||
"marketplace.migration.notice":
|
||||
"Modlar agentlarla değiştirildi. Daha önce marketplace modları yüklediyseniz, yeni formata geçiş yapmak için bunları kaldırın ve agent olarak yeniden yükleyin.",
|
||||
|
||||
// Plan follow-up question shown after plan_exit
|
||||
"plan.followup.header": "Uygula",
|
||||
|
||||
Generated
+5
-3
@@ -19,7 +19,6 @@ export const dict = {
|
||||
// Marketplace
|
||||
"marketplace.tab.skills": "Навички",
|
||||
"marketplace.tab.mcpServers": "MCP-сервери",
|
||||
"marketplace.tab.modes": "Режими",
|
||||
"marketplace.category.all": "Усі",
|
||||
"marketplace.placeholder": "Буде реалізовано",
|
||||
"marketplace.card.installed": "Встановлено",
|
||||
@@ -45,6 +44,7 @@ export const dict = {
|
||||
"marketplace.remove.cancel": "Скасувати",
|
||||
"marketplace.remove.confirm.button": "Видалити",
|
||||
"marketplace.tab.mcp": "MCP",
|
||||
"marketplace.tab.agents": "Агенти",
|
||||
"marketplace.search": "Пошук...",
|
||||
"marketplace.filter.all": "Усі елементи",
|
||||
"marketplace.filter.notInstalled": "Не встановлено",
|
||||
@@ -60,7 +60,7 @@ export const dict = {
|
||||
"marketplace.scope.global": "глобально",
|
||||
"marketplace.remove.type.mcp": "MCP-сервер",
|
||||
"marketplace.remove.type.skill": "навичка",
|
||||
"marketplace.remove.type.mode": "режим",
|
||||
"marketplace.remove.type.agent": "агент",
|
||||
"marketplace.remove.failed": "Не вдалося видалити {{name}}",
|
||||
"marketplace.install": "Встановити",
|
||||
"marketplace.filter.installed": "Встановлено",
|
||||
@@ -69,8 +69,10 @@ export const dict = {
|
||||
"marketplace.warning.busyMany": "Виконується кілька сесій, їх буде перервано",
|
||||
"marketplace.warning.installAnyway": "Встановити все одно",
|
||||
"marketplace.warning.cancel": "Скасувати",
|
||||
"marketplace.contribute.prompt": "Бракує навички, режиму або MCP-сервера?",
|
||||
"marketplace.contribute.prompt": "Бракує навички, агента або MCP-сервера?",
|
||||
"marketplace.contribute.cta": "Зробити внесок на GitHub",
|
||||
"marketplace.migration.notice":
|
||||
"Режими замінено агентами. Якщо ви раніше встановлювали режими з маркетплейсу, видаліть їх та перевстановіть як агенти для переходу на новий формат.",
|
||||
|
||||
// Plan follow-up question shown after plan_exit
|
||||
"plan.followup.header": "Реалізувати",
|
||||
|
||||
Generated
+5
-3
@@ -17,7 +17,6 @@ export const dict = {
|
||||
// Marketplace
|
||||
"marketplace.tab.skills": "技能",
|
||||
"marketplace.tab.mcpServers": "MCP 服务器",
|
||||
"marketplace.tab.modes": "模式",
|
||||
"marketplace.category.all": "全部",
|
||||
"marketplace.placeholder": "待实现",
|
||||
"marketplace.card.installed": "已安装",
|
||||
@@ -42,6 +41,7 @@ export const dict = {
|
||||
"marketplace.remove.cancel": "取消",
|
||||
"marketplace.remove.confirm.button": "移除",
|
||||
"marketplace.tab.mcp": "MCP",
|
||||
"marketplace.tab.agents": "智能体",
|
||||
"marketplace.search": "搜索...",
|
||||
"marketplace.filter.all": "所有项目",
|
||||
"marketplace.filter.notInstalled": "未安装",
|
||||
@@ -57,7 +57,7 @@ export const dict = {
|
||||
"marketplace.scope.global": "全局",
|
||||
"marketplace.remove.type.mcp": "MCP 服务器",
|
||||
"marketplace.remove.type.skill": "技能",
|
||||
"marketplace.remove.type.mode": "模式",
|
||||
"marketplace.remove.type.agent": "智能体",
|
||||
"marketplace.remove.failed": "移除 {{name}} 失败",
|
||||
"marketplace.install": "安装",
|
||||
"marketplace.filter.installed": "已安装",
|
||||
@@ -66,8 +66,10 @@ export const dict = {
|
||||
"marketplace.warning.busyMany": "多个会话正在运行,将被中断",
|
||||
"marketplace.warning.installAnyway": "仍然安装",
|
||||
"marketplace.warning.cancel": "取消",
|
||||
"marketplace.contribute.prompt": "缺少技能、模式或 MCP 服务器?",
|
||||
"marketplace.contribute.prompt": "缺少技能、智能体或 MCP 服务器?",
|
||||
"marketplace.contribute.cta": "在 GitHub 上贡献",
|
||||
"marketplace.migration.notice":
|
||||
"模式已被智能体取代。如果您之前安装了市场中的模式,请将其删除并重新安装为智能体,以迁移到新格式。",
|
||||
|
||||
// Plan follow-up question shown after plan_exit
|
||||
"plan.followup.header": "实现",
|
||||
|
||||
Generated
+5
-3
@@ -17,7 +17,6 @@ export const dict = {
|
||||
// Marketplace
|
||||
"marketplace.tab.skills": "技能",
|
||||
"marketplace.tab.mcpServers": "MCP 伺服器",
|
||||
"marketplace.tab.modes": "模式",
|
||||
"marketplace.category.all": "全部",
|
||||
"marketplace.placeholder": "待實作",
|
||||
"marketplace.card.installed": "已安裝",
|
||||
@@ -42,6 +41,7 @@ export const dict = {
|
||||
"marketplace.remove.cancel": "取消",
|
||||
"marketplace.remove.confirm.button": "移除",
|
||||
"marketplace.tab.mcp": "MCP",
|
||||
"marketplace.tab.agents": "智能體",
|
||||
"marketplace.search": "搜尋...",
|
||||
"marketplace.filter.all": "所有項目",
|
||||
"marketplace.filter.notInstalled": "未安裝",
|
||||
@@ -57,7 +57,7 @@ export const dict = {
|
||||
"marketplace.scope.global": "全域",
|
||||
"marketplace.remove.type.mcp": "MCP 伺服器",
|
||||
"marketplace.remove.type.skill": "技能",
|
||||
"marketplace.remove.type.mode": "模式",
|
||||
"marketplace.remove.type.agent": "智能體",
|
||||
"marketplace.remove.failed": "移除 {{name}} 失敗",
|
||||
"marketplace.install": "安裝",
|
||||
"marketplace.filter.installed": "已安裝",
|
||||
@@ -66,8 +66,10 @@ export const dict = {
|
||||
"marketplace.warning.busyMany": "多個工作階段正在執行,將被中斷",
|
||||
"marketplace.warning.installAnyway": "仍然安裝",
|
||||
"marketplace.warning.cancel": "取消",
|
||||
"marketplace.contribute.prompt": "缺少技能、模式或 MCP 伺服器?",
|
||||
"marketplace.contribute.prompt": "缺少技能、智能體或 MCP 伺服器?",
|
||||
"marketplace.contribute.cta": "在 GitHub 上貢獻",
|
||||
"marketplace.migration.notice":
|
||||
"模式已被智能體取代。如果您之前安裝了市場中的模式,請將其刪除並重新安裝為智能體,以遷移到新格式。",
|
||||
|
||||
// Plan follow-up question shown after plan_exit
|
||||
"plan.followup.header": "實作",
|
||||
|
||||
@@ -851,14 +851,14 @@
|
||||
"mercury-next-edit"
|
||||
],
|
||||
"enumDescriptions": [
|
||||
"Codestral via Kilo Gateway (default)",
|
||||
"Codestral via Kilo Gateway",
|
||||
"Mercury Edit 2 via Kilo Gateway",
|
||||
"Mercury Next Edit (multi-line edit predictions with jump-to-edit UX) via Kilo Gateway",
|
||||
"Codestral via your connected Mistral provider API key",
|
||||
"Mercury Edit 2 (FIM) via your connected Inception provider API key",
|
||||
"Mercury Next Edit (multi-line edit predictions with jump-to-edit UX) via your connected Inception provider API key"
|
||||
],
|
||||
"description": "Model to use for inline autocomplete suggestions"
|
||||
"description": "Model to use for inline autocomplete suggestions. If unset, the recommended default is used."
|
||||
},
|
||||
"kilo-code.new.autocomplete.provider": {
|
||||
"type": "string",
|
||||
|
||||
@@ -48,7 +48,12 @@ import { GitOps } from "./agent-manager/GitOps"
|
||||
import { GitStatsPoller, type LocalStats } from "./agent-manager/GitStatsPoller"
|
||||
import { diffSummary as localDiffSummary } from "./agent-manager/local-diff"
|
||||
import { getWorkspaceRoot } from "./review-utils"
|
||||
import { MarketplaceService, type MarketplaceItem, type RemoveResult } from "./services/marketplace"
|
||||
import {
|
||||
MarketplaceService,
|
||||
type MarketplaceItem,
|
||||
type AgentMarketplaceItem,
|
||||
type RemoveResult,
|
||||
} from "./services/marketplace"
|
||||
import type { RemoteStatusService } from "./services/RemoteStatusService"
|
||||
import { resolveProjectDirectory } from "./project-directory"
|
||||
import { getBusySessionCount, seedSessionStatuses } from "./session-status"
|
||||
@@ -57,6 +62,7 @@ import { retry } from "./services/cli-backend/retry"
|
||||
import { slimPart, slimParts } from "./kilo-provider/slim-metadata"
|
||||
import { handleSidebarWorktreeMessage } from "./kilo-provider/sidebar-worktree"
|
||||
import { parseMessageFiles, type MessageFile } from "./kilo-provider/message-files"
|
||||
import { renameSession } from "./kilo-provider/rename-session"
|
||||
import { handleFileSearch } from "./kilo-provider/file-search"
|
||||
import { watchFontSizeConfig } from "./kilo-provider/font-size"
|
||||
import { getTerminalContents } from "./services/terminal/context"
|
||||
@@ -831,8 +837,8 @@ export class KiloProvider implements vscode.WebviewViewProvider, TelemetryProper
|
||||
console.error("[Kilo New] removeSkill failed:", e),
|
||||
)
|
||||
break
|
||||
case "removeMode":
|
||||
this.handleRemoveMode(message.name).catch((e) => console.error("[Kilo New] handleRemoveMode failed:", e))
|
||||
case "removeAgent":
|
||||
this.handleRemoveAgent(message.name).catch((e) => console.error("[Kilo New] handleRemoveAgent failed:", e))
|
||||
break
|
||||
case "removeMcp":
|
||||
this.handleRemoveMcp(message.name).catch((e) => console.error("[Kilo New] handleRemoveMcp failed:", e))
|
||||
@@ -1128,6 +1134,10 @@ export class KiloProvider implements vscode.WebviewViewProvider, TelemetryProper
|
||||
})
|
||||
break
|
||||
}
|
||||
case "dismissAgentMigrationBanner": {
|
||||
await this.extensionContext?.globalState.update("kilo.agentMigrationBannerDismissed", true)
|
||||
break
|
||||
}
|
||||
}
|
||||
})
|
||||
this.webviewMessageDisposable = watchFontSizeConfig((msg) => this.postMessage(msg), this.webviewMessageDisposable)
|
||||
@@ -1150,7 +1160,8 @@ export class KiloProvider implements vscode.WebviewViewProvider, TelemetryProper
|
||||
const mp = this.getMarketplace()
|
||||
const skills = await this.fetchCliSkills()
|
||||
const data = await mp.fetchData(workspace, skills)
|
||||
this.postMessage({ type: "marketplaceData", ...data })
|
||||
const dismissed = this.extensionContext?.globalState.get<boolean>("kilo.agentMigrationBannerDismissed") ?? false
|
||||
this.postMessage({ type: "marketplaceData", ...data, showAgentMigrationBanner: !dismissed })
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1659,27 +1670,18 @@ export class KiloProvider implements vscode.WebviewViewProvider, TelemetryProper
|
||||
* Handle renaming a session.
|
||||
*/
|
||||
private async handleRenameSession(sessionID: string, title: string): Promise<void> {
|
||||
if (!this.client) {
|
||||
this.postMessage({ type: "error", message: "Not connected to CLI backend" })
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
const workspaceDir = this.getWorkspaceDirectory(sessionID)
|
||||
const { data: updated } = await this.client.session.update(
|
||||
{ sessionID, directory: workspaceDir, title },
|
||||
{ throwOnError: true },
|
||||
)
|
||||
if (this.currentSession?.id === sessionID) {
|
||||
this.setCurrentSession(updated)
|
||||
}
|
||||
const updated = await renameSession({
|
||||
client: this.client,
|
||||
sessionID,
|
||||
title,
|
||||
directory: this.getWorkspaceDirectory(sessionID),
|
||||
})
|
||||
if (this.currentSession?.id === sessionID) this.setCurrentSession(updated)
|
||||
this.postMessage({ type: "sessionUpdated", session: this.sessionToWebview(updated) })
|
||||
} catch (error) {
|
||||
console.error("[Kilo New] KiloProvider: Failed to rename session:", error)
|
||||
this.postMessage({
|
||||
type: "error",
|
||||
message: getErrorMessage(error) || "Failed to rename session",
|
||||
})
|
||||
this.postMessage({ type: "error", message: getErrorMessage(error) || "Failed to rename session" })
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1953,32 +1955,28 @@ export class KiloProvider implements vscode.WebviewViewProvider, TelemetryProper
|
||||
return true
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a custom mode via the CLI backend (deletes from disk + refreshes state).
|
||||
* The webview optimistically removes the mode from its list before this runs.
|
||||
* On failure, re-fetches agents so the webview reverts to the authoritative state.
|
||||
*/
|
||||
private async handleRemoveMode(name: string): Promise<void> {
|
||||
/** Remove an agent via CLI, falling back to kilo.json removal. */
|
||||
private async handleRemoveAgent(name: string): Promise<void> {
|
||||
if (!this.client) return
|
||||
|
||||
// 1. Try CLI removal (handles .md files and legacy .kilocodemodes)
|
||||
try {
|
||||
const dir = this.getWorkspaceDirectory()
|
||||
const result = await this.client.kilocode.removeAgent({ name, directory: dir })
|
||||
const result = await this.client.kilocode.removeAgent({ name, directory: this.getWorkspaceDirectory() })
|
||||
if (!result.error) {
|
||||
this.cachedAgentsMessage = null
|
||||
await this.fetchAndSendAgents()
|
||||
return
|
||||
}
|
||||
} catch {
|
||||
// CLI removal failed — agent may be in kilo.json instead
|
||||
// fall through to kilo.json removal
|
||||
}
|
||||
|
||||
// 2. Try removing from kilo.json (handles marketplace-installed modes)
|
||||
const stub = { id: name, type: "mode" as const, name, description: "", content: "" }
|
||||
const removed = await this.removeMarketplaceItemFromAllScopes(stub)
|
||||
if (!removed) {
|
||||
console.error("[Kilo New] KiloProvider: Failed to remove mode:", name)
|
||||
const stub: AgentMarketplaceItem = {
|
||||
id: name,
|
||||
type: "agent",
|
||||
name,
|
||||
description: "",
|
||||
content: { mode: "primary", description: "", prompt: "" },
|
||||
}
|
||||
if (!(await this.removeMarketplaceItemFromAllScopes(stub))) {
|
||||
console.error("[Kilo New] KiloProvider: Failed to remove agent:", name)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3038,7 +3036,11 @@ export class KiloProvider implements vscode.WebviewViewProvider, TelemetryProper
|
||||
const { section, leaf } = buildSettingPath(key)
|
||||
if (section === "autocomplete" && !validAutocompleteSetting(leaf, value)) return
|
||||
const config = vscode.workspace.getConfiguration(`kilo-code.new${section ? `.${section}` : ""}`)
|
||||
await config.update(leaf, value, vscode.ConfigurationTarget.Global)
|
||||
// Normalize a webview-side clear to `undefined` so VS Code removes the
|
||||
// key from settings.json rather than persisting a literal `null`. This
|
||||
// lets the runtime fall back to the resolved default.
|
||||
const next = value === null ? undefined : value
|
||||
await config.update(leaf, next, vscode.ConfigurationTarget.Global)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -3074,6 +3076,7 @@ export class KiloProvider implements vscode.WebviewViewProvider, TelemetryProper
|
||||
await this.extensionContext?.globalState.update("variantSelections", undefined)
|
||||
await this.extensionContext?.globalState.update("recentModels", undefined)
|
||||
await this.extensionContext?.globalState.update("kilo.dismissedNotificationIds", undefined)
|
||||
await this.extensionContext?.globalState.update("kilo.agentMigrationBannerDismissed", undefined)
|
||||
|
||||
// Re-send all settings to the webview so the UI reflects the reset
|
||||
this.postMessage(buildAutocompleteSettingsMessage())
|
||||
|
||||
@@ -487,7 +487,7 @@ export function activate(context: vscode.ExtensionContext) {
|
||||
)
|
||||
|
||||
// Register autocomplete provider
|
||||
registerAutocompleteProvider(context, connectionService)
|
||||
void registerAutocompleteProvider(context, connectionService)
|
||||
|
||||
// Register commit message generation
|
||||
registerCommitMessageService(context, connectionService)
|
||||
|
||||
@@ -388,6 +388,7 @@ export type WebviewMessage =
|
||||
message: Record<string, unknown>
|
||||
}
|
||||
| { type: "sessionStatus"; sessionID: string; status: string; attempt?: number; message?: string; next?: number }
|
||||
| { type: "sessionTurnClosed"; sessionID: string; reason: "completed" | "error" | "interrupted" }
|
||||
| {
|
||||
type: "permissionRequest"
|
||||
permission: {
|
||||
@@ -509,6 +510,12 @@ export function mapSSEEventToWebviewMessage(event: Event, sessionID: string | un
|
||||
...extra,
|
||||
}
|
||||
}
|
||||
case "session.turn.close":
|
||||
return {
|
||||
type: "sessionTurnClosed",
|
||||
sessionID: event.properties.sessionID,
|
||||
reason: event.properties.reason,
|
||||
}
|
||||
case "permission.asked":
|
||||
return {
|
||||
type: "permissionRequest",
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
import type { KiloClient, Session } from "@kilocode/sdk/v2/client"
|
||||
import { parseSessionTitle } from "../shared/session-title"
|
||||
|
||||
export async function renameSession(input: {
|
||||
client: KiloClient | null
|
||||
sessionID: string
|
||||
title: unknown
|
||||
directory: string
|
||||
}): Promise<Session> {
|
||||
if (!input.client) throw new Error("Not connected to CLI backend")
|
||||
const result = parseSessionTitle(input.title)
|
||||
if ("error" in result) throw new Error("Invalid session title")
|
||||
const { data } = await input.client.session.update(
|
||||
{ sessionID: input.sessionID, directory: input.directory, title: result.value },
|
||||
{ throwOnError: true },
|
||||
)
|
||||
return data
|
||||
}
|
||||
@@ -33,45 +33,31 @@ describe("autocomplete settings", () => {
|
||||
expect(buildAutocompleteSettingsMessage().settings.model).toBe("mercury-edit-2")
|
||||
})
|
||||
|
||||
it("does not infer direct provider from a bare model name when provider is unset", async () => {
|
||||
// Safety: a legacy `model` setting alone must never silently route to a
|
||||
// direct BYOK provider. Direct providers require an explicit `provider`.
|
||||
it("passes a bare model setting through unchanged so the webview can render it as-is", async () => {
|
||||
// The webview now distinguishes "no explicit setting" (null) from "user
|
||||
// picked something." We don't try to interpret a bare `model` here —
|
||||
// resolving it to a default happens at the runtime layer, not in the
|
||||
// settings message.
|
||||
state.set("model", "mercury-edit-2")
|
||||
const { buildAutocompleteSettingsMessage } = await import("../settings")
|
||||
|
||||
expect(buildAutocompleteSettingsMessage().settings.provider).toBe("kilo")
|
||||
expect(buildAutocompleteSettingsMessage().settings.model).toBe("mistralai/codestral-2508")
|
||||
expect(buildAutocompleteSettingsMessage().settings.provider).toBeNull()
|
||||
expect(buildAutocompleteSettingsMessage().settings.model).toBe("mercury-edit-2")
|
||||
})
|
||||
|
||||
it("defaults to codestral when no model is set", async () => {
|
||||
it("returns null for both keys when nothing is set (let the webview render 'Not set')", async () => {
|
||||
const { buildAutocompleteSettingsMessage } = await import("../settings")
|
||||
|
||||
expect(buildAutocompleteSettingsMessage().settings.provider).toBe("kilo")
|
||||
expect(buildAutocompleteSettingsMessage().settings.model).toBe("mistralai/codestral-2508")
|
||||
expect(buildAutocompleteSettingsMessage().settings.provider).toBeNull()
|
||||
expect(buildAutocompleteSettingsMessage().settings.model).toBeNull()
|
||||
})
|
||||
|
||||
it("defaults to codestral when stored model is no longer supported", async () => {
|
||||
it("preserves an unsupported stored model verbatim — runtime fallback handles resolution", async () => {
|
||||
state.set("model", "some/removed-model")
|
||||
const { buildAutocompleteSettingsMessage } = await import("../settings")
|
||||
|
||||
expect(buildAutocompleteSettingsMessage().settings.provider).toBe("kilo")
|
||||
expect(buildAutocompleteSettingsMessage().settings.model).toBe("mistralai/codestral-2508")
|
||||
})
|
||||
|
||||
it("maps legacy inception/mercury-edit to Kilo Gateway Mercury", async () => {
|
||||
state.set("model", "inception/mercury-edit")
|
||||
const { buildAutocompleteSettingsMessage } = await import("../settings")
|
||||
|
||||
expect(buildAutocompleteSettingsMessage().settings.provider).toBe("kilo")
|
||||
expect(buildAutocompleteSettingsMessage().settings.model).toBe("inception/mercury-edit-2")
|
||||
})
|
||||
|
||||
it("maps legacy inception/mercury-edit-2 to Kilo Gateway Mercury", async () => {
|
||||
state.set("model", "inception/mercury-edit-2")
|
||||
const { buildAutocompleteSettingsMessage } = await import("../settings")
|
||||
|
||||
expect(buildAutocompleteSettingsMessage().settings.provider).toBe("kilo")
|
||||
expect(buildAutocompleteSettingsMessage().settings.model).toBe("inception/mercury-edit-2")
|
||||
expect(buildAutocompleteSettingsMessage().settings.provider).toBeNull()
|
||||
expect(buildAutocompleteSettingsMessage().settings.model).toBe("some/removed-model")
|
||||
})
|
||||
|
||||
it("validates supported model updates", async () => {
|
||||
@@ -81,12 +67,20 @@ describe("autocomplete settings", () => {
|
||||
expect(validAutocompleteSetting("provider", "inception")).toBe(true)
|
||||
})
|
||||
|
||||
it("accepts null/undefined for provider and model so users can clear the setting", async () => {
|
||||
const { validAutocompleteSetting } = await import("../settings")
|
||||
|
||||
expect(validAutocompleteSetting("provider", null)).toBe(true)
|
||||
expect(validAutocompleteSetting("provider", undefined)).toBe(true)
|
||||
expect(validAutocompleteSetting("model", null)).toBe(true)
|
||||
expect(validAutocompleteSetting("model", undefined)).toBe(true)
|
||||
})
|
||||
|
||||
it("rejects unsupported autocomplete updates", async () => {
|
||||
const { validAutocompleteSetting } = await import("../settings")
|
||||
|
||||
expect(validAutocompleteSetting("model", "other/model")).toBe(false)
|
||||
expect(validAutocompleteSetting("provider", undefined)).toBe(false)
|
||||
expect(validAutocompleteSetting("provider", null)).toBe(false)
|
||||
expect(validAutocompleteSetting("provider", "openrouter")).toBe(false)
|
||||
})
|
||||
|
||||
it("rejects non-boolean toggle updates", async () => {
|
||||
|
||||
@@ -1,15 +1,22 @@
|
||||
import * as vscode from "vscode"
|
||||
import { AutocompleteServiceManager } from "./AutocompleteServiceManager"
|
||||
import { ensureBackendForAutocomplete } from "./ensure-backend"
|
||||
import { migrateDefaultAutocompleteSettings } from "./migrate-default"
|
||||
import { nesLog } from "./next-edit/log"
|
||||
import { INLINE_COMPLETION_ACCEPTED_COMMAND as NEXT_EDIT_ACCEPTED_COMMAND } from "./next-edit/NextEditInlineCompletionProvider"
|
||||
import { chainNextPrediction } from "./next-edit/NextEditSuggestionManager"
|
||||
import type { KiloConnectionService } from "../cli-backend"
|
||||
|
||||
export const registerAutocompleteProvider = (
|
||||
export const registerAutocompleteProvider = async (
|
||||
context: vscode.ExtensionContext,
|
||||
connectionService: KiloConnectionService,
|
||||
) => {
|
||||
// Run before constructing the manager so its initial readSettings() sees
|
||||
// the cleared state and behaves as "Not set." Awaited because the manager's
|
||||
// constructor synchronously kicks off readSettings() via load(), which would
|
||||
// otherwise race with the migration.
|
||||
await migrateDefaultAutocompleteSettings(context)
|
||||
|
||||
const autocompleteManager = new AutocompleteServiceManager(context, connectionService)
|
||||
context.subscriptions.push(autocompleteManager)
|
||||
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
import * as vscode from "vscode"
|
||||
import { DEFAULT_AUTOCOMPLETE_MODEL } from "../../shared/autocomplete-models"
|
||||
|
||||
const FLAG = "kilo.autocomplete.defaultClearMigrationV1"
|
||||
|
||||
/**
|
||||
* One-time migration: clear `kilo-code.new.autocomplete.{provider,model}` when
|
||||
* they exactly match the current `DEFAULT_AUTOCOMPLETE_MODEL`. Many users have
|
||||
* the default explicitly stored only because it was the only thing visible in
|
||||
* the dropdown — leaving it pinned would block them from picking up future
|
||||
* default changes (e.g. a switch to Mercury Next Edit) silently. After the
|
||||
* migration runs they show up as "Not set" and follow the resolved default.
|
||||
*
|
||||
* Users who picked a different model are untouched. The migration runs once
|
||||
* per machine and is gated on a globalState flag.
|
||||
*
|
||||
* TODO(2026-09): remove this migration. By September 2026 the cohort that
|
||||
* needed it will either have migrated already or be fine staying pinned.
|
||||
*/
|
||||
export async function migrateDefaultAutocompleteSettings(context: vscode.ExtensionContext): Promise<void> {
|
||||
if (context.globalState.get<boolean>(FLAG)) return
|
||||
|
||||
const config = vscode.workspace.getConfiguration("kilo-code.new.autocomplete")
|
||||
// Read the user/global scope specifically. `get()` returns the merged
|
||||
// effective value (workspace > global > default), which would let a
|
||||
// workspace-level pin or the schema default falsely look like a stored
|
||||
// global default and cause us to no-op while still flipping the flag.
|
||||
const provider = config.inspect<string>("provider")?.globalValue
|
||||
const model = config.inspect<string>("model")?.globalValue
|
||||
|
||||
const matchesDefault =
|
||||
provider === DEFAULT_AUTOCOMPLETE_MODEL.providerID && model === DEFAULT_AUTOCOMPLETE_MODEL.modelID
|
||||
|
||||
if (matchesDefault) {
|
||||
await config.update("provider", undefined, vscode.ConfigurationTarget.Global)
|
||||
await config.update("model", undefined, vscode.ConfigurationTarget.Global)
|
||||
}
|
||||
|
||||
await context.globalState.update(FLAG, true)
|
||||
}
|
||||
@@ -1,9 +1,5 @@
|
||||
import * as vscode from "vscode"
|
||||
import {
|
||||
getAutocompleteModel,
|
||||
validAutocompleteModel,
|
||||
validAutocompleteProvider,
|
||||
} from "../../shared/autocomplete-models"
|
||||
import { validAutocompleteModel, validAutocompleteProvider } from "../../shared/autocomplete-models"
|
||||
|
||||
type Message = {
|
||||
type: string
|
||||
@@ -22,15 +18,17 @@ export async function routeAutocompleteMessage(message: Message, post: Post): Pr
|
||||
|
||||
export function buildAutocompleteSettingsMessage() {
|
||||
const config = vscode.workspace.getConfiguration("kilo-code.new.autocomplete")
|
||||
const info = getAutocompleteModel(config.get<string>("provider"), config.get<string>("model"))
|
||||
// Pass through provider/model as-is (null when unset) so the webview can
|
||||
// distinguish "user hasn't picked" from "user picked the current default."
|
||||
// The runtime resolves null → DEFAULT_AUTOCOMPLETE_MODEL via getAutocompleteModel().
|
||||
return {
|
||||
type: "autocompleteSettingsLoaded" as const,
|
||||
settings: {
|
||||
enableAutoTrigger: config.get<boolean>("enableAutoTrigger", true),
|
||||
enableSmartInlineTaskKeybinding: config.get<boolean>("enableSmartInlineTaskKeybinding", false),
|
||||
enableChatAutocomplete: config.get<boolean>("enableChatAutocomplete", false),
|
||||
provider: info.providerID,
|
||||
model: info.modelID,
|
||||
provider: config.get<string>("provider") ?? null,
|
||||
model: config.get<string>("model") ?? null,
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -46,10 +44,13 @@ export function watchAutocompleteConfig(post: Post): vscode.Disposable {
|
||||
|
||||
export function validAutocompleteSetting(key: string, value: unknown) {
|
||||
if (key === "model") {
|
||||
// Allow clearing back to the server-side default.
|
||||
if (value === null || value === undefined) return true
|
||||
return validAutocompleteModel(value)
|
||||
}
|
||||
|
||||
if (key === "provider") {
|
||||
if (value === null || value === undefined) return true
|
||||
return validAutocompleteProvider(value)
|
||||
}
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@ export function resolveEventSessionId(
|
||||
case "session.updated":
|
||||
return event.properties.info.id
|
||||
case "session.status":
|
||||
case "session.turn.close":
|
||||
case "session.idle":
|
||||
case "session.error":
|
||||
case "todo.updated":
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { parse as parseYaml } from "yaml"
|
||||
import type { MarketplaceItem, McpMarketplaceItem, ModeMarketplaceItem, SkillMarketplaceItem, RawSkill } from "./types"
|
||||
import type { MarketplaceItem, McpMarketplaceItem, AgentMarketplaceItem, SkillMarketplaceItem, RawSkill } from "./types"
|
||||
|
||||
const BASE_URL = "https://api.kilo.ai/api/marketplace"
|
||||
const CACHE_TTL = 300_000
|
||||
@@ -76,18 +76,6 @@ export class MarketplaceApiClient {
|
||||
this.cache.set(key, { data, timestamp: Date.now() })
|
||||
}
|
||||
|
||||
private async fetchModes(): Promise<ModeMarketplaceItem[]> {
|
||||
const cached = this.getCached("modes")
|
||||
if (cached) return cached as ModeMarketplaceItem[]
|
||||
|
||||
const text = await fetchWithRetry(`${BASE_URL}/modes`)
|
||||
const parsed = parseResponse(text) as { items?: unknown[] }
|
||||
const items = (parsed.items ?? []) as Array<Record<string, unknown>>
|
||||
const result = items.map((item) => ({ ...item, type: "mode" as const }) as ModeMarketplaceItem)
|
||||
this.setCache("modes", result)
|
||||
return result
|
||||
}
|
||||
|
||||
private async fetchMcps(): Promise<McpMarketplaceItem[]> {
|
||||
const cached = this.getCached("mcps")
|
||||
if (cached) return cached as McpMarketplaceItem[]
|
||||
@@ -100,6 +88,18 @@ export class MarketplaceApiClient {
|
||||
return result
|
||||
}
|
||||
|
||||
private async fetchAgents(): Promise<AgentMarketplaceItem[]> {
|
||||
const cached = this.getCached("agents")
|
||||
if (cached) return cached as AgentMarketplaceItem[]
|
||||
|
||||
const text = await fetchWithRetry(`${BASE_URL}/agents`)
|
||||
const parsed = parseResponse(text) as { items?: unknown[] }
|
||||
const items = (parsed.items ?? []) as Array<Record<string, unknown>>
|
||||
const result = items.map((item) => ({ ...item, type: "agent" as const }) as AgentMarketplaceItem)
|
||||
this.setCache("agents", result)
|
||||
return result
|
||||
}
|
||||
|
||||
private async fetchSkills(): Promise<SkillMarketplaceItem[]> {
|
||||
const cached = this.getCached("skills")
|
||||
if (cached) return cached as SkillMarketplaceItem[]
|
||||
@@ -116,9 +116,9 @@ export class MarketplaceApiClient {
|
||||
const errors: string[] = []
|
||||
|
||||
const settled = await Promise.all([
|
||||
this.fetchModes().catch((err: unknown) => {
|
||||
errors.push(`Failed to fetch modes: ${err instanceof Error ? err.message : String(err)}`)
|
||||
return [] as ModeMarketplaceItem[]
|
||||
this.fetchAgents().catch((err: unknown) => {
|
||||
errors.push(`Failed to fetch agents: ${err instanceof Error ? err.message : String(err)}`)
|
||||
return [] as AgentMarketplaceItem[]
|
||||
}),
|
||||
this.fetchMcps().catch((err: unknown) => {
|
||||
errors.push(`Failed to fetch mcps: ${err instanceof Error ? err.message : String(err)}`)
|
||||
|
||||
@@ -16,6 +16,7 @@ export class InstallationDetector {
|
||||
/**
|
||||
* Detect installed marketplace items.
|
||||
*
|
||||
* Agents are detected from .kilo/agents/*.md files.
|
||||
* MCP servers and modes are detected from kilo.json config files.
|
||||
* Skills come from the CLI backend (via GET /skill), which is the
|
||||
* authoritative source — it scans all skill directories.
|
||||
@@ -23,12 +24,14 @@ export class InstallationDetector {
|
||||
async detect(workspace?: string, skills?: CliSkill[]): Promise<MarketplaceInstalledMetadata> {
|
||||
const project = workspace
|
||||
? Object.fromEntries([
|
||||
...(await this.detectAgentFiles("project", workspace)),
|
||||
...(await this.detectFromConfig(this.paths.configPath("project", workspace))),
|
||||
...this.skillEntries(skills, workspace, true),
|
||||
])
|
||||
: {}
|
||||
|
||||
const global = Object.fromEntries([
|
||||
...(await this.detectAgentFiles("global")),
|
||||
...(await this.detectFromConfig(this.paths.configPath("global"))),
|
||||
...this.skillEntries(skills, workspace, false),
|
||||
])
|
||||
@@ -52,6 +55,20 @@ export class InstallationDetector {
|
||||
.map((s) => [s.name, { type: "skill" }])
|
||||
}
|
||||
|
||||
/** Scan .kilo/agents/*.md files to detect installed marketplace agents. */
|
||||
private async detectAgentFiles(scope: "project" | "global", workspace?: string): Promise<Entry[]> {
|
||||
const dir = this.paths.agentsDir(scope, workspace)
|
||||
try {
|
||||
const files = await fs.readdir(dir)
|
||||
return files.filter((f) => f.endsWith(".md")).map((f) => [path.basename(f, ".md"), { type: "agent" }] as Entry)
|
||||
} catch (err) {
|
||||
if ((err as NodeJS.ErrnoException).code !== "ENOENT") {
|
||||
console.warn(`Failed to detect agent files from ${dir}:`, err)
|
||||
}
|
||||
return []
|
||||
}
|
||||
}
|
||||
|
||||
/** Read mcp and agent entries from a kilo.json config file. */
|
||||
private async detectFromConfig(filepath: string): Promise<Entry[]> {
|
||||
try {
|
||||
@@ -67,7 +84,7 @@ export class InstallationDetector {
|
||||
|
||||
if (parsed?.agent && typeof parsed.agent === "object") {
|
||||
for (const key of Object.keys(parsed.agent)) {
|
||||
entries.push([key, { type: "mode" }])
|
||||
entries.push([key, { type: "agent" }])
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -65,6 +65,7 @@ export class MarketplaceService {
|
||||
|
||||
export type {
|
||||
MarketplaceItem,
|
||||
AgentMarketplaceItem,
|
||||
InstallMarketplaceItemOptions,
|
||||
MarketplaceDataResponse,
|
||||
InstallResult,
|
||||
|
||||
@@ -7,7 +7,7 @@ import type {
|
||||
MarketplaceItem,
|
||||
SkillMarketplaceItem,
|
||||
McpMarketplaceItem,
|
||||
ModeMarketplaceItem,
|
||||
AgentMarketplaceItem,
|
||||
McpInstallationMethod,
|
||||
InstallMarketplaceItemOptions,
|
||||
InstallResult,
|
||||
@@ -26,7 +26,7 @@ export class MarketplaceInstaller {
|
||||
const scope = options.target ?? "project"
|
||||
if (item.type === "skill") return this.installSkill(item, scope, workspace)
|
||||
if (item.type === "mcp") return this.installMcp(item, options, scope, workspace)
|
||||
return this.installMode(item, scope, workspace)
|
||||
return this.installAgent(item, scope, workspace)
|
||||
}
|
||||
|
||||
// ── MCP ─────────────────────────────────────────────────────────────
|
||||
@@ -81,10 +81,10 @@ export class MarketplaceInstaller {
|
||||
return normalizeMcpEntry(raw)
|
||||
}
|
||||
|
||||
// ── Mode ────────────────────────────────────────────────────────────
|
||||
// ── Agent ───────────────────────────────────────────────────────────
|
||||
|
||||
async installMode(
|
||||
item: ModeMarketplaceItem,
|
||||
async installAgent(
|
||||
item: AgentMarketplaceItem,
|
||||
scope: "project" | "global",
|
||||
workspace?: string,
|
||||
): Promise<InstallResult> {
|
||||
@@ -92,16 +92,72 @@ export class MarketplaceInstaller {
|
||||
return { success: false, slug: item.id, error: "No workspace directory for project-scope install" }
|
||||
}
|
||||
|
||||
const config = await this.readConfig(scope, workspace)
|
||||
if (!config.agent) config.agent = {}
|
||||
|
||||
if (config.agent[item.id]) {
|
||||
return { success: false, slug: item.id, error: "Mode already installed. Remove it first." }
|
||||
if (!isSafeId(item.id)) {
|
||||
return { success: false, slug: item.id, error: "Invalid agent id" }
|
||||
}
|
||||
|
||||
config.agent[item.id] = convertModeToAgent(item.content)
|
||||
const dir = this.paths.agentsDir(scope, workspace)
|
||||
await fs.mkdir(dir, { recursive: true })
|
||||
|
||||
const filepath = path.join(dir, `${item.id}.md`)
|
||||
if (!path.resolve(filepath).startsWith(path.resolve(dir))) {
|
||||
return { success: false, slug: item.id, error: "Invalid agent id" }
|
||||
}
|
||||
|
||||
try {
|
||||
await fs.access(filepath)
|
||||
return { success: false, slug: item.id, error: "Agent already installed. Remove it first." }
|
||||
} catch (err) {
|
||||
if ((err as NodeJS.ErrnoException).code !== "ENOENT") throw err
|
||||
}
|
||||
|
||||
const { prompt, ...front } = item.content
|
||||
const frontmatter = yaml.stringify(front).trimEnd()
|
||||
const content = `---\n${frontmatter}\n---\n\n${prompt}\n`
|
||||
await fs.writeFile(filepath, content, "utf-8")
|
||||
|
||||
// Migration: remove stale kilo.json agent entry with same id if present
|
||||
const config = await this.readConfig(scope, workspace)
|
||||
if (config.agent?.[item.id]) {
|
||||
delete (config.agent as Record<string, unknown>)[item.id]
|
||||
if (Object.keys(config.agent as object).length === 0) delete config.agent
|
||||
await this.writeConfig(scope, workspace, config)
|
||||
}
|
||||
|
||||
return { success: true, slug: item.id, filePath: filepath, line: 1 }
|
||||
}
|
||||
|
||||
async removeAgent(
|
||||
item: AgentMarketplaceItem,
|
||||
scope: "project" | "global",
|
||||
workspace?: string,
|
||||
): Promise<RemoveResult> {
|
||||
if (!isSafeId(item.id)) {
|
||||
return { success: false, slug: item.id, error: "Invalid agent id" }
|
||||
}
|
||||
|
||||
const dir = this.paths.agentsDir(scope, workspace)
|
||||
const filepath = path.join(dir, `${item.id}.md`)
|
||||
if (!path.resolve(filepath).startsWith(path.resolve(dir))) {
|
||||
return { success: false, slug: item.id, error: "Invalid agent id" }
|
||||
}
|
||||
|
||||
try {
|
||||
await fs.unlink(filepath)
|
||||
} catch (err) {
|
||||
if ((err as NodeJS.ErrnoException).code !== "ENOENT") {
|
||||
return { success: false, slug: item.id, error: String(err) }
|
||||
}
|
||||
}
|
||||
|
||||
// Also clean up any stale kilo.json agent entry
|
||||
const config = await this.readConfig(scope, workspace)
|
||||
if (config.agent?.[item.id]) {
|
||||
delete (config.agent as Record<string, unknown>)[item.id]
|
||||
if (Object.keys(config.agent as object).length === 0) delete config.agent
|
||||
await this.writeConfig(scope, workspace, config)
|
||||
}
|
||||
|
||||
await this.writeConfig(scope, workspace, config)
|
||||
return { success: true, slug: item.id }
|
||||
}
|
||||
|
||||
@@ -191,7 +247,7 @@ export class MarketplaceInstaller {
|
||||
async remove(item: MarketplaceItem, scope: "project" | "global", workspace?: string): Promise<RemoveResult> {
|
||||
if (item.type === "skill") return this.removeSkill(item, scope, workspace)
|
||||
if (item.type === "mcp") return this.removeMcp(item, scope, workspace)
|
||||
return this.removeMode(item, scope, workspace)
|
||||
return this.removeAgent(item, scope, workspace)
|
||||
}
|
||||
|
||||
async removeMcp(item: McpMarketplaceItem, scope: "project" | "global", workspace?: string): Promise<RemoveResult> {
|
||||
@@ -205,17 +261,6 @@ export class MarketplaceInstaller {
|
||||
return { success: true, slug: item.id }
|
||||
}
|
||||
|
||||
async removeMode(item: ModeMarketplaceItem, scope: "project" | "global", workspace?: string): Promise<RemoveResult> {
|
||||
const config = await this.readConfig(scope, workspace)
|
||||
if (!config.agent?.[item.id]) {
|
||||
return { success: true, slug: item.id }
|
||||
}
|
||||
delete config.agent[item.id]
|
||||
if (Object.keys(config.agent).length === 0) delete config.agent
|
||||
await this.writeConfig(scope, workspace, config)
|
||||
return { success: true, slug: item.id }
|
||||
}
|
||||
|
||||
async removeSkill(
|
||||
item: SkillMarketplaceItem,
|
||||
scope: "project" | "global",
|
||||
@@ -318,47 +363,6 @@ function isSafeId(id: string): boolean {
|
||||
return /^[\w\-@.]+$/.test(id)
|
||||
}
|
||||
|
||||
// Group name → opencode permission key mapping (mirrors ModesMigrator)
|
||||
const GROUP_PERMISSIONS: Record<string, string> = {
|
||||
read: "read",
|
||||
edit: "edit",
|
||||
browser: "bash",
|
||||
command: "bash",
|
||||
mcp: "mcp",
|
||||
}
|
||||
const ALL_PERMISSIONS = ["read", "edit", "bash", "mcp"]
|
||||
|
||||
function convertModeToAgent(content: string): Record<string, unknown> {
|
||||
const mode = yaml.parse(content) as Record<string, unknown>
|
||||
const groups = (mode.groups ?? []) as Array<string | [string, Record<string, unknown>]>
|
||||
|
||||
const permission: Record<string, unknown> = {}
|
||||
const allowed = new Set<string>()
|
||||
for (const group of groups) {
|
||||
if (typeof group === "string") {
|
||||
const key = GROUP_PERMISSIONS[group] ?? group
|
||||
allowed.add(key)
|
||||
permission[key] = "allow"
|
||||
} else if (Array.isArray(group)) {
|
||||
const [name, cfg] = group
|
||||
const key = GROUP_PERMISSIONS[name] ?? name
|
||||
allowed.add(key)
|
||||
permission[key] = cfg?.fileRegex ? { [String(cfg.fileRegex)]: "allow", "*": "deny" } : "allow"
|
||||
}
|
||||
}
|
||||
for (const perm of ALL_PERMISSIONS) {
|
||||
if (!allowed.has(perm)) permission[perm] = "deny"
|
||||
}
|
||||
|
||||
const prompt = [mode.roleDefinition, mode.customInstructions].filter(Boolean).join("\n\n")
|
||||
return {
|
||||
mode: "primary",
|
||||
description: mode.description ?? mode.whenToUse ?? mode.name,
|
||||
prompt,
|
||||
permission,
|
||||
}
|
||||
}
|
||||
|
||||
function escapeJsonValue(raw: string): string {
|
||||
return raw
|
||||
.replace(/\\/g, "\\\\")
|
||||
|
||||
@@ -17,6 +17,12 @@ export class MarketplacePaths {
|
||||
return path.join(globalConfigDir(), "kilo.json")
|
||||
}
|
||||
|
||||
/** Agent install directory (where marketplace agents are written as .md files). */
|
||||
agentsDir(scope: "project" | "global", workspace?: string): string {
|
||||
if (scope === "project") return path.join(workspace!, ".kilo", "agents")
|
||||
return path.join(globalConfigDir(), "agents")
|
||||
}
|
||||
|
||||
/** Skill install directory (where the marketplace installer writes to). */
|
||||
skillsDir(scope: "project" | "global", workspace?: string): string {
|
||||
if (scope === "project") return path.join(workspace!, ".kilo", "skills")
|
||||
|
||||
@@ -29,9 +29,17 @@ export interface McpMarketplaceItem extends MarketplaceItemBase {
|
||||
parameters?: McpParameter[]
|
||||
}
|
||||
|
||||
export interface ModeMarketplaceItem extends MarketplaceItemBase {
|
||||
type: "mode"
|
||||
content: string
|
||||
export interface AgentContent {
|
||||
mode: "primary" | "subagent" | "all"
|
||||
description: string
|
||||
prompt: string
|
||||
options?: Record<string, unknown>
|
||||
permission?: Record<string, unknown>
|
||||
}
|
||||
|
||||
export interface AgentMarketplaceItem extends MarketplaceItemBase {
|
||||
type: "agent"
|
||||
content: AgentContent
|
||||
}
|
||||
|
||||
export interface RawSkill {
|
||||
@@ -51,7 +59,7 @@ export interface SkillMarketplaceItem extends MarketplaceItemBase {
|
||||
displayCategory: string
|
||||
}
|
||||
|
||||
export type MarketplaceItem = McpMarketplaceItem | ModeMarketplaceItem | SkillMarketplaceItem
|
||||
export type MarketplaceItem = McpMarketplaceItem | AgentMarketplaceItem | SkillMarketplaceItem
|
||||
|
||||
export interface InstallMarketplaceItemOptions {
|
||||
target?: "global" | "project"
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
export const SESSION_TITLE_LIMIT = 200
|
||||
|
||||
// Block terminal/display controls and bidi marks that can visually spoof a title.
|
||||
const unsafe = /[\u0000-\u001f\u007f-\u009f\u061c\u200e\u200f\u2028\u2029\u202a-\u202e\u2066-\u2069]/u
|
||||
|
||||
type SessionTitleIssue = "invalid" | "required" | "too_long" | "control"
|
||||
type SessionTitleResult = { value: string } | { error: SessionTitleIssue }
|
||||
|
||||
export function parseSessionTitle(raw: unknown): SessionTitleResult {
|
||||
if (typeof raw !== "string") return { error: "invalid" }
|
||||
const value = raw.trim()
|
||||
if (!value) return { error: "required" }
|
||||
if (value.length > SESSION_TITLE_LIMIT) return { error: "too_long" }
|
||||
if (unsafe.test(value)) return { error: "control" }
|
||||
return { value }
|
||||
}
|
||||
@@ -0,0 +1,157 @@
|
||||
import { describe, it, expect, afterEach, beforeEach } from "bun:test"
|
||||
import * as vscode from "vscode"
|
||||
import { migrateDefaultAutocompleteSettings } from "../../src/services/autocomplete/migrate-default"
|
||||
import { DEFAULT_AUTOCOMPLETE_MODEL } from "../../src/shared/autocomplete-models"
|
||||
|
||||
type Scoped = { globalValue?: unknown; workspaceValue?: unknown }
|
||||
type State = Map<string, Scoped>
|
||||
|
||||
type Stub = {
|
||||
getConfiguration: (section?: string) => {
|
||||
get: (key: string, fallback?: unknown) => unknown
|
||||
inspect: (key: string) => Scoped | undefined
|
||||
update: (key: string, value: unknown, target: unknown) => Promise<void>
|
||||
}
|
||||
}
|
||||
|
||||
const original = vscode.workspace.getConfiguration
|
||||
|
||||
function makeContext(initial: Record<string, unknown> = {}) {
|
||||
const flag = new Map<string, unknown>(Object.entries(initial))
|
||||
return {
|
||||
flag,
|
||||
context: {
|
||||
globalState: {
|
||||
get: <T>(key: string) => flag.get(key) as T | undefined,
|
||||
update: async (key: string, value: unknown) => {
|
||||
flag.set(key, value)
|
||||
},
|
||||
},
|
||||
} as any,
|
||||
}
|
||||
}
|
||||
|
||||
function stubConfig(state: State) {
|
||||
function entry(key: string): Scoped {
|
||||
const e = state.get(key)
|
||||
if (e) return e
|
||||
const fresh: Scoped = {}
|
||||
state.set(key, fresh)
|
||||
return fresh
|
||||
}
|
||||
;(vscode.workspace as unknown as Stub).getConfiguration = (section?: string) => {
|
||||
if (section !== "kilo-code.new.autocomplete") {
|
||||
return {
|
||||
get: () => undefined,
|
||||
inspect: () => undefined,
|
||||
update: async () => {},
|
||||
}
|
||||
}
|
||||
return {
|
||||
get: (key: string, fallback?: unknown) => {
|
||||
const e = state.get(key)
|
||||
return e?.workspaceValue ?? e?.globalValue ?? fallback
|
||||
},
|
||||
inspect: (key: string) => state.get(key) ?? {},
|
||||
update: async (key: string, value: unknown, target: unknown) => {
|
||||
// vscode.ConfigurationTarget.Global = 1, Workspace = 2
|
||||
const scope: keyof Scoped = target === 2 ? "workspaceValue" : "globalValue"
|
||||
const e = entry(key)
|
||||
if (value === undefined) delete e[scope]
|
||||
else e[scope] = value
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function setGlobal(state: State, key: string, value: unknown) {
|
||||
const e = state.get(key) ?? {}
|
||||
e.globalValue = value
|
||||
state.set(key, e)
|
||||
}
|
||||
|
||||
function setWorkspace(state: State, key: string, value: unknown) {
|
||||
const e = state.get(key) ?? {}
|
||||
e.workspaceValue = value
|
||||
state.set(key, e)
|
||||
}
|
||||
|
||||
afterEach(() => {
|
||||
;(vscode.workspace as unknown as Stub).getConfiguration = original as Stub["getConfiguration"]
|
||||
})
|
||||
|
||||
describe("migrateDefaultAutocompleteSettings", () => {
|
||||
let state: State
|
||||
|
||||
beforeEach(() => {
|
||||
state = new Map()
|
||||
stubConfig(state)
|
||||
})
|
||||
|
||||
it("clears provider/model when both equal the current default at global scope", async () => {
|
||||
setGlobal(state, "provider", DEFAULT_AUTOCOMPLETE_MODEL.providerID)
|
||||
setGlobal(state, "model", DEFAULT_AUTOCOMPLETE_MODEL.modelID)
|
||||
const { context, flag } = makeContext()
|
||||
|
||||
await migrateDefaultAutocompleteSettings(context)
|
||||
|
||||
expect(state.get("provider")?.globalValue).toBeUndefined()
|
||||
expect(state.get("model")?.globalValue).toBeUndefined()
|
||||
expect(flag.get("kilo.autocomplete.defaultClearMigrationV1")).toBe(true)
|
||||
})
|
||||
|
||||
it("leaves an explicitly chosen non-default model untouched", async () => {
|
||||
setGlobal(state, "provider", "inception")
|
||||
setGlobal(state, "model", "mercury-edit-2")
|
||||
const { context, flag } = makeContext()
|
||||
|
||||
await migrateDefaultAutocompleteSettings(context)
|
||||
|
||||
expect(state.get("provider")?.globalValue).toBe("inception")
|
||||
expect(state.get("model")?.globalValue).toBe("mercury-edit-2")
|
||||
expect(flag.get("kilo.autocomplete.defaultClearMigrationV1")).toBe(true)
|
||||
})
|
||||
|
||||
it("leaves a partial match untouched", async () => {
|
||||
setGlobal(state, "provider", DEFAULT_AUTOCOMPLETE_MODEL.providerID)
|
||||
setGlobal(state, "model", "inception/mercury-edit-2")
|
||||
const { context } = makeContext()
|
||||
|
||||
await migrateDefaultAutocompleteSettings(context)
|
||||
|
||||
expect(state.get("provider")?.globalValue).toBe(DEFAULT_AUTOCOMPLETE_MODEL.providerID)
|
||||
expect(state.get("model")?.globalValue).toBe("inception/mercury-edit-2")
|
||||
})
|
||||
|
||||
it("ignores workspace-scoped pins so they aren't mistaken for global defaults", async () => {
|
||||
setWorkspace(state, "provider", DEFAULT_AUTOCOMPLETE_MODEL.providerID)
|
||||
setWorkspace(state, "model", DEFAULT_AUTOCOMPLETE_MODEL.modelID)
|
||||
const { context } = makeContext()
|
||||
|
||||
await migrateDefaultAutocompleteSettings(context)
|
||||
|
||||
// Workspace value is intact — we only clear at global scope.
|
||||
expect(state.get("provider")?.workspaceValue).toBe(DEFAULT_AUTOCOMPLETE_MODEL.providerID)
|
||||
expect(state.get("model")?.workspaceValue).toBe(DEFAULT_AUTOCOMPLETE_MODEL.modelID)
|
||||
})
|
||||
|
||||
it("only runs once per machine", async () => {
|
||||
setGlobal(state, "provider", DEFAULT_AUTOCOMPLETE_MODEL.providerID)
|
||||
setGlobal(state, "model", DEFAULT_AUTOCOMPLETE_MODEL.modelID)
|
||||
const { context } = makeContext({ "kilo.autocomplete.defaultClearMigrationV1": true })
|
||||
|
||||
await migrateDefaultAutocompleteSettings(context)
|
||||
|
||||
// Setting was preserved — second run is a no-op.
|
||||
expect(state.get("provider")?.globalValue).toBe(DEFAULT_AUTOCOMPLETE_MODEL.providerID)
|
||||
expect(state.get("model")?.globalValue).toBe(DEFAULT_AUTOCOMPLETE_MODEL.modelID)
|
||||
})
|
||||
|
||||
it("sets the flag even when nothing needed clearing", async () => {
|
||||
const { context, flag } = makeContext()
|
||||
|
||||
await migrateDefaultAutocompleteSettings(context)
|
||||
|
||||
expect(flag.get("kilo.autocomplete.defaultClearMigrationV1")).toBe(true)
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,85 @@
|
||||
import { describe, it, expect, afterEach, beforeEach } from "bun:test"
|
||||
import * as vscode from "vscode"
|
||||
import { buildAutocompleteSettingsMessage, validAutocompleteSetting } from "../../src/services/autocomplete/settings"
|
||||
|
||||
type Stub = {
|
||||
getConfiguration: (section?: string) => {
|
||||
get: <T>(key: string, fallback?: T) => T | undefined
|
||||
update?: (key: string, value: unknown) => Promise<void>
|
||||
}
|
||||
}
|
||||
|
||||
const original = vscode.workspace.getConfiguration
|
||||
|
||||
function stubConfig(state: Map<string, unknown>) {
|
||||
;(vscode.workspace as unknown as Stub).getConfiguration = (section?: string) => {
|
||||
if (section !== "kilo-code.new.autocomplete") {
|
||||
return { get: <T>(_key: string, fallback?: T) => fallback }
|
||||
}
|
||||
return {
|
||||
get: <T>(key: string, fallback?: T) => (state.has(key) ? (state.get(key) as T) : fallback),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
afterEach(() => {
|
||||
;(vscode.workspace as unknown as Stub).getConfiguration = original as Stub["getConfiguration"]
|
||||
})
|
||||
|
||||
describe("buildAutocompleteSettingsMessage", () => {
|
||||
let state: Map<string, unknown>
|
||||
|
||||
beforeEach(() => {
|
||||
state = new Map()
|
||||
stubConfig(state)
|
||||
})
|
||||
|
||||
it("returns null for both keys when nothing is set so the webview renders 'Not set'", () => {
|
||||
const msg = buildAutocompleteSettingsMessage()
|
||||
|
||||
expect(msg.settings.provider).toBeNull()
|
||||
expect(msg.settings.model).toBeNull()
|
||||
})
|
||||
|
||||
it("passes an explicit BYOK selection through verbatim", () => {
|
||||
state.set("provider", "inception")
|
||||
state.set("model", "mercury-edit-2")
|
||||
|
||||
const msg = buildAutocompleteSettingsMessage()
|
||||
|
||||
expect(msg.settings.provider).toBe("inception")
|
||||
expect(msg.settings.model).toBe("mercury-edit-2")
|
||||
})
|
||||
|
||||
it("does not coerce a bare model setting to a default — let the webview see what was stored", () => {
|
||||
state.set("model", "mercury-edit-2")
|
||||
|
||||
const msg = buildAutocompleteSettingsMessage()
|
||||
|
||||
expect(msg.settings.provider).toBeNull()
|
||||
expect(msg.settings.model).toBe("mercury-edit-2")
|
||||
})
|
||||
})
|
||||
|
||||
describe("validAutocompleteSetting", () => {
|
||||
it("accepts null/undefined for provider and model so the user can clear back to the default", () => {
|
||||
expect(validAutocompleteSetting("provider", null)).toBe(true)
|
||||
expect(validAutocompleteSetting("provider", undefined)).toBe(true)
|
||||
expect(validAutocompleteSetting("model", null)).toBe(true)
|
||||
expect(validAutocompleteSetting("model", undefined)).toBe(true)
|
||||
})
|
||||
|
||||
it("accepts known providers and models", () => {
|
||||
expect(validAutocompleteSetting("provider", "inception")).toBe(true)
|
||||
expect(validAutocompleteSetting("model", "mercury-edit-2")).toBe(true)
|
||||
})
|
||||
|
||||
it("rejects unknown providers and models", () => {
|
||||
expect(validAutocompleteSetting("provider", "openrouter")).toBe(false)
|
||||
expect(validAutocompleteSetting("model", "gpt-5")).toBe(false)
|
||||
})
|
||||
|
||||
it("rejects non-boolean toggle updates", () => {
|
||||
expect(validAutocompleteSetting("enableAutoTrigger", "true")).toBe(false)
|
||||
})
|
||||
})
|
||||
@@ -46,6 +46,14 @@ describe("resolveEventSessionId", () => {
|
||||
expect(resolveEventSessionId(e, noLookup)).toBe("s4")
|
||||
})
|
||||
|
||||
it("returns sessionID from session.turn.close", () => {
|
||||
const e = event({
|
||||
type: "session.turn.close",
|
||||
properties: { sessionID: "s-turn", reason: "interrupted" },
|
||||
})
|
||||
expect(resolveEventSessionId(e, noLookup)).toBe("s-turn")
|
||||
})
|
||||
|
||||
it("returns sessionID from message.updated and calls onMessageUpdated", () => {
|
||||
const e = event({
|
||||
type: "message.updated",
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
import { describe, expect, it } from "bun:test"
|
||||
import { renameSession } from "../../src/kilo-provider/rename-session"
|
||||
import { SESSION_TITLE_LIMIT } from "../../src/shared/session-title"
|
||||
|
||||
type Params = { sessionID: string; directory?: string; title?: string }
|
||||
|
||||
function client() {
|
||||
const calls: Params[] = []
|
||||
return {
|
||||
calls,
|
||||
value: {
|
||||
session: {
|
||||
update: async (params: Params) => {
|
||||
calls.push(params)
|
||||
return {
|
||||
data: {
|
||||
id: params.sessionID,
|
||||
title: params.title,
|
||||
time: { created: 1, updated: 2 },
|
||||
},
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
describe("renameSession", () => {
|
||||
it("normalizes and persists a valid title through the backend client", async () => {
|
||||
const api = client()
|
||||
|
||||
const updated = await renameSession({
|
||||
client: api.value as never,
|
||||
sessionID: "ses_1",
|
||||
title: " Rename active session ",
|
||||
directory: "/repo",
|
||||
})
|
||||
|
||||
expect(api.calls).toHaveLength(1)
|
||||
expect(api.calls[0]).toEqual({ sessionID: "ses_1", directory: "/repo", title: "Rename active session" })
|
||||
expect(updated.title).toBe("Rename active session")
|
||||
})
|
||||
|
||||
it("rejects unsafe titles before they reach the backend", async () => {
|
||||
const api = client()
|
||||
const input = [" ", "a".repeat(SESSION_TITLE_LIMIT + 1), "Title\nSecond line", "Title\u202espoof"]
|
||||
|
||||
for (const title of input) {
|
||||
await expect(
|
||||
renameSession({ client: api.value as never, sessionID: "ses_1", title, directory: "/repo" }),
|
||||
).rejects.toThrow("Invalid session title")
|
||||
}
|
||||
|
||||
expect(api.calls).toEqual([])
|
||||
})
|
||||
})
|
||||
@@ -21,6 +21,7 @@ import type {
|
||||
EventMessagePartUpdated,
|
||||
EventMessageUpdated,
|
||||
EventSessionStatus,
|
||||
EventSessionTurnClose,
|
||||
EventPermissionAsked,
|
||||
EventPermissionReplied,
|
||||
EventTodoUpdated,
|
||||
@@ -309,6 +310,16 @@ describe("mapSSEEventToWebviewMessage", () => {
|
||||
}
|
||||
})
|
||||
|
||||
it("maps session.turn.close to its terminal reason", () => {
|
||||
const event: EventSessionTurnClose = {
|
||||
id: "evt-turn",
|
||||
type: "session.turn.close",
|
||||
properties: { sessionID: "sess-1", reason: "interrupted" },
|
||||
}
|
||||
const msg = mapSSEEventToWebviewMessage(event, "sess-1")
|
||||
expect(msg).toEqual({ type: "sessionTurnClosed", sessionID: "sess-1", reason: "interrupted" })
|
||||
})
|
||||
|
||||
it("maps permission.asked to permissionRequest", () => {
|
||||
const event: EventPermissionAsked = {
|
||||
type: "permission.asked",
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
import { describe, expect, it } from "bun:test"
|
||||
import { terminal } from "../../webview-ui/src/context/session-outcome"
|
||||
import type { Message, TodoItem } from "../../webview-ui/src/types/messages"
|
||||
|
||||
function message(finish?: string, error?: Message["error"]): Message {
|
||||
return {
|
||||
id: "m1",
|
||||
sessionID: "s1",
|
||||
role: "assistant",
|
||||
createdAt: new Date(0).toISOString(),
|
||||
finish,
|
||||
error,
|
||||
}
|
||||
}
|
||||
|
||||
function todo(status: TodoItem["status"]): TodoItem {
|
||||
return { id: status, content: status, status }
|
||||
}
|
||||
|
||||
describe("terminal", () => {
|
||||
it("returns no terminal state before a turn closes", () => {
|
||||
expect(terminal({ messages: [message("stop")], todos: [] })).toBeUndefined()
|
||||
})
|
||||
|
||||
it("hides normal completed turns", () => {
|
||||
expect(terminal({ reason: "completed", messages: [message("stop")], todos: [] })).toBeUndefined()
|
||||
})
|
||||
|
||||
it("warns when a completed turn leaves to-dos unfinished", () => {
|
||||
expect(
|
||||
terminal({ reason: "completed", messages: [message("stop")], todos: [todo("completed"), todo("pending")] }),
|
||||
).toEqual({ kind: "incomplete", tone: "warning", finish: "stop", remaining: 1 })
|
||||
})
|
||||
|
||||
it("treats cancelled to-dos as terminal rather than remaining work", () => {
|
||||
expect(terminal({ reason: "completed", messages: [message("stop")], todos: [todo("cancelled")] })).toBeUndefined()
|
||||
})
|
||||
|
||||
it("surfaces response limit and unknown model finishes before generic incomplete status", () => {
|
||||
expect(terminal({ reason: "completed", messages: [message("length")], todos: [todo("pending")] })?.kind).toBe(
|
||||
"limit",
|
||||
)
|
||||
expect(terminal({ reason: "completed", messages: [message("unknown")], todos: [] })?.kind).toBe("unknown")
|
||||
})
|
||||
|
||||
it("surfaces filtered and unexpected provider finishes", () => {
|
||||
expect(terminal({ reason: "completed", messages: [message("content-filter")], todos: [] })?.kind).toBe("filtered")
|
||||
expect(terminal({ reason: "completed", messages: [message("other")], todos: [] })?.kind).toBe("unexpected")
|
||||
})
|
||||
|
||||
it("surfaces interruption and failures without a rendered error", () => {
|
||||
expect(terminal({ reason: "interrupted", messages: [message("stop")], todos: [todo("pending")] })).toEqual({
|
||||
kind: "interrupted",
|
||||
tone: "warning",
|
||||
finish: "stop",
|
||||
remaining: 1,
|
||||
})
|
||||
expect(terminal({ reason: "error", messages: [message("error")], todos: [] })?.kind).toBe("error")
|
||||
})
|
||||
|
||||
it("does not duplicate a concrete rendered failure", () => {
|
||||
expect(terminal({ reason: "error", messages: [message("error", { name: "APIError" })], todos: [] })).toBeUndefined()
|
||||
})
|
||||
|
||||
it("retains a fallback failure when the concrete error is hidden", () => {
|
||||
expect(
|
||||
terminal({
|
||||
reason: "error",
|
||||
messages: [message("error", { name: "APIError" })],
|
||||
todos: [],
|
||||
hidden: () => true,
|
||||
})?.kind,
|
||||
).toBe("error")
|
||||
})
|
||||
|
||||
it("reports only the latest assistant finish reason", () => {
|
||||
const user: Message = { id: "u1", sessionID: "s1", role: "user", createdAt: new Date(1).toISOString() }
|
||||
expect(terminal({ reason: "completed", messages: [message("length"), user], todos: [] })?.finish).toBeUndefined()
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,47 @@
|
||||
import { describe, expect, it } from "bun:test"
|
||||
import { parseSessionTitle, SESSION_TITLE_LIMIT } from "../../src/shared/session-title"
|
||||
|
||||
describe("parseSessionTitle", () => {
|
||||
it("rejects non-string input from untrusted callers", () => {
|
||||
expect(parseSessionTitle(null)).toEqual({ error: "invalid" })
|
||||
})
|
||||
|
||||
it("trims a valid title", () => {
|
||||
expect(parseSessionTitle(" Review authentication flow ")).toEqual({ value: "Review authentication flow" })
|
||||
})
|
||||
|
||||
it("rejects empty titles", () => {
|
||||
expect(parseSessionTitle(" \t \n ")).toEqual({ error: "required" })
|
||||
})
|
||||
|
||||
it("accepts the display limit and rejects longer titles", () => {
|
||||
expect(parseSessionTitle("a".repeat(SESSION_TITLE_LIMIT))).toEqual({ value: "a".repeat(SESSION_TITLE_LIMIT) })
|
||||
expect(parseSessionTitle("a".repeat(SESSION_TITLE_LIMIT + 1))).toEqual({ error: "too_long" })
|
||||
})
|
||||
|
||||
it("rejects every blocked control and directional formatting range", () => {
|
||||
const values = [
|
||||
"Task\u0000suffix",
|
||||
"Task\u001bsuffix",
|
||||
"Task\u001fsuffix",
|
||||
"Task\u007fsuffix",
|
||||
"Task\u009fsuffix",
|
||||
"Task\u061csuffix",
|
||||
"Task\u200esuffix",
|
||||
"Task\u200fsuffix",
|
||||
"Task\u2028suffix",
|
||||
"Task\u2029suffix",
|
||||
"Task\u202asuffix",
|
||||
"Task\u202esuffix",
|
||||
"Task\u2066suffix",
|
||||
"Task\u2069suffix",
|
||||
]
|
||||
for (const value of values) expect(parseSessionTitle(value)).toEqual({ error: "control" })
|
||||
})
|
||||
|
||||
it("accepts normal unicode display text", () => {
|
||||
expect(parseSessionTitle("Analyse de la session - \u4fee\u6b63")).toEqual({
|
||||
value: "Analyse de la session - \u4fee\u6b63",
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -25,6 +25,7 @@ import { RevertBanner } from "./RevertBanner"
|
||||
import { AccountSwitcher } from "../shared/AccountSwitcher"
|
||||
import { KiloNotifications } from "./KiloNotifications"
|
||||
import { WorkingIndicator } from "../shared/WorkingIndicator"
|
||||
import { TurnOutcome } from "../shared/TurnOutcome"
|
||||
import { QuestionDock } from "./QuestionDock"
|
||||
import { Virtualizer } from "virtua/solid"
|
||||
import { SuggestBar } from "./SuggestBar"
|
||||
@@ -251,6 +252,7 @@ export const MessageList: Component<MessageListProps> = (props) => {
|
||||
</Show>
|
||||
<For each={queuedTurns()}>{(turn) => <VscodeSessionTurn turn={turn} queued />}</For>
|
||||
<WorkingIndicator />
|
||||
<TurnOutcome />
|
||||
<For each={props.questions?.()}>{(req) => <QuestionDock request={req} />}</For>
|
||||
<For each={props.suggestions?.()}>{(req) => <SuggestBar request={req} />}</For>
|
||||
</Show>
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
* session activity) and a context window progress bar.
|
||||
*/
|
||||
|
||||
import { Component, For, Show, createMemo, createSignal, onMount, onCleanup } from "solid-js"
|
||||
import { Component, For, Show, createMemo, createSignal, createEffect, onMount, onCleanup } from "solid-js"
|
||||
import { IconButton } from "@kilocode/kilo-ui/icon-button"
|
||||
import { Tooltip } from "@kilocode/kilo-ui/tooltip"
|
||||
import { Icon } from "@kilocode/kilo-ui/icon"
|
||||
@@ -19,6 +19,7 @@ import { useLanguage } from "../../context/language"
|
||||
import { useVSCode } from "../../context/vscode"
|
||||
import { TaskTimeline } from "./TaskTimeline"
|
||||
import { ContextProgress } from "./ContextProgress"
|
||||
import { SessionRenameEditor } from "../shared/SessionRenameEditor"
|
||||
import { target as todoTarget } from "../../context/todo-revert"
|
||||
import type { Part, TodoItem, ExtensionMessage } from "../../types/messages"
|
||||
|
||||
@@ -31,6 +32,7 @@ export const TaskHeader: Component<TaskHeaderProps> = (props) => {
|
||||
const language = useLanguage()
|
||||
|
||||
const title = createMemo(() => session.currentSession()?.title ?? language.t("command.session.new"))
|
||||
const canRename = createMemo(() => !props.readonly && !!session.currentSession())
|
||||
const hasMessages = createMemo(() => session.messages().length > 0)
|
||||
const busy = createMemo(() => session.status() === "busy")
|
||||
const canCompact = createMemo(() => !busy() && session.visibleMessages().length > 0 && !!session.selected())
|
||||
@@ -114,6 +116,31 @@ export const TaskHeader: Component<TaskHeaderProps> = (props) => {
|
||||
})
|
||||
|
||||
const [todosOpen, setTodosOpen] = createSignal(false)
|
||||
const [renaming, setRenaming] = createSignal<{ id: string; title: string }>()
|
||||
|
||||
const startRename = () => {
|
||||
if (props.readonly) return
|
||||
const info = session.currentSession()
|
||||
if (!info) return
|
||||
setRenaming({ id: info.id, title: info.title ?? "" })
|
||||
}
|
||||
|
||||
const commitRename = (title: string) => {
|
||||
const info = renaming()
|
||||
if (!info) return
|
||||
setRenaming(undefined)
|
||||
if (title === info.title) return
|
||||
session.renameSession(info.id, title)
|
||||
}
|
||||
|
||||
const cancelRename = () => {
|
||||
setRenaming(undefined)
|
||||
}
|
||||
|
||||
createEffect(() => {
|
||||
const info = renaming()
|
||||
if (info && session.currentSession()?.id !== info.id) setRenaming(undefined)
|
||||
})
|
||||
|
||||
const donePart = (idx: number): Part | undefined =>
|
||||
todoTarget({ messages: session.messages(), parts: session.allParts() }, idx)
|
||||
@@ -128,8 +155,34 @@ export const TaskHeader: Component<TaskHeaderProps> = (props) => {
|
||||
return (
|
||||
<Show when={hasMessages()}>
|
||||
<div data-component="task-header">
|
||||
<div data-slot="task-header-title" title={title()}>
|
||||
{title()}
|
||||
<div data-slot="task-header-title">
|
||||
<Show
|
||||
when={!renaming()}
|
||||
fallback={
|
||||
<SessionRenameEditor
|
||||
title={renaming()?.title ?? ""}
|
||||
autosize
|
||||
onSave={commitRename}
|
||||
onCancel={cancelRename}
|
||||
/>
|
||||
}
|
||||
>
|
||||
<span
|
||||
data-slot="task-header-title-trigger"
|
||||
data-renamable={canRename() ? "" : undefined}
|
||||
title={canRename() ? language.t("agentManager.worktree.doubleClickRename") : title()}
|
||||
tabIndex={canRename() ? 0 : undefined}
|
||||
role={canRename() ? "button" : undefined}
|
||||
onDblClick={startRename}
|
||||
onKeyDown={(e) => {
|
||||
if (!canRename() || (e.key !== "Enter" && e.key !== " ")) return
|
||||
e.preventDefault()
|
||||
startRename()
|
||||
}}
|
||||
>
|
||||
<span data-slot="task-header-title-label">{title()}</span>
|
||||
</span>
|
||||
</Show>
|
||||
</div>
|
||||
<div data-slot="task-header-stats">
|
||||
<Show when={cost()}>
|
||||
|
||||
@@ -11,12 +11,12 @@ import { ContextMenu } from "@kilocode/kilo-ui/context-menu"
|
||||
import { Dialog } from "@kilocode/kilo-ui/dialog"
|
||||
import { Button } from "@kilocode/kilo-ui/button"
|
||||
import { IconButton } from "@kilocode/kilo-ui/icon-button"
|
||||
import { InlineInput } from "@kilocode/kilo-ui/inline-input"
|
||||
import { useDialog } from "@kilocode/kilo-ui/context/dialog"
|
||||
import { useSession } from "../../context/session"
|
||||
import { useLanguage } from "../../context/language"
|
||||
import { formatRelativeDate } from "../../utils/date"
|
||||
import type { SessionInfo } from "../../types/messages"
|
||||
import { SessionRenameEditor } from "../shared/SessionRenameEditor"
|
||||
|
||||
const DATE_GROUP_KEYS = ["time.today", "time.yesterday", "time.thisWeek", "time.thisMonth", "time.older"] as const
|
||||
|
||||
@@ -46,7 +46,7 @@ const SessionList: Component<SessionListProps> = (props) => {
|
||||
const dialog = useDialog()
|
||||
|
||||
const [renamingId, setRenamingId] = createSignal<string | null>(null)
|
||||
const [renameValue, setRenameValue] = createSignal("")
|
||||
const [pendingRenameId, setPendingRenameId] = createSignal<string | null>(null)
|
||||
|
||||
onMount(() => {
|
||||
console.log("[Kilo New] SessionList mounted, loading sessions")
|
||||
@@ -60,27 +60,18 @@ const SessionList: Component<SessionListProps> = (props) => {
|
||||
|
||||
function startRename(s: SessionInfo) {
|
||||
setRenamingId(s.id)
|
||||
setRenameValue(s.title || "")
|
||||
}
|
||||
|
||||
function saveRename() {
|
||||
function saveRename(title: string) {
|
||||
const id = renamingId()
|
||||
const title = renameValue().trim()
|
||||
if (!id || !title) {
|
||||
cancelRename()
|
||||
return
|
||||
}
|
||||
if (!id) return
|
||||
const existing = session.sessions().find((s) => s.id === id)
|
||||
if (!existing || title !== (existing.title || "")) {
|
||||
session.renameSession(id, title)
|
||||
}
|
||||
if (!existing || title !== (existing.title || "")) session.renameSession(id, title)
|
||||
setRenamingId(null)
|
||||
setRenameValue("")
|
||||
}
|
||||
|
||||
function cancelRename() {
|
||||
setRenamingId(null)
|
||||
setRenameValue("")
|
||||
}
|
||||
|
||||
function confirmDelete(s: SessionInfo) {
|
||||
@@ -115,8 +106,16 @@ const SessionList: Component<SessionListProps> = (props) => {
|
||||
{node}
|
||||
</ContextMenu.Trigger>
|
||||
<ContextMenu.Portal>
|
||||
<ContextMenu.Content>
|
||||
<ContextMenu.Item onSelect={() => startRename(item)}>
|
||||
<ContextMenu.Content
|
||||
class="session-list-menu"
|
||||
onCloseAutoFocus={(event) => {
|
||||
if (pendingRenameId() !== item.id) return
|
||||
event.preventDefault()
|
||||
setPendingRenameId(null)
|
||||
startRename(item)
|
||||
}}
|
||||
>
|
||||
<ContextMenu.Item onSelect={() => setPendingRenameId(item.id)}>
|
||||
<ContextMenu.ItemLabel>{language.t("common.rename")}</ContextMenu.ItemLabel>
|
||||
</ContextMenu.Item>
|
||||
<ContextMenu.Item onSelect={() => session.exportSessionTranscript(item.id)}>
|
||||
@@ -161,7 +160,16 @@ const SessionList: Component<SessionListProps> = (props) => {
|
||||
<span data-slot="list-item-title">{s.title || language.t("session.untitled")}</span>
|
||||
<span data-slot="list-item-description">{formatRelativeDate(s.updatedAt)}</span>
|
||||
<span
|
||||
data-slot="session-delete-button"
|
||||
data-slot="session-row-action"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation()
|
||||
startRename(s)
|
||||
}}
|
||||
>
|
||||
<IconButton icon="edit" size="small" variant="ghost" aria-label={language.t("common.rename")} />
|
||||
</span>
|
||||
<span
|
||||
data-slot="session-row-action"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation()
|
||||
confirmDelete(s)
|
||||
@@ -177,24 +185,7 @@ const SessionList: Component<SessionListProps> = (props) => {
|
||||
</>
|
||||
}
|
||||
>
|
||||
<InlineInput
|
||||
ref={(el) => requestAnimationFrame(() => el?.focus())}
|
||||
value={renameValue()}
|
||||
onInput={(e) => setRenameValue(e.currentTarget.value)}
|
||||
onKeyDown={(e) => {
|
||||
e.stopPropagation()
|
||||
if (e.key === "Enter") {
|
||||
e.preventDefault()
|
||||
saveRename()
|
||||
}
|
||||
if (e.key === "Escape") {
|
||||
e.preventDefault()
|
||||
cancelRename()
|
||||
}
|
||||
}}
|
||||
onBlur={() => saveRename()}
|
||||
style={{ width: "100%" }}
|
||||
/>
|
||||
<SessionRenameEditor title={s.title || ""} fill stop onSave={saveRename} onCancel={cancelRename} />
|
||||
</Show>
|
||||
)}
|
||||
</List>
|
||||
|
||||
@@ -23,7 +23,7 @@ interface Props {
|
||||
items: MarketplaceItem[]
|
||||
metadata: MarketplaceInstalledMetadata
|
||||
fetching: boolean
|
||||
type: "mcp" | "mode" | "skill"
|
||||
type: "mcp" | "agent" | "skill"
|
||||
searchPlaceholder: string
|
||||
emptyMessage: string
|
||||
onInstall: (item: MarketplaceItem) => void
|
||||
|
||||
@@ -9,7 +9,7 @@ import { useDialog } from "@kilocode/kilo-ui/context/dialog"
|
||||
import type {
|
||||
MarketplaceItem,
|
||||
McpMarketplaceItem,
|
||||
ModeMarketplaceItem,
|
||||
AgentMarketplaceItem,
|
||||
SkillMarketplaceItem,
|
||||
MarketplaceInstalledMetadata,
|
||||
} from "../../types/marketplace"
|
||||
@@ -31,12 +31,13 @@ export const MarketplaceView = () => {
|
||||
const [metadata, setMetadata] = createSignal<MarketplaceInstalledMetadata>(EMPTY_METADATA)
|
||||
const [fetching, setFetching] = createSignal(true)
|
||||
const [errors, setErrors] = createSignal<string[]>([])
|
||||
const [tab, setTab] = createSignal("mcp")
|
||||
const [tab, setTab] = createSignal("agent")
|
||||
const [pending, setPending] = createSignal<{ item: MarketplaceItem; scope: "project" | "global" } | null>(null)
|
||||
const [showMigrationBanner, setShowMigrationBanner] = createSignal(false)
|
||||
|
||||
const skills = createMemo(() => items().filter((i): i is SkillMarketplaceItem => i.type === "skill"))
|
||||
const mcps = createMemo(() => items().filter((i): i is McpMarketplaceItem => i.type === "mcp"))
|
||||
const modes = createMemo(() => items().filter((i): i is ModeMarketplaceItem => i.type === "mode"))
|
||||
const agents = createMemo(() => items().filter((i): i is AgentMarketplaceItem => i.type === "agent"))
|
||||
|
||||
const fetchData = () => {
|
||||
setFetching(true)
|
||||
@@ -51,6 +52,7 @@ export const MarketplaceView = () => {
|
||||
setMetadata(msg.marketplaceInstalledMetadata ?? EMPTY_METADATA)
|
||||
setErrors(msg.errors ?? [])
|
||||
setFetching(false)
|
||||
setShowMigrationBanner(msg.showAgentMigrationBanner ?? false)
|
||||
}
|
||||
if (msg.type === "marketplaceRemoveResult") {
|
||||
const removed = pending()
|
||||
@@ -138,6 +140,11 @@ export const MarketplaceView = () => {
|
||||
setErrors((prev) => prev.filter((_, i) => i !== idx))
|
||||
}
|
||||
|
||||
const dismissMigrationBanner = () => {
|
||||
setShowMigrationBanner(false)
|
||||
vscode.postMessage({ type: "dismissAgentMigrationBanner" })
|
||||
}
|
||||
|
||||
return (
|
||||
<div class="marketplace-view">
|
||||
<Show when={errors().length > 0}>
|
||||
@@ -153,18 +160,26 @@ export const MarketplaceView = () => {
|
||||
|
||||
<Tabs value={tab()} onChange={setTab} class="marketplace-tabs-root">
|
||||
<Tabs.List>
|
||||
<Tabs.Trigger value="agent">{t("marketplace.tab.agents")}</Tabs.Trigger>
|
||||
<Tabs.Trigger value="mcp">{t("marketplace.tab.mcp")}</Tabs.Trigger>
|
||||
<Tabs.Trigger value="mode">{t("marketplace.tab.modes")}</Tabs.Trigger>
|
||||
<Tabs.Trigger value="skill">{t("marketplace.tab.skills")}</Tabs.Trigger>
|
||||
</Tabs.List>
|
||||
|
||||
<div class="marketplace-content">
|
||||
<Tabs.Content value="mcp">
|
||||
<Tabs.Content value="agent">
|
||||
<Show when={showMigrationBanner()}>
|
||||
<Card variant="info" class="marketplace-error-banner">
|
||||
<span>{t("marketplace.migration.notice")}</span>
|
||||
<Button variant="ghost" size="small" onClick={dismissMigrationBanner}>
|
||||
{t("marketplace.error.dismiss")}
|
||||
</Button>
|
||||
</Card>
|
||||
</Show>
|
||||
<MarketplaceListView
|
||||
items={mcps()}
|
||||
items={agents()}
|
||||
metadata={metadata()}
|
||||
fetching={fetching()}
|
||||
type="mcp"
|
||||
type="agent"
|
||||
searchPlaceholder={t("marketplace.search")}
|
||||
emptyMessage={t("marketplace.empty")}
|
||||
onInstall={handleInstall}
|
||||
@@ -172,12 +187,12 @@ export const MarketplaceView = () => {
|
||||
/>
|
||||
</Tabs.Content>
|
||||
|
||||
<Tabs.Content value="mode">
|
||||
<Tabs.Content value="mcp">
|
||||
<MarketplaceListView
|
||||
items={modes()}
|
||||
items={mcps()}
|
||||
metadata={metadata()}
|
||||
fetching={fetching()}
|
||||
type="mode"
|
||||
type="mcp"
|
||||
searchPlaceholder={t("marketplace.search")}
|
||||
emptyMessage={t("marketplace.empty")}
|
||||
onInstall={handleInstall}
|
||||
|
||||
@@ -15,20 +15,24 @@ export const RemoveDialog = (props: Props) => {
|
||||
|
||||
const typeName = () => {
|
||||
if (props.item.type === "mcp") return t("marketplace.remove.type.mcp")
|
||||
if (props.item.type === "mode") return t("marketplace.remove.type.mode")
|
||||
if (props.item.type === "agent") return t("marketplace.remove.type.agent")
|
||||
return t("marketplace.remove.type.skill")
|
||||
}
|
||||
|
||||
return (
|
||||
<Dialog title={t("marketplace.remove.title", { name: props.item.name })} fit>
|
||||
<p>{t("marketplace.remove.confirm", { type: typeName(), scope: t(`marketplace.scope.${props.scope}`) })}</p>
|
||||
<div class="marketplace-remove-actions">
|
||||
<Button variant="secondary" onClick={props.onClose}>
|
||||
{t("marketplace.remove.cancel")}
|
||||
</Button>
|
||||
<Button variant="primary" class="danger-btn" onClick={props.onConfirm}>
|
||||
{t("marketplace.remove.confirm.button")}
|
||||
</Button>
|
||||
<div class="dialog-confirm-body">
|
||||
<span>
|
||||
{t("marketplace.remove.confirm", { type: typeName(), scope: t(`marketplace.scope.${props.scope}`) })}
|
||||
</span>
|
||||
<div class="dialog-confirm-actions">
|
||||
<Button variant="secondary" onClick={props.onClose}>
|
||||
{t("marketplace.remove.cancel")}
|
||||
</Button>
|
||||
<Button variant="primary" class="danger-btn" onClick={props.onConfirm}>
|
||||
{t("marketplace.remove.confirm.button")}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</Dialog>
|
||||
)
|
||||
|
||||
@@ -200,9 +200,9 @@ const AgentBehaviourTab: Component = () => {
|
||||
|
||||
const confirmRemoveMode = (agent: AgentInfo) => {
|
||||
dialog.show(() => (
|
||||
<Dialog title={language.t("settings.agentBehaviour.removeMode.title")} fit>
|
||||
<Dialog title={language.t("settings.agentBehaviour.removeAgent.title")} fit>
|
||||
<div class="dialog-confirm-body">
|
||||
<span>{language.t("settings.agentBehaviour.removeMode.confirm", { name: agent.name })}</span>
|
||||
<span>{language.t("settings.agentBehaviour.removeAgent.confirm", { name: agent.name })}</span>
|
||||
<div class="dialog-confirm-actions">
|
||||
<Button variant="ghost" size="large" onClick={() => dialog.close()}>
|
||||
{language.t("common.cancel")}
|
||||
@@ -216,7 +216,7 @@ const AgentBehaviourTab: Component = () => {
|
||||
// to prevent the reactive list re-render from firing click handlers
|
||||
// on shifted list items while the dialog overlay is still present.
|
||||
setTimeout(() => {
|
||||
session.removeMode(agent.name)
|
||||
session.removeAgent(agent.name)
|
||||
// If we were editing this mode, go back to list
|
||||
if (editingAgent() === agent.name) {
|
||||
setAgentView("list")
|
||||
@@ -225,7 +225,7 @@ const AgentBehaviourTab: Component = () => {
|
||||
}, 150)
|
||||
}}
|
||||
>
|
||||
{language.t("settings.agentBehaviour.removeMode.button")}
|
||||
{language.t("settings.agentBehaviour.removeAgent.button")}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -357,7 +357,7 @@ const AgentBehaviourTab: Component = () => {
|
||||
color: "var(--text-weak-base, var(--vscode-descriptionForeground))",
|
||||
}}
|
||||
>
|
||||
{language.t("settings.agentBehaviour.noModesFound")}
|
||||
{language.t("settings.agentBehaviour.noAgentsFound")}
|
||||
</div>
|
||||
</Card>
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@ import { useLanguage } from "../../context/language"
|
||||
import { useProvider } from "../../context/provider"
|
||||
import { useSession } from "../../context/session"
|
||||
import { parseModelString } from "../../../../src/shared/provider-model"
|
||||
import { DEFAULT_AUTOCOMPLETE_MODEL } from "../../../../src/shared/autocomplete-models"
|
||||
import { ModelSelectorBase } from "../shared/ModelSelector"
|
||||
import { ThinkingSelectorBase } from "../shared/ThinkingSelector"
|
||||
import SettingsRow from "./SettingsRow"
|
||||
@@ -17,9 +16,14 @@ const ModelsTab: Component = () => {
|
||||
const provider = useProvider()
|
||||
const session = useSession()
|
||||
|
||||
const autocompleteProvider = () =>
|
||||
String(settings()["autocomplete.provider"] ?? DEFAULT_AUTOCOMPLETE_MODEL.providerID)
|
||||
const autocompleteModel = () => String(settings()["autocomplete.model"] ?? DEFAULT_AUTOCOMPLETE_MODEL.modelID)
|
||||
const autocompleteProvider = () => {
|
||||
const v = settings()["autocomplete.provider"]
|
||||
return typeof v === "string" ? v : undefined
|
||||
}
|
||||
const autocompleteModel = () => {
|
||||
const v = settings()["autocomplete.model"]
|
||||
return typeof v === "string" ? v : undefined
|
||||
}
|
||||
|
||||
function handleModelSelect(configKey: "model" | "small_model") {
|
||||
return (providerID: string, modelID: string) => {
|
||||
@@ -73,7 +77,13 @@ const ModelsTab: Component = () => {
|
||||
}
|
||||
|
||||
function handleAutocompleteModelSelect(providerID: string, modelID: string) {
|
||||
if (!providerID || !modelID) return
|
||||
if (!providerID || !modelID) {
|
||||
// Clearing both keys reverts to the resolved server-side default. Users
|
||||
// who pick "Not set" follow future default changes automatically.
|
||||
updateSetting("autocomplete.provider", null)
|
||||
updateSetting("autocomplete.model", null)
|
||||
return
|
||||
}
|
||||
updateSetting("autocomplete.provider", providerID)
|
||||
updateSetting("autocomplete.model", modelID)
|
||||
}
|
||||
@@ -137,6 +147,8 @@ const ModelsTab: Component = () => {
|
||||
placement="bottom-start"
|
||||
models={AUTOCOMPLETE_SELECTOR_MODELS}
|
||||
favorites={false}
|
||||
allowClear
|
||||
clearLabel={language.t("settings.providers.notSet")}
|
||||
/>
|
||||
</SettingsRow>
|
||||
</Card>
|
||||
|
||||
@@ -1,7 +1,14 @@
|
||||
import { AUTOCOMPLETE_MODELS, getAutocompleteModel } from "../../../../src/shared/autocomplete-models"
|
||||
import type { EnrichedModel } from "../../context/provider"
|
||||
|
||||
/**
|
||||
* Resolve the (provider, model) pair to the dropdown's value. Returns
|
||||
* `null` when neither is set so the selector renders the "Not set" (clear)
|
||||
* state via `allowClear`. The runtime resolves unset values to
|
||||
* `DEFAULT_AUTOCOMPLETE_MODEL` separately.
|
||||
*/
|
||||
export function getAutocompleteSelection(provider?: string, modelID?: string) {
|
||||
if (!provider && !modelID) return null
|
||||
const model = getAutocompleteModel(provider, modelID)
|
||||
return { providerID: model.providerID, modelID: model.modelID }
|
||||
}
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
import { Component, createSignal } from "solid-js"
|
||||
import { InlineInput } from "@kilocode/kilo-ui/inline-input"
|
||||
import { showToast } from "@kilocode/kilo-ui/toast"
|
||||
import { useLanguage } from "../../context/language"
|
||||
import { parseSessionTitle, SESSION_TITLE_LIMIT } from "../../../../src/shared/session-title"
|
||||
|
||||
interface SessionRenameEditorProps {
|
||||
title: string
|
||||
autosize?: boolean
|
||||
fill?: boolean
|
||||
stop?: boolean
|
||||
onSave: (title: string) => void
|
||||
onCancel: () => void
|
||||
}
|
||||
|
||||
export const SessionRenameEditor: Component<SessionRenameEditorProps> = (props) => {
|
||||
const language = useLanguage()
|
||||
const [value, setValue] = createSignal(props.title)
|
||||
|
||||
const save = () => {
|
||||
const result = parseSessionTitle(value())
|
||||
if ("error" in result) {
|
||||
showToast({ variant: "error", title: language.t("toast.session.rename.invalid.title") })
|
||||
return
|
||||
}
|
||||
props.onSave(result.value)
|
||||
}
|
||||
|
||||
return (
|
||||
<span data-slot="session-title-editor" data-fill={props.fill ? "" : undefined}>
|
||||
<InlineInput
|
||||
class="session-title-input"
|
||||
aria-label={language.t("common.rename")}
|
||||
value={value()}
|
||||
size={props.autosize ? Math.min(Math.max(value().length + 2, 14), 48) : undefined}
|
||||
maxLength={SESSION_TITLE_LIMIT}
|
||||
onInput={(e) => setValue(e.currentTarget.value)}
|
||||
onKeyDown={(e) => {
|
||||
if (props.stop) e.stopPropagation()
|
||||
if (e.key === "Enter") {
|
||||
e.preventDefault()
|
||||
save()
|
||||
}
|
||||
if (e.key === "Escape") {
|
||||
e.preventDefault()
|
||||
props.onCancel()
|
||||
}
|
||||
}}
|
||||
onBlur={save}
|
||||
ref={(el) =>
|
||||
requestAnimationFrame(() => {
|
||||
el.focus()
|
||||
el.select()
|
||||
})
|
||||
}
|
||||
/>
|
||||
</span>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
import { Card } from "@kilocode/kilo-ui/card"
|
||||
import { type Component, Show, createMemo } from "solid-js"
|
||||
import { useSession } from "../../context/session"
|
||||
import { terminal, type TerminalState } from "../../context/session-outcome"
|
||||
import { useLanguage } from "../../context/language"
|
||||
|
||||
export const TurnOutcome: Component = () => {
|
||||
const session = useSession()
|
||||
const language = useLanguage()
|
||||
const state = createMemo(() =>
|
||||
terminal({
|
||||
reason: session.closeReason(),
|
||||
messages: session.visibleMessages(),
|
||||
todos: session.todos(),
|
||||
hidden: session.isErrorHidden,
|
||||
}),
|
||||
)
|
||||
|
||||
const label = (value: TerminalState) => {
|
||||
if (value.kind === "interrupted") return language.t("session.outcome.interrupted")
|
||||
if (value.kind === "error") return language.t("session.outcome.error")
|
||||
if (value.kind === "limit") return language.t("session.outcome.limit")
|
||||
if (value.kind === "unknown") return language.t("session.outcome.unknown")
|
||||
if (value.kind === "filtered") return language.t("session.outcome.filtered")
|
||||
if (value.kind === "unexpected") return language.t("session.outcome.unexpected")
|
||||
return language.t("session.outcome.incomplete", { count: String(value.remaining) })
|
||||
}
|
||||
|
||||
return (
|
||||
<Show when={session.status() === "idle" && state()}>
|
||||
{(value) => (
|
||||
<div
|
||||
class="vscode-session-turn"
|
||||
role="status"
|
||||
title={value().finish ? language.t("session.outcome.finish", { reason: value().finish! }) : undefined}
|
||||
>
|
||||
<Card variant={value().tone === "critical" ? "error" : "warning"}>{label(value())}</Card>
|
||||
</div>
|
||||
)}
|
||||
</Show>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
import type { Message, SessionCloseReason, TodoItem } from "../types/messages"
|
||||
|
||||
type TerminalKind = "incomplete" | "limit" | "unknown" | "filtered" | "unexpected" | "interrupted" | "error"
|
||||
type TerminalTone = "warning" | "critical"
|
||||
|
||||
export interface TerminalState {
|
||||
kind: TerminalKind
|
||||
tone: TerminalTone
|
||||
finish?: string
|
||||
remaining: number
|
||||
}
|
||||
|
||||
interface Input {
|
||||
reason?: SessionCloseReason
|
||||
messages: Message[]
|
||||
todos: TodoItem[]
|
||||
hidden?: (id: string) => boolean
|
||||
}
|
||||
|
||||
export function terminal(input: Input): TerminalState | undefined {
|
||||
if (!input.reason) return undefined
|
||||
const last = input.messages[input.messages.length - 1]
|
||||
const finish = last?.role === "assistant" ? last.finish : undefined
|
||||
const remaining = input.todos.filter((item) => item.status !== "completed" && item.status !== "cancelled").length
|
||||
|
||||
if (input.reason === "interrupted") return { kind: "interrupted", tone: "warning", finish, remaining }
|
||||
if (input.reason === "error") {
|
||||
if (last?.role === "assistant" && last.error && !input.hidden?.(last.id)) return undefined
|
||||
return { kind: "error", tone: "critical", finish, remaining }
|
||||
}
|
||||
if (finish === "length") return { kind: "limit", tone: "warning", finish, remaining }
|
||||
if (finish === "unknown") return { kind: "unknown", tone: "warning", finish, remaining }
|
||||
if (finish === "content-filter") return { kind: "filtered", tone: "warning", finish, remaining }
|
||||
if (finish === "other") return { kind: "unexpected", tone: "warning", finish, remaining }
|
||||
if (remaining > 0) return { kind: "incomplete", tone: "warning", finish, remaining }
|
||||
return undefined
|
||||
}
|
||||
@@ -20,6 +20,7 @@ import type {
|
||||
PartDelta,
|
||||
SessionStatus,
|
||||
SessionStatusInfo,
|
||||
SessionCloseReason,
|
||||
PermissionRequest,
|
||||
QuestionRequest,
|
||||
SuggestionRequest,
|
||||
@@ -108,6 +109,7 @@ interface SessionContextValue {
|
||||
// Session status
|
||||
status: Accessor<SessionStatus>
|
||||
statusInfo: Accessor<SessionStatusInfo>
|
||||
closeReason: Accessor<SessionCloseReason | undefined>
|
||||
statusText: Accessor<string | undefined>
|
||||
busySince: Accessor<number | undefined>
|
||||
loading: Accessor<boolean>
|
||||
@@ -185,7 +187,7 @@ interface SessionContextValue {
|
||||
// Agent/mode selection (per-session)
|
||||
agents: Accessor<AgentInfo[]>
|
||||
allAgents: Accessor<AgentInfo[]>
|
||||
removeMode: (name: string) => void
|
||||
removeAgent: (name: string) => void
|
||||
removeMcp: (name: string) => void
|
||||
|
||||
// MCP server status (runtime connect/disconnect)
|
||||
@@ -284,6 +286,7 @@ export const SessionProvider: ParentComponent = (props) => {
|
||||
|
||||
// Per-session status map — keyed by sessionID
|
||||
const [statusMap, setStatusMap] = createStore<Record<string, SessionStatusInfo>>({})
|
||||
const [closeMap, setCloseMap] = createStore<Record<string, SessionCloseReason | undefined>>({})
|
||||
const [busySinceMap, setBusySinceMap] = createStore<Record<string, number>>({})
|
||||
|
||||
const idle: SessionStatusInfo = { type: "idle" }
|
||||
@@ -294,6 +297,16 @@ export const SessionProvider: ParentComponent = (props) => {
|
||||
return id ? (statusMap[id] ?? idle) : idle
|
||||
}
|
||||
const status = () => statusInfo().type as SessionStatus
|
||||
const closeReason = () => {
|
||||
const id = currentSessionID()
|
||||
return id ? closeMap[id] : undefined
|
||||
}
|
||||
const clearClose = (id: string) =>
|
||||
setCloseMap(
|
||||
produce((map) => {
|
||||
delete map[id]
|
||||
}),
|
||||
)
|
||||
const busySince = () => {
|
||||
const id = currentSessionID()
|
||||
return id ? busySinceMap[id] : undefined
|
||||
@@ -336,7 +349,7 @@ export const SessionProvider: ParentComponent = (props) => {
|
||||
// Skills loaded from the CLI backend
|
||||
const [skills, setSkills] = createSignal<SkillInfo[]>([])
|
||||
|
||||
const removeMode = (name: string) => {
|
||||
const removeAgent = (name: string) => {
|
||||
setAgents((prev) => prev.filter((a) => a.name !== name))
|
||||
|
||||
// Clear stale selections so selectedAgentName() falls back to the default
|
||||
@@ -352,7 +365,7 @@ export const SessionProvider: ParentComponent = (props) => {
|
||||
}),
|
||||
)
|
||||
|
||||
vscode.postMessage({ type: "removeMode", name })
|
||||
vscode.postMessage({ type: "removeAgent", name })
|
||||
}
|
||||
|
||||
const removeMcp = (name: string) => {
|
||||
@@ -837,6 +850,10 @@ export const SessionProvider: ParentComponent = (props) => {
|
||||
handleSessionStatus(message.sessionID, message.status, message.attempt, message.message, message.next)
|
||||
break
|
||||
|
||||
case "sessionTurnClosed":
|
||||
setCloseMap(message.sessionID, message.reason)
|
||||
break
|
||||
|
||||
case "todoUpdated":
|
||||
handleTodoUpdated(message.sessionID, message.items)
|
||||
break
|
||||
@@ -1316,8 +1333,9 @@ export const SessionProvider: ParentComponent = (props) => {
|
||||
? { type: "offline", message: message ?? "" }
|
||||
: { type: newStatus }
|
||||
setStatusMap(sessionID, info)
|
||||
// Track busy start time
|
||||
// Track busy start time and discard the previous turn's terminal state.
|
||||
if (prev.type === "idle" && newStatus !== "idle") {
|
||||
clearClose(sessionID)
|
||||
setBusySinceMap(sessionID, Date.now())
|
||||
}
|
||||
if (newStatus === "idle") {
|
||||
@@ -1326,7 +1344,7 @@ export const SessionProvider: ParentComponent = (props) => {
|
||||
delete map[sessionID]
|
||||
}),
|
||||
)
|
||||
// Session is idle — any remaining pending optimistic IDs are either
|
||||
// Session is idle - any remaining pending optimistic IDs are either
|
||||
// already confirmed (messageCreated removed them) or orphaned (queued
|
||||
// callbacks were dropped on abort). Clean up the tracking set; the
|
||||
// messages themselves will be reconciled on the next messagesLoaded.
|
||||
@@ -1554,6 +1572,7 @@ export const SessionProvider: ParentComponent = (props) => {
|
||||
const next = session.revert ?? undefined
|
||||
setStore("sessions", session.id, session)
|
||||
if (prev?.messageID === next?.messageID && prev?.partID === next?.partID) return
|
||||
clearClose(session.id)
|
||||
resetTodos(session.id, next)
|
||||
}
|
||||
|
||||
@@ -1670,6 +1689,7 @@ export const SessionProvider: ParentComponent = (props) => {
|
||||
delete map[sessionID]
|
||||
}),
|
||||
)
|
||||
clearClose(sessionID)
|
||||
setBusySinceMap(
|
||||
produce((map) => {
|
||||
delete map[sessionID]
|
||||
@@ -1906,7 +1926,10 @@ export const SessionProvider: ParentComponent = (props) => {
|
||||
for (const q of scopedQuestions(sid)) {
|
||||
rejectQuestion(q.id)
|
||||
}
|
||||
if (sid) addOptimistic(sid, messageID, text, files)
|
||||
if (sid) {
|
||||
clearClose(sid)
|
||||
addOptimistic(sid, messageID, text, files)
|
||||
}
|
||||
|
||||
const scope = draftID ?? sid
|
||||
const agent = promptAgent(scope)
|
||||
@@ -1969,7 +1992,10 @@ export const SessionProvider: ParentComponent = (props) => {
|
||||
rejectQuestion(q.id)
|
||||
}
|
||||
|
||||
if (sid) addOptimistic(sid, messageID, `/${command} ${args}`.trim(), files)
|
||||
if (sid) {
|
||||
clearClose(sid)
|
||||
addOptimistic(sid, messageID, `/${command} ${args}`.trim(), files)
|
||||
}
|
||||
|
||||
const scope = draftID ?? sid
|
||||
const agent = promptAgent(scope)
|
||||
@@ -2306,6 +2332,7 @@ export const SessionProvider: ParentComponent = (props) => {
|
||||
function revertSession(messageID: string, partID?: string) {
|
||||
const id = currentSessionID()
|
||||
if (!id) return
|
||||
clearClose(id)
|
||||
// Restore the reverted user message's prompt text into the input.
|
||||
// Dispatch as a window message so PromptInput picks it up via onMessage.
|
||||
const parts = store.parts[messageID]
|
||||
@@ -2423,6 +2450,7 @@ export const SessionProvider: ParentComponent = (props) => {
|
||||
sessions,
|
||||
status,
|
||||
statusInfo,
|
||||
closeReason,
|
||||
statusText,
|
||||
busySince,
|
||||
loading,
|
||||
@@ -2459,7 +2487,7 @@ export const SessionProvider: ParentComponent = (props) => {
|
||||
skills,
|
||||
refreshSkills,
|
||||
removeSkill,
|
||||
removeMode,
|
||||
removeAgent,
|
||||
removeMcp,
|
||||
mcpStatus,
|
||||
mcpLoading,
|
||||
|
||||
+14
-6
@@ -447,6 +447,7 @@ export const dict = {
|
||||
"toast.session.unshare.failed.title": "فشل إلغاء مشاركة الجلسة",
|
||||
"toast.session.unshare.failed.description": "حدث خطأ أثناء إلغاء مشاركة الجلسة",
|
||||
|
||||
"toast.session.rename.invalid.title": "عنوان الجلسة غير صالح",
|
||||
"toast.session.listFailed.title": "فشل تحميل الجلسات لـ {{project}}",
|
||||
|
||||
"toast.update.title": "تحديث متاح",
|
||||
@@ -1107,6 +1108,14 @@ export const dict = {
|
||||
"session.status.retrying": "...إعادة المحاولة (المحاولة {{ attempt }})… {{ message }}",
|
||||
"session.status.working": "...جارٍ العمل",
|
||||
"session.status.offline": "انقطع الاتصال بالشبكة — جارٍ إعادة الاتصال...",
|
||||
"session.outcome.incomplete": "انتهى الدور مع تبقي {{count}} مهام",
|
||||
"session.outcome.limit": "تم الوصول إلى حد الاستجابة قبل الاكتمال",
|
||||
"session.outcome.unknown": "انتهى الدور بدون سبب إنهاء من النموذج",
|
||||
"session.outcome.filtered": "أوقف المزود هذه الاستجابة بسبب عامل تصفية المحتوى.",
|
||||
"session.outcome.unexpected": "انتهت الاستجابة بشكل غير متوقع وقد تكون غير مكتملة.",
|
||||
"session.outcome.interrupted": "تمت مقاطعة الدور",
|
||||
"session.outcome.error": "فشل الدور",
|
||||
"session.outcome.finish": "سبب الإنهاء: {{reason}}",
|
||||
|
||||
"ui.sessionTurn.cancel": "إلغاء",
|
||||
"ui.sessionTurn.status.thinking": "...جارٍ التفكير",
|
||||
@@ -1167,7 +1176,6 @@ export const dict = {
|
||||
'يتم التحكم في Telemetry بواسطة إعداد Telemetry المدمج في VS Code. لتعطيله، انتقل إلى الإعدادات > Telemetry > Telemetry Level واضبطه على "off". أعد تشغيل VS Code لتطبيق التغيير.',
|
||||
"settings.aboutKiloCode.telemetry.openSettings": "فتح إعدادات Telemetry",
|
||||
|
||||
"settings.agentBehaviour.subtab.modes": "الأوضاع",
|
||||
"settings.agentBehaviour.subtab.agents": "الوكلاء",
|
||||
"settings.agentBehaviour.subtab.mcpServers": "خوادم MCP",
|
||||
"settings.agentBehaviour.subtab.rules": "القواعد",
|
||||
@@ -1279,7 +1287,7 @@ export const dict = {
|
||||
"settings.agentBehaviour.noSkillsFound":
|
||||
"لم يتم العثور على مهارات. أضف مسارات مجلدات أو عناوين URL أدناه لإتاحة المهارات.",
|
||||
"settings.agentBehaviour.availableModes": "الأوضاع المخصصة المتاحة",
|
||||
"settings.agentBehaviour.noModesFound": "لم يتم العثور على أوضاع.",
|
||||
"settings.agentBehaviour.noAgentsFound": "لم يتم العثور على وكلاء.",
|
||||
"settings.agentBehaviour.createMode": "إنشاء وضع جديد",
|
||||
"settings.agentBehaviour.createMode.name": "الاسم",
|
||||
"settings.agentBehaviour.createMode.name.placeholder": "مثال: reviewer",
|
||||
@@ -1322,10 +1330,10 @@ export const dict = {
|
||||
"settings.agentBehaviour.permissions.copy": "نسخ الأذونات كـ JSON",
|
||||
"settings.agentBehaviour.permissions.hint":
|
||||
"يتم تقييم القواعد بالترتيب — القاعدة المطابقة الأخيرة هي التي تُطبق. هذه هي مجموعة القواعد المحلولة من خلفية CLI.",
|
||||
"settings.agentBehaviour.removeMode.title": "إزالة الوضع",
|
||||
"settings.agentBehaviour.removeMode.confirm":
|
||||
'هل تريد إزالة الوضع "{{name}}"؟ سيؤدي هذا إلى تعطيل الوضع عن طريق تحديث الإعدادات.',
|
||||
"settings.agentBehaviour.removeMode.button": "إزالة",
|
||||
"settings.agentBehaviour.removeAgent.title": "إزالة الوكيل",
|
||||
"settings.agentBehaviour.removeAgent.confirm":
|
||||
'هل تريد إزالة الوكيل "{{name}}"؟ سيؤدي هذا إلى تعطيله عن طريق تحديث الإعدادات.',
|
||||
"settings.agentBehaviour.removeAgent.button": "إزالة",
|
||||
"settings.agentBehaviour.removeMcp.title": "إزالة خادم MCP",
|
||||
"settings.agentBehaviour.removeMcp.confirm": 'هل تريد إزالة خادم MCP "{{name}}"؟ سيؤدي هذا إلى إزالته من الإعدادات.',
|
||||
"settings.agentBehaviour.removeMcp.button": "إزالة",
|
||||
|
||||
+14
-6
@@ -450,6 +450,7 @@ export const dict = {
|
||||
"toast.session.unshare.failed.title": "Falha ao parar de compartilhar sessão",
|
||||
"toast.session.unshare.failed.description": "Ocorreu um erro ao parar de compartilhar a sessão",
|
||||
|
||||
"toast.session.rename.invalid.title": "Título de sessão inválido",
|
||||
"toast.session.listFailed.title": "Falha ao carregar sessões para {{project}}",
|
||||
|
||||
"toast.update.title": "Atualização disponível",
|
||||
@@ -1126,6 +1127,14 @@ export const dict = {
|
||||
"session.status.retrying": "Tentando novamente (tentativa {{ attempt }})… {{ message }}",
|
||||
"session.status.working": "Trabalhando…",
|
||||
"session.status.offline": "Rede desconectada — reconectando...",
|
||||
"session.outcome.incomplete": "Turno encerrado com {{count}} tarefas restantes",
|
||||
"session.outcome.limit": "Limite de resposta atingido antes da conclusão",
|
||||
"session.outcome.unknown": "Turno encerrado sem um motivo de conclusão do modelo",
|
||||
"session.outcome.filtered": "O provedor interrompeu esta resposta devido a um filtro de conteúdo.",
|
||||
"session.outcome.unexpected": "A resposta terminou inesperadamente e pode estar incompleta.",
|
||||
"session.outcome.interrupted": "Turno interrompido",
|
||||
"session.outcome.error": "Turno falhou",
|
||||
"session.outcome.finish": "Motivo da conclusão: {{reason}}",
|
||||
|
||||
"ui.sessionTurn.cancel": "Cancelar",
|
||||
"ui.sessionTurn.status.thinking": "Pensando...",
|
||||
@@ -1191,7 +1200,6 @@ export const dict = {
|
||||
'A telemetria é controlada pela configuração de telemetria integrada do VS Code. Para desativá-la, vá para Configurações > Telemetria > Nível de Telemetria e defina como "off". Reinicie o VS Code para aplicar a alteração.',
|
||||
"settings.aboutKiloCode.telemetry.openSettings": "Abrir Configurações de Telemetria",
|
||||
|
||||
"settings.agentBehaviour.subtab.modes": "Modos",
|
||||
"settings.agentBehaviour.subtab.agents": "Agentes",
|
||||
"settings.agentBehaviour.subtab.mcpServers": "Servidores MCP",
|
||||
"settings.agentBehaviour.subtab.rules": "Regras",
|
||||
@@ -1310,7 +1318,7 @@ export const dict = {
|
||||
"settings.agentBehaviour.noSkillsFound":
|
||||
"Nenhuma habilidade encontrada. Adicione caminhos de pastas ou URLs abaixo para disponibilizar habilidades.",
|
||||
"settings.agentBehaviour.availableModes": "Modos personalizados disponíveis",
|
||||
"settings.agentBehaviour.noModesFound": "Nenhum modo encontrado.",
|
||||
"settings.agentBehaviour.noAgentsFound": "Nenhum agente encontrado.",
|
||||
"settings.agentBehaviour.createMode": "Criar Novo Modo",
|
||||
"settings.agentBehaviour.createMode.name": "Nome",
|
||||
"settings.agentBehaviour.createMode.name.placeholder": "ex: reviewer",
|
||||
@@ -1354,10 +1362,10 @@ export const dict = {
|
||||
"settings.agentBehaviour.permissions.copy": "Copiar permissões como JSON",
|
||||
"settings.agentBehaviour.permissions.hint":
|
||||
"As regras são avaliadas em ordem — a última regra correspondente vence. Este é o conjunto de regras resolvido do backend da CLI.",
|
||||
"settings.agentBehaviour.removeMode.title": "Remover modo",
|
||||
"settings.agentBehaviour.removeMode.confirm":
|
||||
'Remover o modo "{{name}}"? Isso desativará o modo atualizando sua configuração.',
|
||||
"settings.agentBehaviour.removeMode.button": "Remover",
|
||||
"settings.agentBehaviour.removeAgent.title": "Remover agente",
|
||||
"settings.agentBehaviour.removeAgent.confirm":
|
||||
'Remover agente "{{name}}"? Isso irá desativá-lo atualizando sua configuração.',
|
||||
"settings.agentBehaviour.removeAgent.button": "Remover",
|
||||
"settings.agentBehaviour.removeMcp.title": "Remover servidor MCP",
|
||||
"settings.agentBehaviour.removeMcp.confirm":
|
||||
'Remover o servidor MCP "{{name}}"? Isso o removerá da sua configuração.',
|
||||
|
||||
+14
-6
@@ -454,6 +454,7 @@ export const dict = {
|
||||
"toast.session.unshare.failed.title": "Neuspjelo ukidanje dijeljenja",
|
||||
"toast.session.unshare.failed.description": "Došlo je do greške prilikom ukidanja dijeljenja",
|
||||
|
||||
"toast.session.rename.invalid.title": "Nevažeći naslov sesije",
|
||||
"toast.session.listFailed.title": "Neuspjelo učitavanje sesija za {{project}}",
|
||||
|
||||
"toast.update.title": "Dostupno ažuriranje",
|
||||
@@ -1132,6 +1133,14 @@ export const dict = {
|
||||
"session.status.retrying": "Ponovni pokušaj (pokušaj {{ attempt }})… {{ message }}",
|
||||
"session.status.working": "Radim…",
|
||||
"session.status.offline": "Mreža prekinuta — ponovno povezivanje...",
|
||||
"session.outcome.incomplete": "Potez završen sa {{count}} preostalih zadataka",
|
||||
"session.outcome.limit": "Ograničenje odgovora dosegnuto prije završetka",
|
||||
"session.outcome.unknown": "Potez završen bez razloga završetka modela",
|
||||
"session.outcome.filtered": "Provajder je zaustavio ovaj odgovor zbog filtera sadržaja.",
|
||||
"session.outcome.unexpected": "Odgovor je neočekivano završen i može biti nepotpun.",
|
||||
"session.outcome.interrupted": "Potez prekinut",
|
||||
"session.outcome.error": "Potez nije uspio",
|
||||
"session.outcome.finish": "Razlog završetka: {{reason}}",
|
||||
|
||||
"ui.sessionTurn.cancel": "Otkaži",
|
||||
"ui.sessionTurn.status.thinking": "Razmišljam...",
|
||||
@@ -1194,7 +1203,6 @@ export const dict = {
|
||||
'Telemetrija je kontrolisana ugrađenom postavkom za telemetriju u VS Code-u. Da biste je onemogućili, idite na Postavke > Telemetrija > Nivo telemetrije i postavite na "off". Ponovo pokrenite VS Code da biste primijenili promjenu.',
|
||||
"settings.aboutKiloCode.telemetry.openSettings": "Otvori postavke telemetrije",
|
||||
|
||||
"settings.agentBehaviour.subtab.modes": "Modovi",
|
||||
"settings.agentBehaviour.subtab.agents": "Agenti",
|
||||
"settings.agentBehaviour.subtab.mcpServers": "MCP serveri",
|
||||
"settings.agentBehaviour.subtab.rules": "Pravila",
|
||||
@@ -1309,7 +1317,7 @@ export const dict = {
|
||||
"settings.agentBehaviour.noSkillsFound":
|
||||
"Nisu pronađene vještine. Dodajte putanje mapa ili URL-ove ispod kako biste učinili vještine dostupnim.",
|
||||
"settings.agentBehaviour.availableModes": "Dostupni prilagođeni modovi",
|
||||
"settings.agentBehaviour.noModesFound": "Nisu pronađeni modovi.",
|
||||
"settings.agentBehaviour.noAgentsFound": "Nisu pronađeni agenti.",
|
||||
"settings.agentBehaviour.createMode": "Kreiraj novi mod",
|
||||
"settings.agentBehaviour.createMode.name": "Naziv",
|
||||
"settings.agentBehaviour.createMode.name.placeholder": "npr. reviewer",
|
||||
@@ -1353,10 +1361,10 @@ export const dict = {
|
||||
"settings.agentBehaviour.permissions.copy": "Kopiraj dozvole kao JSON",
|
||||
"settings.agentBehaviour.permissions.hint":
|
||||
"Pravila se evaluiraju po redoslijedu — zadnje pravilo koje se podudara pobjeđuje. Ovo je riješeni skup pravila iz CLI backenda.",
|
||||
"settings.agentBehaviour.removeMode.title": "Ukloni mod",
|
||||
"settings.agentBehaviour.removeMode.confirm":
|
||||
'Ukloniti mod "{{name}}"? Ovo će onemogućiti mod ažuriranjem vaše konfiguracije.',
|
||||
"settings.agentBehaviour.removeMode.button": "Ukloni",
|
||||
"settings.agentBehaviour.removeAgent.title": "Ukloni agenta",
|
||||
"settings.agentBehaviour.removeAgent.confirm":
|
||||
'Ukloniti agenta "{{name}}"? Ovo će ga onemogućiti ažuriranjem konfiguracije.',
|
||||
"settings.agentBehaviour.removeAgent.button": "Ukloni",
|
||||
"settings.agentBehaviour.removeMcp.title": "Ukloni MCP server",
|
||||
"settings.agentBehaviour.removeMcp.confirm":
|
||||
'Ukloniti MCP server "{{name}}"? Ovo će ga ukloniti iz vaše konfiguracije.',
|
||||
|
||||
+14
-6
@@ -451,6 +451,7 @@ export const dict = {
|
||||
"toast.session.unshare.failed.title": "Kunne ikke stoppe deling af session",
|
||||
"toast.session.unshare.failed.description": "Der opstod en fejl under stop af sessionsdeling",
|
||||
|
||||
"toast.session.rename.invalid.title": "Ugyldig sessionstitel",
|
||||
"toast.session.listFailed.title": "Kunne ikke indlæse sessioner for {{project}}",
|
||||
|
||||
"toast.update.title": "Opdatering tilgængelig",
|
||||
@@ -1124,6 +1125,14 @@ export const dict = {
|
||||
"session.status.retrying": "Prøver igen (forsøg {{ attempt }})… {{ message }}",
|
||||
"session.status.working": "Arbejder…",
|
||||
"session.status.offline": "Netværk afbrudt — genopretter forbindelse...",
|
||||
"session.outcome.incomplete": "Tur afsluttet, {{count}} to-dos tilbage",
|
||||
"session.outcome.limit": "Svarbegrænsning nået før fuldførelse",
|
||||
"session.outcome.unknown": "Tur afsluttet uden en model-afslutningsårsag",
|
||||
"session.outcome.filtered": "Udbyderen stoppede dette svar på grund af et indholdsfilter.",
|
||||
"session.outcome.unexpected": "Svaret sluttede uventet og kan være ufuldstændigt.",
|
||||
"session.outcome.interrupted": "Tur afbrudt",
|
||||
"session.outcome.error": "Tur mislykkedes",
|
||||
"session.outcome.finish": "Afslutningsårsag: {{reason}}",
|
||||
|
||||
"ui.sessionTurn.cancel": "Annuller",
|
||||
"ui.sessionTurn.status.thinking": "Tænker...",
|
||||
@@ -1187,7 +1196,6 @@ export const dict = {
|
||||
'Telemetri styres af VS Codes indbyggede telemetriindstilling. For at deaktivere den, gå til Indstillinger > Telemetry > Telemetry Level og sæt den til "off". Genstart VS Code for at anvende ændringen.',
|
||||
"settings.aboutKiloCode.telemetry.openSettings": "Åbn telemetriindstillinger",
|
||||
|
||||
"settings.agentBehaviour.subtab.modes": "Tilstande",
|
||||
"settings.agentBehaviour.subtab.agents": "Agenter",
|
||||
"settings.agentBehaviour.subtab.mcpServers": "MCP-servere",
|
||||
"settings.agentBehaviour.subtab.rules": "Regler",
|
||||
@@ -1301,7 +1309,7 @@ export const dict = {
|
||||
"settings.agentBehaviour.noSkillsFound":
|
||||
"Ingen skills fundet. Tilføj skill-mappestier eller URL'er nedenfor for at gøre skills tilgængelige.",
|
||||
"settings.agentBehaviour.availableModes": "Tilgængelige brugerdefinerede tilstande",
|
||||
"settings.agentBehaviour.noModesFound": "Ingen tilstande fundet.",
|
||||
"settings.agentBehaviour.noAgentsFound": "Ingen agenter fundet.",
|
||||
"settings.agentBehaviour.createMode": "Opret ny tilstand",
|
||||
"settings.agentBehaviour.createMode.name": "Navn",
|
||||
"settings.agentBehaviour.createMode.name.placeholder": "f.eks. reviewer",
|
||||
@@ -1344,10 +1352,10 @@ export const dict = {
|
||||
"settings.agentBehaviour.permissions.copy": "Kopiér tilladelser som JSON",
|
||||
"settings.agentBehaviour.permissions.hint":
|
||||
"Reglerne evalueres i rækkefølge — den sidst matchende regel vinder. Dette er det endelige regelsæt fra CLI-backenden.",
|
||||
"settings.agentBehaviour.removeMode.title": "Fjern tilstand",
|
||||
"settings.agentBehaviour.removeMode.confirm":
|
||||
'Vil du fjerne tilstanden "{{name}}"? Dette vil deaktivere tilstanden ved at opdatere din konfiguration.',
|
||||
"settings.agentBehaviour.removeMode.button": "Fjern",
|
||||
"settings.agentBehaviour.removeAgent.title": "Fjern agent",
|
||||
"settings.agentBehaviour.removeAgent.confirm":
|
||||
'Fjern agent "{{name}}"? Dette deaktiverer agenten ved at opdatere din konfiguration.',
|
||||
"settings.agentBehaviour.removeAgent.button": "Fjern",
|
||||
"settings.agentBehaviour.removeMcp.title": "Fjern MCP-server",
|
||||
"settings.agentBehaviour.removeMcp.confirm":
|
||||
'Vil du fjerne MCP-serveren "{{name}}"? Dette vil fjerne den fra din konfiguration.',
|
||||
|
||||
+14
-6
@@ -456,6 +456,7 @@ export const dict = {
|
||||
"toast.session.unshare.failed.title": "Aufheben des Teilens fehlgeschlagen",
|
||||
"toast.session.unshare.failed.description": "Beim Aufheben des Teilens ist ein Fehler aufgetreten",
|
||||
|
||||
"toast.session.rename.invalid.title": "Ungültiger Sitzungstitel",
|
||||
"toast.session.listFailed.title": "Sitzungen für {{project}} konnten nicht geladen werden",
|
||||
|
||||
"toast.update.title": "Update verfügbar",
|
||||
@@ -1139,6 +1140,14 @@ export const dict = {
|
||||
"session.status.retrying": "Erneuter Versuch ({{ attempt }})… {{ message }}",
|
||||
"session.status.working": "Wird bearbeitet…",
|
||||
"session.status.offline": "Netzwerk getrennt — Verbindung wird wiederhergestellt...",
|
||||
"session.outcome.incomplete": "Zug beendet mit {{count}} verbleibenden To-dos",
|
||||
"session.outcome.limit": "Antwortlimit vor Abschluss erreicht",
|
||||
"session.outcome.unknown": "Zug ohne Modell-Abschlussgrund beendet",
|
||||
"session.outcome.filtered": "Der Anbieter hat diese Antwort aufgrund eines Inhaltsfilters gestoppt.",
|
||||
"session.outcome.unexpected": "Die Antwort wurde unerwartet beendet und ist möglicherweise unvollständig.",
|
||||
"session.outcome.interrupted": "Zug unterbrochen",
|
||||
"session.outcome.error": "Zug fehlgeschlagen",
|
||||
"session.outcome.finish": "Abschlussgrund: {{reason}}",
|
||||
|
||||
"ui.sessionTurn.cancel": "Abbrechen",
|
||||
"ui.sessionTurn.status.thinking": "Denke nach...",
|
||||
@@ -1205,7 +1214,6 @@ export const dict = {
|
||||
'Die Telemetrie wird durch die integrierte Telemetrie-Einstellung von VS Code gesteuert. Um sie zu deaktivieren, gehen Sie zu Einstellungen > Telemetrie > Telemetrie-Stufe und setzen Sie diese auf "off". Starten Sie VS Code neu, um die Änderung zu übernehmen.',
|
||||
"settings.aboutKiloCode.telemetry.openSettings": "Telemetrie-Einstellungen öffnen",
|
||||
|
||||
"settings.agentBehaviour.subtab.modes": "Modi",
|
||||
"settings.agentBehaviour.subtab.agents": "Agenten",
|
||||
"settings.agentBehaviour.subtab.mcpServers": "MCP-Server",
|
||||
"settings.agentBehaviour.subtab.rules": "Regeln",
|
||||
@@ -1325,7 +1333,7 @@ export const dict = {
|
||||
"settings.agentBehaviour.noSkillsFound":
|
||||
"Keine Skills gefunden. Fügen Sie unten Skill-Ordnerpfade oder URLs hinzu, um Skills verfügbar zu machen.",
|
||||
"settings.agentBehaviour.availableModes": "Verfügbare benutzerdefinierte Modi",
|
||||
"settings.agentBehaviour.noModesFound": "Keine Modi gefunden.",
|
||||
"settings.agentBehaviour.noAgentsFound": "Keine Agenten gefunden.",
|
||||
"settings.agentBehaviour.createMode": "Neuen Modus erstellen",
|
||||
"settings.agentBehaviour.createMode.name": "Name",
|
||||
"settings.agentBehaviour.createMode.name.placeholder": "z.B. reviewer",
|
||||
@@ -1370,10 +1378,10 @@ export const dict = {
|
||||
"settings.agentBehaviour.permissions.copy": "Berechtigungen als JSON kopieren",
|
||||
"settings.agentBehaviour.permissions.hint":
|
||||
"Regeln werden der Reihe nach ausgewertet — die letzte übereinstimmende Regel gewinnt. Dies ist das aufgelöste Regelwerk vom CLI-Backend.",
|
||||
"settings.agentBehaviour.removeMode.title": "Modus entfernen",
|
||||
"settings.agentBehaviour.removeMode.confirm":
|
||||
'Modus "{{name}}" entfernen? Dadurch wird der Modus durch Aktualisierung Ihrer Konfiguration deaktiviert.',
|
||||
"settings.agentBehaviour.removeMode.button": "Entfernen",
|
||||
"settings.agentBehaviour.removeAgent.title": "Agent entfernen",
|
||||
"settings.agentBehaviour.removeAgent.confirm":
|
||||
'Agent "{{name}}" entfernen? Dies deaktiviert den Agenten durch Aktualisierung der Konfiguration.',
|
||||
"settings.agentBehaviour.removeAgent.button": "Entfernen",
|
||||
"settings.agentBehaviour.removeMcp.title": "MCP-Server entfernen",
|
||||
"settings.agentBehaviour.removeMcp.confirm":
|
||||
'MCP-Server "{{name}}" entfernen? Dadurch wird er aus Ihrer Konfiguration entfernt.',
|
||||
|
||||
@@ -451,6 +451,7 @@ export const dict = {
|
||||
"toast.session.unshare.failed.title": "Failed to unshare session",
|
||||
"toast.session.unshare.failed.description": "An error occurred while unsharing the session",
|
||||
|
||||
"toast.session.rename.invalid.title": "Invalid session title",
|
||||
"toast.session.listFailed.title": "Failed to load sessions for {{project}}",
|
||||
|
||||
"toast.update.title": "Update available",
|
||||
@@ -1079,6 +1080,14 @@ export const dict = {
|
||||
"session.status.retrying": "Retrying (attempt {{ attempt }})… {{ message }}",
|
||||
"session.status.working": "Working...",
|
||||
"session.status.offline": "Network disconnected — reconnecting...",
|
||||
"session.outcome.incomplete": "Turn ended with {{count}} to-dos remaining.",
|
||||
"session.outcome.limit": "Response reached its output limit and may be incomplete.",
|
||||
"session.outcome.unknown": "Response ended without a finish reason and may be incomplete.",
|
||||
"session.outcome.filtered": "The provider stopped this response because of a content filter.",
|
||||
"session.outcome.unexpected": "Response ended unexpectedly and may be incomplete.",
|
||||
"session.outcome.interrupted": "Turn interrupted.",
|
||||
"session.outcome.error": "Turn failed.",
|
||||
"session.outcome.finish": "Technical finish reason: {{reason}}",
|
||||
"sidebar.session.newSession": "New Session",
|
||||
"sidebar.session.newSession.tooltip": "Start a fresh conversation while keeping the current session intact.",
|
||||
"sidebar.session.newSession.disabled": "This session is already new. Start chatting or create a worktree instead.",
|
||||
@@ -1170,7 +1179,6 @@ export const dict = {
|
||||
'Telemetry is controlled by VS Code\'s built-in telemetry setting. To disable it, go to Settings > Telemetry > Telemetry Level and set it to "off". Restart VS Code to apply the change.',
|
||||
"settings.aboutKiloCode.telemetry.openSettings": "Open Telemetry Settings",
|
||||
|
||||
"settings.agentBehaviour.subtab.modes": "Modes",
|
||||
"settings.agentBehaviour.subtab.agents": "Agents",
|
||||
"settings.agentBehaviour.subtab.mcpServers": "MCP Servers",
|
||||
"settings.agentBehaviour.subtab.rules": "Rules",
|
||||
@@ -1289,11 +1297,11 @@ export const dict = {
|
||||
"settings.agentBehaviour.noSkillsFound":
|
||||
"No skills discovered. Add skill folder paths or URLs below to make skills available.",
|
||||
"settings.agentBehaviour.availableModes": "Available Custom Modes",
|
||||
"settings.agentBehaviour.noModesFound": "No modes found.",
|
||||
"settings.agentBehaviour.removeMode.title": "Remove mode",
|
||||
"settings.agentBehaviour.removeMode.confirm":
|
||||
'Remove mode "{{name}}"? This will disable the mode by updating your config.',
|
||||
"settings.agentBehaviour.removeMode.button": "Remove",
|
||||
"settings.agentBehaviour.noAgentsFound": "No agents found.",
|
||||
"settings.agentBehaviour.removeAgent.title": "Remove agent",
|
||||
"settings.agentBehaviour.removeAgent.confirm":
|
||||
'Remove agent "{{name}}"? This will disable the agent by updating your config.',
|
||||
"settings.agentBehaviour.removeAgent.button": "Remove",
|
||||
"settings.agentBehaviour.skillPaths": "Skill Folder Paths",
|
||||
"settings.agentBehaviour.skillUrls": "Skill URLs",
|
||||
"settings.agentBehaviour.removeSkill.title": "Remove skill",
|
||||
|
||||
+14
-6
@@ -454,6 +454,7 @@ export const dict = {
|
||||
"toast.session.unshare.failed.title": "Fallo al dejar de compartir sesión",
|
||||
"toast.session.unshare.failed.description": "Ocurrió un error al dejar de compartir la sesión",
|
||||
|
||||
"toast.session.rename.invalid.title": "Título de sesión no válido",
|
||||
"toast.session.listFailed.title": "Fallo al cargar sesiones para {{project}}",
|
||||
|
||||
"toast.update.title": "Actualización disponible",
|
||||
@@ -1135,6 +1136,14 @@ export const dict = {
|
||||
"session.status.retrying": "Reintentando (intento {{ attempt }})… {{ message }}",
|
||||
"session.status.working": "Trabajando…",
|
||||
"session.status.offline": "Red desconectada — reconectando...",
|
||||
"session.outcome.incomplete": "Turno finalizado con {{count}} tareas pendientes",
|
||||
"session.outcome.limit": "Límite de respuesta alcanzado antes de finalizar",
|
||||
"session.outcome.unknown": "Turno finalizado sin motivo de finalización del modelo",
|
||||
"session.outcome.filtered": "El proveedor detuvo esta respuesta debido a un filtro de contenido.",
|
||||
"session.outcome.unexpected": "La respuesta terminó inesperadamente y puede estar incompleta.",
|
||||
"session.outcome.interrupted": "Turno interrumpido",
|
||||
"session.outcome.error": "Turno fallido",
|
||||
"session.outcome.finish": "Motivo de finalización: {{reason}}",
|
||||
|
||||
"ui.sessionTurn.cancel": "Cancelar",
|
||||
"ui.sessionTurn.status.thinking": "Pensando...",
|
||||
@@ -1199,7 +1208,6 @@ export const dict = {
|
||||
'La telemetría está controlada por la configuración de telemetría integrada de VS Code. Para desactivarla, ve a Configuración > Telemetría > Nivel de telemetría y establécelo en "off". Reinicia VS Code para aplicar el cambio.',
|
||||
"settings.aboutKiloCode.telemetry.openSettings": "Abrir configuración de telemetría",
|
||||
|
||||
"settings.agentBehaviour.subtab.modes": "Modos",
|
||||
"settings.agentBehaviour.subtab.agents": "Agentes",
|
||||
"settings.agentBehaviour.subtab.mcpServers": "Servidores MCP",
|
||||
"settings.agentBehaviour.subtab.rules": "Reglas",
|
||||
@@ -1316,7 +1324,7 @@ export const dict = {
|
||||
"settings.agentBehaviour.noSkillsFound":
|
||||
"No se encontraron habilidades. Agregue rutas de carpetas o URLs abajo para hacer disponibles las habilidades.",
|
||||
"settings.agentBehaviour.availableModes": "Modos personalizados disponibles",
|
||||
"settings.agentBehaviour.noModesFound": "No se encontraron modos.",
|
||||
"settings.agentBehaviour.noAgentsFound": "No se encontraron agentes.",
|
||||
"settings.agentBehaviour.createMode": "Crear nuevo modo",
|
||||
"settings.agentBehaviour.createMode.name": "Nombre",
|
||||
"settings.agentBehaviour.createMode.name.placeholder": "ej. reviewer",
|
||||
@@ -1362,10 +1370,10 @@ export const dict = {
|
||||
"settings.agentBehaviour.permissions.copy": "Copiar permisos como JSON",
|
||||
"settings.agentBehaviour.permissions.hint":
|
||||
"Las reglas se evalúan en orden — gana la última regla coincidente. Este es el conjunto de reglas resuelto desde el backend de la CLI.",
|
||||
"settings.agentBehaviour.removeMode.title": "Eliminar modo",
|
||||
"settings.agentBehaviour.removeMode.confirm":
|
||||
'¿Eliminar el modo "{{name}}"? Esto desactivará el modo actualizando su configuración.',
|
||||
"settings.agentBehaviour.removeMode.button": "Eliminar",
|
||||
"settings.agentBehaviour.removeAgent.title": "Eliminar agente",
|
||||
"settings.agentBehaviour.removeAgent.confirm":
|
||||
'¿Eliminar agente "{{name}}"? Esto lo desactivará actualizando tu configuración.',
|
||||
"settings.agentBehaviour.removeAgent.button": "Eliminar",
|
||||
"settings.agentBehaviour.removeMcp.title": "Eliminar servidor MCP",
|
||||
"settings.agentBehaviour.removeMcp.confirm":
|
||||
'¿Eliminar el servidor MCP "{{name}}"? Esto lo eliminará de su configuración.',
|
||||
|
||||
+14
-6
@@ -457,6 +457,7 @@ export const dict = {
|
||||
"toast.session.unshare.failed.title": "Échec de l'annulation du partage",
|
||||
"toast.session.unshare.failed.description": "Une erreur s'est produite lors de l'annulation du partage de la session",
|
||||
|
||||
"toast.session.rename.invalid.title": "Titre de session non valide",
|
||||
"toast.session.listFailed.title": "Échec du chargement des sessions pour {{project}}",
|
||||
|
||||
"toast.update.title": "Mise à jour disponible",
|
||||
@@ -1143,6 +1144,14 @@ export const dict = {
|
||||
"session.status.retrying": "Nouvelle tentative (essai {{ attempt }})… {{ message }}",
|
||||
"session.status.working": "En cours…",
|
||||
"session.status.offline": "Réseau déconnecté — reconnexion en cours...",
|
||||
"session.outcome.incomplete": "Tour terminé avec {{count}} tâches restantes",
|
||||
"session.outcome.limit": "Limite de réponse atteinte avant la fin",
|
||||
"session.outcome.unknown": "Tour terminé sans motif de fin du modèle",
|
||||
"session.outcome.filtered": "Le fournisseur a arrêté cette réponse en raison d'un filtre de contenu.",
|
||||
"session.outcome.unexpected": "La réponse s'est terminée de manière inattendue et peut être incomplète.",
|
||||
"session.outcome.interrupted": "Tour interrompu",
|
||||
"session.outcome.error": "Échec du tour",
|
||||
"session.outcome.finish": "Motif de fin : {{reason}}",
|
||||
|
||||
"ui.sessionTurn.cancel": "Annuler",
|
||||
"ui.sessionTurn.status.thinking": "Réflexion...",
|
||||
@@ -1209,7 +1218,6 @@ export const dict = {
|
||||
'La télémétrie est contrôlée par le paramètre de télémétrie intégré de VS Code. Pour la désactiver, allez dans Paramètres > Télémétrie > Niveau de télémétrie et réglez-le sur "off". Redémarrez VS Code pour appliquer la modification.',
|
||||
"settings.aboutKiloCode.telemetry.openSettings": "Ouvrir les paramètres de télémétrie",
|
||||
|
||||
"settings.agentBehaviour.subtab.modes": "Modes",
|
||||
"settings.agentBehaviour.subtab.agents": "Agents",
|
||||
"settings.agentBehaviour.subtab.mcpServers": "Serveurs MCP",
|
||||
"settings.agentBehaviour.subtab.rules": "Règles",
|
||||
@@ -1329,7 +1337,7 @@ export const dict = {
|
||||
"settings.agentBehaviour.noSkillsFound":
|
||||
"Aucune compétence découverte. Ajoutez des chemins de dossiers ou des URLs ci-dessous pour rendre les compétences disponibles.",
|
||||
"settings.agentBehaviour.availableModes": "Modes personnalisés disponibles",
|
||||
"settings.agentBehaviour.noModesFound": "Aucun mode trouvé.",
|
||||
"settings.agentBehaviour.noAgentsFound": "Aucun agent trouvé.",
|
||||
"settings.agentBehaviour.createMode": "Créer un nouveau mode",
|
||||
"settings.agentBehaviour.createMode.name": "Nom",
|
||||
"settings.agentBehaviour.createMode.name.placeholder": "ex : reviewer",
|
||||
@@ -1376,10 +1384,10 @@ export const dict = {
|
||||
"settings.agentBehaviour.permissions.copy": "Copier les permissions en JSON",
|
||||
"settings.agentBehaviour.permissions.hint":
|
||||
"Les règles sont évaluées dans l'ordre — la dernière règle correspondante l'emporte. Il s'agit de l'ensemble de règles résolu depuis le backend CLI.",
|
||||
"settings.agentBehaviour.removeMode.title": "Supprimer le mode",
|
||||
"settings.agentBehaviour.removeMode.confirm":
|
||||
'Supprimer le mode "{{name}}" ? Cela désactivera le mode en mettant à jour votre configuration.',
|
||||
"settings.agentBehaviour.removeMode.button": "Supprimer",
|
||||
"settings.agentBehaviour.removeAgent.title": "Supprimer l'agent",
|
||||
"settings.agentBehaviour.removeAgent.confirm":
|
||||
"Supprimer l'agent \"{{name}}\" ? Cela désactivera l'agent en mettant à jour votre configuration.",
|
||||
"settings.agentBehaviour.removeAgent.button": "Supprimer",
|
||||
"settings.agentBehaviour.removeMcp.title": "Supprimer le serveur MCP",
|
||||
"settings.agentBehaviour.removeMcp.confirm":
|
||||
'Supprimer le serveur MCP "{{name}}" ? Cela le supprimera de votre configuration.',
|
||||
|
||||
+14
-6
@@ -448,6 +448,7 @@ export const dict = {
|
||||
"toast.session.unshare.failed.title": "セッションの共有解除に失敗しました",
|
||||
"toast.session.unshare.failed.description": "セッションの共有解除中にエラーが発生しました",
|
||||
|
||||
"toast.session.rename.invalid.title": "無効なセッションタイトル",
|
||||
"toast.session.listFailed.title": "{{project}}のセッション読み込みに失敗しました",
|
||||
|
||||
"toast.update.title": "アップデートが利用可能です",
|
||||
@@ -1119,6 +1120,14 @@ export const dict = {
|
||||
"session.status.retrying": "再試行中({{ attempt }}回目)… {{ message }}",
|
||||
"session.status.working": "作業中…",
|
||||
"session.status.offline": "ネットワークが切断されました — 再接続中…",
|
||||
"session.outcome.incomplete": "{{count}} 個の To-Do を残してターンが終了しました",
|
||||
"session.outcome.limit": "完了前に応答制限に達しました",
|
||||
"session.outcome.unknown": "モデルの終了理由なしでターンが終了しました",
|
||||
"session.outcome.filtered": "コンテンツフィルターにより、プロバイダーがこの応答を停止しました。",
|
||||
"session.outcome.unexpected": "応答が予期せず終了したため、不完全である可能性があります。",
|
||||
"session.outcome.interrupted": "ターンが中断されました",
|
||||
"session.outcome.error": "ターンが失敗しました",
|
||||
"session.outcome.finish": "終了理由: {{reason}}",
|
||||
|
||||
"ui.sessionTurn.cancel": "キャンセル",
|
||||
"ui.sessionTurn.status.thinking": "考え中...",
|
||||
@@ -1183,7 +1192,6 @@ export const dict = {
|
||||
"テレメトリは VS Code の組み込みテレメトリ設定によって制御されます。無効にするには、設定 > テレメトリ > Telemetry Level に移動して「off」に設定してください。変更を適用するには、VS Code を再起動してください。",
|
||||
"settings.aboutKiloCode.telemetry.openSettings": "テレメトリ設定を開く",
|
||||
|
||||
"settings.agentBehaviour.subtab.modes": "モード",
|
||||
"settings.agentBehaviour.subtab.agents": "エージェント",
|
||||
"settings.agentBehaviour.subtab.mcpServers": "MCPサーバー",
|
||||
"settings.agentBehaviour.subtab.rules": "ルール",
|
||||
@@ -1296,7 +1304,7 @@ export const dict = {
|
||||
"settings.agentBehaviour.noSkillsFound":
|
||||
"スキルが見つかりません。スキルを利用可能にするには、以下にスキルフォルダパスまたはURLを追加してください。",
|
||||
"settings.agentBehaviour.availableModes": "利用可能なカスタムモード",
|
||||
"settings.agentBehaviour.noModesFound": "モードが見つかりません。",
|
||||
"settings.agentBehaviour.noAgentsFound": "エージェントが見つかりません。",
|
||||
"settings.agentBehaviour.createMode": "新しいモードを作成",
|
||||
"settings.agentBehaviour.createMode.name": "名前",
|
||||
"settings.agentBehaviour.createMode.name.placeholder": "例: reviewer",
|
||||
@@ -1341,10 +1349,10 @@ export const dict = {
|
||||
"settings.agentBehaviour.permissions.copy": "権限をJSONとしてコピー",
|
||||
"settings.agentBehaviour.permissions.hint":
|
||||
"ルールは順番に評価され、最後に一致したルールが適用されます。これはCLIバックエンドから解決されたルールセットです。",
|
||||
"settings.agentBehaviour.removeMode.title": "モードを削除",
|
||||
"settings.agentBehaviour.removeMode.confirm":
|
||||
'モード "{{name}}" を削除しますか?設定を更新してモードを無効にします。',
|
||||
"settings.agentBehaviour.removeMode.button": "削除",
|
||||
"settings.agentBehaviour.removeAgent.title": "エージェントを削除",
|
||||
"settings.agentBehaviour.removeAgent.confirm":
|
||||
'エージェント "{{name}}" を削除しますか?設定を更新してエージェントを無効にします。',
|
||||
"settings.agentBehaviour.removeAgent.button": "削除",
|
||||
"settings.agentBehaviour.removeMcp.title": "MCPサーバーを削除",
|
||||
"settings.agentBehaviour.removeMcp.confirm": 'MCPサーバー "{{name}}" を削除しますか?設定から削除されます。',
|
||||
"settings.agentBehaviour.removeMcp.button": "削除",
|
||||
|
||||
+14
-6
@@ -450,6 +450,7 @@ export const dict = {
|
||||
"toast.session.unshare.failed.title": "세션 공유 해제 실패",
|
||||
"toast.session.unshare.failed.description": "세션 공유를 해제하는 동안 오류가 발생했습니다",
|
||||
|
||||
"toast.session.rename.invalid.title": "잘못된 세션 제목",
|
||||
"toast.session.listFailed.title": "{{project}}에 대한 세션을 로드하지 못했습니다",
|
||||
|
||||
"toast.update.title": "업데이트 가능",
|
||||
@@ -1116,6 +1117,14 @@ export const dict = {
|
||||
"session.status.retrying": "재시도 중 ({{ attempt }}번째 시도)… {{ message }}",
|
||||
"session.status.working": "작업 중...",
|
||||
"session.status.offline": "네트워크 연결 끊김 — 다시 연결 중...",
|
||||
"session.outcome.incomplete": "턴이 종료되었으며 {{count}}개의 할 일이 남았습니다",
|
||||
"session.outcome.limit": "완료 전에 응답 제한에 도달했습니다",
|
||||
"session.outcome.unknown": "모델의 종료 이유 없이 턴이 종료되었습니다",
|
||||
"session.outcome.filtered": "콘텐츠 필터로 인해 제공자가 이 응답을 중단했습니다.",
|
||||
"session.outcome.unexpected": "응답이 예기치 않게 종료되었으며 불완전할 수 있습니다.",
|
||||
"session.outcome.interrupted": "턴이 중단되었습니다",
|
||||
"session.outcome.error": "턴이 실패했습니다",
|
||||
"session.outcome.finish": "종료 이유: {{reason}}",
|
||||
|
||||
"ui.sessionTurn.cancel": "취소",
|
||||
"ui.sessionTurn.status.thinking": "생각 중...",
|
||||
@@ -1178,7 +1187,6 @@ export const dict = {
|
||||
'원격 측정은 VS Code에 내장된 원격 측정 설정으로 제어됩니다. 비활성화하려면 설정 > 원격 측정 > 원격 측정 수준으로 이동하여 "off"로 설정하세요. 변경 사항을 적용하려면 VS Code를 다시 시작하세요.',
|
||||
"settings.aboutKiloCode.telemetry.openSettings": "원격 측정 설정 열기",
|
||||
|
||||
"settings.agentBehaviour.subtab.modes": "모드",
|
||||
"settings.agentBehaviour.subtab.agents": "에이전트",
|
||||
"settings.agentBehaviour.subtab.mcpServers": "MCP 서버",
|
||||
"settings.agentBehaviour.subtab.rules": "규칙",
|
||||
@@ -1290,7 +1298,7 @@ export const dict = {
|
||||
"settings.agentBehaviour.noSkillsFound":
|
||||
"스킬을 찾을 수 없습니다. 스킬을 사용하려면 아래에 스킬 폴더 경로 또는 URL을 추가하세요.",
|
||||
"settings.agentBehaviour.availableModes": "사용 가능한 사용자 정의 모드",
|
||||
"settings.agentBehaviour.noModesFound": "모드를 찾을 수 없습니다.",
|
||||
"settings.agentBehaviour.noAgentsFound": "에이전트를 찾을 수 없습니다.",
|
||||
"settings.agentBehaviour.createMode": "새 모드 만들기",
|
||||
"settings.agentBehaviour.createMode.name": "이름",
|
||||
"settings.agentBehaviour.createMode.name.placeholder": "예: reviewer",
|
||||
@@ -1332,10 +1340,10 @@ export const dict = {
|
||||
"settings.agentBehaviour.permissions.copy": "권한을 JSON으로 복사",
|
||||
"settings.agentBehaviour.permissions.hint":
|
||||
"규칙은 순서대로 평가되며, 마지막에 일치하는 규칙이 적용됩니다. 이것은 CLI 백엔드에서 확인된 규칙 세트입니다.",
|
||||
"settings.agentBehaviour.removeMode.title": "모드 제거",
|
||||
"settings.agentBehaviour.removeMode.confirm":
|
||||
'모드 "{{name}}"을(를) 제거하시겠습니까? 구성을 업데이트하여 모드를 비활성화합니다.',
|
||||
"settings.agentBehaviour.removeMode.button": "제거",
|
||||
"settings.agentBehaviour.removeAgent.title": "에이전트 제거",
|
||||
"settings.agentBehaviour.removeAgent.confirm":
|
||||
'에이전트 "{{name}}"을(를) 제거하시겠습니까? 구성을 업데이트하여 에이전트를 비활성화합니다.',
|
||||
"settings.agentBehaviour.removeAgent.button": "제거",
|
||||
"settings.agentBehaviour.removeMcp.title": "MCP 서버 제거",
|
||||
"settings.agentBehaviour.removeMcp.confirm": 'MCP 서버 "{{name}}"을(를) 제거하시겠습니까? 구성에서 제거됩니다.',
|
||||
"settings.agentBehaviour.removeMcp.button": "제거",
|
||||
|
||||
+14
-6
@@ -454,6 +454,7 @@ export const dict = {
|
||||
"toast.session.unshare.success.description": "Delen van sessie succesvol gestopt!",
|
||||
"toast.session.unshare.failed.title": "Delen van sessie stoppen mislukt",
|
||||
"toast.session.unshare.failed.description": "Er is een fout opgetreden bij het stoppen van het delen van de sessie",
|
||||
"toast.session.rename.invalid.title": "Ongeldige sessietitel",
|
||||
"toast.session.listFailed.title": "Laden van sessies voor {{project}} is mislukt",
|
||||
|
||||
"toast.update.title": "Update beschikbaar",
|
||||
@@ -1119,6 +1120,14 @@ export const dict = {
|
||||
"session.status.retrying": "Opnieuw proberen (poging {{ attempt }})... {{ message }}",
|
||||
"session.status.working": "Bezig...",
|
||||
"session.status.offline": "Netwerkverbinding verbroken — opnieuw verbinden...",
|
||||
"session.outcome.incomplete": "Beurt beëindigd met {{count}} resterende to-do's",
|
||||
"session.outcome.limit": "Antwoordlimiet bereikt voor voltooiing",
|
||||
"session.outcome.unknown": "Beurt beëindigd zonder voltooiingsreden van het model",
|
||||
"session.outcome.filtered": "De provider heeft deze reactie gestopt vanwege een contentfilter.",
|
||||
"session.outcome.unexpected": "Reactie is onverwacht beëindigd en is mogelijk onvolledig.",
|
||||
"session.outcome.interrupted": "Beurt onderbroken",
|
||||
"session.outcome.error": "Beurt mislukt",
|
||||
"session.outcome.finish": "Voltooiingsreden: {{reason}}",
|
||||
|
||||
"ui.sessionTurn.cancel": "Annuleren",
|
||||
"ui.sessionTurn.status.thinking": "Denken...",
|
||||
@@ -1184,7 +1193,6 @@ export const dict = {
|
||||
'Telemetrie wordt beheerd door de ingebouwde telemetrie-instelling van VS Code. Om dit uit te schakelen, gaat u naar Instellingen > Telemetrie > Telemetrieniveau en stelt u dit in op "off". Herstart VS Code om de wijziging toe te passen.',
|
||||
"settings.aboutKiloCode.telemetry.openSettings": "Telemetrie-instellingen openen",
|
||||
|
||||
"settings.agentBehaviour.subtab.modes": "Modi",
|
||||
"settings.agentBehaviour.subtab.agents": "Agenten",
|
||||
"settings.agentBehaviour.subtab.mcpServers": "MCP Servers",
|
||||
"settings.agentBehaviour.subtab.rules": "Regels",
|
||||
@@ -1306,7 +1314,7 @@ export const dict = {
|
||||
"settings.agentBehaviour.noSkillsFound":
|
||||
"Geen skills ontdekt. Voeg hieronder skill mappaden of URL's toe om skills beschikbaar te maken.",
|
||||
"settings.agentBehaviour.availableModes": "Beschikbare Aangepaste Modi",
|
||||
"settings.agentBehaviour.noModesFound": "Geen modi gevonden.",
|
||||
"settings.agentBehaviour.noAgentsFound": "Geen agenten gevonden.",
|
||||
"settings.agentBehaviour.importMode": "Importeren",
|
||||
"settings.agentBehaviour.importMode.invalidName":
|
||||
"Ongeldige modusnaam in bestand. De naam moet beginnen met een kleine letter en mag alleen kleine letters, cijfers en streepjes bevatten.",
|
||||
@@ -1315,10 +1323,10 @@ export const dict = {
|
||||
"Ongeldig JSON-bestand. Selecteer een geldig agentdefinitiebestand.",
|
||||
"settings.agentBehaviour.importMode.tooLarge": "Bestand is te groot. Agentdefinities moeten kleiner zijn dan 1 MB.",
|
||||
"settings.agentBehaviour.exportMode": "Agentdefinitie exporteren",
|
||||
"settings.agentBehaviour.removeMode.title": "Verwijder modus",
|
||||
"settings.agentBehaviour.removeMode.confirm":
|
||||
'Modus "{{name}}" verwijderen? Dit zal de modus uitschakelen door je configuratie bij te werken.',
|
||||
"settings.agentBehaviour.removeMode.button": "Verwijderen",
|
||||
"settings.agentBehaviour.removeAgent.title": "Verwijder agent",
|
||||
"settings.agentBehaviour.removeAgent.confirm":
|
||||
'Agent "{{name}}" verwijderen? Dit schakelt de agent uit door uw configuratie bij te werken.',
|
||||
"settings.agentBehaviour.removeAgent.button": "Verwijderen",
|
||||
"settings.agentBehaviour.skillPaths": "Skill Mappaden",
|
||||
"settings.agentBehaviour.skillUrls": "Skill URL's",
|
||||
"settings.agentBehaviour.removeSkill.title": "Verwijder skill",
|
||||
|
||||
+14
-6
@@ -454,6 +454,7 @@ export const dict = {
|
||||
"toast.session.unshare.failed.title": "Kunne ikke stoppe deling av sesjon",
|
||||
"toast.session.unshare.failed.description": "Det oppstod en feil da delingen av sesjonen skulle stoppes",
|
||||
|
||||
"toast.session.rename.invalid.title": "Ugyldig sesjonstittel",
|
||||
"toast.session.listFailed.title": "Kunne ikke laste sesjoner for {{project}}",
|
||||
|
||||
"toast.update.title": "Oppdatering tilgjengelig",
|
||||
@@ -1091,6 +1092,14 @@ export const dict = {
|
||||
"session.status.retrying": "Prøver på nytt (forsøk {{ attempt }})… {{ message }}",
|
||||
"session.status.working": "Arbeider…",
|
||||
"session.status.offline": "Nettverk frakoblet — kobler til på nytt...",
|
||||
"session.outcome.incomplete": "Runden ble avsluttet med {{count}} oppgaver igjen",
|
||||
"session.outcome.limit": "Svarsgrensen ble nådd før fullføring",
|
||||
"session.outcome.unknown": "Runden ble avsluttet uten avslutningsårsak fra modellen",
|
||||
"session.outcome.filtered": "Leverandøren stoppet denne responsen på grunn av et innholdsfilter.",
|
||||
"session.outcome.unexpected": "Responsen ble avsluttet uventet og kan være ufullstendig.",
|
||||
"session.outcome.interrupted": "Runde avbrutt",
|
||||
"session.outcome.error": "Runden feilet",
|
||||
"session.outcome.finish": "Avslutningsårsak: {{reason}}",
|
||||
|
||||
"ui.sessionTurn.cancel": "Avbryt",
|
||||
"ui.sessionTurn.status.thinking": "Tenker...",
|
||||
@@ -1153,7 +1162,6 @@ export const dict = {
|
||||
'Telemetri styres av den innebygde telemetri-innstillingen i VS Code. For å deaktivere den, gå til Innstillinger > Telemetry > Telemetry Level og sett den til "off". Start VS Code på nytt for å ta i bruk endringen.',
|
||||
"settings.aboutKiloCode.telemetry.openSettings": "Åpne innstillinger for telemetri",
|
||||
|
||||
"settings.agentBehaviour.subtab.modes": "Moduser",
|
||||
"settings.agentBehaviour.subtab.agents": "Agenter",
|
||||
"settings.agentBehaviour.subtab.mcpServers": "MCP-servere",
|
||||
"settings.agentBehaviour.subtab.rules": "Regler",
|
||||
@@ -1301,7 +1309,7 @@ export const dict = {
|
||||
"settings.agentBehaviour.noSkillsFound":
|
||||
"Ingen ferdigheter funnet. Legg til ferdighetsmappestier eller URLer nedenfor for å gjøre ferdigheter tilgjengelige.",
|
||||
"settings.agentBehaviour.availableModes": "Tilgjengelige egendefinerte moduser",
|
||||
"settings.agentBehaviour.noModesFound": "Ingen moduser funnet.",
|
||||
"settings.agentBehaviour.noAgentsFound": "Ingen agenter funnet.",
|
||||
"settings.agentBehaviour.createMode": "Opprett ny modus",
|
||||
"settings.agentBehaviour.createMode.name": "Navn",
|
||||
"settings.agentBehaviour.createMode.name.placeholder": "f.eks. reviewer",
|
||||
@@ -1344,10 +1352,10 @@ export const dict = {
|
||||
"settings.agentBehaviour.permissions.copy": "Kopier tillatelser som JSON",
|
||||
"settings.agentBehaviour.permissions.hint":
|
||||
"Reglene evalueres i rekkefølge — siste matchende regel vinner. Dette er det gjeldende regelsettet fra CLI-backenden.",
|
||||
"settings.agentBehaviour.removeMode.title": "Fjern modus",
|
||||
"settings.agentBehaviour.removeMode.confirm":
|
||||
'Vil du fjerne modusen "{{name}}"? Dette vil deaktivere modusen ved å oppdatere konfigurasjonen din.',
|
||||
"settings.agentBehaviour.removeMode.button": "Fjern",
|
||||
"settings.agentBehaviour.removeAgent.title": "Fjern agent",
|
||||
"settings.agentBehaviour.removeAgent.confirm":
|
||||
'Fjern agent "{{name}}"? Dette deaktiverer agenten ved å oppdatere konfigurasjonen din.',
|
||||
"settings.agentBehaviour.removeAgent.button": "Fjern",
|
||||
"settings.agentBehaviour.removeMcp.title": "Fjern MCP-server",
|
||||
"settings.agentBehaviour.removeMcp.confirm":
|
||||
'Vil du fjerne MCP-serveren "{{name}}"? Dette vil fjerne den fra konfigurasjonen din.',
|
||||
|
||||
+14
-6
@@ -452,6 +452,7 @@ export const dict = {
|
||||
"toast.session.unshare.failed.title": "Nie udało się zatrzymać udostępniania sesji",
|
||||
"toast.session.unshare.failed.description": "Wystąpił błąd podczas zatrzymywania udostępniania sesji",
|
||||
|
||||
"toast.session.rename.invalid.title": "Nieprawidłowy tytuł sesji",
|
||||
"toast.session.listFailed.title": "Nie udało się załadować sesji dla {{project}}",
|
||||
|
||||
"toast.update.title": "Dostępna aktualizacja",
|
||||
@@ -1090,6 +1091,14 @@ export const dict = {
|
||||
"session.status.retrying": "Ponawiam próbę ({{ attempt }})… {{ message }}",
|
||||
"session.status.working": "Pracuję…",
|
||||
"session.status.offline": "Odłączono od sieci — ponowne łączenie...",
|
||||
"session.outcome.incomplete": "Tura zakończona, pozostało {{count}} to-dos",
|
||||
"session.outcome.limit": "Osiągnięto limit odpowiedzi przed ukończeniem",
|
||||
"session.outcome.unknown": "Tura zakończona bez powodu zakończenia od modelu",
|
||||
"session.outcome.filtered": "Dostawca zatrzymał tę odpowiedź z powodu filtru treści.",
|
||||
"session.outcome.unexpected": "Odpowiedź zakończyła się nieoczekiwanie i może być niekompletna.",
|
||||
"session.outcome.interrupted": "Tura przerwana",
|
||||
"session.outcome.error": "Tura nie powiodła się",
|
||||
"session.outcome.finish": "Powód zakończenia: {{reason}}",
|
||||
|
||||
"ui.sessionTurn.cancel": "Anuluj",
|
||||
"ui.sessionTurn.status.thinking": "Myślę...",
|
||||
@@ -1153,7 +1162,6 @@ export const dict = {
|
||||
'Telemetria jest kontrolowana przez wbudowane ustawienie telemetrii VS Code. Aby ją wyłączyć, przejdź do Ustawienia > Telemetria > Poziom telemetrii i ustaw na "off". Uruchom ponownie VS Code, aby zastosować zmianę.',
|
||||
"settings.aboutKiloCode.telemetry.openSettings": "Otwórz ustawienia telemetrii",
|
||||
|
||||
"settings.agentBehaviour.subtab.modes": "Tryby",
|
||||
"settings.agentBehaviour.subtab.agents": "Agenci",
|
||||
"settings.agentBehaviour.subtab.mcpServers": "Serwery MCP",
|
||||
"settings.agentBehaviour.subtab.rules": "Reguły",
|
||||
@@ -1302,7 +1310,7 @@ export const dict = {
|
||||
"settings.agentBehaviour.noSkillsFound":
|
||||
"Nie znaleziono umiejętności. Dodaj ścieżki folderów lub adresy URL poniżej, aby udostępnić umiejętności.",
|
||||
"settings.agentBehaviour.availableModes": "Dostępne tryby niestandardowe",
|
||||
"settings.agentBehaviour.noModesFound": "Nie znaleziono trybów.",
|
||||
"settings.agentBehaviour.noAgentsFound": "Nie znaleziono agentów.",
|
||||
"settings.agentBehaviour.createMode": "Utwórz nowy tryb",
|
||||
"settings.agentBehaviour.createMode.name": "Nazwa",
|
||||
"settings.agentBehaviour.createMode.name.placeholder": "np. reviewer",
|
||||
@@ -1347,10 +1355,10 @@ export const dict = {
|
||||
"settings.agentBehaviour.permissions.copy": "Kopiuj uprawnienia jako JSON",
|
||||
"settings.agentBehaviour.permissions.hint":
|
||||
"Reguły są sprawdzane po kolei — ostatnia pasująca reguła wygrywa. To jest wynikowy zestaw reguł z backendu CLI.",
|
||||
"settings.agentBehaviour.removeMode.title": "Usuń tryb",
|
||||
"settings.agentBehaviour.removeMode.confirm":
|
||||
'Usunąć tryb "{{name}}"? Spowoduje to wyłączenie trybu poprzez aktualizację konfiguracji.',
|
||||
"settings.agentBehaviour.removeMode.button": "Usuń",
|
||||
"settings.agentBehaviour.removeAgent.title": "Usuń agenta",
|
||||
"settings.agentBehaviour.removeAgent.confirm":
|
||||
'Usunąć agenta "{{name}}"? Spowoduje to jego wyłączenie przez aktualizację konfiguracji.',
|
||||
"settings.agentBehaviour.removeAgent.button": "Usuń",
|
||||
"settings.agentBehaviour.removeMcp.title": "Usuń serwer MCP",
|
||||
"settings.agentBehaviour.removeMcp.confirm":
|
||||
'Usunąć serwer MCP "{{name}}"? Spowoduje to usunięcie go z konfiguracji.',
|
||||
|
||||
+13
-6
@@ -451,6 +451,7 @@ export const dict = {
|
||||
"toast.session.unshare.failed.title": "Не удалось отменить публикацию",
|
||||
"toast.session.unshare.failed.description": "Произошла ошибка при отмене публикации",
|
||||
|
||||
"toast.session.rename.invalid.title": "Недопустимое название сессии",
|
||||
"toast.session.listFailed.title": "Не удалось загрузить сессии для {{project}}",
|
||||
|
||||
"toast.update.title": "Доступно обновление",
|
||||
@@ -1129,6 +1130,14 @@ export const dict = {
|
||||
"session.status.retrying": "Повторная попытка ({{ attempt }})… {{ message }}",
|
||||
"session.status.working": "Работаю…",
|
||||
"session.status.offline": "Сеть отключена — переподключение...",
|
||||
"session.outcome.incomplete": "Раунд завершен, осталось задач: {{count}}",
|
||||
"session.outcome.limit": "Достигнут лимит ответов до завершения",
|
||||
"session.outcome.unknown": "Раунд завершен без указания причины моделью",
|
||||
"session.outcome.filtered": "Провайдер остановил этот ответ из-за фильтра контента.",
|
||||
"session.outcome.unexpected": "Ответ неожиданно завершился и может быть неполным.",
|
||||
"session.outcome.interrupted": "Раунд прерван",
|
||||
"session.outcome.error": "Раунд завершился с ошибкой",
|
||||
"session.outcome.finish": "Причина завершения: {{reason}}",
|
||||
|
||||
"ui.sessionTurn.cancel": "Отмена",
|
||||
"ui.sessionTurn.status.thinking": "Думаю...",
|
||||
@@ -1191,7 +1200,6 @@ export const dict = {
|
||||
'Телеметрия управляется встроенной настройкой телеметрии VS Code. Чтобы отключить её, перейдите в Настройки > Телеметрия > Уровень телеметрии и установите значение "off". Перезапустите VS Code, чтобы применить изменение.',
|
||||
"settings.aboutKiloCode.telemetry.openSettings": "Открыть настройки телеметрии",
|
||||
|
||||
"settings.agentBehaviour.subtab.modes": "Режимы",
|
||||
"settings.agentBehaviour.subtab.agents": "Агенты",
|
||||
"settings.agentBehaviour.subtab.mcpServers": "MCP-серверы",
|
||||
"settings.agentBehaviour.subtab.rules": "Правила",
|
||||
@@ -1305,7 +1313,7 @@ export const dict = {
|
||||
"settings.agentBehaviour.noSkillsFound":
|
||||
"Навыки не обнаружены. Добавьте пути к папкам навыков или URL-адреса ниже, чтобы сделать навыки доступными.",
|
||||
"settings.agentBehaviour.availableModes": "Доступные пользовательские режимы",
|
||||
"settings.agentBehaviour.noModesFound": "Режимы не найдены.",
|
||||
"settings.agentBehaviour.noAgentsFound": "Агенты не найдены.",
|
||||
"settings.agentBehaviour.createMode": "Создать новый режим",
|
||||
"settings.agentBehaviour.createMode.name": "Название",
|
||||
"settings.agentBehaviour.createMode.name.placeholder": "например, reviewer",
|
||||
@@ -1351,10 +1359,9 @@ export const dict = {
|
||||
"settings.agentBehaviour.permissions.copy": "Скопировать разрешения как JSON",
|
||||
"settings.agentBehaviour.permissions.hint":
|
||||
"Правила оцениваются по порядку — побеждает последнее совпавшее правило. Это разрешенный набор правил из бэкенда CLI.",
|
||||
"settings.agentBehaviour.removeMode.title": "Удалить режим",
|
||||
"settings.agentBehaviour.removeMode.confirm":
|
||||
'Удалить режим "{{name}}"? Это отключит режим, обновив вашу конфигурацию.',
|
||||
"settings.agentBehaviour.removeMode.button": "Удалить",
|
||||
"settings.agentBehaviour.removeAgent.title": "Удалить агент",
|
||||
"settings.agentBehaviour.removeAgent.confirm": 'Удалить агент "{{name}}"? Это отключит агент, обновив конфигурацию.',
|
||||
"settings.agentBehaviour.removeAgent.button": "Удалить",
|
||||
"settings.agentBehaviour.removeMcp.title": "Удалить сервер MCP",
|
||||
"settings.agentBehaviour.removeMcp.confirm": 'Удалить сервер MCP "{{name}}"? Это удалит его из вашей конфигурации.',
|
||||
"settings.agentBehaviour.removeMcp.button": "Удалить",
|
||||
|
||||
+14
-6
@@ -450,6 +450,7 @@ export const dict = {
|
||||
"toast.session.unshare.failed.title": "ไม่สามารถยกเลิกการแชร์เซสชัน",
|
||||
"toast.session.unshare.failed.description": "เกิดข้อผิดพลาดระหว่างการยกเลิกการแชร์เซสชัน",
|
||||
|
||||
"toast.session.rename.invalid.title": "ชื่อเซสชันไม่ถูกต้อง",
|
||||
"toast.session.listFailed.title": "ไม่สามารถโหลดเซสชันสำหรับ {{project}}",
|
||||
|
||||
"toast.update.title": "มีการอัปเดต",
|
||||
@@ -1114,6 +1115,14 @@ export const dict = {
|
||||
"session.status.retrying": "กำลังลองใหม่ (ครั้งที่ {{ attempt }})… {{ message }}",
|
||||
"session.status.working": "กำลังทำงาน...",
|
||||
"session.status.offline": "เครือข่ายถูกตัดการเชื่อมต่อ — กำลังเชื่อมต่อใหม่...",
|
||||
"session.outcome.incomplete": "เทิร์นสิ้นสุดโดยเหลือสิ่งที่ต้องทำอีก {{count}} รายการ",
|
||||
"session.outcome.limit": "ถึงขีดจำกัดการตอบกลับก่อนเสร็จสิ้น",
|
||||
"session.outcome.unknown": "เทิร์นสิ้นสุดโดยไม่มีเหตุผลการเสร็จสิ้นของโมเดล",
|
||||
"session.outcome.filtered": "ผู้ให้บริการหยุดการตอบกลับนี้เนื่องจากตัวกรองเนื้อหา",
|
||||
"session.outcome.unexpected": "การตอบกลับสิ้นสุดลงโดยไม่คาดคิดและอาจไม่สมบูรณ์",
|
||||
"session.outcome.interrupted": "เทิร์นถูกขัดจังหวะ",
|
||||
"session.outcome.error": "เทิร์นล้มเหลว",
|
||||
"session.outcome.finish": "เหตุผลการเสร็จสิ้น: {{reason}}",
|
||||
|
||||
"ui.sessionTurn.cancel": "ยกเลิก",
|
||||
"ui.sessionTurn.status.thinking": "กำลังคิด...",
|
||||
@@ -1175,7 +1184,6 @@ export const dict = {
|
||||
'Telemetry ถูกควบคุมโดยการตั้งค่า Telemetry ในตัวของ VS Code หากต้องการปิดใช้งาน ให้ไปที่ Settings > Telemetry > Telemetry Level แล้วตั้งค่าเป็น "off" รีสตาร์ท VS Code เพื่อให้การเปลี่ยนแปลงมีผล',
|
||||
"settings.aboutKiloCode.telemetry.openSettings": "เปิดการตั้งค่า Telemetry",
|
||||
|
||||
"settings.agentBehaviour.subtab.modes": "โหมด",
|
||||
"settings.agentBehaviour.subtab.agents": "ตัวแทน",
|
||||
"settings.agentBehaviour.subtab.mcpServers": "เซิร์ฟเวอร์ MCP",
|
||||
"settings.agentBehaviour.subtab.rules": "กฎ",
|
||||
@@ -1287,7 +1295,7 @@ export const dict = {
|
||||
"settings.agentBehaviour.discoveredSkills": "ทักษะที่ค้นพบ",
|
||||
"settings.agentBehaviour.noSkillsFound": "ไม่พบทักษะ เพิ่มเส้นทางโฟลเดอร์หรือ URL ด้านล่างเพื่อทำให้ทักษะพร้อมใช้งาน",
|
||||
"settings.agentBehaviour.availableModes": "โหมดกำหนดเองที่ใช้ได้",
|
||||
"settings.agentBehaviour.noModesFound": "ไม่พบโหมด",
|
||||
"settings.agentBehaviour.noAgentsFound": "ไม่พบเอเจนต์",
|
||||
"settings.agentBehaviour.createMode": "สร้างโหมดใหม่",
|
||||
"settings.agentBehaviour.createMode.name": "ชื่อ",
|
||||
"settings.agentBehaviour.createMode.name.placeholder": "เช่น reviewer",
|
||||
@@ -1330,10 +1338,10 @@ export const dict = {
|
||||
"settings.agentBehaviour.permissions.copy": "คัดลอกสิทธิ์เป็น JSON",
|
||||
"settings.agentBehaviour.permissions.hint":
|
||||
"กฎจะถูกประเมินตามลำดับ — กฎที่ตรงกันล่าสุดจะมีผล นี่คือชุดกฎที่ประมวลผลแล้วจากแบ็กเอนด์ CLI",
|
||||
"settings.agentBehaviour.removeMode.title": "ลบโหมด",
|
||||
"settings.agentBehaviour.removeMode.confirm":
|
||||
'ต้องการลบโหมด "{{name}}" หรือไม่? การดำเนินการนี้จะปิดใช้งานโหมดโดยอัปเดตการกำหนดค่าของคุณ',
|
||||
"settings.agentBehaviour.removeMode.button": "ลบ",
|
||||
"settings.agentBehaviour.removeAgent.title": "ลบเอเจนต์",
|
||||
"settings.agentBehaviour.removeAgent.confirm":
|
||||
'ลบเอเจนต์ "{{name}}" หรือไม่? การดำเนินการนี้จะปิดใช้งานเอเจนต์โดยการอัปเดตการตั้งค่า',
|
||||
"settings.agentBehaviour.removeAgent.button": "ลบ",
|
||||
"settings.agentBehaviour.removeMcp.title": "ลบเซิร์ฟเวอร์ MCP",
|
||||
"settings.agentBehaviour.removeMcp.confirm":
|
||||
'ต้องการลบเซิร์ฟเวอร์ MCP "{{name}}" หรือไม่? การดำเนินการนี้จะลบออกจากการกำหนดค่าของคุณ',
|
||||
|
||||
+14
-6
@@ -451,6 +451,7 @@ export const dict = {
|
||||
"toast.session.unshare.failed.title": "Oturum paylaşımı kaldırılamadı",
|
||||
"toast.session.unshare.failed.description": "Oturum paylaşımı kaldırılırken bir hata oluştu",
|
||||
|
||||
"toast.session.rename.invalid.title": "Geçersiz oturum başlığı",
|
||||
"toast.session.listFailed.title": "{{project}} için oturumlar yüklenemedi",
|
||||
|
||||
"toast.update.title": "Güncelleme mevcut",
|
||||
@@ -1117,6 +1118,14 @@ export const dict = {
|
||||
"session.status.retrying": "Yeniden deneniyor (deneme {{ attempt }})… {{ message }}",
|
||||
"session.status.working": "Çalışıyor...",
|
||||
"session.status.offline": "Ağ bağlantısı kesildi — yeniden bağlanılıyor...",
|
||||
"session.outcome.incomplete": "Tur, {{count}} yapılacak öğe kalarak sona erdi",
|
||||
"session.outcome.limit": "Tamamlanmadan önce yanıt sınırına ulaşıldı",
|
||||
"session.outcome.unknown": "Tur, model bitiş nedeni olmadan sona erdi",
|
||||
"session.outcome.filtered": "Sağlayıcı, bir içerik filtresi nedeniyle bu yanıtı durdurdu.",
|
||||
"session.outcome.unexpected": "Yanıt beklenmedik bir şekilde sona erdi ve eksik olabilir.",
|
||||
"session.outcome.interrupted": "Tur kesintiye uğradı",
|
||||
"session.outcome.error": "Tur başarısız oldu",
|
||||
"session.outcome.finish": "Bitiş nedeni: {{reason}}",
|
||||
|
||||
"ui.sessionTurn.cancel": "İptal",
|
||||
"ui.sessionTurn.status.thinking": "Düşünüyor...",
|
||||
@@ -1180,7 +1189,6 @@ export const dict = {
|
||||
"Telemetri, VS Code'un yerleşik telemetri ayarı tarafından kontrol edilir. Devre dışı bırakmak için Ayarlar > Telemetri > Telemetri Düzeyi'ne gidin ve \"off\" olarak ayarlayın. Değişikliği uygulamak için VS Code'u yeniden başlatın.",
|
||||
"settings.aboutKiloCode.telemetry.openSettings": "Telemetri Ayarlarını Aç",
|
||||
|
||||
"settings.agentBehaviour.subtab.modes": "Modlar",
|
||||
"settings.agentBehaviour.subtab.agents": "Ajanlar",
|
||||
"settings.agentBehaviour.subtab.mcpServers": "MCP Sunucuları",
|
||||
"settings.agentBehaviour.subtab.rules": "Kurallar",
|
||||
@@ -1298,7 +1306,7 @@ export const dict = {
|
||||
"settings.agentBehaviour.noSkillsFound":
|
||||
"Keşfedilen beceri yok. Becerileri kullanılabilir kılmak için aşağıya beceri klasör yolları veya URL'ler ekleyin.",
|
||||
"settings.agentBehaviour.availableModes": "Mevcut Özel Modlar",
|
||||
"settings.agentBehaviour.noModesFound": "Mod bulunamadı.",
|
||||
"settings.agentBehaviour.noAgentsFound": "Ajan bulunamadı.",
|
||||
"settings.agentBehaviour.importMode": "İçe Aktar",
|
||||
"settings.agentBehaviour.importMode.invalidName":
|
||||
"Dosyadaki mod adı geçersiz. Ad küçük harfle başlamalı ve yalnızca küçük harfler, rakamlar ve tire içermelidir.",
|
||||
@@ -1307,10 +1315,10 @@ export const dict = {
|
||||
"Geçersiz JSON dosyası. Lütfen geçerli bir ajan tanım dosyası seçin.",
|
||||
"settings.agentBehaviour.importMode.tooLarge": "Dosya çok büyük. Ajan tanımları 1 MB'den küçük olmalıdır.",
|
||||
"settings.agentBehaviour.exportMode": "Ajan tanımını dışa aktar",
|
||||
"settings.agentBehaviour.removeMode.title": "Modu kaldır",
|
||||
"settings.agentBehaviour.removeMode.confirm":
|
||||
'"{{name}}" modu kaldırılsın mı? Bu, yapılandırmanızı güncelleyerek modu devre dışı bırakacak.',
|
||||
"settings.agentBehaviour.removeMode.button": "Kaldır",
|
||||
"settings.agentBehaviour.removeAgent.title": "Ajanı kaldır",
|
||||
"settings.agentBehaviour.removeAgent.confirm":
|
||||
'"{{name}}" ajanını kaldır? Bu, yapılandırmanızı güncelleyerek ajanı devre dışı bırakır.',
|
||||
"settings.agentBehaviour.removeAgent.button": "Kaldır",
|
||||
"settings.agentBehaviour.skillPaths": "Beceri Klasör Yolları",
|
||||
"settings.agentBehaviour.skillUrls": "Beceri URL'leri",
|
||||
"settings.agentBehaviour.removeSkill.title": "Beceriyi kaldır",
|
||||
|
||||
+14
-6
@@ -455,6 +455,7 @@ export const dict = {
|
||||
"toast.session.unshare.failed.title": "Не вдалося закрити доступ до сесії",
|
||||
"toast.session.unshare.failed.description": "Під час закриття доступу до сесії сталася помилка",
|
||||
|
||||
"toast.session.rename.invalid.title": "Некоректна назва сесії",
|
||||
"toast.session.listFailed.title": "Не вдалося завантажити сесії для {{project}}",
|
||||
|
||||
"toast.update.title": "Доступне оновлення",
|
||||
@@ -1116,6 +1117,14 @@ export const dict = {
|
||||
"session.status.retrying": "Повторна спроба (спроба {{ attempt }})… {{ message }}",
|
||||
"session.status.working": "Працює...",
|
||||
"session.status.offline": "Мережу відключено — перепідключення...",
|
||||
"session.outcome.incomplete": "Хід завершився з {{count}} невиконаними завданнями",
|
||||
"session.outcome.limit": "Ліміт відповідей досягнуто до завершення",
|
||||
"session.outcome.unknown": "Хід завершився без причини завершення моделі",
|
||||
"session.outcome.filtered": "Провайдер зупинив цю відповідь через фільтр вмісту.",
|
||||
"session.outcome.unexpected": "Відповідь завершилася несподівано і може бути неповною.",
|
||||
"session.outcome.interrupted": "Хід перервано",
|
||||
"session.outcome.error": "Хід не вдався",
|
||||
"session.outcome.finish": "Причина завершення: {{reason}}",
|
||||
|
||||
"ui.sessionTurn.cancel": "Скасувати",
|
||||
"ui.sessionTurn.status.thinking": "Думаю...",
|
||||
@@ -1179,7 +1188,6 @@ export const dict = {
|
||||
'Телеметрія керується вбудованим налаштуванням телеметрії VS Code. Щоб вимкнути її, перейдіть до Налаштування > Телеметрія > Рівень телеметрії та встановіть значення "off". Перезапустіть VS Code, щоб застосувати зміну.',
|
||||
"settings.aboutKiloCode.telemetry.openSettings": "Відкрити налаштування телеметрії",
|
||||
|
||||
"settings.agentBehaviour.subtab.modes": "Режими",
|
||||
"settings.agentBehaviour.subtab.agents": "Агенти",
|
||||
"settings.agentBehaviour.subtab.mcpServers": "MCP-сервери",
|
||||
"settings.agentBehaviour.subtab.rules": "Правила",
|
||||
@@ -1299,7 +1307,7 @@ export const dict = {
|
||||
"settings.agentBehaviour.noSkillsFound":
|
||||
"Навичок не виявлено. Додайте шляхи до папок навичок або URL нижче, щоб зробити їх доступними.",
|
||||
"settings.agentBehaviour.availableModes": "Доступні власні режими",
|
||||
"settings.agentBehaviour.noModesFound": "Режимів не знайдено.",
|
||||
"settings.agentBehaviour.noAgentsFound": "Агентів не знайдено.",
|
||||
"settings.agentBehaviour.importMode": "Імпортувати",
|
||||
"settings.agentBehaviour.importMode.invalidName":
|
||||
"Назва режиму у файлі недійсна. Назва має починатися з малої літери і містити лише малі літери, цифри та дефіси.",
|
||||
@@ -1308,10 +1316,10 @@ export const dict = {
|
||||
"Недійсний файл JSON. Будь ласка, виберіть дійсний файл визначення агента.",
|
||||
"settings.agentBehaviour.importMode.tooLarge": "Файл занадто великий. Визначення агентів мають бути менше 1 МБ.",
|
||||
"settings.agentBehaviour.exportMode": "Експортувати визначення агента",
|
||||
"settings.agentBehaviour.removeMode.title": "Видалити режим",
|
||||
"settings.agentBehaviour.removeMode.confirm":
|
||||
'Видалити режим "{{name}}"? Це оновить вашу конфігурацію, щоб вимкнути режим.',
|
||||
"settings.agentBehaviour.removeMode.button": "Видалити",
|
||||
"settings.agentBehaviour.removeAgent.title": "Видалити агент",
|
||||
"settings.agentBehaviour.removeAgent.confirm":
|
||||
'Видалити агент "{{name}}"? Це вимкне агент шляхом оновлення конфігурації.',
|
||||
"settings.agentBehaviour.removeAgent.button": "Видалити",
|
||||
"settings.agentBehaviour.skillPaths": "Шляхи до папок навичок",
|
||||
"settings.agentBehaviour.skillUrls": "URL навичок",
|
||||
"settings.agentBehaviour.removeSkill.title": "Видалити навичку",
|
||||
|
||||
+13
-5
@@ -447,6 +447,7 @@ export const dict = {
|
||||
"toast.session.unshare.failed.title": "取消分享失败",
|
||||
"toast.session.unshare.failed.description": "取消分享会话时发生错误",
|
||||
|
||||
"toast.session.rename.invalid.title": "无效的会话标题",
|
||||
"toast.session.listFailed.title": "无法加载 {{project}} 的会话",
|
||||
|
||||
"toast.update.title": "有可用更新",
|
||||
@@ -1098,6 +1099,14 @@ export const dict = {
|
||||
"session.status.retrying": "正在重试(第 {{ attempt }} 次)… {{ message }}",
|
||||
"session.status.working": "处理中…",
|
||||
"session.status.offline": "网络已断开 — 正在重连...",
|
||||
"session.outcome.incomplete": "回合已结束,尚有 {{count}} 个待办事项",
|
||||
"session.outcome.limit": "未完成前已达到响应限制",
|
||||
"session.outcome.unknown": "回合已结束,模型未提供结束原因",
|
||||
"session.outcome.filtered": "提供商因为内容过滤器停止了此响应。",
|
||||
"session.outcome.unexpected": "响应意外结束,可能不完整。",
|
||||
"session.outcome.interrupted": "回合已中断",
|
||||
"session.outcome.error": "回合失败",
|
||||
"session.outcome.finish": "结束原因:{{reason}}",
|
||||
|
||||
"ui.sessionTurn.cancel": "取消",
|
||||
"ui.sessionTurn.status.thinking": "思考中...",
|
||||
@@ -1157,7 +1166,6 @@ export const dict = {
|
||||
'遥测由 VS Code 的内置遥测设置控制。若要将其禁用,请转到「设置」>「遥测」>「遥测级别」并将其设置为 "off"。重启 VS Code 以应用更改。',
|
||||
"settings.aboutKiloCode.telemetry.openSettings": "打开遥测设置",
|
||||
|
||||
"settings.agentBehaviour.subtab.modes": "模式",
|
||||
"settings.agentBehaviour.subtab.agents": "代理",
|
||||
"settings.agentBehaviour.subtab.mcpServers": "MCP 服务器",
|
||||
"settings.agentBehaviour.subtab.rules": "规则",
|
||||
@@ -1266,7 +1274,7 @@ export const dict = {
|
||||
"settings.agentBehaviour.discoveredSkills": "已发现的技能",
|
||||
"settings.agentBehaviour.noSkillsFound": "未发现任何技能。请在下方添加技能文件夹路径或 URL 以使技能可用。",
|
||||
"settings.agentBehaviour.availableModes": "可用自定义模式",
|
||||
"settings.agentBehaviour.noModesFound": "未找到模式。",
|
||||
"settings.agentBehaviour.noAgentsFound": "未找到智能体。",
|
||||
"settings.agentBehaviour.createMode": "创建新模式",
|
||||
"settings.agentBehaviour.createMode.name": "名称",
|
||||
"settings.agentBehaviour.createMode.name.placeholder": "例如:reviewer",
|
||||
@@ -1305,9 +1313,9 @@ export const dict = {
|
||||
"settings.agentBehaviour.permissions.col.action": "操作",
|
||||
"settings.agentBehaviour.permissions.copy": "复制权限为 JSON",
|
||||
"settings.agentBehaviour.permissions.hint": "规则按顺序评估 — 最后匹配的规则生效。这是从 CLI 后端解析出的规则集。",
|
||||
"settings.agentBehaviour.removeMode.title": "移除模式",
|
||||
"settings.agentBehaviour.removeMode.confirm": '移除模式 "{{name}}" 吗?这将通过更新配置来禁用该模式。',
|
||||
"settings.agentBehaviour.removeMode.button": "移除",
|
||||
"settings.agentBehaviour.removeAgent.title": "移除智能体",
|
||||
"settings.agentBehaviour.removeAgent.confirm": '移除智能体 "{{name}}" 吗?这将通过更新配置来禁用该智能体。',
|
||||
"settings.agentBehaviour.removeAgent.button": "移除",
|
||||
"settings.agentBehaviour.removeMcp.title": "移除 MCP 服务器",
|
||||
"settings.agentBehaviour.removeMcp.confirm": '移除 MCP 服务器 "{{name}}" 吗?这将从您的配置中移除它。',
|
||||
"settings.agentBehaviour.removeMcp.button": "移除",
|
||||
|
||||
+13
-5
@@ -447,6 +447,7 @@ export const dict = {
|
||||
"toast.session.unshare.failed.title": "取消分享失敗",
|
||||
"toast.session.unshare.failed.description": "取消分享工作階段時發生錯誤",
|
||||
|
||||
"toast.session.rename.invalid.title": "無效的工作階段標題",
|
||||
"toast.session.listFailed.title": "無法載入 {{project}} 的工作階段",
|
||||
|
||||
"toast.update.title": "有可用更新",
|
||||
@@ -1066,6 +1067,14 @@ export const dict = {
|
||||
"session.status.retrying": "正在重試(第 {{ attempt }} 次)… {{ message }}",
|
||||
"session.status.working": "處理中…",
|
||||
"session.status.offline": "網路已斷線 — 正在重新連線...",
|
||||
"session.outcome.incomplete": "回合已結束,尚有 {{count}} 個待辦事項",
|
||||
"session.outcome.limit": "未完成前已達到回應限制",
|
||||
"session.outcome.unknown": "回合已結束,模型未提供結束原因",
|
||||
"session.outcome.filtered": "提供商因為內容過濾器停止了此回應。",
|
||||
"session.outcome.unexpected": "回應意外結束,可能不完整。",
|
||||
"session.outcome.interrupted": "回合已中斷",
|
||||
"session.outcome.error": "回合失敗",
|
||||
"session.outcome.finish": "結束原因:{{reason}}",
|
||||
|
||||
"ui.sessionTurn.cancel": "取消",
|
||||
"ui.sessionTurn.status.thinking": "思考中...",
|
||||
@@ -1125,7 +1134,6 @@ export const dict = {
|
||||
'遙測由 VS Code 內建的遙測設定控制。若要停用,請前往「設定」>「遙測」>「遙測層級」並將其設為 "off"。重新啟動 VS Code 以套用變更。',
|
||||
"settings.aboutKiloCode.telemetry.openSettings": "開啟遙測設定",
|
||||
|
||||
"settings.agentBehaviour.subtab.modes": "模式",
|
||||
"settings.agentBehaviour.subtab.agents": "代理程式",
|
||||
"settings.agentBehaviour.subtab.mcpServers": "MCP 伺服器",
|
||||
"settings.agentBehaviour.subtab.rules": "規則",
|
||||
@@ -1234,7 +1242,7 @@ export const dict = {
|
||||
"settings.agentBehaviour.discoveredSkills": "已發現的 Skill",
|
||||
"settings.agentBehaviour.noSkillsFound": "未發現任何 Skill。請在下方新增 Skill 資料夾路徑或 URL 以使 Skill 可用。",
|
||||
"settings.agentBehaviour.availableModes": "可用自訂模式",
|
||||
"settings.agentBehaviour.noModesFound": "未找到模式。",
|
||||
"settings.agentBehaviour.noAgentsFound": "未找到智能體。",
|
||||
"settings.agentBehaviour.createMode": "建立新模式",
|
||||
"settings.agentBehaviour.createMode.name": "名稱",
|
||||
"settings.agentBehaviour.createMode.name.placeholder": "例如:reviewer",
|
||||
@@ -1275,9 +1283,9 @@ export const dict = {
|
||||
"settings.agentBehaviour.permissions.copy": "複製權限為 JSON",
|
||||
"settings.agentBehaviour.permissions.hint":
|
||||
"規則會按順序評估 — 最後符合的規則為準。這是來自 CLI 後端的已解析規則集。",
|
||||
"settings.agentBehaviour.removeMode.title": "移除模式",
|
||||
"settings.agentBehaviour.removeMode.confirm": '要移除模式 "{{name}}" 嗎?這將透過更新設定來停用該模式。',
|
||||
"settings.agentBehaviour.removeMode.button": "移除",
|
||||
"settings.agentBehaviour.removeAgent.title": "移除智能體",
|
||||
"settings.agentBehaviour.removeAgent.confirm": '要移除智能體 "{{name}}" 嗎?這將透過更新設定來停用該智能體。',
|
||||
"settings.agentBehaviour.removeAgent.button": "移除",
|
||||
"settings.agentBehaviour.removeMcp.title": "移除 MCP 伺服器",
|
||||
"settings.agentBehaviour.removeMcp.confirm": '要移除 MCP 伺服器 "{{name}}" 嗎?這將從您的設定中移除它。',
|
||||
"settings.agentBehaviour.removeMcp.button": "移除",
|
||||
|
||||
@@ -44,6 +44,7 @@ import type {
|
||||
KilocodeNotification,
|
||||
PermissionRequest,
|
||||
ProviderAuthState,
|
||||
SessionCloseReason,
|
||||
QuestionRequest,
|
||||
SuggestionRequest,
|
||||
} from "../types/messages"
|
||||
@@ -160,6 +161,7 @@ export function mockSessionValue(overrides?: {
|
||||
questions?: QuestionRequest[]
|
||||
suggestions?: SuggestionRequest[]
|
||||
status?: string
|
||||
closeReason?: SessionCloseReason
|
||||
}) {
|
||||
const id = overrides?.id ?? "story-session-001"
|
||||
const permissions = overrides?.permissions ?? []
|
||||
@@ -179,6 +181,7 @@ export function mockSessionValue(overrides?: {
|
||||
sessions: () => [],
|
||||
status: () => status,
|
||||
statusInfo: () => ({ type: status }),
|
||||
closeReason: () => overrides?.closeReason,
|
||||
statusText: () => (status === "idle" ? undefined : "Thinking…"),
|
||||
busySince: () => (status === "busy" ? Date.now() - 2000 : undefined),
|
||||
loading: () => false,
|
||||
@@ -216,7 +219,7 @@ export function mockSessionValue(overrides?: {
|
||||
skills: () => [],
|
||||
refreshSkills: noop,
|
||||
removeSkill: noop,
|
||||
removeMode: noop,
|
||||
removeAgent: noop,
|
||||
selectedAgent: () => "code",
|
||||
selectAgent: noop,
|
||||
getSessionAgent: () => "code",
|
||||
|
||||
@@ -14,6 +14,7 @@ import { TaskHeader } from "../components/chat/TaskHeader"
|
||||
import { QuestionDock } from "../components/chat/QuestionDock"
|
||||
import { SuggestBar } from "../components/chat/SuggestBar"
|
||||
import { MessageList } from "../components/chat/MessageList"
|
||||
import { TurnOutcome } from "../components/shared/TurnOutcome"
|
||||
import { SessionContext } from "../context/session"
|
||||
import { ServerContext } from "../context/server"
|
||||
import type { Message, Part, QuestionRequest, SuggestionRequest, TodoItem } from "../types/messages"
|
||||
@@ -445,6 +446,52 @@ export const MessageListSubagentToQueuedUserSpacing: Story = {
|
||||
},
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// TurnOutcome - abnormal terminal state cards
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
const outcomeMessage: Message = {
|
||||
id: "asst-msg-outcome-001",
|
||||
sessionID: SESSION_ID,
|
||||
role: "assistant",
|
||||
createdAt: new Date(subNow).toISOString(),
|
||||
finish: "unknown",
|
||||
}
|
||||
|
||||
export const TurnOutcomeUnknown: Story = {
|
||||
name: "TurnOutcome - response ended without a finish reason",
|
||||
render: () => {
|
||||
const session = {
|
||||
...mockSessionValue({ id: SESSION_ID, status: "idle", closeReason: "completed" }),
|
||||
visibleMessages: () => [outcomeMessage],
|
||||
}
|
||||
return (
|
||||
<StoryProviders sessionID={SESSION_ID} status="idle" noPadding>
|
||||
<SessionContext.Provider value={session as any}>
|
||||
<TurnOutcome />
|
||||
</SessionContext.Provider>
|
||||
</StoryProviders>
|
||||
)
|
||||
},
|
||||
}
|
||||
|
||||
export const TurnOutcomeFailed: Story = {
|
||||
name: "TurnOutcome - failed turn fallback",
|
||||
render: () => {
|
||||
const session = {
|
||||
...mockSessionValue({ id: SESSION_ID, status: "idle", closeReason: "error" }),
|
||||
visibleMessages: () => [{ ...outcomeMessage, id: "asst-msg-outcome-002", finish: "error" }],
|
||||
}
|
||||
return (
|
||||
<StoryProviders sessionID={SESSION_ID} status="idle" noPadding>
|
||||
<SessionContext.Provider value={session as any}>
|
||||
<TurnOutcome />
|
||||
</SessionContext.Provider>
|
||||
</StoryProviders>
|
||||
)
|
||||
},
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// TaskHeader with todos
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user