mirror of
https://github.com/getpaseo/paseo.git
synced 2026-11-11 10:57:07 +00:00
Add remote Paseo Agent configuration
This commit is contained in:
@@ -0,0 +1,80 @@
|
||||
import { describe, expect, test } from "vitest";
|
||||
|
||||
import { SessionInboundMessageSchema, SessionOutboundMessageSchema } from "./messages.js";
|
||||
|
||||
describe("Paseo Agent config RPC schemas", () => {
|
||||
test("parses provider config requests with providerType outside the message type field", () => {
|
||||
const parsed = SessionInboundMessageSchema.parse({
|
||||
type: "config.paseo_agent.set_provider.request",
|
||||
requestId: "req-set-openrouter",
|
||||
name: "openrouter-main",
|
||||
providerType: "openrouter",
|
||||
options: {
|
||||
apiKey: "sk-test",
|
||||
models: [{ id: "anthropic/claude-3.7-sonnet", reasoning: true }],
|
||||
},
|
||||
});
|
||||
|
||||
expect(parsed.type).toBe("config.paseo_agent.set_provider.request");
|
||||
expect(parsed.providerType).toBe("openrouter");
|
||||
});
|
||||
|
||||
test("parses redacted provider responses without raw secret fields", () => {
|
||||
const parsed = SessionOutboundMessageSchema.parse({
|
||||
type: "config.paseo_agent.get_providers.response",
|
||||
payload: {
|
||||
requestId: "req-get",
|
||||
defaultModel: "openrouter-main/anthropic/claude-3.7-sonnet",
|
||||
providers: [
|
||||
{
|
||||
name: "openrouter-main",
|
||||
providerType: "openrouter",
|
||||
baseUrl: "https://openrouter.ai/api/v1",
|
||||
api: "openai-completions",
|
||||
models: [{ id: "anthropic/claude-3.7-sonnet" }],
|
||||
auth: { kind: "api_key", configured: true, source: "literal" },
|
||||
available: true,
|
||||
error: null,
|
||||
},
|
||||
],
|
||||
error: null,
|
||||
},
|
||||
});
|
||||
|
||||
expect(parsed.payload.providers[0]?.providerType).toBe("openrouter");
|
||||
expect(JSON.stringify(parsed)).not.toContain("apiKey");
|
||||
});
|
||||
|
||||
test("preserves future OAuth credential fields on inbound schema parse", () => {
|
||||
const parsed = SessionInboundMessageSchema.parse({
|
||||
type: "config.paseo_agent.store_chatgpt_credential.request",
|
||||
requestId: "req-oauth",
|
||||
providerName: "chatgpt",
|
||||
credential: {
|
||||
type: "oauth",
|
||||
access: "access-token",
|
||||
refresh: "refresh-token",
|
||||
expires: 123,
|
||||
accountId: "acct_123",
|
||||
futureField: { keep: true },
|
||||
},
|
||||
});
|
||||
|
||||
expect(parsed.credential.futureField).toEqual({ keep: true });
|
||||
});
|
||||
|
||||
test("parses ChatGPT provider config separately from credential storage", () => {
|
||||
const parsed = SessionInboundMessageSchema.parse({
|
||||
type: "config.paseo_agent.set_provider.request",
|
||||
requestId: "req-set-chatgpt",
|
||||
name: "chatgpt",
|
||||
providerType: "openai-codex",
|
||||
options: {
|
||||
models: [{ id: "gpt-5.3-codex", reasoning: true }],
|
||||
},
|
||||
});
|
||||
|
||||
expect(parsed.providerType).toBe("openai-codex");
|
||||
expect(JSON.stringify(parsed)).not.toContain("access-token");
|
||||
});
|
||||
});
|
||||
@@ -1922,6 +1922,112 @@ export const ListProviderFeaturesRequestMessageSchema = z.object({
|
||||
requestId: z.string(),
|
||||
});
|
||||
|
||||
const PaseoAgentProviderTypeSchema = z.enum([
|
||||
"openrouter",
|
||||
"openai",
|
||||
"anthropic",
|
||||
"opencode",
|
||||
"openai-compatible",
|
||||
"openai-codex",
|
||||
"custom",
|
||||
]);
|
||||
|
||||
const PaseoAgentProviderModelConfigSchema = z
|
||||
.object({
|
||||
id: z.string().min(1),
|
||||
label: z.string().min(1).optional(),
|
||||
api: z.string().min(1).optional(),
|
||||
reasoning: z.boolean().optional(),
|
||||
contextWindow: z.number().int().positive().optional(),
|
||||
maxTokens: z.number().int().positive().optional(),
|
||||
})
|
||||
.strict();
|
||||
|
||||
const PaseoAgentSetProviderOptionsSchema = z
|
||||
.object({
|
||||
apiKey: z.string().min(1).optional(),
|
||||
baseUrl: z.string().url().optional(),
|
||||
api: z.string().min(1).optional(),
|
||||
headers: z.record(z.string()).optional(),
|
||||
authHeader: z.boolean().optional(),
|
||||
models: z.array(PaseoAgentProviderModelConfigSchema).min(1),
|
||||
})
|
||||
.strict();
|
||||
|
||||
const PaseoAgentOAuthCredentialSchema = z
|
||||
.object({
|
||||
type: z.literal("oauth"),
|
||||
access: z.string(),
|
||||
refresh: z.string(),
|
||||
expires: z.number(),
|
||||
accountId: z.string().min(1).optional(),
|
||||
})
|
||||
.passthrough();
|
||||
|
||||
export const PaseoAgentProviderAuthStateSchema = z
|
||||
.object({
|
||||
kind: z.enum(["api_key", "oauth", "none"]),
|
||||
configured: z.boolean(),
|
||||
source: z
|
||||
.enum(["literal", "env", "default_env", "command", "stored", "refresh_token"])
|
||||
.optional(),
|
||||
hint: z.string().optional(),
|
||||
})
|
||||
.strict();
|
||||
|
||||
export const RedactedPaseoAgentProviderConfigSchema = z
|
||||
.object({
|
||||
name: z.string().min(1),
|
||||
providerType: z.enum([
|
||||
"openrouter",
|
||||
"openai",
|
||||
"anthropic",
|
||||
"opencode",
|
||||
"openai-compatible",
|
||||
"openai-codex",
|
||||
"custom",
|
||||
]),
|
||||
baseUrl: z.string().optional(),
|
||||
api: z.string().optional(),
|
||||
models: z.array(PaseoAgentProviderModelConfigSchema),
|
||||
auth: PaseoAgentProviderAuthStateSchema,
|
||||
available: z.boolean(),
|
||||
error: z.string().nullable().optional(),
|
||||
})
|
||||
.strict();
|
||||
|
||||
export const PaseoAgentGetProvidersRequestSchema = z.object({
|
||||
type: z.literal("config.paseo_agent.get_providers.request"),
|
||||
requestId: z.string(),
|
||||
});
|
||||
|
||||
export const PaseoAgentSetProviderRequestSchema = z.object({
|
||||
type: z.literal("config.paseo_agent.set_provider.request"),
|
||||
requestId: z.string(),
|
||||
name: z.string().trim().min(1),
|
||||
providerType: PaseoAgentProviderTypeSchema,
|
||||
options: PaseoAgentSetProviderOptionsSchema,
|
||||
});
|
||||
|
||||
export const PaseoAgentRemoveProviderRequestSchema = z.object({
|
||||
type: z.literal("config.paseo_agent.remove_provider.request"),
|
||||
requestId: z.string(),
|
||||
name: z.string().trim().min(1),
|
||||
});
|
||||
|
||||
export const PaseoAgentSetDefaultModelRequestSchema = z.object({
|
||||
type: z.literal("config.paseo_agent.set_default_model.request"),
|
||||
requestId: z.string(),
|
||||
model: z.string().trim().min(1).nullable(),
|
||||
});
|
||||
|
||||
export const PaseoAgentStoreChatGptCredentialRequestSchema = z.object({
|
||||
type: z.literal("config.paseo_agent.store_chatgpt_credential.request"),
|
||||
requestId: z.string(),
|
||||
providerName: z.string().trim().min(1),
|
||||
credential: PaseoAgentOAuthCredentialSchema,
|
||||
});
|
||||
|
||||
export const ListCommandsRequestSchema = z.object({
|
||||
type: z.literal("list_commands_request"),
|
||||
agentId: z.string(),
|
||||
@@ -2073,6 +2179,11 @@ export const SessionInboundMessageSchema = z.discriminatedUnion("type", [
|
||||
ListProviderModelsRequestMessageSchema,
|
||||
ListProviderModesRequestMessageSchema,
|
||||
ListProviderFeaturesRequestMessageSchema,
|
||||
PaseoAgentGetProvidersRequestSchema,
|
||||
PaseoAgentSetProviderRequestSchema,
|
||||
PaseoAgentRemoveProviderRequestSchema,
|
||||
PaseoAgentSetDefaultModelRequestSchema,
|
||||
PaseoAgentStoreChatGptCredentialRequestSchema,
|
||||
ListAvailableProvidersRequestMessageSchema,
|
||||
GetProvidersSnapshotRequestMessageSchema,
|
||||
RefreshProvidersSnapshotRequestMessageSchema,
|
||||
@@ -2364,6 +2475,8 @@ export const ServerInfoStatusPayloadSchema = z
|
||||
daemonSelfUpdate: z.boolean().optional(),
|
||||
// COMPAT(agentForkContext): added in v0.1.102, remove gate after 2026-12-28.
|
||||
agentForkContext: z.boolean().optional(),
|
||||
// COMPAT(paseoAgentConfig): added in v0.1.85, remove gate after 2026-11-30.
|
||||
paseoAgentConfig: z.boolean().optional(),
|
||||
})
|
||||
.optional(),
|
||||
})
|
||||
@@ -3870,6 +3983,57 @@ export const ListProviderFeaturesResponseMessageSchema = z.object({
|
||||
}),
|
||||
});
|
||||
|
||||
export const PaseoAgentGetProvidersResponseSchema = z.object({
|
||||
type: z.literal("config.paseo_agent.get_providers.response"),
|
||||
payload: z.object({
|
||||
requestId: z.string(),
|
||||
defaultModel: z.string().nullable(),
|
||||
providers: z.array(RedactedPaseoAgentProviderConfigSchema),
|
||||
error: z.string().nullable(),
|
||||
}),
|
||||
});
|
||||
|
||||
export const PaseoAgentSetProviderResponseSchema = z.object({
|
||||
type: z.literal("config.paseo_agent.set_provider.response"),
|
||||
payload: z.object({
|
||||
requestId: z.string(),
|
||||
success: z.boolean(),
|
||||
provider: RedactedPaseoAgentProviderConfigSchema.nullable(),
|
||||
error: z.string().nullable(),
|
||||
}),
|
||||
});
|
||||
|
||||
export const PaseoAgentRemoveProviderResponseSchema = z.object({
|
||||
type: z.literal("config.paseo_agent.remove_provider.response"),
|
||||
payload: z.object({
|
||||
requestId: z.string(),
|
||||
success: z.boolean(),
|
||||
removed: z.boolean(),
|
||||
error: z.string().nullable(),
|
||||
}),
|
||||
});
|
||||
|
||||
export const PaseoAgentSetDefaultModelResponseSchema = z.object({
|
||||
type: z.literal("config.paseo_agent.set_default_model.response"),
|
||||
payload: z.object({
|
||||
requestId: z.string(),
|
||||
success: z.boolean(),
|
||||
defaultModel: z.string().nullable(),
|
||||
error: z.string().nullable(),
|
||||
}),
|
||||
});
|
||||
|
||||
export const PaseoAgentStoreChatGptCredentialResponseSchema = z.object({
|
||||
type: z.literal("config.paseo_agent.store_chatgpt_credential.response"),
|
||||
payload: z.object({
|
||||
requestId: z.string(),
|
||||
success: z.boolean(),
|
||||
providerName: z.string(),
|
||||
auth: PaseoAgentProviderAuthStateSchema,
|
||||
error: z.string().nullable(),
|
||||
}),
|
||||
});
|
||||
|
||||
const ProviderAvailabilitySchema = z.object({
|
||||
provider: AgentProviderSchema,
|
||||
available: z.boolean(),
|
||||
@@ -4265,6 +4429,11 @@ export const SessionOutboundMessageSchema = z.discriminatedUnion("type", [
|
||||
ListProviderModelsResponseMessageSchema,
|
||||
ListProviderModesResponseMessageSchema,
|
||||
ListProviderFeaturesResponseMessageSchema,
|
||||
PaseoAgentGetProvidersResponseSchema,
|
||||
PaseoAgentSetProviderResponseSchema,
|
||||
PaseoAgentRemoveProviderResponseSchema,
|
||||
PaseoAgentSetDefaultModelResponseSchema,
|
||||
PaseoAgentStoreChatGptCredentialResponseSchema,
|
||||
ListAvailableProvidersResponseSchema,
|
||||
GetProvidersSnapshotResponseMessageSchema,
|
||||
ProvidersSnapshotUpdateMessageSchema,
|
||||
@@ -4397,6 +4566,22 @@ export type ListProviderModesResponseMessage = z.infer<
|
||||
export type ListProviderFeaturesResponseMessage = z.infer<
|
||||
typeof ListProviderFeaturesResponseMessageSchema
|
||||
>;
|
||||
export type RedactedPaseoAgentProviderConfig = z.infer<
|
||||
typeof RedactedPaseoAgentProviderConfigSchema
|
||||
>;
|
||||
export type PaseoAgentProviderAuthState = z.infer<typeof PaseoAgentProviderAuthStateSchema>;
|
||||
export type PaseoAgentOAuthCredential = z.infer<typeof PaseoAgentOAuthCredentialSchema>;
|
||||
export type PaseoAgentGetProvidersResponse = z.infer<typeof PaseoAgentGetProvidersResponseSchema>;
|
||||
export type PaseoAgentSetProviderResponse = z.infer<typeof PaseoAgentSetProviderResponseSchema>;
|
||||
export type PaseoAgentRemoveProviderResponse = z.infer<
|
||||
typeof PaseoAgentRemoveProviderResponseSchema
|
||||
>;
|
||||
export type PaseoAgentSetDefaultModelResponse = z.infer<
|
||||
typeof PaseoAgentSetDefaultModelResponseSchema
|
||||
>;
|
||||
export type PaseoAgentStoreChatGptCredentialResponse = z.infer<
|
||||
typeof PaseoAgentStoreChatGptCredentialResponseSchema
|
||||
>;
|
||||
export type ListAvailableProvidersResponse = z.infer<typeof ListAvailableProvidersResponseSchema>;
|
||||
export type DaemonGetStatusResponse = z.infer<typeof DaemonGetStatusResponseSchema>;
|
||||
export type DaemonGetPairingOfferResponse = z.infer<typeof DaemonGetPairingOfferResponseSchema>;
|
||||
@@ -4473,6 +4658,15 @@ export type ListProviderModesRequestMessage = z.infer<typeof ListProviderModesRe
|
||||
export type ListProviderFeaturesRequestMessage = z.infer<
|
||||
typeof ListProviderFeaturesRequestMessageSchema
|
||||
>;
|
||||
export type PaseoAgentGetProvidersRequest = z.infer<typeof PaseoAgentGetProvidersRequestSchema>;
|
||||
export type PaseoAgentSetProviderRequest = z.infer<typeof PaseoAgentSetProviderRequestSchema>;
|
||||
export type PaseoAgentRemoveProviderRequest = z.infer<typeof PaseoAgentRemoveProviderRequestSchema>;
|
||||
export type PaseoAgentSetDefaultModelRequest = z.infer<
|
||||
typeof PaseoAgentSetDefaultModelRequestSchema
|
||||
>;
|
||||
export type PaseoAgentStoreChatGptCredentialRequest = z.infer<
|
||||
typeof PaseoAgentStoreChatGptCredentialRequestSchema
|
||||
>;
|
||||
export type ListAvailableProvidersRequestMessage = z.infer<
|
||||
typeof ListAvailableProvidersRequestMessageSchema
|
||||
>;
|
||||
|
||||
Reference in New Issue
Block a user