开源 企业版 高校版 私有云 模力方舟 AI 队友
代码拉取完成,页面将自动刷新
加入 Gitee
与超过 1400万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
已有帐号? 立即登录
文件
main
分支 (5)
标签 (3)
main
feature/v6
test/test-most-core-func
version/i18n/zh-cn
feature/prod
v3
v2
v1
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
项目仓库所选许可证以仓库主分支所使用许可证为准
main
分支 (5)
标签 (3)
main
feature/v6
test/test-most-core-func
version/i18n/zh-cn
feature/prod
v3
v2
v1
克隆/下载
克隆/下载
提示
下载代码请复制以下命令到终端执行
为确保你提交的代码身份被 Gitee 正确识别,请执行以下命令完成配置
初次使用 SSH 协议进行代码克隆、推送等操作时,需按下述提示完成 SSH 配置
1 生成 RSA 密钥
2 获取 RSA 公钥内容,并配置到 SSH公钥
在 Gitee 上使用 SVN,请访问 使用指南
使用 HTTPS 协议时,命令行会出现如下账号密码验证步骤。基于安全考虑,Gitee 建议 配置并使用私人令牌 替代登录密码进行克隆、推送等操作
Username for 'https://gitee.com': userName
Password for 'https://userName@gitee.com': # 私人令牌
main
分支 (5)
标签 (3)
main
feature/v6
test/test-most-core-func
version/i18n/zh-cn
feature/prod
v3
v2
v1
claude-code
/
src
/
utils
/
transcriptSearch.ts
claude-code
/
src
/
utils
/
transcriptSearch.ts
transcriptSearch.ts 7.86 KB
一键复制 编辑 原始数据 按行查看 历史
claude-code-best 提交于 2026年03月31日 23:43 +08:00 . feat: 完成一大波类型修复, 虽然 any 很多
import type { RenderableMessage } from '../types/message.js'
import {
INTERRUPT_MESSAGE,
INTERRUPT_MESSAGE_FOR_TOOL_USE,
} from './messages.js'
const SYSTEM_REMINDER_CLOSE = '</system-reminder>'
// UserTextMessage.tsx:~84 replaces these with <InterruptedByUser />
// (renders 'Interrupted · /issue...'). Raw text never appears on screen;
// searching it yields phantom matches — /terr → in[terr]upted.
const RENDERED_AS_SENTINEL = new Set([
INTERRUPT_MESSAGE,
INTERRUPT_MESSAGE_FOR_TOOL_USE,
])
const searchTextCache = new WeakMap<RenderableMessage, string>()
/** Flatten a RenderableMessage to lowercased searchable text. WeakMap-
* cached — messages are append-only and immutable so a hit is always
* valid. Lowercased at cache time: the only caller immediately
* .toLowerCase()d the result, re-lowering ~1.5MB on every keystroke
* (the backspace hang). Returns '' for non-searchable types. */
export function renderableSearchText(msg: RenderableMessage): string {
const cached = searchTextCache.get(msg)
if (cached !== undefined) return cached
const result = computeSearchText(msg).toLowerCase()
searchTextCache.set(msg, result)
return result
}
function computeSearchText(msg: RenderableMessage): string {
let raw = ''
switch (msg.type) {
case 'user': {
const c = msg.message.content
if (typeof c === 'string') {
raw = RENDERED_AS_SENTINEL.has(c) ? '' : c
} else {
const parts: string[] = []
for (const b of c) {
if (b.type === 'text') {
if (!RENDERED_AS_SENTINEL.has(b.text)) parts.push(b.text)
} else if (b.type === 'tool_result') {
// b.content is the MODEL-facing serialization (from each tool's
// mapToolResultToToolResultBlockParam) — adds system-reminders,
// <persisted-output> wrappers, backgroundInfo strings,
// CYBER_RISK_MITIGATION_REMINDER. The UI
// renders msg.toolUseResult (the tool's native Out) via
// renderToolResultMessage — DIFFERENT text. Indexing b.content
// yields phantoms: /malware → matches the reminder, /background
// → matches the model-only ID string, none render.
//
// Duck-type the native Out instead. Covers the common shapes:
// Bash {stdout,stderr}, Grep {content,filenames}, Read
// {file.content}. Unknown shapes index empty — under-count is
// honest, phantom is a lie. Proper fix is per-tool
// extractSearchText(Out) on the Tool interface (TODO).
parts.push(toolResultSearchText(msg.toolUseResult))
}
}
raw = parts.join('\n')
}
break
}
case 'assistant': {
const c = msg.message.content
if (Array.isArray(c)) {
// text blocks + tool_use inputs. tool_use renders as "⏺ Bash(cmd)"
// — the command/pattern/path is visible and searchable-expected.
// Skip thinking (hidden by hidePastThinking in transcript mount).
raw = c
.flatMap(b => {
if (b.type === 'text') return [b.text]
if (b.type === 'tool_use') return [toolUseSearchText(b.input)]
return []
})
.join('\n')
}
break
}
case 'attachment': {
// relevant_memories renders full m.content in transcript mode
// (AttachmentMessage.tsx <Ansi>{m.content}</Ansi>). Visible but
// unsearchable without this — [ dump finds it, / doesn't.
if (msg.attachment.type === 'relevant_memories') {
raw = msg.attachment.memories.map(m => m.content).join('\n')
} else if (
// Mid-turn prompts — queued while an agent is running. Render via
// UserTextMessage (AttachmentMessage.tsx:~348). stickyPromptText
// (VirtualMessageList.tsx:~103) has the same guards — mirror here.
msg.attachment.type === 'queued_command' &&
msg.attachment.commandMode !== 'task-notification' &&
!msg.attachment.isMeta
) {
const p = msg.attachment.prompt
raw =
typeof p === 'string'
? p
: (p as any[]).flatMap(b => (b.type === 'text' ? [b.text] : [])).join('\n')
}
break
}
case 'collapsed_read_search': {
// relevant_memories attachments are absorbed into collapse groups
// (collapseReadSearch.ts); their content is visible in transcript mode
// via CollapsedReadSearchContent, so mirror it here for / search.
if (msg.relevantMemories) {
raw = msg.relevantMemories.map(m => m.content).join('\n')
}
break
}
default:
// grouped_tool_use, system — no text content
break
}
// Strip <system-reminder> anywhere — Claude context, not user-visible.
// Mid-message on cc -c resumes (memory reminders between prompt lines).
let t = raw
let open = t.indexOf('<system-reminder>')
while (open >= 0) {
const close = t.indexOf(SYSTEM_REMINDER_CLOSE, open)
if (close < 0) break
t = t.slice(0, open) + t.slice(close + SYSTEM_REMINDER_CLOSE.length)
open = t.indexOf('<system-reminder>')
}
return t
}
/** Tool invocation display: renderToolUseMessage shows input fields like
* command (Bash), pattern (Grep), file_path (Read/Edit), prompt (Agent).
* Same duck-type strategy as toolResultSearchText — known field names,
* unknown → empty. Under-count > phantom. */
export function toolUseSearchText(input: unknown): string {
if (!input || typeof input !== 'object') return ''
const o = input as Record<string, unknown>
const parts: string[] = []
// renderToolUseMessage typically shows one or two of these as the
// primary argument. tool_name itself is in the "⏺ Bash(...)" chrome,
// handled by under-count (the overlay matches it but we don't count it).
for (const k of [
'command',
'pattern',
'file_path',
'path',
'prompt',
'description',
'query',
'url',
'skill', // SkillTool
]) {
const v = o[k]
if (typeof v === 'string') parts.push(v)
}
// args[] (Tmux/TungstenTool), files[] (SendUserFile) — tool-use
// renders the joined array as the primary display. Under-count > skip.
for (const k of ['args', 'files']) {
const v = o[k]
if (Array.isArray(v) && v.every(x => typeof x === 'string')) {
parts.push((v as string[]).join(''))
}
}
return parts.join('\n')
}
/** Duck-type the tool's native Out for searchable text. Known shapes:
* {stdout,stderr} (Bash/Shell), {content} (Grep), {file:{content}} (Read),
* {filenames:[]} (Grep/Glob), {output} (generic). Falls back to concating
* all top-level string fields — crude but better than indexing model-chatter.
* Empty for unknown shapes: under-count > phantom. */
export function toolResultSearchText(r: unknown): string {
if (!r || typeof r !== 'object') return typeof r === 'string' ? r : ''
const o = r as Record<string, unknown>
// Known shapes first (common tools).
if (typeof o.stdout === 'string') {
const err = typeof o.stderr === 'string' ? o.stderr : ''
return o.stdout + (err ? '\n' + err : '')
}
if (
o.file &&
typeof o.file === 'object' &&
typeof (o.file as { content?: unknown }).content === 'string'
) {
return (o.file as { content: string }).content
}
// Known output-field names only. A blind walk would index metadata
// the UI doesn't show (rawOutputPath, backgroundTaskId, filePath,
// durationMs-as-string). Allowlist the fields tools actually render.
// Tools not matching any shape index empty — add them here as found.
const parts: string[] = []
for (const k of ['content', 'output', 'result', 'text', 'message']) {
const v = o[k]
if (typeof v === 'string') parts.push(v)
}
for (const k of ['filenames', 'lines', 'results']) {
const v = o[k]
if (Array.isArray(v) && v.every(x => typeof x === 'string')) {
parts.push((v as string[]).join('\n'))
}
}
return parts.join('\n')
}
Loading...
举报
举报成功
我们将于2个工作日内通过站内信反馈结果给你!
请认真填写举报原因,尽可能描述详细。
请选择举报类型
取消
发送
误判申诉

此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。

如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。

取消
提交

发行版

暂无发行版

贡献者

全部

近期动态

不能加载更多了
编辑仓库简介
简介内容
主页
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/jbcode/claude-code.git
git@gitee.com:jbcode/claude-code.git
jbcode
claude-code
claude-code
main
点此查找更多帮助

搜索帮助

评论
仓库举报
回到顶部
登录提示
该操作需登录 Gitee 帐号,请先登录后再操作。
立即登录
没有帐号,去注册

AltStyle によって変換されたページ (->オリジナル) /