feat(sasquatch-pro): crew agent sends Pro credentials too

useCrewAgentChat now signs the same NIP-98 auth + attaches the viewer's Pro
receipt (when they have one), so the proxy's Pro gate lets Pro users through the
gateway models; everyone else still falls back to the keyless provider.
This commit is contained in:
SkateSpots 2026-09-27 14:27:02 +07:00
parent ccc04cc172
commit 8d272a9c76

View file

@ -1,6 +1,9 @@
import { useState, useCallback } from 'react';
import { useCVMClient } from '@/hooks/useCVMClient';
import { callSasquatchAI, parseToolCall, type ChatTurn } from '@/lib/sasquatchBrain';
import { useCurrentUser } from '@/hooks/useCurrentUser';
import { useSasquatchPro } from '@/hooks/useSasquatchPro';
import { buildProAuthHeaders } from '@/lib/proAuth';
export interface CrewAgentMessage {
id: string;
@ -166,6 +169,8 @@ Rules:
*/
export function useCrewAgentChat(ctx: CrewContext) {
const cvm = useCVMClient();
const { user } = useCurrentUser();
const { isPro, receiptEvent } = useSasquatchPro();
const [messages, setMessages] = useState<CrewAgentMessage[]>([]);
const [isThinking, setIsThinking] = useState(false);
@ -206,12 +211,21 @@ export function useCrewAgentChat(ctx: CrewContext) {
append({ role: 'user', text: q });
try {
// Pass the viewer's identity + Pro pass so the proxy's gate (when on)
// lets Pro users through; others fall back to the keyless provider.
const authHeaders = isPro
? await buildProAuthHeaders({
pubkey: user?.pubkey,
signEvent: user ? (e) => user.signer.signEvent(e) : undefined,
receiptEvent,
})
: {};
const system = buildCrewSystemPrompt(ctx);
// First pass — AI answers directly from crew memory or emits a tool call.
const firstPass: ChatTurn[] = [
{ role: 'user', content: `${system}\n\n---\n\nMember: ${q}` },
];
const aiText = await callSasquatchAI(firstPass);
const aiText = await callSasquatchAI(firstPass, 400, undefined, authHeaders);
const toolCall = parseToolCall(aiText);
if (!toolCall) {
@ -246,7 +260,7 @@ ${JSON.stringify(toolResult, null, 2)}
- If count > 0: a short intro line — the app shows the results as cards below your message
- Keep it short and skater-friendly. Never invent data.`,
},
]);
], 400, undefined, authHeaders);
append({
role: 'agent',
@ -263,7 +277,7 @@ ${JSON.stringify(toolResult, null, 2)}
setIsThinking(false);
}
},
[ctx, isThinking, append, runTool],
[ctx, isThinking, append, runTool, isPro, receiptEvent, user],
);
return { messages, isThinking, send };