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:
parent
ccc04cc172
commit
8d272a9c76
1 changed files with 17 additions and 3 deletions
|
|
@ -1,6 +1,9 @@
|
||||||
import { useState, useCallback } from 'react';
|
import { useState, useCallback } from 'react';
|
||||||
import { useCVMClient } from '@/hooks/useCVMClient';
|
import { useCVMClient } from '@/hooks/useCVMClient';
|
||||||
import { callSasquatchAI, parseToolCall, type ChatTurn } from '@/lib/sasquatchBrain';
|
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 {
|
export interface CrewAgentMessage {
|
||||||
id: string;
|
id: string;
|
||||||
|
|
@ -166,6 +169,8 @@ Rules:
|
||||||
*/
|
*/
|
||||||
export function useCrewAgentChat(ctx: CrewContext) {
|
export function useCrewAgentChat(ctx: CrewContext) {
|
||||||
const cvm = useCVMClient();
|
const cvm = useCVMClient();
|
||||||
|
const { user } = useCurrentUser();
|
||||||
|
const { isPro, receiptEvent } = useSasquatchPro();
|
||||||
const [messages, setMessages] = useState<CrewAgentMessage[]>([]);
|
const [messages, setMessages] = useState<CrewAgentMessage[]>([]);
|
||||||
const [isThinking, setIsThinking] = useState(false);
|
const [isThinking, setIsThinking] = useState(false);
|
||||||
|
|
||||||
|
|
@ -206,12 +211,21 @@ export function useCrewAgentChat(ctx: CrewContext) {
|
||||||
append({ role: 'user', text: q });
|
append({ role: 'user', text: q });
|
||||||
|
|
||||||
try {
|
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);
|
const system = buildCrewSystemPrompt(ctx);
|
||||||
// First pass — AI answers directly from crew memory or emits a tool call.
|
// First pass — AI answers directly from crew memory or emits a tool call.
|
||||||
const firstPass: ChatTurn[] = [
|
const firstPass: ChatTurn[] = [
|
||||||
{ role: 'user', content: `${system}\n\n---\n\nMember: ${q}` },
|
{ 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);
|
const toolCall = parseToolCall(aiText);
|
||||||
|
|
||||||
if (!toolCall) {
|
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
|
- 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.`,
|
- Keep it short and skater-friendly. Never invent data.`,
|
||||||
},
|
},
|
||||||
]);
|
], 400, undefined, authHeaders);
|
||||||
|
|
||||||
append({
|
append({
|
||||||
role: 'agent',
|
role: 'agent',
|
||||||
|
|
@ -263,7 +277,7 @@ ${JSON.stringify(toolResult, null, 2)}
|
||||||
setIsThinking(false);
|
setIsThinking(false);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[ctx, isThinking, append, runTool],
|
[ctx, isThinking, append, runTool, isPro, receiptEvent, user],
|
||||||
);
|
);
|
||||||
|
|
||||||
return { messages, isThinking, send };
|
return { messages, isThinking, send };
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue