Files
paseo/plugins/muse-provider/server/commands.ts
T
Mohamed Boudraandmillerben95 8332f4d1ff feat(muse): add Muse Code as a built-in provider plugin (#5719)
* test(muse): record real host protocol fixtures

* feat(muse): add built-in MSP provider

Co-authored-by: millerben95 <millerben95@users.noreply.github.com>

* fix(muse): expose provider settings in the app

The daemon registered host settings without a client contribution, leaving sandbox, network, and workspace trust unreachable. Share the definition with a settings screen and expose it through Command Center even when installed plugins are disabled.

* docs(muse): publish setup and provider support

* test: correct runtime fixtures and restart readiness

* fix(muse): hide reminder housekeeping from the timeline

* fix(muse): use the official Muse Code mark

Source: https://muse.ai/images/favicon/app-squiggle.svg

Preserve the official silhouette path verbatim. Remove its gradient definition and use currentColor, scaling the original 100-unit coordinates into the 24-unit viewBox. Black silhouette renders match pixel-for-pixel.

* fix(muse): adapt to current plugin APIs

Use the screen API introduced with sidebar plugin items. Usage reports now come from source account discovery; remove the retired agent usage-reference request and headline marker, and exercise discovery through the existing provider fixtures.

---------

Co-authored-by: millerben95 <millerben95@users.noreply.github.com>
2026-09-30 14:56:41 +01:00

57 lines
1.9 KiB
TypeScript

import type { ProviderEvent, ProviderPrompt } from "@getpaseo/plugin/server/provider";
import type { TurnStartParams } from "./msp.js";
import { MspConnection } from "./connection.js";
import { ackSchema, skillsSchema } from "./wire.js";
import { MuseError } from "./errors.js";
export class Commands {
private selectors = new Set<string>();
constructor(
private readonly host: MspConnection,
private readonly sessionId: string,
private readonly id: string,
private readonly emit: (event: ProviderEvent) => void,
) {}
async refresh(): Promise<void> {
const { skills } = await this.host.request(
"skill/list",
{ sessionId: this.sessionId },
skillsSchema,
);
this.selectors = new Set(skills.map((skill) => skill.selector));
this.emit({
type: "session.commands",
sessionId: this.id,
commands: [
{ name: "compact", description: "Compact conversation context" },
...skills
.filter((skill) => skill.selector !== "compact")
.map((skill) => ({
name: skill.selector,
description: skill.description,
argumentHint: skill.argumentHint,
})),
],
});
}
async compact(prompt: ProviderPrompt): Promise<boolean> {
if (prompt.input.type !== "command" || prompt.input.name !== "compact") return false;
await this.host.command("session/compact", { sessionId: this.sessionId }, ackSchema);
this.emit({
type: "session.prompt_result",
sessionId: this.id,
clientMessageId: prompt.clientMessageId,
result: { type: "completed" },
});
return true;
}
input(
command: Extract<ProviderPrompt["input"], { type: "command" }>,
): TurnStartParams["input"][number] {
if (!this.selectors.has(command.name))
throw new MuseError("unknownCommand", `Muse skill is unavailable: ${command.name}`);
return { type: "skill", selector: command.name, arguments: command.arguments };
}
}