diff --git a/.changeset/clear-diffs-settle.md b/.changeset/clear-diffs-settle.md new file mode 100644 index 00000000000..2db456fe67e --- /dev/null +++ b/.changeset/clear-diffs-settle.md @@ -0,0 +1,5 @@ +--- +"kilo-code": patch +--- + +Clear Agent Manager file diff previews stuck on `Loading diff...` when the active diff source stops or changes. diff --git a/packages/kilo-docs/pages/collaborate/teams/billing.md b/packages/kilo-docs/pages/collaborate/teams/billing.md index 545c8887818..c8b89f50c98 100644 --- a/packages/kilo-docs/pages/collaborate/teams/billing.md +++ b/packages/kilo-docs/pages/collaborate/teams/billing.md @@ -68,7 +68,7 @@ To fill empty seats or remove members ahead of seat deletion, see the [team mana ## Automatic Top-Up -Ensure your team has uninterrupted access to Kilo Code by enabling Automatic Top-Up. This feature keeps your organization's balance funded so you never have to worry about manual recharges. +Ensure your team has uninterrupted access to Kilo Code by enabling [Automatic Top-Up](https://kilo.ai/features/auto-top-ups). This feature keeps your organization's balance funded so you never have to worry about manual recharges. Auto top-up is also available for individual accounts — see [Adding Credits](/docs/getting-started/adding-credits) for details. ### How It Works diff --git a/packages/kilo-docs/pages/getting-started/adding-credits.md b/packages/kilo-docs/pages/getting-started/adding-credits.md index f5c89de697c..a8b021abcea 100644 --- a/packages/kilo-docs/pages/getting-started/adding-credits.md +++ b/packages/kilo-docs/pages/getting-started/adding-credits.md @@ -9,9 +9,9 @@ Once you've used any initial free Kilo Credits, you can easily add more: - Subscribe to the [Kilo Pass](https://kilo.ai/features/kilo-pass), the most cost effective way to add credits. - Purchase additional credits as a one-time transaction. -- Enable automatic top-up, which purchases additional credits when your balance is below $5. +- Enable [automatic top-up](https://kilo.ai/features/auto-top-ups), which purchases additional credits when your balance runs low. Auto top-up is available for both individual and organization accounts. -These options are available to purchase from your [personal profile page](https://app.kilo.ai/profile). +These options are available to purchase from your [personal profile page](https://app.kilo.ai/profile). Organization owners can manage credits and auto top-up from the [Organization dashboard](https://app.kilo.ai). You can also use subscriptions or credits you may have purchased directly with an AI provider by adding your keys on the [Bring your own Key (BYOK)](https://app.kilo.ai/byok) settings screen. For setup details and supported providers, see [AI Providers documentation](/docs/ai-providers). If your provider is not yet supported, you can also [directly connect your provider](/docs/getting-started/setup-authentication) in the extension and CLI. diff --git a/packages/kilo-vscode/src/diff/SourceController.ts b/packages/kilo-vscode/src/diff/SourceController.ts index 47d1a771471..11a51ed3449 100644 --- a/packages/kilo-vscode/src/diff/SourceController.ts +++ b/packages/kilo-vscode/src/diff/SourceController.ts @@ -181,8 +181,12 @@ export class SourceController { return } const diff = await source.fetchFile(file).catch(() => null) - // Drop the response if the source has been disposed/swapped while we waited. - if (this.epoch !== epoch) return + // Discard stale content after disposal/swap, but still complete the request + // so consumers can clear per-file loading state. + if (this.epoch !== epoch) { + this.send(this.messages.diffFile(source, file, null)) + return + } this.send(this.messages.diffFile(source, file, diff)) } diff --git a/packages/kilo-vscode/tests/unit/source-controller.test.ts b/packages/kilo-vscode/tests/unit/source-controller.test.ts index f9a49cd2cbc..549fe75af02 100644 --- a/packages/kilo-vscode/tests/unit/source-controller.test.ts +++ b/packages/kilo-vscode/tests/unit/source-controller.test.ts @@ -345,6 +345,40 @@ describe("SourceController.requestFile", () => { controller.stop() }) + + it("posts null when a pending fetchFile result is invalidated by stop", async () => { + let release: () => void = () => {} + const workspace: DiffSource = { + descriptor: WORKSPACE_DESC, + async fetch() { + return { diffs: [] } + }, + async fetchFile() { + await new Promise((resolve) => (release = resolve)) + return { + file: "foo.ts", + before: "a", + after: "b", + additions: 1, + deletions: 1, + } + }, + } + const { controller, posted } = make({ workspace }) + + controller.setContext({ workspaceRoot: "/repo" }) + await controller.activate("workspace") + posted.length = 0 + const request = controller.requestFile("foo.ts") + controller.stop() + release() + await request + + const files = byType(posted, "diffViewer.diffFile") + expect(files).toHaveLength(1) + expect(files[0]!.file).toBe("foo.ts") + expect(files[0]!.diff).toBeNull() + }) }) describe("SourceController.reactivate", () => {