mirror of
https://github.com/claude-code-best/claude-code.git
synced 2026-06-17 13:55:50 +00:00
@@ -1,4 +1,5 @@
|
||||
import { describe, expect, test } from 'bun:test'
|
||||
import type { NotebookCellSource } from '../../types/notebook.js'
|
||||
import { parseCellId, mapNotebookCellsToToolResult } from '../notebook'
|
||||
|
||||
// ─── parseCellId ───────────────────────────────────────────────────────
|
||||
@@ -59,7 +60,10 @@ describe('mapNotebookCellsToToolResult', () => {
|
||||
},
|
||||
]
|
||||
|
||||
const result = mapNotebookCellsToToolResult(data, 'tool-123')
|
||||
const result = mapNotebookCellsToToolResult(
|
||||
data as NotebookCellSource[],
|
||||
'tool-123',
|
||||
)
|
||||
expect(result.tool_use_id).toBe('tool-123')
|
||||
expect(result.type).toBe('tool_result')
|
||||
})
|
||||
@@ -74,7 +78,10 @@ describe('mapNotebookCellsToToolResult', () => {
|
||||
},
|
||||
]
|
||||
|
||||
const result = mapNotebookCellsToToolResult(data, 'tool-1')
|
||||
const result = mapNotebookCellsToToolResult(
|
||||
data as NotebookCellSource[],
|
||||
'tool-1',
|
||||
)
|
||||
expect(result.content).toBeInstanceOf(Array)
|
||||
expect(result.content!.length).toBeGreaterThanOrEqual(1)
|
||||
|
||||
@@ -100,7 +107,10 @@ describe('mapNotebookCellsToToolResult', () => {
|
||||
},
|
||||
]
|
||||
|
||||
const result = mapNotebookCellsToToolResult(data, 'tool-2')
|
||||
const result = mapNotebookCellsToToolResult(
|
||||
data as NotebookCellSource[],
|
||||
'tool-2',
|
||||
)
|
||||
// Two adjacent text blocks should be merged into one
|
||||
const textBlocks = (result.content as any[]).filter(
|
||||
(b: any) => b.type === 'text',
|
||||
@@ -134,7 +144,10 @@ describe('mapNotebookCellsToToolResult', () => {
|
||||
},
|
||||
]
|
||||
|
||||
const result = mapNotebookCellsToToolResult(data, 'tool-3')
|
||||
const result = mapNotebookCellsToToolResult(
|
||||
data as NotebookCellSource[],
|
||||
'tool-3',
|
||||
)
|
||||
const types = (result.content as any[]).map((b: any) => b.type)
|
||||
expect(types).toContain('image')
|
||||
})
|
||||
@@ -148,7 +161,10 @@ describe('mapNotebookCellsToToolResult', () => {
|
||||
},
|
||||
]
|
||||
|
||||
const result = mapNotebookCellsToToolResult(data, 'tool-4')
|
||||
const result = mapNotebookCellsToToolResult(
|
||||
data as NotebookCellSource[],
|
||||
'tool-4',
|
||||
)
|
||||
const textBlock = result.content![0] as { type: string; text: string }
|
||||
expect(textBlock.text).toContain('<cell_type>markdown</cell_type>')
|
||||
})
|
||||
@@ -163,7 +179,10 @@ describe('mapNotebookCellsToToolResult', () => {
|
||||
},
|
||||
]
|
||||
|
||||
const result = mapNotebookCellsToToolResult(data, 'tool-5')
|
||||
const result = mapNotebookCellsToToolResult(
|
||||
data as NotebookCellSource[],
|
||||
'tool-5',
|
||||
)
|
||||
const textBlock = result.content![0] as { type: string; text: string }
|
||||
expect(textBlock.text).toContain('<language>scala</language>')
|
||||
})
|
||||
|
||||
@@ -358,22 +358,22 @@ export interface HookResult {
|
||||
}
|
||||
|
||||
export type AggregatedHookResult = {
|
||||
message?: HookResultMessage
|
||||
blockingError?: HookBlockingError
|
||||
preventContinuation?: boolean
|
||||
stopReason?: string
|
||||
hookPermissionDecisionReason?: string
|
||||
hookSource?: string
|
||||
permissionBehavior?: PermissionResult['behavior']
|
||||
additionalContexts?: string[]
|
||||
initialUserMessage?: string
|
||||
updatedInput?: Record<string, unknown>
|
||||
updatedMCPToolOutput?: unknown
|
||||
permissionRequestResult?: PermissionRequestResult
|
||||
watchPaths?: string[]
|
||||
elicitationResponse?: ElicitationResponse
|
||||
elicitationResultResponse?: ElicitationResponse
|
||||
retry?: boolean
|
||||
message?: HookResultMessage // 插入会话的钩子消息(含系统/附件类),供 UI 与后续轮次展示
|
||||
blockingError?: HookBlockingError // 致命阻塞:附带命令与错误文案,调用方应中止当前工具/流程
|
||||
preventContinuation?: boolean // 为 true 时请求不再继续后续对话轮次(与 stopReason 配套)
|
||||
stopReason?: string // 停止继续时的可读原因,用于日志、遥测或向用户解释为何结束
|
||||
hookPermissionDecisionReason?: string // 钩子对权限决策的补充说明,常与 permissionBehavior 一同产出
|
||||
hookSource?: string // 产生本次权限/改参结果的定义来源(如 settings 与 policy 合并后的条目来源)
|
||||
permissionBehavior?: PermissionResult['behavior'] // 多钩并行时按 deny > ask > allow 聚合后的权限行为
|
||||
additionalContexts?: string[] // 注入模型上下文的补充片段(如 UserPromptSubmit),可与多条钩子结果合并
|
||||
initialUserMessage?: string // 会话启动等场景预置的首条用户侧文案,供首轮上下文使用
|
||||
updatedInput?: Record<string, unknown> // 钩子改写后的工具入参;可在 allow/ask 时与权限一起产出,也可单独改参
|
||||
updatedMCPToolOutput?: unknown // PostToolUse 钩子对 MCP 工具原始输出的替换内容
|
||||
permissionRequestResult?: PermissionRequestResult // PermissionRequest 事件钩子的 allow/deny 及可选改参
|
||||
watchPaths?: string[] // SessionStart 等声明的监视路径,供文件变更相关逻辑使用
|
||||
elicitationResponse?: ElicitationResponse // Elicitation 钩子的交互/采集结果(MCP elicit 流程)
|
||||
elicitationResultResponse?: ElicitationResponse // ElicitationResult 钩子对上一轮引导的后续响应数据
|
||||
retry?: boolean // PermissionDenied 等场景是否建议用户重试当前操作
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -25,7 +25,8 @@ function isLargeOutputs(
|
||||
let size = 0
|
||||
for (const o of outputs) {
|
||||
if (!o) continue
|
||||
size += (o.text?.length ?? 0) + (o.image?.image_data.length ?? 0)
|
||||
const imageLen = 'image' in o && o.image ? o.image.image_data.length : 0
|
||||
size += (o.text?.length ?? 0) + imageLen
|
||||
if (size > LARGE_OUTPUT_THRESHOLD) return true
|
||||
}
|
||||
return false
|
||||
@@ -139,7 +140,7 @@ function cellOutputToToolResult(output: NotebookCellSourceOutput) {
|
||||
type: 'text',
|
||||
})
|
||||
}
|
||||
if (output.image) {
|
||||
if ('image' in output && output.image) {
|
||||
outputs.push({
|
||||
type: 'image',
|
||||
source: {
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import type { McpbManifestAny as McpbManifest } from '@anthropic-ai/mcpb'
|
||||
type McpbUserConfigurationOption = any
|
||||
import axios from 'axios'
|
||||
import { createHash } from 'crypto'
|
||||
import { chmod, writeFile } from 'fs/promises'
|
||||
@@ -19,6 +18,19 @@ import {
|
||||
import { jsonParse, jsonStringify } from '../slowOperations.js'
|
||||
import { getSystemDirectories } from '../systemDirectories.js'
|
||||
import { classifyFetchError, logPluginFetch } from './fetchTelemetry.js'
|
||||
|
||||
/** DXT / MCPB `user_config` 中单字段的 JSON Schema 式描述(校验见 `validateUserConfig`)。 */
|
||||
export type McpbUserConfigurationOption = {
|
||||
type: 'string' | 'number' | 'boolean' | 'file' | 'directory' // 控件/校验类型
|
||||
required?: boolean // 是否必填
|
||||
title?: string // 表单标签(缺省用 key)
|
||||
description?: string // 帮助说明
|
||||
sensitive?: boolean // true 时写入安全存储而非明文 settings
|
||||
multiple?: boolean // string 类型时是否允许多值(数组)
|
||||
min?: number // 数值下限
|
||||
max?: number // 数值上限
|
||||
}
|
||||
|
||||
/**
|
||||
* User configuration values for MCPB
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user