MCPcopy Create free account
hub / github.com/claude-code-best/claude-code / extractFirstPromptFromChunk

Function extractFirstPromptFromChunk

src/utils/sessionStorage.ts:4933–5027  ·  view source on GitHub ↗

* Scans a chunk of text for the first meaningful user prompt.

(chunk: string)

Source from the content-addressed store, hash-verified

4931 * Scans a chunk of text for the first meaningful user prompt.
4932 */
4933function extractFirstPromptFromChunk(chunk: string): string {
4934 let start = 0
4935 let hasTickMessages = false
4936 let firstCommandFallback = ''
4937 while (start < chunk.length) {
4938 const newlineIdx = chunk.indexOf('\n', start)
4939 const line =
4940 newlineIdx >= 0 ? chunk.slice(start, newlineIdx) : chunk.slice(start)
4941 start = newlineIdx >= 0 ? newlineIdx + 1 : chunk.length
4942
4943 if (!line.includes('"type":"user"') && !line.includes('"type": "user"')) {
4944 continue
4945 }
4946 if (line.includes('"tool_result"')) continue
4947 if (line.includes('"isMeta":true') || line.includes('"isMeta": true'))
4948 continue
4949
4950 try {
4951 const entry = jsonParse(line) as Record<string, unknown>
4952 if (entry.type !== 'user') continue
4953
4954 const message = entry.message as Record<string, unknown> | undefined
4955 if (!message) continue
4956
4957 const content = message.content
4958 // Collect all text values from the message content. For array content
4959 // (common in VS Code where IDE metadata tags come before the user's
4960 // actual prompt), iterate all text blocks so we don't miss the real
4961 // prompt hidden behind <ide_selection>/<ide_opened_file> blocks.
4962 const texts: string[] = []
4963 if (typeof content === 'string') {
4964 texts.push(content)
4965 } else if (Array.isArray(content)) {
4966 for (const block of content) {
4967 const b = block as Record<string, unknown>
4968 if (b.type === 'text' && typeof b.text === 'string') {
4969 texts.push(b.text as string)
4970 }
4971 }
4972 }
4973
4974 for (const text of texts) {
4975 if (!text) continue
4976
4977 let result = text.replace(/\n/g, ' ').trim()
4978
4979 // Skip command messages (slash commands) but remember the first one
4980 // as a fallback title. Matches skip logic in
4981 // getFirstMeaningfulUserMessageTextContent, but instead of discarding
4982 // command messages entirely, we format them cleanly (e.g. "/clear")
4983 // so the session still appears in the resume picker.
4984 const commandNameTag = extractTag(result, COMMAND_NAME_TAG)
4985 if (commandNameTag) {
4986 const name = commandNameTag.replace(/^\//, '')
4987 const commandArgs = extractTag(result, 'command-args')?.trim() || ''
4988 if (builtInCommandNames().has(name) || !commandArgs) {
4989 if (!firstCommandFallback) {
4990 firstCommandFallback = commandNameTag

Callers 1

readLiteMetadataFunction · 0.85

Calls 4

jsonParseFunction · 0.85
extractTagFunction · 0.85
pushMethod · 0.45
hasMethod · 0.45

Tested by

no test coverage detected