Help agents diagnose Paseo provider problems (#3243)
* feat(skills): add Paseo help and provider diagnostics Give support agents a topology-aware troubleshooting entry point backed by the deployed documentation index, and expose the daemon provider diagnostic through the CLI so agents can inspect the affected host directly. Agent-launching skills now use configured profiles instead of the removed orchestration preferences. * test(cli): keep provider diagnostics on real boundaries Remove the internal client mock and preserve its normalization and host-targeting assertions through the existing isolated-daemon coverage.
This commit is contained in:
@@ -0,0 +1,45 @@
|
||||
import type { Command } from "commander";
|
||||
import { connectToDaemon } from "../../utils/client.js";
|
||||
import type { CommandOptions, OutputSchema, SingleResult } from "../../output/index.js";
|
||||
|
||||
export interface ProviderDiagnosticResult {
|
||||
provider: string;
|
||||
diagnostic: string;
|
||||
}
|
||||
|
||||
export const providerDiagnosticSchema: OutputSchema<ProviderDiagnosticResult> = {
|
||||
idField: "provider",
|
||||
columns: [
|
||||
{ header: "PROVIDER", field: "provider" },
|
||||
{ header: "DIAGNOSTIC", field: "diagnostic" },
|
||||
],
|
||||
renderHuman(result) {
|
||||
if (result.type === "single") return result.data.diagnostic;
|
||||
return result.data.map((entry) => entry.diagnostic).join("\n\n");
|
||||
},
|
||||
};
|
||||
|
||||
export interface ProviderDiagnosticOptions extends CommandOptions {
|
||||
host?: string;
|
||||
}
|
||||
|
||||
export async function runDiagnosticCommand(
|
||||
provider: string,
|
||||
options: ProviderDiagnosticOptions,
|
||||
_command: Command,
|
||||
): Promise<SingleResult<ProviderDiagnosticResult>> {
|
||||
const client = await connectToDaemon({ host: options.host });
|
||||
try {
|
||||
const result = await client.getProviderDiagnostic(provider.trim().toLowerCase());
|
||||
return {
|
||||
type: "single",
|
||||
data: {
|
||||
provider: result.provider,
|
||||
diagnostic: result.diagnostic,
|
||||
},
|
||||
schema: providerDiagnosticSchema,
|
||||
};
|
||||
} finally {
|
||||
await client.close();
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
import { Command } from "commander";
|
||||
import { runLsCommand } from "./ls.js";
|
||||
import { runModelsCommand } from "./models.js";
|
||||
import { runDiagnosticCommand } from "./diagnostic.js";
|
||||
import { withOutput } from "../../output/index.js";
|
||||
import { addJsonAndDaemonHostOptions } from "../../utils/command-options.js";
|
||||
|
||||
@@ -19,5 +20,12 @@ export function createProviderCommand(): Command {
|
||||
.option("--thinking", "Include thinking option IDs for each model"),
|
||||
).action(withOutput(runModelsCommand));
|
||||
|
||||
addJsonAndDaemonHostOptions(
|
||||
provider
|
||||
.command("diagnostic")
|
||||
.description("Show provider installation, environment, and availability diagnostics")
|
||||
.argument("<provider>", "Provider name"),
|
||||
).action(withOutput(runDiagnosticCommand));
|
||||
|
||||
return provider;
|
||||
}
|
||||
|
||||
@@ -17,6 +17,8 @@
|
||||
* - provider models opencode lists opencode models
|
||||
* - provider models unknown fails with error
|
||||
* - provider models --json outputs valid JSON
|
||||
* - provider diagnostic shows the daemon's provider diagnostic
|
||||
* - provider diagnostic --json returns structured output
|
||||
*/
|
||||
|
||||
import assert from "node:assert";
|
||||
@@ -44,6 +46,11 @@ interface ProviderListRow {
|
||||
enabled: string;
|
||||
}
|
||||
|
||||
interface ProviderDiagnostic {
|
||||
provider: string;
|
||||
diagnostic: string;
|
||||
}
|
||||
|
||||
const EXPECTED_CLAUDE_MODELS = [
|
||||
{
|
||||
id: "claude-opus-5",
|
||||
@@ -190,6 +197,7 @@ try {
|
||||
assert.strictEqual(result.exitCode, 0, "provider --help should exit 0");
|
||||
assert(result.stdout.includes("ls"), "help should mention ls");
|
||||
assert(result.stdout.includes("models"), "help should mention models");
|
||||
assert(result.stdout.includes("diagnostic"), "help should mention diagnostic");
|
||||
console.log("✓ provider --help shows subcommands\n");
|
||||
}
|
||||
|
||||
@@ -424,6 +432,39 @@ try {
|
||||
);
|
||||
console.log("✓ provider models --quiet outputs model IDs only\n");
|
||||
}
|
||||
|
||||
// Test 12: provider diagnostic shows the daemon's provider diagnostic
|
||||
{
|
||||
console.log("Test 12: provider diagnostic shows the daemon's provider diagnostic");
|
||||
const result = await ctx.paseo([
|
||||
"provider",
|
||||
"diagnostic",
|
||||
" Claude ",
|
||||
"--host",
|
||||
`127.0.0.1:${ctx.port}`,
|
||||
]);
|
||||
assert.strictEqual(result.exitCode, 0, "provider diagnostic should exit 0");
|
||||
assert(result.stdout.includes("Claude Code"), "diagnostic should identify the provider");
|
||||
assert(result.stdout.includes("Daemon PATH:"), "diagnostic should include the daemon PATH");
|
||||
assert(result.stdout.includes("Resolved path:"), "diagnostic should include binary resolution");
|
||||
assert(result.stdout.includes("Version:"), "diagnostic should include the provider version");
|
||||
assert(result.stdout.includes("Status:"), "diagnostic should include provider status");
|
||||
console.log("✓ provider diagnostic shows the daemon's provider diagnostic\n");
|
||||
}
|
||||
|
||||
// Test 13: provider diagnostic --json returns structured output
|
||||
{
|
||||
console.log("Test 13: provider diagnostic --json returns structured output");
|
||||
const result = await ctx.paseo(["provider", "diagnostic", "claude", "--json"]);
|
||||
assert.strictEqual(result.exitCode, 0, "provider diagnostic --json should exit 0");
|
||||
const data = JSON.parse(result.stdout.trim()) as ProviderDiagnostic;
|
||||
assert.strictEqual(data.provider, "claude", "JSON should identify the provider");
|
||||
assert(data.diagnostic.includes("Daemon PATH:"), "JSON should include the daemon PATH");
|
||||
assert(data.diagnostic.includes("Resolved path:"), "JSON should include binary resolution");
|
||||
assert(data.diagnostic.includes("Version:"), "JSON should include the provider version");
|
||||
assert(data.diagnostic.includes("Status:"), "JSON should include provider status");
|
||||
console.log("✓ provider diagnostic --json returns structured output\n");
|
||||
}
|
||||
} finally {
|
||||
await ctx.stop();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user