mirror of
https://github.com/MoonshotAI/kimi-code.git
synced 2026-08-06 23:36:06 +00:00
fix(tui): surface capability install errors (#2682)
Some checks are pending
CI / test (1) (push) Waiting to run
CI / test (2) (push) Waiting to run
CI / test (3) (push) Waiting to run
CI / test (4) (push) Waiting to run
CI / test (5) (push) Waiting to run
CI / test-pi-tui (push) Waiting to run
CI / test-windows (push) Waiting to run
CI / lint (push) Waiting to run
CI / build (push) Waiting to run
CI / typecheck (push) Waiting to run
Nix Build / Check flake.nix workspace sync (push) Waiting to run
Nix Build / nix build .#kimi-code (push) Blocked by required conditions
Release / Native release artifact (push) Blocked by required conditions
Release / Release (push) Waiting to run
Release / Deploy docs (push) Blocked by required conditions
Release / Publish native release assets (push) Blocked by required conditions
Some checks are pending
CI / test (1) (push) Waiting to run
CI / test (2) (push) Waiting to run
CI / test (3) (push) Waiting to run
CI / test (4) (push) Waiting to run
CI / test (5) (push) Waiting to run
CI / test-pi-tui (push) Waiting to run
CI / test-windows (push) Waiting to run
CI / lint (push) Waiting to run
CI / build (push) Waiting to run
CI / typecheck (push) Waiting to run
Nix Build / Check flake.nix workspace sync (push) Waiting to run
Nix Build / nix build .#kimi-code (push) Blocked by required conditions
Release / Native release artifact (push) Blocked by required conditions
Release / Release (push) Waiting to run
Release / Deploy docs (push) Blocked by required conditions
Release / Publish native release assets (push) Blocked by required conditions
This commit is contained in:
parent
3c75a27da6
commit
013203421d
5 changed files with 83 additions and 6 deletions
|
|
@ -2,4 +2,4 @@
|
|||
"@moonshot-ai/kimi-code": minor
|
||||
---
|
||||
|
||||
Add Windows support for the built-in Kimi Computer Use capability. Install it from `/plugins` on Windows x64.
|
||||
Add Windows support for the built-in Kimi Computer Use capability and show the underlying error when capability setup fails. Install it from `/plugins` on Windows x64.
|
||||
|
|
|
|||
|
|
@ -539,7 +539,8 @@ async function installCapabilityFromPanel(
|
|||
}
|
||||
logCapabilityStatus(result);
|
||||
if (result.install.error !== undefined) {
|
||||
host.showError(`${label} installation failed. Check the logs and install again from /plugins.`);
|
||||
host.showError(`${label} installation failed: ${result.install.error}`);
|
||||
host.showStatus('Fix the reported error, then install again from /plugins.', 'warning');
|
||||
return;
|
||||
}
|
||||
if (result.state !== 'ready') {
|
||||
|
|
|
|||
|
|
@ -199,6 +199,29 @@ describe('plugins command capability surface', () => {
|
|||
expect(statuses.some((s) => s.includes('is installed'))).toBe(true);
|
||||
});
|
||||
|
||||
it('shows the engine error when a background capability install fails', async () => {
|
||||
const { host, statuses } = fakeHost({
|
||||
engineV2: true,
|
||||
capabilityStatus: () =>
|
||||
Promise.resolve({
|
||||
state: 'not_installed',
|
||||
steps: [],
|
||||
install: { running: false, error: 'Authenticode signature is not valid' },
|
||||
}),
|
||||
});
|
||||
|
||||
await installCapabilityFromPanel(
|
||||
host,
|
||||
fakePanel().panel,
|
||||
{ id: 'kimi-cu', displayName: 'Kimi Computer Use', source: 'capability:kimi-cu' } as never,
|
||||
);
|
||||
|
||||
expect(statuses).toContain(
|
||||
'Kimi Computer Use installation failed: Authenticode signature is not valid',
|
||||
);
|
||||
expect(statuses).toContain('Fix the reported error, then install again from /plugins.');
|
||||
});
|
||||
|
||||
it('shows required permissions once after installation instead of exposing step details', async () => {
|
||||
const { host, statuses } = fakeHost({
|
||||
engineV2: true,
|
||||
|
|
|
|||
|
|
@ -4,14 +4,15 @@
|
|||
* Holds the closed registry of built-in capability entries and serializes
|
||||
* install runs per entry. Install progress lives in memory only and is
|
||||
* polled by clients; a failed attempt leaves its error in the progress state
|
||||
* until the next attempt starts. Listing degrades a single entry's failing
|
||||
* detection to a failed step on that entry instead of rejecting the whole
|
||||
* list. Bound at App scope.
|
||||
* until the next attempt starts and logs the failure through `log`. Listing
|
||||
* degrades a single entry's failing detection to a failed step on that entry
|
||||
* instead of rejecting the whole list. Bound at App scope.
|
||||
*/
|
||||
|
||||
import { homedir } from 'node:os';
|
||||
|
||||
import { LifecycleScope, ScopeActivation, registerScopedService } from '#/_base/di/scope';
|
||||
import { ILogService } from '#/_base/log/log';
|
||||
import { Error2 } from '#/errors';
|
||||
import { IBootstrapService } from '#/app/bootstrap/bootstrap';
|
||||
import { IPluginService } from '#/app/plugin/plugin';
|
||||
|
|
@ -42,6 +43,7 @@ export class CapabilityService implements ICapabilityService {
|
|||
@IBootstrapService bootstrap: IBootstrapService,
|
||||
@IPluginService plugins: IPluginService,
|
||||
@IHostProcessService hostProcess: IHostProcessService,
|
||||
@ILogService private readonly log: ILogService,
|
||||
entriesOverride?: readonly CapabilityEntry[],
|
||||
) {
|
||||
if (entriesOverride !== undefined) {
|
||||
|
|
@ -98,6 +100,12 @@ export class CapabilityService implements ICapabilityService {
|
|||
});
|
||||
this.installProgress.set(entry.id, { running: false });
|
||||
} catch (error) {
|
||||
const step = this.installProgress.get(entry.id)?.step;
|
||||
this.log.warn('capability install failed', {
|
||||
capabilityId: entry.id,
|
||||
step,
|
||||
error,
|
||||
});
|
||||
this.installProgress.set(entry.id, {
|
||||
running: false,
|
||||
error: error instanceof Error ? error.message : String(error),
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
import { describe, expect, it } from 'vitest';
|
||||
|
||||
import { isError2 } from '#/_base/errors/errors';
|
||||
import type { ILogService, LogPayload } from '#/_base/log/log';
|
||||
import { CapabilityErrors } from '#/app/capability/errors';
|
||||
import { CapabilityService } from '#/app/capability/capabilityService';
|
||||
import type {
|
||||
|
|
@ -15,6 +16,8 @@ import type {
|
|||
CapabilityInstallReporter,
|
||||
} from '#/app/capability/types';
|
||||
|
||||
import { stubLog } from '../../_base/log/stubs';
|
||||
|
||||
function fakeEntry(overrides: {
|
||||
id: 'kimi-cu' | 'kimi-webbridge';
|
||||
pluginId?: string;
|
||||
|
|
@ -36,12 +39,16 @@ function fakeEntry(overrides: {
|
|||
};
|
||||
}
|
||||
|
||||
function fakeService(entries: readonly CapabilityEntry[]): CapabilityService {
|
||||
function fakeService(
|
||||
entries: readonly CapabilityEntry[],
|
||||
log: ILogService = stubLog(),
|
||||
): CapabilityService {
|
||||
// bootstrap / hostProcess are unused when entries are injected.
|
||||
return new CapabilityService(
|
||||
undefined as never,
|
||||
undefined as never,
|
||||
undefined as never,
|
||||
log,
|
||||
entries,
|
||||
);
|
||||
}
|
||||
|
|
@ -239,4 +246,42 @@ describe('CapabilityService', () => {
|
|||
expect(retried.install.error).toBeUndefined();
|
||||
expect(attempts).toBe(2);
|
||||
});
|
||||
|
||||
it('logs an install error with its last progress step when setup fails', async () => {
|
||||
const warnings: Array<{ message: string; payload?: LogPayload }> = [];
|
||||
let resolveLogged: (() => void) | undefined;
|
||||
const logged = new Promise<void>((resolve) => {
|
||||
resolveLogged = resolve;
|
||||
});
|
||||
const error = new Error('signature mismatch');
|
||||
const log = {
|
||||
...stubLog(),
|
||||
warn: (message: string, payload?: LogPayload) => {
|
||||
warnings.push({ message, payload });
|
||||
resolveLogged?.();
|
||||
},
|
||||
} satisfies ILogService;
|
||||
const service = fakeService(
|
||||
[
|
||||
fakeEntry({
|
||||
id: 'kimi-cu',
|
||||
install: async (report) => {
|
||||
report('runtime');
|
||||
throw error;
|
||||
},
|
||||
}),
|
||||
],
|
||||
log,
|
||||
);
|
||||
|
||||
await service.installCapability('kimi-cu');
|
||||
await logged;
|
||||
|
||||
expect(warnings).toEqual([
|
||||
{
|
||||
message: 'capability install failed',
|
||||
payload: { capabilityId: 'kimi-cu', step: 'runtime', error },
|
||||
},
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue