ai-sdk-6 — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited ai-sdk-6 (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
Apply this skill only to ai@6 projects. Resolve compatible provider and UI packages from the existing manifest/lockfile. Use ai-sdk when the major is unknown and ai-sdk-7 for an authorized upgrade.
Read the resolved ai/docs/, provider docs and source/types for the exact minor release. In a monorepo, resolve from the app using the dependency. Default web docs and repository main can describe v7. ai bundles docs/ from 6.0.32; the tree mirrors the website paths (mapping in ai-sdk). If installed docs are unavailable, select the ai@<resolved-version> tag in vercel/ai and read content/docs/. Feature links here use a checked v6 documentation snapshot as a fallback; match the project's release when available. This tag selects documentation, not an application dependency version.
system; ToolLoopAgent uses instructions.stopWhen: stepCountIs(...). Text functions default to onestep (tool execution without a follow-up answer); ToolLoopAgent defaults to 20.
convertToModelMessages is async; await it.Output for new schema output; legacy objectfunctions are deprecated.
inputSchema; SDK-executed approval is tool-level needsApproval.V6 does not know v7's toolApproval: unless a typecheck rejects it, it is ignored and the tool runs without approval.
useChat owns messages and stream status, not form input. Use theappropriate transport and UI-message response protocol.
onFinish; result usage is final-step usage,while totalUsage covers all steps.
Use a configured model verified for the actual provider. Typecheck and test a multi-turn stream with relevant tool/approval/error states after integration changes.
Checked with [email protected], @ai-sdk/[email protected], [email protected], React 19 and TypeScript 5.9: tsc --noEmit, plus a mock-model run through one tool step and the follow-up answer. A string model resolves through the AI Gateway. In v7, system, stepCountIs and result.toUIMessageStreamResponse() become instructions, isStepCount and createUIMessageStreamResponse({ stream: toUIMessageStream({ stream: result.stream }) }).
// app/api/chat/route.ts
import { convertToModelMessages, stepCountIs, streamText, tool, validateUIMessages,
type InferUITools, type UIDataTypes, type UIMessage } from 'ai';
import { z } from 'zod';
const tools = {
weather: tool({
inputSchema: z.object({ city: z.string() }),
execute: async ({ city }) => ({ city, celsius: 21 }),
}),
};
export type ChatMessage = UIMessage<never, UIDataTypes, InferUITools<typeof tools>>;
export async function POST(req: Request) {
const { messages } = await req.json();
const uiMessages = await validateUIMessages<ChatMessage>({ messages, tools });
const result = streamText({
model: 'provider/model-id', // configured gateway ID, or a provider instance
system: 'Answer briefly.',
messages: await convertToModelMessages(uiMessages),
tools,
stopWhen: stepCountIs(5),
});
return result.toUIMessageStreamResponse();
}// app/page.tsx
'use client';
import { useChat } from '@ai-sdk/react';
import { DefaultChatTransport } from 'ai';
import type { ChatMessage } from './api/chat/route';
const transport = new DefaultChatTransport<ChatMessage>({ api: '/api/chat' });
export default function Chat() {
const { messages, sendMessage, status } = useChat<ChatMessage>({ transport });
return (
<form action={(form) => void sendMessage({ text: String(form.get('text')) })}>
{messages.map((m) => <div key={m.id}>{m.parts.map((part, i) =>
part.type === 'text' ? <p key={i}>{part.text}</p>
: part.type === 'tool-weather' && part.state === 'output-available'
? <p key={i}>{part.output.city}: {part.output.celsius} °C</p> : null)}</div>)}
<input name="text" disabled={status === 'submitted' || status === 'streaming'} />
</form>
);
}~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.