@juspay/neurolink 10.12.6 → 10.12.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,3 +1,9 @@
1
+ ## [10.12.7](https://github.com/juspay/neurolink/compare/v10.12.6...v10.12.7) (2026-08-15)
2
+
3
+ ### Bug Fixes
4
+
5
+ - **(vertex):** stop dropping input.files content on the Claude generate path ([6d88778](https://github.com/juspay/neurolink/commit/6d88778bf3f07f954009b9b56f6b11fef3f7b810))
6
+
1
7
  ## [10.12.6](https://github.com/juspay/neurolink/compare/v10.12.5...v10.12.6) (2026-08-15)
2
8
 
3
9
  ### Bug Fixes
@@ -993,7 +993,7 @@ IMPORTANT FILE HANDLING INSTRUCTIONS:
993
993
  - The full content of the user's local file(s) is INLINED in this message under "## CSV Data from ..." / "## PDF Data from ..." / "## File: ..." headings \u2014 it is the actual file the user is asking about.
994
994
  - TREAT THE INLINED CONTENT AS IF IT WERE AN ATTACHMENT. Do NOT respond with "no files attached" or ask the user to re-upload \u2014 the data is already here.
995
995
  - DO NOT use GitHub tools (get_file_contents, search_code, etc.) for local files - they only work for remote repository files.
996
- - Analyze the inlined file content directly without attempting to fetch or read files using tools.`,m=(r.systemPrompt||"").trim();r.systemPrompt=m?`${m}${p}`:p.trim()}})}async function rdr(r){if(r.input??={},!(!r.input.csvFiles||r.input.csvFiles.length===0)){g.info(`[CSV] Processing ${r.input.csvFiles.length} explicit CSV file(s)`),r.input.text=r.input.text||"";for(let e=0;e<r.input.csvFiles.length;e++){let t=r.input.csvFiles[e];try{let n=await cl.detectAndProcess(t,{allowedTypes:["csv"],csvOptions:r.csvOptions}),o=Ph(t,e),s=typeof t=="string"?t:o,i=`
996
+ - Analyze the inlined file content directly without attempting to fetch or read files using tools.`,m=(r.systemPrompt||"").trim();r.systemPrompt=m?`${m}${p}`:p.trim();let f=r;typeof f.prompt=="string"&&(f.prompt=c.text)}})}async function rdr(r){if(r.input??={},!(!r.input.csvFiles||r.input.csvFiles.length===0)){g.info(`[CSV] Processing ${r.input.csvFiles.length} explicit CSV file(s)`),r.input.text=r.input.text||"";for(let e=0;e<r.input.csvFiles.length;e++){let t=r.input.csvFiles[e];try{let n=await cl.detectAndProcess(t,{allowedTypes:["csv"],csvOptions:r.csvOptions}),o=Ph(t,e),s=typeof t=="string"?t:o,i=`
997
997
 
998
998
  ## CSV Data from "${o}":
999
999
  `;if(n.metadata){let a=tj(n.metadata);a&&(i+=a+`
@@ -1138,7 +1138,7 @@ The final_result tool is no longer available. Provide your final answer directly
1138
1138
 
1139
1139
  IMPORTANT: You MUST call the 'final_result' tool to return your response in the required structured format. Do not respond with plain text - always use the final_result tool.`,g.debug("[GoogleVertex] Added final_result tool for Anthropic structured output (stream)",{schemaKeys:Object.keys(j),totalTools:l.length})}let h=e.systemPrompt?e.systemPrompt+f:f?f.trim():void 0,y=Sa(this.providerName,t,{...e.temperature!==void 0&&{temperature:e.temperature},...e.topP!==void 0&&{topP:e.topP}},"vertex.anthropic.stream"),x={model:t,max_tokens:u_(t,e.maxTokens),messages:i,...l&&l.length>0&&{tools:l},...m&&{tool_choice:{type:"any"}},...h&&{system:h},...y.temperature!==void 0&&{temperature:y.temperature},...y.topP!==void 0&&{top_p:y.topP},...e.stopSequences&&e.stopSequences.length>0&&{stop_sequences:e.stopSequences}},b=e.maxSteps||as,T=m?Math.max(b-1,0):b,w=[],C=[],R=kj(),k={input:0,output:0,total:0},I={streamId:`native-anthropic-vertex-${Date.now()}`,startTime:n,responseTime:0,totalToolExecutions:0},P=[],A={},M={},N={},B={},L=(l??[]).map(se=>se.name),F=Wo({system:h,messages:fse(i)}),V=Oe.provider.startSpan("anthropic.vertex.stream",{kind:Sr.CLIENT,attributes:{[En.OBSERVATION_TYPE]:"span",[Pe.GEN_AI_SYSTEM]:"anthropic",[Pe.GEN_AI_MODEL]:t,[Pe.GEN_AI_OPERATION]:"stream",[Pe.NL_PROVIDER]:this.providerName,[Pe.NL_TOOL_COUNT]:L.length,[En.OBSERVATION_INPUT]:F,[En.TRACE_INPUT]:F,[En.OBSERVATION_METADATA]:Wo({toolsOffered:L,toolCount:L.length,maxSteps:b,structuredOutput:m})}}),G=mt.setSpan(xr.active(),V),$="",O=0,J={read:0,creation:0,creation5m:0,creation1h:0},te,Q=()=>{try{te?.controller.abort()}catch{}},he=new AbortController;he.signal.addEventListener("abort",Q);let Ie=()=>he.abort();e.abortSignal?.addEventListener("abort",Ie),e.abortSignal?.aborted&&he.abort();let H=e.toolTimeoutMs??sw,ie=e.turnTimeoutMs??o,ee=YI({turnTimeoutMs:e.turnTimeoutMs,defaultTurnTimeoutMs:o,stallTimeoutMs:e.stallTimeoutMs,wrapupTimeLeadMs:e.wrapupTimeLeadMs,onDeadline:se=>{g.warn(se==="timeout"?`[GoogleVertex] Anthropic stream turn exceeded its ${ie}ms time budget \u2014 aborting`:`[GoogleVertex] Anthropic stream turn made no progress for ${e.stallTimeoutMs}ms \u2014 aborting`),he.abort()}});(async()=>{let se=0,Y=[...i],j=!1,re=!1,D=!1,oe=!1,Z=!1,ae,ce=jh(Md("vertex",t)),ye=new Map;try{for(;se<T;){if(he.signal.aborted){j=!0;break}if(ce.shouldStop())if(MBe(Y,t,ce.projectedNextPromptTokens))ce.resetAfterReclaim();else{D=!0,g.warn(`[GoogleVertex] Anthropic stream turn stopped by the context guard: projected prompt ~${ce.projectedNextPromptTokens} tokens >= threshold ${ce.thresholdTokens} (step ${se}) \u2014 synthesizing a final answer.`);break}se++,ee.noteProgress(),this.refreshAnthropicToolDeclarations(e.tools,l,d,ye);let de=Oe.generation.startSpan("anthropic.messages.stream",{kind:Sr.CLIENT,attributes:{[En.OBSERVATION_TYPE]:"generation",[En.OBSERVATION_MODEL_NAME]:t,[En.OBSERVATION_MODEL_PARAMETERS]:Wo({max_tokens:x.max_tokens,temperature:x.temperature,top_p:x.top_p}),[En.OBSERVATION_INPUT]:Wo({system:h,messages:fse(Y)}),[En.OBSERVATION_METADATA]:Wo({step:se,toolsOffered:L.length}),[Pe.GEN_AI_SYSTEM]:"anthropic",[Pe.GEN_AI_MODEL]:t,[Pe.GEN_AI_OPERATION]:"chat"}},G),qe;try{let q=ob({system:h,tools:l,messages:Y}),fe=await s.messages.stream({...x,...q.system!==void 0&&{system:q.system},...q.tools&&q.tools.length>0&&{tools:q.tools},messages:q.messages});te=fe;let Ce=!1;fe.on("text",U=>{ee.noteProgress(),U.length>0&&(Ce||(Ce=!0,de.setAttribute(En.OBSERVATION_COMPLETION_START_TIME,new Date().toISOString())),R.push(U),O+=U.length)}),qe=await fe.finalMessage()}catch(q){if(de.setStatus({code:$e.ERROR,message:q instanceof Error?q.message:String(q)}),q instanceof Error&&de.recordException(q),de.end(),he.signal.aborted||Yl(q)){te=void 0,j=!0;break}throw q}te=void 0;try{let q=qe.usage?.cache_read_input_tokens??0,fe=qe.usage?.cache_creation_input_tokens??0,Ce=qe.usage?.cache_creation?.ephemeral_5m_input_tokens??0,U=qe.usage?.cache_creation?.ephemeral_1h_input_tokens??0;J.read+=q,J.creation+=fe,J.creation5m+=Ce,J.creation1h+=U,k.input+=qe.usage?.input_tokens||0,k.output+=qe.usage?.output_tokens||0,k.total=k.input+k.output+J.read+J.creation,ae=qe.stop_reason,ce.noteUsage((qe.usage?.input_tokens||0)+q+fe,qe.usage?.output_tokens||0);for(let me of qe.content)me.type==="text"&&typeof me.text=="string"&&($+=me.text);de.setAttribute(En.OBSERVATION_OUTPUT,Wo(qe.content)),de.setAttribute(En.OBSERVATION_USAGE_DETAILS,Wo({input:qe.usage?.input_tokens??0,output:qe.usage?.output_tokens??0,input_cached_tokens:q,input_cache_creation_5m:Ce,input_cache_creation_1h:U,total:(qe.usage?.input_tokens??0)+(qe.usage?.output_tokens??0)+q+Ce+U})),de.setAttribute(Pe.GEN_AI_INPUT_TOKENS,qe.usage?.input_tokens??0),de.setAttribute(Pe.GEN_AI_OUTPUT_TOKENS,qe.usage?.output_tokens??0),qe.stop_reason&&de.setAttribute(Pe.GEN_AI_FINISH_REASON,qe.stop_reason),de.setStatus({code:$e.OK})}finally{de.end()}let ze=qe.content.filter(q=>q.type==="tool_use");if(m){let q=ze.find(fe=>fe.name==="final_result");if(q){A.value=q.input,R.push(JSON.stringify(q.input)),Z=!0,g.debug("[GoogleVertex] Extracted structured output from final_result tool (stream)",{keys:Object.keys(q.input)});break}}if(ze.length===0){Z=!0;break}let le=[],Le=[],_=[];for(let q of ze){if(he.signal.aborted){j=!0;break}w.push({toolName:q.name,args:q.input}),P.push(q.name),Le.push({toolCallId:q.id,toolName:q.name,args:q.input});let fe=ye.get(q.name);if(fe&&fe.count>=Wn){g.warn(`[GoogleVertex] Tool "${q.name}" has exceeded retry limit (${Wn}), skipping execution`);let Se=`TOOL_PERMANENTLY_FAILED: The tool "${q.name}" has failed ${fe.count} times and will not be retried. Last error: ${fe.lastError}. Please proceed without using this tool or inform the user that this functionality is unavailable.`,ne={error:Se};C.push({name:q.name,input:q.input,output:ne}),le.push({type:"tool_result",tool_use_id:q.id,content:Se}),_.push({toolCallId:q.id,toolName:q.name,output:ne});continue}let Ce=Oe.mcp.startSpan("ai.toolCall",{kind:Sr.INTERNAL,attributes:{[En.OBSERVATION_TYPE]:"tool",[Pe.GEN_AI_TOOL_NAME]:q.name,"ai.toolCall.name":q.name,"ai.toolCall.id":q.id,"ai.toolCall.args":Wo(q.input,2e4),[En.OBSERVATION_INPUT]:Wo(q.input,2e4),[En.OBSERVATION_METADATA]:Wo({step:se})}},G),U=(Se,ne)=>{Ce.setAttribute("ai.toolCall.result",Wo(Se)),Ce.setAttribute(En.OBSERVATION_OUTPUT,Wo(Se)),ne?(Ce.setAttribute(En.OBSERVATION_LEVEL,"ERROR"),Ce.setAttribute(En.OBSERVATION_STATUS_MESSAGE,ne),Ce.setStatus({code:$e.ERROR,message:ne})):Ce.setStatus({code:$e.OK}),Ce.end()},me=d.get(q.name);if(me||(me=this.resolveAnthropicToolOnMiss(q.name,e.tools,l,d,ye)),me)try{let Se={toolCallId:q.id,messages:[],abortSignal:he.signal};ee.noteProgress();let ne=await vt(oh(xr.with(mt.setSpan(G,Ce),()=>Promise.resolve(me(q.input,Se))),he.signal),H,`Tool "${q.name}" execution timed out after ${H}ms`);ee.noteProgress(),U(ne,Lte(ne));let _e=NI(ne);if(_e){let Be=ye.get(q.name)||{count:0,lastError:""};Be.count++,Be.lastError=_e,ye.set(q.name,Be)}else ye.delete(q.name);C.push({name:q.name,input:q.input,output:ne});let Ue=typeof ne=="string"?ne:zp(ne??null);le.push({type:"tool_result",tool_use_id:q.id,content:Ue}),_.push({toolCallId:q.id,toolName:q.name,output:ne})}catch(Se){if(he.signal.aborted||Yl(Se)){U({aborted:!0}),_.push({toolCallId:q.id,toolName:q.name,output:{aborted:!0}}),j=!0;break}ee.noteProgress(),Se instanceof tc&&this.emitTurnEvent({phase:"tool-timeout",step:se,maxSteps:b,toolName:q.name});let ne=Se instanceof Error?Se.message:String(Se),_e=ye.get(q.name)||{count:0,lastError:""};_e.count++,_e.lastError=ne,ye.set(q.name,_e),g.warn(`[GoogleVertex] Tool "${q.name}" failed (attempt ${_e.count}/${Wn}): ${ne}`);let Ue=`Error executing tool "${q.name}": ${ne}`,Be={error:Ue};U(Be,Ue),C.push({name:q.name,input:q.input,output:Be}),le.push({type:"tool_result",tool_use_id:q.id,content:Ue}),_.push({toolCallId:q.id,toolName:q.name,output:Be})}else{let Se=`TOOL_NOT_FOUND: The tool "${q.name}" does not exist.`,ne={error:Se},_e=ye.get(q.name)||{count:0,lastError:""};_e.count++,_e.lastError=Se,ye.set(q.name,_e),U(ne,Se),C.push({name:q.name,input:q.input,output:ne}),le.push({type:"tool_result",tool_use_id:q.id,content:Se}),_.push({toolCallId:q.id,toolName:q.name,output:ne})}}if((Le.length>0||_.length>0)&&vt(this.handleToolExecutionStorage(Le.map(q=>({...q,stepIndex:se})),_.map(q=>({...q,stepIndex:se})),e,new Date),Jm,"tool storage write timed out").catch(q=>{g.warn("[GoogleVertex] Failed to store native Anthropic stream tool executions",{error:q instanceof Error?q.message:String(q)})}),j)break;let z=T-se;z>0&&z<=3?le.push({type:"text",text:`NOTE: Only ${z} tool step(s) remain. Consolidate what you have and `+(m?"call final_result with your best answer.":"provide your final answer.")}):ee.shouldNudgeWrapup()&&le.push({type:"text",text:JI(m)});let X=qe.content.filter(q=>q.type!=="server_tool_use");Y.push({role:"assistant",content:X}),Y.push({role:"user",content:le}),ce.noteAppendedChars(le.reduce((q,fe)=>q+("content"in fe?fe.content.length:fe.text.length),0))}if(!Z){he.signal.aborted&&(j=!0);let de=w.filter(ze=>ze.toolName!=="final_result").length,qe=Math.max(1024,Math.min(x.max_tokens,Md("vertex",t)-ce.projectedNextPromptTokens-4e3));if(j){if(g.warn(`[GoogleVertex] Native Anthropic stream loop ended mid-turn (${ee.timedOut?"turn time limit":ee.stalled?"stall watchdog":"caller abort"}); returning an honest terminal message.`),$.length===0&&O===0&&!A.value){let ze=this.buildLoopExitMessage({turnClock:ee,wasAborted:j,stallTimeoutMs:e.stallTimeoutMs,maxSteps:b,toolCallCount:de});R.push(ze),$=ze}}else if(m){D||(re=!0),g.warn(D?"[GoogleVertex] Native Anthropic stream loop stopped by the context guard without final_result; forcing a finalization call.":`[GoogleVertex] Native Anthropic stream loop reached maxSteps (${b}) without final_result; forcing a finalization call.`);try{let ze=ob({system:h,tools:l,messages:Y}),le=await s.messages.stream({...x,max_tokens:qe,tool_choice:{type:"tool",name:"final_result"},...ze.system!==void 0&&{system:ze.system},...ze.tools&&ze.tools.length>0&&{tools:ze.tools},messages:ze.messages});te=le;let Le=await le.finalMessage();te=void 0,k.input+=Le.usage?.input_tokens||0,k.output+=Le.usage?.output_tokens||0,J.read+=Le.usage?.cache_read_input_tokens??0,J.creation+=Le.usage?.cache_creation_input_tokens??0,J.creation5m+=Le.usage?.cache_creation?.ephemeral_5m_input_tokens??0,J.creation1h+=Le.usage?.cache_creation?.ephemeral_1h_input_tokens??0,k.total=k.input+k.output+J.read+J.creation,ae=Le.stop_reason;let _=Le.content.find(z=>z.type==="tool_use"&&z.name==="final_result");if(_)A.value=_.input,R.push(JSON.stringify(_.input)),oe=!0,g.debug("[GoogleVertex] Forced finalization returned structured output (stream)",{keys:Object.keys(_.input)});else{let z=D?Zl(de):hg(b,de);R.push(z),$+=z}}catch(ze){te=void 0,(he.signal.aborted||Yl(ze))&&(re=!1,j=!0),g.warn("[GoogleVertex] Forced finalization call failed; falling back to a terminal message",{error:ze instanceof Error?ze.message:String(ze)});let le=D&&!j?Zl(de):this.buildLoopExitMessage({turnClock:ee,wasAborted:j,stallTimeoutMs:e.stallTimeoutMs,maxSteps:b,toolCallCount:de});R.push(le),$+=le}}else if(D||(re=!0),$.length===0){g.warn(D?"[GoogleVertex] Native Anthropic stream loop stopped by the context guard with no text; synthesizing a final answer with tools disabled.":`[GoogleVertex] Native Anthropic stream loop reached maxSteps (${b}) with no text; synthesizing a final answer with tools disabled.`);try{let ze=(h?h+`
1140
1140
 
1141
- `:"")+"Tool calling is no longer available for this turn. Provide your final answer directly as plain text now, using the information gathered so far.",le=ob({system:ze,tools:l,messages:Y}),Le=await s.messages.stream({...x,max_tokens:qe,tool_choice:{type:"none"},system:le.system,...le.tools&&le.tools.length>0&&{tools:le.tools},messages:le.messages});te=Le;let _=await Le.finalMessage();te=void 0,k.input+=_.usage?.input_tokens||0,k.output+=_.usage?.output_tokens||0,J.read+=_.usage?.cache_read_input_tokens??0,J.creation+=_.usage?.cache_creation_input_tokens??0,J.creation5m+=_.usage?.cache_creation?.ephemeral_5m_input_tokens??0,J.creation1h+=_.usage?.cache_creation?.ephemeral_1h_input_tokens??0,k.total=k.input+k.output+J.read+J.creation,ae=_.stop_reason;let z=_.content.filter(X=>X.type==="text").map(X=>X.text).join("");if(z)oe=!0,R.push(z),$=z;else{let X=D?Zl(de):hg(b,de);R.push(X),$=X}}catch(ze){te=void 0,(he.signal.aborted||Yl(ze))&&(re=!1,j=!0),g.warn("[GoogleVertex] Tools-disabled backstop call failed; falling back to a terminal message",{error:ze instanceof Error?ze.message:String(ze)});let le=D&&!j?Zl(de):this.buildLoopExitMessage({turnClock:ee,wasAborted:j,stallTimeoutMs:e.stallTimeoutMs,maxSteps:b,toolCallCount:de});R.push(le),$=le}}}let Fe=$.length===0&&O===0&&!A.value,we=w.filter(de=>de.toolName!=="final_result").length;if(Fe&&we>0){let de=D&&!j?Zl(we):this.buildLoopExitMessage({turnClock:ee,wasAborted:j,stallTimeoutMs:e.stallTimeoutMs,maxSteps:b,toolCallCount:we});R.push(de),$=de}M.value=ae==="max_tokens"?"length":re&&!oe?"tool-calls":"stop",I.finishReason=M.value,I.responseTime=Date.now()-n,I.totalToolExecutions=w.filter(de=>de.toolName!=="final_result").length;let Rt=XI({timedOut:ee.timedOut,stalled:ee.stalled,wasAborted:j,cappedWithoutAnswer:re&&!oe,contextCappedWithoutAnswer:D&&!oe,finishReason:M.value});N.value=Rt,B.value=ae??void 0,I.stopReason=Rt,I.rawFinishReason=B.value,I.stepsUsed=se,Rt!=="completed"&&this.emitTurnEvent({phase:Rt,step:se,maxSteps:b,toolCallCount:I.totalToolExecutions,elapsedMs:ee.elapsedMs()}),J.read>0&&(k.cacheReadTokens=J.read),J.creation>0&&(k.cacheCreationTokens=J.creation);let Ye=Wo({text:$,...A.value?{structuredOutput:A.value}:{}});V.setAttribute(En.OBSERVATION_OUTPUT,Ye),V.setAttribute(En.TRACE_OUTPUT,Ye),V.setAttribute(En.OBSERVATION_METADATA,Wo({toolsOffered:L,toolCount:L.length,maxSteps:b,steps:se,toolCallCount:I.totalToolExecutions,toolsCalled:P.filter(de=>de!=="final_result"),structuredOutput:m,usage:{input:k.input,output:k.output,input_cached_tokens:J.read,input_cache_creation:J.creation,input_cache_creation_5m:J.creation5m,input_cache_creation_1h:J.creation1h}})),V.setStatus({code:$e.OK}),R.close()}catch(Fe){V.setStatus({code:$e.ERROR,message:Fe instanceof Error?Fe.message:String(Fe)}),Fe instanceof Error&&V.recordException(Fe),g.error("[GoogleVertex] Native Anthropic SDK stream error",Fe),R.error(this.handleProviderError(Fe))}finally{V.end(),e.abortSignal?.removeEventListener("abort",Ie),he.signal.removeEventListener("abort",Q),ee.dispose()}})().catch(()=>{});let Te={stream:R.iterable,provider:this.providerName,model:t,usage:k,metadata:I};return Object.defineProperty(Te,"toolCalls",{enumerable:!0,configurable:!0,get:()=>w.filter(se=>se.toolName!=="final_result")}),Object.defineProperty(Te,"toolsUsed",{enumerable:!0,configurable:!0,get:()=>P.filter(se=>se!=="final_result")}),Object.defineProperty(Te,"toolExecutions",{enumerable:!0,configurable:!0,get:()=>lv(C.filter(se=>se.name!=="final_result"))}),Object.defineProperty(Te,"structuredOutput",{enumerable:!0,configurable:!0,get:()=>A.value}),Object.defineProperty(Te,"finishReason",{enumerable:!0,configurable:!0,get:()=>M.value}),Object.defineProperty(Te,"stopReason",{enumerable:!0,configurable:!0,get:()=>N.value}),Object.defineProperty(Te,"rawFinishReason",{enumerable:!0,configurable:!0,get:()=>B.value}),Te}async executeNativeAnthropicGenerate(e){let t=Wte(e.model||this.modelName||"claude-sonnet-4-5@20250929"),n=Date.now(),o=nc(e.timeout)??3e5,s=await this.createAnthropicVertexClient(o);g.debug("[GoogleVertex] Using native @anthropic-ai/vertex-sdk for Claude generate",{model:t,project:this.projectId,location:this.location});let i=[],a=e.prompt||e.input?.text||"Please respond.";if(e.conversationMessages&&e.conversationMessages.length>0)i.push(..._se(e.conversationMessages));else if(e.conversationHistory&&e.conversationHistory.length>0)for(let D of e.conversationHistory)(D.role==="user"||D.role==="assistant")&&i.push({role:D.role,content:zp(D.content)});let c=e.input,l=[];if(c?.pdfFiles&&c.pdfFiles.length>0){g.debug(`[GoogleVertex] Processing ${c.pdfFiles.length} PDF file(s) for native Anthropic generate`);for(let D of c.pdfFiles){let oe;typeof D=="string"?Rr.existsSync(D)?oe=Rr.readFileSync(D):oe=Buffer.from(D,"base64"):oe=D;let Z=oe.toString("base64");l.push({type:"document",source:{type:"base64",media_type:"application/pdf",data:Z}})}}if(c?.images&&c.images.length>0){g.debug(`[GoogleVertex] Processing ${c.images.length} image(s) for native Anthropic generate`);for(let D of c.images){let oe=Fw(D),Z,ae="image/jpeg";if(typeof oe=="string")if(Rr.existsSync(oe)){Z=Rr.readFileSync(oe);let ye=bv(oe);ae=ye.startsWith("image/")?ye:this.detectImageType(Z)}else if(oe.startsWith("data:")){let ye=oe.match(/^data:([^;]+);base64,(.+)$/);if(ye)ae=ye[1],Z=Buffer.from(ye[2],"base64");else continue}else if(oe.startsWith("http://")||oe.startsWith("https://"))try{let ye=await fetch(oe);if(!ye.ok){g.warn(`[GoogleVertex] Image fetch failed: ${ye.status} ${ye.statusText}, skipping`,{url:tn(oe)});continue}let Fe=await ye.arrayBuffer();Z=Buffer.from(Fe);let we=ye.headers.get("content-type");we&&we.startsWith("image/")&&(ae=we.split(";")[0])}catch(ye){g.warn(`[GoogleVertex] Image URL fetch threw, skipping: ${ye instanceof Error?ye.message:String(ye)}`,{url:tn(oe)});continue}else Z=Buffer.from(oe,"base64"),ae=this.detectImageType(Z);else Z=oe,ae=this.detectImageType(Z);let ce=Z.toString("base64");l.push({type:"image",source:{type:"base64",media_type:ae,data:ce}})}}l.push({type:"text",text:a}),Ese(i,l.length===1&&l[0].type==="text"?a:l);let d,p=new Bd,m=[];if(!e.disableTools&&e.tools&&Object.keys(e.tools).length>0){d=[];for(let[D,oe]of Object.entries(e.tools))d.push(this.buildAnthropicToolDeclaration(D,oe)),oe.execute&&p.set(D,oe.execute)}let f=!1,h="";if(e.schema){f=!0;let D=Cn(e.schema),oe=pn(D);oe.$schema&&delete oe.$schema;let Z=di(oe),ae={name:"final_result",description:"Return the final structured result. You MUST call this tool when you have gathered all information and are ready to provide the final answer. The arguments should contain the structured data matching the expected schema.",input_schema:{type:"object",properties:Z.properties||Z,required:Z.required||[]}};d||(d=[]),d.push(ae),h=`
1141
+ `:"")+"Tool calling is no longer available for this turn. Provide your final answer directly as plain text now, using the information gathered so far.",le=ob({system:ze,tools:l,messages:Y}),Le=await s.messages.stream({...x,max_tokens:qe,tool_choice:{type:"none"},system:le.system,...le.tools&&le.tools.length>0&&{tools:le.tools},messages:le.messages});te=Le;let _=await Le.finalMessage();te=void 0,k.input+=_.usage?.input_tokens||0,k.output+=_.usage?.output_tokens||0,J.read+=_.usage?.cache_read_input_tokens??0,J.creation+=_.usage?.cache_creation_input_tokens??0,J.creation5m+=_.usage?.cache_creation?.ephemeral_5m_input_tokens??0,J.creation1h+=_.usage?.cache_creation?.ephemeral_1h_input_tokens??0,k.total=k.input+k.output+J.read+J.creation,ae=_.stop_reason;let z=_.content.filter(X=>X.type==="text").map(X=>X.text).join("");if(z)oe=!0,R.push(z),$=z;else{let X=D?Zl(de):hg(b,de);R.push(X),$=X}}catch(ze){te=void 0,(he.signal.aborted||Yl(ze))&&(re=!1,j=!0),g.warn("[GoogleVertex] Tools-disabled backstop call failed; falling back to a terminal message",{error:ze instanceof Error?ze.message:String(ze)});let le=D&&!j?Zl(de):this.buildLoopExitMessage({turnClock:ee,wasAborted:j,stallTimeoutMs:e.stallTimeoutMs,maxSteps:b,toolCallCount:de});R.push(le),$=le}}}let Fe=$.length===0&&O===0&&!A.value,we=w.filter(de=>de.toolName!=="final_result").length;if(Fe&&we>0){let de=D&&!j?Zl(we):this.buildLoopExitMessage({turnClock:ee,wasAborted:j,stallTimeoutMs:e.stallTimeoutMs,maxSteps:b,toolCallCount:we});R.push(de),$=de}M.value=ae==="max_tokens"?"length":re&&!oe?"tool-calls":"stop",I.finishReason=M.value,I.responseTime=Date.now()-n,I.totalToolExecutions=w.filter(de=>de.toolName!=="final_result").length;let Rt=XI({timedOut:ee.timedOut,stalled:ee.stalled,wasAborted:j,cappedWithoutAnswer:re&&!oe,contextCappedWithoutAnswer:D&&!oe,finishReason:M.value});N.value=Rt,B.value=ae??void 0,I.stopReason=Rt,I.rawFinishReason=B.value,I.stepsUsed=se,Rt!=="completed"&&this.emitTurnEvent({phase:Rt,step:se,maxSteps:b,toolCallCount:I.totalToolExecutions,elapsedMs:ee.elapsedMs()}),J.read>0&&(k.cacheReadTokens=J.read),J.creation>0&&(k.cacheCreationTokens=J.creation);let Ye=Wo({text:$,...A.value?{structuredOutput:A.value}:{}});V.setAttribute(En.OBSERVATION_OUTPUT,Ye),V.setAttribute(En.TRACE_OUTPUT,Ye),V.setAttribute(En.OBSERVATION_METADATA,Wo({toolsOffered:L,toolCount:L.length,maxSteps:b,steps:se,toolCallCount:I.totalToolExecutions,toolsCalled:P.filter(de=>de!=="final_result"),structuredOutput:m,usage:{input:k.input,output:k.output,input_cached_tokens:J.read,input_cache_creation:J.creation,input_cache_creation_5m:J.creation5m,input_cache_creation_1h:J.creation1h}})),V.setStatus({code:$e.OK}),R.close()}catch(Fe){V.setStatus({code:$e.ERROR,message:Fe instanceof Error?Fe.message:String(Fe)}),Fe instanceof Error&&V.recordException(Fe),g.error("[GoogleVertex] Native Anthropic SDK stream error",Fe),R.error(this.handleProviderError(Fe))}finally{V.end(),e.abortSignal?.removeEventListener("abort",Ie),he.signal.removeEventListener("abort",Q),ee.dispose()}})().catch(()=>{});let Te={stream:R.iterable,provider:this.providerName,model:t,usage:k,metadata:I};return Object.defineProperty(Te,"toolCalls",{enumerable:!0,configurable:!0,get:()=>w.filter(se=>se.toolName!=="final_result")}),Object.defineProperty(Te,"toolsUsed",{enumerable:!0,configurable:!0,get:()=>P.filter(se=>se!=="final_result")}),Object.defineProperty(Te,"toolExecutions",{enumerable:!0,configurable:!0,get:()=>lv(C.filter(se=>se.name!=="final_result"))}),Object.defineProperty(Te,"structuredOutput",{enumerable:!0,configurable:!0,get:()=>A.value}),Object.defineProperty(Te,"finishReason",{enumerable:!0,configurable:!0,get:()=>M.value}),Object.defineProperty(Te,"stopReason",{enumerable:!0,configurable:!0,get:()=>N.value}),Object.defineProperty(Te,"rawFinishReason",{enumerable:!0,configurable:!0,get:()=>B.value}),Te}async executeNativeAnthropicGenerate(e){let t=Wte(e.model||this.modelName||"claude-sonnet-4-5@20250929"),n=Date.now(),o=nc(e.timeout)??3e5,s=await this.createAnthropicVertexClient(o);g.debug("[GoogleVertex] Using native @anthropic-ai/vertex-sdk for Claude generate",{model:t,project:this.projectId,location:this.location});let i=[],a=e.input?.text||e.prompt||"Please respond.";if(e.conversationMessages&&e.conversationMessages.length>0)i.push(..._se(e.conversationMessages));else if(e.conversationHistory&&e.conversationHistory.length>0)for(let D of e.conversationHistory)(D.role==="user"||D.role==="assistant")&&i.push({role:D.role,content:zp(D.content)});let c=e.input,l=[];if(c?.pdfFiles&&c.pdfFiles.length>0){g.debug(`[GoogleVertex] Processing ${c.pdfFiles.length} PDF file(s) for native Anthropic generate`);for(let D of c.pdfFiles){let oe;typeof D=="string"?Rr.existsSync(D)?oe=Rr.readFileSync(D):oe=Buffer.from(D,"base64"):oe=D;let Z=oe.toString("base64");l.push({type:"document",source:{type:"base64",media_type:"application/pdf",data:Z}})}}if(c?.images&&c.images.length>0){g.debug(`[GoogleVertex] Processing ${c.images.length} image(s) for native Anthropic generate`);for(let D of c.images){let oe=Fw(D),Z,ae="image/jpeg";if(typeof oe=="string")if(Rr.existsSync(oe)){Z=Rr.readFileSync(oe);let ye=bv(oe);ae=ye.startsWith("image/")?ye:this.detectImageType(Z)}else if(oe.startsWith("data:")){let ye=oe.match(/^data:([^;]+);base64,(.+)$/);if(ye)ae=ye[1],Z=Buffer.from(ye[2],"base64");else continue}else if(oe.startsWith("http://")||oe.startsWith("https://"))try{let ye=await fetch(oe);if(!ye.ok){g.warn(`[GoogleVertex] Image fetch failed: ${ye.status} ${ye.statusText}, skipping`,{url:tn(oe)});continue}let Fe=await ye.arrayBuffer();Z=Buffer.from(Fe);let we=ye.headers.get("content-type");we&&we.startsWith("image/")&&(ae=we.split(";")[0])}catch(ye){g.warn(`[GoogleVertex] Image URL fetch threw, skipping: ${ye instanceof Error?ye.message:String(ye)}`,{url:tn(oe)});continue}else Z=Buffer.from(oe,"base64"),ae=this.detectImageType(Z);else Z=oe,ae=this.detectImageType(Z);let ce=Z.toString("base64");l.push({type:"image",source:{type:"base64",media_type:ae,data:ce}})}}l.push({type:"text",text:a}),Ese(i,l.length===1&&l[0].type==="text"?a:l);let d,p=new Bd,m=[];if(!e.disableTools&&e.tools&&Object.keys(e.tools).length>0){d=[];for(let[D,oe]of Object.entries(e.tools))d.push(this.buildAnthropicToolDeclaration(D,oe)),oe.execute&&p.set(D,oe.execute)}let f=!1,h="";if(e.schema){f=!0;let D=Cn(e.schema),oe=pn(D);oe.$schema&&delete oe.$schema;let Z=di(oe),ae={name:"final_result",description:"Return the final structured result. You MUST call this tool when you have gathered all information and are ready to provide the final answer. The arguments should contain the structured data matching the expected schema.",input_schema:{type:"object",properties:Z.properties||Z,required:Z.required||[]}};d||(d=[]),d.push(ae),h=`
1142
1142
 
1143
1143
  IMPORTANT: You MUST call the 'final_result' tool to return your response in the required structured format. Do not respond with plain text - always use the final_result tool.`,g.debug("[GoogleVertex] Added final_result tool for Anthropic structured output (generate)",{schemaKeys:Object.keys(Z),totalTools:d.length})}let y=e.systemPrompt?e.systemPrompt+h:h?h.trim():void 0,x=Sa(this.providerName,t,{...e.temperature!==void 0&&{temperature:e.temperature},...e.topP!==void 0&&{topP:e.topP}},"vertex.anthropic.generate"),b={model:t,max_tokens:u_(t,e.maxTokens),messages:i,...d&&d.length>0&&{tools:d},...f&&{tool_choice:{type:"any"}},...y&&{system:y},...x.temperature!==void 0&&{temperature:x.temperature},...x.topP!==void 0&&{top_p:x.topP},...e.stopSequences&&e.stopSequences.length>0&&{stop_sequences:e.stopSequences}},T=e.maxSteps||as,w=f?Math.max(T-1,0):T,C=0,R="",k="",I,P=[],A=0,M=0,N=0,B=0,L,F=!1,V=!1,G=!1,$=!1,O=!1,J=[...i],te=jh(Md("vertex",t)),Q=new Map,he=new AbortController,Ie=()=>he.abort();e.abortSignal?.addEventListener("abort",Ie),e.abortSignal?.aborted&&he.abort();let H=e.toolTimeoutMs??sw,ie=YI({turnTimeoutMs:e.turnTimeoutMs,stallTimeoutMs:e.stallTimeoutMs,wrapupTimeLeadMs:e.wrapupTimeLeadMs,onDeadline:D=>{g.warn(D==="timeout"?`[GoogleVertex] Anthropic generate turn exceeded its ${e.turnTimeoutMs}ms time budget \u2014 aborting`:`[GoogleVertex] Anthropic generate turn made no progress for ${e.stallTimeoutMs}ms \u2014 aborting`),he.abort()}}),ee=()=>{ie.dispose(),e.abortSignal?.removeEventListener("abort",Ie)};for(;C<w;){if(he.signal.aborted){F=!0;break}if(te.shouldStop())if(MBe(J,t,te.projectedNextPromptTokens))te.resetAfterReclaim();else{G=!0,g.warn(`[GoogleVertex] Anthropic generate turn stopped by the context guard: projected prompt ~${te.projectedNextPromptTokens} tokens >= threshold ${te.thresholdTokens} (step ${C}) \u2014 synthesizing a final answer.`);break}C++,ie.noteProgress(),this.refreshAnthropicToolDeclarations(e.tools,d,p,Q);try{let D=ob({system:y,tools:d,messages:J}),oe=await vt(s.messages.create({...b,...D.system!==void 0&&{system:D.system},...D.tools&&D.tools.length>0&&{tools:D.tools},messages:D.messages},{signal:he.signal}),o,"Anthropic generate timed out");A+=oe.usage?.input_tokens||0,M+=oe.usage?.output_tokens||0,N+=oe.usage?.cache_read_input_tokens||0,B+=oe.usage?.cache_creation_input_tokens||0,L=oe.stop_reason,te.noteUsage((oe.usage?.input_tokens||0)+(oe.usage?.cache_read_input_tokens||0)+(oe.usage?.cache_creation_input_tokens||0),oe.usage?.output_tokens||0);let Z=oe.content.filter(de=>de.type==="tool_use");if(f){let de=Z.find(qe=>qe.name==="final_result");if(de){I=de.input,R=JSON.stringify(I),O=!0,g.debug("[GoogleVertex] Extracted structured output from final_result tool (generate)",{keys:Object.keys(I)});break}}let ce=oe.content.filter(de=>de.type==="text").map(de=>de.text).join("");if(Z.length===0){R=ce||k,O=!0;break}let ye=[],Fe=[],we=[];for(let de of Z){if(he.signal.aborted){F=!0;break}P.push({toolName:de.name,args:de.input}),Fe.push({toolCallId:de.id,toolName:de.name,args:de.input});let qe=Q.get(de.name);if(qe&&qe.count>=Wn){g.warn(`[GoogleVertex] Tool "${de.name}" has exceeded retry limit (${Wn}), skipping execution`);let le=`TOOL_PERMANENTLY_FAILED: The tool "${de.name}" has failed ${qe.count} times and will not be retried. Last error: ${qe.lastError}. Please proceed without using this tool or inform the user that this functionality is unavailable.`,Le={error:le};m.push({name:de.name,input:de.input,output:Le}),ye.push({type:"tool_result",tool_use_id:de.id,content:le}),we.push({toolCallId:de.id,toolName:de.name,output:Le});continue}let ze=p.get(de.name);if(ze||(ze=this.resolveAnthropicToolOnMiss(de.name,e.tools,d,p,Q)),ze)try{let le={toolCallId:de.id,messages:[],abortSignal:he.signal};ie.noteProgress();let Le=await vt(oh(Promise.resolve(ze(de.input,le)),he.signal),H,`Tool "${de.name}" execution timed out after ${H}ms`);ie.noteProgress();let _=NI(Le);if(_){let X=Q.get(de.name)||{count:0,lastError:""};X.count++,X.lastError=_,Q.set(de.name,X)}else Q.delete(de.name);m.push({name:de.name,input:de.input,output:Le});let z=typeof Le=="string"?Le:zp(Le??null);ye.push({type:"tool_result",tool_use_id:de.id,content:z}),we.push({toolCallId:de.id,toolName:de.name,output:Le})}catch(le){if(he.signal.aborted||Yl(le)){we.push({toolCallId:de.id,toolName:de.name,output:{aborted:!0}}),F=!0;break}ie.noteProgress(),le instanceof tc&&this.emitTurnEvent({phase:"tool-timeout",step:C,maxSteps:T,toolName:de.name});let Le=le instanceof Error?le.message:String(le),_=Q.get(de.name)||{count:0,lastError:""};_.count++,_.lastError=Le,Q.set(de.name,_),g.warn(`[GoogleVertex] Tool "${de.name}" failed (attempt ${_.count}/${Wn}): ${Le}`);let z=`Error executing tool "${de.name}": ${Le}`,X={error:z};m.push({name:de.name,input:de.input,output:X}),ye.push({type:"tool_result",tool_use_id:de.id,content:z}),we.push({toolCallId:de.id,toolName:de.name,output:X})}else{let le=`TOOL_NOT_FOUND: The tool "${de.name}" does not exist.`,Le={error:le},_=Q.get(de.name)||{count:0,lastError:""};_.count++,_.lastError=le,Q.set(de.name,_),m.push({name:de.name,input:de.input,output:Le}),ye.push({type:"tool_result",tool_use_id:de.id,content:le}),we.push({toolCallId:de.id,toolName:de.name,output:Le})}}if((Fe.length>0||we.length>0)&&vt(this.handleToolExecutionStorage(Fe.map(de=>({...de,stepIndex:C})),we.map(de=>({...de,stepIndex:C})),e,new Date),Jm,"tool storage write timed out").catch(de=>{g.warn("[GoogleVertex] Failed to store native Anthropic generate tool executions",{error:de instanceof Error?de.message:String(de)})}),F)break;let Rt=w-C;Rt>0&&Rt<=3?ye.push({type:"text",text:`NOTE: Only ${Rt} tool step(s) remain. Consolidate what you have and `+(f?"call final_result with your best answer.":"provide your final answer.")}):ie.shouldNudgeWrapup()&&ye.push({type:"text",text:JI(f)});let Ye=oe.content.filter(de=>de.type!=="server_tool_use");J.push({role:"assistant",content:Ye}),J.push({role:"user",content:ye}),te.noteAppendedChars(ye.reduce((de,qe)=>de+("content"in qe?qe.content.length:qe.text.length),0)),k=are(k,ce)}catch(D){if(he.signal.aborted||Yl(D)){F=!0;break}g.error("[GoogleVertex] Native Anthropic SDK generate error",{error:D,model:t,step:C,status:D?.status});try{D&&typeof D=="object"&&(D.requestModel=t)}catch{}throw ee(),this.handleProviderError(D)}}if(!O&&!R){he.signal.aborted&&(F=!0);let D=P.filter(Z=>Z.toolName!=="final_result").length,oe=Math.max(1024,Math.min(b.max_tokens,Md("vertex",t)-te.projectedNextPromptTokens-4e3));if(F)g.warn(`[GoogleVertex] Native Anthropic generate loop ended mid-turn (${ie.timedOut?"turn time limit":ie.stalled?"stall watchdog":"caller abort"}); returning gathered text or an honest terminal message.`),R=k||this.buildLoopExitMessage({turnClock:ie,wasAborted:F,stallTimeoutMs:e.stallTimeoutMs,maxSteps:T,toolCallCount:D});else if(f){G||(V=!0),g.warn(G?"[GoogleVertex] Native Anthropic generate loop stopped by the context guard without final_result; forcing a finalization call.":`[GoogleVertex] Native Anthropic generate loop reached maxSteps (${T}) without final_result; forcing a finalization call.`);try{let Z=ob({system:y,tools:d,messages:J}),ae=await vt(s.messages.create({...b,max_tokens:oe,tool_choice:{type:"tool",name:"final_result"},...Z.system!==void 0&&{system:Z.system},...Z.tools&&Z.tools.length>0&&{tools:Z.tools},messages:Z.messages},{signal:he.signal}),o,"Anthropic finalization call timed out");A+=ae.usage?.input_tokens||0,M+=ae.usage?.output_tokens||0,N+=ae.usage?.cache_read_input_tokens||0,B+=ae.usage?.cache_creation_input_tokens||0,L=ae.stop_reason;let ce=ae.content.find(ye=>ye.type==="tool_use"&&ye.name==="final_result");ce?(I=ce.input,R=JSON.stringify(I),$=!0,g.debug("[GoogleVertex] Forced finalization returned structured output (generate)",{keys:Object.keys(I)})):R=G?Zl(D):hg(T,D)}catch(Z){(he.signal.aborted||Yl(Z))&&(V=!1,F=!0),g.warn("[GoogleVertex] Forced finalization call failed; falling back to a terminal message",{error:Z instanceof Error?Z.message:String(Z)}),R=G&&!F?Zl(D):this.buildLoopExitMessage({turnClock:ie,wasAborted:F,stallTimeoutMs:e.stallTimeoutMs,maxSteps:T,toolCallCount:D})}}else if(G||(V=!0),k)g.warn(G?"[GoogleVertex] Native Anthropic generate loop stopped by the context guard; returning text already gathered from prior steps.":`[GoogleVertex] Native Anthropic generate loop reached maxSteps (${T}); returning text already gathered from prior steps.`),R=k;else{g.warn(G?"[GoogleVertex] Native Anthropic generate loop stopped by the context guard with no text; synthesizing a final answer with tools disabled.":`[GoogleVertex] Native Anthropic generate loop reached maxSteps (${T}) with no text; synthesizing a final answer with tools disabled.`);try{let Z=(y?y+`
1144
1144
 
@@ -4815,7 +4815,15 @@ export class GoogleVertexProvider extends BaseProvider {
4815
4815
  });
4816
4816
  // Build messages from input
4817
4817
  const messages = [];
4818
- const inputText = options.prompt || options.input?.text || "Please respond.";
4818
+ // input.text FIRST the file preprocessors (processUnifiedFilesArray,
4819
+ // processCSVFilesForNativeSDK) append attached-file content to input.text,
4820
+ // while options.prompt is snapshotted from the ORIGINAL input.text at
4821
+ // baseOptions creation (neurolink.ts). With prompt-first precedence every
4822
+ // attached file was silently dropped on the Claude generate path — the
4823
+ // model answered "no file attached" to a request that carried one. The
4824
+ // native Gemini path already reads input.text first for exactly this
4825
+ // reason.
4826
+ const inputText = options.input?.text || options.prompt || "Please respond.";
4819
4827
  // Replay conversationMessages (with tool turns), else the legacy text-only conversationHistory.
4820
4828
  if (options.conversationMessages &&
4821
4829
  options.conversationMessages.length > 0) {
@@ -1073,6 +1073,18 @@ export async function processUnifiedFilesArray(options, maxSize, provider) {
1073
1073
  options.systemPrompt = existingSystem
1074
1074
  ? `${existingSystem}${filePromptAugmentation}`
1075
1075
  : filePromptAugmentation.trim();
1076
+ // Keep options.prompt in sync with the enriched input.text.
1077
+ // neurolink.ts snapshots `prompt: options.input?.text` at baseOptions
1078
+ // creation — BEFORE this function appends file content — and some
1079
+ // native paths (executeNativeAnthropicGenerate historically) read
1080
+ // `options.prompt` first. Leaving the stale snapshot in place means
1081
+ // every appended file is silently dropped on those paths and the model
1082
+ // answers "no file attached". Same dual-write processCSVFilesForNativeSDK
1083
+ // already documents for exactly this trap.
1084
+ const promptCarrier = options;
1085
+ if (typeof promptCarrier.prompt === "string") {
1086
+ promptCarrier.prompt = inp2.text;
1087
+ }
1076
1088
  }
1077
1089
  });
1078
1090
  }
@@ -4815,7 +4815,15 @@ export class GoogleVertexProvider extends BaseProvider {
4815
4815
  });
4816
4816
  // Build messages from input
4817
4817
  const messages = [];
4818
- const inputText = options.prompt || options.input?.text || "Please respond.";
4818
+ // input.text FIRST the file preprocessors (processUnifiedFilesArray,
4819
+ // processCSVFilesForNativeSDK) append attached-file content to input.text,
4820
+ // while options.prompt is snapshotted from the ORIGINAL input.text at
4821
+ // baseOptions creation (neurolink.ts). With prompt-first precedence every
4822
+ // attached file was silently dropped on the Claude generate path — the
4823
+ // model answered "no file attached" to a request that carried one. The
4824
+ // native Gemini path already reads input.text first for exactly this
4825
+ // reason.
4826
+ const inputText = options.input?.text || options.prompt || "Please respond.";
4819
4827
  // Replay conversationMessages (with tool turns), else the legacy text-only conversationHistory.
4820
4828
  if (options.conversationMessages &&
4821
4829
  options.conversationMessages.length > 0) {
@@ -1073,6 +1073,18 @@ export async function processUnifiedFilesArray(options, maxSize, provider) {
1073
1073
  options.systemPrompt = existingSystem
1074
1074
  ? `${existingSystem}${filePromptAugmentation}`
1075
1075
  : filePromptAugmentation.trim();
1076
+ // Keep options.prompt in sync with the enriched input.text.
1077
+ // neurolink.ts snapshots `prompt: options.input?.text` at baseOptions
1078
+ // creation — BEFORE this function appends file content — and some
1079
+ // native paths (executeNativeAnthropicGenerate historically) read
1080
+ // `options.prompt` first. Leaving the stale snapshot in place means
1081
+ // every appended file is silently dropped on those paths and the model
1082
+ // answers "no file attached". Same dual-write processCSVFilesForNativeSDK
1083
+ // already documents for exactly this trap.
1084
+ const promptCarrier = options;
1085
+ if (typeof promptCarrier.prompt === "string") {
1086
+ promptCarrier.prompt = inp2.text;
1087
+ }
1076
1088
  }
1077
1089
  });
1078
1090
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@juspay/neurolink",
3
- "version": "10.12.6",
3
+ "version": "10.12.7",
4
4
  "packageManager": "pnpm@10.15.1",
5
5
  "description": "TypeScript AI SDK with 24+ LLM providers behind one consistent API. MCP-native (connect any MCP server), voice TTS/STT/realtime, RAG, agents, memory, context compaction. OpenAI · Anthropic · Gemini · Bedrock · Azure · Ollama · DeepSeek · NVIDIA NIM and more.",
6
6
  "author": {
@@ -146,6 +146,7 @@
146
146
  "test:anthropic-structured": "npx tsx test/continuous-test-suite-anthropic-structured-tools.ts",
147
147
  "test:sagemaker-tools": "npx tsx test/continuous-test-suite-sagemaker-tools.ts",
148
148
  "test:anthropic-multimodal": "npx tsx test/continuous-test-suite-anthropic-multimodal.ts",
149
+ "test:unified-files-prompt-sync": "npx tsx test/continuous-test-suite-unified-files-prompt-sync.ts",
149
150
  "test:excel-interop": "npx tsx test/continuous-test-suite-excel-interop.ts",
150
151
  "test:envguard": "npx tsx test/helpers/envGuard.test.ts",
151
152
  "test:tool-routing-cli": "npx tsx test/continuous-test-suite-tool-routing-flags.ts && npx tsx test/continuous-test-suite-tool-routing-cli.ts",
@@ -163,7 +164,7 @@
163
164
  "test:system-messages": "npx tsx test/continuous-test-suite-system-messages.ts",
164
165
  "test:test-stubs": "npx tsx test/continuous-test-suite-test-stubs.ts",
165
166
  "test:tool-routing-semantic": "npx tsx test/continuous-test-suite-tool-routing-semantic.ts",
166
- "test:unit": "pnpm run test:envguard && pnpm run test:bugfixes && pnpm run test:file-detector-extension && pnpm run test:file-detector-magic-bytes && pnpm run test:mcp:infra && pnpm run test:mcp:bash && pnpm run test:mcp:limits && pnpm run test:mcp:spans && pnpm run test:autoresearch:redis && pnpm run test:tool-routing && pnpm run test:tool-routing-cli && pnpm run test:tool-dedup && pnpm run test:model-pool && pnpm run test:litellm-context && pnpm run test:dedup-execute-map && pnpm run test:step-budget-guard && pnpm run test:agent-plumbing && pnpm run test:tool-execution-recorder && pnpm run test:proxy-terminal-errors && pnpm run test:proxy-usage-refresh && pnpm run test:system-messages && pnpm run test:tool-routing-semantic && pnpm run test:anthropic-tools-policy && pnpm run test:anthropic-structured && pnpm run test:sagemaker-tools && pnpm run test:anthropic-multimodal && pnpm run test:excel-interop && pnpm run test:model-capabilities && pnpm run test:agent-runtime:vitest && pnpm run test:agent-delegation && pnpm run test:retry-after:vitest && pnpm run test:sampling-params && pnpm run test:structured-recovery && pnpm run test:prompt-redaction && pnpm run test:mcp-result-cache && pnpm run test:test-stubs && pnpm run test:model-not-found-retryable && pnpm run test:websearch-grounding && pnpm run test:archive:security && pnpm run test:office:security && pnpm run test:proxy:vitest",
167
+ "test:unit": "pnpm run test:envguard && pnpm run test:bugfixes && pnpm run test:file-detector-extension && pnpm run test:file-detector-magic-bytes && pnpm run test:mcp:infra && pnpm run test:mcp:bash && pnpm run test:mcp:limits && pnpm run test:mcp:spans && pnpm run test:autoresearch:redis && pnpm run test:tool-routing && pnpm run test:tool-routing-cli && pnpm run test:tool-dedup && pnpm run test:model-pool && pnpm run test:litellm-context && pnpm run test:dedup-execute-map && pnpm run test:step-budget-guard && pnpm run test:agent-plumbing && pnpm run test:tool-execution-recorder && pnpm run test:proxy-terminal-errors && pnpm run test:proxy-usage-refresh && pnpm run test:system-messages && pnpm run test:tool-routing-semantic && pnpm run test:anthropic-tools-policy && pnpm run test:anthropic-structured && pnpm run test:sagemaker-tools && pnpm run test:anthropic-multimodal && pnpm run test:unified-files-prompt-sync && pnpm run test:excel-interop && pnpm run test:model-capabilities && pnpm run test:agent-runtime:vitest && pnpm run test:agent-delegation && pnpm run test:retry-after:vitest && pnpm run test:sampling-params && pnpm run test:structured-recovery && pnpm run test:prompt-redaction && pnpm run test:mcp-result-cache && pnpm run test:test-stubs && pnpm run test:model-not-found-retryable && pnpm run test:websearch-grounding && pnpm run test:archive:security && pnpm run test:office:security && pnpm run test:proxy:vitest",
167
168
  "// CI tier — live providers, runs only when API keys are present (test:credentials and test:dynamic make real provider calls when keys are set, so they live here, not in test:unit)": "",
168
169
  "test:live": "pnpm run test:providers && pnpm run test:mcp:http && pnpm run test:mcp:sdk && pnpm run test:mcp:cli && pnpm run test:observability && pnpm run test:context && pnpm run test:memory && pnpm run test:tool-reliability && pnpm run test:evaluation && pnpm run test:autoresearch && pnpm run test:credentials && pnpm run test:dynamic",
169
170
  "// CI tier — product output (image/video/TTS/PPT) — costs $$ per run": "",