用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
直接命令不会经过审查 Prompt;运行前请先检查来源。
npx skills add https://github.com/majiayu000/claude-skill-registry --skill openai-chatkit-skill命令会保持在同一行。复制前请横向滚动并检查完整内容。
想先保存到本地?可下载 SkillsMP 当前能够提供的文件。
LLM token logprobs and calibration. Per-decision confidence, ECE, Brier, reliability diagrams, low-confidence triage.
Analyze LLM token logprobs and calibration. Use for per-decision confidence, ECE, Brier scores, reliability diagrams, and low-confidence triage.
回顾最近 N 天的 Claude Code 使用记录——扫描原始会话数据,按主题分组汇总"我都做了什么",并从个人操作系统视角输出模式、风险与增删建议。当用户说 /recap、"看看我这几天做了什么"、"回顾一下我最近的会话"、"这两天我用 claude 干了啥"、"活动回顾" 时使用。
基于 SOC 职业分类
正在显示 SKILL.md
| name | openai-chatkit-skill |
| description | Integrate OpenAI ChatKit for conversational AI interface |
| when-to-use | Building chat UI, handling messages, tool calls display |
This skill provides guidance for integrating OpenAI's ChatKit interface for conversational AI experiences.
src/
├── components/
│ └── chat/
│ ├── ChatWindow.tsx # Main chat container
│ ├── ChatMessage.tsx # Individual message display
│ ├── ChatInput.tsx # User input area
│ ├── ChatToolbar.tsx # Quick actions toolbar
│ └── typing-indicator.tsx
├── hooks/
│ └── useChat.ts # Chat state management
├── lib/
│ └── openai.ts # OpenAI client configuration
└── types/
└── chat.ts # Chat type definitions
// src/types/chat.ts
export interface ChatMessage {
id: string
role: 'user' | 'assistant' | 'system'
content: string
timestamp: Date
tools?: ToolCall[]
}
export interface ToolCall {
id: string
name: string
arguments: Record<string, unknown>
result?: unknown
}
export interface ChatState {
messages: ChatMessage[]
isLoading: boolean
error: string | null
}
export interface UseChatReturn extends ChatState {
sendMessage: (content: string) => Promise<void>
clearMessages: () => void
retry: () => Promise<void>
}
// src/lib/openai.ts
import OpenAI from 'openai'
export const openai = new OpenAI({
apiKey: process.env.NEXT_PUBLIC_OPENAI_API_KEY || process.env.OPENAI_API_KEY,
})
export interface ChatCompletionOptions {
model?: string
temperature?: number
max_tokens?: number
stream?: boolean
}
export async function createChatCompletion(
messages: ChatMessage[],
options: ChatCompletionOptions = {}
) {
const response = await openai.chat.completions.create({
model: options.model || 'gpt-4o',
messages: messages.map(m => ({
role: m.role,
content: m.content,
})),
temperature: options.temperature ?? 0.7,
: options. ?? ,
: options. ?? ,
: (),
})
response
}
() {
[
{
: ,
: {
: ,
: ,
: {
: ,
: {},
},
},
},
{
: ,
: {
: ,
: ,
: {
: ,
: {
: { : , : },
: { : , : },
: { : , : },
},
: [],
},
},
},
{
: ,
: {
: ,
: ,
: {
: ,
: {
: { : , : },
: { : , : },
: { : , : },
},
: [],
},
},
},
{
: ,
: {
: ,
: ,
: {
: ,
: {
: { : , : },
},
: [],
},
},
},
]
}
// src/hooks/useChat.ts
'use client'
import { useCallback, useState } from 'react'
import { ChatMessage, UseChatReturn } from '@/types/chat'
import { createChatCompletion } from '@/lib/openai'
import { v4 as uuidv4 } from 'uuid'
const SYSTEM_PROMPT = `You are a helpful AI assistant for task management.
You can help users create, update, and manage their tasks through natural language.
Always be helpful, friendly, and concise in your responses.`
export function useChat(): UseChatReturn {
const [messages, setMessages] = useState<ChatMessage[]>([
{
id: 'system',
role: 'system',
content: SYSTEM_PROMPT,
timestamp: new Date(),
},
])
const [isLoading, setIsLoading] = useState(false)
const [error, setError] = useState<string | null>(null)
const sendMessage = useCallback(async (content: string) => {
: = {
: (),
: ,
content,
: (),
}
( [...prev, userMessage])
()
()
{
response = (
[...messages, userMessage],
{ : }
)
: = {
: (),
: ,
: response.[]?.?. || ,
: (),
}
( [...prev, assistantMessage])
} (err) {
(err ? err. : )
} {
()
}
}, [messages])
clearMessages = ( {
([
{
: ,
: ,
: ,
: (),
},
])
}, [])
retry = ( () => {
lastUserMessage = [...messages].().( m. === )
(lastUserMessage) {
(lastUserMessage.)
}
}, [messages, sendMessage])
{
messages,
isLoading,
error,
sendMessage,
clearMessages,
retry,
}
}
// src/components/chat/ChatWindow.tsx
'use client'
import { useRef, useEffect } from 'react'
import { useChat } from '@/hooks/useChat'
import { ChatMessage } from './ChatMessage'
import { ChatInput } from './ChatInput'
export function ChatWindow() {
const { messages, isLoading, error, sendMessage } = useChat()
const messagesEndRef = useRef<HTMLDivElement>(null)
useEffect(() => {
messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' })
}, [messages])
const handleSend = async (content: string) => {
await sendMessage(content)
}
const assistantMessages = messages.filter(m => m.role === 'assistant')
const userMessages = messages.filter(m => m.role === 'user')
(
)
}
// src/components/chat/ChatMessage.tsx
import { ChatMessage as ChatMessageType } from '@/types/chat'
interface ChatMessageProps {
message: ChatMessageType
isLatest?: boolean
}
export function ChatMessage({ message, isLatest }: ChatMessageProps) {
const isUser = message.role === 'user'
return (
<div className={`flex ${isUser ? 'justify-end' : 'justify-start'}`}>
<div className={`max-w-[80%] ${isUser ? 'order-2' : 'order-1'}`}>
{/* Avatar */}
<div className={`flex items-center gap-2 mb-1 ${isUser ? 'flex-row-reverse' : ''}`}>
<div className={`
${ ? '' ' '}
`}>
{isUser ? 'U' : 'AI'}
{new Date(message.timestamp).toLocaleTimeString()}
{/* Message bubble */}
{message.content}
{/* Tool calls indicator */}
{message.tools && message.tools.length > 0 && (
{message.tools.map(tool => (
{tool.name}
))}
)}
)
}
// src/components/chat/ChatInput.tsx
'use client'
import { useState, useRef, useEffect } from 'react'
interface ChatInputProps {
onSend: (content: string) => Promise<void>
isLoading: boolean
}
export function ChatInput({ onSend, isLoading }: ChatInputProps) {
const [input, setInput] = useState('')
const textareaRef = useRef<HTMLTextAreaElement>(null)
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault()
if (!input.trim() || isLoading) return
const content = input.trim()
setInput('')
await onSend(content)
}
const handleKeyDown = (e: React.KeyboardEvent) => {
if (e.key === && !e.) {
e.()
(e)
}
}
( {
(textareaRef.) {
textareaRef... =
textareaRef... =
}
}, [input])
(
)
}
// Streaming chat implementation
export async function* streamChat(messages: ChatMessage[]) {
const response = await openai.chat.completions.create({
model: 'gpt-4o',
messages: messages.map(m => ({ role: m.role, content: m.content })),
stream: true,
})
for await (const chunk of response) {
const content = chunk.choices[0]?.delta?.content
if (content) {
yield content
}
}
}
// Usage in component
async function handleStreamingSend(content: string) {
const encoder = new TextEncoder()
const stream = await streamChat([...messages, userMessage])
// Display streaming content
for await ( chunk stream) {
( prev + chunk)
}
}