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

Function extractFirstPromptFromChunk

src/utils/sessionStorage.ts:4819–4915  ·  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

4817 * Scans a chunk of text for the first meaningful user prompt.
4818 */
4819function extractFirstPromptFromChunk(chunk: string): string {
4820 let start = 0
4821 let hasTickMessages = false
4822 let firstCommandFallback = ''
4823 while (start < chunk.length) {
4824 const newlineIdx = chunk.indexOf('\n', start)
4825 const line =
4826 newlineIdx >= 0 ? chunk.slice(start, newlineIdx) : chunk.slice(start)
4827 start = newlineIdx >= 0 ? newlineIdx + 1 : chunk.length
4828
4829 if (!line.includes('"type":"user"') && !line.includes('"type": "user"')) {
4830 continue
4831 }
4832 if (line.includes('"tool_result"')) continue
4833 if (line.includes('"isMeta":true') || line.includes('"isMeta": true'))
4834 continue
4835
4836 try {
4837 const entry = jsonParse(line) as Record<string, unknown>
4838 if (entry.type !== 'user') continue
4839
4840 const message = entry.message as Record<string, unknown> | undefined
4841 if (!message) continue
4842
4843 const content = message.content
4844 // Collect all text values from the message content. For array content
4845 // (common in VS Code where IDE metadata tags come before the user's
4846 // actual prompt), iterate all text blocks so we don't miss the real
4847 // prompt hidden behind <ide_selection>/<ide_opened_file> blocks.
4848 const texts: string[] = []
4849 if (typeof content === 'string') {
4850 texts.push(content)
4851 } else if (Array.isArray(content)) {
4852 for (const block of content) {
4853 const b = block as Record<string, unknown>
4854 if (b.type === 'text' && typeof b.text === 'string') {
4855 texts.push(b.text as string)
4856 }
4857 }
4858 }
4859
4860 for (const text of texts) {
4861 if (!text) continue
4862
4863 let result = text.replace(/\n/g, ' ').trim()
4864
4865 // Skip command messages (slash commands) but remember the first one
4866 // as a fallback title. Matches skip logic in
4867 // getFirstMeaningfulUserMessageTextContent, but instead of discarding
4868 // command messages entirely, we format them cleanly (e.g. "/clear")
4869 // so the session still appears in the resume picker.
4870 const commandNameTag = extractTag(result, COMMAND_NAME_TAG)
4871 if (commandNameTag) {
4872 const name = commandNameTag.replace(/^\//, '')
4873 const commandArgs = extractTag(result, 'command-args')?.trim() || ''
4874 if (builtInCommandNames().has(name) || !commandArgs) {
4875 if (!firstCommandFallback) {
4876 firstCommandFallback = commandNameTag

Callers 1

readLiteMetadataFunction · 0.85

Calls 4

jsonParseFunction · 0.85
extractTagFunction · 0.85
featureFunction · 0.85
hasMethod · 0.45

Tested by

no test coverage detected