restore: skills

This commit is contained in:
oboard
2026-03-31 20:11:19 +08:00
parent 33c1de7c75
commit 0f21b48891
38 changed files with 1756 additions and 78 deletions

View File

@@ -12,14 +12,102 @@ export type Logger = {
export type ClaudeForChromeContext = {
serverName?: string
logger?: Logger
[key: string]: unknown
}
export const BROWSER_TOOLS: Array<{ name: string }> = []
export const BROWSER_TOOLS: Array<{ name: string; description: string }> = [
{
name: 'navigate',
description: 'Navigate a browser tab to a URL.',
},
{
name: 'read_page',
description: 'Capture high-level page state from the active tab.',
},
{
name: 'get_page_text',
description: 'Read visible page text from the active tab.',
},
{
name: 'find',
description: 'Find a pattern within page content.',
},
{
name: 'form_input',
description: 'Fill or update form inputs in the page.',
},
{
name: 'computer',
description: 'Perform browser-scoped mouse and keyboard actions.',
},
{
name: 'javascript_tool',
description: 'Run page-scoped JavaScript in the browser tab.',
},
{
name: 'tabs_context_mcp',
description: 'List or inspect browser tabs.',
},
{
name: 'tabs_create_mcp',
description: 'Create a new browser tab.',
},
{
name: 'resize_window',
description: 'Resize the browser window.',
},
{
name: 'upload_image',
description: 'Upload an image into the current page flow.',
},
{
name: 'read_console_messages',
description: 'Read browser console messages.',
},
{
name: 'read_network_requests',
description: 'Read captured network requests.',
},
{
name: 'shortcuts_list',
description: 'List extension/browser shortcuts.',
},
{
name: 'shortcuts_execute',
description: 'Execute a configured extension/browser shortcut.',
},
{
name: 'gif_creator',
description: 'Create or manage simple browser recordings.',
},
{
name: 'update_plan',
description: 'Update an in-browser action plan.',
},
]
export function createClaudeForChromeMcpServer(context: ClaudeForChromeContext) {
let closed = false
const handlers = new Map<unknown, unknown>()
export function createClaudeForChromeMcpServer(_context: ClaudeForChromeContext) {
return {
async connect() {},
setRequestHandler() {},
async close() {},
async connect() {
context.logger?.warn(
'Claude in Chrome MCP is running with a restored compatibility shim; browser actions are not available in this workspace.',
)
},
setRequestHandler(schema: unknown, handler: unknown) {
handlers.set(schema, handler)
},
async close() {
closed = true
handlers.clear()
context.logger?.info(
'Claude in Chrome MCP shim closed.',
)
},
get isClosed() {
return closed
},
}
}

View File

@@ -5,32 +5,10 @@ export const DEFAULT_GRANT_FLAGS = {
export const API_RESIZE_PARAMS = {}
export function targetImageSize(width: number, height: number) {
return [width, height] as const
}
export function buildComputerUseTools() {
return [] as Array<{ name: string }>
}
export function createComputerUseMcpServer() {
return {
async connect() {},
setRequestHandler() {},
async close() {},
}
}
export function bindSessionContext() {
return async () => ({
is_error: true,
content: [
{
type: 'text',
text: 'Computer use is unavailable in the restored development build.',
},
],
})
export type ToolDef = {
name: string
description: string
inputSchema?: Record<string, unknown>
}
export type DisplayGeometry = Record<string, unknown>
@@ -48,12 +26,170 @@ export type ScreenshotDims = {
originX?: number
originY?: number
}
export type CuPermissionRequest = Record<string, unknown>
export type CuPermissionResponse = Record<string, unknown>
export type CuPermissionRequest = {
apps?: Array<{ bundleId?: string; displayName?: string }>
flags?: Record<string, boolean>
tccState?: { accessibility?: boolean; screenRecording?: boolean }
}
export type CuPermissionResponse = {
granted: Array<{ bundleId?: string; displayName?: string; grantedAt?: string }>
denied: Array<{ bundleId?: string; displayName?: string }>
flags: Record<string, boolean>
}
export type CuCallToolResult = {
is_error?: boolean
content?: Array<{ type: string; text?: string }>
content?: Array<{
type: string
text?: string
mimeType?: string
data?: string
}>
telemetry?: Record<string, unknown>
}
export type ComputerUseSessionContext = Record<string, unknown>
export type ComputerUseSessionContext = {
onPermissionRequest?: (
req: CuPermissionRequest,
signal?: AbortSignal,
) => Promise<CuPermissionResponse> | CuPermissionResponse
getAllowedApps?: () => Array<{ bundleId?: string; displayName?: string }>
getGrantFlags?: () => Record<string, boolean>
[key: string]: unknown
}
export type ComputerExecutor = Record<string, unknown>
function successText(text: string): CuCallToolResult {
return {
content: [{ type: 'text', text }],
}
}
function errorText(text: string): CuCallToolResult {
return {
is_error: true,
content: [{ type: 'text', text }],
}
}
export function targetImageSize(width: number, height: number) {
return [width, height] as const
}
const TOOL_DEFS: ToolDef[] = [
{
name: 'request_access',
description:
'Request access to applications and computer-use permissions for this session.',
},
{
name: 'list_granted_applications',
description: 'List applications currently granted for computer use.',
},
{ name: 'screenshot', description: 'Capture a screenshot.' },
{ name: 'zoom', description: 'Capture a zoomed screenshot region.' },
{ name: 'cursor_position', description: 'Read the current cursor position.' },
{ name: 'mouse_move', description: 'Move the mouse cursor.' },
{ name: 'left_click', description: 'Left click at a coordinate.' },
{ name: 'right_click', description: 'Right click at a coordinate.' },
{ name: 'middle_click', description: 'Middle click at a coordinate.' },
{ name: 'double_click', description: 'Double click at a coordinate.' },
{ name: 'triple_click', description: 'Triple click at a coordinate.' },
{ name: 'left_mouse_down', description: 'Press the left mouse button.' },
{ name: 'left_mouse_up', description: 'Release the left mouse button.' },
{ name: 'left_click_drag', description: 'Drag with the left mouse button.' },
{ name: 'scroll', description: 'Scroll at a coordinate or direction.' },
{ name: 'type', description: 'Type text through the active application.' },
{ name: 'key', description: 'Press a key or key chord.' },
{ name: 'hold_key', description: 'Hold one or more keys for a duration.' },
{ name: 'read_clipboard', description: 'Read clipboard text.' },
{ name: 'write_clipboard', description: 'Write clipboard text.' },
{
name: 'open_application',
description: 'Open an application by bundle identifier.',
},
{ name: 'wait', description: 'Wait for a short duration.' },
{
name: 'computer_batch',
description: 'Execute a sequence of computer-use actions.',
},
]
export function buildComputerUseTools() {
return TOOL_DEFS
}
export function createComputerUseMcpServer(
adapter?: { logger?: { warn(message: string): void; info?(message: string): void } },
) {
let closed = false
const handlers = new Map<unknown, unknown>()
return {
async connect() {
adapter?.logger?.warn(
'Computer Use MCP is running with a restored compatibility shim; request_access works, but native desktop actions remain unavailable in this workspace.',
)
},
setRequestHandler(schema: unknown, handler: unknown) {
handlers.set(schema, handler)
},
async close() {
closed = true
handlers.clear()
adapter?.logger?.info?.('Computer Use MCP shim closed.')
},
get isClosed() {
return closed
},
}
}
export function bindSessionContext(
_adapter?: unknown,
_coordinateMode?: unknown,
ctx?: ComputerUseSessionContext,
) {
return async (
name: string,
args: CuPermissionRequest | Record<string, unknown>,
): Promise<CuCallToolResult> => {
switch (name) {
case 'request_access': {
if (ctx?.onPermissionRequest) {
const response = await ctx.onPermissionRequest(args as CuPermissionRequest)
const grantedCount = Array.isArray(response.granted)
? response.granted.length
: 0
return successText(
grantedCount > 0
? `Computer-use access updated for ${grantedCount} application(s).`
: 'Computer-use access request completed.',
)
}
return errorText(
'Computer-use access approval is not configured in this restored workspace.',
)
}
case 'list_granted_applications': {
const apps = ctx?.getAllowedApps?.() ?? []
if (apps.length === 0) {
return successText('No computer-use applications are currently granted.')
}
const names = apps
.map(app => app.displayName || app.bundleId || 'unknown')
.join(', ')
return successText(`Granted computer-use applications: ${names}`)
}
case 'read_clipboard':
return errorText(
'Clipboard access is unavailable in the restored computer-use shim.',
)
default:
return errorText(
`Computer-use tool "${name}" is not available in this restored workspace. The shim currently supports session approval flows, but not native desktop execution.`,
)
}
}
}

View File

@@ -6,10 +6,25 @@ export const DEFAULT_GRANT_FLAGS = {
export type CoordinateMode = 'screen' | 'viewport'
export type CuSubGates = Record<string, boolean>
export type Logger = {
silly?(message: string, ...args: unknown[]): void
debug?(message: string, ...args: unknown[]): void
info(message: string): void
warn(message: string): void
error(message: string): void
}
export type ComputerUseHostAdapter = Record<string, unknown>
export type CuPermissionRequest = Record<string, unknown>
export type CuPermissionResponse = Record<string, unknown>
export type ComputerUseHostAdapter = {
logger?: Logger
executor?: Record<string, unknown>
[key: string]: unknown
}
export type CuPermissionRequest = {
apps?: Array<{ bundleId?: string; displayName?: string }>
flags?: Record<string, boolean>
tccState?: { accessibility?: boolean; screenRecording?: boolean }
[key: string]: unknown
}
export type CuPermissionResponse = {
granted: Array<{ bundleId?: string; displayName?: string; grantedAt?: string }>
denied: Array<{ bundleId?: string; displayName?: string }>
flags: Record<string, boolean>
}