@astralyn/pi 1.4.0 → 1.4.2
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 +12 -0
- package/dist/bundle/chunks/{chunk-BMTEURL3.js → chunk-FGPSYHTQ.js} +72 -11
- package/dist/bundle/chunks/{chunk-TJIPCBZF.js → chunk-HXKY52DF.js} +1 -1
- package/dist/bundle/chunks/{virtual-modules-3CTTTQQN.js → virtual-modules-5NSVVTKO.js} +1 -1
- package/dist/bundle/cli.js +1 -1
- package/dist/bundle/index.js +1 -1
- package/dist/bundle/rpc-entry.js +1 -1
- package/dist/core/compaction/compaction.d.ts.map +1 -1
- package/dist/core/compaction/compaction.js +5 -5
- package/dist/core/compaction/compaction.js.map +1 -1
- package/dist/core/extensions/index.d.ts +1 -1
- package/dist/core/extensions/index.d.ts.map +1 -1
- package/dist/core/extensions/index.js.map +1 -1
- package/dist/core/extensions/types.d.ts +25 -1
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/extensions/cached-compaction/index.d.ts +3 -0
- package/dist/extensions/cached-compaction/index.d.ts.map +1 -0
- package/dist/extensions/cached-compaction/index.js +91 -0
- package/dist/extensions/cached-compaction/index.js.map +1 -0
- package/dist/extensions/cached-compaction/render.d.ts +11 -0
- package/dist/extensions/cached-compaction/render.d.ts.map +1 -0
- package/dist/extensions/cached-compaction/render.js +19 -0
- package/dist/extensions/cached-compaction/render.js.map +1 -0
- package/dist/extensions/cached-compaction/summary.d.ts +15 -0
- package/dist/extensions/cached-compaction/summary.d.ts.map +1 -0
- package/dist/extensions/cached-compaction/summary.js +131 -0
- package/dist/extensions/cached-compaction/summary.js.map +1 -0
- package/dist/extensions/index.d.ts.map +1 -1
- package/dist/extensions/index.js +4 -0
- package/dist/extensions/index.js.map +1 -1
- package/dist/extensions/tool-presentation/index.d.ts +7 -0
- package/dist/extensions/tool-presentation/index.d.ts.map +1 -0
- package/dist/extensions/tool-presentation/index.js +9 -0
- package/dist/extensions/tool-presentation/index.js.map +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/modes/interactive/components/index.d.ts +1 -1
- package/dist/modes/interactive/components/index.d.ts.map +1 -1
- package/dist/modes/interactive/components/index.js +1 -1
- package/dist/modes/interactive/components/index.js.map +1 -1
- package/dist/modes/interactive/components/tool-execution.d.ts +85 -0
- package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -0
- package/dist/modes/interactive/components/tool-execution.js +362 -0
- package/dist/modes/interactive/components/tool-execution.js.map +1 -0
- package/dist/modes/interactive/interactive-mode.js +1 -1
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/interactive/tool-view/chat.d.ts +1 -1
- package/dist/modes/interactive/tool-view/chat.d.ts.map +1 -1
- package/dist/modes/interactive/tool-view/chat.js +2 -3
- package/dist/modes/interactive/tool-view/chat.js.map +1 -1
- package/dist/modes/interactive/tool-view/shell.d.ts +15 -0
- package/dist/modes/interactive/tool-view/shell.d.ts.map +1 -0
- package/dist/modes/interactive/tool-view/shell.js +51 -0
- package/dist/modes/interactive/tool-view/shell.js.map +1 -0
- package/dist/modes/interactive/tool-view/tool-execution.d.ts +10 -79
- package/dist/modes/interactive/tool-view/tool-execution.d.ts.map +1 -1
- package/dist/modes/interactive/tool-view/tool-execution.js +7 -298
- package/dist/modes/interactive/tool-view/tool-execution.js.map +1 -1
- package/docs/bundled/extensions/cached-compaction.md +35 -0
- package/docs/bundled/tool-presentation.md +9 -7
- package/docs/compaction.md +1 -1
- package/docs/docs.json +4 -0
- package/docs/extensions.md +3 -1
- package/npm-shrinkwrap.json +2 -2
- package/package.json +1 -1
|
@@ -728,7 +728,7 @@ ${sections.join(`
|
|
|
728
728
|
|
|
729
729
|
`)}var SUMMARIZATION_SYSTEM_PROMPT=`You are a context summarization assistant. Your task is to read a conversation between a user and an AI assistant, then produce a structured summary following the exact format specified.
|
|
730
730
|
|
|
731
|
-
Do NOT continue the conversation. Do NOT respond to any questions in the conversation. ONLY output the structured summary.`;function createUsageTotals(){return{input:0,output:0,cacheRead:0,cacheWrite:0,cost:0}}function addUsageToTotals(totals,usage){totals.input+=usage.input,totals.output+=usage.output,totals.cacheRead+=usage.cacheRead,totals.cacheWrite+=usage.cacheWrite,totals.cost+=usage.cost.total}function combineUsage(first,second){return{input:first.input+second.input,output:first.output+second.output,cacheRead:first.cacheRead+second.cacheRead,cacheWrite:first.cacheWrite+second.cacheWrite,...first.cacheWrite1h!==void 0||second.cacheWrite1h!==void 0?{cacheWrite1h:(first.cacheWrite1h??0)+(second.cacheWrite1h??0)}:{},...first.reasoning!==void 0||second.reasoning!==void 0?{reasoning:(first.reasoning??0)+(second.reasoning??0)}:{},totalTokens:first.totalTokens+second.totalTokens,cost:{input:first.cost.input+second.cost.input,output:first.cost.output+second.cost.output,cacheRead:first.cost.cacheRead+second.cost.cacheRead,cacheWrite:first.cost.cacheWrite+second.cost.cacheWrite,total:first.cost.total+second.cost.total}}}var TASK_USAGE_TYPE="task-usage";function isRecord(value){return typeof value=="object"&&value!==null&&!Array.isArray(value)}function isUsageValue(value){return typeof value=="number"&&Number.isFinite(value)&&value>=0}function getTaskUsageRecord(entry){if(entry.type!=="custom"||entry.customType!==TASK_USAGE_TYPE)return;let data=entry.data;if(!isRecord(data)||data.version!==1||typeof data.taskId!="string"||!data.taskId.trim())return;let usage=data.usage;if(!isRecord(usage)||!isRecord(usage.cost))return;let{input:input2,output,cacheRead,cacheWrite,totalTokens,reasoning,cacheWrite1h}=usage,cost=usage.cost;if(!(!isUsageValue(input2)||!isUsageValue(output)||!isUsageValue(cacheRead)||!isUsageValue(cacheWrite)||!isUsageValue(totalTokens)||!isUsageValue(cost.input)||!isUsageValue(cost.output)||!isUsageValue(cost.cacheRead)||!isUsageValue(cost.cacheWrite)||!isUsageValue(cost.total)||reasoning!==void 0&&!isUsageValue(reasoning)||cacheWrite1h!==void 0&&!isUsageValue(cacheWrite1h)))return{version:1,taskId:data.taskId,usage:{input:input2,output,cacheRead,cacheWrite,totalTokens,...reasoning===void 0?{}:{reasoning},...cacheWrite1h===void 0?{}:{cacheWrite1h},cost:{input:cost.input,output:cost.output,cacheRead:cost.cacheRead,cacheWrite:cost.cacheWrite,total:cost.total}}}}function*accountedUsageEntries(entries){let backgroundTasks=new Set;for(let entry of entries)if(entry.type==="message"&&entry.message.role==="assistant")yield{key:`${entry.message.provider}/${entry.message.responseModel??entry.message.model}`,usage:entry.message.usage};else if(entry.type==="usage")yield{key:`${entry.provider}/${entry.model}`,usage:entry.usage};else if(entry.type==="message"&&entry.message.role==="toolResult"&&entry.message.usage)yield{key:"Tools/summaries",usage:entry.message.usage};else if((entry.type==="branch_summary"||entry.type==="compaction")&&entry.usage)yield{key:"Tools/summaries",usage:entry.usage};else{let record=getTaskUsageRecord(entry);if(!record||backgroundTasks.has(record.taskId))continue;backgroundTasks.add(record.taskId),yield{key:"Tools/summaries",usage:record.usage}}}function getAccountedUsages(entries){return Array.from(accountedUsageEntries(entries),({usage})=>usage)}function getUsageCostBreakdown(entries){let totalsByKey=new Map;for(let{key,usage}of accountedUsageEntries(entries)){let totals=totalsByKey.get(key);totals||(totals=createUsageTotals(),totalsByKey.set(key,totals)),addUsageToTotals(totals,usage)}return Array.from(totalsByKey,([key,totals])=>({key,cost:totals.cost,tokens:totals.input+totals.output+totals.cacheRead+totals.cacheWrite})).filter(entry=>entry.cost>0||entry.tokens>0).sort((a,b2)=>b2.cost-a.cost)}function extractFileOperations(messages,entries,prevCompactionIndex){let fileOps=createFileOps();if(prevCompactionIndex>=0){let prevCompaction=entries[prevCompactionIndex];if(!prevCompaction.fromHook&&prevCompaction.details){let details=prevCompaction.details;if(Array.isArray(details.readFiles))for(let f2 of details.readFiles)fileOps.read.add(f2);if(Array.isArray(details.modifiedFiles))for(let f2 of details.modifiedFiles)fileOps.edited.add(f2)}}for(let msg of messages)extractFileOpsFromMessage(msg,fileOps);return fileOps}function getMessagesFromProjectedEntryForCompaction(entry){return entry.sourceEntry.type==="compaction"?[]:entry.messages.filter(message=>message.role!=="system")}var DEFAULT_COMPACTION_SETTINGS={enabled:!0,reserveTokens:16384,keepRecentTokens:2e4};function calculateContextTokens(usage){return usage.totalTokens||usage.input+usage.output+usage.cacheRead+usage.cacheWrite}function getAssistantUsage(msg){if(msg.role==="assistant"&&"usage"in msg){let assistantMsg=msg;if(assistantMsg.stopReason!=="aborted"&&assistantMsg.stopReason!=="error"&&assistantMsg.usage&&calculateContextTokens(assistantMsg.usage)>0)return assistantMsg.usage}}function getLastAssistantUsage(entries){for(let i=entries.length-1;i>=0;i--){let entry=entries[i];if(entry.type==="message"){let usage=getAssistantUsage(entry.message);if(usage)return usage}}}function getLastAssistantUsageInfo(messages){for(let i=messages.length-1;i>=0;i--){let usage=getAssistantUsage(messages[i]);if(usage)return{usage,index:i}}}function estimateContextTokens2(messages){let usageInfo=getLastAssistantUsageInfo(messages);if(!usageInfo){let estimated=0;for(let message of messages)estimated+=estimateTokens2(message);return{tokens:estimated,usageTokens:0,trailingTokens:estimated,lastUsageIndex:null}}let usageTokens=calculateContextTokens(usageInfo.usage),trailingTokens=0;for(let i=usageInfo.index+1;i<messages.length;i++)trailingTokens+=estimateTokens2(messages[i]);return{tokens:usageTokens+trailingTokens,usageTokens,trailingTokens,lastUsageIndex:usageInfo.index}}function estimateProjectedContextTokens(projection,branchEntries){let estimate=estimateContextTokens2(projection.messages);if(estimate.lastUsageIndex!==null){let projectedMessageIndex=0,usageEntryId;for(let entry of projection.entries){let nextMessageIndex=projectedMessageIndex+entry.messages.length;if(estimate.lastUsageIndex<nextMessageIndex){usageEntryId=entry.sourceEntry.id;break}projectedMessageIndex=nextMessageIndex}let usageEntryIndex=usageEntryId?branchEntries.findIndex(entry=>entry.id===usageEntryId):-1,latestInvalidatingEntryIndex=-1;for(let i=branchEntries.length-1;i>=0;i--){let entry=branchEntries[i];if(entry.type==="context_edit"||entry.type==="compaction"){latestInvalidatingEntryIndex=i;break}}if(usageEntryIndex>latestInvalidatingEntryIndex)return estimate}let currentSystem=getCurrentSystemMessage(projection.messages),tokens2=currentSystem?estimateTokens2(currentSystem):0;for(let message of projection.messages)message.role!=="system"&&(tokens2+=estimateTokens2(message));return{tokens:tokens2,usageTokens:0,trailingTokens:tokens2,lastUsageIndex:null}}function shouldCompact(contextTokens,contextWindow,settings2){return settings2.enabled?contextTokens>contextWindow-settings2.reserveTokens:!1}var ESTIMATED_IMAGE_CHARS=4800;function estimateTextAndImageContentChars(content){if(typeof content=="string")return content.length;let chars=0;for(let block of content)block.type==="text"&&block.text?chars+=block.text.length:block.type==="image"&&(chars+=ESTIMATED_IMAGE_CHARS);return chars}function estimateTokens2(message){let chars=0;switch(message.role){case"system":{let system=message;if(chars=estimateTextAndImageContentChars(system.content),system.sections)for(let section of Object.values(system.sections))section&&(chars+=section.length);return system.toolsAdded&&(chars+=JSON.stringify(system.toolsAdded).length),Math.ceil(chars/4)}case"user":return chars=estimateTextAndImageContentChars(message.content),Math.ceil(chars/4);case"assistant":{let assistant=message;for(let block of assistant.content)block.type==="text"?chars+=block.text.length:block.type==="thinking"?chars+=block.thinking.length:block.type==="toolCall"&&(chars+=block.name.length+JSON.stringify(block.arguments).length);return Math.ceil(chars/4)}case"custom":case"toolResult":return chars=estimateTextAndImageContentChars(message.content),Math.ceil(chars/4);case"bashExecution":return chars=message.command.length+message.output.length,Math.ceil(chars/4);case"branchSummary":case"compactionSummary":return chars=message.summary.length,Math.ceil(chars/4)}return 0}function isCutPointMessage(message){switch(message.role){case"user":case"assistant":case"bashExecution":case"custom":case"branchSummary":case"compactionSummary":return!0;case"toolResult":return!1}return!1}function isTurnStartMessage(message){switch(message.role){case"user":case"bashExecution":case"custom":case"branchSummary":case"compactionSummary":return!0;case"assistant":case"toolResult":return!1}return!1}function isTurnStartEntry(entry){return entry.type==="compaction"?!1:sessionEntryToContextMessages(entry).some(isTurnStartMessage)}function findValidCutPoints(entries,startIndex,endIndex){let cutPoints=[];for(let i=startIndex;i<endIndex;i++){let entry=entries[i];entry.type!=="compaction"&&sessionEntryToContextMessages(entry).some(isCutPointMessage)&&cutPoints.push(i)}return cutPoints}function findTurnStartIndex(entries,entryIndex,startIndex){for(let i=entryIndex;i>=startIndex;i--)if(isTurnStartEntry(entries[i]))return i;return-1}function findCutPoint(entries,startIndex,endIndex,keepRecentTokens){let cutPoints=findValidCutPoints(entries,startIndex,endIndex);if(cutPoints.length===0)return{firstKeptEntryIndex:startIndex,turnStartIndex:-1,isSplitTurn:!1};let accumulatedTokens=0,cutIndex=cutPoints[0];for(let i=endIndex-1;i>=startIndex;i--){let entry=entries[i],messageTokens=sessionEntryToContextMessages(entry).reduce((sum,message)=>sum+estimateTokens2(message),0);if(messageTokens!==0&&(accumulatedTokens+=messageTokens,accumulatedTokens>=keepRecentTokens)){cutIndex=cutPoints.find(candidate=>candidate>=i)??cutPoints[cutPoints.length-1];break}}for(;cutIndex>startIndex;){let prevEntry=entries[cutIndex-1];if(prevEntry.type==="compaction"||sessionEntryToContextMessages(prevEntry).length>0)break;cutIndex--}let cutEntry=entries[cutIndex],startsTurn=isTurnStartEntry(cutEntry),turnStartIndex=startsTurn?-1:findTurnStartIndex(entries,cutIndex,startIndex);return{firstKeptEntryIndex:cutIndex,turnStartIndex,isSplitTurn:!startsTurn&&turnStartIndex!==-1}}var SUMMARIZATION_PROMPT=`The messages above are a conversation to summarize. Create a structured context checkpoint summary that another LLM will use to continue the work.
|
|
731
|
+
Do NOT continue the conversation. Do NOT respond to any questions in the conversation. ONLY output the structured summary.`;function createUsageTotals(){return{input:0,output:0,cacheRead:0,cacheWrite:0,cost:0}}function addUsageToTotals(totals,usage){totals.input+=usage.input,totals.output+=usage.output,totals.cacheRead+=usage.cacheRead,totals.cacheWrite+=usage.cacheWrite,totals.cost+=usage.cost.total}function combineUsage(first,second){return{input:first.input+second.input,output:first.output+second.output,cacheRead:first.cacheRead+second.cacheRead,cacheWrite:first.cacheWrite+second.cacheWrite,...first.cacheWrite1h!==void 0||second.cacheWrite1h!==void 0?{cacheWrite1h:(first.cacheWrite1h??0)+(second.cacheWrite1h??0)}:{},...first.reasoning!==void 0||second.reasoning!==void 0?{reasoning:(first.reasoning??0)+(second.reasoning??0)}:{},totalTokens:first.totalTokens+second.totalTokens,cost:{input:first.cost.input+second.cost.input,output:first.cost.output+second.cost.output,cacheRead:first.cost.cacheRead+second.cost.cacheRead,cacheWrite:first.cost.cacheWrite+second.cost.cacheWrite,total:first.cost.total+second.cost.total}}}var TASK_USAGE_TYPE="task-usage";function isRecord(value){return typeof value=="object"&&value!==null&&!Array.isArray(value)}function isUsageValue(value){return typeof value=="number"&&Number.isFinite(value)&&value>=0}function getTaskUsageRecord(entry){if(entry.type!=="custom"||entry.customType!==TASK_USAGE_TYPE)return;let data=entry.data;if(!isRecord(data)||data.version!==1||typeof data.taskId!="string"||!data.taskId.trim())return;let usage=data.usage;if(!isRecord(usage)||!isRecord(usage.cost))return;let{input:input2,output,cacheRead,cacheWrite,totalTokens,reasoning,cacheWrite1h}=usage,cost=usage.cost;if(!(!isUsageValue(input2)||!isUsageValue(output)||!isUsageValue(cacheRead)||!isUsageValue(cacheWrite)||!isUsageValue(totalTokens)||!isUsageValue(cost.input)||!isUsageValue(cost.output)||!isUsageValue(cost.cacheRead)||!isUsageValue(cost.cacheWrite)||!isUsageValue(cost.total)||reasoning!==void 0&&!isUsageValue(reasoning)||cacheWrite1h!==void 0&&!isUsageValue(cacheWrite1h)))return{version:1,taskId:data.taskId,usage:{input:input2,output,cacheRead,cacheWrite,totalTokens,...reasoning===void 0?{}:{reasoning},...cacheWrite1h===void 0?{}:{cacheWrite1h},cost:{input:cost.input,output:cost.output,cacheRead:cost.cacheRead,cacheWrite:cost.cacheWrite,total:cost.total}}}}function*accountedUsageEntries(entries){let backgroundTasks=new Set;for(let entry of entries)if(entry.type==="message"&&entry.message.role==="assistant")yield{key:`${entry.message.provider}/${entry.message.responseModel??entry.message.model}`,usage:entry.message.usage};else if(entry.type==="usage")yield{key:`${entry.provider}/${entry.model}`,usage:entry.usage};else if(entry.type==="message"&&entry.message.role==="toolResult"&&entry.message.usage)yield{key:"Tools/summaries",usage:entry.message.usage};else if((entry.type==="branch_summary"||entry.type==="compaction")&&entry.usage)yield{key:"Tools/summaries",usage:entry.usage};else{let record=getTaskUsageRecord(entry);if(!record||backgroundTasks.has(record.taskId))continue;backgroundTasks.add(record.taskId),yield{key:"Tools/summaries",usage:record.usage}}}function getAccountedUsages(entries){return Array.from(accountedUsageEntries(entries),({usage})=>usage)}function getUsageCostBreakdown(entries){let totalsByKey=new Map;for(let{key,usage}of accountedUsageEntries(entries)){let totals=totalsByKey.get(key);totals||(totals=createUsageTotals(),totalsByKey.set(key,totals)),addUsageToTotals(totals,usage)}return Array.from(totalsByKey,([key,totals])=>({key,cost:totals.cost,tokens:totals.input+totals.output+totals.cacheRead+totals.cacheWrite})).filter(entry=>entry.cost>0||entry.tokens>0).sort((a,b2)=>b2.cost-a.cost)}function extractFileOperations(messages,entries,prevCompactionIndex){let fileOps=createFileOps();if(prevCompactionIndex>=0){let prevCompaction=entries[prevCompactionIndex];if(prevCompaction.details){let details=prevCompaction.details;if(Array.isArray(details.readFiles))for(let f2 of details.readFiles)typeof f2=="string"&&fileOps.read.add(f2);if(Array.isArray(details.modifiedFiles))for(let f2 of details.modifiedFiles)typeof f2=="string"&&fileOps.edited.add(f2)}}for(let msg of messages)extractFileOpsFromMessage(msg,fileOps);return fileOps}function getMessagesFromProjectedEntryForCompaction(entry){return entry.sourceEntry.type==="compaction"?[]:entry.messages.filter(message=>message.role!=="system")}var DEFAULT_COMPACTION_SETTINGS={enabled:!0,reserveTokens:16384,keepRecentTokens:2e4};function calculateContextTokens(usage){return usage.totalTokens||usage.input+usage.output+usage.cacheRead+usage.cacheWrite}function getAssistantUsage(msg){if(msg.role==="assistant"&&"usage"in msg){let assistantMsg=msg;if(assistantMsg.stopReason!=="aborted"&&assistantMsg.stopReason!=="error"&&assistantMsg.usage&&calculateContextTokens(assistantMsg.usage)>0)return assistantMsg.usage}}function getLastAssistantUsage(entries){for(let i=entries.length-1;i>=0;i--){let entry=entries[i];if(entry.type==="message"){let usage=getAssistantUsage(entry.message);if(usage)return usage}}}function getLastAssistantUsageInfo(messages){for(let i=messages.length-1;i>=0;i--){let usage=getAssistantUsage(messages[i]);if(usage)return{usage,index:i}}}function estimateContextTokens2(messages){let usageInfo=getLastAssistantUsageInfo(messages);if(!usageInfo){let estimated=0;for(let message of messages)estimated+=estimateTokens2(message);return{tokens:estimated,usageTokens:0,trailingTokens:estimated,lastUsageIndex:null}}let usageTokens=calculateContextTokens(usageInfo.usage),trailingTokens=0;for(let i=usageInfo.index+1;i<messages.length;i++)trailingTokens+=estimateTokens2(messages[i]);return{tokens:usageTokens+trailingTokens,usageTokens,trailingTokens,lastUsageIndex:usageInfo.index}}function estimateProjectedContextTokens(projection,branchEntries){let estimate=estimateContextTokens2(projection.messages);if(estimate.lastUsageIndex!==null){let projectedMessageIndex=0,usageEntryId;for(let entry of projection.entries){let nextMessageIndex=projectedMessageIndex+entry.messages.length;if(estimate.lastUsageIndex<nextMessageIndex){usageEntryId=entry.sourceEntry.id;break}projectedMessageIndex=nextMessageIndex}let usageEntryIndex=usageEntryId?branchEntries.findIndex(entry=>entry.id===usageEntryId):-1,latestInvalidatingEntryIndex=-1;for(let i=branchEntries.length-1;i>=0;i--){let entry=branchEntries[i];if(entry.type==="context_edit"||entry.type==="compaction"){latestInvalidatingEntryIndex=i;break}}if(usageEntryIndex>latestInvalidatingEntryIndex)return estimate}let currentSystem=getCurrentSystemMessage(projection.messages),tokens2=currentSystem?estimateTokens2(currentSystem):0;for(let message of projection.messages)message.role!=="system"&&(tokens2+=estimateTokens2(message));return{tokens:tokens2,usageTokens:0,trailingTokens:tokens2,lastUsageIndex:null}}function shouldCompact(contextTokens,contextWindow,settings2){return settings2.enabled?contextTokens>contextWindow-settings2.reserveTokens:!1}var ESTIMATED_IMAGE_CHARS=4800;function estimateTextAndImageContentChars(content){if(typeof content=="string")return content.length;let chars=0;for(let block of content)block.type==="text"&&block.text?chars+=block.text.length:block.type==="image"&&(chars+=ESTIMATED_IMAGE_CHARS);return chars}function estimateTokens2(message){let chars=0;switch(message.role){case"system":{let system=message;if(chars=estimateTextAndImageContentChars(system.content),system.sections)for(let section of Object.values(system.sections))section&&(chars+=section.length);return system.toolsAdded&&(chars+=JSON.stringify(system.toolsAdded).length),Math.ceil(chars/4)}case"user":return chars=estimateTextAndImageContentChars(message.content),Math.ceil(chars/4);case"assistant":{let assistant=message;for(let block of assistant.content)block.type==="text"?chars+=block.text.length:block.type==="thinking"?chars+=block.thinking.length:block.type==="toolCall"&&(chars+=block.name.length+JSON.stringify(block.arguments).length);return Math.ceil(chars/4)}case"custom":case"toolResult":return chars=estimateTextAndImageContentChars(message.content),Math.ceil(chars/4);case"bashExecution":return chars=message.command.length+message.output.length,Math.ceil(chars/4);case"branchSummary":case"compactionSummary":return chars=message.summary.length,Math.ceil(chars/4)}return 0}function isCutPointMessage(message){switch(message.role){case"user":case"assistant":case"bashExecution":case"custom":case"branchSummary":case"compactionSummary":return!0;case"toolResult":return!1}return!1}function isTurnStartMessage(message){switch(message.role){case"user":case"bashExecution":case"custom":case"branchSummary":case"compactionSummary":return!0;case"assistant":case"toolResult":return!1}return!1}function isTurnStartEntry(entry){return entry.type==="compaction"?!1:sessionEntryToContextMessages(entry).some(isTurnStartMessage)}function findValidCutPoints(entries,startIndex,endIndex){let cutPoints=[];for(let i=startIndex;i<endIndex;i++){let entry=entries[i];entry.type!=="compaction"&&sessionEntryToContextMessages(entry).some(isCutPointMessage)&&cutPoints.push(i)}return cutPoints}function findTurnStartIndex(entries,entryIndex,startIndex){for(let i=entryIndex;i>=startIndex;i--)if(isTurnStartEntry(entries[i]))return i;return-1}function findCutPoint(entries,startIndex,endIndex,keepRecentTokens){let cutPoints=findValidCutPoints(entries,startIndex,endIndex);if(cutPoints.length===0)return{firstKeptEntryIndex:startIndex,turnStartIndex:-1,isSplitTurn:!1};let accumulatedTokens=0,cutIndex=cutPoints[0];for(let i=endIndex-1;i>=startIndex;i--){let entry=entries[i],messageTokens=sessionEntryToContextMessages(entry).reduce((sum,message)=>sum+estimateTokens2(message),0);if(messageTokens!==0&&(accumulatedTokens+=messageTokens,accumulatedTokens>=keepRecentTokens)){cutIndex=cutPoints.find(candidate=>candidate>=i)??cutPoints[cutPoints.length-1];break}}for(;cutIndex>startIndex;){let prevEntry=entries[cutIndex-1];if(prevEntry.type==="compaction"||sessionEntryToContextMessages(prevEntry).length>0)break;cutIndex--}let cutEntry=entries[cutIndex],startsTurn=isTurnStartEntry(cutEntry),turnStartIndex=startsTurn?-1:findTurnStartIndex(entries,cutIndex,startIndex);return{firstKeptEntryIndex:cutIndex,turnStartIndex,isSplitTurn:!startsTurn&&turnStartIndex!==-1}}var SUMMARIZATION_PROMPT=`The messages above are a conversation to summarize. Create a structured context checkpoint summary that another LLM will use to continue the work.
|
|
732
732
|
|
|
733
733
|
Use this EXACT format:
|
|
734
734
|
|
|
@@ -878,7 +878,7 @@ Hint: ${hints.join(`
|
|
|
878
878
|
Hint: `)}`:head;if(markerIndex!==-1){let bounded=truncateHead(received,{maxBytes:RECEIVED_ARGUMENTS_MAX_BYTES,maxLines:RECEIVED_ARGUMENTS_MAX_LINES});enriched+=`${RECEIVED_ARGUMENTS_MARKER}${bounded.content}`,bounded.truncated&&(enriched+=`
|
|
879
879
|
\u2026 (arguments truncated)`)}return new Error(enriched)}function wrapPrepareArguments(definition){let tool={name:definition.name,description:definition.description,parameters:definition.parameters};return raw=>{let args=definition.prepareArguments?definition.prepareArguments(raw):raw;try{validateToolArguments(tool,{type:"toolCall",id:"",name:definition.name,arguments:args})}catch(error){throw enrichValidationError(error,definition.parameters,args)}return args}}function wrapToolDefinition(definition,ctxFactory){return{name:definition.name,label:definition.label,description:definition.description,parameters:definition.parameters,outputSchema:definition.outputSchema,constrainedSampling:definition.constrainedSampling,prepareArguments:wrapPrepareArguments(definition),executionMode:definition.executionMode,execute:(toolCallId,params,signal,onUpdate,ctx)=>definition.execute(toolCallId,params,signal,onUpdate,ctx??ctxFactory?.(toolCallId,signal))}}function createToolDefinitionFromAgentTool(tool){return{name:tool.name,label:tool.label,description:tool.description,parameters:tool.parameters,outputSchema:tool.outputSchema,constrainedSampling:tool.constrainedSampling,prepareArguments:tool.prepareArguments,executionMode:tool.executionMode,execute:async(toolCallId,params,signal,onUpdate)=>tool.execute(toolCallId,params,signal,onUpdate)}}function wrapRegisteredTool(registeredTool,runner){return wrapToolDefinition(registeredTool.definition,(toolCallId,signal)=>runner.createToolContext(toolCallId,signal))}function wrapRegisteredTools(registeredTools,runner){return registeredTools.map(tool=>wrapRegisteredTool(tool,runner))}import*as fs5 from"node:fs";import{createRequire as createRequire5}from"node:module";import*as path7 from"node:path";import{fileURLToPath as fileURLToPath5}from"node:url";import{spawn as spawn3}from"node:child_process";async function execCommand(command,args,cwd,options){return new Promise(resolve20=>{let proc=spawn3(command,args,{cwd,shell:!1,stdio:["ignore","pipe","pipe"]}),stdout="",stderr="",killed=!1,timeoutId,killProcess=()=>{killed||(killed=!0,proc.kill("SIGTERM"),setTimeout(()=>{proc.killed||proc.kill("SIGKILL")},5e3))};options?.signal&&(options.signal.aborted?killProcess():options.signal.addEventListener("abort",killProcess,{once:!0})),options?.timeout&&options.timeout>0&&(timeoutId=setTimeout(()=>{killProcess()},options.timeout)),proc.stdout?.on("data",data=>{stdout+=data.toString()}),proc.stderr?.on("data",data=>{stderr+=data.toString()}),waitForChildProcess(proc).then(code=>{timeoutId&&clearTimeout(timeoutId),options?.signal&&options.signal.removeEventListener("abort",killProcess),resolve20({stdout,stderr,code:code??0,killed})}).catch(_err=>{timeoutId&&clearTimeout(timeoutId),options?.signal&&options.signal.removeEventListener("abort",killProcess),resolve20({stdout,stderr,code:1,killed})})})}function toolPatternRegExp(pattern){let source=pattern.split("*").map(part=>part.replace(/[.+?^${}()|[\]\\]/g,"\\$&")).join(".*");return new RegExp(`^${source}$`)}function createToolNameMatcher(entries){let names2=new Set(entries.filter(entry=>!entry.includes("*"))),patterns=entries.filter(entry=>entry.includes("*")).map(toolPatternRegExp);return name=>names2.has(name)||patterns.some(pattern=>pattern.test(name))}var LIST_MCP_RESOURCES_TOOL="list_mcp_resources",LIST_MCP_RESOURCE_TEMPLATES_TOOL="list_mcp_resource_templates",READ_MCP_RESOURCE_TOOL="read_mcp_resource",MCP_RESOURCE_TOOLS=new Set([LIST_MCP_RESOURCES_TOOL,LIST_MCP_RESOURCE_TEMPLATES_TOOL,READ_MCP_RESOURCE_TOOL]);function isMcpToolName(name){return name.startsWith("mcp__")||MCP_RESOURCE_TOOLS.has(name)}var MCP_EXPOSURES=["codemode","deferred","direct","hidden"],MCP_EXPOSURE_ALIASES={"codemode-deferred":"codemode"},LOOPBACK_HOSTS=["localhost","127.0.0.1","[::1]"];function isLoopbackRedirectUri(value){if(!URL.canParse(value))return!1;let url=new URL(value);return url.protocol==="http:"&&LOOPBACK_HOSTS.includes(url.hostname)&&url.search===""&&url.hash===""}var SERVER_NAME=/^[A-Za-z0-9_-]+$/;function mcpNamespace(server){return`mcp__${server.replace(/-/g,"_")}`}function isRecord3(value){return typeof value=="object"&&value!==null&&!Array.isArray(value)}function isStringRecord(value){return isRecord3(value)&&Object.values(value).every(entry=>typeof entry=="string")}function validateOAuth(value){if(value===void 0)return;if(!isRecord3(value))return"oauth must be an object";if(value.clientId!==void 0&&typeof value.clientId!="string")return"oauth.clientId must be a string";if(value.clientSecret!==void 0&&typeof value.clientSecret!="string")return"oauth.clientSecret must be a string";let port=value.callbackPort;if(port!==void 0&&(typeof port!="number"||!Number.isInteger(port)||port<1||port>65535))return"oauth.callbackPort must be a port number";if(value.callbackUrl!==void 0){if(typeof value.callbackUrl!="string"||!isLoopbackRedirectUri(value.callbackUrl))return"oauth.callbackUrl must be an http URI on localhost, 127.0.0.1, or [::1] without query or fragment";let urlPort=new URL(value.callbackUrl).port;if(urlPort&&port!==void 0&&Number(urlPort)!==port)return"oauth.callbackUrl and oauth.callbackPort name different ports"}if(value.scope!==void 0&&typeof value.scope!="string")return"oauth.scope must be a string";if(value.clientName!==void 0&&(typeof value.clientName!="string"||!value.clientName.trim()))return"oauth.clientName must be a non-empty string";if(value.clientRegistration!==void 0&&value.clientRegistration!=="dcr"){if(value.clientRegistration!=="cimd")return'oauth.clientRegistration must be "dcr" or "cimd"';if(value.clientId!==void 0||value.clientName!==void 0)return'oauth.clientRegistration "cimd" cannot be combined with oauth.clientId or oauth.clientName';let callback=typeof value.callbackUrl=="string"?new URL(value.callbackUrl):void 0;if(callback&&(callback.hostname==="[::1]"||callback.pathname!=="/callback"))return'oauth.clientRegistration "cimd" requires oauth.callbackUrl on localhost or 127.0.0.1 with path /callback'}let metadataUrl=value.authServerMetadataUrl;if(metadataUrl!==void 0){let url=typeof metadataUrl=="string"&&URL.canParse(metadataUrl)?new URL(metadataUrl):void 0;if(!url||!(url.protocol==="https:"||url.protocol==="http:"&&LOOPBACK_HOSTS.includes(url.hostname)))return"oauth.authServerMetadataUrl must be an https URL, or http on localhost, 127.0.0.1, or [::1]"}}function isExposure(value){return typeof value=="string"&&MCP_EXPOSURES.includes(value)}function resolveExposureAlias(value){return typeof value=="string"?MCP_EXPOSURE_ALIASES[value]??value:value}function resolveExposureAliases(value){let{exposure,toolExposure}=value,resolved={...value};return exposure!==void 0&&(resolved.exposure=resolveExposureAlias(exposure)),isRecord3(toolExposure)&&(resolved.toolExposure=Object.fromEntries(Object.entries(toolExposure).map(([tool,entry])=>[tool,resolveExposureAlias(entry)]))),resolved}function getMcpToolExposure(config,toolName){let overrides=config.toolExposure??{},exact=overrides[toolName];if(exact!==void 0)return exact;for(let[pattern,exposure]of Object.entries(overrides))if(pattern.includes("*")&&toolPatternRegExp(pattern).test(toolName))return exposure;return config.exposure??"codemode"}function validateMcpServerConfig(name,raw){if(!SERVER_NAME.test(name))return`invalid server name "${name}" (use letters, digits, "_" and "-")`;if(!isRecord3(raw))return`server "${name}" must be an object`;let value=resolveExposureAliases(raw),{type,exposure,enabled,timeout,toolExposure,description}=value,exposures=MCP_EXPOSURES.map(value2=>`"${value2}"`).join(", ");if(exposure!==void 0&&!isExposure(exposure))return`server "${name}": exposure must be one of ${exposures}`;if(toolExposure!==void 0){if(!isRecord3(toolExposure))return`server "${name}": toolExposure must map tool names to exposures`;for(let[tool,value2]of Object.entries(toolExposure))if(!isExposure(value2))return`server "${name}": toolExposure "${tool}" must be one of ${exposures}`}if(enabled!==void 0&&typeof enabled!="boolean")return`server "${name}": enabled must be a boolean`;if(description!==void 0&&typeof description!="string")return`server "${name}": description must be a string`;if(timeout!==void 0&&(typeof timeout!="number"||!(timeout>0)))return`server "${name}": timeout must be a positive number of seconds`;if(type==="sse")return`server "${name}": legacy SSE transport is not supported; use the streamable HTTP URL`;if(typeof value.url=="string"&&(type===void 0||type==="http"||type==="streamable-http")){if(!URL.canParse(value.url)||!/^https?:$/.test(new URL(value.url).protocol))return`server "${name}": url must be an http or https URL`;if(value.headers!==void 0&&!isStringRecord(value.headers))return`server "${name}": headers must map names to strings`;let oauthError=validateOAuth(value.oauth);if(oauthError)return`server "${name}": ${oauthError}`;if(value.auth!==void 0){if(!isRecord3(value.auth)||typeof value.auth.provider!="string"||!value.auth.provider)return`server "${name}": auth.provider must be a provider name`;let url=new URL(value.url);if(url.protocol!=="https:"&&!LOOPBACK_HOSTS.includes(url.hostname))return`server "${name}": auth requires an https URL, or http on localhost, 127.0.0.1, or [::1]`}return value}return typeof value.command=="string"&&(type===void 0||type==="stdio")?value.args!==void 0&&!(Array.isArray(value.args)&&value.args.every(arg=>typeof arg=="string"))?`server "${name}": args must be an array of strings`:value.env!==void 0&&!isStringRecord(value.env)?`server "${name}": env must map names to strings`:value.cwd!==void 0&&typeof value.cwd!="string"?`server "${name}": cwd must be a string`:value:`server "${name}" needs either "command" (stdio) or "url" (streamable HTTP)`}var McpServerRegistry=class{constructor(){this.servers=new Map}register(server){this.servers.set(server.name,server),this.changeListener?.()}unregister(name,extensionPath){this.servers.get(name)?.extensionPath===extensionPath&&(this.servers.delete(name),this.changeListener?.())}get(name){return this.servers.get(name)}list(){return[...this.servers.values()].map(server=>({...server,config:structuredClone(server.config)}))}setChangeListener(listener){this.changeListener=listener}};var ENABLED=process.env.PI_TIMING==="1",timingNamespaces=new Map;function resetTimings(namespace="main"){ENABLED&&timingNamespaces.set(namespace,{timings:[],lastTime:Date.now()})}function time(label,namespace="main"){if(!ENABLED)return;let now=Date.now();timingNamespaces.has(namespace)||resetTimings(namespace);let timingNamespace=timingNamespaces.get(namespace);timingNamespace.timings.push({label,ms:now-timingNamespace.lastTime}),timingNamespace.lastTime=now}function printTimingGroup(title,timings){let printableTimings=timings.filter(timing=>timing.ms>=0);if(printableTimings.length!==0){console.error(`
|
|
880
880
|
--- ${title} ---`);for(let t of printableTimings)console.error(` ${t.label}: ${t.ms}ms`);console.error(` TOTAL: ${printableTimings.reduce((a,b2)=>a+b2.ms,0)}ms`),console.error(`${"-".repeat(title.length+8)}
|
|
881
|
-
`)}}function printTimings(){if(ENABLED)for(let[namespace,timingNamespace]of timingNamespaces)printTimingGroup(`Startup Timings: ${namespace}`,timingNamespace.timings)}var require3=createRequire5(import.meta.url),isNodeSeaBinary="sea"in process.features&&process.features.sea===!0||process.getBuiltinModule("node:sea")?.isSea()===!0,isTypeScriptSourceRuntime=!isBunBinary&&path7.extname(fileURLToPath5(import.meta.url))===".ts",usesEmbeddedModules=isBunBinary||isNodeSeaBinary||isBundledNode,createJitiPromise;function getCreateJiti(){return createJitiPromise??=(usesEmbeddedModules?import("./jiti-static-loader-CLT3YR3B.js"):import("./jiti-loader-BFSSLU7G.js")).then(module=>module.createJiti),createJitiPromise}var virtualModulesPromise;function getVirtualModules(){return virtualModulesPromise??=import("./virtual-modules-3CTTTQQN.js").then(module=>module.VIRTUAL_MODULES),virtualModulesPromise}var _aliases=null;function getAliases(){if(_aliases)return _aliases;let __dirname2=path7.dirname(fileURLToPath5(import.meta.url)),packageIndex=path7.resolve(__dirname2,"../..","index.js"),typeboxEntry=require3.resolve("typebox"),typeboxCompileEntry=require3.resolve("typebox/compile"),typeboxValueEntry=require3.resolve("typebox/value"),resolveImport=specifier=>fileURLToPath5(import.meta.resolve(specifier)),piCodingAgentEntry=packageIndex,piAgentCoreEntry=resolveImport("@earendil-works/pi-agent-core"),piTuiEntry=resolveImport("@earendil-works/pi-tui"),piAiCompatEntry=resolveImport("@earendil-works/pi-ai/compat"),piAiModelsEntry=resolveImport("@earendil-works/pi-ai/models"),piAiOauthEntry=resolveImport("@earendil-works/pi-ai/oauth"),piAiProvidersEntry=resolveImport("@earendil-works/pi-ai/providers/all");return _aliases={"@earendil-works/pi-coding-agent":piCodingAgentEntry,[DISTRIBUTION_PACKAGE_NAME]:piCodingAgentEntry,"@earendil-works/pi-agent-core":piAgentCoreEntry,"@earendil-works/pi-tui":piTuiEntry,"@earendil-works/pi-ai/providers/all":piAiProvidersEntry,"@earendil-works/pi-ai/compat":piAiCompatEntry,"@earendil-works/pi-ai/models":piAiModelsEntry,"@earendil-works/pi-ai/oauth":piAiOauthEntry,"@earendil-works/pi-ai":piAiCompatEntry,"@mariozechner/pi-coding-agent":piCodingAgentEntry,"@mariozechner/pi-agent-core":piAgentCoreEntry,"@mariozechner/pi-tui":piTuiEntry,"@mariozechner/pi-ai/providers/all":piAiProvidersEntry,"@mariozechner/pi-ai/compat":piAiCompatEntry,"@mariozechner/pi-ai/models":piAiModelsEntry,"@mariozechner/pi-ai/oauth":piAiOauthEntry,"@mariozechner/pi-ai":piAiCompatEntry,typebox:typeboxEntry,"typebox/compile":typeboxCompileEntry,"typebox/value":typeboxValueEntry,"@sinclair/typebox":typeboxEntry,"@sinclair/typebox/compile":typeboxCompileEntry,"@sinclair/typebox/value":typeboxValueEntry},_aliases}var extensionCacheCwd,extensionCacheGeneration=0,extensionCache=new Map;function clearExtensionCache(){extensionCache.clear(),extensionCacheCwd=void 0,extensionCacheGeneration++}function useExtensionCacheCwd(cwd){let resolvedCwd=resolvePath(cwd);return extensionCacheCwd!==void 0&&extensionCacheCwd!==resolvedCwd&&clearExtensionCache(),extensionCacheCwd=resolvedCwd,{cwd:resolvedCwd,generation:extensionCacheGeneration}}function createExtensionRuntime(){let notInitialized=()=>{throw new Error("Extension runtime not initialized. Action methods cannot be called during extension loading.")},state2={},eventBusUnsubscribers=new Set,assertActive=()=>{if(state2.staleMessage)throw new Error(state2.staleMessage)},runtime={sendMessage:notInitialized,sendUserMessage:notInitialized,appendEntry:notInitialized,setSessionName:notInitialized,getSessionName:notInitialized,setLabel:notInitialized,getActiveTools:notInitialized,getAllTools:notInitialized,getSettings:notInitialized,setActiveTools:notInitialized,refreshTools:()=>{},getCommands:notInitialized,setModel:()=>Promise.reject(new Error("Extension runtime not initialized")),getThinkingLevel:notInitialized,setThinkingLevel:notInitialized,flagValues:new Map,pendingProviderRegistrations:[],pendingNativeProviderRegistrations:[],mcpServers:new McpServerRegistry,pendingVirtualModelRegistrations:[],createContext:notInitialized,assertActive,invalidate:message=>{if(!state2.staleMessage){state2.staleMessage=message??"This extension ctx is stale after session replacement or reload. Do not use a captured pi or command ctx after ctx.newSession(), ctx.fork(), ctx.switchSession(), or ctx.reload(). For newSession, fork, and switchSession, move post-replacement work into withSession and use the ctx passed to withSession. For reload, do not use the old ctx after await ctx.reload().";for(let unsubscribe of eventBusUnsubscribers)unsubscribe();eventBusUnsubscribers.clear()}},trackEventBusSubscription:unsubscribe=>{let active=!0,trackedUnsubscribe=()=>{active&&(active=!1,eventBusUnsubscribers.delete(trackedUnsubscribe),unsubscribe())};return eventBusUnsubscribers.add(trackedUnsubscribe),trackedUnsubscribe},registerProvider:(name,config,extensionPath="<unknown>")=>{runtime.pendingProviderRegistrations.push({name,config,extensionPath})},registerNativeProvider:(provider,extensionPath="<unknown>")=>{runtime.pendingNativeProviderRegistrations.push({provider,extensionPath})},unregisterProvider:name=>{runtime.pendingProviderRegistrations=runtime.pendingProviderRegistrations.filter(r=>r.name!==name),runtime.pendingNativeProviderRegistrations=runtime.pendingNativeProviderRegistrations.filter(r=>r.provider.id!==name)},registerVirtualModel:(definition,extensionPath="<unknown>")=>{runtime.pendingVirtualModelRegistrations.push({definition,extensionPath})},unregisterVirtualModel:(provider,id)=>{runtime.pendingVirtualModelRegistrations=runtime.pendingVirtualModelRegistrations.filter(({definition})=>definition.provider!==provider||definition.id!==id)}};return runtime}function createExtensionAPI(extension,runtime,cwd,eventBus){let pendingFlagValues=new Map,pendingRuntimeChanges=[],loadingUnsubscribers=[],state2="loading",assertActive=()=>{if(state2==="failed")throw new Error(`Extension "${extension.path}" failed to load and its API is no longer active.`);runtime.assertActive()},applyRuntimeChange=change=>{state2==="loading"?pendingRuntimeChanges.push(change):change()},clearPending=()=>{pendingFlagValues.clear(),pendingRuntimeChanges.length=0,loadingUnsubscribers.length=0};return{api:{on(event,handler){assertActive();let registeredHandler=(...args)=>handler(...args),list2=extension.handlers.get(event)??[];return list2.push(registeredHandler),extension.handlers.set(event,list2),()=>{let handlers=extension.handlers.get(event);if(!handlers)return;let handlerIndex=handlers.indexOf(registeredHandler);handlerIndex!==-1&&(handlers.splice(handlerIndex,1),handlers.length===0&&extension.handlers.delete(event))}},registerTool(tool){if(assertActive(),typeof tool.parameters!="object"||tool.parameters===null||Array.isArray(tool.parameters))throw new Error(`Tool "${tool.name}" registered by extension "${extension.path}" must define an object parameter schema.`);extension.tools.set(tool.name,{definition:tool,sourceInfo:extension.sourceInfo}),runtime.refreshTools()},registerCommand(name,options){if(assertActive(),typeof name!="string"||name.length===0)throw new Error(`Command registered by extension "${extension.path}" must have a non-empty string name. Use pi.registerCommand("name", { description, handler }).`);if(typeof options?.handler!="function")throw new Error(`Command "/${name}" registered by extension "${extension.path}" must define handler().`);extension.commands.set(name,{name,sourceInfo:extension.sourceInfo,...options})},registerShortcut(shortcut,options){assertActive(),extension.shortcuts.set(shortcut,{shortcut,extensionPath:extension.path,...options})},registerFlag(name,options){if(assertActive(),options.default!==void 0&&typeof options.default!==options.type)throw new Error(`Invalid default for flag "${name}": expected ${options.type}, got ${typeof options.default}`);extension.flags.set(name,{name,extensionPath:extension.path,...options}),options.default!==void 0&&!runtime.flagValues.has(name)&&(state2==="loading"?pendingFlagValues.has(name)||pendingFlagValues.set(name,options.default):runtime.flagValues.set(name,options.default))},registerMessageRenderer(customType,renderer){assertActive(),extension.messageRenderers.set(customType,renderer)},registerMarkdownTransformer(transformer){assertActive(),extension.markdownTransformer=transformer},registerEntryRenderer(customType,renderer){assertActive(),extension.entryRenderers??=new Map,extension.entryRenderers.set(customType,renderer)},registerToolRenderer(resolver){assertActive(),extension.toolRenderers??=[],extension.toolRenderers.push(resolver)},getFlag(name){if(assertActive(),!!extension.flags.has(name))return runtime.flagValues.has(name)?runtime.flagValues.get(name):pendingFlagValues.get(name)},sendMessage(message,options){assertActive(),runtime.sendMessage(message,options)},sendUserMessage(content,options){assertActive(),runtime.sendUserMessage(content,options)},appendEntry(customType,data){assertActive(),runtime.appendEntry(customType,data)},setSessionName(name){assertActive(),runtime.setSessionName(name)},getSessionName(){return assertActive(),runtime.getSessionName()},setLabel(entryId,label){assertActive(),runtime.setLabel(entryId,label)},exec(command,args,options){return assertActive(),execCommand(command,args,options?.cwd??cwd,options)},getActiveTools(){return assertActive(),runtime.getActiveTools()},getAllTools(){return assertActive(),runtime.getAllTools()},getSettings(){return assertActive(),runtime.getSettings()},setActiveTools(toolNames){assertActive(),runtime.setActiveTools(toolNames)},getCommands(){return assertActive(),runtime.getCommands()},setModel(model){return assertActive(),runtime.setModel(model)},getThinkingLevel(){return assertActive(),runtime.getThinkingLevel()},setThinkingLevel(level){assertActive(),runtime.setThinkingLevel(level)},registerProvider(providerOrName,config){if(assertActive(),typeof providerOrName=="string"){if(!config)throw new Error("Provider config is required when registering by name");applyRuntimeChange(()=>runtime.registerProvider(providerOrName,config,extension.path));return}applyRuntimeChange(()=>runtime.registerNativeProvider(providerOrName,extension.path))},unregisterProvider(name){assertActive(),applyRuntimeChange(()=>runtime.unregisterProvider(name,extension.path))},registerMcpServer(name,config){assertActive();let validated=validateMcpServerConfig(name,config);if(typeof validated=="string")throw new Error(`Invalid MCP server registered by extension "${extension.path}": ${validated}`);let owner=runtime.mcpServers.get(name)?.extensionPath;if(owner!==void 0&&owner!==extension.path)throw new Error(`MCP server "${name}" is already registered by extension "${owner}"`);let clash=runtime.mcpServers.list().find(server2=>server2.name!==name&&mcpNamespace(server2.name)===mcpNamespace(name));if(clash)throw new Error(`MCP server "${name}" conflicts with registered server "${clash.name}"`);let server={name,config:structuredClone(validated),extensionPath:extension.path};applyRuntimeChange(()=>runtime.mcpServers.register(server))},unregisterMcpServer(name){assertActive(),applyRuntimeChange(()=>runtime.mcpServers.unregister(name,extension.path))},getMcpServers(){return assertActive(),runtime.mcpServers.list()},registerVirtualModel(model){assertActive();let definition={...model,route:request=>model.route(request,runtime.createContext())};applyRuntimeChange(()=>runtime.registerVirtualModel(definition,extension.path))},unregisterVirtualModel(provider,id){assertActive(),applyRuntimeChange(()=>runtime.unregisterVirtualModel(provider,id))},events:{emit(channel,data){assertActive(),eventBus.emit(channel,data)},on(channel,handler){assertActive();let unsubscribe=runtime.trackEventBusSubscription(eventBus.on(channel,handler));return state2==="loading"&&loadingUnsubscribers.push(unsubscribe),unsubscribe}}},commit:()=>{if(state2==="loading"){runtime.assertActive();for(let[name,value]of pendingFlagValues)runtime.flagValues.has(name)||runtime.flagValues.set(name,value);for(let apply of pendingRuntimeChanges)apply();state2="active",clearPending()}},discard:()=>{if(state2==="loading"){state2="failed";for(let unsubscribe of loadingUnsubscribers)unsubscribe();clearPending()}}}}function isCurrentCacheToken(cacheToken){return cacheToken!==void 0&&extensionCacheCwd===cacheToken.cwd&&extensionCacheGeneration===cacheToken.generation}async function loadExtensionModule(extensionPath,cacheToken){if(isCurrentCacheToken(cacheToken)){let cachedFactory=extensionCache.get(extensionPath);if(cachedFactory)return cachedFactory}let createJitiImpl=await getCreateJiti(),resolutionOptions=usesEmbeddedModules?{virtualModules:await getVirtualModules(),tryNative:!1}:isTypeScriptSourceRuntime?{virtualModules:await getVirtualModules(),tsconfigPaths:!0}:{alias:getAliases()},factory=await createJitiImpl(import.meta.url,{moduleCache:!1,...resolutionOptions}).import(extensionPath,{default:!0});if(typeof factory=="function")return isCurrentCacheToken(cacheToken)&&extensionCache.set(extensionPath,factory),factory}function createExtension(extensionPath,resolvedPath){let source=getSyntheticPathSource(extensionPath)??"local",baseDir=isSyntheticPath(extensionPath)?void 0:path7.dirname(resolvedPath);return{path:extensionPath,resolvedPath,sourceInfo:createSyntheticSourceInfo(extensionPath,{source,baseDir}),handlers:new Map,tools:new Map,messageRenderers:new Map,entryRenderers:new Map,commands:new Map,flags:new Map,shortcuts:new Map}}async function initializeExtension(factory,extensionPath,resolvedPath,cwd,eventBus,runtime){let extension=createExtension(extensionPath,resolvedPath),load=createExtensionAPI(extension,runtime,cwd,eventBus);try{await factory(load.api),load.commit()}catch(error){throw load.discard(),error}return time(`${extensionPath} factory`,"extensions"),extension}async function loadExtension(extensionPath,cwd,eventBus,runtime,cacheToken){let resolvedPath=resolvePath(extensionPath,cwd,{normalizeUnicodeSpaces:!0});try{let factory=await loadExtensionModule(resolvedPath,cacheToken);return time(`${extensionPath} module import`,"extensions"),factory?{extension:await initializeExtension(factory,extensionPath,resolvedPath,cwd,eventBus,runtime),error:null}:{extension:null,error:`Extension does not export a valid factory function: ${extensionPath}`}}catch(err){return{extension:null,error:`Failed to load extension: ${err instanceof Error?err.message:String(err)}`}}}async function loadExtensionFromFactory(factory,cwd,eventBus,runtime,extensionPath="<inline>"){let resolvedCwd=resolvePath(cwd);return initializeExtension(factory,extensionPath,extensionPath,resolvedCwd,eventBus,runtime)}async function loadExtensionsInternal(paths,cwd,eventBus,runtime,useCache=!1){let extensions=[],errors=[],warnings=[],cacheToken=useCache?useExtensionCacheCwd(cwd):void 0,resolvedCwd=cacheToken?.cwd??resolvePath(cwd),resolvedEventBus=eventBus??createEventBus(),resolvedRuntime=runtime??createExtensionRuntime();for(let extPath of paths){let{extension,error}=await loadExtension(extPath,resolvedCwd,resolvedEventBus,resolvedRuntime,cacheToken);if(error){errors.push({path:extPath,error});continue}extension&&extensions.push(extension)}return{extensions,errors,warnings,runtime:resolvedRuntime}}async function loadExtensions(paths,cwd,eventBus,runtime){return loadExtensionsInternal(paths,cwd,eventBus,runtime)}async function loadExtensionsCached(paths,cwd,eventBus,runtime){return loadExtensionsInternal(paths,cwd,eventBus,runtime,!0)}function isExtensionFile(name){return name.endsWith(".ts")||name.endsWith(".js")}function resolveExtensionEntries2(dir){let packageJsonPath=path7.join(dir,"package.json");if(fs5.existsSync(packageJsonPath)){let manifest=readPiManifest(packageJsonPath);if(manifest?.extensions?.length){let entries=[];for(let extPath of manifest.extensions){let resolvedExtPath=path7.resolve(dir,extPath);fs5.existsSync(resolvedExtPath)&&entries.push(resolvedExtPath)}if(entries.length>0)return entries}}let indexTs=path7.join(dir,"index.ts"),indexJs=path7.join(dir,"index.js");return fs5.existsSync(indexTs)?[indexTs]:fs5.existsSync(indexJs)?[indexJs]:null}function discoverExtensionsInDir(dir){if(!fs5.existsSync(dir))return[];let discovered=[];try{let entries=fs5.readdirSync(dir,{withFileTypes:!0});for(let entry of entries){let entryPath=path7.join(dir,entry.name);if((entry.isFile()||entry.isSymbolicLink())&&isExtensionFile(entry.name)){discovered.push(entryPath);continue}if(entry.isDirectory()||entry.isSymbolicLink()){let entries2=resolveExtensionEntries2(entryPath);entries2&&discovered.push(...entries2)}}}catch{return[]}return discovered}async function discoverAndLoadExtensions(configuredPaths,cwd,agentDir=getAgentDir(),eventBus){let resolvedCwd=resolvePath(cwd),resolvedAgentDir=resolvePath(agentDir),allPaths=[],seen=new Set,addPaths=paths=>{for(let p of paths){let resolved=path7.resolve(p);seen.has(resolved)||(seen.add(resolved),allPaths.push(p))}},localExtDir=path7.join(resolvedCwd,CONFIG_DIR_NAME,"extensions");addPaths(discoverExtensionsInDir(localExtDir));let globalExtDir=path7.join(resolvedAgentDir,"extensions");addPaths(discoverExtensionsInDir(globalExtDir));for(let p of configuredPaths){let resolved=resolvePath(p,resolvedCwd,{normalizeUnicodeSpaces:!0});if(fs5.existsSync(resolved)&&fs5.statSync(resolved).isDirectory()){let entries=resolveExtensionEntries2(resolved);if(entries){addPaths(entries);continue}addPaths(discoverExtensionsInDir(resolved));continue}addPaths([resolved])}return loadExtensions(allPaths,resolvedCwd,eventBus)}var ModelRegistry=class{constructor(runtime){this.runtime=runtime}getRuntime(){return this.runtime}refresh(options){return this.runtime.refresh(options)}getError(){return this.runtime.getError()}getAll(){return[...this.runtime.getModels()]}getAvailable(){return[...this.runtime.getAvailableSnapshot()]}find(provider,modelId){return this.runtime.getModel(provider,modelId)}findOfType(type,provider,modelId){return this.runtime.getModelOfType(type,provider,modelId)}hasConfiguredAuth(model){return this.runtime.hasConfiguredAuth(model.provider)}async getApiKeyAndHeaders(model){try{let resolution=await this.runtime.getAuth(model);if(!resolution){let compatibility=this.runtime.getCompatibilityRequestConfig(model);return compatibility.authHeader?{ok:!1,error:`No API key found for "${model.provider}"`}:{ok:!0,headers:compatibility.headers}}return{ok:!0,apiKey:resolution.auth.apiKey,headers:resolution.auth.headers,...resolution.auth.baseUrl?{baseUrl:resolution.auth.baseUrl}:{},env:resolution.env}}catch(error){let cause=error instanceof Error?error.cause:void 0,message=cause instanceof Error?cause.message:error instanceof Error?error.message:String(error);return{ok:!1,error:message==="authHeader requires a resolved API key"?`No API key found for "${model.provider}"`:message}}}getProviderAuthStatus(provider){return this.runtime.getProviderAuthStatus(provider)}getProvider(provider){return this.runtime.getProvider(provider)}stream(model,context,options){return this.runtime.stream(model,context,options)}streamSimple(model,context,options){return this.runtime.streamSimple(model,context,options)}complete(model,context,options){return this.runtime.complete(model,context,options)}getModelsOfType(type,provider){return this.runtime.getModelsOfType(type,provider)}getAvailableOfType(type,provider,options){return this.runtime.getAvailableOfType(type,provider,options)}getModelOfType(type,provider,modelId){return this.runtime.getModelOfType(type,provider,modelId)}classify(model,context,options){return this.runtime.classify(model,context,options)}generateImages(model,context,options){return this.runtime.generateImages(model,context,options)}getProviderDisplayName(provider){return this.runtime.getProvider(provider)?.name??provider}getProviderAuth(provider){return this.runtime.getAuth(provider)}async getApiKeyForProvider(provider){try{return(await this.runtime.getAuth(provider))?.auth.apiKey}catch{return}}isUsingOAuth(model){return this.runtime.isUsingOAuth(model.provider)}registerProvider(providerOrName,config){if(typeof providerOrName=="string"){if(!config)throw new Error("Provider config is required when registering by name");this.runtime.registerProvider(providerOrName,config);return}this.runtime.registerNativeProvider(providerOrName)}unregisterProvider(providerName){this.runtime.unregisterProvider(providerName)}registerVirtualModel(definition){this.runtime.registerVirtualModel(definition)}unregisterVirtualModel(providerName,id){this.runtime.unregisterVirtualModel(providerName,id)}getRegisteredProviderConfig(providerName){return this.runtime.getRegisteredProviderConfig(providerName)}getRegisteredNativeProvider(providerName){return this.runtime.getRegisteredNativeProvider(providerName)}getRegisteredProviderIds(){return this.runtime.getRegisteredProviderIds()}};function truncateToVisualLines(text2,maxVisualLines,width,paddingX=0,keep="end"){if(!text2)return{visualLines:[],skippedCount:0};let allVisualLines=new Text(text2,paddingX,0).render(width);if(allVisualLines.length<=maxVisualLines)return{visualLines:allVisualLines,skippedCount:0};let truncatedLines=keep==="start"?allVisualLines.slice(0,maxVisualLines):allVisualLines.slice(-maxVisualLines),skippedCount=allVisualLines.length-maxVisualLines;return{visualLines:truncatedLines,skippedCount}}var VisualLinePreview=class{constructor(options){this.options=options}render(width){if(this.cachedLines===void 0||this.cachedWidth!==width){let{text:text2,maxVisualLines,keep,formatHint}=this.options,preview=truncateToVisualLines(text2,maxVisualLines,width,0,keep),lines=preview.visualLines;if(preview.skippedCount>0){let hint=truncateToWidth(formatHint(preview.skippedCount),width,"...");this.cachedLines=keep==="start"?[...lines,hint]:[hint,...lines]}else this.cachedLines=lines;this.cachedWidth=width}return this.cachedLines}invalidate(){this.cachedWidth=void 0,this.cachedLines=void 0}};import*as os4 from"node:os";import{pathToFileURL as pathToFileURL2}from"node:url";var ST="(?:\\u0007|\\u001B\\u005C|\\u009C)",OSC_START="\\u001B\\]",CSI_START="[\\u001B\\u009B][[\\]()#;?]*(?:\\d{1,4}(?:[;:]\\d{0,4})*)?",CSI_FINAL="[\\dA-PR-TZcf-nq-uy=><~]",ansiRegex=new RegExp(`(?:${OSC_START}[\\s\\S]*?${ST})|${CSI_START}${CSI_FINAL}`,"g"),unfinishedAnsiAtEndRegex=new RegExp(`(?:${OSC_START}(?:[^\\u0007\\u009C\\u001B]|\\u001B(?!\\\\))*|${CSI_START})$`),MAX_PENDING_ANSI_LENGTH=256;function splitIncompleteAnsiSuffix(value){if(!value.includes("\x1B")&&!value.includes("\x9B"))return{complete:value,pending:""};let windowStart=Math.max(0,value.length-MAX_PENDING_ANSI_LENGTH),match2=unfinishedAnsiAtEndRegex.exec(value.slice(windowStart));if(!match2)return{complete:value,pending:""};let splitAt=windowStart+match2.index;return{complete:value.slice(0,splitAt),pending:value.slice(splitAt)}}function stripAnsi(value){if(typeof value!="string")throw new TypeError(`Expected a \`string\`, got \`${typeof value}\``);return!value.includes("\x1B")&&!value.includes("\x9B")?value:value.replace(ansiRegex,"")}function shortenPath2(path14){if(typeof path14!="string")return"";let home=os4.homedir();return path14.startsWith(home)?`~${path14.slice(home.length)}`:path14}function linkPath(styledText,rawPath,cwd){if(!getCapabilities().hyperlinks)return styledText;let absolutePath=resolvePath(rawPath,cwd);return hyperlink(styledText,pathToFileURL2(absolutePath).href)}function str(value){return typeof value=="string"?value:value==null?"":null}function parseLineNumber(value){return typeof value=="string"&&value.trim()!==""&&(value=Number(value)),typeof value=="number"&&Number.isFinite(value)?value:void 0}function formatReadLineRange(offset,limit){if(offset==null&&limit==null)return"";let start=offset==null?1:parseLineNumber(offset);if(start===void 0)return"";if(limit==null)return`:${start}`;let count=parseLineNumber(limit);if(count===void 0)return"";let end=start+count-1;return`:${start}${end?`-${end}`:""}`}function replaceTabs(text2){return text2.replace(/\t/g," ")}function normalizeDisplayText(text2){return text2.replace(/\r/g,"")}function getTextOutput(result2,showImages){if(!result2)return"";let textBlocks=result2.content.filter(c=>c.type==="text"),imageBlocks=result2.content.filter(c=>c.type==="image"),output=textBlocks.map(c=>sanitizeBinaryOutput(stripAnsi(c.text||"")).replace(/\r/g,"")).join(`
|
|
881
|
+
`)}}function printTimings(){if(ENABLED)for(let[namespace,timingNamespace]of timingNamespaces)printTimingGroup(`Startup Timings: ${namespace}`,timingNamespace.timings)}var require3=createRequire5(import.meta.url),isNodeSeaBinary="sea"in process.features&&process.features.sea===!0||process.getBuiltinModule("node:sea")?.isSea()===!0,isTypeScriptSourceRuntime=!isBunBinary&&path7.extname(fileURLToPath5(import.meta.url))===".ts",usesEmbeddedModules=isBunBinary||isNodeSeaBinary||isBundledNode,createJitiPromise;function getCreateJiti(){return createJitiPromise??=(usesEmbeddedModules?import("./jiti-static-loader-CLT3YR3B.js"):import("./jiti-loader-BFSSLU7G.js")).then(module=>module.createJiti),createJitiPromise}var virtualModulesPromise;function getVirtualModules(){return virtualModulesPromise??=import("./virtual-modules-5NSVVTKO.js").then(module=>module.VIRTUAL_MODULES),virtualModulesPromise}var _aliases=null;function getAliases(){if(_aliases)return _aliases;let __dirname2=path7.dirname(fileURLToPath5(import.meta.url)),packageIndex=path7.resolve(__dirname2,"../..","index.js"),typeboxEntry=require3.resolve("typebox"),typeboxCompileEntry=require3.resolve("typebox/compile"),typeboxValueEntry=require3.resolve("typebox/value"),resolveImport=specifier=>fileURLToPath5(import.meta.resolve(specifier)),piCodingAgentEntry=packageIndex,piAgentCoreEntry=resolveImport("@earendil-works/pi-agent-core"),piTuiEntry=resolveImport("@earendil-works/pi-tui"),piAiCompatEntry=resolveImport("@earendil-works/pi-ai/compat"),piAiModelsEntry=resolveImport("@earendil-works/pi-ai/models"),piAiOauthEntry=resolveImport("@earendil-works/pi-ai/oauth"),piAiProvidersEntry=resolveImport("@earendil-works/pi-ai/providers/all");return _aliases={"@earendil-works/pi-coding-agent":piCodingAgentEntry,[DISTRIBUTION_PACKAGE_NAME]:piCodingAgentEntry,"@earendil-works/pi-agent-core":piAgentCoreEntry,"@earendil-works/pi-tui":piTuiEntry,"@earendil-works/pi-ai/providers/all":piAiProvidersEntry,"@earendil-works/pi-ai/compat":piAiCompatEntry,"@earendil-works/pi-ai/models":piAiModelsEntry,"@earendil-works/pi-ai/oauth":piAiOauthEntry,"@earendil-works/pi-ai":piAiCompatEntry,"@mariozechner/pi-coding-agent":piCodingAgentEntry,"@mariozechner/pi-agent-core":piAgentCoreEntry,"@mariozechner/pi-tui":piTuiEntry,"@mariozechner/pi-ai/providers/all":piAiProvidersEntry,"@mariozechner/pi-ai/compat":piAiCompatEntry,"@mariozechner/pi-ai/models":piAiModelsEntry,"@mariozechner/pi-ai/oauth":piAiOauthEntry,"@mariozechner/pi-ai":piAiCompatEntry,typebox:typeboxEntry,"typebox/compile":typeboxCompileEntry,"typebox/value":typeboxValueEntry,"@sinclair/typebox":typeboxEntry,"@sinclair/typebox/compile":typeboxCompileEntry,"@sinclair/typebox/value":typeboxValueEntry},_aliases}var extensionCacheCwd,extensionCacheGeneration=0,extensionCache=new Map;function clearExtensionCache(){extensionCache.clear(),extensionCacheCwd=void 0,extensionCacheGeneration++}function useExtensionCacheCwd(cwd){let resolvedCwd=resolvePath(cwd);return extensionCacheCwd!==void 0&&extensionCacheCwd!==resolvedCwd&&clearExtensionCache(),extensionCacheCwd=resolvedCwd,{cwd:resolvedCwd,generation:extensionCacheGeneration}}function createExtensionRuntime(){let notInitialized=()=>{throw new Error("Extension runtime not initialized. Action methods cannot be called during extension loading.")},state2={},eventBusUnsubscribers=new Set,assertActive=()=>{if(state2.staleMessage)throw new Error(state2.staleMessage)},runtime={sendMessage:notInitialized,sendUserMessage:notInitialized,appendEntry:notInitialized,setSessionName:notInitialized,getSessionName:notInitialized,setLabel:notInitialized,getActiveTools:notInitialized,getAllTools:notInitialized,getSettings:notInitialized,setActiveTools:notInitialized,refreshTools:()=>{},getCommands:notInitialized,setModel:()=>Promise.reject(new Error("Extension runtime not initialized")),getThinkingLevel:notInitialized,setThinkingLevel:notInitialized,flagValues:new Map,pendingProviderRegistrations:[],pendingNativeProviderRegistrations:[],mcpServers:new McpServerRegistry,pendingVirtualModelRegistrations:[],createContext:notInitialized,assertActive,invalidate:message=>{if(!state2.staleMessage){state2.staleMessage=message??"This extension ctx is stale after session replacement or reload. Do not use a captured pi or command ctx after ctx.newSession(), ctx.fork(), ctx.switchSession(), or ctx.reload(). For newSession, fork, and switchSession, move post-replacement work into withSession and use the ctx passed to withSession. For reload, do not use the old ctx after await ctx.reload().";for(let unsubscribe of eventBusUnsubscribers)unsubscribe();eventBusUnsubscribers.clear()}},trackEventBusSubscription:unsubscribe=>{let active=!0,trackedUnsubscribe=()=>{active&&(active=!1,eventBusUnsubscribers.delete(trackedUnsubscribe),unsubscribe())};return eventBusUnsubscribers.add(trackedUnsubscribe),trackedUnsubscribe},registerProvider:(name,config,extensionPath="<unknown>")=>{runtime.pendingProviderRegistrations.push({name,config,extensionPath})},registerNativeProvider:(provider,extensionPath="<unknown>")=>{runtime.pendingNativeProviderRegistrations.push({provider,extensionPath})},unregisterProvider:name=>{runtime.pendingProviderRegistrations=runtime.pendingProviderRegistrations.filter(r=>r.name!==name),runtime.pendingNativeProviderRegistrations=runtime.pendingNativeProviderRegistrations.filter(r=>r.provider.id!==name)},registerVirtualModel:(definition,extensionPath="<unknown>")=>{runtime.pendingVirtualModelRegistrations.push({definition,extensionPath})},unregisterVirtualModel:(provider,id)=>{runtime.pendingVirtualModelRegistrations=runtime.pendingVirtualModelRegistrations.filter(({definition})=>definition.provider!==provider||definition.id!==id)}};return runtime}function createExtensionAPI(extension,runtime,cwd,eventBus){let pendingFlagValues=new Map,pendingRuntimeChanges=[],loadingUnsubscribers=[],state2="loading",assertActive=()=>{if(state2==="failed")throw new Error(`Extension "${extension.path}" failed to load and its API is no longer active.`);runtime.assertActive()},applyRuntimeChange=change=>{state2==="loading"?pendingRuntimeChanges.push(change):change()},clearPending=()=>{pendingFlagValues.clear(),pendingRuntimeChanges.length=0,loadingUnsubscribers.length=0};return{api:{on(event,handler){assertActive();let registeredHandler=(...args)=>handler(...args),list2=extension.handlers.get(event)??[];return list2.push(registeredHandler),extension.handlers.set(event,list2),()=>{let handlers=extension.handlers.get(event);if(!handlers)return;let handlerIndex=handlers.indexOf(registeredHandler);handlerIndex!==-1&&(handlers.splice(handlerIndex,1),handlers.length===0&&extension.handlers.delete(event))}},registerTool(tool){if(assertActive(),typeof tool.parameters!="object"||tool.parameters===null||Array.isArray(tool.parameters))throw new Error(`Tool "${tool.name}" registered by extension "${extension.path}" must define an object parameter schema.`);extension.tools.set(tool.name,{definition:tool,sourceInfo:extension.sourceInfo}),runtime.refreshTools()},registerCommand(name,options){if(assertActive(),typeof name!="string"||name.length===0)throw new Error(`Command registered by extension "${extension.path}" must have a non-empty string name. Use pi.registerCommand("name", { description, handler }).`);if(typeof options?.handler!="function")throw new Error(`Command "/${name}" registered by extension "${extension.path}" must define handler().`);extension.commands.set(name,{name,sourceInfo:extension.sourceInfo,...options})},registerShortcut(shortcut,options){assertActive(),extension.shortcuts.set(shortcut,{shortcut,extensionPath:extension.path,...options})},registerFlag(name,options){if(assertActive(),options.default!==void 0&&typeof options.default!==options.type)throw new Error(`Invalid default for flag "${name}": expected ${options.type}, got ${typeof options.default}`);extension.flags.set(name,{name,extensionPath:extension.path,...options}),options.default!==void 0&&!runtime.flagValues.has(name)&&(state2==="loading"?pendingFlagValues.has(name)||pendingFlagValues.set(name,options.default):runtime.flagValues.set(name,options.default))},registerMessageRenderer(customType,renderer){assertActive(),extension.messageRenderers.set(customType,renderer)},registerMarkdownTransformer(transformer){assertActive(),extension.markdownTransformer=transformer},registerEntryRenderer(customType,renderer){assertActive(),extension.entryRenderers??=new Map,extension.entryRenderers.set(customType,renderer)},registerToolRenderer(resolver){assertActive(),extension.toolRenderers??=[],extension.toolRenderers.push(resolver)},getFlag(name){if(assertActive(),!!extension.flags.has(name))return runtime.flagValues.has(name)?runtime.flagValues.get(name):pendingFlagValues.get(name)},sendMessage(message,options){assertActive(),runtime.sendMessage(message,options)},sendUserMessage(content,options){assertActive(),runtime.sendUserMessage(content,options)},appendEntry(customType,data){assertActive(),runtime.appendEntry(customType,data)},setSessionName(name){assertActive(),runtime.setSessionName(name)},getSessionName(){return assertActive(),runtime.getSessionName()},setLabel(entryId,label){assertActive(),runtime.setLabel(entryId,label)},exec(command,args,options){return assertActive(),execCommand(command,args,options?.cwd??cwd,options)},getActiveTools(){return assertActive(),runtime.getActiveTools()},getAllTools(){return assertActive(),runtime.getAllTools()},getSettings(){return assertActive(),runtime.getSettings()},setActiveTools(toolNames){assertActive(),runtime.setActiveTools(toolNames)},getCommands(){return assertActive(),runtime.getCommands()},setModel(model){return assertActive(),runtime.setModel(model)},getThinkingLevel(){return assertActive(),runtime.getThinkingLevel()},setThinkingLevel(level){assertActive(),runtime.setThinkingLevel(level)},registerProvider(providerOrName,config){if(assertActive(),typeof providerOrName=="string"){if(!config)throw new Error("Provider config is required when registering by name");applyRuntimeChange(()=>runtime.registerProvider(providerOrName,config,extension.path));return}applyRuntimeChange(()=>runtime.registerNativeProvider(providerOrName,extension.path))},unregisterProvider(name){assertActive(),applyRuntimeChange(()=>runtime.unregisterProvider(name,extension.path))},registerMcpServer(name,config){assertActive();let validated=validateMcpServerConfig(name,config);if(typeof validated=="string")throw new Error(`Invalid MCP server registered by extension "${extension.path}": ${validated}`);let owner=runtime.mcpServers.get(name)?.extensionPath;if(owner!==void 0&&owner!==extension.path)throw new Error(`MCP server "${name}" is already registered by extension "${owner}"`);let clash=runtime.mcpServers.list().find(server2=>server2.name!==name&&mcpNamespace(server2.name)===mcpNamespace(name));if(clash)throw new Error(`MCP server "${name}" conflicts with registered server "${clash.name}"`);let server={name,config:structuredClone(validated),extensionPath:extension.path};applyRuntimeChange(()=>runtime.mcpServers.register(server))},unregisterMcpServer(name){assertActive(),applyRuntimeChange(()=>runtime.mcpServers.unregister(name,extension.path))},getMcpServers(){return assertActive(),runtime.mcpServers.list()},registerVirtualModel(model){assertActive();let definition={...model,route:request=>model.route(request,runtime.createContext())};applyRuntimeChange(()=>runtime.registerVirtualModel(definition,extension.path))},unregisterVirtualModel(provider,id){assertActive(),applyRuntimeChange(()=>runtime.unregisterVirtualModel(provider,id))},events:{emit(channel,data){assertActive(),eventBus.emit(channel,data)},on(channel,handler){assertActive();let unsubscribe=runtime.trackEventBusSubscription(eventBus.on(channel,handler));return state2==="loading"&&loadingUnsubscribers.push(unsubscribe),unsubscribe}}},commit:()=>{if(state2==="loading"){runtime.assertActive();for(let[name,value]of pendingFlagValues)runtime.flagValues.has(name)||runtime.flagValues.set(name,value);for(let apply of pendingRuntimeChanges)apply();state2="active",clearPending()}},discard:()=>{if(state2==="loading"){state2="failed";for(let unsubscribe of loadingUnsubscribers)unsubscribe();clearPending()}}}}function isCurrentCacheToken(cacheToken){return cacheToken!==void 0&&extensionCacheCwd===cacheToken.cwd&&extensionCacheGeneration===cacheToken.generation}async function loadExtensionModule(extensionPath,cacheToken){if(isCurrentCacheToken(cacheToken)){let cachedFactory=extensionCache.get(extensionPath);if(cachedFactory)return cachedFactory}let createJitiImpl=await getCreateJiti(),resolutionOptions=usesEmbeddedModules?{virtualModules:await getVirtualModules(),tryNative:!1}:isTypeScriptSourceRuntime?{virtualModules:await getVirtualModules(),tsconfigPaths:!0}:{alias:getAliases()},factory=await createJitiImpl(import.meta.url,{moduleCache:!1,...resolutionOptions}).import(extensionPath,{default:!0});if(typeof factory=="function")return isCurrentCacheToken(cacheToken)&&extensionCache.set(extensionPath,factory),factory}function createExtension(extensionPath,resolvedPath){let source=getSyntheticPathSource(extensionPath)??"local",baseDir=isSyntheticPath(extensionPath)?void 0:path7.dirname(resolvedPath);return{path:extensionPath,resolvedPath,sourceInfo:createSyntheticSourceInfo(extensionPath,{source,baseDir}),handlers:new Map,tools:new Map,messageRenderers:new Map,entryRenderers:new Map,commands:new Map,flags:new Map,shortcuts:new Map}}async function initializeExtension(factory,extensionPath,resolvedPath,cwd,eventBus,runtime){let extension=createExtension(extensionPath,resolvedPath),load=createExtensionAPI(extension,runtime,cwd,eventBus);try{await factory(load.api),load.commit()}catch(error){throw load.discard(),error}return time(`${extensionPath} factory`,"extensions"),extension}async function loadExtension(extensionPath,cwd,eventBus,runtime,cacheToken){let resolvedPath=resolvePath(extensionPath,cwd,{normalizeUnicodeSpaces:!0});try{let factory=await loadExtensionModule(resolvedPath,cacheToken);return time(`${extensionPath} module import`,"extensions"),factory?{extension:await initializeExtension(factory,extensionPath,resolvedPath,cwd,eventBus,runtime),error:null}:{extension:null,error:`Extension does not export a valid factory function: ${extensionPath}`}}catch(err){return{extension:null,error:`Failed to load extension: ${err instanceof Error?err.message:String(err)}`}}}async function loadExtensionFromFactory(factory,cwd,eventBus,runtime,extensionPath="<inline>"){let resolvedCwd=resolvePath(cwd);return initializeExtension(factory,extensionPath,extensionPath,resolvedCwd,eventBus,runtime)}async function loadExtensionsInternal(paths,cwd,eventBus,runtime,useCache=!1){let extensions=[],errors=[],warnings=[],cacheToken=useCache?useExtensionCacheCwd(cwd):void 0,resolvedCwd=cacheToken?.cwd??resolvePath(cwd),resolvedEventBus=eventBus??createEventBus(),resolvedRuntime=runtime??createExtensionRuntime();for(let extPath of paths){let{extension,error}=await loadExtension(extPath,resolvedCwd,resolvedEventBus,resolvedRuntime,cacheToken);if(error){errors.push({path:extPath,error});continue}extension&&extensions.push(extension)}return{extensions,errors,warnings,runtime:resolvedRuntime}}async function loadExtensions(paths,cwd,eventBus,runtime){return loadExtensionsInternal(paths,cwd,eventBus,runtime)}async function loadExtensionsCached(paths,cwd,eventBus,runtime){return loadExtensionsInternal(paths,cwd,eventBus,runtime,!0)}function isExtensionFile(name){return name.endsWith(".ts")||name.endsWith(".js")}function resolveExtensionEntries2(dir){let packageJsonPath=path7.join(dir,"package.json");if(fs5.existsSync(packageJsonPath)){let manifest=readPiManifest(packageJsonPath);if(manifest?.extensions?.length){let entries=[];for(let extPath of manifest.extensions){let resolvedExtPath=path7.resolve(dir,extPath);fs5.existsSync(resolvedExtPath)&&entries.push(resolvedExtPath)}if(entries.length>0)return entries}}let indexTs=path7.join(dir,"index.ts"),indexJs=path7.join(dir,"index.js");return fs5.existsSync(indexTs)?[indexTs]:fs5.existsSync(indexJs)?[indexJs]:null}function discoverExtensionsInDir(dir){if(!fs5.existsSync(dir))return[];let discovered=[];try{let entries=fs5.readdirSync(dir,{withFileTypes:!0});for(let entry of entries){let entryPath=path7.join(dir,entry.name);if((entry.isFile()||entry.isSymbolicLink())&&isExtensionFile(entry.name)){discovered.push(entryPath);continue}if(entry.isDirectory()||entry.isSymbolicLink()){let entries2=resolveExtensionEntries2(entryPath);entries2&&discovered.push(...entries2)}}}catch{return[]}return discovered}async function discoverAndLoadExtensions(configuredPaths,cwd,agentDir=getAgentDir(),eventBus){let resolvedCwd=resolvePath(cwd),resolvedAgentDir=resolvePath(agentDir),allPaths=[],seen=new Set,addPaths=paths=>{for(let p of paths){let resolved=path7.resolve(p);seen.has(resolved)||(seen.add(resolved),allPaths.push(p))}},localExtDir=path7.join(resolvedCwd,CONFIG_DIR_NAME,"extensions");addPaths(discoverExtensionsInDir(localExtDir));let globalExtDir=path7.join(resolvedAgentDir,"extensions");addPaths(discoverExtensionsInDir(globalExtDir));for(let p of configuredPaths){let resolved=resolvePath(p,resolvedCwd,{normalizeUnicodeSpaces:!0});if(fs5.existsSync(resolved)&&fs5.statSync(resolved).isDirectory()){let entries=resolveExtensionEntries2(resolved);if(entries){addPaths(entries);continue}addPaths(discoverExtensionsInDir(resolved));continue}addPaths([resolved])}return loadExtensions(allPaths,resolvedCwd,eventBus)}var ModelRegistry=class{constructor(runtime){this.runtime=runtime}getRuntime(){return this.runtime}refresh(options){return this.runtime.refresh(options)}getError(){return this.runtime.getError()}getAll(){return[...this.runtime.getModels()]}getAvailable(){return[...this.runtime.getAvailableSnapshot()]}find(provider,modelId){return this.runtime.getModel(provider,modelId)}findOfType(type,provider,modelId){return this.runtime.getModelOfType(type,provider,modelId)}hasConfiguredAuth(model){return this.runtime.hasConfiguredAuth(model.provider)}async getApiKeyAndHeaders(model){try{let resolution=await this.runtime.getAuth(model);if(!resolution){let compatibility=this.runtime.getCompatibilityRequestConfig(model);return compatibility.authHeader?{ok:!1,error:`No API key found for "${model.provider}"`}:{ok:!0,headers:compatibility.headers}}return{ok:!0,apiKey:resolution.auth.apiKey,headers:resolution.auth.headers,...resolution.auth.baseUrl?{baseUrl:resolution.auth.baseUrl}:{},env:resolution.env}}catch(error){let cause=error instanceof Error?error.cause:void 0,message=cause instanceof Error?cause.message:error instanceof Error?error.message:String(error);return{ok:!1,error:message==="authHeader requires a resolved API key"?`No API key found for "${model.provider}"`:message}}}getProviderAuthStatus(provider){return this.runtime.getProviderAuthStatus(provider)}getProvider(provider){return this.runtime.getProvider(provider)}stream(model,context,options){return this.runtime.stream(model,context,options)}streamSimple(model,context,options){return this.runtime.streamSimple(model,context,options)}complete(model,context,options){return this.runtime.complete(model,context,options)}getModelsOfType(type,provider){return this.runtime.getModelsOfType(type,provider)}getAvailableOfType(type,provider,options){return this.runtime.getAvailableOfType(type,provider,options)}getModelOfType(type,provider,modelId){return this.runtime.getModelOfType(type,provider,modelId)}classify(model,context,options){return this.runtime.classify(model,context,options)}generateImages(model,context,options){return this.runtime.generateImages(model,context,options)}getProviderDisplayName(provider){return this.runtime.getProvider(provider)?.name??provider}getProviderAuth(provider){return this.runtime.getAuth(provider)}async getApiKeyForProvider(provider){try{return(await this.runtime.getAuth(provider))?.auth.apiKey}catch{return}}isUsingOAuth(model){return this.runtime.isUsingOAuth(model.provider)}registerProvider(providerOrName,config){if(typeof providerOrName=="string"){if(!config)throw new Error("Provider config is required when registering by name");this.runtime.registerProvider(providerOrName,config);return}this.runtime.registerNativeProvider(providerOrName)}unregisterProvider(providerName){this.runtime.unregisterProvider(providerName)}registerVirtualModel(definition){this.runtime.registerVirtualModel(definition)}unregisterVirtualModel(providerName,id){this.runtime.unregisterVirtualModel(providerName,id)}getRegisteredProviderConfig(providerName){return this.runtime.getRegisteredProviderConfig(providerName)}getRegisteredNativeProvider(providerName){return this.runtime.getRegisteredNativeProvider(providerName)}getRegisteredProviderIds(){return this.runtime.getRegisteredProviderIds()}};function truncateToVisualLines(text2,maxVisualLines,width,paddingX=0,keep="end"){if(!text2)return{visualLines:[],skippedCount:0};let allVisualLines=new Text(text2,paddingX,0).render(width);if(allVisualLines.length<=maxVisualLines)return{visualLines:allVisualLines,skippedCount:0};let truncatedLines=keep==="start"?allVisualLines.slice(0,maxVisualLines):allVisualLines.slice(-maxVisualLines),skippedCount=allVisualLines.length-maxVisualLines;return{visualLines:truncatedLines,skippedCount}}var VisualLinePreview=class{constructor(options){this.options=options}render(width){if(this.cachedLines===void 0||this.cachedWidth!==width){let{text:text2,maxVisualLines,keep,formatHint}=this.options,preview=truncateToVisualLines(text2,maxVisualLines,width,0,keep),lines=preview.visualLines;if(preview.skippedCount>0){let hint=truncateToWidth(formatHint(preview.skippedCount),width,"...");this.cachedLines=keep==="start"?[...lines,hint]:[hint,...lines]}else this.cachedLines=lines;this.cachedWidth=width}return this.cachedLines}invalidate(){this.cachedWidth=void 0,this.cachedLines=void 0}};import*as os4 from"node:os";import{pathToFileURL as pathToFileURL2}from"node:url";var ST="(?:\\u0007|\\u001B\\u005C|\\u009C)",OSC_START="\\u001B\\]",CSI_START="[\\u001B\\u009B][[\\]()#;?]*(?:\\d{1,4}(?:[;:]\\d{0,4})*)?",CSI_FINAL="[\\dA-PR-TZcf-nq-uy=><~]",ansiRegex=new RegExp(`(?:${OSC_START}[\\s\\S]*?${ST})|${CSI_START}${CSI_FINAL}`,"g"),unfinishedAnsiAtEndRegex=new RegExp(`(?:${OSC_START}(?:[^\\u0007\\u009C\\u001B]|\\u001B(?!\\\\))*|${CSI_START})$`),MAX_PENDING_ANSI_LENGTH=256;function splitIncompleteAnsiSuffix(value){if(!value.includes("\x1B")&&!value.includes("\x9B"))return{complete:value,pending:""};let windowStart=Math.max(0,value.length-MAX_PENDING_ANSI_LENGTH),match2=unfinishedAnsiAtEndRegex.exec(value.slice(windowStart));if(!match2)return{complete:value,pending:""};let splitAt=windowStart+match2.index;return{complete:value.slice(0,splitAt),pending:value.slice(splitAt)}}function stripAnsi(value){if(typeof value!="string")throw new TypeError(`Expected a \`string\`, got \`${typeof value}\``);return!value.includes("\x1B")&&!value.includes("\x9B")?value:value.replace(ansiRegex,"")}function shortenPath2(path14){if(typeof path14!="string")return"";let home=os4.homedir();return path14.startsWith(home)?`~${path14.slice(home.length)}`:path14}function linkPath(styledText,rawPath,cwd){if(!getCapabilities().hyperlinks)return styledText;let absolutePath=resolvePath(rawPath,cwd);return hyperlink(styledText,pathToFileURL2(absolutePath).href)}function str(value){return typeof value=="string"?value:value==null?"":null}function parseLineNumber(value){return typeof value=="string"&&value.trim()!==""&&(value=Number(value)),typeof value=="number"&&Number.isFinite(value)?value:void 0}function formatReadLineRange(offset,limit){if(offset==null&&limit==null)return"";let start=offset==null?1:parseLineNumber(offset);if(start===void 0)return"";if(limit==null)return`:${start}`;let count=parseLineNumber(limit);if(count===void 0)return"";let end=start+count-1;return`:${start}${end?`-${end}`:""}`}function replaceTabs(text2){return text2.replace(/\t/g," ")}function normalizeDisplayText(text2){return text2.replace(/\r/g,"")}function getTextOutput(result2,showImages){if(!result2)return"";let textBlocks=result2.content.filter(c=>c.type==="text"),imageBlocks=result2.content.filter(c=>c.type==="image"),output=textBlocks.map(c=>sanitizeBinaryOutput(stripAnsi(c.text||"")).replace(/\r/g,"")).join(`
|
|
882
882
|
`),caps=getCapabilities();if(imageBlocks.length>0&&(!caps.images||!showImages)){let imageIndicators=imageBlocks.map(img=>{let mimeType=img.mimeType??"image/unknown",dims=img.data&&img.mimeType?getImageDimensions(img.data,img.mimeType)??void 0:void 0;return imageFallback(mimeType,dims)}).join(`
|
|
883
883
|
`);output=output?`${output}
|
|
884
884
|
${imageIndicators}`:imageIndicators}return output}var COLLAPSED_ARGS_CHARS=100;function formatToolCallWithArgs(title,args,theme2,expanded){let header2=theme2.fg("toolTitle",theme2.bold(title));if(args==null)return header2;let entries=typeof args=="object"&&!Array.isArray(args)?Object.entries(args):[["args",args]];if(entries.length===0)return header2;if(expanded){let lines=entries.map(([key,value])=>{let text2=typeof value=="string"?value:JSON.stringify(value,null,2)??String(value);return` ${key}: ${replaceTabs(text2).replace(/\r/g,"").split(`
|
|
@@ -1783,7 +1783,13 @@ ${statusParts.join(`
|
|
|
1783
1783
|
`),this.box.addChild(new Markdown(text2,0,0,this.markdownTheme,{color:text3=>theme.fg("customMessageText",text3)}))}};import{isAbsolute as isAbsolute5,relative as relative7,resolve as resolve13,sep as sep10}from"node:path";function areExperimentalFeaturesEnabled(){return process.env.PI_EXPERIMENTAL==="1"}function sanitizeStatusText(text2){return text2.replace(/[\r\n\t]/g," ").replace(/ +/g," ").trim()}function formatTokens(count){return count<1e3?count.toString():count<1e4?`${(count/1e3).toFixed(1)}k`:count<1e6?`${Math.round(count/1e3)}k`:count<1e7?`${(count/1e6).toFixed(1)}M`:`${Math.round(count/1e6)}M`}function formatCwdForFooter(cwd,home){if(!home)return cwd;let resolvedCwd=resolve13(cwd),resolvedHome=resolve13(home),relativeToHome=relative7(resolvedHome,resolvedCwd);return relativeToHome===""||relativeToHome!==".."&&!relativeToHome.startsWith(`..${sep10}`)&&!isAbsolute5(relativeToHome)?relativeToHome===""?"~":`~${sep10}${relativeToHome}`:cwd}var FooterComponent=class{constructor(session,footerData){this.autoCompactEnabled=!0,this.session=session,this.footerData=footerData}setSession(session){this.session=session}setAutoCompactEnabled(enabled){this.autoCompactEnabled=enabled}invalidate(){}dispose(){}getSessionStats(){let sessionManager=this.session.sessionManager,entryCount=sessionManager.getEntryCount(),sessionId=sessionManager.getSessionId(),leafId=sessionManager.getLeafId(),limitsModel=this.session.routedModel?.model??this.session.model,cached=this.sessionStats;if(cached&&cached.session===this.session&&cached.sessionId===sessionId&&cached.leafId===leafId&&cached.entryCount===entryCount&&cached.limitsModel===limitsModel)return cached;let usageTotals=createUsageTotals(),latestCacheHitRate,entries=this.session.sessionManager.getEntries();for(let usage of getAccountedUsages(entries))addUsageToTotals(usageTotals,usage);for(let entry of entries)if(entry.type==="message"&&entry.message.role==="assistant"){let latestPromptTokens=entry.message.usage.input+entry.message.usage.cacheRead+entry.message.usage.cacheWrite;latestCacheHitRate=latestPromptTokens>0?entry.message.usage.cacheRead/latestPromptTokens*100:void 0}let contextUsage=this.session.getContextUsage();return this.sessionStats={session:this.session,sessionId,leafId,entryCount,limitsModel,usageTotals,latestCacheHitRate,contextUsage},this.sessionStats}render(width){let state2=this.session.state,{usageTotals,latestCacheHitRate,contextUsage}=this.getSessionStats(),contextWindow=contextUsage?.contextWindow??state2.model?.contextWindow??0,contextPercentValue=contextUsage?.percent??0,contextPercent=contextUsage?.percent!==null?contextPercentValue.toFixed(1):"?",pwd=formatCwdForFooter(this.session.sessionManager.getCwd(),process.env.HOME||process.env.USERPROFILE),branch=this.footerData.getGitBranch();branch&&(pwd=`${pwd} (${branch})`);let sessionName=this.session.sessionManager.getSessionName();sessionName&&(pwd=`${pwd} \u2022 ${sessionName}`);let statsParts=[];usageTotals.input&&statsParts.push(`\u2191${formatTokens(usageTotals.input)}`),usageTotals.output&&statsParts.push(`\u2193${formatTokens(usageTotals.output)}`),usageTotals.cacheRead&&statsParts.push(`R${formatTokens(usageTotals.cacheRead)}`),usageTotals.cacheWrite&&statsParts.push(`W${formatTokens(usageTotals.cacheWrite)}`),(usageTotals.cacheRead>0||usageTotals.cacheWrite>0)&&latestCacheHitRate!==void 0&&statsParts.push(`CH${latestCacheHitRate.toFixed(1)}%`);let usingSubscription=state2.model?state2.model.provider==="kimi-coding"||this.session.modelRuntime.isUsingSubscription(state2.model.provider):!1;if(usageTotals.cost||usingSubscription){let costStr=`$${usageTotals.cost.toFixed(3)}${usingSubscription?" (sub)":""}`;statsParts.push(costStr)}let contextPercentStr,autoIndicator=this.autoCompactEnabled?" (auto)":"",contextPercentDisplay=contextPercent==="?"?`?/${formatTokens(contextWindow)}${autoIndicator}`:`${contextPercent}%/${formatTokens(contextWindow)}${autoIndicator}`;contextPercentValue>90?contextPercentStr=theme.fg("error",contextPercentDisplay):contextPercentValue>70?contextPercentStr=theme.fg("warning",contextPercentDisplay):contextPercentStr=contextPercentDisplay,statsParts.push(contextPercentStr),areExperimentalFeaturesEnabled()&&statsParts.push(`${theme.fg("dim","\u2022")} ${theme.bold(theme.fg("warning","xp"))}`);let statsLeft=statsParts.join(" "),modelName=state2.model?.id||"no-model",statsLeftWidth=visibleWidth(statsLeft);statsLeftWidth>width&&(statsLeft=truncateToWidth(statsLeft,width,"..."),statsLeftWidth=visibleWidth(statsLeft));let minPadding=2,rightSideWithoutProvider=modelName;if(state2.model?.reasoning){let thinkingLevel=state2.thinkingLevel||"off";rightSideWithoutProvider=thinkingLevel==="off"?`${modelName} \u2022 thinking off`:`${modelName} \u2022 ${thinkingLevel}`}let routed=this.session.routedModel;if(routed){let level=routed.thinkingLevel?` \u2022 ${routed.thinkingLevel}`:"";rightSideWithoutProvider+=` \u2192 ${routed.model.id}${level}`}let rightSide=rightSideWithoutProvider;this.footerData.getAvailableProviderCount()>1&&state2.model&&(rightSide=`(${state2.model.provider}) ${rightSideWithoutProvider}`,statsLeftWidth+minPadding+visibleWidth(rightSide)>width&&(rightSide=rightSideWithoutProvider));let rightSideWidth=visibleWidth(rightSide),totalNeeded=statsLeftWidth+minPadding+rightSideWidth,statsLine;if(totalNeeded<=width){let padding=" ".repeat(width-statsLeftWidth-rightSideWidth);statsLine=statsLeft+padding+rightSide}else{let availableForRight=width-statsLeftWidth-minPadding;if(availableForRight>0){let truncatedRight=truncateToWidth(rightSide,availableForRight,""),truncatedRightWidth=visibleWidth(truncatedRight),padding=" ".repeat(Math.max(0,width-statsLeftWidth-truncatedRightWidth));statsLine=statsLeft+padding+truncatedRight}else statsLine=statsLeft}let dimStatsLeft=theme.fg("dim",statsLeft),remainder=statsLine.slice(statsLeft.length),dimRemainder=theme.fg("dim",remainder),lines=[truncateToWidth(theme.fg("dim",pwd),width,theme.fg("dim","...")),dimStatsLeft+dimRemainder],extensionStatuses=this.footerData.getExtensionStatuses();if(extensionStatuses.size>0){let statusLine=Array.from(extensionStatuses.entries()).sort(([a],[b2])=>a.localeCompare(b2)).map(([,text2])=>sanitizeStatusText(text2)).join(" ");lines.push(truncateToWidth(statusLine,width,theme.fg("dim","...")))}return lines}};var LoginDialogComponent=class extends Container{get focused(){return this._focused}set focused(value){this._focused=value,this.input.focused=value}constructor(tui,providerId,onComplete,providerNameOverride,titleOverride){super(),this.abortController=new AbortController,this._focused=!1,this.tui=tui,this.onComplete=onComplete;let title=titleOverride??`Login to ${providerNameOverride||providerId}`;this.addChild(new DynamicBorder),this.addChild(new Text(theme.fg("accent",theme.bold(title)),1,0)),this.contentContainer=new Container,this.addChild(this.contentContainer),this.input=new Input,this.input.onSubmit=()=>{if(this.inputResolver){let value=this.input.getValue();this.replaceInputWithSubmittedText(value),this.inputResolver(value),this.inputResolver=void 0,this.inputRejecter=void 0}},this.input.onEscape=()=>{this.cancel()},this.addChild(new DynamicBorder)}get signal(){return this.abortController.signal}replaceInputWithSubmittedText(value){this.contentContainer.children=this.contentContainer.children.map(child=>child===this.input?new Text(`> ${value}`,0,0):child)}cancel(){this.abortController.abort(),this.inputRejecter&&(this.inputRejecter(new Error("Login cancelled")),this.inputResolver=void 0,this.inputRejecter=void 0),this.onComplete(!1,"Login cancelled")}showAuth(url,instructions){this.contentContainer.clear(),this.contentContainer.addChild(new Spacer(1)),this.authUrl=new AuthUrlComponent(this.tui,url),this.contentContainer.addChild(this.authUrl),instructions&&(this.contentContainer.addChild(new Spacer(1)),this.contentContainer.addChild(new Text(theme.fg("warning",instructions),1,0))),openBrowser(url),this.tui.requestRender()}showDeviceCode(info){this.authUrl=void 0,this.contentContainer.clear(),this.contentContainer.addChild(new Spacer(1));let linkedUrl=`\x1B]8;;${info.verificationUri}\x07${info.verificationUri}\x1B]8;;\x07`;this.contentContainer.addChild(new Text(theme.fg("accent",linkedUrl),1,0));let clickHint=process.platform==="darwin"?"Cmd+click to open":"Ctrl+click to open",hyperlink2=`\x1B]8;;${info.verificationUri}\x07${clickHint}\x1B]8;;\x07`;this.contentContainer.addChild(new Text(theme.fg("dim",hyperlink2),1,0)),this.contentContainer.addChild(new Spacer(1)),this.contentContainer.addChild(new Text(theme.fg("warning",`Enter code: ${info.userCode}`),1,0)),this.tui.requestRender()}showManualInput(prompt){return this.input.setValue(""),this.contentContainer.addChild(new Spacer(1)),this.contentContainer.addChild(new Text(theme.fg("dim",prompt),1,0)),this.contentContainer.addChild(this.input),this.contentContainer.addChild(new Text(`(${keyHint("tui.select.cancel","to cancel")})`,1,0)),this.tui.requestRender(),new Promise((resolve20,reject)=>{this.inputResolver=resolve20,this.inputRejecter=reject})}showPrompt(message,placeholder){return this.contentContainer.addChild(new Spacer(1)),this.contentContainer.addChild(new Text(theme.fg("text",message),1,0)),placeholder&&this.contentContainer.addChild(new Text(theme.fg("dim",`e.g., ${placeholder}`),1,0)),this.contentContainer.addChild(this.input),this.contentContainer.addChild(new Text(`(${keyHint("tui.select.cancel","to cancel,")} ${keyHint("tui.select.confirm","to submit")})`,1,0)),this.input.setValue(""),this.tui.requestRender(),new Promise((resolve20,reject)=>{this.inputResolver=resolve20,this.inputRejecter=reject})}showDetails(lines){this.authUrl=void 0,this.contentContainer.clear(),this.contentContainer.addChild(new Spacer(1));for(let line of lines)this.contentContainer.addChild(new Text(line,1,0));this.tui.requestRender()}showInfo(message,links=[],showCloseHint=!1){this.contentContainer.addChild(new Spacer(1)),this.contentContainer.addChild(new Text(theme.fg("text",message),1,0));for(let link of links){let text2=link.label?`${link.label}: ${link.url}`:link.url,hyperlink2=`\x1B]8;;${link.url}\x07${text2}\x1B]8;;\x07`;this.contentContainer.addChild(new Text(theme.fg("accent",hyperlink2),1,0))}showCloseHint&&(this.contentContainer.addChild(new Spacer(1)),this.contentContainer.addChild(new Text(`(${keyHint("tui.select.cancel","to close")})`,1,0))),this.tui.requestRender()}showWaiting(message){this.contentContainer.addChild(new Spacer(1)),this.contentContainer.addChild(new Text(theme.fg("dim",message),1,0)),this.contentContainer.addChild(new Text(`(${keyHint("tui.select.cancel","to cancel")})`,1,0)),this.tui.requestRender()}showProgress(message){this.contentContainer.addChild(new Text(theme.fg("dim",message),1,0)),this.tui.requestRender()}handleInput(data){let kb=getKeybindings();if(kb.matches(data,"tui.select.cancel")){this.cancel();return}if(this.authUrl&&kb.matches(data,"app.message.copy")){this.authUrl.copy();return}this.input.handleInput(data)}};var ModelCatalogRefreshCoordinator=class{constructor(){this.activeByRuntime=new WeakMap}refresh(modelRuntime,signal){signal.throwIfAborted();let active=this.activeByRuntime.get(modelRuntime);if(!active){let controller=new AbortController,created,operation=modelRuntime.refresh({signal:controller.signal}),promise=raceWithAbortSignal(operation,controller.signal).finally(()=>{this.activeByRuntime.get(modelRuntime)===created&&this.activeByRuntime.delete(modelRuntime)});created={controller,promise,waiters:0},active=created,this.activeByRuntime.set(modelRuntime,active)}return active.waiters++,raceWithAbortSignal(active.promise,signal).finally(()=>{active.waiters--,active.waiters===0&&this.activeByRuntime.get(modelRuntime)===active&&active.controller.abort()})}},modelCatalogRefreshCoordinator=new ModelCatalogRefreshCoordinator;function refreshModelCatalogs(modelRuntime,signal){return modelCatalogRefreshCoordinator.refresh(modelRuntime,signal)}function getModelSearchText(item){let{id,provider}=item,name=item.name?` ${item.name}`:"";return`${id} ${provider} ${provider}/${id} ${provider} ${id}${name}`}function getModelSelectorSearchText(item){let{id,provider}=item,name=item.name?` ${item.name}`:"";return`${provider} ${provider}/${id} ${provider} ${id}${name}`}var ModelSelectorComponent=class extends Container{get focused(){return this._focused}set focused(value){this._focused=value,this.searchInput.focused=value}constructor(tui,currentModel,modelRuntime,scopedModels,onSelect,onCancel,initialSearchInput,onSelectAsDefault,defaultModel){if(super(),this._focused=!1,this.allModels=[],this.scopedModelItems=[],this.activeModels=[],this.filteredModels=[],this.selectedIndex=0,this.refreshStatusMessage="Refreshing model catalogs\u2026",this.refreshStatusSuccess=!1,this.scope="all",this.refreshAbortController=new AbortController,this.closed=!1,this.tui=tui,this.currentModel=currentModel,this.modelRuntime=modelRuntime,this.scopedModels=scopedModels,this.defaultModel=defaultModel,this.scope=scopedModels.length>0?"scoped":"all",this.onSelectCallback=onSelect,this.onSelectAsDefaultCallback=onSelectAsDefault,this.onCancelCallback=onCancel,this.addChild(new DynamicBorder),this.addChild(new Spacer(1)),scopedModels.length>0)this.scopeText=new Text(this.getScopeText(),0,0),this.addChild(this.scopeText),this.scopeHintText=new Text(this.getScopeHintText(),0,0),this.addChild(this.scopeHintText);else{let hintText="Only showing models from configured providers. Use /login to add providers.";this.addChild(new Text(theme.fg("warning",hintText),0,0))}this.addChild(new Spacer(1)),this.searchInput=new Input,initialSearchInput&&this.searchInput.setValue(initialSearchInput),this.searchInput.onSubmit=()=>{this.filteredModels[this.selectedIndex]&&this.handleSelect(this.filteredModels[this.selectedIndex].model)},this.addChild(this.searchInput),this.addChild(new Spacer(1)),this.listContainer=new Container,this.addChild(this.listContainer),this.addChild(new Spacer(1)),this.onSelectAsDefaultCallback&&this.addChild(new Text(theme.fg("dim",` ${keyDisplayText("tui.select.confirm")} to select \xB7 ${keyDisplayText("app.models.save")} to set as default \xB7 ${keyDisplayText("tui.select.cancel")} to cancel`),0,0)),this.addChild(new DynamicBorder),this.loadModelsFromSnapshot(),initialSearchInput?this.filterModels(initialSearchInput):this.updateList(),this.tui.requestRender(),this.refreshModels()}loadModelsFromSnapshot(){let models=this.modelRuntime.getAvailableSnapshot().map(model=>({provider:model.provider,id:model.id,model}));this.allModels=this.sortModels(models),this.scopedModels=this.scopedModels.map(scoped=>{let refreshed=this.modelRuntime.getModel(scoped.model.provider,scoped.model.id);return refreshed?{...scoped,model:refreshed}:scoped}),this.scopedModelItems=this.scopedModels.map(scoped=>({provider:scoped.model.provider,id:scoped.model.id,model:scoped.model})),this.activeModels=this.scope==="scoped"?this.scopedModelItems:this.allModels,this.filteredModels=this.activeModels;let currentIndex=this.filteredModels.findIndex(item=>modelsAreEqual(this.currentModel,item.model));this.selectedIndex=currentIndex>=0?currentIndex:Math.min(this.selectedIndex,Math.max(0,this.filteredModels.length-1))}async refreshModels(){let timedOut=!1;this.refreshTimeout=setTimeout(()=>{timedOut=!0,this.refreshAbortController.abort()},15e3);try{let result2=await refreshModelCatalogs(this.modelRuntime,this.refreshAbortController.signal);if(this.closed)return;this.refreshStatusMessage="",result2.aborted&&timedOut?this.errorMessage="Model refresh timed out; showing cached models.":result2.errors.size===1?this.errorMessage=`Could not refresh ${result2.errors.keys().next().value}; showing cached models.`:result2.errors.size>1?this.errorMessage=`Could not refresh ${result2.errors.size} model catalogs (${[...result2.errors.keys()].join(", ")}); showing cached models.`:(this.errorMessage=this.modelRuntime.getError(),this.errorMessage||(this.refreshStatusMessage="Model catalogs refreshed.",this.refreshStatusSuccess=!0)),this.loadModelsFromSnapshot(),this.filterModels(this.searchInput.getValue()),this.tui.requestRender()}catch(error){if(this.closed)return;this.refreshStatusMessage="",this.errorMessage=timedOut?"Model refresh timed out; showing cached models.":`Could not refresh model catalogs: ${error instanceof Error?error.message:String(error)}`,this.updateList(),this.tui.requestRender()}finally{this.refreshTimeout&&clearTimeout(this.refreshTimeout)}}dispose(){this.closed||(this.closed=!0,this.refreshTimeout&&clearTimeout(this.refreshTimeout),this.refreshAbortController.abort())}sortModels(models){let sorted=[...models];return sorted.sort((a,b2)=>{let aIsCurrent=modelsAreEqual(this.currentModel,a.model),bIsCurrent=modelsAreEqual(this.currentModel,b2.model);if(aIsCurrent&&!bIsCurrent)return-1;if(!aIsCurrent&&bIsCurrent)return 1;let aIsDefault=this.isDefaultModel(a.model),bIsDefault=this.isDefaultModel(b2.model);return aIsDefault&&!bIsDefault?-1:!aIsDefault&&bIsDefault?1:a.provider.localeCompare(b2.provider)}),sorted}getScopeText(){let allText=this.scope==="all"?theme.fg("accent","all"):theme.fg("muted","all"),scopedText=this.scope==="scoped"?theme.fg("accent","scoped"):theme.fg("muted","scoped");return`${theme.fg("muted","Scope: ")}${allText}${theme.fg("muted"," | ")}${scopedText}`}getScopeHintText(){return keyHint("tui.input.tab","scope")+theme.fg("muted"," (all/scoped)")}isDefaultModel(model){return this.defaultModel?.provider===model.provider&&this.defaultModel.id===model.id}isDefaultSearch(query){let normalized=query.trim().toLowerCase();return normalized.length>0&&"default".startsWith(normalized)}setScope(scope){if(this.scope===scope)return;this.scope=scope,this.activeModels=this.scope==="scoped"?this.scopedModelItems:this.allModels;let currentIndex=this.activeModels.findIndex(item=>modelsAreEqual(this.currentModel,item.model));this.selectedIndex=currentIndex>=0?currentIndex:0,this.filterModels(this.searchInput.getValue()),this.scopeText&&this.scopeText.setText(this.getScopeText())}filterModels(query){if(query){let filtered=fuzzyFilter(this.activeModels,query,item=>{let defaultText=this.isDefaultModel(item.model)?" default":"";return`${getModelSelectorSearchText({id:item.id,provider:item.provider,name:item.model.name})}${defaultText}`});if(this.isDefaultSearch(query)){let defaultItems=this.activeModels.filter(item=>this.isDefaultModel(item.model)),defaultKeys=new Set(defaultItems.map(item=>`${item.provider}\0${item.id}`));this.filteredModels=[...defaultItems,...filtered.filter(item=>!defaultKeys.has(`${item.provider}\0${item.id}`))]}else this.filteredModels=filtered}else this.filteredModels=this.activeModels;this.selectedIndex=query?0:Math.min(this.selectedIndex,Math.max(0,this.filteredModels.length-1)),this.updateList()}updateList(){this.listContainer.clear();let maxVisible=10,startIndex=Math.max(0,Math.min(this.selectedIndex-Math.floor(maxVisible/2),this.filteredModels.length-maxVisible)),endIndex=Math.min(startIndex+maxVisible,this.filteredModels.length);for(let i=startIndex;i<endIndex;i++){let item=this.filteredModels[i];if(!item)continue;let isSelected2=i===this.selectedIndex,isCurrent=modelsAreEqual(this.currentModel,item.model),defaultBadge=this.isDefaultModel(item.model)?theme.fg("muted"," \xB7 default"):"",cursor=isSelected2?theme.fg("accent","\u2192 "):" ",currentMarker=isCurrent?theme.fg("accent","\u2713 "):" ",modelText2=isSelected2?theme.fg("accent",item.id):item.id,providerBadge=theme.fg("muted",`[${item.provider}]`),line=`${cursor}${currentMarker}${modelText2} ${providerBadge}${defaultBadge}`;this.listContainer.addChild(new Text(line,0,0))}if(startIndex>0||endIndex<this.filteredModels.length){let scrollInfo=theme.fg("muted",` (${this.selectedIndex+1}/${this.filteredModels.length})`);this.listContainer.addChild(new Text(scrollInfo,0,0))}if(this.errorMessage){let errorLines=this.errorMessage.split(`
|
|
1784
1784
|
`);for(let line of errorLines)this.listContainer.addChild(new Text(theme.fg("error",line),0,0))}else if(this.filteredModels.length===0)this.listContainer.addChild(new Text(theme.fg("muted"," No matching models"),0,0));else{let selected=this.filteredModels[this.selectedIndex];this.listContainer.addChild(new Spacer(1)),this.listContainer.addChild(new Text(theme.fg("muted",` Model Name: ${selected.model.name}`),0,0))}this.refreshStatusMessage&&(this.listContainer.addChild(new Spacer(1)),this.listContainer.addChild(new Text(theme.fg(this.refreshStatusSuccess?"success":"muted",` ${this.refreshStatusMessage}`),0,0)))}handleInput(keyData){let kb=getKeybindings();if(kb.matches(keyData,"tui.input.tab")){if(this.scopedModelItems.length>0){let nextScope=this.scope==="all"?"scoped":"all";this.setScope(nextScope),this.scopeHintText&&this.scopeHintText.setText(this.getScopeHintText())}return}if(kb.matches(keyData,"tui.select.up")){if(this.filteredModels.length===0)return;this.selectedIndex=this.selectedIndex===0?this.filteredModels.length-1:this.selectedIndex-1,this.updateList()}else if(kb.matches(keyData,"tui.select.down")){if(this.filteredModels.length===0)return;this.selectedIndex=this.selectedIndex===this.filteredModels.length-1?0:this.selectedIndex+1,this.updateList()}else if(kb.matches(keyData,"tui.select.confirm")){let selectedModel=this.filteredModels[this.selectedIndex];selectedModel&&this.handleSelect(selectedModel.model)}else if(kb.matches(keyData,"tui.select.cancel"))this.dispose(),this.onCancelCallback();else if(kb.matches(keyData,"app.models.save")&&this.onSelectAsDefaultCallback){let selectedModel=this.filteredModels[this.selectedIndex];selectedModel&&(this.dispose(),this.onSelectAsDefaultCallback(selectedModel.model))}else this.searchInput.handleInput(keyData),this.filterModels(this.searchInput.getValue())}handleSelect(model){this.dispose(),this.onSelectCallback(model)}getSearchInput(){return this.searchInput}};function formatAuthSelectorProviderType(authType,subscription){return authType==="api_key"?"API key":subscription===!1?"account":"subscription"}function formatAuthSelectorProviderStatus(provider){if(!provider.status)return theme.fg("muted"," \u2022 not configured");if(provider.status.type!==provider.authType){let label=`${formatAuthSelectorProviderType(provider.status.type,provider.subscription)} configured`;return theme.fg("muted"," \u2022 ")+theme.fg("warning",label)}if(!provider.status.source||provider.status.source==="OAuth"||provider.status.source==="stored credential")return theme.fg("success"," \u2713 configured");let source=/^[A-Z][A-Z0-9_]*(?:, [A-Z][A-Z0-9_]*)*$/.test(provider.status.source)?`env: ${provider.status.source}`:provider.status.source;return theme.fg("success",` \u2713 ${source}`)}var OAuthSelectorComponent=class extends Container{get focused(){return this._focused}set focused(value){this._focused=value,this.searchInput.focused=value}constructor(mode,providers,onSelect,onCancel,initialSearchInput){super(),this._focused=!1,this.selectedIndex=0,this.mode=mode,this.allProviders=providers,this.filteredProviders=providers,this.showAuthTypeLabels=new Set(providers.map(provider=>provider.authType)).size>1,this.onSelectCallback=onSelect,this.onCancelCallback=onCancel,this.addChild(new DynamicBorder),this.addChild(new Spacer(1));let title=mode==="login"?"Select provider to configure:":"Select provider to logout:";this.addChild(new TruncatedText(theme.fg("accent",theme.bold(title)),1,0)),this.addChild(new Spacer(1)),this.searchInput=new Input,initialSearchInput&&this.searchInput.setValue(initialSearchInput),this.searchInput.onSubmit=()=>{let selectedProvider=this.filteredProviders[this.selectedIndex];selectedProvider&&this.onSelectCallback(selectedProvider.id,selectedProvider.authType)},this.addChild(this.searchInput),this.addChild(new Spacer(1)),this.listContainer=new Container,this.addChild(this.listContainer),this.addChild(new Spacer(1)),this.addChild(new DynamicBorder),this.filterProviders(initialSearchInput??"")}filterProviders(query){this.filteredProviders=query?fuzzyFilter(this.allProviders,query,provider=>`${provider.name} ${provider.id} ${provider.authType} ${provider.method?.name??""}`):this.allProviders,this.selectedIndex=Math.max(0,Math.min(this.selectedIndex,Math.max(0,this.filteredProviders.length-1))),this.updateList()}updateList(){this.listContainer.clear();let maxVisible=8,startIndex=Math.max(0,Math.min(this.selectedIndex-Math.floor(maxVisible/2),this.filteredProviders.length-maxVisible)),endIndex=Math.min(startIndex+maxVisible,this.filteredProviders.length);for(let i=startIndex;i<endIndex;i++){let provider=this.filteredProviders[i];if(!provider)continue;let isSelected2=i===this.selectedIndex,statusIndicator=formatAuthSelectorProviderStatus(provider),authTypeLabel=this.showAuthTypeLabels?theme.fg("muted",` [${formatAuthSelectorProviderType(provider.authType,provider.subscription)}]`):"",line="";if(isSelected2){let prefix=theme.fg("accent","\u2192 "),text2=theme.fg("accent",provider.name);line=prefix+text2+authTypeLabel+statusIndicator}else line=` ${theme.fg("text",provider.name)}`+authTypeLabel+statusIndicator;this.listContainer.addChild(new TruncatedText(line,1,0))}if(startIndex>0||endIndex<this.filteredProviders.length){let scrollInfo=theme.fg("muted",` (${this.selectedIndex+1}/${this.filteredProviders.length})`);this.listContainer.addChild(new TruncatedText(scrollInfo,1,0))}if(this.filteredProviders.length===0){let message=this.allProviders.length===0?this.mode==="login"?"No providers available":"No providers logged in. Use /login first.":"No matching providers";this.listContainer.addChild(new TruncatedText(theme.fg("muted",` ${message}`),1,0))}}handleInput(keyData){let kb=getKeybindings();if(kb.matches(keyData,"tui.select.up")){if(this.filteredProviders.length===0)return;this.selectedIndex=Math.max(0,this.selectedIndex-1),this.updateList()}else if(kb.matches(keyData,"tui.select.down")){if(this.filteredProviders.length===0)return;this.selectedIndex=Math.min(this.filteredProviders.length-1,this.selectedIndex+1),this.updateList()}else if(kb.matches(keyData,"tui.select.confirm")){let selectedProvider=this.filteredProviders[this.selectedIndex];selectedProvider&&this.onSelectCallback(selectedProvider.id,selectedProvider.authType)}else kb.matches(keyData,"tui.select.cancel")?this.onCancelCallback():(this.searchInput.handleInput(keyData),this.filterProviders(this.searchInput.getValue()))}};var SUBMENU_SELECT_LIST_LAYOUT={minPrimaryColumnWidth:12,maxPrimaryColumnWidth:32},SelectSubmenu=class extends Container{constructor(title,description,options,currentValue,onSelect,onCancel,onSelectionChange,submenuOptions){super(),this.allOptions=options,this.listLayout=submenuOptions?.layout??SUBMENU_SELECT_LIST_LAYOUT,this.onSelectCb=onSelect,this.onCancelCb=onCancel,this.onSelectionChangeCb=onSelectionChange,this.addChild(new Text(theme.bold(theme.fg("accent",title)),0,0)),description&&(this.addChild(new Spacer(1)),this.addChild(new Text(theme.fg("muted",description),0,0))),submenuOptions?.searchable&&(this.addChild(new Spacer(1)),this.searchInput=new Input,this.searchInput.onSubmit=()=>{this.selectList.handleInput("\r")},this.addChild(this.searchInput)),this.addChild(new Spacer(1)),this.selectList=this.buildSelectList(options,currentValue),this.listChildIndex=this.children.length,this.addChild(this.selectList),this.addChild(new Spacer(1));let hint=submenuOptions?.searchable?" Type to filter \xB7 Enter to select \xB7 Esc to go back":" Enter to select \xB7 Esc to go back";this.addChild(new Text(theme.fg("dim",hint),0,0))}buildSelectList(options,preselect){let list2=new SelectList(options,Math.min(options.length,10),getSelectListTheme(),this.listLayout),idx=options.findIndex(o=>o.value===preselect);if(idx!==-1&&list2.setSelectedIndex(idx),list2.onSelect=item=>this.onSelectCb(item.value),list2.onCancel=this.onCancelCb,this.onSelectionChangeCb){let cb=this.onSelectionChangeCb;list2.onSelectionChange=item=>cb(item.value)}return list2}applyFilter(query){let filtered=query?fuzzyFilter(this.allOptions,query,item=>`${item.label} ${item.description??""}`):this.allOptions,newList=this.buildSelectList(filtered,"");this.children[this.listChildIndex]=newList,this.selectList=newList}handleInput(data){if(this.searchInput){let kb=getKeybindings();kb.matches(data,"tui.select.up")||kb.matches(data,"tui.select.down")||kb.matches(data,"tui.select.confirm")||kb.matches(data,"tui.select.cancel")?this.selectList.handleInput(data):(this.searchInput.handleInput(data),this.applyFilter(this.searchInput.getValue()))}else this.selectList.handleInput(data)}},SteppedSubmenu=class extends Container{constructor(steps,onComplete,onCancel,opts={}){super(),this.steps=steps,this.onComplete=onComplete,this.onCancel=onCancel,this.opts=opts,this.context={...opts.initialContext??{}},this.activeComponent=this.buildStep(opts.startAtStep??0)}buildStep(stepIndex){let step=this.steps[stepIndex],total=this.steps.length,stepLabel=total>1?`Step ${stepIndex+1}/${total} \xB7 `:"",title=typeof step.title=="function"?step.title(this.context):step.title,desc=typeof step.description=="function"?step.description(this.context):step.description,items=step.options(this.context),preselect=step.preselect?.(this.context)??"";return new SelectSubmenu(title,`${stepLabel}${desc}`,items,preselect,value=>{this.context[step.key]=value,stepIndex<total-1?this.activeComponent=this.buildStep(stepIndex+1):(this.onComplete({...this.context}),this.opts.loop?(this.context={},this.activeComponent=this.buildStep(0)):this.onCancel())},()=>{stepIndex>0?(delete this.context[step.key],this.activeComponent=this.buildStep(stepIndex-1)):this.onCancel()},void 0,step.searchable||step.layout?{searchable:step.searchable,layout:step.layout}:void 0)}render(width){return this.activeComponent.render(width)}handleInput(data){this.activeComponent.handleInput?.(data)}invalidate(){this.activeComponent.invalidate?.()}};var MODEL_PICKER_LAYOUT={minPrimaryColumnWidth:12,maxPrimaryColumnWidth:46},THINKING_DESCRIPTIONS={off:"No reasoning",minimal:"Very brief reasoning (~1k tokens)",low:"Light reasoning (~2k tokens)",medium:"Moderate reasoning (~8k tokens)",high:"Deep reasoning (~16k tokens)",xhigh:"Extra-high reasoning (~32k tokens)",max:"Maximum reasoning"},DEFAULT_PROJECT_TRUST_LABELS={ask:"Ask",always:"Always trust",never:"Never trust"},DEFAULT_PROJECT_TRUST_BY_LABEL=new Map(Object.entries(DEFAULT_PROJECT_TRUST_LABELS).map(([value,label])=>[label,value])),WarningSettingsSubmenu=class extends Container{constructor(warnings,onChange,onCancel){super(),this.state={...warnings};let items=[{id:"anthropic-extra-usage",label:"Anthropic extra usage",description:"Warn when Anthropic subscription auth may use paid extra usage",currentValue:this.state.anthropicExtraUsage??SETTINGS_DEFAULTS.warnings.anthropicExtraUsage?"true":"false",values:["true","false"]}];this.settingsList=new SettingsList(items,Math.min(items.length,10),getSettingsListTheme(),(id,newValue)=>{id==="anthropic-extra-usage"&&(this.state={...this.state,anthropicExtraUsage:newValue==="true"},onChange({...this.state}))},onCancel),this.addChild(this.settingsList)}handleInput(data){this.settingsList.handleInput(data)}},CLEAR_OVERRIDE_VALUE="__clear__";function modelSettingKey(model){return`${model.provider}/${model.id}`}function modelDisplayLabel(model){return`${model.id} [${model.provider}]`}function modelThinkingOverridesSummary(overrides){let count=Object.keys(overrides).length;return count===0?"none":`${count} configured`}function modelItemLabel(model){return`${model.id} ${theme.fg("muted",`[${model.provider}]`)}`}function themeItems(availableThemes,currentTheme){return availableThemes.map(name=>({value:name,label:`${name===currentTheme?"\u2713 ":" "}${name}`,...name===SYSTEM_THEME_NAME?{description:"Theme created from your terminal's colors"}:{}}))}var AUTOMATIC_THEME_VALUE="/";function singleModeThemeItems(availableThemes,currentTheme){let items=themeItems(availableThemes,currentTheme),systemIndex=items.findIndex(item=>item.value===SYSTEM_THEME_NAME);return[...systemIndex===-1?[]:items.splice(systemIndex,1),{value:AUTOMATIC_THEME_VALUE,label:" automatic",description:"Use separate themes for light and dark terminal appearance"},...items]}function preferredTheme(availableThemes,preferred,fallback){return preferred&&availableThemes.includes(preferred)?preferred:availableThemes.includes(fallback)?fallback:availableThemes[0]??fallback}function defaultAutomaticThemes(currentThemeSetting,availableThemes){let autoTheme=parseAutoThemeSetting(currentThemeSetting);if(autoTheme)return autoTheme;let currentFixedTheme=currentThemeSetting.includes("/")?void 0:currentThemeSetting,themeName=preferredTheme(availableThemes,currentFixedTheme,SYSTEM_THEME_NAME);return{lightTheme:themeName,darkTheme:themeName}}var ThemeSubmenu=class extends Container{constructor(currentThemeSetting,terminalTheme,availableThemes,callbacks,onDone){super(),this.callbacks=callbacks,this.availableThemes=availableThemes,this.terminalTheme=terminalTheme,this.onDone=onDone,this.originalThemeSetting=currentThemeSetting;let autoTheme=parseAutoThemeSetting(currentThemeSetting),automaticThemes=defaultAutomaticThemes(currentThemeSetting,availableThemes),fixedTheme=autoTheme||currentThemeSetting.includes("/")?void 0:currentThemeSetting;this.mode=autoTheme?"automatic":"single",this.lightTheme=automaticThemes.lightTheme,this.darkTheme=automaticThemes.darkTheme,this.singleTheme=preferredTheme(availableThemes,fixedTheme??(autoTheme?this.getActiveAutomaticTheme():void 0),SYSTEM_THEME_NAME),this.mode==="automatic"?this.showAutomaticMenu():this.showSingleMenu()}handleInput(data){this.inputComponent?.handleInput?.(data)}setContent(renderComponent,inputComponent=renderComponent){this.clear(),this.addChild(renderComponent),this.inputComponent=inputComponent}showSingleMenu(){this.mode="single";let menu=new SelectSubmenu("Theme","Select a theme, or choose automatic to follow terminal appearance.",singleModeThemeItems(this.availableThemes,this.singleTheme),this.singleTheme,value=>{if(value===AUTOMATIC_THEME_VALUE){this.mode="automatic",this.callbacks.onThemePreview?.(this.getThemeSetting()),this.showAutomaticMenu();return}this.singleTheme=value,this.apply(value)},()=>this.cancel(),value=>{this.callbacks.onThemePreview?.(value===AUTOMATIC_THEME_VALUE?this.getAutomaticThemeSetting():value)});this.setContent(menu)}showAutomaticMenu(){this.mode="automatic";let content=new Container;content.addChild(new Text(theme.bold(theme.fg("accent","Automatic Theme")),0,0)),content.addChild(new Spacer(1)),content.addChild(new Text(theme.fg("muted","Choose themes for terminal light and dark appearance."),0,0)),content.addChild(new Text(theme.fg("muted","Light/dark detection requires terminal support."),0,0)),content.addChild(new Spacer(1));let items=[{id:"light-theme",label:"Light theme",description:"Theme to use in automatic mode when the terminal is light",currentValue:this.lightTheme,submenu:(currentValue,done)=>this.createThemeSelect("Light Theme","Select the theme to use for light terminal appearance",currentValue,done,value=>{this.lightTheme=value,this.callbacks.onThemePreview?.(this.getThemeSetting()),done(value)})},{id:"dark-theme",label:"Dark theme",description:"Theme to use in automatic mode when the terminal is dark",currentValue:this.darkTheme,submenu:(currentValue,done)=>this.createThemeSelect("Dark Theme","Select the theme to use for dark terminal appearance",currentValue,done,value=>{this.darkTheme=value,this.callbacks.onThemePreview?.(this.getThemeSetting()),done(value)})},{id:"apply",label:"Apply",description:"Save and go back",currentValue:"save and go back",values:["save and go back"]},{id:"single-mode",label:"Change mode",description:"Switch to one theme for light and dark",currentValue:"switch to single theme",values:["switch to single theme"]}],settingsList=new SettingsList(items,Math.min(items.length,10),getSettingsListTheme(),id=>{switch(id){case"single-mode":this.mode="single",this.singleTheme=this.getActiveAutomaticTheme(),this.callbacks.onThemePreview?.(this.singleTheme),this.showSingleMenu();break;case"apply":this.apply(this.getAutomaticThemeSetting());break}},()=>this.cancel());content.addChild(settingsList),this.setContent(content,settingsList)}createThemeSelect(title,description,currentValue,done,onSelect){return new SelectSubmenu(title,description,themeItems(this.availableThemes,currentValue),currentValue,onSelect,()=>{this.callbacks.onThemePreview?.(this.getThemeSetting()),done()},value=>this.callbacks.onThemePreview?.(value))}getThemeSetting(){return this.mode==="automatic"?this.getAutomaticThemeSetting():this.singleTheme}getActiveAutomaticTheme(){return this.terminalTheme==="light"?this.lightTheme:this.darkTheme}getAutomaticThemeSetting(){return`${this.lightTheme}/${this.darkTheme}`}apply(themeSetting){this.onDone(themeSetting)}cancel(){this.callbacks.onThemePreview?.(this.originalThemeSetting),this.onDone()}},SettingsSelectorComponent=class extends Container{constructor(config,callbacks){super();let supportsImages=getCapabilities().images,followUpKey=keyDisplayText("app.message.followUp"),cycleThinkingKey=keyDisplayText("app.thinking.cycle"),currentWarnings={...config.warnings},currentModelThinkingLevels={...config.modelThinkingLevels},defaultModelByValue=new Map(config.availableDefaultModels.map(model=>[modelSettingKey(model),model])),currentDefaultModelKey=defaultModelByValue.has(config.defaultModel)?config.defaultModel:void 0,currentModelKey=config.currentModel?modelSettingKey(config.currentModel):void 0,items=[{id:"autocompact",label:"Auto-compact",description:"Automatically compact context when it gets too large",currentValue:config.autoCompact?"true":"false",values:["true","false"]},{id:"steering-mode",label:"Steering mode",description:"Enter while streaming queues steering messages. 'one-at-a-time': deliver one, wait for response. 'all': deliver all at once.",currentValue:config.steeringMode,values:["one-at-a-time","all"]},{id:"follow-up-mode",label:"Follow-up mode",description:`${followUpKey} queues follow-up messages until agent stops. 'one-at-a-time': deliver one, wait for response. 'all': deliver all at once.`,currentValue:config.followUpMode,values:["one-at-a-time","all"]},{id:"transport",label:"Transport",description:"Preferred transport for providers that support multiple transports",currentValue:config.transport,values:["sse","websocket","websocket-cached","auto"]},{id:"share-destination",label:"Session share destination",description:"Where to upload sessions with /share (auto prefers Radius when authenticated, otherwise GitHub Gist)",currentValue:config.sessionShareDestination,values:["auto","gist","radius"]},{id:"http-idle-timeout",label:"HTTP idle timeout",description:"Maximum idle gap while waiting for HTTP headers or body chunks. Disable for local models that pause longer than five minutes.",currentValue:formatHttpIdleTimeoutMs(config.httpIdleTimeoutMs),values:HTTP_IDLE_TIMEOUT_CHOICES.map(choice=>choice.label)},{id:"cache-warming-mode",label:"Cache warming",description:"off; streaming while the agent runs; idle also between runs while continuation stays profitable",currentValue:config.cacheWarmingMode,values:[...CACHE_WARMING_MODES]},{id:"hide-thinking",label:"Hide thinking",description:"Hide thinking blocks in assistant responses",currentValue:config.hideThinkingBlock?"true":"false",values:["true","false"]},{id:"mermaid-rendering",label:"Mermaid diagrams",description:"Render Mermaid code blocks as Unicode diagrams",currentValue:config.mermaidRenderingMode,values:["off","final","streaming"]},{id:"cache-miss-notices",label:"Cache miss notices",description:"Show transcript notices for cache costs and provider recovery diagnostics",currentValue:config.showCacheMissNotices?"true":"false",values:["true","false"]},{id:"collapse-changelog",label:"Collapse changelog",description:"Show condensed changelog after updates",currentValue:config.collapseChangelog?"true":"false",values:["true","false"]},{id:"quiet-startup",label:"Quiet startup",description:"Disable verbose printing at startup (header: keep only the startup header)",currentValue:String(config.quietStartup),values:["true","header","false"]},{id:"install-telemetry",label:"Provider attribution",description:"Send optional provider attribution headers for supported services",currentValue:config.enableInstallTelemetry?"true":"false",values:["true","false"]},{id:"default-project-trust",label:"Default project trust",description:"Fallback behavior when no extension or saved trust decision decides project trust",currentValue:DEFAULT_PROJECT_TRUST_LABELS[config.defaultProjectTrust],values:Object.values(DEFAULT_PROJECT_TRUST_LABELS)},{id:"double-escape-action",label:"Double-escape action",description:"Action when pressing Escape twice with empty editor",currentValue:config.doubleEscapeAction,values:["tree","fork","none"]},{id:"tree-filter-mode",label:"Tree filter mode",description:"Default filter when opening /tree",currentValue:config.treeFilterMode,values:["default","no-tools","user-only","labeled-only","all"]},{id:"warnings",label:"Warnings",description:"Enable or disable individual warnings",currentValue:"configure",submenu:(_currentValue,done)=>new WarningSettingsSubmenu(currentWarnings,warnings=>{currentWarnings=warnings,callbacks.onWarningsChange(warnings)},()=>done())},{id:"model-thinking",label:"Default thinking level per model",description:`Override the default thinking level for specific models. ${cycleThinkingKey} cycles in-session.`,currentValue:modelThinkingOverridesSummary(currentModelThinkingLevels),submenu:(_currentValue,done)=>{let steps=[{key:"model",title:"Per-Model Thinking Level",description:"Select a model to configure",options:()=>{let items2=[...config.availableDefaultModels].sort((a,b2)=>{let aKey=modelSettingKey(a),bKey=modelSettingKey(b2);return aKey===currentModelKey?-1:bKey===currentModelKey?1:aKey===currentDefaultModelKey?-1:bKey===currentDefaultModelKey?1:a.provider.localeCompare(b2.provider)}).map(model=>{let key=modelSettingKey(model),override=currentModelThinkingLevels[key];return{value:key,label:modelItemLabel(model),description:override??void 0}});return items2.length===0&&items2.push({value:"__none__",label:"No models available",description:"Log in to a provider or configure an API key first"}),items2},preselect:()=>currentModelKey??currentDefaultModelKey,searchable:!0,layout:MODEL_PICKER_LAYOUT},{key:"level",title:ctx=>{let m2=defaultModelByValue.get(ctx.model);return`Thinking Level for ${m2?modelDisplayLabel(m2):ctx.model}`},description:"Select default thinking level for this model",options:ctx=>{let model=defaultModelByValue.get(ctx.model);if(!model)return[];let levels=model.reasoning?getSupportedThinkingLevels(model):["off"],activeLevel=currentModelThinkingLevels[ctx.model],items2=levels.map(level=>({value:level,label:`${level===activeLevel?"\u2713 ":" "}${level}`,description:THINKING_DESCRIPTIONS[level]}));return currentModelThinkingLevels[ctx.model]!==void 0&&items2.push({value:CLEAR_OVERRIDE_VALUE,label:" (clear override)",description:`Revert to global default (${config.thinkingLevel})`}),items2},preselect:ctx=>currentModelThinkingLevels[ctx.model]}],summary=()=>modelThinkingOverridesSummary(currentModelThinkingLevels);return new SteppedSubmenu(steps,selections=>{let model=defaultModelByValue.get(selections.model);model&&(selections.level===CLEAR_OVERRIDE_VALUE?(callbacks.onModelThinkingLevelRemove(model.provider,model.id),delete currentModelThinkingLevels[selections.model]):(callbacks.onModelThinkingLevelChange(model.provider,model.id,selections.level),currentModelThinkingLevels[selections.model]=selections.level))},()=>{done(summary())},{loop:!0})}},{id:"tui-mode",label:"TUI mode",description:"Interface layout; regular mode uses the terminal's normal scrollback",currentValue:config.tuiMode,values:["regular","fullscreen"]},{id:"fullscreen-exit-output",label:"Fullscreen exit output",description:"Print the transcript or only a session resume hint when exiting fullscreen mode",currentValue:config.fullscreenExitOutput,values:["transcript","resume-hint"]},{id:"fullscreen-scrollbar",label:"Fullscreen scrollbar",description:"Scrollbar behavior in fullscreen mode; has no effect in regular mode",currentValue:config.fullscreenScrollbar,values:["auto","always","hidden"]},{id:"fullscreen-copy-on-select",label:"Fullscreen copy on select",description:"Automatically copy selected text in fullscreen mode; disable to copy selections with Ctrl+X",currentValue:config.fullscreenCopyOnSelect?"true":"false",values:["true","false"]},{id:"fullscreen-wheel-scroll-lines",label:"Fullscreen wheel scrolling",description:"Lines per mouse-wheel event in fullscreen mode; 'auto' speeds up fast wheel spins where the terminal does not",currentValue:String(config.fullscreenWheelScrollLines),values:["auto",...[...new Set([1,2,3,5,10,config.fullscreenWheelScrollLines])].filter(lines=>lines!=="auto").sort((a,b2)=>a-b2).map(String)]},{id:"theme",label:"Theme",description:"Color theme for the interface",currentValue:config.currentTheme,submenu:(currentValue,done)=>new ThemeSubmenu(currentValue,config.terminalTheme,config.availableThemes,callbacks,done)}];supportsImages&&(items.splice(1,0,{id:"show-images",label:"Show images",description:"Render images inline in terminal",currentValue:config.showImages?"true":"false",values:["true","false"]}),items.splice(2,0,{id:"image-width-cells",label:"Image width",description:"Preferred inline image width in terminal cells",currentValue:String(config.imageWidthCells),values:["60","80","120"]})),items.splice(supportsImages?3:1,0,{id:"auto-resize-images",label:"Auto-resize images",description:"Resize large images to 2000x2000 max for better model compatibility",currentValue:config.autoResizeImages?"true":"false",values:["true","false"]});let autoResizeIndex=items.findIndex(item=>item.id==="auto-resize-images");items.splice(autoResizeIndex+1,0,{id:"block-images",label:"Block images",description:"Prevent images from being sent to LLM providers",currentValue:config.blockImages?"true":"false",values:["true","false"]});let blockImagesIndex=items.findIndex(item=>item.id==="block-images");items.splice(blockImagesIndex+1,0,{id:"skill-commands",label:"Skill commands",description:"Register skills as /skill:name commands",currentValue:config.enableSkillCommands?"true":"false",values:["true","false"]});let skillCommandsIndex=items.findIndex(item=>item.id==="skill-commands");items.splice(skillCommandsIndex+1,0,{id:"show-hardware-cursor",label:"Show hardware cursor",description:"Use the terminal cursor instead of Pi's drawn cursor",currentValue:config.showHardwareCursor?"true":"false",values:["true","false"]});let hardwareCursorIndex=items.findIndex(item=>item.id==="show-hardware-cursor");items.splice(hardwareCursorIndex+1,0,{id:"editor-padding",label:"Editor padding",description:"Horizontal padding for input editor (0-3)",currentValue:String(config.editorPaddingX),values:["0","1","2","3"]});let editorPaddingIndex=items.findIndex(item=>item.id==="editor-padding");items.splice(editorPaddingIndex+1,0,{id:"output-padding",label:"Output padding",description:"Horizontal padding for messages, tool output, and command output",currentValue:String(config.outputPad),values:["0","1"]});let outputPaddingIndex=items.findIndex(item=>item.id==="output-padding");items.splice(outputPaddingIndex+1,0,{id:"autocomplete-max-visible",label:"Autocomplete max items",description:"Max visible items in autocomplete dropdown (3-20)",currentValue:String(config.autocompleteMaxVisible),values:["3","5","7","10","15","20"]});let autocompleteIndex=items.findIndex(item=>item.id==="autocomplete-max-visible");items.splice(autocompleteIndex+1,0,{id:"clear-on-shrink",label:"Clear on shrink",description:"Clear empty rows when content shrinks (may cause flicker)",currentValue:config.clearOnShrink?"true":"false",values:["true","false"]});let clearOnShrinkIndex=items.findIndex(item=>item.id==="clear-on-shrink");items.splice(clearOnShrinkIndex+1,0,{id:"terminal-progress",label:"Terminal progress",description:"Show OSC 9;4 progress indicators in the terminal tab bar",currentValue:config.showTerminalProgress?"true":"false",values:["true","false"]}),this.addChild(new DynamicBorder),this.settingsList=new SettingsList(items,10,getSettingsListTheme(),(id,newValue)=>{switch(id){case"autocompact":callbacks.onAutoCompactChange(newValue==="true");break;case"show-images":callbacks.onShowImagesChange(newValue==="true");break;case"image-width-cells":callbacks.onImageWidthCellsChange(parseInt(newValue,10));break;case"auto-resize-images":callbacks.onAutoResizeImagesChange(newValue==="true");break;case"block-images":callbacks.onBlockImagesChange(newValue==="true");break;case"skill-commands":callbacks.onEnableSkillCommandsChange(newValue==="true");break;case"steering-mode":callbacks.onSteeringModeChange(newValue);break;case"follow-up-mode":callbacks.onFollowUpModeChange(newValue);break;case"transport":callbacks.onTransportChange(newValue);break;case"share-destination":callbacks.onSessionShareDestinationChange(newValue);break;case"http-idle-timeout":{let choice=HTTP_IDLE_TIMEOUT_CHOICES.find(item=>item.label===newValue);choice&&callbacks.onHttpIdleTimeoutMsChange(choice.timeoutMs);break}case"cache-warming-mode":callbacks.onCacheWarmingModeChange(newValue);break;case"hide-thinking":callbacks.onHideThinkingBlockChange(newValue==="true");break;case"mermaid-rendering":callbacks.onMermaidRenderingModeChange(newValue);break;case"cache-miss-notices":callbacks.onShowCacheMissNoticesChange(newValue==="true");break;case"collapse-changelog":callbacks.onCollapseChangelogChange(newValue==="true");break;case"quiet-startup":callbacks.onQuietStartupChange(newValue==="header"?"header":newValue==="true");break;case"install-telemetry":callbacks.onEnableInstallTelemetryChange(newValue==="true");break;case"default-project-trust":{let defaultProjectTrust=DEFAULT_PROJECT_TRUST_BY_LABEL.get(newValue);defaultProjectTrust&&callbacks.onDefaultProjectTrustChange(defaultProjectTrust);break}case"double-escape-action":callbacks.onDoubleEscapeActionChange(newValue);break;case"tree-filter-mode":callbacks.onTreeFilterModeChange(newValue);break;case"show-hardware-cursor":callbacks.onShowHardwareCursorChange(newValue==="true");break;case"editor-padding":callbacks.onEditorPaddingXChange(parseInt(newValue,10));break;case"output-padding":callbacks.onOutputPadChange(newValue==="0"?0:1);break;case"autocomplete-max-visible":callbacks.onAutocompleteMaxVisibleChange(parseInt(newValue,10));break;case"clear-on-shrink":callbacks.onClearOnShrinkChange(newValue==="true");break;case"terminal-progress":callbacks.onShowTerminalProgressChange(newValue==="true");break;case"tui-mode":callbacks.onTuiModeChange(newValue);break;case"fullscreen-exit-output":callbacks.onFullscreenExitOutputChange(newValue);break;case"fullscreen-scrollbar":callbacks.onFullscreenScrollbarChange(newValue);break;case"fullscreen-copy-on-select":callbacks.onFullscreenCopyOnSelectChange(newValue==="true");break;case"fullscreen-wheel-scroll-lines":callbacks.onFullscreenWheelScrollLinesChange(newValue==="auto"?"auto":parseInt(newValue,10));break;case"theme":callbacks.onThemeChange(newValue);break}},callbacks.onCancel,{enableSearch:!0}),this.addChild(this.settingsList),this.addChild(new DynamicBorder)}getSettingsList(){return this.settingsList}};var SkillInvocationMessageComponent=class extends Box{constructor(skillBlock,markdownTheme=getMarkdownTheme(),outputPad=1){super(outputPad,1,t=>theme.bg("customMessageBg",t)),this.expanded=!1,this.skillBlock=skillBlock,this.markdownTheme=markdownTheme,this.updateDisplay()}setExpanded(expanded){this.expanded=expanded,this.updateDisplay()}setOutputPad(outputPad){this.setPaddingX(outputPad)}invalidate(){super.invalidate(),this.updateDisplay()}updateDisplay(){this.clear();let content=new Container;if(this.expanded){let label=theme.fg("customMessageLabel","\x1B[1m[skill]\x1B[22m");content.addChild(new Text(label,0,0));let header2=`**${this.skillBlock.name}**
|
|
1785
1785
|
|
|
1786
|
-
`;content.addChild(new Markdown(header2+this.skillBlock.content,0,0,this.markdownTheme,{color:text2=>theme.fg("customMessageText",text2)}))}else{let line=theme.fg("customMessageLabel","\x1B[1m[skill]\x1B[22m ")+theme.fg("customMessageText",this.skillBlock.name)+theme.fg("dim",` (${keyText("app.tools.expand")} to expand)`);content.addChild(new Text(line,0,0))}this.addChild(new MouseRegion(content,event=>{if(!(event.type!=="click"||event.button!=="left"))return this.setExpanded(!this.expanded),{handled:!0}}))}};var THINKING_SELECT_LIST_LAYOUT={minPrimaryColumnWidth:12,maxPrimaryColumnWidth:32},LEVEL_DESCRIPTIONS={off:"No reasoning",minimal:"Very brief reasoning (~1k tokens)",low:"Light reasoning (~2k tokens)",medium:"Moderate reasoning (~8k tokens)",high:"Deep reasoning (~16k tokens)",xhigh:"Extra-high reasoning (~32k tokens)",max:"Maximum reasoning"},ThinkingSelectorComponent=class extends Container{get focused(){return this._focused}set focused(value){this._focused=value,this.searchInput.focused=value}constructor(currentLevel,availableLevels,onSelect,onCancel,onSelectAsDefault,defaultThinkingLevel){super(),this._focused=!1,this.onSelect=onSelect,this.onCancel=onCancel,this.onSelectAsDefault=onSelectAsDefault,this.allItems=availableLevels.map(level=>({value:level,label:`${level===currentLevel?"\u2713 ":" "}${level}`,description:level===defaultThinkingLevel?`${LEVEL_DESCRIPTIONS[level]} \xB7 default`:LEVEL_DESCRIPTIONS[level]})),this.addChild(new DynamicBorder),this.addChild(new Spacer(1)),this.addChild(new Text("Thinking Level",0,0)),this.addChild(new Spacer(1)),this.addChild(new Text(`${keyDisplayText("app.thinking.cycle")} cycles thinking levels in-session`,0,0)),this.addChild(new Spacer(1)),this.searchInput=new Input,this.searchInput.onSubmit=()=>this.selectList.handleInput("\r"),this.addChild(this.searchInput),this.addChild(new Spacer(1)),this.selectList=this.buildSelectList(this.allItems,currentLevel),this.selectListChildIndex=this.children.length,this.addChild(this.selectList),this.addChild(new Spacer(1)),this.addChild(new Text(theme.fg("dim",` ${keyDisplayText("tui.select.confirm")} to select \xB7 ${keyDisplayText("app.thinking.save")} to set as default \xB7 ${keyDisplayText("tui.select.cancel")} to cancel`),0,0)),this.addChild(new DynamicBorder)}buildSelectList(items,preselect){let list2=new SelectList(items,Math.max(1,items.length),getSelectListTheme(),THINKING_SELECT_LIST_LAYOUT),currentIndex=items.findIndex(item=>item.value===preselect);return currentIndex!==-1&&list2.setSelectedIndex(currentIndex),list2.onSelect=item=>this.onSelect(item.value),list2.onCancel=()=>this.onCancel(),list2}applyFilter(query){let filtered=query?fuzzyFilter(this.allItems,query,item=>`${item.value} ${item.description??""}`):this.allItems,selectedValue=this.selectList.getSelectedItem()?.value,newList=this.buildSelectList(filtered,selectedValue);this.children[this.selectListChildIndex]=newList,this.selectList=newList}handleInput(keyData){let kb=getKeybindings();if(kb.matches(keyData,"app.thinking.save")&&this.onSelectAsDefault){let item=this.selectList.getSelectedItem();item&&this.onSelectAsDefault(item.value);return}if(kb.matches(keyData,"tui.select.up")||kb.matches(keyData,"tui.select.down")||kb.matches(keyData,"tui.select.confirm")||kb.matches(keyData,"tui.select.cancel")){this.selectList.handleInput(keyData);return}this.searchInput.handleInput(keyData),this.applyFilter(this.searchInput.getValue())}getSelectList(){return this.selectList}};var TREE_GUTTER_WIDTH=2,MIN_VISIBLE_ANCHOR_CONTENT_WIDTH=4,MAX_VISIBLE_ANCHOR_CONTENT_WIDTH=20,MIN_ANCHOR_CONTEXT_WIDTH=2,MAX_ANCHOR_CONTEXT_WIDTH=12;function renderHorizontalViewport(rows,width){let viewportWidth=Math.max(0,width-TREE_GUTTER_WIDTH),maxBodyWidth=rows.reduce((max,row)=>Math.max(max,row.bodyWidth),0),maxHorizontalScroll=Math.max(0,maxBodyWidth-viewportWidth),selectedRow=rows.find(row=>row.isSelected),horizontalScroll=0;if(selectedRow&&maxHorizontalScroll>0){let minVisibleAnchorContentWidth=Math.min(MAX_VISIBLE_ANCHOR_CONTENT_WIDTH,Math.max(MIN_VISIBLE_ANCHOR_CONTENT_WIDTH,Math.floor(viewportWidth/3)));if(selectedRow.anchorCol>viewportWidth-minVisibleAnchorContentWidth){let anchorContextWidth=Math.min(MAX_ANCHOR_CONTEXT_WIDTH,Math.max(MIN_ANCHOR_CONTEXT_WIDTH,Math.floor(viewportWidth/4)));horizontalScroll=Math.min(maxHorizontalScroll,selectedRow.anchorCol-anchorContextWidth)}}return rows.map(row=>{let line=horizontalScroll>0?`${row.gutter}${sliceByColumn(row.body,horizontalScroll,viewportWidth,!0)}\x1B[0m`:row.gutter+row.body;return truncateToWidth(line,width,"")})}var TreeList=class{constructor(tree,currentLeafId,maxVisibleLines,initialSelectedId,initialFilterMode){this.flatNodes=[],this.filteredNodes=[],this.selectedIndex=0,this.filterMode="default",this.searchQuery="",this.toolCallMap=new Map,this.multipleRoots=!1,this.showLabelTimestamps=!1,this.activePathIds=new Set,this.visibleParentMap=new Map,this.visibleChildrenMap=new Map,this.lastSelectedId=null,this.foldedNodes=new Set,this.currentLeafId=currentLeafId,this.maxVisibleLines=maxVisibleLines,this.filterMode=initialFilterMode??"default",this.multipleRoots=tree.length>1,this.flatNodes=this.flattenTree(tree),this.buildActivePath(),this.applyFilter();let targetId=initialSelectedId??currentLeafId;this.selectedIndex=this.findNearestVisibleIndex(targetId),this.lastSelectedId=this.filteredNodes[this.selectedIndex]?.node.entry.id??null}findNearestVisibleIndex(entryId){if(this.filteredNodes.length===0)return 0;let entryMap=new Map;for(let flatNode of this.flatNodes)entryMap.set(flatNode.node.entry.id,flatNode);let visibleIdToIndex=new Map(this.filteredNodes.map((node,i)=>[node.node.entry.id,i])),currentId=entryId;for(;currentId!==null;){let index3=visibleIdToIndex.get(currentId);if(index3!==void 0)return index3;let node=entryMap.get(currentId);if(!node)break;currentId=node.node.entry.parentId??null}return this.filteredNodes.length-1}buildActivePath(){if(this.activePathIds.clear(),!this.currentLeafId)return;let entryMap=new Map;for(let flatNode of this.flatNodes)entryMap.set(flatNode.node.entry.id,flatNode);let currentId=this.currentLeafId;for(;currentId;){this.activePathIds.add(currentId);let node=entryMap.get(currentId);if(!node)break;currentId=node.node.entry.parentId??null}}flattenTree(roots){let result2=[];this.toolCallMap.clear();let stack=[],containsActive=new Map,leafId=this.currentLeafId;{let allNodes=[],preOrderStack=[...roots];for(;preOrderStack.length>0;){let node=preOrderStack.pop();allNodes.push(node);for(let i=node.children.length-1;i>=0;i--)preOrderStack.push(node.children[i])}for(let i=allNodes.length-1;i>=0;i--){let node=allNodes[i],has=leafId!==null&&node.entry.id===leafId;for(let child of node.children)containsActive.get(child)&&(has=!0);containsActive.set(node,has)}}let multipleRoots=roots.length>1,orderedRoots=[...roots].sort((a,b2)=>Number(containsActive.get(b2))-Number(containsActive.get(a)));for(let i=orderedRoots.length-1;i>=0;i--){let isLast=i===orderedRoots.length-1;stack.push([orderedRoots[i],multipleRoots?1:0,multipleRoots,multipleRoots,isLast,[],multipleRoots])}for(;stack.length>0;){let[node,indent,justBranched,showConnector,isLast,gutters,isVirtualRootChild]=stack.pop(),entry=node.entry;if(entry.type==="message"&&entry.message.role==="assistant"){let content=entry.message.content;if(Array.isArray(content)){for(let block of content)if(typeof block=="object"&&block!==null&&"type"in block&&block.type==="toolCall"){let tc=block;this.toolCallMap.set(tc.id,{name:tc.name,arguments:tc.arguments})}}}result2.push({node,indent,showConnector,isLast,gutters,isVirtualRootChild});let children=node.children,multipleChildren=children.length>1,orderedChildren=(()=>{let prioritized=[],rest=[];for(let child of children)containsActive.get(child)?prioritized.push(child):rest.push(child);return[...prioritized,...rest]})(),childIndent;multipleChildren||justBranched&&indent>0?childIndent=indent+1:childIndent=indent;let connectorDisplayed=showConnector&&!isVirtualRootChild,currentDisplayIndent=this.multipleRoots?Math.max(0,indent-1):indent,connectorPosition=Math.max(0,currentDisplayIndent-1),childGutters=connectorDisplayed?[...gutters,{position:connectorPosition,show:!isLast}]:gutters;for(let i=orderedChildren.length-1;i>=0;i--){let childIsLast=i===orderedChildren.length-1;stack.push([orderedChildren[i],childIndent,multipleChildren,multipleChildren,childIsLast,childGutters,!1])}}return result2}applyFilter(){this.filteredNodes.length>0&&(this.lastSelectedId=this.filteredNodes[this.selectedIndex]?.node.entry.id??this.lastSelectedId);let searchTokens=this.searchQuery.toLowerCase().split(/\s+/).filter(Boolean);if(this.filteredNodes=this.flatNodes.filter(flatNode=>{let entry=flatNode.node.entry;if(entry.type==="usage")return!1;let isCurrentLeaf=entry.id===this.currentLeafId;if(entry.type==="message"&&entry.message.role==="assistant"&&!isCurrentLeaf){let msg=entry.message,hasText=this.hasTextContent(msg.content),isErrorOrAborted=msg.stopReason&&msg.stopReason!=="stop"&&msg.stopReason!=="toolUse";if(!hasText&&!isErrorOrAborted)return!1}let passesFilter=!0,isSettingsEntry=entry.type==="label"||entry.type==="context_edit"||entry.type==="custom"||entry.type==="model_change"||entry.type==="thinking_level_change"||entry.type==="session_info";switch(this.filterMode){case"user-only":passesFilter=entry.type==="message"&&entry.message.role==="user";break;case"no-tools":passesFilter=!isSettingsEntry&&!(entry.type==="message"&&entry.message.role==="toolResult");break;case"labeled-only":passesFilter=flatNode.node.label!==void 0;break;case"all":passesFilter=!0;break;default:passesFilter=!isSettingsEntry;break}if(!passesFilter)return!1;if(searchTokens.length>0){let nodeText=this.getSearchableText(flatNode.node).toLowerCase();return searchTokens.every(token=>nodeText.includes(token))}return!0}),this.foldedNodes.size>0){let skipSet=new Set;for(let flatNode of this.flatNodes){let{id,parentId}=flatNode.node.entry;parentId!=null&&(this.foldedNodes.has(parentId)||skipSet.has(parentId))&&skipSet.add(id)}this.filteredNodes=this.filteredNodes.filter(flatNode=>!skipSet.has(flatNode.node.entry.id))}this.recalculateVisualStructure(),this.lastSelectedId?this.selectedIndex=this.findNearestVisibleIndex(this.lastSelectedId):this.selectedIndex>=this.filteredNodes.length&&(this.selectedIndex=Math.max(0,this.filteredNodes.length-1)),this.filteredNodes.length>0&&(this.lastSelectedId=this.filteredNodes[this.selectedIndex]?.node.entry.id??this.lastSelectedId)}recalculateVisualStructure(){if(this.filteredNodes.length===0)return;let visibleIds=new Set(this.filteredNodes.map(n=>n.node.entry.id)),entryMap=new Map;for(let flatNode of this.flatNodes)entryMap.set(flatNode.node.entry.id,flatNode);let findVisibleAncestor=nodeId=>{let currentId=entryMap.get(nodeId)?.node.entry.parentId??null;for(;currentId!==null;){if(visibleIds.has(currentId))return currentId;currentId=entryMap.get(currentId)?.node.entry.parentId??null}return null},visibleParent=new Map,visibleChildren=new Map;visibleChildren.set(null,[]);for(let flatNode of this.filteredNodes){let nodeId=flatNode.node.entry.id,ancestorId=findVisibleAncestor(nodeId);visibleParent.set(nodeId,ancestorId),visibleChildren.has(ancestorId)||visibleChildren.set(ancestorId,[]),visibleChildren.get(ancestorId).push(nodeId)}let visibleRootIds=visibleChildren.get(null);this.multipleRoots=visibleRootIds.length>1;let filteredNodeMap=new Map;for(let flatNode of this.filteredNodes)filteredNodeMap.set(flatNode.node.entry.id,flatNode);let stack=[];for(let i=visibleRootIds.length-1;i>=0;i--){let isLast=i===visibleRootIds.length-1;stack.push([visibleRootIds[i],this.multipleRoots?1:0,this.multipleRoots,this.multipleRoots,isLast,[],this.multipleRoots])}for(;stack.length>0;){let[nodeId,indent,justBranched,showConnector,isLast,gutters,isVirtualRootChild]=stack.pop(),flatNode=filteredNodeMap.get(nodeId);if(!flatNode)continue;flatNode.indent=indent,flatNode.showConnector=showConnector,flatNode.isLast=isLast,flatNode.gutters=gutters,flatNode.isVirtualRootChild=isVirtualRootChild;let children=visibleChildren.get(nodeId)||[],multipleChildren=children.length>1,childIndent;multipleChildren||justBranched&&indent>0?childIndent=indent+1:childIndent=indent;let connectorDisplayed=showConnector&&!isVirtualRootChild,currentDisplayIndent=this.multipleRoots?Math.max(0,indent-1):indent,connectorPosition=Math.max(0,currentDisplayIndent-1),childGutters=connectorDisplayed?[...gutters,{position:connectorPosition,show:!isLast}]:gutters;for(let i=children.length-1;i>=0;i--){let childIsLast=i===children.length-1;stack.push([children[i],childIndent,multipleChildren,multipleChildren,childIsLast,childGutters,!1])}}this.visibleParentMap=visibleParent,this.visibleChildrenMap=visibleChildren}getSearchableText(node){let entry=node.entry,parts=[];switch(node.label&&parts.push(node.label),entry.type){case"message":{let msg=entry.message;if(parts.push(msg.role),"content"in msg&&msg.content&&parts.push(this.extractContent(msg.content)),msg.role==="bashExecution"){let bashMsg=msg;bashMsg.command&&parts.push(bashMsg.command)}break}case"custom_message":{parts.push(entry.customType),typeof entry.content=="string"?parts.push(entry.content):parts.push(this.extractContent(entry.content));break}case"compaction":parts.push("compaction");break;case"branch_summary":parts.push("branch summary",entry.summary);break;case"session_info":parts.push("title"),entry.name&&parts.push(entry.name);break;case"model_change":parts.push("model",entry.modelId);break;case"thinking_level_change":parts.push("thinking",entry.thinkingLevel);break;case"custom":parts.push("custom",entry.customType);break;case"context_edit":parts.push("context edit",entry.replacement===null?"omit":"replace",entry.targetId);break;case"label":parts.push("label",entry.label??"");break}return parts.join(" ")}invalidate(){}getSearchQuery(){return this.searchQuery}getSelectedNode(){return this.filteredNodes[this.selectedIndex]?.node}copySelected(){let node=this.getSelectedNode();this.onCopy?.(node?this.getEntryCopyText(node):void 0)}updateNodeLabel(entryId,label,labelTimestamp){for(let flatNode of this.flatNodes)if(flatNode.node.entry.id===entryId){flatNode.node.label=label,flatNode.node.labelTimestamp=label?labelTimestamp??new Date().toISOString():void 0;break}}getStatusLabels(){let labels="";switch(this.filterMode){case"no-tools":labels+=" [no-tools]";break;case"user-only":labels+=" [user]";break;case"labeled-only":labels+=" [labeled]";break;case"all":labels+=" [all]";break}return this.showLabelTimestamps&&(labels+=" [+label time]"),labels}render(width){let lines=[];if(this.filteredNodes.length===0)return lines.push(truncateToWidth(theme.fg("muted"," No entries found"),width)),lines.push(truncateToWidth(theme.fg("muted",` (0/0)${this.getStatusLabels()}`),width)),lines;let startIndex=Math.max(0,Math.min(this.selectedIndex-Math.floor(this.maxVisibleLines/2),this.filteredNodes.length-this.maxVisibleLines)),endIndex=Math.min(startIndex+this.maxVisibleLines,this.filteredNodes.length),renderedRows=[];for(let i=startIndex;i<endIndex;i++){let flatNode=this.filteredNodes[i],entry=flatNode.node.entry,isSelected2=i===this.selectedIndex,cursor=isSelected2?theme.fg("accent","\u203A "):" ",displayIndent=this.multipleRoots?Math.max(0,flatNode.indent-1):flatNode.indent,connector=flatNode.showConnector&&!flatNode.isVirtualRootChild?flatNode.isLast?"\u2514\u2500 ":"\u251C\u2500 ":"",connectorPosition=connector?displayIndent-1:-1,totalChars=displayIndent*3,prefixChars=[],isFolded=this.foldedNodes.has(entry.id);for(let i2=0;i2<totalChars;i2++){let level=Math.floor(i2/3),posInLevel=i2%3,gutter2=flatNode.gutters.find(g=>g.position===level);if(gutter2)posInLevel===0?prefixChars.push(gutter2.show?"\u2502":" "):prefixChars.push(" ");else if(connector&&level===connectorPosition)if(posInLevel===0)prefixChars.push(flatNode.isLast?"\u2514":"\u251C");else if(posInLevel===1){let foldable=this.isFoldable(entry.id);prefixChars.push(isFolded?"\u229E":foldable?"\u229F":"\u2500")}else prefixChars.push(" ");else prefixChars.push(" ")}let prefix=prefixChars.join(""),showsFoldInConnector=flatNode.showConnector&&!flatNode.isVirtualRootChild,foldMarker=isFolded&&!showsFoldInConnector?theme.fg("accent","\u229E "):"",pathMarker=this.activePathIds.has(entry.id)?theme.fg("accent","\u2022 "):"",label=flatNode.node.label?theme.fg("warning",`[${flatNode.node.label}] `):"",labelTimestamp=this.showLabelTimestamps&&flatNode.node.label&&flatNode.node.labelTimestamp?theme.fg("muted",`${this.formatLabelTimestamp(flatNode.node.labelTimestamp)} `):"",content=this.getEntryDisplayText(flatNode.node,isSelected2),prefixPart=theme.fg("dim",prefix)+foldMarker+pathMarker,anchorCol=visibleWidth(prefixPart),gutter=cursor,body2=prefixPart+label+labelTimestamp+content;isSelected2&&(gutter=theme.bg("selectedBg",gutter),body2=theme.bg("selectedBg",body2)),renderedRows.push({gutter,body:body2,anchorCol,bodyWidth:visibleWidth(body2),isSelected:isSelected2})}return lines.push(...renderHorizontalViewport(renderedRows,width)),lines.push(truncateToWidth(theme.fg("muted",` (${this.selectedIndex+1}/${this.filteredNodes.length})${this.getStatusLabels()}`),width)),lines}getEntryDisplayText(node,isSelected2){let entry=node.entry,result2,normalize2=s=>s.replace(/[\n\t]/g," ").trim();switch(entry.type){case"message":{let msg=entry.message,role=msg.role;if(role==="user"){let msgWithContent=msg,content=normalize2(this.extractContent(msgWithContent.content));result2=theme.fg("accent","user: ")+content}else if(role==="assistant"){let msgWithContent=msg,textContent=normalize2(this.extractContent(msgWithContent.content));if(textContent)result2=theme.fg("success","assistant: ")+textContent;else if(msgWithContent.stopReason==="aborted")result2=theme.fg("success","assistant: ")+theme.fg("muted","(aborted)");else if(msgWithContent.errorMessage){let errMsg=normalize2(msgWithContent.errorMessage).slice(0,80);result2=theme.fg("success","assistant: ")+theme.fg("error",errMsg)}else result2=theme.fg("success","assistant: ")+theme.fg("muted","(no content)")}else if(role==="toolResult"){let toolMsg=msg,toolCall=toolMsg.toolCallId?this.toolCallMap.get(toolMsg.toolCallId):void 0;toolCall?result2=theme.fg("muted",this.formatToolCall(toolCall.name,toolCall.arguments)):result2=theme.fg("muted",`[${toolMsg.toolName??"tool"}]`)}else if(role==="bashExecution"){let bashMsg=msg;result2=theme.fg("dim",`[bash]: ${normalize2(bashMsg.command??"")}`)}else result2=theme.fg("dim",`[${role}]`);break}case"custom_message":{let content=typeof entry.content=="string"?entry.content:entry.content.filter(c=>c.type==="text").map(c=>c.text).join("");result2=theme.fg("customMessageLabel",`[${entry.customType}]: `)+normalize2(content);break}case"compaction":{let tokens2=Math.round(entry.tokensBefore/1e3);result2=theme.fg("borderAccent",`[compaction: ${tokens2}k tokens]`);break}case"branch_summary":result2=theme.fg("warning","[branch summary]: ")+normalize2(entry.summary);break;case"model_change":result2=theme.fg("dim",`[model: ${entry.modelId}]`);break;case"thinking_level_change":result2=theme.fg("dim",`[thinking: ${entry.thinkingLevel}]`);break;case"custom":result2=theme.fg("dim",`[custom: ${entry.customType}]`);break;case"context_edit":result2=theme.fg("dim",`[context ${entry.replacement===null?"omit":"replace"}: ${entry.targetId}]`);break;case"label":result2=theme.fg("dim",`[label: ${entry.label??"(cleared)"}]`);break;case"session_info":result2=entry.name?[theme.fg("dim","[title: "),theme.fg("dim",entry.name),theme.fg("dim","]")].join(""):[theme.fg("dim","[title: "),theme.italic(theme.fg("dim","empty")),theme.fg("dim","]")].join("");break;default:result2=""}return isSelected2?theme.bold(result2):result2}formatLabelTimestamp(timestamp){let date=new Date(timestamp),now=new Date,hours=date.getHours().toString().padStart(2,"0"),minutes=date.getMinutes().toString().padStart(2,"0"),time2=`${hours}:${minutes}`;if(date.getFullYear()===now.getFullYear()&&date.getMonth()===now.getMonth()&&date.getDate()===now.getDate())return time2;let month=date.getMonth()+1,day=date.getDate();return date.getFullYear()===now.getFullYear()?`${month}/${day} ${time2}`:`${date.getFullYear().toString().slice(-2)}/${month}/${day} ${time2}`}extractContent(content){return this.extractFullContent(content).slice(0,200)}extractFullContent(content){if(typeof content=="string")return content;if(!Array.isArray(content))return"";let result2="";for(let block of content)typeof block=="object"&&block!==null&&"type"in block&&block.type==="text"&&(result2+=block.text);return result2}getEntryCopyText(node){let entry=node.entry,text2;switch(entry.type){case"message":entry.message.role==="bashExecution"?text2=entry.message.command:"content"in entry.message&&(text2=this.extractFullContent(entry.message.content),!text2&&entry.message.role==="assistant"&&(text2=entry.message.errorMessage));break;case"custom_message":text2=this.extractFullContent(entry.content);break;case"compaction":text2=entry.summary;break;case"branch_summary":text2=entry.summary;break}return text2?.trim()?text2:void 0}hasTextContent(content){if(typeof content=="string")return content.trim().length>0;if(Array.isArray(content)){for(let c of content)if(typeof c=="object"&&c!==null&&"type"in c&&c.type==="text"){let text2=c.text;if(text2&&text2.trim().length>0)return!0}}return!1}formatToolCall(name,args){let shortenPath3=p=>{let home=process.env.HOME||process.env.USERPROFILE||"";return home&&p.startsWith(home)?`~${p.slice(home.length)}`:p};switch(name){case"read":return`[read: ${shortenPath3(String(args.path||args.file_path||""))}${formatReadLineRange(args.offset,args.limit)}]`;case"write":return`[write: ${shortenPath3(String(args.path||args.file_path||""))}]`;case"edit":return`[edit: ${shortenPath3(String(args.path||args.file_path||""))}]`;case"bash":{let rawCmd=String(args.command||"");return`[bash: ${rawCmd.replace(/[\n\t]/g," ").trim().slice(0,50)}${rawCmd.length>50?"...":""}]`}case"grep":{let pattern=String(args.pattern||""),path14=shortenPath3(String(args.path||"."));return`[grep: /${pattern}/ in ${path14}]`}case"find":{let pattern=String(args.pattern||""),path14=shortenPath3(String(args.path||"."));return`[find: ${pattern} in ${path14}]`}case"ls":return`[ls: ${shortenPath3(String(args.path||"."))}]`;default:{let argsStr=JSON.stringify(args).slice(0,40);return`[${name}: ${argsStr}${JSON.stringify(args).length>40?"...":""}]`}}}handleInput(keyData){let kb=getKeybindings();if(kb.matches(keyData,"tui.select.up"))this.selectedIndex=this.selectedIndex===0?this.filteredNodes.length-1:this.selectedIndex-1;else if(kb.matches(keyData,"tui.select.down"))this.selectedIndex=this.selectedIndex===this.filteredNodes.length-1?0:this.selectedIndex+1;else if(kb.matches(keyData,"app.tree.foldOrUp")){let currentId=this.filteredNodes[this.selectedIndex]?.node.entry.id;currentId&&this.isFoldable(currentId)&&!this.foldedNodes.has(currentId)?(this.foldedNodes.add(currentId),this.applyFilter()):this.selectedIndex=this.findBranchSegmentStart("up")}else if(kb.matches(keyData,"app.tree.unfoldOrDown")){let currentId=this.filteredNodes[this.selectedIndex]?.node.entry.id;currentId&&this.foldedNodes.has(currentId)?(this.foldedNodes.delete(currentId),this.applyFilter()):this.selectedIndex=this.findBranchSegmentStart("down")}else if(kb.matches(keyData,"tui.editor.cursorLeft")||kb.matches(keyData,"tui.select.pageUp"))this.selectedIndex=Math.max(0,this.selectedIndex-this.maxVisibleLines);else if(kb.matches(keyData,"tui.editor.cursorRight")||kb.matches(keyData,"tui.select.pageDown"))this.selectedIndex=Math.min(this.filteredNodes.length-1,this.selectedIndex+this.maxVisibleLines);else if(kb.matches(keyData,"tui.select.confirm")){let selected=this.filteredNodes[this.selectedIndex];selected&&this.onSelect&&this.onSelect(selected.node.entry.id)}else if(kb.matches(keyData,"app.message.copy"))this.copySelected();else if(kb.matches(keyData,"tui.select.cancel"))this.searchQuery?(this.searchQuery="",this.foldedNodes.clear(),this.applyFilter()):this.onCancel?.();else if(kb.matches(keyData,"app.tree.filter.default"))this.filterMode="default",this.foldedNodes.clear(),this.applyFilter();else if(kb.matches(keyData,"app.tree.filter.noTools"))this.filterMode=this.filterMode==="no-tools"?"default":"no-tools",this.foldedNodes.clear(),this.applyFilter();else if(kb.matches(keyData,"app.tree.filter.userOnly"))this.filterMode=this.filterMode==="user-only"?"default":"user-only",this.foldedNodes.clear(),this.applyFilter();else if(kb.matches(keyData,"app.tree.filter.labeledOnly"))this.filterMode=this.filterMode==="labeled-only"?"default":"labeled-only",this.foldedNodes.clear(),this.applyFilter();else if(kb.matches(keyData,"app.tree.filter.all"))this.filterMode=this.filterMode==="all"?"default":"all",this.foldedNodes.clear(),this.applyFilter();else if(kb.matches(keyData,"app.tree.filter.cycleBackward")){let modes=["default","no-tools","user-only","labeled-only","all"],currentIndex=modes.indexOf(this.filterMode);this.filterMode=modes[(currentIndex-1+modes.length)%modes.length],this.foldedNodes.clear(),this.applyFilter()}else if(kb.matches(keyData,"app.tree.filter.cycleForward")){let modes=["default","no-tools","user-only","labeled-only","all"],currentIndex=modes.indexOf(this.filterMode);this.filterMode=modes[(currentIndex+1)%modes.length],this.foldedNodes.clear(),this.applyFilter()}else if(kb.matches(keyData,"tui.editor.deleteCharBackward"))this.searchQuery.length>0&&(this.searchQuery=this.searchQuery.slice(0,-1),this.foldedNodes.clear(),this.applyFilter());else if(kb.matches(keyData,"app.tree.editLabel")){let selected=this.filteredNodes[this.selectedIndex];selected&&this.onLabelEdit&&this.onLabelEdit(selected.node.entry.id,selected.node.label)}else kb.matches(keyData,"app.tree.toggleLabelTimestamp")?this.showLabelTimestamps=!this.showLabelTimestamps:![...keyData].some(ch=>{let code=ch.charCodeAt(0);return code<32||code===127||code>=128&&code<=159})&&keyData.length>0&&(this.searchQuery+=keyData,this.foldedNodes.clear(),this.applyFilter())}isFoldable(entryId){let children=this.visibleChildrenMap.get(entryId);if(!children||children.length===0)return!1;let parentId=this.visibleParentMap.get(entryId);if(parentId==null)return!0;let siblings=this.visibleChildrenMap.get(parentId);return siblings!==void 0&&siblings.length>1}findBranchSegmentStart(direction){let selectedId=this.filteredNodes[this.selectedIndex]?.node.entry.id;if(!selectedId)return this.selectedIndex;let indexByEntryId=new Map(this.filteredNodes.map((node,i)=>[node.node.entry.id,i])),currentId=selectedId;if(direction==="down")for(;;){let children=this.visibleChildrenMap.get(currentId)??[];if(children.length===0)return indexByEntryId.get(currentId);if(children.length>1)return indexByEntryId.get(children[0]);currentId=children[0]}for(;;){let parentId=this.visibleParentMap.get(currentId)??null;if(parentId===null)return indexByEntryId.get(currentId);if((this.visibleChildrenMap.get(parentId)??[]).length>1){let segmentStart=indexByEntryId.get(currentId);if(segmentStart<this.selectedIndex)return segmentStart}currentId=parentId}}},SearchLine=class{constructor(treeList){this.treeList=treeList}invalidate(){}render(width){let query=this.treeList.getSearchQuery();return query?[truncateToWidth(` ${theme.fg("muted","Type to search:")} ${theme.fg("accent",query)}`,width)]:[truncateToWidth(` ${theme.fg("muted","Type to search:")}`,width)]}handleInput(_keyData){}},TreeHelp=class{invalidate(){}render(width){let items=TREE_HELP_ITEMS.map(({keys,label,labelFirst})=>{let text2=formatHelpKeys(keys);return text2?labelFirst?`${label} ${text2}`:`${text2} ${label}`:label}),availableWidth=Math.max(1,width),indent=" ",separator=" \xB7 ",lines=[],currentLine="";for(let item of items){let candidate=currentLine?`${currentLine}${separator}${item}`:visibleWidth(`${indent}${item}`)<=availableWidth?`${indent}${item}`:item;if(!currentLine||visibleWidth(candidate)<=availableWidth){currentLine=candidate;continue}lines.push(...wrapTextWithAnsi(currentLine.trimEnd(),availableWidth)),currentLine=visibleWidth(`${indent}${item}`)<=availableWidth?`${indent}${item}`:item}return currentLine&&lines.push(...wrapTextWithAnsi(currentLine.trimEnd(),availableWidth)),lines.map(line=>theme.fg("muted",line))}},TREE_HELP_ITEMS=[{keys:["tui.select.up","tui.select.down"],label:"move"},{keys:["tui.editor.cursorLeft","tui.editor.cursorRight"],label:"page"},{keys:["app.tree.foldOrUp","app.tree.unfoldOrDown"],label:"branch"},{keys:["app.message.copy"],label:"copy"},{keys:["app.tree.editLabel"],label:"label"},{keys:["app.tree.toggleLabelTimestamp"],label:"label time"},{keys:["app.tree.filter.default","app.tree.filter.noTools","app.tree.filter.userOnly","app.tree.filter.labeledOnly","app.tree.filter.all"],label:"filters",labelFirst:!0},{keys:["app.tree.filter.cycleForward","app.tree.filter.cycleBackward"],label:"cycle",labelFirst:!0}];function formatHelpKeys(keybindings){let keys=[];for(let keybinding of keybindings){let key=getKeybindings().getKeys(keybinding)[0];key!==void 0&&keys.push(key)}return keys.length===0?"":formatKeyText(compactRawKeys(keys)).replace(/\bpageUp\b/g,"pgup").replace(/\bpageDown\b/g,"pgdn").replace(/\bup\b/g,"\u2191").replace(/\bdown\b/g,"\u2193").replace(/\bleft\b/g,"\u2190").replace(/\bright\b/g,"\u2192")}function compactRawKeys(keys){if(keys.length===1)return keys[0];let parts=keys.map(key=>{let separatorIndex=key.lastIndexOf("+");return separatorIndex===-1?{prefix:"",suffix:key}:{prefix:key.slice(0,separatorIndex+1),suffix:key.slice(separatorIndex+1)}}),prefix=parts[0].prefix;return prefix&&parts.every(part=>part.prefix===prefix)?`${prefix}${parts.map(part=>part.suffix).join("/")}`:keys.join("/")}var LabelInput=class{get focused(){return this._focused}set focused(value){this._focused=value,this.input.focused=value}constructor(entryId,currentLabel){this._focused=!1,this.entryId=entryId,this.input=new Input,currentLabel&&this.input.setValue(currentLabel)}invalidate(){}render(width){let lines=[],availableWidth=width-2;return lines.push(truncateToWidth(` ${theme.fg("muted","Label (empty to remove):")}`,width)),lines.push(...this.input.render(availableWidth).map(line=>truncateToWidth(` ${line}`,width))),lines.push(truncateToWidth(` ${keyHint("tui.select.confirm","save")} ${keyHint("tui.select.cancel","cancel")}`,width)),lines}handleInput(keyData){let kb=getKeybindings();if(kb.matches(keyData,"tui.select.confirm")){let value=this.input.getValue().trim();this.onSubmit?.(this.entryId,value||void 0)}else kb.matches(keyData,"tui.select.cancel")?this.onCancel?.():this.input.handleInput(keyData)}},TreeSelectorComponent=class extends Container{get focused(){return this._focused}set focused(value){this._focused=value,this.labelInput&&(this.labelInput.focused=value)}constructor(tree,currentLeafId,terminalHeight,onSelect,onCancel,onLabelChange,initialSelectedId,initialFilterMode){super(),this.labelInput=null,this._focused=!1,this.onLabelChangeCallback=onLabelChange;let maxVisibleLines=Math.max(5,Math.floor(terminalHeight/2));this.treeList=new TreeList(tree,currentLeafId,maxVisibleLines,initialSelectedId,initialFilterMode),this.treeList.onSelect=onSelect,this.treeList.onCancel=onCancel,this.treeList.onCopy=text2=>this.onCopy?.(text2),this.treeList.onLabelEdit=(entryId,currentLabel)=>this.showLabelInput(entryId,currentLabel),this.treeContainer=new Container,this.treeContainer.addChild(this.treeList),this.labelInputContainer=new Container,this.addChild(new Spacer(1)),this.addChild(new DynamicBorder),this.addChild(new Text(theme.bold(" Session Tree"),1,0)),this.addChild(new TreeHelp),this.addChild(new SearchLine(this.treeList)),this.addChild(new DynamicBorder),this.addChild(new Spacer(1)),this.addChild(this.treeContainer),this.addChild(this.labelInputContainer),this.addChild(new Spacer(1)),this.addChild(new DynamicBorder),tree.length===0&&setTimeout(()=>onCancel(),100)}showLabelInput(entryId,currentLabel){this.labelInput=new LabelInput(entryId,currentLabel),this.labelInput.onSubmit=(id,label)=>{this.treeList.updateNodeLabel(id,label),this.onLabelChangeCallback?.(id,label),this.hideLabelInput()},this.labelInput.onCancel=()=>this.hideLabelInput(),this.labelInput.focused=this._focused,this.treeContainer.clear(),this.labelInputContainer.clear(),this.labelInputContainer.addChild(this.labelInput)}hideLabelInput(){this.labelInput=null,this.labelInputContainer.clear(),this.treeContainer.clear(),this.treeContainer.addChild(this.treeList)}handleInput(keyData){this.labelInput?this.labelInput.handleInput(keyData):this.treeList.handleInput(keyData)}getTreeList(){return this.treeList}};var OSC133_ZONE_START2="\x1B]133;A\x07",OSC133_ZONE_END2="\x1B]133;B\x07",OSC133_ZONE_FINAL2="\x1B]133;C\x07",UserMessageComponent=class extends Container{constructor(text2,markdownTheme=getMarkdownTheme(),outputPad=1,markdownTransformers=[]){super(),this.text=text2,this.markdownTheme=markdownTheme,this.outputPad=outputPad,this.markdownTransformers=markdownTransformers,this.rebuild()}setOutputPad(padding){this.outputPad=padding,this.rebuild()}rebuild(){this.clear(),this.addChild(new Markdown(this.text,this.outputPad,1,this.markdownTheme,{color:content=>theme.fg("userMessageText",content),bgColor:content=>theme.bg("userMessageBg",content)},{preserveOrderedListMarkers:!0,preserveBackslashEscapes:!0,transform:createMarkdownTransform("user",!1,this.markdownTransformers)}))}render(width){let lines=super.render(width);return lines.length===0||(lines[0]=OSC133_ZONE_START2+lines[0],lines[lines.length-1]=OSC133_ZONE_END2+OSC133_ZONE_FINAL2+lines[lines.length-1]),lines}};var UserMessageList=class{constructor(messages,initialSelectedId){this.messages=[],this.selectedIndex=0,this.maxVisible=10,this.messages=messages;let initialIndex=initialSelectedId?messages.findIndex(message=>message.id===initialSelectedId):-1;this.selectedIndex=initialIndex>=0?initialIndex:Math.max(0,messages.length-1)}invalidate(){}render(width){let lines=[];if(this.messages.length===0)return lines.push(theme.fg("muted"," No user messages found")),lines;let startIndex=Math.max(0,Math.min(this.selectedIndex-Math.floor(this.maxVisible/2),this.messages.length-this.maxVisible)),endIndex=Math.min(startIndex+this.maxVisible,this.messages.length);for(let i=startIndex;i<endIndex;i++){let message=this.messages[i],isSelected2=i===this.selectedIndex,normalizedMessage=message.text.replace(/\n/g," ").trim(),cursor=isSelected2?theme.fg("accent","\u203A "):" ",maxMsgWidth=width-2,truncatedMsg=truncateToWidth(normalizedMessage,maxMsgWidth),messageLine=cursor+(isSelected2?theme.bold(truncatedMsg):truncatedMsg);lines.push(messageLine);let metadata=` Message ${i+1} of ${this.messages.length}`,metadataLine=theme.fg("muted",metadata);lines.push(metadataLine),lines.push("")}if(startIndex>0||endIndex<this.messages.length){let scrollInfo=theme.fg("muted",` (${this.selectedIndex+1}/${this.messages.length})`);lines.push(scrollInfo)}return lines}handleInput(keyData){let kb=getKeybindings();if(kb.matches(keyData,"tui.select.up"))this.selectedIndex=this.selectedIndex===0?this.messages.length-1:this.selectedIndex-1;else if(kb.matches(keyData,"tui.select.down"))this.selectedIndex=this.selectedIndex===this.messages.length-1?0:this.selectedIndex+1;else if(kb.matches(keyData,"tui.select.confirm")){let selected=this.messages[this.selectedIndex];selected&&this.onSelect&&this.onSelect(selected.id)}else kb.matches(keyData,"tui.select.cancel")&&this.onCancel&&this.onCancel()}},UserMessageSelectorComponent=class extends Container{constructor(messages,onSelect,onCancel,initialSelectedId){super(),this.addChild(new Spacer(1)),this.addChild(new Text(theme.bold("Fork from Message"),1,0)),this.addChild(new Text(theme.fg("muted","Select a user message to copy the active path up to that point into a new session"),1,0)),this.addChild(new Spacer(1)),this.addChild(new DynamicBorder),this.addChild(new Spacer(1)),this.messageList=new UserMessageList(messages,initialSelectedId),this.messageList.onSelect=onSelect,this.messageList.onCancel=onCancel,this.addChild(this.messageList),this.addChild(new Spacer(1)),this.addChild(new DynamicBorder),messages.length===0&&setTimeout(()=>onCancel(),100)}getMessageList(){return this.messageList}};function createAllToolRenderers(){return{tasks:{renderCall:(args,theme2,context)=>renderTasksCall(args,theme2,context),renderResult:renderTasksResult},read:readRenderers,bash:createShellRenderers({name:"bash",prompt:"$"}),powershell:createShellRenderers({name:"powershell",prompt:"PS>"}),edit:editRenderers,write:writeRenderers,grep:grepRenderers,find:findRenderers,ls:lsRenderers}}function withBuiltInRenderers(toolName,definition){let builtIn=createAllToolRenderers()[toolName];return definition?builtIn?{...definition,renderCall:definition.renderCall??builtIn.renderCall,renderResult:definition.renderResult??builtIn.renderResult}:definition:builtIn}function formatFallbackArgs(args){if(!args||typeof args!="object")return"";let entries=Object.entries(args);if(entries.length===0)return"";let summary=entries.map(([key,value])=>{try{return`${key}=${JSON.stringify(value)??String(value)}`}catch{return`${key}=${String(value)}`}}).join(" ").replace(/\s+/g," ");return truncateToWidth(summary,toolStyle.fallbackArgsWidth,"...")}function createCallFallback(toolName,args,expanded=!1){if(expanded)return new Text(formatToolCallWithArgs(toolName,args,theme,!0),0,0);let summary=formatFallbackArgs(args),suffix=summary?theme.fg("dim",`(${summary})`):"";return new Text(`${theme.fg("toolTitle",theme.bold(toolName))}${suffix}`,0,0)}var FallbackResultComponent=class{constructor(output,expanded){this.output=output,this.expanded=expanded}render(width){let styledOutput=theme.fg("toolOutput",this.output);if(this.expanded)return new Text(styledOutput,0,0).render(width);let preview=truncateToVisualLines(styledOutput,toolStyle.collapsed.fallbackLines,width);if(preview.skippedCount<=0)return preview.visualLines;let noun=preview.skippedCount===1?"line":"lines",hint=theme.fg("muted",`... (${preview.skippedCount} earlier ${noun},`)+` ${keyHint("app.tools.expand","to expand")}${theme.fg("muted",")")}`;return[truncateToWidth(hint,width,"..."),...preview.visualLines]}invalidate(){}};var builtInRenderers,ToolExecutionComponent=class extends Container{constructor(toolName,toolCallId,args,options={},toolDefinition,ui,cwd){super(),this.selfRenderHeight=0,this.rendererState={},this.imageComponents=[],this.imageSources=[],this.imageSpacers=[],this.expanded=!1,this.isPartial=!0,this.executionStarted=!1,this.argsComplete=!1,this.hideComponent=!1,this.disposed=!1,this.toolName=toolName,this.toolCallId=toolCallId,this.args=args,this.toolDefinition=toolDefinition,this.showImages=options.showImages??!0,this.imageWidthCells=options.imageWidthCells??60,this.outputPad=options.outputPad??1,this.ui=ui,this.cwd=cwd,this.gap=new Spacer(toolStyle.gap.afterOther),this.addChild(this.gap),this.contentContainer=new Container,this.selfRenderContainer=new Container,this.addChild(this.isSelfRendered()?this.selfRenderContainer:this.contentContainer),this.updateDisplay()}getCallRenderer(){return this.toolDefinition?.renderCall}getResultRenderer(){return this.toolDefinition?.renderResult}isSelfRendered(){return this.toolDefinition?.renderShell==="self"}status(){return toolStatus({isPartial:this.isPartial,isError:this.result?.isError??!1})}setLeadingGap(lines){this.gap.setLines(lines)}getRenderContext(lastComponent){return{args:this.args,toolCallId:this.toolCallId,invalidate:()=>{this.disposed||(this.invalidate(),this.ui.requestRender())},lastComponent,state:this.rendererState,cwd:this.cwd,executionStarted:this.executionStarted,argsComplete:this.argsComplete,isPartial:this.isPartial,expanded:this.expanded,showImages:this.showImages,isError:this.result?.isError??!1,durationMs:this.isPartial?void 0:this.result?.durationMs,outputPad:this.outputPad,result:this.result?{content:this.result.content,details:this.result.details}:void 0}}frame(component,kind){return new FramedComponent(component,kind,()=>toolMarkerColor(this.status()))}createResultFallback(){let output=this.getTextOutput();if(output)return new FallbackResultComponent(output,this.expanded)}hidesCollapsedResult(){if(this.expanded||this.result?.isError||!toolStyle.collapsed.headerOnly.has(this.toolName))return!1;builtInRenderers??=createAllToolRenderers();let builtIn=builtInRenderers[this.toolName];return builtIn?.renderResult!==void 0&&builtIn.renderResult===this.getResultRenderer()}createResultRegion(component){return new MouseRegion(component,event=>{if(!(!this.result||event.type!=="click"||event.button!=="left"))return this.setExpanded(!this.expanded),{handled:!0}})}updateArgs(args){this.args=args,this.updateDisplay()}markExecutionStarted(){this.disposed||(this.executionStarted=!0,this.updateDisplay(),this.ui.requestRender())}setArgsComplete(){this.argsComplete=!0,this.updateDisplay(),this.ui.requestRender()}updateResult(result2,isPartial=!1){this.result=result2,this.isPartial=isPartial,this.updateDisplay()}setExpanded(expanded){this.expanded=expanded,this.updateDisplay()}setOutputPad(outputPad){this.outputPad=outputPad,this.updateDisplay()}setShowImages(show){this.showImages=show,this.updateDisplay()}setImageWidthCells(width){this.imageWidthCells=Math.max(1,Math.floor(width)),this.updateDisplay()}invalidate(){super.invalidate(),this.updateDisplay()}render(width){if(this.hideComponent)return[];if(this.isSelfRendered()){let contentLines=this.selfRenderContainer.render(width);if(this.selfRenderHeight=contentLines.length,contentLines.length===0&&this.imageComponents.length===0)return[];let lines=[];contentLines.length>0&&(lines.push(""),lines.push(...contentLines));for(let i=0;i<this.imageComponents.length;i++){let spacer=this.imageSpacers[i];spacer&&lines.push(...spacer.render(width));let imageComponent=this.imageComponents[i];imageComponent&&lines.push(...imageComponent.render(width))}return lines}return super.render(width)}handleMouse(event){if(!this.isSelfRendered())return super.handleMouse(event);if(!(event.y<=0||event.y>this.selfRenderHeight))return this.selfRenderContainer.handleMouse({...event,y:event.y-1,height:this.selfRenderHeight})}updateDisplay(){let hasContent=!1;this.hideComponent=!1;let selfRendered=this.isSelfRendered(),renderContainer=selfRendered?this.selfRenderContainer:this.contentContainer;renderContainer.clear();let addCall=component=>{renderContainer.addChild(selfRendered?component:this.createResultRegion(this.frame(component,"header"))),hasContent=!0},addResult=component=>{renderContainer.addChild(selfRendered?component:this.createResultRegion(this.frame(component,"body"))),hasContent=!0},callRenderer=this.getCallRenderer();if(!callRenderer)addCall(createCallFallback(this.toolName,this.args,this.expanded));else try{let component=callRenderer(this.args,theme,this.getRenderContext(this.callRendererComponent));this.callRendererComponent=component,addCall(component)}catch{this.callRendererComponent=void 0,addCall(createCallFallback(this.toolName,this.args,this.expanded))}if(this.result&&(selfRendered||!this.hidesCollapsedResult())){let resultRenderer=this.getResultRenderer();if(resultRenderer)try{let component=resultRenderer({content:this.result.content,details:this.result.details},{expanded:this.expanded,isPartial:this.isPartial},theme,this.getRenderContext(this.resultRendererComponent));this.resultRendererComponent=component,addResult(component)}catch{this.resultRendererComponent=void 0;let component=this.createResultFallback();component&&addResult(component)}else{let component=this.createResultFallback();component&&addResult(component)}}let previousImages=this.imageComponents,previousSources=this.imageSources;for(let img of this.imageComponents)this.removeChild(img);this.imageComponents=[],this.imageSources=[];for(let spacer of this.imageSpacers)this.removeChild(spacer);if(this.imageSpacers=[],this.result){let imageBlocks=this.result.content.filter(c=>c.type==="image"),caps=getCapabilities();for(let img of imageBlocks)if(caps.images&&this.showImages&&img.data&&img.mimeType){let spacer=new Spacer(1);this.addChild(spacer),this.imageSpacers.push(spacer);let source={data:img.data,mimeType:img.mimeType,widthCells:this.imageWidthCells},index3=this.imageComponents.length,previous=previousSources[index3],imageComponent=previous?.data===source.data&&previous.mimeType===source.mimeType&&previous.widthCells===source.widthCells?previousImages[index3]:new Image(source.data,source.mimeType,{fallbackColor:s=>theme.fg("toolOutput",s)},{maxWidthCells:source.widthCells});source.mimeType!=="image/png"&&ensurePngTranscoder(()=>{this.disposed||(this.invalidate(),this.ui.requestRender())}),this.imageComponents.push(imageComponent),this.imageSources.push(source),this.addChild(imageComponent)}}!hasContent&&this.imageComponents.length===0&&(this.hideComponent=!0)}getTextOutput(){return getTextOutput(this.result,this.showImages)}dispose(){this.disposed||(this.disposed=!0,this.rendererState.dispose?.())}};function hotkeysTaskSection(display){let detach=KEYBINDINGS["app.tasks.detach"],detachSelected=KEYBINDINGS["app.tasks.detachSelected"];return`
|
|
1786
|
+
`;content.addChild(new Markdown(header2+this.skillBlock.content,0,0,this.markdownTheme,{color:text2=>theme.fg("customMessageText",text2)}))}else{let line=theme.fg("customMessageLabel","\x1B[1m[skill]\x1B[22m ")+theme.fg("customMessageText",this.skillBlock.name)+theme.fg("dim",` (${keyText("app.tools.expand")} to expand)`);content.addChild(new Text(line,0,0))}this.addChild(new MouseRegion(content,event=>{if(!(event.type!=="click"||event.button!=="left"))return this.setExpanded(!this.expanded),{handled:!0}}))}};var THINKING_SELECT_LIST_LAYOUT={minPrimaryColumnWidth:12,maxPrimaryColumnWidth:32},LEVEL_DESCRIPTIONS={off:"No reasoning",minimal:"Very brief reasoning (~1k tokens)",low:"Light reasoning (~2k tokens)",medium:"Moderate reasoning (~8k tokens)",high:"Deep reasoning (~16k tokens)",xhigh:"Extra-high reasoning (~32k tokens)",max:"Maximum reasoning"},ThinkingSelectorComponent=class extends Container{get focused(){return this._focused}set focused(value){this._focused=value,this.searchInput.focused=value}constructor(currentLevel,availableLevels,onSelect,onCancel,onSelectAsDefault,defaultThinkingLevel){super(),this._focused=!1,this.onSelect=onSelect,this.onCancel=onCancel,this.onSelectAsDefault=onSelectAsDefault,this.allItems=availableLevels.map(level=>({value:level,label:`${level===currentLevel?"\u2713 ":" "}${level}`,description:level===defaultThinkingLevel?`${LEVEL_DESCRIPTIONS[level]} \xB7 default`:LEVEL_DESCRIPTIONS[level]})),this.addChild(new DynamicBorder),this.addChild(new Spacer(1)),this.addChild(new Text("Thinking Level",0,0)),this.addChild(new Spacer(1)),this.addChild(new Text(`${keyDisplayText("app.thinking.cycle")} cycles thinking levels in-session`,0,0)),this.addChild(new Spacer(1)),this.searchInput=new Input,this.searchInput.onSubmit=()=>this.selectList.handleInput("\r"),this.addChild(this.searchInput),this.addChild(new Spacer(1)),this.selectList=this.buildSelectList(this.allItems,currentLevel),this.selectListChildIndex=this.children.length,this.addChild(this.selectList),this.addChild(new Spacer(1)),this.addChild(new Text(theme.fg("dim",` ${keyDisplayText("tui.select.confirm")} to select \xB7 ${keyDisplayText("app.thinking.save")} to set as default \xB7 ${keyDisplayText("tui.select.cancel")} to cancel`),0,0)),this.addChild(new DynamicBorder)}buildSelectList(items,preselect){let list2=new SelectList(items,Math.max(1,items.length),getSelectListTheme(),THINKING_SELECT_LIST_LAYOUT),currentIndex=items.findIndex(item=>item.value===preselect);return currentIndex!==-1&&list2.setSelectedIndex(currentIndex),list2.onSelect=item=>this.onSelect(item.value),list2.onCancel=()=>this.onCancel(),list2}applyFilter(query){let filtered=query?fuzzyFilter(this.allItems,query,item=>`${item.value} ${item.description??""}`):this.allItems,selectedValue=this.selectList.getSelectedItem()?.value,newList=this.buildSelectList(filtered,selectedValue);this.children[this.selectListChildIndex]=newList,this.selectList=newList}handleInput(keyData){let kb=getKeybindings();if(kb.matches(keyData,"app.thinking.save")&&this.onSelectAsDefault){let item=this.selectList.getSelectedItem();item&&this.onSelectAsDefault(item.value);return}if(kb.matches(keyData,"tui.select.up")||kb.matches(keyData,"tui.select.down")||kb.matches(keyData,"tui.select.confirm")||kb.matches(keyData,"tui.select.cancel")){this.selectList.handleInput(keyData);return}this.searchInput.handleInput(keyData),this.applyFilter(this.searchInput.getValue())}getSelectList(){return this.selectList}};var FALLBACK_PREVIEW_LINES=10,DEFAULT_TOOL_ROW_GAP={afterTool:1,afterMultilineTool:1,afterOther:1},ToolExecutionComponent=class extends Container{constructor(toolName,toolCallId,args,options={},toolDefinition,ui,cwd){super(),this.leadingGap=1,this.selfRenderOffset=1,this.selfRenderHeight=0,this.rendererState={},this.imageComponents=[],this.imageSources=[],this.imageSpacers=[],this.expanded=!1,this.isPartial=!0,this.executionStarted=!1,this.argsComplete=!1,this.hideComponent=!1,this.disposed=!1,this.toolName=toolName,this.toolCallId=toolCallId,this.args=args,this.toolDefinition=toolDefinition,this.showImages=options.showImages??!0,this.imageWidthCells=options.imageWidthCells??60,this.outputPad=options.outputPad??1,this.ui=ui,this.cwd=cwd,this.gap=new Spacer(this.leadingGap),this.addChild(this.gap),this.contentBox=new Box(1,1,text2=>theme.bg("toolPendingBg",text2)),this.contentText=new Text("",1,1,text2=>theme.bg("toolPendingBg",text2)),this.contentTextRegion=this.createResultRegion(this.contentText),this.selfRenderContainer=new Container,this.hasRendererDefinition()?this.addChild(this.getRenderShell()==="self"?this.selfRenderContainer:this.contentBox):this.addChild(this.contentTextRegion),this.updateDisplay()}getShell(){if(this.toolDefinition?.renderShell!=="self")return this.toolDefinition?.shell}getCallRenderer(){return this.toolDefinition?.renderCall??this.getShell()?.renderCall}getResultRenderer(){return this.toolDefinition?.renderResult??this.getShell()?.renderResult}hasRendererDefinition(){return this.toolDefinition!==void 0}getRenderShell(){return this.toolDefinition?.renderShell==="self"||this.getShell()?"self":"default"}setLeadingGap(lines){this.leadingGap=Math.max(0,Math.floor(lines)),this.gap.setLines(this.leadingGap)}getToolRowGap(){return this.getShell()?.gap??DEFAULT_TOOL_ROW_GAP}getRenderContext(lastComponent){return{args:this.args,toolCallId:this.toolCallId,invalidate:()=>{this.disposed||(this.invalidate(),this.ui.requestRender())},lastComponent,state:this.rendererState,cwd:this.cwd,executionStarted:this.executionStarted,argsComplete:this.argsComplete,isPartial:this.isPartial,expanded:this.expanded,showImages:this.showImages,isError:this.result?.isError??!1,durationMs:this.isPartial?void 0:this.result?.durationMs,outputPad:this.outputPad,result:this.result?{content:this.result.content,details:this.result.details}:void 0}}frame(component,kind,lastComponent){let shell=this.getShell();return shell?shell.frame(component,kind,this.getRenderContext(lastComponent)):component}createCallFallback(){let shell=this.getShell();return shell?.renderCall?shell.renderCall(this.args,theme,this.getRenderContext(this.callRendererComponent)):new Text(formatToolCallWithArgs(this.toolName,this.args,theme,this.expanded),0,0)}createResultFallback(){let shell=this.getShell();if(shell?.renderResult&&this.result)return shell.renderResult({content:this.result.content,details:this.result.details},{expanded:this.expanded,isPartial:this.isPartial},theme,this.getRenderContext(this.resultRendererComponent));let output=this.getTextOutput();if(!output)return;let lines=output.split(`
|
|
1787
|
+
`),displayLines=this.expanded?lines:lines.slice(0,FALLBACK_PREVIEW_LINES),remaining=lines.length-displayLines.length,text2=displayLines.map(line=>theme.fg("toolOutput",line)).join(`
|
|
1788
|
+
`);return remaining>0&&(text2+=`${theme.fg("muted",`
|
|
1789
|
+
... (${remaining} more lines,`)} ${keyHint("app.tools.expand","to expand")}${theme.fg("muted",")")}`),new Text(text2,0,0)}hidesCollapsedResult(){return this.getShell()?.shouldHideResult?.(this.getRenderContext(this.resultRendererComponent))??!1}createResultRegion(component){return new MouseRegion(component,event=>{if(!(!this.result||event.type!=="click"||event.button!=="left"))return this.setExpanded(!this.expanded),{handled:!0}})}updateArgs(args){this.args=args,this.updateDisplay()}markExecutionStarted(){this.disposed||(this.executionStarted=!0,this.updateDisplay(),this.ui.requestRender())}setArgsComplete(){this.argsComplete=!0,this.updateDisplay(),this.ui.requestRender()}updateResult(result2,isPartial=!1){this.result=result2,this.isPartial=isPartial,this.updateDisplay()}setExpanded(expanded){this.expanded=expanded,this.updateDisplay()}setOutputPad(outputPad){this.outputPad=outputPad,this.updateDisplay()}setShowImages(show){this.showImages=show,this.updateDisplay()}setImageWidthCells(width){this.imageWidthCells=Math.max(1,Math.floor(width)),this.updateDisplay()}invalidate(){super.invalidate(),this.updateDisplay()}render(width){if(this.hideComponent)return[];if(this.hasRendererDefinition()&&this.getRenderShell()==="self"){let contentLines=this.selfRenderContainer.render(width);this.selfRenderHeight=contentLines.length;let leadingLines=contentLines.length>0?this.gap.render(width):[];if(this.selfRenderOffset=leadingLines.length,contentLines.length===0&&this.imageComponents.length===0)return[];let lines=[...leadingLines,...contentLines];for(let i=0;i<this.imageComponents.length;i++){let spacer=this.imageSpacers[i];spacer&&lines.push(...spacer.render(width));let imageComponent=this.imageComponents[i];imageComponent&&lines.push(...imageComponent.render(width))}return lines}return super.render(width)}handleMouse(event){if(!this.hasRendererDefinition()||this.getRenderShell()!=="self")return super.handleMouse(event);if(!(event.y<this.selfRenderOffset||event.y>=this.selfRenderOffset+this.selfRenderHeight))return this.selfRenderContainer.handleMouse({...event,y:event.y-this.selfRenderOffset,height:this.selfRenderHeight})}updateDisplay(){let bgFn=this.isPartial?text2=>theme.bg("toolPendingBg",text2):this.result?.isError?text2=>theme.bg("toolErrorBg",text2):text2=>theme.bg("toolSuccessBg",text2),hasContent=!1;if(this.hideComponent=!1,this.hasRendererDefinition()){let renderContainer=this.getRenderShell()==="self"?this.selfRenderContainer:this.contentBox;renderContainer instanceof Box&&(renderContainer.setBgFn(bgFn),renderContainer.setPaddingX(this.outputPad)),renderContainer.clear();let addCall=component=>{renderContainer.addChild(this.createResultRegion(this.frame(component,"header",this.callRendererComponent))),hasContent=!0},addResult=component=>{renderContainer.addChild(this.createResultRegion(this.frame(component,"body",this.resultRendererComponent))),hasContent=!0},callRenderer=this.getCallRenderer();if(!callRenderer)addCall(this.createCallFallback());else try{let component=callRenderer(this.args,theme,this.getRenderContext(this.callRendererComponent));this.callRendererComponent=component,addCall(component)}catch{this.callRendererComponent=void 0,addCall(this.createCallFallback())}if(this.result&&!this.hidesCollapsedResult()){let resultRenderer=this.getResultRenderer();if(resultRenderer)try{let component=resultRenderer({content:this.result.content,details:this.result.details},{expanded:this.expanded,isPartial:this.isPartial},theme,this.getRenderContext(this.resultRendererComponent));this.resultRendererComponent=component,addResult(component)}catch{this.resultRendererComponent=void 0;let component=this.createResultFallback();component&&addResult(component)}else{let component=this.createResultFallback();component&&addResult(component)}}}else this.contentText.setCustomBgFn(bgFn),this.contentText.setPaddingX(this.outputPad),this.contentText.setText(this.formatToolExecution()),hasContent=!0;let previousImages=this.imageComponents,previousSources=this.imageSources;for(let img of this.imageComponents)this.removeChild(img);this.imageComponents=[],this.imageSources=[];for(let spacer of this.imageSpacers)this.removeChild(spacer);if(this.imageSpacers=[],this.result){let imageBlocks=this.result.content.filter(c=>c.type==="image"),caps=getCapabilities();for(let img of imageBlocks)if(caps.images&&this.showImages&&img.data&&img.mimeType){let spacer=new Spacer(1);this.addChild(spacer),this.imageSpacers.push(spacer);let source={data:img.data,mimeType:img.mimeType,widthCells:this.imageWidthCells},index3=this.imageComponents.length,previous=previousSources[index3],imageComponent=previous?.data===source.data&&previous.mimeType===source.mimeType&&previous.widthCells===source.widthCells?previousImages[index3]:new Image(source.data,source.mimeType,{fallbackColor:s=>theme.fg("toolOutput",s)},{maxWidthCells:source.widthCells});source.mimeType!=="image/png"&&ensurePngTranscoder(()=>{this.disposed||(this.invalidate(),this.ui.requestRender())}),this.imageComponents.push(imageComponent),this.imageSources.push(source),this.addChild(imageComponent)}}this.hasRendererDefinition()&&!hasContent&&this.imageComponents.length===0&&(this.hideComponent=!0)}getTextOutput(){return getTextOutput(this.result,this.showImages)}formatToolExecution(){let text2=theme.fg("toolTitle",theme.bold(this.toolName)),content=JSON.stringify(this.args,null,2);content&&(text2+=`
|
|
1790
|
+
|
|
1791
|
+
${content}`);let output=this.getTextOutput();return output&&(text2+=`
|
|
1792
|
+
${output}`),text2}dispose(){this.disposed||(this.disposed=!0,this.rendererState.dispose?.())}};var TREE_GUTTER_WIDTH=2,MIN_VISIBLE_ANCHOR_CONTENT_WIDTH=4,MAX_VISIBLE_ANCHOR_CONTENT_WIDTH=20,MIN_ANCHOR_CONTEXT_WIDTH=2,MAX_ANCHOR_CONTEXT_WIDTH=12;function renderHorizontalViewport(rows,width){let viewportWidth=Math.max(0,width-TREE_GUTTER_WIDTH),maxBodyWidth=rows.reduce((max,row)=>Math.max(max,row.bodyWidth),0),maxHorizontalScroll=Math.max(0,maxBodyWidth-viewportWidth),selectedRow=rows.find(row=>row.isSelected),horizontalScroll=0;if(selectedRow&&maxHorizontalScroll>0){let minVisibleAnchorContentWidth=Math.min(MAX_VISIBLE_ANCHOR_CONTENT_WIDTH,Math.max(MIN_VISIBLE_ANCHOR_CONTENT_WIDTH,Math.floor(viewportWidth/3)));if(selectedRow.anchorCol>viewportWidth-minVisibleAnchorContentWidth){let anchorContextWidth=Math.min(MAX_ANCHOR_CONTEXT_WIDTH,Math.max(MIN_ANCHOR_CONTEXT_WIDTH,Math.floor(viewportWidth/4)));horizontalScroll=Math.min(maxHorizontalScroll,selectedRow.anchorCol-anchorContextWidth)}}return rows.map(row=>{let line=horizontalScroll>0?`${row.gutter}${sliceByColumn(row.body,horizontalScroll,viewportWidth,!0)}\x1B[0m`:row.gutter+row.body;return truncateToWidth(line,width,"")})}var TreeList=class{constructor(tree,currentLeafId,maxVisibleLines,initialSelectedId,initialFilterMode){this.flatNodes=[],this.filteredNodes=[],this.selectedIndex=0,this.filterMode="default",this.searchQuery="",this.toolCallMap=new Map,this.multipleRoots=!1,this.showLabelTimestamps=!1,this.activePathIds=new Set,this.visibleParentMap=new Map,this.visibleChildrenMap=new Map,this.lastSelectedId=null,this.foldedNodes=new Set,this.currentLeafId=currentLeafId,this.maxVisibleLines=maxVisibleLines,this.filterMode=initialFilterMode??"default",this.multipleRoots=tree.length>1,this.flatNodes=this.flattenTree(tree),this.buildActivePath(),this.applyFilter();let targetId=initialSelectedId??currentLeafId;this.selectedIndex=this.findNearestVisibleIndex(targetId),this.lastSelectedId=this.filteredNodes[this.selectedIndex]?.node.entry.id??null}findNearestVisibleIndex(entryId){if(this.filteredNodes.length===0)return 0;let entryMap=new Map;for(let flatNode of this.flatNodes)entryMap.set(flatNode.node.entry.id,flatNode);let visibleIdToIndex=new Map(this.filteredNodes.map((node,i)=>[node.node.entry.id,i])),currentId=entryId;for(;currentId!==null;){let index3=visibleIdToIndex.get(currentId);if(index3!==void 0)return index3;let node=entryMap.get(currentId);if(!node)break;currentId=node.node.entry.parentId??null}return this.filteredNodes.length-1}buildActivePath(){if(this.activePathIds.clear(),!this.currentLeafId)return;let entryMap=new Map;for(let flatNode of this.flatNodes)entryMap.set(flatNode.node.entry.id,flatNode);let currentId=this.currentLeafId;for(;currentId;){this.activePathIds.add(currentId);let node=entryMap.get(currentId);if(!node)break;currentId=node.node.entry.parentId??null}}flattenTree(roots){let result2=[];this.toolCallMap.clear();let stack=[],containsActive=new Map,leafId=this.currentLeafId;{let allNodes=[],preOrderStack=[...roots];for(;preOrderStack.length>0;){let node=preOrderStack.pop();allNodes.push(node);for(let i=node.children.length-1;i>=0;i--)preOrderStack.push(node.children[i])}for(let i=allNodes.length-1;i>=0;i--){let node=allNodes[i],has=leafId!==null&&node.entry.id===leafId;for(let child of node.children)containsActive.get(child)&&(has=!0);containsActive.set(node,has)}}let multipleRoots=roots.length>1,orderedRoots=[...roots].sort((a,b2)=>Number(containsActive.get(b2))-Number(containsActive.get(a)));for(let i=orderedRoots.length-1;i>=0;i--){let isLast=i===orderedRoots.length-1;stack.push([orderedRoots[i],multipleRoots?1:0,multipleRoots,multipleRoots,isLast,[],multipleRoots])}for(;stack.length>0;){let[node,indent,justBranched,showConnector,isLast,gutters,isVirtualRootChild]=stack.pop(),entry=node.entry;if(entry.type==="message"&&entry.message.role==="assistant"){let content=entry.message.content;if(Array.isArray(content)){for(let block of content)if(typeof block=="object"&&block!==null&&"type"in block&&block.type==="toolCall"){let tc=block;this.toolCallMap.set(tc.id,{name:tc.name,arguments:tc.arguments})}}}result2.push({node,indent,showConnector,isLast,gutters,isVirtualRootChild});let children=node.children,multipleChildren=children.length>1,orderedChildren=(()=>{let prioritized=[],rest=[];for(let child of children)containsActive.get(child)?prioritized.push(child):rest.push(child);return[...prioritized,...rest]})(),childIndent;multipleChildren||justBranched&&indent>0?childIndent=indent+1:childIndent=indent;let connectorDisplayed=showConnector&&!isVirtualRootChild,currentDisplayIndent=this.multipleRoots?Math.max(0,indent-1):indent,connectorPosition=Math.max(0,currentDisplayIndent-1),childGutters=connectorDisplayed?[...gutters,{position:connectorPosition,show:!isLast}]:gutters;for(let i=orderedChildren.length-1;i>=0;i--){let childIsLast=i===orderedChildren.length-1;stack.push([orderedChildren[i],childIndent,multipleChildren,multipleChildren,childIsLast,childGutters,!1])}}return result2}applyFilter(){this.filteredNodes.length>0&&(this.lastSelectedId=this.filteredNodes[this.selectedIndex]?.node.entry.id??this.lastSelectedId);let searchTokens=this.searchQuery.toLowerCase().split(/\s+/).filter(Boolean);if(this.filteredNodes=this.flatNodes.filter(flatNode=>{let entry=flatNode.node.entry;if(entry.type==="usage")return!1;let isCurrentLeaf=entry.id===this.currentLeafId;if(entry.type==="message"&&entry.message.role==="assistant"&&!isCurrentLeaf){let msg=entry.message,hasText=this.hasTextContent(msg.content),isErrorOrAborted=msg.stopReason&&msg.stopReason!=="stop"&&msg.stopReason!=="toolUse";if(!hasText&&!isErrorOrAborted)return!1}let passesFilter=!0,isSettingsEntry=entry.type==="label"||entry.type==="context_edit"||entry.type==="custom"||entry.type==="model_change"||entry.type==="thinking_level_change"||entry.type==="session_info";switch(this.filterMode){case"user-only":passesFilter=entry.type==="message"&&entry.message.role==="user";break;case"no-tools":passesFilter=!isSettingsEntry&&!(entry.type==="message"&&entry.message.role==="toolResult");break;case"labeled-only":passesFilter=flatNode.node.label!==void 0;break;case"all":passesFilter=!0;break;default:passesFilter=!isSettingsEntry;break}if(!passesFilter)return!1;if(searchTokens.length>0){let nodeText=this.getSearchableText(flatNode.node).toLowerCase();return searchTokens.every(token=>nodeText.includes(token))}return!0}),this.foldedNodes.size>0){let skipSet=new Set;for(let flatNode of this.flatNodes){let{id,parentId}=flatNode.node.entry;parentId!=null&&(this.foldedNodes.has(parentId)||skipSet.has(parentId))&&skipSet.add(id)}this.filteredNodes=this.filteredNodes.filter(flatNode=>!skipSet.has(flatNode.node.entry.id))}this.recalculateVisualStructure(),this.lastSelectedId?this.selectedIndex=this.findNearestVisibleIndex(this.lastSelectedId):this.selectedIndex>=this.filteredNodes.length&&(this.selectedIndex=Math.max(0,this.filteredNodes.length-1)),this.filteredNodes.length>0&&(this.lastSelectedId=this.filteredNodes[this.selectedIndex]?.node.entry.id??this.lastSelectedId)}recalculateVisualStructure(){if(this.filteredNodes.length===0)return;let visibleIds=new Set(this.filteredNodes.map(n=>n.node.entry.id)),entryMap=new Map;for(let flatNode of this.flatNodes)entryMap.set(flatNode.node.entry.id,flatNode);let findVisibleAncestor=nodeId=>{let currentId=entryMap.get(nodeId)?.node.entry.parentId??null;for(;currentId!==null;){if(visibleIds.has(currentId))return currentId;currentId=entryMap.get(currentId)?.node.entry.parentId??null}return null},visibleParent=new Map,visibleChildren=new Map;visibleChildren.set(null,[]);for(let flatNode of this.filteredNodes){let nodeId=flatNode.node.entry.id,ancestorId=findVisibleAncestor(nodeId);visibleParent.set(nodeId,ancestorId),visibleChildren.has(ancestorId)||visibleChildren.set(ancestorId,[]),visibleChildren.get(ancestorId).push(nodeId)}let visibleRootIds=visibleChildren.get(null);this.multipleRoots=visibleRootIds.length>1;let filteredNodeMap=new Map;for(let flatNode of this.filteredNodes)filteredNodeMap.set(flatNode.node.entry.id,flatNode);let stack=[];for(let i=visibleRootIds.length-1;i>=0;i--){let isLast=i===visibleRootIds.length-1;stack.push([visibleRootIds[i],this.multipleRoots?1:0,this.multipleRoots,this.multipleRoots,isLast,[],this.multipleRoots])}for(;stack.length>0;){let[nodeId,indent,justBranched,showConnector,isLast,gutters,isVirtualRootChild]=stack.pop(),flatNode=filteredNodeMap.get(nodeId);if(!flatNode)continue;flatNode.indent=indent,flatNode.showConnector=showConnector,flatNode.isLast=isLast,flatNode.gutters=gutters,flatNode.isVirtualRootChild=isVirtualRootChild;let children=visibleChildren.get(nodeId)||[],multipleChildren=children.length>1,childIndent;multipleChildren||justBranched&&indent>0?childIndent=indent+1:childIndent=indent;let connectorDisplayed=showConnector&&!isVirtualRootChild,currentDisplayIndent=this.multipleRoots?Math.max(0,indent-1):indent,connectorPosition=Math.max(0,currentDisplayIndent-1),childGutters=connectorDisplayed?[...gutters,{position:connectorPosition,show:!isLast}]:gutters;for(let i=children.length-1;i>=0;i--){let childIsLast=i===children.length-1;stack.push([children[i],childIndent,multipleChildren,multipleChildren,childIsLast,childGutters,!1])}}this.visibleParentMap=visibleParent,this.visibleChildrenMap=visibleChildren}getSearchableText(node){let entry=node.entry,parts=[];switch(node.label&&parts.push(node.label),entry.type){case"message":{let msg=entry.message;if(parts.push(msg.role),"content"in msg&&msg.content&&parts.push(this.extractContent(msg.content)),msg.role==="bashExecution"){let bashMsg=msg;bashMsg.command&&parts.push(bashMsg.command)}break}case"custom_message":{parts.push(entry.customType),typeof entry.content=="string"?parts.push(entry.content):parts.push(this.extractContent(entry.content));break}case"compaction":parts.push("compaction");break;case"branch_summary":parts.push("branch summary",entry.summary);break;case"session_info":parts.push("title"),entry.name&&parts.push(entry.name);break;case"model_change":parts.push("model",entry.modelId);break;case"thinking_level_change":parts.push("thinking",entry.thinkingLevel);break;case"custom":parts.push("custom",entry.customType);break;case"context_edit":parts.push("context edit",entry.replacement===null?"omit":"replace",entry.targetId);break;case"label":parts.push("label",entry.label??"");break}return parts.join(" ")}invalidate(){}getSearchQuery(){return this.searchQuery}getSelectedNode(){return this.filteredNodes[this.selectedIndex]?.node}copySelected(){let node=this.getSelectedNode();this.onCopy?.(node?this.getEntryCopyText(node):void 0)}updateNodeLabel(entryId,label,labelTimestamp){for(let flatNode of this.flatNodes)if(flatNode.node.entry.id===entryId){flatNode.node.label=label,flatNode.node.labelTimestamp=label?labelTimestamp??new Date().toISOString():void 0;break}}getStatusLabels(){let labels="";switch(this.filterMode){case"no-tools":labels+=" [no-tools]";break;case"user-only":labels+=" [user]";break;case"labeled-only":labels+=" [labeled]";break;case"all":labels+=" [all]";break}return this.showLabelTimestamps&&(labels+=" [+label time]"),labels}render(width){let lines=[];if(this.filteredNodes.length===0)return lines.push(truncateToWidth(theme.fg("muted"," No entries found"),width)),lines.push(truncateToWidth(theme.fg("muted",` (0/0)${this.getStatusLabels()}`),width)),lines;let startIndex=Math.max(0,Math.min(this.selectedIndex-Math.floor(this.maxVisibleLines/2),this.filteredNodes.length-this.maxVisibleLines)),endIndex=Math.min(startIndex+this.maxVisibleLines,this.filteredNodes.length),renderedRows=[];for(let i=startIndex;i<endIndex;i++){let flatNode=this.filteredNodes[i],entry=flatNode.node.entry,isSelected2=i===this.selectedIndex,cursor=isSelected2?theme.fg("accent","\u203A "):" ",displayIndent=this.multipleRoots?Math.max(0,flatNode.indent-1):flatNode.indent,connector=flatNode.showConnector&&!flatNode.isVirtualRootChild?flatNode.isLast?"\u2514\u2500 ":"\u251C\u2500 ":"",connectorPosition=connector?displayIndent-1:-1,totalChars=displayIndent*3,prefixChars=[],isFolded=this.foldedNodes.has(entry.id);for(let i2=0;i2<totalChars;i2++){let level=Math.floor(i2/3),posInLevel=i2%3,gutter2=flatNode.gutters.find(g=>g.position===level);if(gutter2)posInLevel===0?prefixChars.push(gutter2.show?"\u2502":" "):prefixChars.push(" ");else if(connector&&level===connectorPosition)if(posInLevel===0)prefixChars.push(flatNode.isLast?"\u2514":"\u251C");else if(posInLevel===1){let foldable=this.isFoldable(entry.id);prefixChars.push(isFolded?"\u229E":foldable?"\u229F":"\u2500")}else prefixChars.push(" ");else prefixChars.push(" ")}let prefix=prefixChars.join(""),showsFoldInConnector=flatNode.showConnector&&!flatNode.isVirtualRootChild,foldMarker=isFolded&&!showsFoldInConnector?theme.fg("accent","\u229E "):"",pathMarker=this.activePathIds.has(entry.id)?theme.fg("accent","\u2022 "):"",label=flatNode.node.label?theme.fg("warning",`[${flatNode.node.label}] `):"",labelTimestamp=this.showLabelTimestamps&&flatNode.node.label&&flatNode.node.labelTimestamp?theme.fg("muted",`${this.formatLabelTimestamp(flatNode.node.labelTimestamp)} `):"",content=this.getEntryDisplayText(flatNode.node,isSelected2),prefixPart=theme.fg("dim",prefix)+foldMarker+pathMarker,anchorCol=visibleWidth(prefixPart),gutter=cursor,body2=prefixPart+label+labelTimestamp+content;isSelected2&&(gutter=theme.bg("selectedBg",gutter),body2=theme.bg("selectedBg",body2)),renderedRows.push({gutter,body:body2,anchorCol,bodyWidth:visibleWidth(body2),isSelected:isSelected2})}return lines.push(...renderHorizontalViewport(renderedRows,width)),lines.push(truncateToWidth(theme.fg("muted",` (${this.selectedIndex+1}/${this.filteredNodes.length})${this.getStatusLabels()}`),width)),lines}getEntryDisplayText(node,isSelected2){let entry=node.entry,result2,normalize2=s=>s.replace(/[\n\t]/g," ").trim();switch(entry.type){case"message":{let msg=entry.message,role=msg.role;if(role==="user"){let msgWithContent=msg,content=normalize2(this.extractContent(msgWithContent.content));result2=theme.fg("accent","user: ")+content}else if(role==="assistant"){let msgWithContent=msg,textContent=normalize2(this.extractContent(msgWithContent.content));if(textContent)result2=theme.fg("success","assistant: ")+textContent;else if(msgWithContent.stopReason==="aborted")result2=theme.fg("success","assistant: ")+theme.fg("muted","(aborted)");else if(msgWithContent.errorMessage){let errMsg=normalize2(msgWithContent.errorMessage).slice(0,80);result2=theme.fg("success","assistant: ")+theme.fg("error",errMsg)}else result2=theme.fg("success","assistant: ")+theme.fg("muted","(no content)")}else if(role==="toolResult"){let toolMsg=msg,toolCall=toolMsg.toolCallId?this.toolCallMap.get(toolMsg.toolCallId):void 0;toolCall?result2=theme.fg("muted",this.formatToolCall(toolCall.name,toolCall.arguments)):result2=theme.fg("muted",`[${toolMsg.toolName??"tool"}]`)}else if(role==="bashExecution"){let bashMsg=msg;result2=theme.fg("dim",`[bash]: ${normalize2(bashMsg.command??"")}`)}else result2=theme.fg("dim",`[${role}]`);break}case"custom_message":{let content=typeof entry.content=="string"?entry.content:entry.content.filter(c=>c.type==="text").map(c=>c.text).join("");result2=theme.fg("customMessageLabel",`[${entry.customType}]: `)+normalize2(content);break}case"compaction":{let tokens2=Math.round(entry.tokensBefore/1e3);result2=theme.fg("borderAccent",`[compaction: ${tokens2}k tokens]`);break}case"branch_summary":result2=theme.fg("warning","[branch summary]: ")+normalize2(entry.summary);break;case"model_change":result2=theme.fg("dim",`[model: ${entry.modelId}]`);break;case"thinking_level_change":result2=theme.fg("dim",`[thinking: ${entry.thinkingLevel}]`);break;case"custom":result2=theme.fg("dim",`[custom: ${entry.customType}]`);break;case"context_edit":result2=theme.fg("dim",`[context ${entry.replacement===null?"omit":"replace"}: ${entry.targetId}]`);break;case"label":result2=theme.fg("dim",`[label: ${entry.label??"(cleared)"}]`);break;case"session_info":result2=entry.name?[theme.fg("dim","[title: "),theme.fg("dim",entry.name),theme.fg("dim","]")].join(""):[theme.fg("dim","[title: "),theme.italic(theme.fg("dim","empty")),theme.fg("dim","]")].join("");break;default:result2=""}return isSelected2?theme.bold(result2):result2}formatLabelTimestamp(timestamp){let date=new Date(timestamp),now=new Date,hours=date.getHours().toString().padStart(2,"0"),minutes=date.getMinutes().toString().padStart(2,"0"),time2=`${hours}:${minutes}`;if(date.getFullYear()===now.getFullYear()&&date.getMonth()===now.getMonth()&&date.getDate()===now.getDate())return time2;let month=date.getMonth()+1,day=date.getDate();return date.getFullYear()===now.getFullYear()?`${month}/${day} ${time2}`:`${date.getFullYear().toString().slice(-2)}/${month}/${day} ${time2}`}extractContent(content){return this.extractFullContent(content).slice(0,200)}extractFullContent(content){if(typeof content=="string")return content;if(!Array.isArray(content))return"";let result2="";for(let block of content)typeof block=="object"&&block!==null&&"type"in block&&block.type==="text"&&(result2+=block.text);return result2}getEntryCopyText(node){let entry=node.entry,text2;switch(entry.type){case"message":entry.message.role==="bashExecution"?text2=entry.message.command:"content"in entry.message&&(text2=this.extractFullContent(entry.message.content),!text2&&entry.message.role==="assistant"&&(text2=entry.message.errorMessage));break;case"custom_message":text2=this.extractFullContent(entry.content);break;case"compaction":text2=entry.summary;break;case"branch_summary":text2=entry.summary;break}return text2?.trim()?text2:void 0}hasTextContent(content){if(typeof content=="string")return content.trim().length>0;if(Array.isArray(content)){for(let c of content)if(typeof c=="object"&&c!==null&&"type"in c&&c.type==="text"){let text2=c.text;if(text2&&text2.trim().length>0)return!0}}return!1}formatToolCall(name,args){let shortenPath3=p=>{let home=process.env.HOME||process.env.USERPROFILE||"";return home&&p.startsWith(home)?`~${p.slice(home.length)}`:p};switch(name){case"read":return`[read: ${shortenPath3(String(args.path||args.file_path||""))}${formatReadLineRange(args.offset,args.limit)}]`;case"write":return`[write: ${shortenPath3(String(args.path||args.file_path||""))}]`;case"edit":return`[edit: ${shortenPath3(String(args.path||args.file_path||""))}]`;case"bash":{let rawCmd=String(args.command||"");return`[bash: ${rawCmd.replace(/[\n\t]/g," ").trim().slice(0,50)}${rawCmd.length>50?"...":""}]`}case"grep":{let pattern=String(args.pattern||""),path14=shortenPath3(String(args.path||"."));return`[grep: /${pattern}/ in ${path14}]`}case"find":{let pattern=String(args.pattern||""),path14=shortenPath3(String(args.path||"."));return`[find: ${pattern} in ${path14}]`}case"ls":return`[ls: ${shortenPath3(String(args.path||"."))}]`;default:{let argsStr=JSON.stringify(args).slice(0,40);return`[${name}: ${argsStr}${JSON.stringify(args).length>40?"...":""}]`}}}handleInput(keyData){let kb=getKeybindings();if(kb.matches(keyData,"tui.select.up"))this.selectedIndex=this.selectedIndex===0?this.filteredNodes.length-1:this.selectedIndex-1;else if(kb.matches(keyData,"tui.select.down"))this.selectedIndex=this.selectedIndex===this.filteredNodes.length-1?0:this.selectedIndex+1;else if(kb.matches(keyData,"app.tree.foldOrUp")){let currentId=this.filteredNodes[this.selectedIndex]?.node.entry.id;currentId&&this.isFoldable(currentId)&&!this.foldedNodes.has(currentId)?(this.foldedNodes.add(currentId),this.applyFilter()):this.selectedIndex=this.findBranchSegmentStart("up")}else if(kb.matches(keyData,"app.tree.unfoldOrDown")){let currentId=this.filteredNodes[this.selectedIndex]?.node.entry.id;currentId&&this.foldedNodes.has(currentId)?(this.foldedNodes.delete(currentId),this.applyFilter()):this.selectedIndex=this.findBranchSegmentStart("down")}else if(kb.matches(keyData,"tui.editor.cursorLeft")||kb.matches(keyData,"tui.select.pageUp"))this.selectedIndex=Math.max(0,this.selectedIndex-this.maxVisibleLines);else if(kb.matches(keyData,"tui.editor.cursorRight")||kb.matches(keyData,"tui.select.pageDown"))this.selectedIndex=Math.min(this.filteredNodes.length-1,this.selectedIndex+this.maxVisibleLines);else if(kb.matches(keyData,"tui.select.confirm")){let selected=this.filteredNodes[this.selectedIndex];selected&&this.onSelect&&this.onSelect(selected.node.entry.id)}else if(kb.matches(keyData,"app.message.copy"))this.copySelected();else if(kb.matches(keyData,"tui.select.cancel"))this.searchQuery?(this.searchQuery="",this.foldedNodes.clear(),this.applyFilter()):this.onCancel?.();else if(kb.matches(keyData,"app.tree.filter.default"))this.filterMode="default",this.foldedNodes.clear(),this.applyFilter();else if(kb.matches(keyData,"app.tree.filter.noTools"))this.filterMode=this.filterMode==="no-tools"?"default":"no-tools",this.foldedNodes.clear(),this.applyFilter();else if(kb.matches(keyData,"app.tree.filter.userOnly"))this.filterMode=this.filterMode==="user-only"?"default":"user-only",this.foldedNodes.clear(),this.applyFilter();else if(kb.matches(keyData,"app.tree.filter.labeledOnly"))this.filterMode=this.filterMode==="labeled-only"?"default":"labeled-only",this.foldedNodes.clear(),this.applyFilter();else if(kb.matches(keyData,"app.tree.filter.all"))this.filterMode=this.filterMode==="all"?"default":"all",this.foldedNodes.clear(),this.applyFilter();else if(kb.matches(keyData,"app.tree.filter.cycleBackward")){let modes=["default","no-tools","user-only","labeled-only","all"],currentIndex=modes.indexOf(this.filterMode);this.filterMode=modes[(currentIndex-1+modes.length)%modes.length],this.foldedNodes.clear(),this.applyFilter()}else if(kb.matches(keyData,"app.tree.filter.cycleForward")){let modes=["default","no-tools","user-only","labeled-only","all"],currentIndex=modes.indexOf(this.filterMode);this.filterMode=modes[(currentIndex+1)%modes.length],this.foldedNodes.clear(),this.applyFilter()}else if(kb.matches(keyData,"tui.editor.deleteCharBackward"))this.searchQuery.length>0&&(this.searchQuery=this.searchQuery.slice(0,-1),this.foldedNodes.clear(),this.applyFilter());else if(kb.matches(keyData,"app.tree.editLabel")){let selected=this.filteredNodes[this.selectedIndex];selected&&this.onLabelEdit&&this.onLabelEdit(selected.node.entry.id,selected.node.label)}else kb.matches(keyData,"app.tree.toggleLabelTimestamp")?this.showLabelTimestamps=!this.showLabelTimestamps:![...keyData].some(ch=>{let code=ch.charCodeAt(0);return code<32||code===127||code>=128&&code<=159})&&keyData.length>0&&(this.searchQuery+=keyData,this.foldedNodes.clear(),this.applyFilter())}isFoldable(entryId){let children=this.visibleChildrenMap.get(entryId);if(!children||children.length===0)return!1;let parentId=this.visibleParentMap.get(entryId);if(parentId==null)return!0;let siblings=this.visibleChildrenMap.get(parentId);return siblings!==void 0&&siblings.length>1}findBranchSegmentStart(direction){let selectedId=this.filteredNodes[this.selectedIndex]?.node.entry.id;if(!selectedId)return this.selectedIndex;let indexByEntryId=new Map(this.filteredNodes.map((node,i)=>[node.node.entry.id,i])),currentId=selectedId;if(direction==="down")for(;;){let children=this.visibleChildrenMap.get(currentId)??[];if(children.length===0)return indexByEntryId.get(currentId);if(children.length>1)return indexByEntryId.get(children[0]);currentId=children[0]}for(;;){let parentId=this.visibleParentMap.get(currentId)??null;if(parentId===null)return indexByEntryId.get(currentId);if((this.visibleChildrenMap.get(parentId)??[]).length>1){let segmentStart=indexByEntryId.get(currentId);if(segmentStart<this.selectedIndex)return segmentStart}currentId=parentId}}},SearchLine=class{constructor(treeList){this.treeList=treeList}invalidate(){}render(width){let query=this.treeList.getSearchQuery();return query?[truncateToWidth(` ${theme.fg("muted","Type to search:")} ${theme.fg("accent",query)}`,width)]:[truncateToWidth(` ${theme.fg("muted","Type to search:")}`,width)]}handleInput(_keyData){}},TreeHelp=class{invalidate(){}render(width){let items=TREE_HELP_ITEMS.map(({keys,label,labelFirst})=>{let text2=formatHelpKeys(keys);return text2?labelFirst?`${label} ${text2}`:`${text2} ${label}`:label}),availableWidth=Math.max(1,width),indent=" ",separator=" \xB7 ",lines=[],currentLine="";for(let item of items){let candidate=currentLine?`${currentLine}${separator}${item}`:visibleWidth(`${indent}${item}`)<=availableWidth?`${indent}${item}`:item;if(!currentLine||visibleWidth(candidate)<=availableWidth){currentLine=candidate;continue}lines.push(...wrapTextWithAnsi(currentLine.trimEnd(),availableWidth)),currentLine=visibleWidth(`${indent}${item}`)<=availableWidth?`${indent}${item}`:item}return currentLine&&lines.push(...wrapTextWithAnsi(currentLine.trimEnd(),availableWidth)),lines.map(line=>theme.fg("muted",line))}},TREE_HELP_ITEMS=[{keys:["tui.select.up","tui.select.down"],label:"move"},{keys:["tui.editor.cursorLeft","tui.editor.cursorRight"],label:"page"},{keys:["app.tree.foldOrUp","app.tree.unfoldOrDown"],label:"branch"},{keys:["app.message.copy"],label:"copy"},{keys:["app.tree.editLabel"],label:"label"},{keys:["app.tree.toggleLabelTimestamp"],label:"label time"},{keys:["app.tree.filter.default","app.tree.filter.noTools","app.tree.filter.userOnly","app.tree.filter.labeledOnly","app.tree.filter.all"],label:"filters",labelFirst:!0},{keys:["app.tree.filter.cycleForward","app.tree.filter.cycleBackward"],label:"cycle",labelFirst:!0}];function formatHelpKeys(keybindings){let keys=[];for(let keybinding of keybindings){let key=getKeybindings().getKeys(keybinding)[0];key!==void 0&&keys.push(key)}return keys.length===0?"":formatKeyText(compactRawKeys(keys)).replace(/\bpageUp\b/g,"pgup").replace(/\bpageDown\b/g,"pgdn").replace(/\bup\b/g,"\u2191").replace(/\bdown\b/g,"\u2193").replace(/\bleft\b/g,"\u2190").replace(/\bright\b/g,"\u2192")}function compactRawKeys(keys){if(keys.length===1)return keys[0];let parts=keys.map(key=>{let separatorIndex=key.lastIndexOf("+");return separatorIndex===-1?{prefix:"",suffix:key}:{prefix:key.slice(0,separatorIndex+1),suffix:key.slice(separatorIndex+1)}}),prefix=parts[0].prefix;return prefix&&parts.every(part=>part.prefix===prefix)?`${prefix}${parts.map(part=>part.suffix).join("/")}`:keys.join("/")}var LabelInput=class{get focused(){return this._focused}set focused(value){this._focused=value,this.input.focused=value}constructor(entryId,currentLabel){this._focused=!1,this.entryId=entryId,this.input=new Input,currentLabel&&this.input.setValue(currentLabel)}invalidate(){}render(width){let lines=[],availableWidth=width-2;return lines.push(truncateToWidth(` ${theme.fg("muted","Label (empty to remove):")}`,width)),lines.push(...this.input.render(availableWidth).map(line=>truncateToWidth(` ${line}`,width))),lines.push(truncateToWidth(` ${keyHint("tui.select.confirm","save")} ${keyHint("tui.select.cancel","cancel")}`,width)),lines}handleInput(keyData){let kb=getKeybindings();if(kb.matches(keyData,"tui.select.confirm")){let value=this.input.getValue().trim();this.onSubmit?.(this.entryId,value||void 0)}else kb.matches(keyData,"tui.select.cancel")?this.onCancel?.():this.input.handleInput(keyData)}},TreeSelectorComponent=class extends Container{get focused(){return this._focused}set focused(value){this._focused=value,this.labelInput&&(this.labelInput.focused=value)}constructor(tree,currentLeafId,terminalHeight,onSelect,onCancel,onLabelChange,initialSelectedId,initialFilterMode){super(),this.labelInput=null,this._focused=!1,this.onLabelChangeCallback=onLabelChange;let maxVisibleLines=Math.max(5,Math.floor(terminalHeight/2));this.treeList=new TreeList(tree,currentLeafId,maxVisibleLines,initialSelectedId,initialFilterMode),this.treeList.onSelect=onSelect,this.treeList.onCancel=onCancel,this.treeList.onCopy=text2=>this.onCopy?.(text2),this.treeList.onLabelEdit=(entryId,currentLabel)=>this.showLabelInput(entryId,currentLabel),this.treeContainer=new Container,this.treeContainer.addChild(this.treeList),this.labelInputContainer=new Container,this.addChild(new Spacer(1)),this.addChild(new DynamicBorder),this.addChild(new Text(theme.bold(" Session Tree"),1,0)),this.addChild(new TreeHelp),this.addChild(new SearchLine(this.treeList)),this.addChild(new DynamicBorder),this.addChild(new Spacer(1)),this.addChild(this.treeContainer),this.addChild(this.labelInputContainer),this.addChild(new Spacer(1)),this.addChild(new DynamicBorder),tree.length===0&&setTimeout(()=>onCancel(),100)}showLabelInput(entryId,currentLabel){this.labelInput=new LabelInput(entryId,currentLabel),this.labelInput.onSubmit=(id,label)=>{this.treeList.updateNodeLabel(id,label),this.onLabelChangeCallback?.(id,label),this.hideLabelInput()},this.labelInput.onCancel=()=>this.hideLabelInput(),this.labelInput.focused=this._focused,this.treeContainer.clear(),this.labelInputContainer.clear(),this.labelInputContainer.addChild(this.labelInput)}hideLabelInput(){this.labelInput=null,this.labelInputContainer.clear(),this.treeContainer.clear(),this.treeContainer.addChild(this.treeList)}handleInput(keyData){this.labelInput?this.labelInput.handleInput(keyData):this.treeList.handleInput(keyData)}getTreeList(){return this.treeList}};var OSC133_ZONE_START2="\x1B]133;A\x07",OSC133_ZONE_END2="\x1B]133;B\x07",OSC133_ZONE_FINAL2="\x1B]133;C\x07",UserMessageComponent=class extends Container{constructor(text2,markdownTheme=getMarkdownTheme(),outputPad=1,markdownTransformers=[]){super(),this.text=text2,this.markdownTheme=markdownTheme,this.outputPad=outputPad,this.markdownTransformers=markdownTransformers,this.rebuild()}setOutputPad(padding){this.outputPad=padding,this.rebuild()}rebuild(){this.clear(),this.addChild(new Markdown(this.text,this.outputPad,1,this.markdownTheme,{color:content=>theme.fg("userMessageText",content),bgColor:content=>theme.bg("userMessageBg",content)},{preserveOrderedListMarkers:!0,preserveBackslashEscapes:!0,transform:createMarkdownTransform("user",!1,this.markdownTransformers)}))}render(width){let lines=super.render(width);return lines.length===0||(lines[0]=OSC133_ZONE_START2+lines[0],lines[lines.length-1]=OSC133_ZONE_END2+OSC133_ZONE_FINAL2+lines[lines.length-1]),lines}};var UserMessageList=class{constructor(messages,initialSelectedId){this.messages=[],this.selectedIndex=0,this.maxVisible=10,this.messages=messages;let initialIndex=initialSelectedId?messages.findIndex(message=>message.id===initialSelectedId):-1;this.selectedIndex=initialIndex>=0?initialIndex:Math.max(0,messages.length-1)}invalidate(){}render(width){let lines=[];if(this.messages.length===0)return lines.push(theme.fg("muted"," No user messages found")),lines;let startIndex=Math.max(0,Math.min(this.selectedIndex-Math.floor(this.maxVisible/2),this.messages.length-this.maxVisible)),endIndex=Math.min(startIndex+this.maxVisible,this.messages.length);for(let i=startIndex;i<endIndex;i++){let message=this.messages[i],isSelected2=i===this.selectedIndex,normalizedMessage=message.text.replace(/\n/g," ").trim(),cursor=isSelected2?theme.fg("accent","\u203A "):" ",maxMsgWidth=width-2,truncatedMsg=truncateToWidth(normalizedMessage,maxMsgWidth),messageLine=cursor+(isSelected2?theme.bold(truncatedMsg):truncatedMsg);lines.push(messageLine);let metadata=` Message ${i+1} of ${this.messages.length}`,metadataLine=theme.fg("muted",metadata);lines.push(metadataLine),lines.push("")}if(startIndex>0||endIndex<this.messages.length){let scrollInfo=theme.fg("muted",` (${this.selectedIndex+1}/${this.messages.length})`);lines.push(scrollInfo)}return lines}handleInput(keyData){let kb=getKeybindings();if(kb.matches(keyData,"tui.select.up"))this.selectedIndex=this.selectedIndex===0?this.messages.length-1:this.selectedIndex-1;else if(kb.matches(keyData,"tui.select.down"))this.selectedIndex=this.selectedIndex===this.messages.length-1?0:this.selectedIndex+1;else if(kb.matches(keyData,"tui.select.confirm")){let selected=this.messages[this.selectedIndex];selected&&this.onSelect&&this.onSelect(selected.id)}else kb.matches(keyData,"tui.select.cancel")&&this.onCancel&&this.onCancel()}},UserMessageSelectorComponent=class extends Container{constructor(messages,onSelect,onCancel,initialSelectedId){super(),this.addChild(new Spacer(1)),this.addChild(new Text(theme.bold("Fork from Message"),1,0)),this.addChild(new Text(theme.fg("muted","Select a user message to copy the active path up to that point into a new session"),1,0)),this.addChild(new Spacer(1)),this.addChild(new DynamicBorder),this.addChild(new Spacer(1)),this.messageList=new UserMessageList(messages,initialSelectedId),this.messageList.onSelect=onSelect,this.messageList.onCancel=onCancel,this.addChild(this.messageList),this.addChild(new Spacer(1)),this.addChild(new DynamicBorder),messages.length===0&&setTimeout(()=>onCancel(),100)}getMessageList(){return this.messageList}};function hotkeysTaskSection(display){let detach=KEYBINDINGS["app.tasks.detach"],detachSelected=KEYBINDINGS["app.tasks.detachSelected"];return`
|
|
1787
1793
|
**Tasks**
|
|
1788
1794
|
| Key | Action |
|
|
1789
1795
|
|-----|--------|
|
|
@@ -1800,7 +1806,7 @@ ${task.kind}
|
|
|
1800
1806
|
${task.id}`.toLocaleLowerCase().includes(search2)):rows,this.rows.some(task=>task.id===selectedId)||(this.state.selectedId=this.rows[0]?.id)}};var actions=["app.tasks.search","app.tasks.kill","app.tasks.detachSelected","app.tasks.previousTab","app.tasks.nextTab","app.tasks.follow","app.tasks.top","app.tasks.bottom","app.tasks.nextFocus","app.tasks.previousFocus","app.tasks.help"],TasksMenu=class{constructor(options){this.focused=!1,this.list=new TaskList,this.focus="list",this.searching=!1,this.dirty=!0,this.tickQueued=!1,this.refreshQueued=!1,this.disposed=!1,this.options=options,this.width=options.tui.terminal.columns,this.selection=new TaskSelection(options.state??{tab:"output"}),this.inspector=new TaskInspector({host:options.host,theme:options.theme,requestRender:()=>options.tui.requestRender()}),this.search=new Input({prompt:"Find task: ",placeholder:"title, command, kind or ID"}),this.sync(),this.unsubscribe=options.host.subscribe(()=>{this.dirty=!0,this.queueTick(),options.tui.requestRender()}),this.pollTimer=setInterval(()=>{this.queueTick(!0),this.selection.activeCount&&options.tui.requestRender()},options.pollIntervalMs??1e3),this.pollTimer.unref?.(),this.queueTick(!0)}sync(){if(this.disposed||!this.dirty)return;this.dirty=!1;let previous=this.selection.selected;this.selection.sync(this.options.host.list()),this.inspector.select(this.selection.selected),this.inspector.prune(new Set(this.selection.all.map(task=>task.id)));let selected=this.selection.selected;selected&&isTaskTerminal(selected.status)&&previous&&!isTaskTerminal(previous.status)&&(this.feedback=void 0),this.pendingKill&&(this.pendingKill!==selected?.id||selected&&isTaskTerminal(selected.status))&&this.clearKill();let animates=this.selection.all.some(task=>task.status==="running");animates&&!this.animationTimer?(this.animationTimer=setInterval(()=>this.options.tui.requestRender(),STATUS_SPINNER_INTERVAL_MS),this.animationTimer.unref?.()):animates||(clearInterval(this.animationTimer),this.animationTimer=void 0)}queueTick(refresh=!1){this.disposed||(this.refreshQueued||=refresh,!this.tickQueued&&(this.tickQueued=!0,Promise.resolve().then(async()=>{if(this.tickQueued=!1,this.disposed)return;let refresh2=this.refreshQueued;this.refreshQueued=!1,this.sync(),(refresh2||this.inspector.task&&isTaskTerminal(this.inspector.task.status))&&await this.inspector.refresh()}).catch(()=>{})))}invalidate(){this.inspector.invalidate()}clearKill(){this.pendingKill=void 0}selectedChanged(){this.clearKill(),this.list.showSelection(),this.inspector.select(this.selection.selected),this.queueTick(!0)}stop(confirm=!1){let task=this.selection.selected;if(confirm){let id=this.pendingKill;if(this.clearKill(),!id||id!==task?.id||isTaskTerminal(task.status))return;this.feedback=this.options.host.kill(id)?"Cancellation requested; waiting for cleanup.":"No new cancellation requested."}else task&&!isTaskTerminal(task.status)&&task.status!=="stopping"&&(this.pendingKill=task.id)}finishSearch(cancel){let id=cancel?this.beforeSearch?.id:this.selection.state.selectedId;!cancel&&!id||(this.focus=cancel?this.beforeSearch?.focus??"list":"list",this.searching=!1,this.search.focused=!1,this.selection.query="",this.selection.select(id),this.beforeSearch=void 0,this.selectedChanged())}action(key){switch(key){case"app.tasks.search":this.beforeSearch={id:this.selection.state.selectedId,focus:this.focus},this.focus="list",this.searching=!0,this.search.focused=!0,this.search.setValue("");break;case"app.tasks.previousTab":case"app.tasks.nextTab":this.focus==="inspector"&&(this.selection.state.tab=key==="app.tasks.previousTab"?"output":"info");break;case"app.tasks.nextFocus":case"app.tasks.previousFocus":this.focus=this.focus==="list"?"inspector":"list";break;case"app.tasks.follow":this.focus==="inspector"&&this.selection.state.tab==="output"&&(this.inspector.position.output.jump(!0,!0),this.queueTick(!0));break;case"app.tasks.top":case"app.tasks.bottom":this.focus==="list"?(this.selection.select(key==="app.tasks.top"?this.selection.rows[0]?.id:this.selection.rows.at(-1)?.id),this.selectedChanged()):this.inspector.position[this.selection.state.tab].jump(key==="app.tasks.bottom",this.selection.state.tab==="output");break;case"app.tasks.kill":this.stop();break;case"app.tasks.confirmStop":this.stop(!0);break;case"app.tasks.detachSelected":{let task=this.selection.selected;task?.mode==="foreground"&&!isTaskTerminal(task.status)&&task.status!=="stopping"&&this.options.host.enabled!==!1&&(this.feedback=this.options.host.detach?.(task.id)?"Selected task moved to background; execution continues.":"This task cannot move to background.");break}case"app.tasks.help":this.help=this.help?void 0:new TaskViewport;break}}move(direction,page=!1){if(this.help){this.help.move(direction,page,!1);return}if(this.focus==="list"){let rows=this.selection.rows;if(!rows.length)return;let index3=rows.findIndex(task=>task.id===this.selection.state.selectedId),next=page?Math.max(0,Math.min(rows.length-1,index3+direction*(this.layout?.listPageSize??1))):(index3+direction+rows.length)%rows.length;this.selection.select(rows[next]?.id),this.selectedChanged()}else this.inspector.position[this.selection.state.tab].move(direction,page,this.selection.state.tab==="output")}handleInput(data){if(this.disposed)return;this.sync(),this.render(this.width);let kb=this.options.keybindings;this.feedback=void 0;try{if(this.layout?.tooSmall){if(kb.matches(data,"tui.select.cancel"))if(this.help)this.help=void 0;else if(this.searching)this.finishSearch(!0);else if(this.pendingKill)this.clearKill();else{this.dispose(),this.options.onClose();return}}else if(this.help)kb.matches(data,"tui.select.cancel")||kb.matches(data,"app.tasks.help")?this.help=void 0:kb.matches(data,"app.tasks.top")||kb.matches(data,"app.tasks.bottom")?this.help.jump(kb.matches(data,"app.tasks.bottom"),!1):kb.matches(data,"tui.select.up")||kb.matches(data,"tui.editor.pageUp")?this.help.move(-1,kb.matches(data,"tui.editor.pageUp"),!1):(kb.matches(data,"tui.select.down")||kb.matches(data,"tui.editor.pageDown"))&&this.help.move(1,kb.matches(data,"tui.editor.pageDown"),!1);else if(this.searching)kb.matches(data,"tui.select.cancel")?this.finishSearch(!0):kb.matches(data,"tui.select.confirm")?this.finishSearch(!1):kb.matches(data,"tui.select.up")||kb.matches(data,"tui.select.pageUp")?this.move(-1,kb.matches(data,"tui.select.pageUp")):kb.matches(data,"tui.select.down")||kb.matches(data,"tui.select.pageDown")?this.move(1,kb.matches(data,"tui.select.pageDown")):(this.search.handleInput(data),this.selection.query=this.search.getValue().slice(0,512),this.selection.refresh(),this.selectedChanged());else if(this.pendingKill)kb.matches(data,"app.tasks.confirmStop")?this.stop(!0):kb.matches(data,"tui.select.cancel")&&this.clearKill();else if(kb.matches(data,"tui.select.cancel")){this.dispose(),this.options.onClose();return}else{let pageUp=kb.matches(data,this.focus==="list"?"tui.select.pageUp":"tui.editor.pageUp"),pageDown=kb.matches(data,this.focus==="list"?"tui.select.pageDown":"tui.editor.pageDown");if(pageUp||kb.matches(data,"tui.select.up"))this.move(-1,pageUp);else if(pageDown||kb.matches(data,"tui.select.down"))this.move(1,pageDown);else{if(kb.matches(data,"tui.select.confirm"))return;{let key=actions.find(key2=>kb.matches(data,key2));key&&this.action(key)}}}}catch(error){this.feedback=cleanTaskText(error instanceof Error?error.message:String(error))}this.queueTick(!0),this.options.tui.requestRender()}handleMouse(event){if(this.disposed||event.ctrl||event.alt||event.shift)return;this.feedback=void 0,this.render(event.width);let layout=this.layout;if(event.type==="wheel"&&event.wheelDelta){if(!this.pendingKill&&!layout.tooSmall&&event.y>=2&&event.y<this.options.tui.terminal.rows-3){let delta=Math.sign(event.wheelDelta)*Math.min(20,Math.abs(event.wheelDelta)),region=this.width>=100?event.x<layout.listWidth?"list":"inspector":this.focus;this.help?this.help.move(delta,!1,!1):region==="list"?this.list.scroll(delta):this.searching||this.inspector.position[this.selection.state.tab].move(delta,!1,this.selection.state.tab==="output")}}else if(event.type==="click"&&event.button==="left"){let hit=layout.hits.find(hit2=>hit2.y===event.y&&event.x>=hit2.x&&event.x<hit2.x+hit2.width);try{hit?.cancel?this.searching?this.finishSearch(!0):this.help?this.help=void 0:this.pendingKill?this.clearKill():(this.dispose(),this.options.onClose()):hit?.taskId?(this.selection.select(hit.taskId),this.selectedChanged(),this.focus="list",this.searching&&this.finishSearch(!1)):hit?.tab?(this.focus="inspector",this.selection.state.tab=hit.tab):hit?.key?(hit.key==="app.tasks.follow"&&(this.focus="inspector"),this.action(hit.key)):!this.pendingKill&&!this.searching&&!this.help&&!layout.tooSmall&&event.y>=1&&event.y<this.options.tui.terminal.rows-2&&this.width>=100&&(this.focus=event.x<layout.listWidth?"list":"inspector")}catch(error){this.feedback=cleanTaskText(error instanceof Error?error.message:String(error))}}else return;return this.queueTick(!0),this.options.tui.requestRender(),{handled:!0,focus:event.type==="click"}}render(width){return this.width=width,this.sync(),this.layout=renderTasksLayout({width,height:this.options.tui.terminal.rows,theme:this.options.theme,keybindings:this.options.keybindings,selection:this.selection,inspector:this.inspector,list:this.list,focus:this.focus,searchLine:this.searching?width2=>this.search.render(width2).join(""):void 0,pendingKill:this.pendingKill,feedback:this.feedback,help:this.help,canDetach:this.options.host.enabled!==!1&&!!this.options.host.detach}),this.layout.lines}dispose(){this.disposed||(this.disposed=!0,clearInterval(this.pollTimer),clearInterval(this.animationTimer),this.clearKill(),this.unsubscribe(),this.inspector.dispose())}};function bindTasksUI(ctx){let state2={tab:"output"},unsubscribe,unsubscribeDetachKey,closeMenu,hintTimer,start=()=>{unsubscribe?.(),unsubscribeDetachKey?.();let update=()=>{clearTimeout(hintTimer),hintTimer=void 0;let all=ctx.tasks.list(),background=all.filter(task=>task.mode==="background"&&!isTaskTerminal(task.status)).length,parts=[];background&&(parts.push(theme.fg("text",`${background} background task${background===1?"":"s"}`)),parts.push(theme.fg("accent","/tasks")+theme.fg("muted"," to view")));let detachKey=keyLabel("app.tasks.detach"),now=Date.now(),movable=all.filter(task=>ctx.tasks.canDetach(task.id)),waits=movable.map(task=>task.startedAt+1e4-now).filter(wait=>wait>0);detachKey&&movable.length>waits.length&&parts.push(theme.fg("accent",detachKey)+theme.fg("muted"," to run in background")),detachKey&&waits.length>0&&(hintTimer=setTimeout(update,Math.min(...waits)),hintTimer.unref?.()),ctx.ui.setStatus("background",parts.length?parts.join(theme.fg("dim"," \xB7 ")):void 0)};unsubscribe=ctx.tasks.subscribe(update),unsubscribeDetachKey=ctx.ui.onTerminalInput(data=>{if(!getKeybindings().matches(data,"app.tasks.detach"))return;let count;try{count=ctx.tasks.detachForeground()}catch(error){return ctx.ui.notify(error instanceof Error?error.message:String(error),"warning"),{consume:!0}}if(count!==0)return ctx.ui.notify(`Moved ${count} execution${count===1?"":"s"} to the background. Use /tasks to manage tasks.`),{consume:!0}}),update()},dispose=()=>{unsubscribe?.(),unsubscribe=void 0,unsubscribeDetachKey?.(),unsubscribeDetachKey=void 0,clearTimeout(hintTimer),hintTimer=void 0,closeMenu?.(),closeMenu=void 0,ctx.ui.setStatus("background",void 0)};return start(),{dispose,open:async()=>{closeMenu?.(),await ctx.ui.custom((tui,theme2,keybindings,done)=>{let close=()=>{closeMenu===close&&(closeMenu=void 0),done()};return closeMenu=close,new TasksMenu({state:state2,tui,theme:theme2,keybindings,host:ctx.tasks,onClose:close})},{overlay:!0,overlayOptions:{anchor:"center",width:"100%",maxHeight:"100%"}})}}}import*as crypto3 from"node:crypto";import*as fs8 from"node:fs";import*as os7 from"node:os";import*as path13 from"node:path";import{spawn as spawn12}from"child_process";function detectMiss(prev,message,models){let usage=message.usage,promptTokens=usage.input+usage.cacheRead+usage.cacheWrite;if(!prev||promptTokens<=0||usage.cacheRead+usage.cacheWrite===0&&!prev.reportedCache)return;let missedTokens=Math.min(prev.promptTokens,promptTokens)-usage.cacheRead;if(missedTokens<=1024)return;let paidTokens=usage.input+usage.cacheWrite,paidPerToken=paidTokens>0?(usage.cost.input+usage.cost.cacheWrite)/paidTokens:0,readPerToken=usage.cacheRead>0?usage.cost.cacheRead/usage.cacheRead:(models.getModel(message.provider,message.model)?.cost.cacheRead??0)/1e6;return{missedTokens,missedCost:missedTokens*Math.max(0,paidPerToken-readPerToken),idleMs:Math.max(0,message.timestamp-prev.timestamp),modelChanged:`${message.provider}/${message.model}`!==prev.modelKey}}function asPreviousRequest(message,reportedCache){let usage=message.usage,promptTokens=usage.input+usage.cacheRead+usage.cacheWrite;if(!(promptTokens<=0))return{promptTokens,modelKey:`${message.provider}/${message.model}`,timestamp:message.timestamp,reportedCache:reportedCache||usage.cacheRead+usage.cacheWrite>0}}function scan(entries,models){let prev,totals={missedTokens:0,missedCost:0,missCount:0},misses=new Map;for(let entry of entries){if(entry.type==="compaction"||entry.type==="branch_summary"){prev=void 0;continue}if(entry.type==="usage"&&entry.kind==="cache_warm"){let promptTokens=entry.usage.input+entry.usage.cacheRead+entry.usage.cacheWrite;promptTokens>0&&(prev={promptTokens,modelKey:`${entry.provider}/${entry.model}`,timestamp:Date.parse(entry.timestamp),reportedCache:!0})}else if(entry.type==="message"&&entry.message.role==="assistant"){let miss=detectMiss(prev,entry.message,models);miss&&(totals.missedTokens+=miss.missedTokens,totals.missedCost+=miss.missedCost,totals.missCount+=1,misses.set(entry.message,miss)),prev=asPreviousRequest(entry.message,prev?.reportedCache??!1)??prev}}return{prev,totals,misses}}function computeCacheWaste(entries,models){return scan(entries,models).totals}function collectCacheMisses(entries,models){return scan(entries,models).misses}function detectCacheMiss(entries,message,models){return detectMiss(scan(entries,models).prev,message,models)}import{mkdirSync as mkdirSync14,readFileSync as readFileSync18,rmSync as rmSync4,writeFileSync as writeFileSync12}from"node:fs";import{dirname as dirname23,join as join39}from"node:path";var MAX_CRASH_RECORDS=5,MAX_AGE=10080*60*1e3;function crashLogPath(agentDir=getAgentDir()){return join39(agentDir,"crashes.json")}function readCrashLog(path14=crashLogPath()){try{let records=JSON.parse(readFileSync18(path14,"utf8"));return Array.isArray(records)?records.filter(record=>typeof record=="object"&&record!==null&&typeof record.timestamp=="string"&&typeof record.message=="string"):[]}catch{return[]}}function writeCrashLog(records,path14){mkdirSync14(dirname23(path14),{recursive:!0}),writeFileSync12(path14,`${JSON.stringify(records,null,2)}
|
|
1801
1807
|
`)}function normalizeStackPath(value){return value.replace(/\\/g,"/").replace(/\/+$/u,"")}function stackContainsPath(stack,targetPath,includeDescendants){let target=normalizeStackPath(targetPath);if(!target||isSyntheticPath(target))return!1;let caseInsensitive=/^[a-z]:\//iu.test(target),haystack=caseInsensitive?stack.toLowerCase():stack,needle=caseInsensitive?target.toLowerCase():target;if(includeDescendants)return haystack.includes(`${needle}/`);let index3=haystack.indexOf(needle);for(;index3!==-1;){let next=haystack[index3+needle.length];if(next===void 0||next===":"||next===")"||/\s/u.test(next))return!0;index3=haystack.indexOf(needle,index3+needle.length)}return!1}function findExtensionStackMatches(stack,extensions){if(!stack)return[];let normalizedStack=stack.split(`
|
|
1802
1808
|
`).slice(1).filter(line=>/^\s+at\s/u.test(line)).map(line=>{try{return decodeURI(line)}catch{return line}}).join(`
|
|
1803
|
-
`).replace(/\\/g,"/"),matches=[],seen=new Set;for(let extension of extensions){let resolvedPath=normalizeStackPath(extension.resolvedPath),singleFilePackage=extension.sourceInfo.origin==="package"&&!/^(?:npm:|git:|https?:\/\/|ssh:\/\/)/u.test(extension.sourceInfo.source)&&/\.[cm]?[jt]s$/u.test(extension.sourceInfo.source),packageRoot=extension.sourceInfo.origin==="package"&&!singleFilePackage&&extension.sourceInfo.baseDir?extension.sourceInfo.baseDir:void 0,slashIndex=resolvedPath.lastIndexOf("/"),directoryEntry=/\/index\.[cm]?[jt]s$/u.test(resolvedPath);if(!(packageRoot?stackContainsPath(normalizedStack,packageRoot,!0):directoryEntry&&slashIndex!==-1?stackContainsPath(normalizedStack,resolvedPath.slice(0,slashIndex),!0):stackContainsPath(normalizedStack,resolvedPath,!1)))continue;let label=extension.sourceInfo.origin==="package"&&extension.sourceInfo.source?extension.sourceInfo.source:extension.path;seen.has(label)||(seen.add(label),matches.push(label))}return matches}function recordCrash(crash,path14=crashLogPath()){try{let{error}=crash,record={timestamp:new Date().toISOString(),version:VERSION,kind:crash.kind,message:error instanceof Error?error.message||error.name:String(error),stack:error instanceof Error&&error.stack?error.stack:null,sessionFile:crash.sessionFile??null,cwd:crash.cwd};return writeCrashLog([...readCrashLog(path14),record].slice(-MAX_CRASH_RECORDS),path14),record}catch{return}}function takeUnnotifiedCrash(path14=crashLogPath(),now=Date.now()){let records=readCrashLog(path14),crash=[...records].reverse().find(record=>!record.notified&&now-Date.parse(record.timestamp)<=MAX_AGE);if(crash){try{writeCrashLog(records.map(record=>record.notified?record:{...record,notified:!0}),path14)}catch{}return crash}}function clearCrashLog(path14=crashLogPath()){try{rmSync4(path14,{force:!0})}catch{}}var RADIUS_PROVIDER_ID="radius",ENV_RADIUS_GATEWAY="PI_RADIUS_GATEWAY",RADIUS_MCP_URL=`${normalizeRadiusGatewayUrl(DEFAULT_RADIUS_GATEWAY)}/mcp`;function getRadiusGatewayUrl(){return normalizeRadiusGatewayUrl(process.env[ENV_RADIUS_GATEWAY]??DEFAULT_RADIUS_GATEWAY)}var BUILTIN_SLASH_COMMANDS=[{name:"tasks",description:"View and manage session tasks"},{name:"settings",description:"Open settings menu"},{name:"model",description:"Select model (opens selector UI)",argumentHint:"<provider/model>"},{name:"tree",description:"Navigate session tree (switch branches)"},{name:"thinking",description:"Set thinking level",argumentHint:"<level>"},{name:"scoped-models",description:"Enable/disable models for Ctrl+P cycling"},{name:"export",description:"Export session (HTML default, or specify path: .html/.jsonl)"},{name:"import",description:"Import and resume a session from a JSONL file"},{name:"share",description:"Share session via a Radius artifact or a GitHub gist"},{name:"bug",description:"Report a bug to the Pi developers",argumentHint:"<description>"},{name:"copy",description:"Copy last agent message to clipboard"},{name:"name",description:"Set session display name"},{name:"session",description:"Show session info and stats"},{name:"changelog",description:"Show changelog entries"},{name:"hotkeys",description:"Show all keyboard shortcuts"},{name:"fork",description:"Create a new fork from a previous user message"},{name:"clone",description:"Duplicate the current session at the current position"},{name:"trust",description:"Save project trust decision for future sessions"},{name:"login",description:"Configure provider authentication",argumentHint:"<provider>"},{name:"logout",description:"Remove provider authentication"},{name:"new",description:"Start a new session"},{name:"compact",description:"Manually compact the session context"},{name:"resume",description:"Resume a different session"},{name:"reload",description:"Reload keybindings, extensions, skills, prompts, themes, and context files"},{name:"quit",description:`Quit ${APP_NAME}`}];import path10 from"node:path";import{existsSync as existsSync21,readFileSync as readFileSync19}from"fs";var GITHUB_REPO="earendil-works/pi",CHANGELOG_LINK_BASE_PATH="packages/coding-agent",LEGACY_REPO_RE=/^https:\/\/github\.com\/(?:badlogic|earendil-works)\/pi-mono(?=\/|$)/,URL_SCHEME_RE=/^[a-z][a-z0-9+.-]*:/i,INLINE_MARKDOWN_LINK_RE=/(!?\[[^\]\n]+\]\()([^\s)]+)((?:\s+[^)]*)?\))/g;function entryVersion(entry){return`${entry.major}.${entry.minor}.${entry.patch}`}function normalizeTag(version2){let versionString=typeof version2=="string"?version2:entryVersion(version2);return versionString.startsWith("v")?versionString:`v${versionString}`}function splitLocalTarget(target){let hashIndex=target.indexOf("#"),beforeHash=hashIndex===-1?target:target.slice(0,hashIndex),fragment=hashIndex===-1?"":target.slice(hashIndex),queryIndex=beforeHash.indexOf("?");return queryIndex===-1?{fragment,pathPart:beforeHash,query:""}:{fragment,pathPart:beforeHash.slice(0,queryIndex),query:beforeHash.slice(queryIndex)}}function normalizePathPart(value){return value.replaceAll("\\","/")}function resolveRepositoryPath(targetPath){let normalizedTarget=normalizePathPart(targetPath),joined=normalizedTarget.startsWith("/")?path10.posix.normalize(normalizedTarget.replace(/^\/+/,"")):path10.posix.normalize(path10.posix.join(CHANGELOG_LINK_BASE_PATH,normalizedTarget));if(!(joined==="."||joined.startsWith("../")||joined===".."))return joined}function isDirectoryTarget(originalPath,repositoryPath){return originalPath.endsWith("/")?!0:!path10.posix.basename(repositoryPath).includes(".")}function normalizeChangelogLinkTarget(target,tag){let canonicalTarget=target.replace(LEGACY_REPO_RE,`https://github.com/${GITHUB_REPO}`),repoUrl=`https://github.com/${GITHUB_REPO}`;for(let route2 of["blob","tree"])for(let branch of["main","master"]){let floatingRefPrefix=`${repoUrl}/${route2}/${branch}/`;canonicalTarget.startsWith(floatingRefPrefix)&&(canonicalTarget=`${repoUrl}/${route2}/${tag}/${canonicalTarget.slice(floatingRefPrefix.length)}`)}if(canonicalTarget.startsWith("#")||canonicalTarget.startsWith("//")||URL_SCHEME_RE.test(canonicalTarget))return canonicalTarget;let{fragment,pathPart,query}=splitLocalTarget(canonicalTarget);if(!pathPart)return canonicalTarget;let repositoryPath=resolveRepositoryPath(pathPart);if(!repositoryPath)return canonicalTarget;let route=isDirectoryTarget(pathPart,repositoryPath)?"tree":"blob";return`https://github.com/${GITHUB_REPO}/${route}/${tag}/${encodeURI(repositoryPath)}${query}${fragment}`}function normalizeChangelogLinks(markdown,version2){let tag=normalizeTag(version2);return markdown.replace(INLINE_MARKDOWN_LINK_RE,(_match,prefix,target,suffix)=>`${prefix}${normalizeChangelogLinkTarget(target,tag)}${suffix}`)}function parseChangelog(changelogPath){if(!existsSync21(changelogPath))return[];try{let lines=readFileSync19(changelogPath,"utf-8").split(`
|
|
1809
|
+
`).replace(/\\/g,"/"),matches=[],seen=new Set;for(let extension of extensions){let resolvedPath=normalizeStackPath(extension.resolvedPath),singleFilePackage=extension.sourceInfo.origin==="package"&&!/^(?:npm:|git:|https?:\/\/|ssh:\/\/)/u.test(extension.sourceInfo.source)&&/\.[cm]?[jt]s$/u.test(extension.sourceInfo.source),packageRoot=extension.sourceInfo.origin==="package"&&!singleFilePackage&&extension.sourceInfo.baseDir?extension.sourceInfo.baseDir:void 0,slashIndex=resolvedPath.lastIndexOf("/"),directoryEntry=/\/index\.[cm]?[jt]s$/u.test(resolvedPath);if(!(packageRoot?stackContainsPath(normalizedStack,packageRoot,!0):directoryEntry&&slashIndex!==-1?stackContainsPath(normalizedStack,resolvedPath.slice(0,slashIndex),!0):stackContainsPath(normalizedStack,resolvedPath,!1)))continue;let label=extension.sourceInfo.origin==="package"&&extension.sourceInfo.source?extension.sourceInfo.source:extension.path;seen.has(label)||(seen.add(label),matches.push(label))}return matches}function recordCrash(crash,path14=crashLogPath()){try{let{error}=crash,record={timestamp:new Date().toISOString(),version:VERSION,kind:crash.kind,message:error instanceof Error?error.message||error.name:String(error),stack:error instanceof Error&&error.stack?error.stack:null,sessionFile:crash.sessionFile??null,cwd:crash.cwd};return writeCrashLog([...readCrashLog(path14),record].slice(-MAX_CRASH_RECORDS),path14),record}catch{return}}function takeUnnotifiedCrash(path14=crashLogPath(),now=Date.now()){let records=readCrashLog(path14),crash=[...records].reverse().find(record=>!record.notified&&now-Date.parse(record.timestamp)<=MAX_AGE);if(crash){try{writeCrashLog(records.map(record=>record.notified?record:{...record,notified:!0}),path14)}catch{}return crash}}function clearCrashLog(path14=crashLogPath()){try{rmSync4(path14,{force:!0})}catch{}}var RADIUS_PROVIDER_ID="radius",ENV_RADIUS_GATEWAY="PI_RADIUS_GATEWAY",RADIUS_MCP_URL=`${normalizeRadiusGatewayUrl(DEFAULT_RADIUS_GATEWAY)}/mcp`;function getRadiusGatewayUrl(){return normalizeRadiusGatewayUrl(process.env[ENV_RADIUS_GATEWAY]??DEFAULT_RADIUS_GATEWAY)}var BUILTIN_SLASH_COMMANDS=[{name:"tasks",description:"View and manage session tasks"},{name:"settings",description:"Open settings menu"},{name:"model",description:"Select model (opens selector UI)",argumentHint:"<provider/model>"},{name:"tree",description:"Navigate session tree (switch branches)"},{name:"thinking",description:"Set thinking level",argumentHint:"<level>"},{name:"scoped-models",description:"Enable/disable models for Ctrl+P cycling"},{name:"export",description:"Export session (HTML default, or specify path: .html/.jsonl)"},{name:"import",description:"Import and resume a session from a JSONL file"},{name:"share",description:"Share session via a Radius artifact or a GitHub gist"},{name:"bug",description:"Report a bug to the Pi developers",argumentHint:"<description>"},{name:"copy",description:"Copy last agent message to clipboard"},{name:"name",description:"Set session display name"},{name:"session",description:"Show session info and stats"},{name:"changelog",description:"Show changelog entries"},{name:"hotkeys",description:"Show all keyboard shortcuts"},{name:"fork",description:"Create a new fork from a previous user message"},{name:"clone",description:"Duplicate the current session at the current position"},{name:"trust",description:"Save project trust decision for future sessions"},{name:"login",description:"Configure provider authentication",argumentHint:"<provider>"},{name:"logout",description:"Remove provider authentication"},{name:"new",description:"Start a new session"},{name:"compact",description:"Manually compact the session context"},{name:"resume",description:"Resume a different session"},{name:"reload",description:"Reload keybindings, extensions, skills, prompts, themes, and context files"},{name:"quit",description:`Quit ${APP_NAME}`}];function createAllToolRenderers(){return{tasks:{renderCall:(args,theme2,context)=>renderTasksCall(args,theme2,context),renderResult:renderTasksResult},read:readRenderers,bash:createShellRenderers({name:"bash",prompt:"$"}),powershell:createShellRenderers({name:"powershell",prompt:"PS>"}),edit:editRenderers,write:writeRenderers,grep:grepRenderers,find:findRenderers,ls:lsRenderers}}function withBuiltInRenderers(toolName,definition){let builtIn=createAllToolRenderers()[toolName];return definition?builtIn?{...definition,renderCall:definition.renderCall??builtIn.renderCall,renderResult:definition.renderResult??builtIn.renderResult}:definition:builtIn}import path10 from"node:path";import{existsSync as existsSync21,readFileSync as readFileSync19}from"fs";var GITHUB_REPO="earendil-works/pi",CHANGELOG_LINK_BASE_PATH="packages/coding-agent",LEGACY_REPO_RE=/^https:\/\/github\.com\/(?:badlogic|earendil-works)\/pi-mono(?=\/|$)/,URL_SCHEME_RE=/^[a-z][a-z0-9+.-]*:/i,INLINE_MARKDOWN_LINK_RE=/(!?\[[^\]\n]+\]\()([^\s)]+)((?:\s+[^)]*)?\))/g;function entryVersion(entry){return`${entry.major}.${entry.minor}.${entry.patch}`}function normalizeTag(version2){let versionString=typeof version2=="string"?version2:entryVersion(version2);return versionString.startsWith("v")?versionString:`v${versionString}`}function splitLocalTarget(target){let hashIndex=target.indexOf("#"),beforeHash=hashIndex===-1?target:target.slice(0,hashIndex),fragment=hashIndex===-1?"":target.slice(hashIndex),queryIndex=beforeHash.indexOf("?");return queryIndex===-1?{fragment,pathPart:beforeHash,query:""}:{fragment,pathPart:beforeHash.slice(0,queryIndex),query:beforeHash.slice(queryIndex)}}function normalizePathPart(value){return value.replaceAll("\\","/")}function resolveRepositoryPath(targetPath){let normalizedTarget=normalizePathPart(targetPath),joined=normalizedTarget.startsWith("/")?path10.posix.normalize(normalizedTarget.replace(/^\/+/,"")):path10.posix.normalize(path10.posix.join(CHANGELOG_LINK_BASE_PATH,normalizedTarget));if(!(joined==="."||joined.startsWith("../")||joined===".."))return joined}function isDirectoryTarget(originalPath,repositoryPath){return originalPath.endsWith("/")?!0:!path10.posix.basename(repositoryPath).includes(".")}function normalizeChangelogLinkTarget(target,tag){let canonicalTarget=target.replace(LEGACY_REPO_RE,`https://github.com/${GITHUB_REPO}`),repoUrl=`https://github.com/${GITHUB_REPO}`;for(let route2 of["blob","tree"])for(let branch of["main","master"]){let floatingRefPrefix=`${repoUrl}/${route2}/${branch}/`;canonicalTarget.startsWith(floatingRefPrefix)&&(canonicalTarget=`${repoUrl}/${route2}/${tag}/${canonicalTarget.slice(floatingRefPrefix.length)}`)}if(canonicalTarget.startsWith("#")||canonicalTarget.startsWith("//")||URL_SCHEME_RE.test(canonicalTarget))return canonicalTarget;let{fragment,pathPart,query}=splitLocalTarget(canonicalTarget);if(!pathPart)return canonicalTarget;let repositoryPath=resolveRepositoryPath(pathPart);if(!repositoryPath)return canonicalTarget;let route=isDirectoryTarget(pathPart,repositoryPath)?"tree":"blob";return`https://github.com/${GITHUB_REPO}/${route}/${tag}/${encodeURI(repositoryPath)}${query}${fragment}`}function normalizeChangelogLinks(markdown,version2){let tag=normalizeTag(version2);return markdown.replace(INLINE_MARKDOWN_LINK_RE,(_match,prefix,target,suffix)=>`${prefix}${normalizeChangelogLinkTarget(target,tag)}${suffix}`)}function parseChangelog(changelogPath){if(!existsSync21(changelogPath))return[];try{let lines=readFileSync19(changelogPath,"utf-8").split(`
|
|
1804
1810
|
`),entries=[],currentLines=[],currentVersion=null;for(let line of lines)if(line.startsWith("## ")){currentVersion&¤tLines.length>0&&entries.push({...currentVersion,content:currentLines.join(`
|
|
1805
1811
|
`).trim()});let versionMatch=line.match(/##\s+\[?(\d+)\.(\d+)\.(\d+)\]?/);versionMatch?(currentVersion={major:Number.parseInt(versionMatch[1],10),minor:Number.parseInt(versionMatch[2],10),patch:Number.parseInt(versionMatch[3],10)},currentLines=[line]):(currentVersion=null,currentLines=[])}else currentVersion&¤tLines.push(line);return currentVersion&¤tLines.length>0&&entries.push({...currentVersion,content:currentLines.join(`
|
|
1806
1812
|
`).trim()}),entries}catch(error){return console.error(`Warning: Could not parse changelog: ${error}`),[]}}function compareVersions(v1,v2){return v1.major!==v2.major?v1.major-v2.major:v1.minor!==v2.minor?v1.minor-v2.minor:v1.patch-v2.patch}function getNewEntries(entries,lastVersion){let parts=lastVersion.split(".").map(Number),last={major:parts[0]||0,minor:parts[1]||0,patch:parts[2]||0,content:""};return entries.filter(entry=>compareVersions(entry,last)>0)}import{randomUUID as randomUUID5}from"crypto";import{readFileSync as readFileSync20,unlinkSync as unlinkSync2}from"fs";import{tmpdir as tmpdir5}from"os";import{join as join40}from"path";var SUPPORTED_IMAGE_MIME_TYPES=["image/png","image/jpeg","image/webp","image/gif"],DEFAULT_LIST_TIMEOUT_MS=1e3,DEFAULT_POWERSHELL_TIMEOUT_MS=5e3;function isWaylandSession(env2=process.env){return!!env2.WAYLAND_DISPLAY||env2.XDG_SESSION_TYPE==="wayland"}function baseMimeType2(mimeType){return mimeType.split(";")[0]?.trim().toLowerCase()??mimeType.toLowerCase()}function extensionForImageMimeType(mimeType){switch(baseMimeType2(mimeType)){case"image/png":return"png";case"image/jpeg":return"jpg";case"image/webp":return"webp";case"image/gif":return"gif";default:return null}}function selectPreferredImageMimeType(mimeTypes){let normalized=mimeTypes.map(t=>t.trim()).filter(Boolean).map(t=>({raw:t,base:baseMimeType2(t)}));for(let preferred of SUPPORTED_IMAGE_MIME_TYPES){let match2=normalized.find(t=>t.base===preferred);if(match2)return match2.raw}return normalized.find(t=>t.base.startsWith("image/"))?.raw??null}function isSupportedImageMimeType(mimeType){let base=baseMimeType2(mimeType);return SUPPORTED_IMAGE_MIME_TYPES.some(t=>t===base)}async function convertToPng2(bytes){let photon=await loadPhoton();if(!photon)return null;try{let image=photon.PhotonImage.new_from_byteslice(bytes);try{return image.get_bytes()}finally{image.free()}}catch{return null}}async function readClipboardImageViaWlPaste(){let list2=await runClipboardCommand("wl-paste",["--list-types"],{timeoutMs:DEFAULT_LIST_TIMEOUT_MS});if(list2===void 0)return;let types2=list2.toString("utf-8").split(/\r?\n/).map(t=>t.trim()).filter(Boolean),selectedType=selectPreferredImageMimeType(types2);if(!selectedType)return null;let data=await runClipboardCommand("wl-paste",["--type",selectedType,"--no-newline"]);if(data!==void 0)return data.length===0?null:{bytes:data,mimeType:baseMimeType2(selectedType)}}async function readClipboardImageViaPowerShell(){let tmpFile=join40(tmpdir5(),`pi-wsl-clip-${randomUUID5()}.png`);try{let winPathResult=await runClipboardCommand("wslpath",["-w",tmpFile],{timeoutMs:DEFAULT_LIST_TIMEOUT_MS});if(winPathResult===void 0)return null;let winPath=winPathResult.toString("utf-8").trim();if(!winPath)return null;let psScript=["Add-Type -AssemblyName System.Windows.Forms","Add-Type -AssemblyName System.Drawing",`$path = '${winPath.replaceAll("'","''")}'`,"$img = [System.Windows.Forms.Clipboard]::GetImage()","if ($img) { $img.Save($path, [System.Drawing.Imaging.ImageFormat]::Png); Write-Output 'ok' } else { Write-Output 'empty' }"].join("; "),result2=await runClipboardCommand("powershell.exe",["-NoProfile","-Command",psScript],{timeoutMs:DEFAULT_POWERSHELL_TIMEOUT_MS});if(result2===void 0||result2.toString("utf-8").trim()!=="ok")return null;let bytes=readFileSync20(tmpFile);return bytes.length===0?null:{bytes:new Uint8Array(bytes),mimeType:"image/png"}}catch{return null}finally{try{unlinkSync2(tmpFile)}catch{}}}async function readClipboardImageViaXclip(){let targets=await runClipboardCommand("xclip",["-selection","clipboard","-t","TARGETS","-o"],{timeoutMs:DEFAULT_LIST_TIMEOUT_MS});if(targets===void 0)return;let candidateTypes=targets.toString("utf-8").split(/\r?\n/).map(t=>t.trim()).filter(Boolean),preferred=selectPreferredImageMimeType(candidateTypes);if(!preferred)return null;let data=await runClipboardCommand("xclip",["-selection","clipboard","-t",preferred,"-o"]);if(data!==void 0)return data.length===0?null:{bytes:data,mimeType:baseMimeType2(preferred)}}async function readClipboardImageViaNativeClipboard(){let bytes=await getNativeClipboard()?.getImage();if(bytes!==void 0)return bytes?.length?{bytes,mimeType:detectSupportedImageMimeType(bytes)??"application/octet-stream"}:null}async function readClipboardImage(options){let env2=options?.env??process.env,platform3=options?.platform??process.platform;if(env2.TERMUX_VERSION)return null;let image;if(platform3==="linux"){let wsl=isWSL(env2);(isWaylandSession(env2)||wsl)&&(image=await readClipboardImageViaWlPaste()),image===void 0&&(image=await readClipboardImageViaXclip()),!image&&wsl&&(image=await readClipboardImageViaPowerShell()??image),image===void 0&&(image=await readClipboardImageViaNativeClipboard())}else image=await readClipboardImageViaNativeClipboard();if(!image)return null;if(!isSupportedImageMimeType(image.mimeType)){let pngBytes=await convertToPng2(image.bytes);return pngBytes?{bytes:pngBytes,mimeType:"image/png"}:null}return image}var import_semver2=__toESM(require_semver2(),1);var LATEST_VERSION_URL=`https://registry.npmjs.org/${encodeURIComponent(PACKAGE_NAME)}/latest`,DEFAULT_VERSION_CHECK_TIMEOUT_MS=1e4;function formatVersionCheckError(error){let rootMessage=error instanceof Error&&error.message?error.message:String(error),cause=error instanceof Error?error.cause:void 0,causes=cause instanceof AggregateError?cause.errors:cause===void 0?[]:[cause],codes=causes.map(value=>typeof value=="object"&&value!==null&&"code"in value&&typeof value.code=="string"?value.code:void 0).filter(code=>code!==void 0);if(codes.length>0)return`${rootMessage} (${[...new Set(codes)].join(", ")})`;let causeMessage=causes.find(value=>value instanceof Error&&!!value.message)?.message;return causeMessage?`${rootMessage} (cause: ${causeMessage})`:rootMessage}function comparePackageVersions(leftVersion,rightVersion){let left=(0,import_semver2.valid)(leftVersion.trim()),right=(0,import_semver2.valid)(rightVersion.trim());if(!(!left||!right))return(0,import_semver2.compare)(left,right)}function isNewerPackageVersion(candidateVersion,currentVersion){let comparison=comparePackageVersions(candidateVersion,currentVersion);return comparison!==void 0?comparison>0:candidateVersion.trim()!==currentVersion.trim()}async function getLatestPiRelease(currentVersion,options={}){if(process.env.PI_OFFLINE)return;let response=await fetchWithRetry(LATEST_VERSION_URL,{headers:{"User-Agent":getPiUserAgent(currentVersion),accept:"application/json"}},{maxRetries:options.retry?2:0,timeoutMs:options.timeoutMs??DEFAULT_VERSION_CHECK_TIMEOUT_MS});if(!response.ok)return;let data=await response.json();if(!(typeof data.version!="string"||!data.version.trim()))return{version:data.version.trim(),packageName:PACKAGE_NAME}}async function checkForNewPiVersion(currentVersion){if(!process.env.PI_SKIP_VERSION_CHECK)try{let latestRelease=await getLatestPiRelease(currentVersion);return latestRelease&&isNewerPackageVersion(latestRelease.version,currentVersion)?latestRelease:void 0}catch{return}}import*as path12 from"node:path";var AuthCommandError=class extends Error{},AUTH_COMMAND_USAGE={check:`${APP_NAME} auth check --provider <provider> [--json] [--credentials] [--no-refresh]`,api_key:`${APP_NAME} auth print-api-key --provider <provider> [--model <model>]`,bearer_token:`${APP_NAME} auth print-bearer-token --provider <provider> [--model <model>] [--min-expiry <duration>]`};function getAuthCommandName(kind){return kind==="check"?"auth check":kind==="api_key"?"auth print-api-key":"auth print-bearer-token"}function getAuthCommandUsage(kind){return AUTH_COMMAND_USAGE[kind]}function isAuthCommandHelp(args){return args[0]==="auth"&&(args[1]===void 0||args[1]==="help"||args.includes("--help")||args.includes("-h"))}function printAuthCommandHelp(){console.log(`Usage:
|
|
@@ -1826,7 +1832,7 @@ ${codeSpan(styledWarning)}
|
|
|
1826
1832
|
`)}
|
|
1827
1833
|
`}).join("")}}var CORAL2=rgbColor(228,138,122),BLUE2=rgbColor(79,142,179),YELLOW2=rgbColor(234,182,93),RESET="\x1B[0m";function piLogoLines(){let mode=theme.getColorMode(),fg=color2=>foregroundAnsi(color2,mode),top=`${fg(CORAL2)}${backgroundAnsi(BLUE2,mode)}\u2580${RESET}${fg(CORAL2)}\u2580\u2588${RESET} `,bottom=`${fg(BLUE2)}\u2588\u2580${RESET} ${fg(YELLOW2)}\u2588${RESET}`;return[top,bottom]}function supportsPiLogo(){return!isAppleTerminalSession()}function piWordmark(){let mode=theme.getColorMode();return`${foregroundAnsi(CORAL2,mode)}P${RESET}${foregroundAnsi(YELLOW2,mode)}i${RESET}`}var RADIUS_COLORS=["#4d9abf","#83ccd2","#f1be57","#f09082"].map(hex=>parseColor(hex)),CHARS_PER_COLOR=4,CHARS_PER_SECOND=10,ANIMATION_FRAME_MS=50;function radiusShimmer(text2,elapsedMs){let mode=theme.getColorMode(),cycle=RADIUS_COLORS.length*CHARS_PER_COLOR,offset=elapsedMs/1e3*CHARS_PER_SECOND,result2="",index3=0;for(let char of text2){let position=((index3-offset)%cycle+cycle)%cycle,band=Math.floor(position/CHARS_PER_COLOR),t=position/CHARS_PER_COLOR-band,amount=t*t*(3-2*t),from=RADIUS_COLORS[band],to=RADIUS_COLORS[(band+1)%RADIUS_COLORS.length];result2+=foregroundAnsi(mixColors(from,to,amount,"srgb"),mode)+char,index3++}return`${result2}\x1B[39m`}var RadiusLoginMenuComponent=class extends ExtensionSelectorComponent{constructor(tui,title,options,radiusOption,onSelect,onCancel){super(title,options,option=>{this.stopAnimation(),onSelect(option)},()=>{this.stopAnimation(),onCancel()}),this.animationStart=performance.now(),this.animating=!1,this.radiusOption=radiusOption,this.animationTimer=setInterval(()=>{this.animating&&tui.requestRender()},ANIMATION_FRAME_MS),this.animationTimer.unref?.()}render(width){let lines=super.render(width),{label,text:text2}=this.radiusOption,selectedLine=new Text(theme.fg("accent","\u2192 ")+theme.fg("accent",label),1,0).render(width)[0],index3=selectedLine===void 0?-1:lines.indexOf(selectedLine);if(this.animating=index3>=0,this.animating){let shimmer=radiusShimmer(text2,performance.now()-this.animationStart),animatedLine=theme.fg("accent","\u2192 ")+shimmer+label.slice(text2.length);lines[index3]=new Text(animatedLine,1,0).render(width)[0]??""}return lines}stopAnimation(){clearInterval(this.animationTimer),this.animationTimer=void 0,this.animating=!1}dispose(){this.stopAnimation(),super.dispose()}};function createLoginMenuSelector(tui,title,options,radiusOption,onSelect,onCancel){return new RadiusLoginMenuComponent(tui,title,options,radiusOption,onSelect,onCancel)}function isEnabled2(enabledIds,id){return enabledIds===null||enabledIds.includes(id)}function normalizeEnabled(result2,allIds){return result2.length===allIds.length&&result2.every(id=>allIds.includes(id))?null:result2}function toggle(enabledIds,allIds,id){if(enabledIds===null)return allIds.filter(modelId=>modelId!==id);let index3=enabledIds.indexOf(id);return index3>=0?[...enabledIds.slice(0,index3),...enabledIds.slice(index3+1)]:normalizeEnabled([...enabledIds,id],allIds)}function enableAll(enabledIds,allIds,targetIds){if(enabledIds===null)return null;let targets=targetIds??allIds,result2=[...enabledIds];for(let id of targets)result2.includes(id)||result2.push(id);return normalizeEnabled(result2,allIds)}function clearAll(enabledIds,allIds,targetIds){if(enabledIds===null)return targetIds?allIds.filter(id=>!targetIds.includes(id)):[];let targets=new Set(targetIds??enabledIds);return enabledIds.filter(id=>!targets.has(id))}function move(enabledIds,id,delta){if(enabledIds===null)return null;let list2=[...enabledIds],index3=list2.indexOf(id);if(index3<0)return list2;let newIndex=index3+delta;if(newIndex<0||newIndex>=list2.length)return list2;let result2=[...list2];return[result2[index3],result2[newIndex]]=[result2[newIndex],result2[index3]],result2}function getSortedIds(enabledIds,allIds){if(enabledIds===null)return allIds;let enabledSet=new Set(enabledIds);return[...enabledIds,...allIds.filter(id=>!enabledSet.has(id))]}var ScopedModelsSelectorComponent=class extends Container{get focused(){return this._focused}set focused(value){this._focused=value,this.searchInput.focused=value}constructor(config,callbacks){super(),this.modelsById=new Map,this.allIds=[],this.enabledIds=null,this.filteredItems=[],this.selectedIndex=0,this._focused=!1,this.maxVisible=8,this.isDirty=!1,this.callbacks=callbacks;for(let model of config.allModels){let fullId=`${model.provider}/${model.id}`;this.modelsById.set(fullId,model),this.allIds.push(fullId)}this.enabledIds=config.enabledModelIds===null?null:[...config.enabledModelIds],this.filteredItems=this.buildItems(),this.addChild(new DynamicBorder),this.addChild(new Spacer(1)),this.addChild(new Text(theme.fg("accent",theme.bold("Model Configuration")),0,0)),this.addChild(new Text(theme.fg("muted",`Session-only. ${keyDisplayText("app.models.save")} to save to settings.`),0,0)),this.addChild(new Spacer(1)),this.searchInput=new Input,this.addChild(this.searchInput),this.addChild(new Spacer(1)),this.listContainer=new Container,this.addChild(this.listContainer),this.addChild(new Spacer(1)),config.refreshStatus&&(this.refreshStatusText=new Text(theme.fg("muted",` ${config.refreshStatus}`),0,0),this.addChild(this.refreshStatusText)),this.footerText=new Text(this.getFooterText(),0,0),this.addChild(this.footerText),this.addChild(new DynamicBorder),this.updateList()}updateModels(models,enabledModelIds){let selectedId=this.filteredItems[this.selectedIndex]?.fullId;enabledModelIds!==void 0&&(this.enabledIds=enabledModelIds===null?null:[...enabledModelIds]),this.modelsById.clear(),this.allIds=[];for(let model of models){let fullId=`${model.provider}/${model.id}`;this.modelsById.set(fullId,model),this.allIds.push(fullId)}this.refresh();let refreshedIndex=selectedId?this.filteredItems.findIndex(item=>item.fullId===selectedId):-1;refreshedIndex>=0&&(this.selectedIndex=refreshedIndex,this.updateList())}setRefreshStatus(message,kind){this.refreshStatusText?.setText(theme.fg(kind,` ${message}`))}buildItems(){return getSortedIds(this.enabledIds,this.allIds).map(id=>({fullId:id,model:this.modelsById.get(id),enabled:isEnabled2(this.enabledIds,id)}))}getFooterText(){let enabledCount=this.enabledIds?.filter(id=>this.modelsById.has(id)).length??this.allIds.length,unavailableCount=this.enabledIds?.filter(id=>!this.modelsById.has(id)).length??0,countText=this.enabledIds===null?"all enabled":`${enabledCount}/${this.allIds.length} enabled${unavailableCount?` \xB7 ${unavailableCount} unavailable`:""}`,parts=[`${keyDisplayText("tui.select.confirm")} toggle`,`${keyDisplayText("app.models.enableAll")} all`,`${keyDisplayText("app.models.clearAll")} clear`,`${keyDisplayText("app.models.toggleProvider")} provider`,`${keyDisplayText("app.models.reorderUp")}/${keyDisplayText("app.models.reorderDown")} reorder`,`${keyDisplayText("app.models.save")} save`,countText];return this.isDirty?theme.fg("dim",` ${parts.join(" \xB7 ")} `)+theme.fg("warning","(unsaved)"):theme.fg("dim",` ${parts.join(" \xB7 ")}`)}refresh(){let query=this.searchInput.getValue(),items=this.buildItems();this.filteredItems=query?fuzzyFilter(items,query,item=>item.model?getModelSearchText({id:item.model.id,provider:item.model.provider,name:item.model.name}):item.fullId):items,this.selectedIndex=Math.min(this.selectedIndex,Math.max(0,this.filteredItems.length-1)),this.updateList(),this.footerText.setText(this.getFooterText())}notifyChange(){this.callbacks.onChange(this.enabledIds===null?null:[...this.enabledIds])}updateList(){if(this.listContainer.clear(),this.filteredItems.length===0){this.listContainer.addChild(new Text(theme.fg("muted"," No matching models"),0,0));return}let startIndex=Math.max(0,Math.min(this.selectedIndex-Math.floor(this.maxVisible/2),this.filteredItems.length-this.maxVisible)),endIndex=Math.min(startIndex+this.maxVisible,this.filteredItems.length);for(let i=startIndex;i<endIndex;i++){let item=this.filteredItems[i],isSelected2=i===this.selectedIndex,prefix=isSelected2?theme.fg("accent","\u2192 "):" ",id=item.model?.id??item.fullId,styledId=item.model?id:theme.strikethrough(id),modelText2=isSelected2?theme.fg("accent",styledId):styledId,providerBadge=theme.fg("muted",item.model?` [${item.model.provider}]`:" [unavailable]"),status=item.model&&item.enabled?theme.fg("accent","\u2713 "):" ";this.listContainer.addChild(new Text(`${prefix}${status}${modelText2}${providerBadge}`,0,0))}if((startIndex>0||endIndex<this.filteredItems.length)&&this.listContainer.addChild(new Text(theme.fg("muted",` (${this.selectedIndex+1}/${this.filteredItems.length})`),0,0)),this.filteredItems.length>0){let selected=this.filteredItems[this.selectedIndex];this.listContainer.addChild(new Spacer(1)),this.listContainer.addChild(new Text(theme.fg("muted",` ${selected.model?`Model Name: ${selected.model.name}`:"Model unavailable"}`),0,0))}}handleInput(data){let kb=getKeybindings();if(kb.matches(data,"tui.select.up")){if(this.filteredItems.length===0)return;this.selectedIndex=this.selectedIndex===0?this.filteredItems.length-1:this.selectedIndex-1,this.updateList();return}if(kb.matches(data,"tui.select.down")){if(this.filteredItems.length===0)return;this.selectedIndex=this.selectedIndex===this.filteredItems.length-1?0:this.selectedIndex+1,this.updateList();return}let reorderUp=kb.matches(data,"app.models.reorderUp"),reorderDown=kb.matches(data,"app.models.reorderDown");if(reorderUp||reorderDown){if(this.enabledIds===null)return;let item=this.filteredItems[this.selectedIndex];if(item&&isEnabled2(this.enabledIds,item.fullId)){let delta=reorderUp?-1:1,newIndex=this.enabledIds.indexOf(item.fullId)+delta;newIndex>=0&&newIndex<this.enabledIds.length&&(this.enabledIds=move(this.enabledIds,item.fullId,delta),this.isDirty=!0,this.selectedIndex+=delta,this.refresh(),this.notifyChange())}return}if(kb.matches(data,"tui.select.confirm")){let item=this.filteredItems[this.selectedIndex];item&&(this.enabledIds=toggle(this.enabledIds,this.allIds,item.fullId),this.isDirty=!0,this.refresh(),this.notifyChange());return}if(kb.matches(data,"app.models.enableAll")){let targetIds=this.searchInput.getValue()?this.filteredItems.map(i=>i.fullId):void 0;this.enabledIds=enableAll(this.enabledIds,this.allIds,targetIds),this.isDirty=!0,this.refresh(),this.notifyChange();return}if(kb.matches(data,"app.models.clearAll")){let targetIds=this.searchInput.getValue()?this.filteredItems.map(i=>i.fullId):void 0;this.enabledIds=clearAll(this.enabledIds,this.allIds,targetIds),this.isDirty=!0,this.refresh(),this.notifyChange();return}if(kb.matches(data,"app.models.toggleProvider")){let item=this.filteredItems[this.selectedIndex];if(item?.model){let provider=item.model.provider,providerIds=this.allIds.filter(id=>this.modelsById.get(id).provider===provider),allEnabled=providerIds.every(id=>isEnabled2(this.enabledIds,id));this.enabledIds=allEnabled?clearAll(this.enabledIds,this.allIds,providerIds):enableAll(this.enabledIds,this.allIds,providerIds),this.isDirty=!0,this.refresh(),this.notifyChange()}return}if(kb.matches(data,"app.models.save")){this.callbacks.onPersist(this.enabledIds===null?null:[...this.enabledIds]),this.isDirty=!1,this.footerText.setText(this.getFooterText());return}if(matchesKey(data,Key.ctrl("c"))){this.searchInput.getValue()?(this.searchInput.setValue(""),this.refresh()):this.callbacks.onCancel();return}if(matchesKey(data,Key.escape)){this.callbacks.onCancel();return}this.searchInput.handleInput(data),this.refresh()}getSearchInput(){return this.searchInput}};var StatusIndicator=class extends Loader{constructor(kind,ui,spinnerColorFn,messageColorFn,message,indicator){super(ui,spinnerColorFn,messageColorFn,message,indicator),this.kind=kind}renderInBorder(width){let line=super.render(width+2)[1]??"";return truncateToWidth(line.startsWith(" ")?line.slice(1).trimEnd():line.trimEnd(),width,"")}renderSpinnerInBorder(width){return truncateToWidth(this.getRenderedIndicator(),width,"")}dispose(){this.stop()}},WorkingStatusIndicator=class extends StatusIndicator{constructor(ui,message,indicator,colorFn){super("working",ui,colorFn??(text2=>theme.fg("accent",text2)),colorFn??(text2=>theme.fg("muted",text2)),message,indicator)}},RetryStatusIndicator=class extends StatusIndicator{constructor(ui,attempt2,maxAttempts,delayMs){let retryMessage=seconds=>`Retrying (${attempt2}/${maxAttempts}) in ${seconds}s... (${keyText("app.interrupt")} to cancel)`;super("retry",ui,spinner=>theme.fg("warning",spinner),text2=>theme.fg("muted",text2),retryMessage(Math.ceil(delayMs/1e3))),this.countdown=new CountdownTimer(delayMs,ui,seconds=>{this.setMessage(retryMessage(seconds))},()=>{this.countdown=void 0})}dispose(){this.countdown?.dispose(),this.countdown=void 0,super.dispose()}},CompactionStatusIndicator=class extends StatusIndicator{constructor(ui,reason,colorFn){let cancelHint=`(${keyText("app.interrupt")} to cancel)`,label=reason==="manual"?`Compacting context... ${cancelHint}`:`${reason==="overflow"?"Context overflow detected, ":""}Auto-compacting... ${cancelHint}`;super("compaction",ui,colorFn??(spinner=>theme.fg("accent",spinner)),colorFn??(text2=>theme.fg("muted",text2)),label)}},BranchSummaryStatusIndicator=class extends StatusIndicator{constructor(ui){super("branchSummary",ui,spinner=>theme.fg("accent",spinner),text2=>theme.fg("muted",text2),`Summarizing branch... (${keyText("app.interrupt")} to cancel)`)}},IdleStatus=class{invalidate(){}render(width){let emptyLine=" ".repeat(width);return[emptyLine,emptyLine]}};var ThemedText=class extends Text{constructor(build,paddingX=1,paddingY=1){super("",paddingX,paddingY),this.stale=!0,this.build=build}invalidate(){super.invalidate(),this.stale=!0}render(width){return this.stale&&(this.stale=!1,this.setText(this.build())),super.render(width)}};function formatDecision(trustPath,decision){if(decision===null)return"none";let label=decision.decision?"trusted":"untrusted";return trustPath!==void 0&&decision.path!==trustPath?`${label} (inherited from ${decision.path})`:`${label} (${decision.path})`}var TrustSelectorComponent=class extends Container{constructor(options){super(),this.savedDecision=options.savedDecision,this.trustOptions=getProjectTrustOptions(options.cwd),this.selectedIndex=Math.max(0,this.trustOptions.findIndex(option=>this.isSavedOption(option))),this.onSelectCallback=options.onSelect,this.onCancelCallback=options.onCancel,this.addChild(new DynamicBorder),this.addChild(new Spacer(1)),this.addChild(new Text(theme.fg("accent",theme.bold("Project trust")),1,0)),this.addChild(new Text(theme.fg("muted",options.cwd),1,0)),this.addChild(new Spacer(1)),this.addChild(new Text(theme.fg("muted",`Saved decision: ${formatDecision(this.trustOptions[0]?.savedPath,options.savedDecision)}`),1,0)),this.addChild(new Text(theme.fg("muted",`Current session: ${options.projectTrusted?"trusted":"untrusted"}`),1,0)),this.addChild(new Spacer(1)),this.listContainer=new Container,this.addChild(this.listContainer),this.addChild(new Spacer(1)),this.addChild(new Text(rawKeyHint("\u2191\u2193","navigate")+" "+keyHint("tui.select.confirm","save")+" "+keyHint("tui.select.cancel","cancel"),1,0)),this.addChild(new Spacer(1)),this.addChild(new DynamicBorder),this.updateList()}isSavedOption(option){return option.savedPath!==void 0&&this.savedDecision?.decision===option.trusted&&this.savedDecision.path===option.savedPath}updateList(){this.listContainer.clear();for(let i=0;i<this.trustOptions.length;i++){let option=this.trustOptions[i];if(!option)continue;let isSelected2=i===this.selectedIndex,currentMarker=this.isSavedOption(option)?theme.fg("accent","\u2713 "):" ",prefix=isSelected2?theme.fg("accent","\u2192 "):" ",label=isSelected2?theme.fg("accent",option.label):theme.fg("text",option.label);this.listContainer.addChild(new Text(`${prefix}${currentMarker}${label}`,1,0))}}handleInput(keyData){let kb=getKeybindings();if(kb.matches(keyData,"tui.select.up")||keyData==="k")this.selectedIndex=Math.max(0,this.selectedIndex-1),this.updateList();else if(kb.matches(keyData,"tui.select.down")||keyData==="j")this.selectedIndex=Math.min(this.trustOptions.length-1,this.selectedIndex+1),this.updateList();else if(kb.matches(keyData,"tui.select.confirm")||keyData===`
|
|
1828
1834
|
`){let selected=this.trustOptions[this.selectedIndex];selected&&this.onSelectCallback({trusted:selected.trusted,updates:selected.updates})}else kb.matches(keyData,"tui.select.cancel")&&this.onCancelCallback()}};var HIDDEN_BUILTIN_COMMANDS=["debug","arminsayshi","dementedelves"],InteractiveEditorHost=class{constructor(options){this.submitHandlers=new Set,this.options=options}onSubmit(handler){return this.submitHandlers.add(handler),()=>this.submitHandlers.delete(handler)}getCursor(){return this.options.getEditor().getCursor?.()}onInput(handler){return this.options.addTerminalInputListener(data=>this.isEditorFocused()?handler(data):void 0)}isEditorFocused(){let editor=this.options.getEditor();return this.options.getFocusedComponent()===editor&&!this.options.hasOverlay()&&!editor.isShowingAutocomplete?.()}clear(){this.submitHandlers.clear()}classify(text2){if(text2.startsWith("!"))return"bash";if(!text2.startsWith("/"))return"prompt";let name=text2.slice(1).split(/\s/,1)[0];return BUILTIN_SLASH_COMMANDS.some(command=>command.name===name)||HIDDEN_BUILTIN_COMMANDS.includes(name)||this.options.isSessionCommand(name)?"command":"prompt"}intercept(text2,mode){if(mode==="steer"&&this.declinedFollowUp===text2||this.submitHandlers.size===0)return!1;let event={text:text2,mode,kind:this.classify(text2)};for(let handler of this.submitHandlers)try{let result2=handler(event);if(!result2?.handled)continue;return this.options.setEditorText(result2.editorText??""),this.options.requestRender(),!0}catch(error){return this.options.setEditorText(text2),this.options.showError(`Editor submit handler failed: ${error instanceof Error?error.message:String(error)}`),!0}return mode==="followUp"&&(this.declinedFollowUp=text2,queueMicrotask(()=>{this.declinedFollowUp=void 0})),!1}};function firstLine2(text2){return text2?.split(/\r?\n/,1)[0]?.trim()||"Error"}var ProgramStatusReporter=class{constructor(getTerminal,getSessionName){this.runActive=!1,this.compacting=!1,this.runResult={state:"done"},this.restingStatus={state:"idle"},this.blocked=new Map,this.getTerminal=getTerminal,this.getSessionName=getSessionName}handleEvent(event){switch(event.type){case"agent_start":this.runActive=!0,this.runResult={state:"done"};break;case"message_end":if(event.message.role!=="assistant")return;this.runResult=event.message.stopReason==="error"?{state:"error",message:firstLine2(event.message.errorMessage)}:{state:"done"};break;case"compaction_start":this.compacting=!0;break;case"compaction_end":this.compacting=!1,this.runActive?event.aborted?this.runResult={state:"idle"}:event.errorMessage&&(this.runResult={state:"error",message:firstLine2(event.errorMessage)}):event.aborted?this.restingStatus={state:"idle"}:event.reason==="manual"&&(this.restingStatus=event.errorMessage?{state:"error",message:firstLine2(event.errorMessage)}:{state:"done"});break;case"agent_settled":this.runActive=!1,this.restingStatus=event.aborted?{state:"idle"}:this.runResult;break;case"session_info_changed":break;default:return}this.report()}setBlocked(source,status){this.blocked.delete(source),status&&this.blocked.set(source,status),this.report()}reset(){this.runActive=!1,this.compacting=!1,this.runResult={state:"done"},this.restingStatus={state:"idle"},this.report()}report(){let status={...this.currentStatus(),app:APP_NAME},key=JSON.stringify(status);key!==this.lastReport&&(this.lastReport=key,this.getTerminal().setProgramStatus(status))}currentStatus(){let blocked=[...this.blocked.values()].at(-1);if(blocked)return{state:"blocked",...blocked};if(this.compacting)return{state:"working",message:"Compacting context"};let status=this.runActive?{state:"working"}:this.restingStatus;return status.state==="working"||status.state==="done"?{...status,message:this.getSessionName()}:status}};var TERMINAL_QUERY_TIMEOUT_MS=100;function requestTerminalColors(ui,apply){let query;try{query=ui.queryTerminalColors({timeoutMs:TERMINAL_QUERY_TIMEOUT_MS,onLateReply:apply})}catch{query=Promise.resolve({})}return query.then(apply,()=>apply({}))}function sameRgb(a,b2){return a===b2||a!==void 0&&b2!==void 0&&a.r===b2.r&&a.g===b2.g&&a.b===b2.b}function sameTerminalColors(a,b2){return!sameRgb(a.foreground,b2.foreground)||!sameRgb(a.background,b2.background)?!1:a.palette===b2.palette?!0:!a.palette||!b2.palette||a.palette.length!==b2.palette.length?!1:a.palette.every((color2,index3)=>sameRgb(color2,b2.palette?.[index3]))}var InteractiveThemeController=class{constructor(ui,options){this.autoSyncEnabled=!1,this.terminalColorQuery=Promise.resolve(),this.ui=ui,this.getSettingsManager=options.getSettingsManager,this.showError=options.showError,this.onChanged=options.onChanged,this.currentThemeSetting=options.initialThemeSetting,this.activeThemeName=this.resolveThemeName(),markTerminalColorsPending(),initTheme(this.activeThemeName,!0),this.bindTerminalColorSchemeListener()}rebindTui(){this.terminalColorSchemeUnsubscribe?.(),this.bindTerminalColorSchemeListener(),this.ui.setTerminalColorSchemeNotifications(this.autoSyncEnabled)}applyFromSettings(){let themeSetting=this.getThemeSetting(),themeName=this.resolveThemeName();this.setAutoSync(parseAutoThemeSetting(themeSetting)!==void 0||themeName===SYSTEM_THEME_NAME),this.applyThemeName(themeName,themeSetting!==void 0),this.queryTerminalColors()}waitForTerminalColors(){return this.terminalColorQuery}getThemeSelection(){return this.currentThemeSetting??this.getSettingsManager().getThemeSetting()??this.activeThemeName}setThemeName(themeName,showError=!1){this.setAutoSync(themeName===SYSTEM_THEME_NAME);let result2=this.applyThemeName(themeName,showError);return result2.success&&(this.currentThemeSetting=themeName),result2}setThemeSetting(themeSetting){this.currentThemeSetting=themeSetting,this.applyFromSettings()}setThemeInstance(themeInstance){return this.setAutoSync(!1),setThemeInstance(themeInstance),this.activeThemeName="<in-memory>",this.notifyChanged(),{success:!0}}preview(themeSettingOrName){let themeName=resolveThemeSetting(themeSettingOrName,getTerminalTheme())??this.activeThemeName;themeName&&setTheme(themeName,!0).success&&(this.ui.invalidate(),this.ui.requestRender())}disableAutoSync(){this.setAutoSync(!1)}dispose(){this.setAutoSync(!1),this.terminalColorSchemeUnsubscribe?.(),this.terminalColorSchemeUnsubscribe=void 0}getTerminalTheme(){return getTerminalTheme()}getThemeSetting(){return this.currentThemeSetting??this.getSettingsManager().getThemeSetting()}resolveThemeName(){return resolveThemeSetting(this.getThemeSetting(),getTerminalTheme())??SYSTEM_THEME_NAME}applyThemeName(themeName,showError=!1){let result2=setTheme(themeName,!0);return this.activeThemeName=result2.success?themeName:SYSTEM_THEME_NAME,this.notifyChanged(),!result2.success&&showError&&this.showError(`Failed to load theme "${themeName}": ${result2.error}
|
|
1829
|
-
Fell back to the system theme.`),result2}queryTerminalColors(){this.terminalColorQuery=requestTerminalColors(this.ui,colors=>this.applyTerminalColors(colors))}applyTerminalColors(reported){let previous=this.terminalColors,next={foreground:reported.foreground??previous?.foreground,background:reported.background??previous?.background,palette:reported.palette??previous?.palette};previous&&sameTerminalColors(previous,next)||(this.terminalColors=next,setTerminalColors(next),this.reapplyForTerminal(),this.ui.invalidate(),this.ui.requestRender())}reapplyForTerminal(){if(this.activeThemeName==="<in-memory>")return;let themeName=this.resolveThemeName();(themeName===SYSTEM_THEME_NAME||themeName!==this.activeThemeName)&&this.applyThemeName(themeName)}setAutoSync(enabled){this.autoSyncEnabled!==enabled&&(this.autoSyncEnabled=enabled,this.ui.setTerminalColorSchemeNotifications(enabled))}bindTerminalColorSchemeListener(){this.terminalColorSchemeUnsubscribe=this.ui.onTerminalColorSchemeChange(terminalTheme=>this.applyTerminalColorSchemeChange(terminalTheme))}applyTerminalColorSchemeChange(terminalTheme){if(!this.autoSyncEnabled)return;let previous=getTerminalTheme();setTerminalColorScheme(terminalTheme),getTerminalTheme()!==previous&&this.reapplyForTerminal(),this.queryTerminalColors()}notifyChanged(){this.ui.invalidate(),this.onChanged()}};function disposeAll(components){for(let component of components){let disposable=component;typeof disposable.dispose=="function"&&disposable.dispose()}}var ToolChatContainer=class extends Container{render(width){let previous,previousHeight=0;for(let child of this.children){if(child instanceof ToolExecutionComponent){child.setLeadingGap(0);let lines=child.render(width),start=lines.findIndex(line=>stripAnsi(line).trim().length>0);if(start===-1)continue;let{afterTool,afterMultilineTool,afterOther}=toolStyle.gap;child.setLeadingGap(previous instanceof ToolExecutionComponent?previousHeight>1?afterMultilineTool:afterTool:afterOther),previousHeight=lines.length-start}previous=child}return super.render(width)}clear(){disposeAll(this.children),super.clear()}},PendingToolMap=class extends Map{clear(){disposeAll(this.values()),super.clear()}};function disposeChatRows(chat2){disposeAll(chat2.children)}function createInteractiveTui(options){let terminal=options.terminal??new ProcessTerminal;if(options.tuiMode==="fullscreen"){let styleSearchMatch=text2=>theme.bg("searchMatchBg",theme.fg("searchMatchText",text2));return new TuiAltScreen(terminal,options.showHardwareCursor,options.logDirectory,{searchMatchStyle:text2=>theme.underline(styleSearchMatch(text2)),searchCurrentMatchStyle:text2=>theme.bold(theme.inverse(styleSearchMatch(text2))),searchNavigationButtonStyle:(text2,hovered)=>hovered?theme.underline(text2):text2,scrollToEndIndicator:()=>{let shortcut=keyDisplayText("tui.altScreen.bottom"),label=` \u2193 Jump to latest message${shortcut?` \xB7 ${shortcut}`:""} `;return theme.bg("selectedBg",theme.fg("text",label))},openUrl:openBrowser,onRightClickPaste:options.onRightClickPaste,copyOnSelect:options.fullscreenCopyOnSelect,wheelScrollLines:options.fullscreenWheelScrollLines??"auto",copySelection:async text2=>{try{return await copyToClipboard(text2),!0}catch(error){return error instanceof Error?error.message:String(error)}}})}return new TuiMainScreen(terminal,options.showHardwareCursor,options.logDirectory)}function createInteractiveTuiReference(getTui){return new Proxy({},{get:(_target,property)=>{let tui=getTui(),value=Reflect.get(tui,property,tui);if(typeof value!="function")return value;let methodTui=tui,method=value;return(...args)=>{let currentTui=getTui();if(currentTui!==methodTui){let currentMethod=Reflect.get(currentTui,property,currentTui);if(typeof currentMethod!="function")throw new TypeError(`TUI property ${String(property)} is not callable`);methodTui=currentTui,method=currentMethod}return Reflect.apply(method,methodTui,args)}},set:(_target,property,value)=>{let tui=getTui();return Reflect.set(tui,property,value,tui)},has:(_target,property)=>Reflect.has(getTui(),property),getPrototypeOf:()=>Reflect.getPrototypeOf(getTui())})}function isEmbeddedStatus(editor){return"embedWorkingStatus"in editor&&editor.embedWorkingStatus===!0&&"setWorkingStatusIndicator"in editor&&typeof editor.setWorkingStatusIndicator=="function"}function isExpandable(obj){return typeof obj=="object"&&obj!==null&&"setExpanded"in obj&&typeof obj.setExpanded=="function"}var ExpandableText=class extends ThemedText{constructor(getCollapsedText,getExpandedText,expanded=!1,paddingX=0,paddingY=0){let state2={expanded};super(()=>state2.expanded?getExpandedText():getCollapsedText(),paddingX,paddingY),this.state=state2}setExpanded(expanded){this.state.expanded=expanded,this.invalidate()}},BuiltInHeader=class extends ExpandableText{handleMouse(event){if(!(event.type!=="click"||event.y>1||event.x<1||event.x>4||!this.onLogoClick))return this.onLogoClick(event.screenX-event.x+1,event.screenY-event.y),{handled:!0}}};function isCustomSessionEntry(item){return"type"in item&&item.type==="custom"}function isCompactionCostNotice(item){return"type"in item&&item.type==="compaction_cost"}function isUsageSessionEntry(item){return"type"in item&&item.type==="usage"}var DEAD_TERMINAL_ERROR_CODES=new Set(["EIO","EPIPE","ENOTCONN","ENOTTY"]);function isDeadTerminalError(error){if(!error||typeof error!="object"||!("code"in error))return!1;let code=error.code;return code!==void 0&&DEAD_TERMINAL_ERROR_CODES.has(code)}function formatCrashExtensionHint(extensionMatches){let matches=Array.isArray(extensionMatches)?extensionMatches.filter(match2=>typeof match2=="string"&&match2.length>0):[];if(matches.length===0)return;let quoted=matches.map(match2=>`\`${match2}\``),labels=quoted.length===1?quoted[0]:quoted.length===2?quoted.join(" and "):`${quoted.slice(0,-1).join(", ")}, and ${quoted[quoted.length-1]}`,noun=matches.length===1?"extension":"extensions",pronoun=matches.length===1?"it":"them";return`A stack frame came from loaded ${noun} ${labels}, which may be involved. Try disabling ${pronoun} with \`${APP_NAME} config\`, or run \`${APP_NAME} -ne\` to confirm.`}var ANTHROPIC_SUBSCRIPTION_AUTH_WARNING="Anthropic subscription auth is active. Third-party harness usage draws from extra usage and is billed per token, not your Claude plan limits. Manage extra usage at https://claude.ai/settings/usage. Disable this warning in /settings.";function isAnthropicSubscriptionAuthKey(apiKey){return typeof apiKey=="string"&&apiKey.startsWith("sk-ant-oat")}function isUnknownModel(model){return!!model&&model.provider==="unknown"&&model.id==="unknown"&&model.api==="unknown"}function quoteIfNeeded(value){return value.length>0&&!/[^a-zA-Z0-9_\-./~:@]/.test(value)?value:`'${value.replace(/'/g,"'\\''")}'`}function formatResumeCommand(sessionManager){if(!process.stdout.isTTY||!sessionManager.isPersisted())return;let sessionFile=sessionManager.getSessionFile();if(!sessionFile||!fs8.existsSync(sessionFile))return;let args=[APP_NAME];return sessionManager.usesDefaultSessionDir()||args.push("--session-dir",quoteIfNeeded(sessionManager.getSessionDir())),args.push("--session",sessionManager.getSessionId()),args.join(" ")}function hasDefaultModelProvider(providerId){return providerId in defaultModelPerProvider}function llamaCppPostLoginGuidance(actionLabel,loadedModelCount){return loadedModelCount===0?`${actionLabel}. No llama.cpp models are loaded. Use /llama to load a model, then /model to select it.`:`${actionLabel}. Use /model to select a loaded llama.cpp model, or /llama to manage models.`}var RADIUS_LOGIN_INTRO="Radius is a service crafted for Pi by the builders of Pi, Earendil Works",AUTH_TYPE_ORDER={oauth:0,api_key:1};function createFuzzyAutocompleteItems(items,prefix,getSearchText,toAutocompleteItem){let filtered=fuzzyFilter(items,prefix,getSearchText);return filtered.length===0?null:filtered.map(toAutocompleteItem)}function getLoginProviderCompletionOptions(providerOptions){let byId=new Map;for(let provider of providerOptions){let existing=byId.get(provider.id);if(existing){existing.authTypes.includes(provider.authType)||(existing.authTypes.push(provider.authType),existing.authTypes.sort((a,b2)=>AUTH_TYPE_ORDER[a]-AUTH_TYPE_ORDER[b2]));continue}byId.set(provider.id,{id:provider.id,name:provider.name,authTypes:[provider.authType],subscription:provider.subscription})}return Array.from(byId.values()).sort((a,b2)=>a.name.localeCompare(b2.name))}function getLoginProviderSearchText(provider){let authTypes=provider.authTypes.map(authType=>`${authType} ${formatAuthSelectorProviderType(authType,provider.subscription)}`).join(" ");return`${provider.id} ${provider.name} ${authTypes}`}function formatLoginProviderCompletionDescription(provider){let authTypes=provider.authTypes.map(authType=>formatAuthSelectorProviderType(authType,provider.subscription)).join("/");return provider.name===provider.id?authTypes:`${provider.name} \xB7 ${authTypes}`}var InteractiveMode=class _InteractiveMode{get session(){return this.runtimeHost.session}get agent(){return this.session.agent}get sessionManager(){return this.session.sessionManager}get settingsManager(){return this.session.settingsManager}constructor(runtimeHost,options={}){this.autocompleteProviderWrappers=[],this.isInitialized=!1,this.pendingUserInputs=[],this.activeStatusIndicator=void 0,this.activeWorkingIndicatorEmbedded=!1,this.idleStatus=new IdleStatus,this.workingMessage=void 0,this.workingVisible=!0,this.workingIndicatorOptions=void 0,this.defaultWorkingMessage="Working",this.defaultHiddenThinkingLabel="Thinking...",this.hiddenThinkingLabel=this.defaultHiddenThinkingLabel,this.lastSigintTime=0,this.lastEscapeTime=0,this.changelogMarkdown=void 0,this.startupNoticesShown=!1,this.anthropicSubscriptionWarningShown=!1,this.lastStatusSpacer=void 0,this.lastStatusText=void 0,this.lastStatusMessage="",this.managedToolStatusStarted=!1,this.streamingComponent=void 0,this.entriesRenderedByBoundaryCompaction=new Set,this.streamingMessage=void 0,this.pendingTools=new PendingToolMap,this.editorHost=new InteractiveEditorHost({isSessionCommand:name=>this.session.extensionRunner.getCommand(name)!==void 0||this.session.promptTemplates.some(template=>template.name===name)||this.skillCommands.has(name),getEditor:()=>this.editor,getFocusedComponent:()=>this.renderer.getFocusedComponent(),hasOverlay:()=>this.ui.hasOverlay(),addTerminalInputListener:handler=>this.addExtensionTerminalInputListener(handler),setEditorText:text2=>this.editor.setText(text2),requestRender:()=>this.ui.requestRender(),showError:message=>this.showError(message)}),this.toolOutputExpanded=!1,this.hideThinkingBlock=!1,this.outputPad=1,this.mermaidMarkdownTransformer=createMermaidMarkdownTransformer({getMode:()=>this.settingsManager.getMermaidRenderingMode(),theme}),this.skillCommands=new Map,this.signalCleanupHandlers=[],this.isBashMode=!1,this.bashComponent=void 0,this.pendingBashComponents=[],this.compactionQueuedMessages=[],this.shutdownRequested=!1,this.programStatus=new ProgramStatusReporter(()=>this.ui.terminal,()=>this.sessionManager.getSessionName()),this.bugReportHintShown=!1,this.installChangeWarningShown=!1,this.extensionDialogs=[],this.extensionTerminalInputSubscriptions=new Set,this.extensionWidgetsAbove=new Map,this.extensionWidgetsBelow=new Map,this.customFooter=void 0,this.builtInHeader=void 0,this.customHeader=void 0,this.onRightClickPaste=()=>{this.handleRightClickPaste()},this.isShuttingDown=!1,this.runtimeHost=runtimeHost,setCapabilityOverrides(this.settingsManager.getTerminalCapabilityOverrides());let tuiMode=options.tuiMode??this.settingsManager.getTuiMode();this.options={...options,tuiMode},this.autoTrustOnReloadCwd=options.autoTrustOnReloadCwd,this.runtimeHost.setBeforeSessionInvalidate(()=>{this.tasksUI?.dispose(),this.resetExtensionUI()}),this.runtimeHost.setRebindSession(async()=>{await this.rebindCurrentSession({renderBeforeBind:!0}),this.themeController.applyFromSettings()}),this.version=VERSION,this.renderer=createInteractiveTui({tuiMode,showHardwareCursor:this.settingsManager.getShowHardwareCursor(),logDirectory:getAgentDir(),terminal:options.terminal,onRightClickPaste:this.onRightClickPaste,fullscreenCopyOnSelect:this.settingsManager.getFullscreenCopyOnSelect(),fullscreenWheelScrollLines:this.settingsManager.getFullscreenWheelScrollLines()}),this.ui=createInteractiveTuiReference(()=>this.renderer),this.ui.setClearOnShrink(this.settingsManager.getClearOnShrink()),this.headerContainer=new Container,this.loadedResourcesContainer=new Container,this.chatContainer=new ToolChatContainer,this.documentContainer=new Container,this.documentContainer.addChild(this.headerContainer),this.documentContainer.addChild(this.loadedResourcesContainer),this.documentContainer.addChild(this.chatContainer),this.pendingMessagesContainer=new Container,this.statusContainer=new Container,this.widgetContainerAbove=new Container,this.widgetContainerBelow=new Container,this.keybindings=KeybindingsManager2.create(),setKeybindings(this.keybindings);let editorPaddingX=this.settingsManager.getEditorPaddingX(),autocompleteMaxVisible=this.settingsManager.getAutocompleteMaxVisible();this.defaultEditor=new CustomEditor(this.ui,getEditorTheme(),this.keybindings,{paddingX:editorPaddingX,autocompleteMaxVisible,embedWorkingStatus:!0}),this.editor=this.defaultEditor,this.editorContainer=new Container,this.editorContainer.addChild(this.editor),this.footerDataProvider=new FooterDataProvider(this.sessionManager.getCwd()),this.footer=new FooterComponent(this.session,this.footerDataProvider),this.footer.setAutoCompactEnabled(this.session.autoCompactionEnabled),this.footerContainer=new Container,this.footerContainer.addChild(this.footer),this.hideThinkingBlock=this.settingsManager.getHideThinkingBlock(),this.outputPad=this.settingsManager.getOutputPad(),setRegisteredThemes(this.session.resourceLoader.getThemes().themes),this.themeController=new InteractiveThemeController(this.ui,{getSettingsManager:()=>this.settingsManager,showError:message=>this.showError(message),onChanged:()=>this.updateEditorBorderColor(),initialThemeSetting:options.initialThemeSetting})}getAutocompleteSourceTag(sourceInfo){if(!sourceInfo||sourceInfo.source==="builtin")return;let scopePrefix=sourceInfo.scope==="user"?"u":sourceInfo.scope==="project"?"p":"t",source=sourceInfo.source.trim();if(source==="auto"||source==="local"||source==="cli")return scopePrefix;if(source.startsWith("npm:"))return`${scopePrefix}:${source}`;let gitSource=parseGitUrl(source);if(gitSource){let ref=gitSource.ref?`@${gitSource.ref}`:"";return`${scopePrefix}:git:${gitSource.host}/${gitSource.path}${ref}`}return scopePrefix}prefixAutocompleteDescription(description,sourceInfo){let sourceTag=this.getAutocompleteSourceTag(sourceInfo);return sourceTag?description?`[${sourceTag}] ${description}`:`[${sourceTag}]`:description}getBuiltInCommandConflictDiagnostics(extensionRunner){let builtinNames=new Set(BUILTIN_SLASH_COMMANDS.map(command=>command.name));return extensionRunner.getRegisteredCommands().filter(command=>builtinNames.has(command.name)).map(command=>({type:"warning",message:command.invocationName===command.name?`Extension command '/${command.name}' conflicts with built-in interactive command. Skipping in autocomplete.`:`Extension command '/${command.name}' conflicts with built-in interactive command. Available as '/${command.invocationName}'.`,path:command.sourceInfo.path}))}createBaseAutocompleteProvider(){let slashCommands=BUILTIN_SLASH_COMMANDS.map(command=>({name:command.name,description:command.description,...command.argumentHint&&{argumentHint:command.argumentHint}})),modelCommand=slashCommands.find(command=>command.name==="model");modelCommand&&(modelCommand.getArgumentCompletions=prefix=>{let models=this.session.scopedModels.length>0?this.session.scopedModels.map(s=>s.model):this.session.modelRuntime.getAvailableSnapshot();if(models.length===0)return null;let items=models.map(m2=>({id:m2.id,provider:m2.provider,name:m2.name,label:`${m2.provider}/${m2.id}`}));return createFuzzyAutocompleteItems(items,prefix,getModelSearchText,item=>({value:item.label,label:item.id,description:item.provider}))});let thinkingCommand=slashCommands.find(command=>command.name==="thinking");thinkingCommand&&(thinkingCommand.getArgumentCompletions=prefix=>createFuzzyAutocompleteItems(this.session.getAvailableThinkingLevels(),prefix,level=>level,level=>({value:level,label:level})));let loginCommand=slashCommands.find(command=>command.name==="login");loginCommand&&(loginCommand.getArgumentCompletions=prefix=>{let providers=getLoginProviderCompletionOptions(this.getLoginProviderOptions());return createFuzzyAutocompleteItems(providers,prefix,getLoginProviderSearchText,provider=>({value:provider.id,label:provider.id,description:formatLoginProviderCompletionDescription(provider)}))});let templateCommands=this.session.promptTemplates.map(cmd=>({name:cmd.name,description:this.prefixAutocompleteDescription(cmd.description,cmd.sourceInfo),...cmd.argumentHint&&{argumentHint:cmd.argumentHint}})),builtinCommandNames=new Set(slashCommands.map(c=>c.name)),extensionCommands=this.session.extensionRunner.getRegisteredCommands().filter(cmd=>!builtinCommandNames.has(cmd.name)).map(cmd=>({name:cmd.invocationName,description:this.prefixAutocompleteDescription(cmd.description,cmd.sourceInfo),getArgumentCompletions:cmd.getArgumentCompletions}));this.skillCommands.clear();let skillCommandList=[];if(this.settingsManager.getEnableSkillCommands())for(let skill of this.session.resourceLoader.getSkills().skills){let commandName=`skill:${skill.name}`;this.skillCommands.set(commandName,skill.filePath),skillCommandList.push({name:commandName,description:this.prefixAutocompleteDescription(skill.description,skill.sourceInfo)})}return new CombinedAutocompleteProvider([...slashCommands,...templateCommands,...extensionCommands,...skillCommandList],this.sessionManager.getCwd(),this.fdPath)}setupAutocompleteProvider(){let provider=this.createBaseAutocompleteProvider(),triggerCharacters=[];for(let wrapProvider of this.autocompleteProviderWrappers)provider=wrapProvider(provider),triggerCharacters.push(...provider.triggerCharacters??[]);triggerCharacters.length>0&&(provider.triggerCharacters=[...new Set(triggerCharacters)]),this.autocompleteProvider=provider,this.defaultEditor.setAutocompleteProvider(provider),this.editor!==this.defaultEditor&&this.editor.setAutocompleteProvider?.(provider)}showStartupNoticesIfNeeded(){if(!this.startupNoticesShown&&(this.startupNoticesShown=!0,!!this.changelogMarkdown)){if(this.chatContainer.children.length>0&&this.chatContainer.addChild(new Spacer(1)),this.chatContainer.addChild(new DynamicBorder),this.settingsManager.getCollapseChangelog()){let versionMatch=this.changelogMarkdown.match(/##\s+\[?(\d+\.\d+\.\d+)\]?/),condensedText=`Updated to v${versionMatch?versionMatch[1]:this.version}. Use ${theme.bold("/changelog")} to view full changelog.`;this.chatContainer.addChild(new Text(condensedText,1,0))}else this.chatContainer.addChild(new ThemedText(()=>theme.bold(theme.fg("accent","What's New")),1,0)),this.chatContainer.addChild(new Spacer(1)),this.chatContainer.addChild(new Markdown(this.changelogMarkdown.trim(),1,0,this.getMarkdownThemeWithSettings())),this.chatContainer.addChild(new Spacer(1));this.chatContainer.addChild(new DynamicBorder)}}mountInteractiveTui(tui,components){for(let component of components)tui.addChild(component);if(isViewportTUI(tui)){if(!this.fullscreenLayoutRoot)throw new Error("Fullscreen layout is not initialized");tui.setLayoutRoot(this.fullscreenLayoutRoot)}}stopInteractiveTui(fullscreenExitOutput){if(this.renderer.mode==="fullscreen"&&fullscreenExitOutput==="transcript"){for(;this.renderer.hasOverlayEntries;)this.renderer.hideOverlay();this.switchTuiMode("regular",!1,!1),this.renderer.renderNow()}this.ui.stop({preserveScreen:this.renderer.mode==="fullscreen"})}switchTuiMode(mode,restoreProgress=!0,startRenderer=!0){let previousUi=this.renderer;if(mode===previousUi.mode)return!0;if(previousUi.hasOverlayEntries)return!1;let components=[...previousUi.children],focus=previousUi.getFocusedComponent(),terminal=previousUi.terminal,showHardwareCursor=previousUi.getShowHardwareCursor(),clearOnShrink=previousUi.getClearOnShrink(),onDebug=previousUi.onDebug;previousUi instanceof TuiMainScreen&&(this.mainScreenRenderState=previousUi.captureRenderState()),previousUi.stop({preserveScreen:!0}),previousUi.setFocus(null),previousUi.clear(),isViewportTUI(previousUi)&&previousUi.setLayoutRoot(void 0);let nextUi=createInteractiveTui({tuiMode:mode,showHardwareCursor,logDirectory:getAgentDir(),terminal,onRightClickPaste:this.onRightClickPaste,fullscreenCopyOnSelect:this.settingsManager.getFullscreenCopyOnSelect(),fullscreenWheelScrollLines:this.settingsManager.getFullscreenWheelScrollLines()});return nextUi.setClearOnShrink(clearOnShrink),nextUi.onDebug=onDebug,nextUi instanceof TuiMainScreen&&this.mainScreenRenderState&&nextUi.restoreRenderState(this.mainScreenRenderState),this.renderer=nextUi,this.options.tuiMode=mode,this.mountInteractiveTui(nextUi,components),nextUi.invalidate(),nextUi.setFocus(focus),startRenderer&&(nextUi.start(),this.themeController.rebindTui(),this.rebindExtensionTerminalInputListeners(),restoreProgress&&this.settingsManager.getShowTerminalProgress()&&(this.session.isStreaming||this.session.isCompacting)&&terminal.setProgress(!0)),!0}async init(){if(this.isInitialized)return;if(this.registerSignalHandlers(),this.changelogMarkdown=this.getChangelogForDisplay(),this.session.scopedModels.length>0&&this.shouldShowStartupDetails()){let modelList=this.session.scopedModels.map(sm=>{let thinkingStr=sm.thinkingLevel?`:${sm.thinkingLevel}`:"";return`${sm.model.id}${thinkingStr}`}).join(", "),cycleKeys=this.keybindings.getKeys("app.model.cycleForward"),cycleHint=cycleKeys.length>0?theme.fg("muted",` (${formatKeyText(cycleKeys.join("/"),{capitalize:!0})} to cycle)`):"";console.log(theme.fg("dim",`Model scope: ${modelList}${cycleHint}`))}this.renderWidgets();let viewport=createChatViewport({document:this.documentContainer,pendingMessages:this.pendingMessagesContainer,status:this.statusContainer,widgetsAbove:this.widgetContainerAbove,editor:this.editorContainer,widgetsBelow:this.widgetContainerBelow,footer:this.footerContainer,scrollbar:this.settingsManager.getFullscreenScrollbar(),scrollbarTrackStyle:text2=>theme.fg("scrollbarTrack",text2),scrollbarThumbStyle:text2=>theme.fg("scrollbarThumb",text2)});if(this.transcriptScrollView=viewport.transcript,this.fullscreenLayoutRoot=viewport.root,this.mountInteractiveTui(this.renderer,[this.documentContainer,this.pendingMessagesContainer,this.statusContainer,this.widgetContainerAbove,this.editorContainer,this.widgetContainerBelow,this.footerContainer]),this.defaultEditor.onAction("app.clear",()=>this.handleCtrlC()),this.defaultEditor.onCtrlD=()=>this.handleCtrlD(),this.defaultEditor.onSubmit=text2=>this.handleStartupSubmit(text2),this.ui.setFocus(this.editor),this.ui.start(),this.isInitialized=!0,this.programStatus.report(),this.ensurePngTranscoder(),this.themeController.applyFromSettings(),await this.themeController.waitForTerminalColors(),this.shouldShowStartupHeader()){let showDetails=this.shouldShowStartupDetails(),showLogo=supportsPiLogo(),withLogo=hints=>{if(!showLogo)return`${piWordmark()} ${theme.fg("dim",`v${this.version}`)}
|
|
1835
|
+
Fell back to the system theme.`),result2}queryTerminalColors(){this.terminalColorQuery=requestTerminalColors(this.ui,colors=>this.applyTerminalColors(colors))}applyTerminalColors(reported){let previous=this.terminalColors,next={foreground:reported.foreground??previous?.foreground,background:reported.background??previous?.background,palette:reported.palette??previous?.palette};previous&&sameTerminalColors(previous,next)||(this.terminalColors=next,setTerminalColors(next),this.reapplyForTerminal(),this.ui.invalidate(),this.ui.requestRender())}reapplyForTerminal(){if(this.activeThemeName==="<in-memory>")return;let themeName=this.resolveThemeName();(themeName===SYSTEM_THEME_NAME||themeName!==this.activeThemeName)&&this.applyThemeName(themeName)}setAutoSync(enabled){this.autoSyncEnabled!==enabled&&(this.autoSyncEnabled=enabled,this.ui.setTerminalColorSchemeNotifications(enabled))}bindTerminalColorSchemeListener(){this.terminalColorSchemeUnsubscribe=this.ui.onTerminalColorSchemeChange(terminalTheme=>this.applyTerminalColorSchemeChange(terminalTheme))}applyTerminalColorSchemeChange(terminalTheme){if(!this.autoSyncEnabled)return;let previous=getTerminalTheme();setTerminalColorScheme(terminalTheme),getTerminalTheme()!==previous&&this.reapplyForTerminal(),this.queryTerminalColors()}notifyChanged(){this.ui.invalidate(),this.onChanged()}};function disposeAll(components){for(let component of components){let disposable=component;typeof disposable.dispose=="function"&&disposable.dispose()}}var ToolChatContainer=class extends Container{render(width){let previous,previousHeight=0;for(let child of this.children){if(child instanceof ToolExecutionComponent){child.setLeadingGap(0);let lines=child.render(width),start=lines.findIndex(line=>stripAnsi(line).trim().length>0);if(start===-1)continue;let{afterTool,afterMultilineTool,afterOther}=child.getToolRowGap();child.setLeadingGap(previous instanceof ToolExecutionComponent?previousHeight>1?afterMultilineTool:afterTool:afterOther),previousHeight=lines.length-start}previous=child}return super.render(width)}clear(){disposeAll(this.children),super.clear()}},PendingToolMap=class extends Map{clear(){disposeAll(this.values()),super.clear()}};function disposeChatRows(chat2){disposeAll(chat2.children)}function createInteractiveTui(options){let terminal=options.terminal??new ProcessTerminal;if(options.tuiMode==="fullscreen"){let styleSearchMatch=text2=>theme.bg("searchMatchBg",theme.fg("searchMatchText",text2));return new TuiAltScreen(terminal,options.showHardwareCursor,options.logDirectory,{searchMatchStyle:text2=>theme.underline(styleSearchMatch(text2)),searchCurrentMatchStyle:text2=>theme.bold(theme.inverse(styleSearchMatch(text2))),searchNavigationButtonStyle:(text2,hovered)=>hovered?theme.underline(text2):text2,scrollToEndIndicator:()=>{let shortcut=keyDisplayText("tui.altScreen.bottom"),label=` \u2193 Jump to latest message${shortcut?` \xB7 ${shortcut}`:""} `;return theme.bg("selectedBg",theme.fg("text",label))},openUrl:openBrowser,onRightClickPaste:options.onRightClickPaste,copyOnSelect:options.fullscreenCopyOnSelect,wheelScrollLines:options.fullscreenWheelScrollLines??"auto",copySelection:async text2=>{try{return await copyToClipboard(text2),!0}catch(error){return error instanceof Error?error.message:String(error)}}})}return new TuiMainScreen(terminal,options.showHardwareCursor,options.logDirectory)}function createInteractiveTuiReference(getTui){return new Proxy({},{get:(_target,property)=>{let tui=getTui(),value=Reflect.get(tui,property,tui);if(typeof value!="function")return value;let methodTui=tui,method=value;return(...args)=>{let currentTui=getTui();if(currentTui!==methodTui){let currentMethod=Reflect.get(currentTui,property,currentTui);if(typeof currentMethod!="function")throw new TypeError(`TUI property ${String(property)} is not callable`);methodTui=currentTui,method=currentMethod}return Reflect.apply(method,methodTui,args)}},set:(_target,property,value)=>{let tui=getTui();return Reflect.set(tui,property,value,tui)},has:(_target,property)=>Reflect.has(getTui(),property),getPrototypeOf:()=>Reflect.getPrototypeOf(getTui())})}function isEmbeddedStatus(editor){return"embedWorkingStatus"in editor&&editor.embedWorkingStatus===!0&&"setWorkingStatusIndicator"in editor&&typeof editor.setWorkingStatusIndicator=="function"}function isExpandable(obj){return typeof obj=="object"&&obj!==null&&"setExpanded"in obj&&typeof obj.setExpanded=="function"}var ExpandableText=class extends ThemedText{constructor(getCollapsedText,getExpandedText,expanded=!1,paddingX=0,paddingY=0){let state2={expanded};super(()=>state2.expanded?getExpandedText():getCollapsedText(),paddingX,paddingY),this.state=state2}setExpanded(expanded){this.state.expanded=expanded,this.invalidate()}},BuiltInHeader=class extends ExpandableText{handleMouse(event){if(!(event.type!=="click"||event.y>1||event.x<1||event.x>4||!this.onLogoClick))return this.onLogoClick(event.screenX-event.x+1,event.screenY-event.y),{handled:!0}}};function isCustomSessionEntry(item){return"type"in item&&item.type==="custom"}function isCompactionCostNotice(item){return"type"in item&&item.type==="compaction_cost"}function isUsageSessionEntry(item){return"type"in item&&item.type==="usage"}var DEAD_TERMINAL_ERROR_CODES=new Set(["EIO","EPIPE","ENOTCONN","ENOTTY"]);function isDeadTerminalError(error){if(!error||typeof error!="object"||!("code"in error))return!1;let code=error.code;return code!==void 0&&DEAD_TERMINAL_ERROR_CODES.has(code)}function formatCrashExtensionHint(extensionMatches){let matches=Array.isArray(extensionMatches)?extensionMatches.filter(match2=>typeof match2=="string"&&match2.length>0):[];if(matches.length===0)return;let quoted=matches.map(match2=>`\`${match2}\``),labels=quoted.length===1?quoted[0]:quoted.length===2?quoted.join(" and "):`${quoted.slice(0,-1).join(", ")}, and ${quoted[quoted.length-1]}`,noun=matches.length===1?"extension":"extensions",pronoun=matches.length===1?"it":"them";return`A stack frame came from loaded ${noun} ${labels}, which may be involved. Try disabling ${pronoun} with \`${APP_NAME} config\`, or run \`${APP_NAME} -ne\` to confirm.`}var ANTHROPIC_SUBSCRIPTION_AUTH_WARNING="Anthropic subscription auth is active. Third-party harness usage draws from extra usage and is billed per token, not your Claude plan limits. Manage extra usage at https://claude.ai/settings/usage. Disable this warning in /settings.";function isAnthropicSubscriptionAuthKey(apiKey){return typeof apiKey=="string"&&apiKey.startsWith("sk-ant-oat")}function isUnknownModel(model){return!!model&&model.provider==="unknown"&&model.id==="unknown"&&model.api==="unknown"}function quoteIfNeeded(value){return value.length>0&&!/[^a-zA-Z0-9_\-./~:@]/.test(value)?value:`'${value.replace(/'/g,"'\\''")}'`}function formatResumeCommand(sessionManager){if(!process.stdout.isTTY||!sessionManager.isPersisted())return;let sessionFile=sessionManager.getSessionFile();if(!sessionFile||!fs8.existsSync(sessionFile))return;let args=[APP_NAME];return sessionManager.usesDefaultSessionDir()||args.push("--session-dir",quoteIfNeeded(sessionManager.getSessionDir())),args.push("--session",sessionManager.getSessionId()),args.join(" ")}function hasDefaultModelProvider(providerId){return providerId in defaultModelPerProvider}function llamaCppPostLoginGuidance(actionLabel,loadedModelCount){return loadedModelCount===0?`${actionLabel}. No llama.cpp models are loaded. Use /llama to load a model, then /model to select it.`:`${actionLabel}. Use /model to select a loaded llama.cpp model, or /llama to manage models.`}var RADIUS_LOGIN_INTRO="Radius is a service crafted for Pi by the builders of Pi, Earendil Works",AUTH_TYPE_ORDER={oauth:0,api_key:1};function createFuzzyAutocompleteItems(items,prefix,getSearchText,toAutocompleteItem){let filtered=fuzzyFilter(items,prefix,getSearchText);return filtered.length===0?null:filtered.map(toAutocompleteItem)}function getLoginProviderCompletionOptions(providerOptions){let byId=new Map;for(let provider of providerOptions){let existing=byId.get(provider.id);if(existing){existing.authTypes.includes(provider.authType)||(existing.authTypes.push(provider.authType),existing.authTypes.sort((a,b2)=>AUTH_TYPE_ORDER[a]-AUTH_TYPE_ORDER[b2]));continue}byId.set(provider.id,{id:provider.id,name:provider.name,authTypes:[provider.authType],subscription:provider.subscription})}return Array.from(byId.values()).sort((a,b2)=>a.name.localeCompare(b2.name))}function getLoginProviderSearchText(provider){let authTypes=provider.authTypes.map(authType=>`${authType} ${formatAuthSelectorProviderType(authType,provider.subscription)}`).join(" ");return`${provider.id} ${provider.name} ${authTypes}`}function formatLoginProviderCompletionDescription(provider){let authTypes=provider.authTypes.map(authType=>formatAuthSelectorProviderType(authType,provider.subscription)).join("/");return provider.name===provider.id?authTypes:`${provider.name} \xB7 ${authTypes}`}var InteractiveMode=class _InteractiveMode{get session(){return this.runtimeHost.session}get agent(){return this.session.agent}get sessionManager(){return this.session.sessionManager}get settingsManager(){return this.session.settingsManager}constructor(runtimeHost,options={}){this.autocompleteProviderWrappers=[],this.isInitialized=!1,this.pendingUserInputs=[],this.activeStatusIndicator=void 0,this.activeWorkingIndicatorEmbedded=!1,this.idleStatus=new IdleStatus,this.workingMessage=void 0,this.workingVisible=!0,this.workingIndicatorOptions=void 0,this.defaultWorkingMessage="Working",this.defaultHiddenThinkingLabel="Thinking...",this.hiddenThinkingLabel=this.defaultHiddenThinkingLabel,this.lastSigintTime=0,this.lastEscapeTime=0,this.changelogMarkdown=void 0,this.startupNoticesShown=!1,this.anthropicSubscriptionWarningShown=!1,this.lastStatusSpacer=void 0,this.lastStatusText=void 0,this.lastStatusMessage="",this.managedToolStatusStarted=!1,this.streamingComponent=void 0,this.entriesRenderedByBoundaryCompaction=new Set,this.streamingMessage=void 0,this.pendingTools=new PendingToolMap,this.editorHost=new InteractiveEditorHost({isSessionCommand:name=>this.session.extensionRunner.getCommand(name)!==void 0||this.session.promptTemplates.some(template=>template.name===name)||this.skillCommands.has(name),getEditor:()=>this.editor,getFocusedComponent:()=>this.renderer.getFocusedComponent(),hasOverlay:()=>this.ui.hasOverlay(),addTerminalInputListener:handler=>this.addExtensionTerminalInputListener(handler),setEditorText:text2=>this.editor.setText(text2),requestRender:()=>this.ui.requestRender(),showError:message=>this.showError(message)}),this.toolOutputExpanded=!1,this.hideThinkingBlock=!1,this.outputPad=1,this.mermaidMarkdownTransformer=createMermaidMarkdownTransformer({getMode:()=>this.settingsManager.getMermaidRenderingMode(),theme}),this.skillCommands=new Map,this.signalCleanupHandlers=[],this.isBashMode=!1,this.bashComponent=void 0,this.pendingBashComponents=[],this.compactionQueuedMessages=[],this.shutdownRequested=!1,this.programStatus=new ProgramStatusReporter(()=>this.ui.terminal,()=>this.sessionManager.getSessionName()),this.bugReportHintShown=!1,this.installChangeWarningShown=!1,this.extensionDialogs=[],this.extensionTerminalInputSubscriptions=new Set,this.extensionWidgetsAbove=new Map,this.extensionWidgetsBelow=new Map,this.customFooter=void 0,this.builtInHeader=void 0,this.customHeader=void 0,this.onRightClickPaste=()=>{this.handleRightClickPaste()},this.isShuttingDown=!1,this.runtimeHost=runtimeHost,setCapabilityOverrides(this.settingsManager.getTerminalCapabilityOverrides());let tuiMode=options.tuiMode??this.settingsManager.getTuiMode();this.options={...options,tuiMode},this.autoTrustOnReloadCwd=options.autoTrustOnReloadCwd,this.runtimeHost.setBeforeSessionInvalidate(()=>{this.tasksUI?.dispose(),this.resetExtensionUI()}),this.runtimeHost.setRebindSession(async()=>{await this.rebindCurrentSession({renderBeforeBind:!0}),this.themeController.applyFromSettings()}),this.version=VERSION,this.renderer=createInteractiveTui({tuiMode,showHardwareCursor:this.settingsManager.getShowHardwareCursor(),logDirectory:getAgentDir(),terminal:options.terminal,onRightClickPaste:this.onRightClickPaste,fullscreenCopyOnSelect:this.settingsManager.getFullscreenCopyOnSelect(),fullscreenWheelScrollLines:this.settingsManager.getFullscreenWheelScrollLines()}),this.ui=createInteractiveTuiReference(()=>this.renderer),this.ui.setClearOnShrink(this.settingsManager.getClearOnShrink()),this.headerContainer=new Container,this.loadedResourcesContainer=new Container,this.chatContainer=new ToolChatContainer,this.documentContainer=new Container,this.documentContainer.addChild(this.headerContainer),this.documentContainer.addChild(this.loadedResourcesContainer),this.documentContainer.addChild(this.chatContainer),this.pendingMessagesContainer=new Container,this.statusContainer=new Container,this.widgetContainerAbove=new Container,this.widgetContainerBelow=new Container,this.keybindings=KeybindingsManager2.create(),setKeybindings(this.keybindings);let editorPaddingX=this.settingsManager.getEditorPaddingX(),autocompleteMaxVisible=this.settingsManager.getAutocompleteMaxVisible();this.defaultEditor=new CustomEditor(this.ui,getEditorTheme(),this.keybindings,{paddingX:editorPaddingX,autocompleteMaxVisible,embedWorkingStatus:!0}),this.editor=this.defaultEditor,this.editorContainer=new Container,this.editorContainer.addChild(this.editor),this.footerDataProvider=new FooterDataProvider(this.sessionManager.getCwd()),this.footer=new FooterComponent(this.session,this.footerDataProvider),this.footer.setAutoCompactEnabled(this.session.autoCompactionEnabled),this.footerContainer=new Container,this.footerContainer.addChild(this.footer),this.hideThinkingBlock=this.settingsManager.getHideThinkingBlock(),this.outputPad=this.settingsManager.getOutputPad(),setRegisteredThemes(this.session.resourceLoader.getThemes().themes),this.themeController=new InteractiveThemeController(this.ui,{getSettingsManager:()=>this.settingsManager,showError:message=>this.showError(message),onChanged:()=>this.updateEditorBorderColor(),initialThemeSetting:options.initialThemeSetting})}getAutocompleteSourceTag(sourceInfo){if(!sourceInfo||sourceInfo.source==="builtin")return;let scopePrefix=sourceInfo.scope==="user"?"u":sourceInfo.scope==="project"?"p":"t",source=sourceInfo.source.trim();if(source==="auto"||source==="local"||source==="cli")return scopePrefix;if(source.startsWith("npm:"))return`${scopePrefix}:${source}`;let gitSource=parseGitUrl(source);if(gitSource){let ref=gitSource.ref?`@${gitSource.ref}`:"";return`${scopePrefix}:git:${gitSource.host}/${gitSource.path}${ref}`}return scopePrefix}prefixAutocompleteDescription(description,sourceInfo){let sourceTag=this.getAutocompleteSourceTag(sourceInfo);return sourceTag?description?`[${sourceTag}] ${description}`:`[${sourceTag}]`:description}getBuiltInCommandConflictDiagnostics(extensionRunner){let builtinNames=new Set(BUILTIN_SLASH_COMMANDS.map(command=>command.name));return extensionRunner.getRegisteredCommands().filter(command=>builtinNames.has(command.name)).map(command=>({type:"warning",message:command.invocationName===command.name?`Extension command '/${command.name}' conflicts with built-in interactive command. Skipping in autocomplete.`:`Extension command '/${command.name}' conflicts with built-in interactive command. Available as '/${command.invocationName}'.`,path:command.sourceInfo.path}))}createBaseAutocompleteProvider(){let slashCommands=BUILTIN_SLASH_COMMANDS.map(command=>({name:command.name,description:command.description,...command.argumentHint&&{argumentHint:command.argumentHint}})),modelCommand=slashCommands.find(command=>command.name==="model");modelCommand&&(modelCommand.getArgumentCompletions=prefix=>{let models=this.session.scopedModels.length>0?this.session.scopedModels.map(s=>s.model):this.session.modelRuntime.getAvailableSnapshot();if(models.length===0)return null;let items=models.map(m2=>({id:m2.id,provider:m2.provider,name:m2.name,label:`${m2.provider}/${m2.id}`}));return createFuzzyAutocompleteItems(items,prefix,getModelSearchText,item=>({value:item.label,label:item.id,description:item.provider}))});let thinkingCommand=slashCommands.find(command=>command.name==="thinking");thinkingCommand&&(thinkingCommand.getArgumentCompletions=prefix=>createFuzzyAutocompleteItems(this.session.getAvailableThinkingLevels(),prefix,level=>level,level=>({value:level,label:level})));let loginCommand=slashCommands.find(command=>command.name==="login");loginCommand&&(loginCommand.getArgumentCompletions=prefix=>{let providers=getLoginProviderCompletionOptions(this.getLoginProviderOptions());return createFuzzyAutocompleteItems(providers,prefix,getLoginProviderSearchText,provider=>({value:provider.id,label:provider.id,description:formatLoginProviderCompletionDescription(provider)}))});let templateCommands=this.session.promptTemplates.map(cmd=>({name:cmd.name,description:this.prefixAutocompleteDescription(cmd.description,cmd.sourceInfo),...cmd.argumentHint&&{argumentHint:cmd.argumentHint}})),builtinCommandNames=new Set(slashCommands.map(c=>c.name)),extensionCommands=this.session.extensionRunner.getRegisteredCommands().filter(cmd=>!builtinCommandNames.has(cmd.name)).map(cmd=>({name:cmd.invocationName,description:this.prefixAutocompleteDescription(cmd.description,cmd.sourceInfo),getArgumentCompletions:cmd.getArgumentCompletions}));this.skillCommands.clear();let skillCommandList=[];if(this.settingsManager.getEnableSkillCommands())for(let skill of this.session.resourceLoader.getSkills().skills){let commandName=`skill:${skill.name}`;this.skillCommands.set(commandName,skill.filePath),skillCommandList.push({name:commandName,description:this.prefixAutocompleteDescription(skill.description,skill.sourceInfo)})}return new CombinedAutocompleteProvider([...slashCommands,...templateCommands,...extensionCommands,...skillCommandList],this.sessionManager.getCwd(),this.fdPath)}setupAutocompleteProvider(){let provider=this.createBaseAutocompleteProvider(),triggerCharacters=[];for(let wrapProvider of this.autocompleteProviderWrappers)provider=wrapProvider(provider),triggerCharacters.push(...provider.triggerCharacters??[]);triggerCharacters.length>0&&(provider.triggerCharacters=[...new Set(triggerCharacters)]),this.autocompleteProvider=provider,this.defaultEditor.setAutocompleteProvider(provider),this.editor!==this.defaultEditor&&this.editor.setAutocompleteProvider?.(provider)}showStartupNoticesIfNeeded(){if(!this.startupNoticesShown&&(this.startupNoticesShown=!0,!!this.changelogMarkdown)){if(this.chatContainer.children.length>0&&this.chatContainer.addChild(new Spacer(1)),this.chatContainer.addChild(new DynamicBorder),this.settingsManager.getCollapseChangelog()){let versionMatch=this.changelogMarkdown.match(/##\s+\[?(\d+\.\d+\.\d+)\]?/),condensedText=`Updated to v${versionMatch?versionMatch[1]:this.version}. Use ${theme.bold("/changelog")} to view full changelog.`;this.chatContainer.addChild(new Text(condensedText,1,0))}else this.chatContainer.addChild(new ThemedText(()=>theme.bold(theme.fg("accent","What's New")),1,0)),this.chatContainer.addChild(new Spacer(1)),this.chatContainer.addChild(new Markdown(this.changelogMarkdown.trim(),1,0,this.getMarkdownThemeWithSettings())),this.chatContainer.addChild(new Spacer(1));this.chatContainer.addChild(new DynamicBorder)}}mountInteractiveTui(tui,components){for(let component of components)tui.addChild(component);if(isViewportTUI(tui)){if(!this.fullscreenLayoutRoot)throw new Error("Fullscreen layout is not initialized");tui.setLayoutRoot(this.fullscreenLayoutRoot)}}stopInteractiveTui(fullscreenExitOutput){if(this.renderer.mode==="fullscreen"&&fullscreenExitOutput==="transcript"){for(;this.renderer.hasOverlayEntries;)this.renderer.hideOverlay();this.switchTuiMode("regular",!1,!1),this.renderer.renderNow()}this.ui.stop({preserveScreen:this.renderer.mode==="fullscreen"})}switchTuiMode(mode,restoreProgress=!0,startRenderer=!0){let previousUi=this.renderer;if(mode===previousUi.mode)return!0;if(previousUi.hasOverlayEntries)return!1;let components=[...previousUi.children],focus=previousUi.getFocusedComponent(),terminal=previousUi.terminal,showHardwareCursor=previousUi.getShowHardwareCursor(),clearOnShrink=previousUi.getClearOnShrink(),onDebug=previousUi.onDebug;previousUi instanceof TuiMainScreen&&(this.mainScreenRenderState=previousUi.captureRenderState()),previousUi.stop({preserveScreen:!0}),previousUi.setFocus(null),previousUi.clear(),isViewportTUI(previousUi)&&previousUi.setLayoutRoot(void 0);let nextUi=createInteractiveTui({tuiMode:mode,showHardwareCursor,logDirectory:getAgentDir(),terminal,onRightClickPaste:this.onRightClickPaste,fullscreenCopyOnSelect:this.settingsManager.getFullscreenCopyOnSelect(),fullscreenWheelScrollLines:this.settingsManager.getFullscreenWheelScrollLines()});return nextUi.setClearOnShrink(clearOnShrink),nextUi.onDebug=onDebug,nextUi instanceof TuiMainScreen&&this.mainScreenRenderState&&nextUi.restoreRenderState(this.mainScreenRenderState),this.renderer=nextUi,this.options.tuiMode=mode,this.mountInteractiveTui(nextUi,components),nextUi.invalidate(),nextUi.setFocus(focus),startRenderer&&(nextUi.start(),this.themeController.rebindTui(),this.rebindExtensionTerminalInputListeners(),restoreProgress&&this.settingsManager.getShowTerminalProgress()&&(this.session.isStreaming||this.session.isCompacting)&&terminal.setProgress(!0)),!0}async init(){if(this.isInitialized)return;if(this.registerSignalHandlers(),this.changelogMarkdown=this.getChangelogForDisplay(),this.session.scopedModels.length>0&&this.shouldShowStartupDetails()){let modelList=this.session.scopedModels.map(sm=>{let thinkingStr=sm.thinkingLevel?`:${sm.thinkingLevel}`:"";return`${sm.model.id}${thinkingStr}`}).join(", "),cycleKeys=this.keybindings.getKeys("app.model.cycleForward"),cycleHint=cycleKeys.length>0?theme.fg("muted",` (${formatKeyText(cycleKeys.join("/"),{capitalize:!0})} to cycle)`):"";console.log(theme.fg("dim",`Model scope: ${modelList}${cycleHint}`))}this.renderWidgets();let viewport=createChatViewport({document:this.documentContainer,pendingMessages:this.pendingMessagesContainer,status:this.statusContainer,widgetsAbove:this.widgetContainerAbove,editor:this.editorContainer,widgetsBelow:this.widgetContainerBelow,footer:this.footerContainer,scrollbar:this.settingsManager.getFullscreenScrollbar(),scrollbarTrackStyle:text2=>theme.fg("scrollbarTrack",text2),scrollbarThumbStyle:text2=>theme.fg("scrollbarThumb",text2)});if(this.transcriptScrollView=viewport.transcript,this.fullscreenLayoutRoot=viewport.root,this.mountInteractiveTui(this.renderer,[this.documentContainer,this.pendingMessagesContainer,this.statusContainer,this.widgetContainerAbove,this.editorContainer,this.widgetContainerBelow,this.footerContainer]),this.defaultEditor.onAction("app.clear",()=>this.handleCtrlC()),this.defaultEditor.onCtrlD=()=>this.handleCtrlD(),this.defaultEditor.onSubmit=text2=>this.handleStartupSubmit(text2),this.ui.setFocus(this.editor),this.ui.start(),this.isInitialized=!0,this.programStatus.report(),this.ensurePngTranscoder(),this.themeController.applyFromSettings(),await this.themeController.waitForTerminalColors(),this.shouldShowStartupHeader()){let showDetails=this.shouldShowStartupDetails(),showLogo=supportsPiLogo(),withLogo=hints=>{if(!showLogo)return`${piWordmark()} ${theme.fg("dim",`v${this.version}`)}
|
|
1830
1836
|
${hints}`;let[top,bottom]=piLogoLines();return`${top} ${theme.fg("dim",`v${this.version}`)}
|
|
1831
1837
|
${bottom} ${hints}`},hint=(keybinding,description)=>keyHint(keybinding,description),expandedInstructions=()=>[hint("app.interrupt","to interrupt"),hint("app.clear","to clear"),rawKeyHint(`${keyText("app.clear")} twice`,"to exit"),hint("app.exit","to exit (empty)"),hint("app.suspend","to suspend"),keyHint("tui.editor.deleteToLineEnd","to delete to end"),hint("app.thinking.cycle","to cycle thinking level"),rawKeyHint(`${keyText("app.model.cycleForward")}/${keyText("app.model.cycleBackward")}`,"to cycle models"),hint("app.model.select","to select model"),hint("app.tools.expand","to expand tools"),hint("app.thinking.toggle","to expand thinking"),hint("app.editor.external","for external editor"),rawKeyHint("/","for commands"),rawKeyHint("!","to run bash"),rawKeyHint("!!","to run bash (no context)"),hint("app.message.followUp","to queue follow-up"),hint("app.message.dequeue","to edit all queued messages"),hint("app.clipboard.pasteImage","to paste files on macOS, images, or text"),rawKeyHint("drop files","to attach")].join(`
|
|
1832
1838
|
`),compactInstructions=()=>[hint("app.interrupt","interrupt"),rawKeyHint(`${keyText("app.clear")}/${keyText("app.exit")}`,"clear/exit"),rawKeyHint("/","commands"),rawKeyHint("!","bash"),hint("app.tools.expand","more")].join(theme.fg("muted"," \xB7 ")),compactOnboarding=()=>theme.fg("dim",`Press ${keyText("app.tools.expand")} to show full startup help${showDetails?" and loaded resources":""}.`),onboarding=()=>theme.fg("dim","Pi can explain its own features and look up its docs. Ask it how to use or extend Pi."),header2=new BuiltInHeader(()=>`${withLogo(compactInstructions())}
|
|
@@ -1975,7 +1981,62 @@ This conversation is temporary: it is not added to the original conversation and
|
|
|
1975
1981
|
|
|
1976
1982
|
[Display truncated]`}var BtwAgent=class{constructor(snapshot,runtime,onChange){this.turns=[],this.usage=emptyUsage(),this.blockedTools=0,this.disposed=!1,this.onChange=onChange;let outputReserve=Math.min(32768,snapshot.model.maxTokens,Math.max(1024,Math.floor(snapshot.model.contextWindow/8)));this.inputBudget=snapshot.model.contextWindow-outputReserve-4096;let tools=snapshot.tools.map(tool=>({...structuredClone(tool),label:tool.name,execute:async()=>{throw new Error(TOOL_DENIAL)}}));this.agent=new Agent({initialState:{model:snapshot.model,thinkingLevel:snapshot.thinkingLevel,systemPrompt:snapshot.systemPrompt,tools,messages:createBtwMessages(snapshot)},sessionId:snapshot.streamOptions.sessionId??snapshot.sessionId,transport:snapshot.streamOptions.transport,thinkingBudgets:snapshot.streamOptions.thinkingBudgets,maxRetryDelayMs:snapshot.streamOptions.maxRetryDelayMs,onPayload:snapshot.streamOptions.onPayload,onResponse:snapshot.streamOptions.onResponse,streamFn:(model,context,options)=>runtime.streamSimple(model,context,{...snapshot.streamOptions,...options}),beforeToolCall:async()=>({block:!0,reason:TOOL_DENIAL}),finishTurn:({message,toolResults,context})=>{let question2=this.active;if(!(!question2||this.disposed||message.stopReason==="error"||message.stopReason==="aborted")&&(question2.steps++,!!toolResults.length&&(question2.steps>=3||!this.fits(context.messages))))return question2.turn.status="error",question2.turn.notice=question2.steps>=3?"Stopped after repeated tool requests. BTW can only answer from its snapshot.":"Context limit reached. Reopen /btw for a new conversation.",{action:"end"}}}),this.unsubscribe=this.agent.subscribe(event=>this.handleEvent(event))}get busy(){return this.active!==void 0}validate(text2){if(this.disposed)return"This BTW conversation is closed.";if(this.busy)return"BTW is still answering. Your question is kept in the editor.";if(this.turns.length>=24)return"BTW conversation limit reached. Reopen /btw to start a new one.";if(text2.length>32e3)return`BTW questions are limited to ${32e3.toLocaleString()} characters.`;let question2={role:"user",content:text2,timestamp:Date.now()};if(!this.fits([...this.agent.state.messages,question2]))return"Not enough context space for this BTW question. Compact the main conversation, then reopen /btw."}startQuestion(text2){let error=this.validate(text2);if(error)return{error};let question2={turn:{question:text2,answer:"",thinking:"",status:"streaming",startedAt:Date.now(),elapsedMs:0},steps:0,completedAnswer:"",responseChars:0};return this.active=question2,this.turns.push(question2.turn),{completion:this.runQuestion(question2)}}async runQuestion({turn}){try{this.onChange(),await this.agent.prompt(turn.question),turn.status==="streaming"?(turn.status="done",turn.answer||(turn.notice="The model returned no answer text.")):turn.status==="cancelling"&&(turn.status="cancelled")}catch(error){turn.status="error",turn.notice=displayText(error instanceof Error?error.message:String(error))}finally{this.active=void 0,turn.elapsedMs=Date.now()-turn.startedAt,this.disposed?this.agent.reset():this.onChange()}}cancel(){!this.active||this.disposed||(this.active.turn.status="cancelling",this.agent.abort(),this.onChange())}dispose(){this.disposed||(this.disposed=!0,this.unsubscribe(),this.agent.abort(),this.turns.length=0,this.busy||this.agent.reset())}fits(messages){return estimateContextTokens(normalizeContext({systemPrompt:this.agent.state.systemPrompt,tools:this.agent.state.tools,messages:messages.filter(message=>message.role==="user"||message.role==="assistant"||message.role==="toolResult")})).tokens<this.inputBudget}handleEvent(event){let question2=this.active;if(this.disposed||!question2||event.type!=="message_update"&&event.type!=="message_end"||event.message.role!=="assistant")return;let{turn}=question2,message=event.message;if(this.updateAnswer(question2,message),event.type==="message_end"){question2.completedAnswer=turn.answer,question2.responseChars+=message.content.reduce((sum,part)=>sum+(part.type==="text"?part.text.length:part.type==="thinking"?part.thinking.length:JSON.stringify(part.arguments).length),0),this.blockedTools+=message.content.filter(part=>part.type==="toolCall").length;let usage=message.usage,promptTokens=usage.input+usage.cacheRead+usage.cacheWrite;this.latestCacheHitPercent=(usage.cacheRead>0||usage.cacheWrite>0)&&promptTokens>0?usage.cacheRead/promptTokens*100:void 0;for(let key of["input","output","cacheRead","cacheWrite","totalTokens"])this.usage[key]+=usage[key];for(let key of["input","output","cacheRead","cacheWrite","total"])this.usage.cost[key]+=usage.cost[key];(message.stopReason==="error"||message.stopReason==="aborted")&&(turn.status=message.stopReason==="aborted"?"cancelled":"error",turn.notice??=message.stopReason==="aborted"?"Stopped. You can ask another question.":displayText(message.errorMessage??"The request failed."))}this.onChange()}updateAnswer(question2,message){let{turn}=question2,text2=message.content.filter(part=>part.type==="text").map(part=>part.text).join(""),thinking=message.content.filter(part=>part.type==="thinking").map(part=>part.thinking).join("");text2&&turn.firstAnswerMs===void 0&&(turn.firstAnswerMs=Date.now()-turn.startedAt),turn.answer=displayText([question2.completedAnswer,text2].filter(Boolean).join(`
|
|
1977
1983
|
|
|
1978
|
-
`)),turn.thinking=thinking.slice(-2e3),question2.responseChars+JSON.stringify(message.content).length>512e3&&(turn.notice="Stopped at the BTW response size limit. You can ask a shorter follow-up.",this.agent.abort())}};function tokens(value){return value<1e3?String(value):value<1e4?`${(value/1e3).toFixed(1)}k`:value<1e6?`${Math.round(value/1e3)}k`:value<1e7?`${(value/1e6).toFixed(1)}M`:`${Math.round(value/1e6)}M`}var BtwPanel=class{constructor(tui,getTheme,getState){this.answers=new Map,this.follow=!0,this.offset=0,this.maxOffset=0,this.heldHeight=0,this.disposed=!1,this.tui=tui,this.getTheme=getTheme,this.getState=getState}invalidate(){this.answers.clear()}changed(){if(this.disposed)return;this.tui.requestRender();let state2=this.getState(),busy=state2.phase==="ready"&&state2.conversation.busy;busy&&!this.timer?(this.timer=setTimeout(()=>{this.timer=void 0,this.changed()},150),this.timer.unref?.()):!busy&&this.timer&&(clearTimeout(this.timer),this.timer=void 0)}followTail(){this.follow=!0,this.changed()}scroll(delta){return this.maxOffset===0?!1:(this.offset=Math.max(0,Math.min(this.maxOffset,this.offset+delta)),this.follow=this.offset===this.maxOffset,this.tui.requestRender(),!0)}dispose(){this.disposed=!0,this.timer&&clearTimeout(this.timer),this.timer=void 0,this.answers.clear()}render(width){if(this.disposed||width<1)return[];let state2=this.getState(),busy=state2.phase==="ready"&&state2.conversation.busy,theme2=this.getTheme(),innerWidth=Math.max(1,width-4),lines=this.body(state2,innerWidth,theme2),cap=Math.max(1,Math.floor(this.tui.terminal.rows/3)-2),needed=Math.min(cap,Math.max(1,lines.length));this.heldHeight=busy?Math.min(cap,Math.max(this.heldHeight,needed)):needed,this.maxOffset=Math.max(0,lines.length-this.heldHeight),this.offset=this.follow?this.maxOffset:Math.min(this.offset,this.maxOffset);let body2=lines.slice(this.offset,this.offset+this.heldHeight);for(;body2.length<this.heldHeight;)body2.push("");let close=keyLabel("app.btw.close"),cancel=keyLabel("app.btw.cancel"),title=[theme2.fg("accent",theme2.bold("BTW")),close&&theme2.fg("text",close)+theme2.fg("muted"," close"),busy&&cancel&&theme2.fg("text",cancel)+theme2.fg("muted"," stop")].filter(Boolean).join(theme2.fg("muted"," \xB7 ")),footer=this.footer(state2,theme2);return width<6?body2.map(line=>truncateToWidth(line,width)):[this.border(title,width,!0,theme2),...body2.map(line=>theme2.fg("borderAccent","\u2502 ")+truncateToWidth(line,innerWidth,"\u2026",!0)+theme2.fg("borderAccent"," \u2502")),this.border(footer,width,!1,theme2)]}body(state2,width,theme2){if(state2.phase==="opening")return[theme2.fg("muted","Capturing context\u2026")];if(state2.phase==="error")return new Text(theme2.fg("error",state2.error),0,0).render(width);if(!state2.conversation.turns.length)return[...new Text(theme2.fg("text","Ask a side question in the editor below."),0,0).render(width),...new Text(theme2.fg("muted",`Context at ${new Date(state2.capturedAt).toTimeString().slice(0,8)} \xB7 ${state2.model}`),0,0).render(width)];let lines=[];for(let[index3,turn]of state2.conversation.turns.entries()){if(index3>0&&lines.push(""),lines.push(...new Text(theme2.fg("accent",theme2.bold(`Q${index3+1}: `))+theme2.fg("text",turn.question),0,0).render(width)),turn.answer){let answer=this.answers.get(turn);answer?answer.text!==turn.answer&&(answer.text=turn.answer,answer.markdown.setText(turn.answer)):(answer={text:turn.answer,markdown:new Markdown(turn.answer,0,0,getMarkdownTheme(),{color:text2=>theme2.fg("text",text2)})},this.answers.set(turn,answer)),lines.push(...answer.markdown.render(width))}else turn.thinking&&(turn.status==="streaming"||turn.status==="cancelling")&&lines.push(...wrapTextWithAnsi(theme2.fg("muted",turn.thinking.trimEnd()),width).slice(-2));if(turn.status==="streaming"||turn.status==="cancelling"){let elapsed=((Date.now()-turn.startedAt)/1e3).toFixed(1);lines.push(theme2.fg("muted",`${turn.status==="cancelling"?"Stopping":"Answering"}\u2026 ${elapsed}s`))}turn.notice&&lines.push(...new Text(theme2.fg(turn.status==="error"?"error":"muted",turn.notice),0,0).render(width))}return lines}footer(state2,theme2){let parts=[],label=text2=>theme2.fg("muted",text2),value=text2=>theme2.fg("text",text2);if(this.maxOffset>0){let keys=[keyLabel("app.btw.scrollUp"),keyLabel("app.btw.scrollDown")].filter(Boolean).join("/");parts.push(value(keys)+label(" scroll ")+value(`${this.offset+1}\u2013${this.offset+this.heldHeight}/${this.maxOffset+this.heldHeight}`))}if(state2.phase==="ready"){let{conversation}=state2,{usage}=conversation,stats=[];usage.input>0&&stats.push(`\u2191${tokens(usage.input)}`),usage.output>0&&stats.push(`\u2193${tokens(usage.output)}`),usage.cacheRead>0&&stats.push(`R${tokens(usage.cacheRead)}`),usage.cacheWrite>0&&stats.push(`W${tokens(usage.cacheWrite)}`),conversation.latestCacheHitPercent!==void 0&&stats.push(`CH${conversation.latestCacheHitPercent.toFixed(1)}%`),usage.cost.total>0&&stats.push(`$${usage.cost.total.toFixed(3)}${state2.usesSubscription?" (sub)":""}`),stats.length&&parts.push(value(stats.join(" "))),conversation.blockedTools&&parts.push(value(String(conversation.blockedTools))+label(" tools blocked"));let turn=conversation.turns.at(-1);turn&&!conversation.busy&&(parts.push(value(`${(turn.elapsedMs/1e3).toFixed(1)}s`)),turn.firstAnswerMs!==void 0&&parts.push(label("first ")+value(`${(turn.firstAnswerMs/1e3).toFixed(1)}s`)))}return parts.join(label(" \xB7 "))}border(label,width,top,theme2){let text2=label?` ${truncateToWidth(label,Math.max(0,width-4))} `:"";return theme2.fg("borderAccent",top?"\u256D":"\u2570")+text2+theme2.fg("borderAccent",`${"\u2500".repeat(Math.max(0,width-visibleWidth(text2)-2))}${top?"\u256E":"\u256F"}`)}};var BtwController=class{async open(question2,ctx){let editorHost=ctx.ui.editorHost;if(!editorHost){ctx.ui.notify("/btw is available in interactive mode.","warning");return}this.close(),ctx.ui.setEditorText("");let conversation={ctx,state:{phase:"opening"}};this.current=conversation;try{let pendingSnapshot=ctx.getContextSnapshot();ctx.ui.setWidget("btw",tui=>{let panel=new BtwPanel(tui,()=>ctx.ui.theme,()=>conversation.state);return conversation.panel=panel,panel},{placement:"aboveEditor"}),conversation.unsubscribeKeys=editorHost.onInput(data=>this.handleKey(conversation,data));let snapshot=await pendingSnapshot;if(this.current!==conversation)return;let usesSubscription=ctx.modelRegistry.isUsingOAuth(snapshot.model);if(conversation.state={phase:"ready",capturedAt:snapshot.capturedAt,model:`${snapshot.model.provider}/${snapshot.model.id}`,usesSubscription,conversation:new BtwAgent(snapshot,ctx.modelRuntime,()=>{this.current===conversation&&conversation.panel?.changed()})},conversation.panel?.changed(),question2.trim()){let result2=this.submit(conversation,question2.trim());result2.editorText&&!ctx.ui.getEditorText()&&ctx.ui.setEditorText(result2.editorText)}}catch(error){if(this.current!==conversation)return;conversation.state.phase==="ready"&&conversation.state.conversation.dispose(),conversation.state={phase:"error",error:error instanceof Error?error.message:String(error)},conversation.panel?.changed(),question2&&!ctx.ui.getEditorText()&&ctx.ui.setEditorText(question2)}}intercept(event,ctx){let command=/^\/btw(?:\s+([\s\S]*))?$/.exec(event.text);if(command)return this.open(command[1]??"",ctx),{handled:!0};if(!(!this.current||event.kind!=="prompt"))return this.submit(this.current,event.text)}close(){let conversation=this.current;conversation&&(this.current=void 0,conversation.unsubscribeKeys?.(),conversation.panel?.dispose(),conversation.state.phase==="ready"&&conversation.state.conversation.dispose(),conversation.ctx.ui.setWidget("btw",void 0),conversation.ctx.ui.setEditorText(""))}submit(conversation,text2){let{state:state2}=conversation,result2=state2.phase==="ready"?state2.conversation.startQuestion(text2):{error:"BTW is not ready. Reopen /btw if context preparation failed."};return"error"in result2?(conversation.ctx.ui.notify(result2.error,"warning"),{handled:!0,editorText:text2}):(conversation.panel?.followTail(),result2.completion.catch(error=>{this.current===conversation&&(conversation.ctx.ui.notify(error instanceof Error?error.message:String(error),"error"),conversation.ctx.ui.getEditorText()||conversation.ctx.ui.setEditorText(text2))}),{handled:!0})}handleKey(conversation,data){if(this.current!==conversation)return;let keys=getKeybindings();if(keys.matches(data,"app.btw.close"))return this.close(),{consume:!0};if(keys.matches(data,"app.btw.cancel"))return conversation.state.phase==="ready"&&conversation.state.conversation.busy?conversation.state.conversation.cancel():this.close(),{consume:!0};if(keys.matches(data,"tui.editor.historyPrevious")||keys.matches(data,"tui.editor.historyNext"))return{consume:!0};let direction=keys.matches(data,"app.btw.scrollUp")?-1:keys.matches(data,"app.btw.scrollDown")?1:0,cursorUp=keys.matches(data,"tui.editor.cursorUp"),cursorDown=keys.matches(data,"tui.editor.cursorDown");if(conversation.ctx.ui.getEditorText()){if(cursorUp||cursorDown){let cursor=conversation.ctx.ui.editorHost?.getCursor();if(!cursor||cursorUp&&cursor.line===0&&cursor.col===0)return{consume:!0}}}else if(direction&&conversation.panel?.scroll(direction),direction||cursorUp||cursorDown)return{consume:!0}}};function btwExtension(pi){let controller=new BtwController,unsubscribeSubmit;pi.registerCommand("btw",{description:"Ask a temporary side question using the current context",handler:async(args,ctx)=>{await controller.open(args,ctx)}}),pi.on("session_start",(_event,ctx)=>{unsubscribeSubmit?.(),controller.close(),unsubscribeSubmit=ctx.ui.editorHost?.onSubmit(event=>controller.intercept(event,ctx))}),pi.on("session_tree",()=>controller.close()),pi.on("session_shutdown",()=>{unsubscribeSubmit?.(),unsubscribeSubmit=void 0,controller.close()})}var DEEPWIKI_TOOL_NAME="deepwiki",DEEPWIKI_LABEL="DeepWiki",DEEPWIKI_DESCRIPTION="Query DeepWiki's AI-generated documentation for indexed public GitHub repositories. structure lists a repo's wiki pages; contents reads one page, or the whole wiki truncated past ~120k chars when page is omitted; question answers a focused query about one repo, or across up to 10 repos for a comparison. Results are indexed public snapshots and may cite sources. A repository that is not indexed fails every action with a repository-not-found error.",DEEPWIKI_PROMPT_SNIPPET="Query AI-generated docs for public GitHub repos: architecture, APIs, implementation patterns",DEEPWIKI_PROMPT_GUIDELINES=["Run `deepwiki` action `structure` first for a repo; a repository-not-found error means it is not indexed, so do not retry that repo with `contents` or `question`.","Do not use `deepwiki` for local workspace files, private repos, exact current HEAD, or freshness-sensitive facts (releases, pricing, advisories); use local tools or current primary sources instead."];var PAGE_HEADER_RE=/^#\s+Page:\s+(.+)$/;function pageOffsets(text2){let re=new RegExp(PAGE_HEADER_RE.source,"gm"),chunks=[],match2=re.exec(text2);for(;match2!==null;)chunks.push({title:match2[1].trim(),start:match2.index}),match2=re.exec(text2);return chunks}function cutAtLineBoundary(text2,budget){if(text2.length<=budget)return text2;let slice=text2.slice(0,budget),lastNewline=slice.lastIndexOf(`
|
|
1984
|
+
`)),turn.thinking=thinking.slice(-2e3),question2.responseChars+JSON.stringify(message.content).length>512e3&&(turn.notice="Stopped at the BTW response size limit. You can ask a shorter follow-up.",this.agent.abort())}};function tokens(value){return value<1e3?String(value):value<1e4?`${(value/1e3).toFixed(1)}k`:value<1e6?`${Math.round(value/1e3)}k`:value<1e7?`${(value/1e6).toFixed(1)}M`:`${Math.round(value/1e6)}M`}var BtwPanel=class{constructor(tui,getTheme,getState){this.answers=new Map,this.follow=!0,this.offset=0,this.maxOffset=0,this.heldHeight=0,this.disposed=!1,this.tui=tui,this.getTheme=getTheme,this.getState=getState}invalidate(){this.answers.clear()}changed(){if(this.disposed)return;this.tui.requestRender();let state2=this.getState(),busy=state2.phase==="ready"&&state2.conversation.busy;busy&&!this.timer?(this.timer=setTimeout(()=>{this.timer=void 0,this.changed()},150),this.timer.unref?.()):!busy&&this.timer&&(clearTimeout(this.timer),this.timer=void 0)}followTail(){this.follow=!0,this.changed()}scroll(delta){return this.maxOffset===0?!1:(this.offset=Math.max(0,Math.min(this.maxOffset,this.offset+delta)),this.follow=this.offset===this.maxOffset,this.tui.requestRender(),!0)}dispose(){this.disposed=!0,this.timer&&clearTimeout(this.timer),this.timer=void 0,this.answers.clear()}render(width){if(this.disposed||width<1)return[];let state2=this.getState(),busy=state2.phase==="ready"&&state2.conversation.busy,theme2=this.getTheme(),innerWidth=Math.max(1,width-4),lines=this.body(state2,innerWidth,theme2),cap=Math.max(1,Math.floor(this.tui.terminal.rows/3)-2),needed=Math.min(cap,Math.max(1,lines.length));this.heldHeight=busy?Math.min(cap,Math.max(this.heldHeight,needed)):needed,this.maxOffset=Math.max(0,lines.length-this.heldHeight),this.offset=this.follow?this.maxOffset:Math.min(this.offset,this.maxOffset);let body2=lines.slice(this.offset,this.offset+this.heldHeight);for(;body2.length<this.heldHeight;)body2.push("");let close=keyLabel("app.btw.close"),cancel=keyLabel("app.btw.cancel"),title=[theme2.fg("accent",theme2.bold("BTW")),close&&theme2.fg("text",close)+theme2.fg("muted"," close"),busy&&cancel&&theme2.fg("text",cancel)+theme2.fg("muted"," stop")].filter(Boolean).join(theme2.fg("muted"," \xB7 ")),footer=this.footer(state2,theme2);return width<6?body2.map(line=>truncateToWidth(line,width)):[this.border(title,width,!0,theme2),...body2.map(line=>theme2.fg("borderAccent","\u2502 ")+truncateToWidth(line,innerWidth,"\u2026",!0)+theme2.fg("borderAccent"," \u2502")),this.border(footer,width,!1,theme2)]}body(state2,width,theme2){if(state2.phase==="opening")return[theme2.fg("muted","Capturing context\u2026")];if(state2.phase==="error")return new Text(theme2.fg("error",state2.error),0,0).render(width);if(!state2.conversation.turns.length)return[...new Text(theme2.fg("text","Ask a side question in the editor below."),0,0).render(width),...new Text(theme2.fg("muted",`Context at ${new Date(state2.capturedAt).toTimeString().slice(0,8)} \xB7 ${state2.model}`),0,0).render(width)];let lines=[];for(let[index3,turn]of state2.conversation.turns.entries()){if(index3>0&&lines.push(""),lines.push(...new Text(theme2.fg("accent",theme2.bold(`Q${index3+1}: `))+theme2.fg("text",turn.question),0,0).render(width)),turn.answer){let answer=this.answers.get(turn);answer?answer.text!==turn.answer&&(answer.text=turn.answer,answer.markdown.setText(turn.answer)):(answer={text:turn.answer,markdown:new Markdown(turn.answer,0,0,getMarkdownTheme(),{color:text2=>theme2.fg("text",text2)})},this.answers.set(turn,answer)),lines.push(...answer.markdown.render(width))}else turn.thinking&&(turn.status==="streaming"||turn.status==="cancelling")&&lines.push(...wrapTextWithAnsi(theme2.fg("muted",turn.thinking.trimEnd()),width).slice(-2));if(turn.status==="streaming"||turn.status==="cancelling"){let elapsed=((Date.now()-turn.startedAt)/1e3).toFixed(1);lines.push(theme2.fg("muted",`${turn.status==="cancelling"?"Stopping":"Answering"}\u2026 ${elapsed}s`))}turn.notice&&lines.push(...new Text(theme2.fg(turn.status==="error"?"error":"muted",turn.notice),0,0).render(width))}return lines}footer(state2,theme2){let parts=[],label=text2=>theme2.fg("muted",text2),value=text2=>theme2.fg("text",text2);if(this.maxOffset>0){let keys=[keyLabel("app.btw.scrollUp"),keyLabel("app.btw.scrollDown")].filter(Boolean).join("/");parts.push(value(keys)+label(" scroll ")+value(`${this.offset+1}\u2013${this.offset+this.heldHeight}/${this.maxOffset+this.heldHeight}`))}if(state2.phase==="ready"){let{conversation}=state2,{usage}=conversation,stats=[];usage.input>0&&stats.push(`\u2191${tokens(usage.input)}`),usage.output>0&&stats.push(`\u2193${tokens(usage.output)}`),usage.cacheRead>0&&stats.push(`R${tokens(usage.cacheRead)}`),usage.cacheWrite>0&&stats.push(`W${tokens(usage.cacheWrite)}`),conversation.latestCacheHitPercent!==void 0&&stats.push(`CH${conversation.latestCacheHitPercent.toFixed(1)}%`),usage.cost.total>0&&stats.push(`$${usage.cost.total.toFixed(3)}${state2.usesSubscription?" (sub)":""}`),stats.length&&parts.push(value(stats.join(" "))),conversation.blockedTools&&parts.push(value(String(conversation.blockedTools))+label(" tools blocked"));let turn=conversation.turns.at(-1);turn&&!conversation.busy&&(parts.push(value(`${(turn.elapsedMs/1e3).toFixed(1)}s`)),turn.firstAnswerMs!==void 0&&parts.push(label("first ")+value(`${(turn.firstAnswerMs/1e3).toFixed(1)}s`)))}return parts.join(label(" \xB7 "))}border(label,width,top,theme2){let text2=label?` ${truncateToWidth(label,Math.max(0,width-4))} `:"";return theme2.fg("borderAccent",top?"\u256D":"\u2570")+text2+theme2.fg("borderAccent",`${"\u2500".repeat(Math.max(0,width-visibleWidth(text2)-2))}${top?"\u256E":"\u256F"}`)}};var BtwController=class{async open(question2,ctx){let editorHost=ctx.ui.editorHost;if(!editorHost){ctx.ui.notify("/btw is available in interactive mode.","warning");return}this.close(),ctx.ui.setEditorText("");let conversation={ctx,state:{phase:"opening"}};this.current=conversation;try{let pendingSnapshot=ctx.getContextSnapshot();ctx.ui.setWidget("btw",tui=>{let panel=new BtwPanel(tui,()=>ctx.ui.theme,()=>conversation.state);return conversation.panel=panel,panel},{placement:"aboveEditor"}),conversation.unsubscribeKeys=editorHost.onInput(data=>this.handleKey(conversation,data));let snapshot=await pendingSnapshot;if(this.current!==conversation)return;let usesSubscription=ctx.modelRegistry.isUsingOAuth(snapshot.model);if(conversation.state={phase:"ready",capturedAt:snapshot.capturedAt,model:`${snapshot.model.provider}/${snapshot.model.id}`,usesSubscription,conversation:new BtwAgent(snapshot,ctx.modelRuntime,()=>{this.current===conversation&&conversation.panel?.changed()})},conversation.panel?.changed(),question2.trim()){let result2=this.submit(conversation,question2.trim());result2.editorText&&!ctx.ui.getEditorText()&&ctx.ui.setEditorText(result2.editorText)}}catch(error){if(this.current!==conversation)return;conversation.state.phase==="ready"&&conversation.state.conversation.dispose(),conversation.state={phase:"error",error:error instanceof Error?error.message:String(error)},conversation.panel?.changed(),question2&&!ctx.ui.getEditorText()&&ctx.ui.setEditorText(question2)}}intercept(event,ctx){let command=/^\/btw(?:\s+([\s\S]*))?$/.exec(event.text);if(command)return this.open(command[1]??"",ctx),{handled:!0};if(!(!this.current||event.kind!=="prompt"))return this.submit(this.current,event.text)}close(){let conversation=this.current;conversation&&(this.current=void 0,conversation.unsubscribeKeys?.(),conversation.panel?.dispose(),conversation.state.phase==="ready"&&conversation.state.conversation.dispose(),conversation.ctx.ui.setWidget("btw",void 0),conversation.ctx.ui.setEditorText(""))}submit(conversation,text2){let{state:state2}=conversation,result2=state2.phase==="ready"?state2.conversation.startQuestion(text2):{error:"BTW is not ready. Reopen /btw if context preparation failed."};return"error"in result2?(conversation.ctx.ui.notify(result2.error,"warning"),{handled:!0,editorText:text2}):(conversation.panel?.followTail(),result2.completion.catch(error=>{this.current===conversation&&(conversation.ctx.ui.notify(error instanceof Error?error.message:String(error),"error"),conversation.ctx.ui.getEditorText()||conversation.ctx.ui.setEditorText(text2))}),{handled:!0})}handleKey(conversation,data){if(this.current!==conversation)return;let keys=getKeybindings();if(keys.matches(data,"app.btw.close"))return this.close(),{consume:!0};if(keys.matches(data,"app.btw.cancel"))return conversation.state.phase==="ready"&&conversation.state.conversation.busy?conversation.state.conversation.cancel():this.close(),{consume:!0};if(keys.matches(data,"tui.editor.historyPrevious")||keys.matches(data,"tui.editor.historyNext"))return{consume:!0};let direction=keys.matches(data,"app.btw.scrollUp")?-1:keys.matches(data,"app.btw.scrollDown")?1:0,cursorUp=keys.matches(data,"tui.editor.cursorUp"),cursorDown=keys.matches(data,"tui.editor.cursorDown");if(conversation.ctx.ui.getEditorText()){if(cursorUp||cursorDown){let cursor=conversation.ctx.ui.editorHost?.getCursor();if(!cursor||cursorUp&&cursor.line===0&&cursor.col===0)return{consume:!0}}}else if(direction&&conversation.panel?.scroll(direction),direction||cursorUp||cursorDown)return{consume:!0}}};function btwExtension(pi){let controller=new BtwController,unsubscribeSubmit;pi.registerCommand("btw",{description:"Ask a temporary side question using the current context",handler:async(args,ctx)=>{await controller.open(args,ctx)}}),pi.on("session_start",(_event,ctx)=>{unsubscribeSubmit?.(),controller.close(),unsubscribeSubmit=ctx.ui.editorHost?.onSubmit(event=>controller.intercept(event,ctx))}),pi.on("session_tree",()=>controller.close()),pi.on("session_shutdown",()=>{unsubscribeSubmit?.(),unsubscribeSubmit=void 0,controller.close()})}function formatTokens2(count){return count>=1e6?`${(count/1e6).toFixed(1)}m`:count>=1e3?`${(count/1e3).toFixed(1)}k`:String(count)}var renderCachedCompactionEntry=(entry,_options,theme2)=>{let data=entry.data;if(!data)return;let promptTokens=data.input+data.cacheRead+data.cacheWrite,percentage=promptTokens>0?(100*data.cacheRead/promptTokens).toFixed(1):"0.0",title=`Cached compaction \xB7 ${data.reason==="manual"?"manual":"automatic"}`,stats=`Cache ${formatTokens2(data.cacheRead)}/${formatTokens2(promptTokens)} (${percentage}%) \xB7 output ${formatTokens2(data.output)} \xB7 ${(data.durationMs/1e3).toFixed(1)}s`;return new Text(`${theme2.fg("accent",title)}
|
|
1985
|
+
${theme2.fg("dim",stats)}`,1,0)};function sameMessage(candidate,projected){let serialized=JSON.stringify(candidate);return convertToLlm([projected]).some(message=>JSON.stringify(message)===serialized)}function messagePreview(message){let text2;if(message.role==="user"?text2=contentText(message.content):message.role==="assistant"&&(text2=message.content.flatMap(block=>block.type==="text"?[block.text]:block.type==="toolCall"?[`[tool call: ${block.name} ${JSON.stringify(block.arguments)}]`]:[]).join(`
|
|
1986
|
+
`)),text2=text2?.trim(),!!text2)return text2.length>400?`${text2.slice(0,400)}\u2026`:text2}function keptStart(entries,firstKeptEntryId,conversation){let projected=buildSessionProjection(entries).entries,start=projected.findIndex(entry=>entry.sourceEntry.id===firstKeptEntryId);if(start===-1)return;let at2=-1;for(let message of projected.slice(start).flatMap(entry=>entry.messages))if(at2=conversation.findLastIndex(candidate=>sameMessage(candidate,message)),at2!==-1)break;if(at2===-1)return;let previews=conversation.slice(at2).map(messagePreview),text2=previews[0];return text2?{text:text2,fromEnd:previews.filter(preview=>preview===text2).length,count:previews.length}:void 0}function summaryInstruction(kept,customInstructions){let repeated=kept.fromEnd>1?` Several retained messages begin with this text. The boundary is occurrence ${kept.fromEnd}, counting backward from the end of the conversation.`:"",toolCalls=kept.text.includes("[tool call: ")?" Tool calls are written as [tool call: name arguments].":"",focus=customInstructions?.trim()?`
|
|
1987
|
+
|
|
1988
|
+
Additional focus from the user:
|
|
1989
|
+
${customInstructions.trim()}`:"";return`Stop working on the current task. Do not call any tools.
|
|
1990
|
+
|
|
1991
|
+
Write a structured context checkpoint summary of the earlier part of this conversation. Another LLM will continue the task from your summary, followed by the last ${kept.count} messages, which will remain in context verbatim.
|
|
1992
|
+
|
|
1993
|
+
The retained messages begin with the message that starts with this text.${repeated}${toolCalls}
|
|
1994
|
+
|
|
1995
|
+
<kept-start>
|
|
1996
|
+
${kept.text}
|
|
1997
|
+
</kept-start>
|
|
1998
|
+
|
|
1999
|
+
Summarize only the messages before that boundary, as if the conversation had ended immediately before it. Work occurring at or after the boundary has not happened as far as this summary is concerned: do not list it as completed. If it was already planned, include it under Next Steps instead.
|
|
2000
|
+
|
|
2001
|
+
If the conversation contains an earlier checkpoint summary, fold its still-relevant facts into this summary and update its progress and next steps.
|
|
2002
|
+
|
|
2003
|
+
Use exactly this structure:
|
|
2004
|
+
|
|
2005
|
+
## Goal
|
|
2006
|
+
[What the user is trying to accomplish. Include multiple goals if applicable.]
|
|
2007
|
+
|
|
2008
|
+
## Constraints & Preferences
|
|
2009
|
+
- [Requirements, preferences, and explicit constraints from the user]
|
|
2010
|
+
- [Use "(none)" when appropriate]
|
|
2011
|
+
|
|
2012
|
+
## Progress
|
|
2013
|
+
### Done
|
|
2014
|
+
- [x] [Work completed before the boundary]
|
|
2015
|
+
|
|
2016
|
+
### In Progress
|
|
2017
|
+
- [ ] [Work underway at the boundary]
|
|
2018
|
+
|
|
2019
|
+
### Blocked
|
|
2020
|
+
- [Issues preventing progress, or "(none)"]
|
|
2021
|
+
|
|
2022
|
+
## Key Decisions
|
|
2023
|
+
- **[Decision]**: [Rationale]
|
|
2024
|
+
|
|
2025
|
+
## Next Steps
|
|
2026
|
+
1. [Ordered steps needed to continue]
|
|
2027
|
+
|
|
2028
|
+
## Critical Context
|
|
2029
|
+
- [Exact information needed to continue: file paths, symbols, commands, important tool results, error messages, and relevant technical details]
|
|
2030
|
+
|
|
2031
|
+
Be concise but preserve information required to continue without rereading the original conversation. Keep exact file paths, function names, commands, and error messages. Do not include file-operation lists; they will be added automatically. Return only the summary.${focus}`}function isPlainObject(value){return typeof value=="object"&&value!==null&&!Array.isArray(value)}function checkpointSummary(text2,fileOps,entries){let read=new Set(fileOps.read),modified=new Set([...fileOps.written,...fileOps.edited]),previousDetails=getLatestCompactionEntry(entries)?.details;if(isPlainObject(previousDetails)){let{readFiles,modifiedFiles}=previousDetails;if(Array.isArray(readFiles))for(let file of readFiles)typeof file=="string"&&read.add(file);if(Array.isArray(modifiedFiles))for(let file of modifiedFiles)typeof file=="string"&&modified.add(file)}let details={readFiles:[...read].filter(file=>!modified.has(file)).sort(),modifiedFiles:[...modified].sort()};return{summary:[text2.replace(/<(read-files|modified-files)>[\s\S]*?<\/\1>/g,"").trim(),details.readFiles.length>0?`<read-files>
|
|
2032
|
+
${details.readFiles.join(`
|
|
2033
|
+
`)}
|
|
2034
|
+
</read-files>`:"",details.modifiedFiles.length>0?`<modified-files>
|
|
2035
|
+
${details.modifiedFiles.join(`
|
|
2036
|
+
`)}
|
|
2037
|
+
</modified-files>`:""].filter(Boolean).join(`
|
|
2038
|
+
|
|
2039
|
+
`),details}}var CARD_TYPE="cached-compaction";function cachedCompaction(pi){let completed,pendingCard;pi.registerEntryRenderer(CARD_TYPE,renderCachedCompactionEntry),pi.on("session_before_compact",async(event,ctx)=>{if(completed=void 0,event.reason==="overflow")return;let startedAt=Date.now();try{let snapshot=await ctx.getContextSnapshot(),kept=keptStart(event.branchEntries,event.preparation.firstKeptEntryId,snapshot.messages);if(!kept)return;let response=await ctx.modelRegistry.streamSimple(snapshot.model,{messages:[...snapshot.messages,{role:"user",content:[{type:"text",text:summaryInstruction(kept,event.customInstructions)}],timestamp:Date.now()}]},{...snapshot.streamOptions,reasoning:snapshot.thinkingLevel==="off"?void 0:snapshot.thinkingLevel,signal:event.signal}).result();if(response.stopReason==="aborted")return{cancel:!0};if(response.stopReason!=="stop"||response.content.some(block=>block.type==="toolCall"))return;let text2=contentText(response.content).trim();if(!text2)return;let checkpoint=checkpointSummary(text2,event.preparation.fileOps,event.branchEntries);return completed={reason:event.reason,cacheRead:response.usage.cacheRead,input:response.usage.input,cacheWrite:response.usage.cacheWrite,output:response.usage.output,durationMs:Date.now()-startedAt},{compaction:{summary:checkpoint.summary,firstKeptEntryId:event.preparation.firstKeptEntryId,tokensBefore:event.preparation.tokensBefore,usage:response.usage,details:checkpoint.details}}}catch{return event.signal.aborted?{cancel:!0}:void 0}}),pi.on("session_compact",event=>{if(!event.fromExtension||!completed)return;let card=completed;completed=void 0,pendingCard=card,setTimeout(()=>{if(pendingCard===card){pendingCard=void 0;try{pi.appendEntry(CARD_TYPE,card)}catch{}}},0)}),pi.on("session_compact_failed",()=>{completed=void 0}),pi.on("session_shutdown",()=>{completed=void 0,pendingCard=void 0})}var DEEPWIKI_TOOL_NAME="deepwiki",DEEPWIKI_LABEL="DeepWiki",DEEPWIKI_DESCRIPTION="Query DeepWiki's AI-generated documentation for indexed public GitHub repositories. structure lists a repo's wiki pages; contents reads one page, or the whole wiki truncated past ~120k chars when page is omitted; question answers a focused query about one repo, or across up to 10 repos for a comparison. Results are indexed public snapshots and may cite sources. A repository that is not indexed fails every action with a repository-not-found error.",DEEPWIKI_PROMPT_SNIPPET="Query AI-generated docs for public GitHub repos: architecture, APIs, implementation patterns",DEEPWIKI_PROMPT_GUIDELINES=["Run `deepwiki` action `structure` first for a repo; a repository-not-found error means it is not indexed, so do not retry that repo with `contents` or `question`.","Do not use `deepwiki` for local workspace files, private repos, exact current HEAD, or freshness-sensitive facts (releases, pricing, advisories); use local tools or current primary sources instead."];var PAGE_HEADER_RE=/^#\s+Page:\s+(.+)$/;function pageOffsets(text2){let re=new RegExp(PAGE_HEADER_RE.source,"gm"),chunks=[],match2=re.exec(text2);for(;match2!==null;)chunks.push({title:match2[1].trim(),start:match2.index}),match2=re.exec(text2);return chunks}function cutAtLineBoundary(text2,budget){if(text2.length<=budget)return text2;let slice=text2.slice(0,budget),lastNewline=slice.lastIndexOf(`
|
|
1979
2040
|
`);return lastNewline>=Math.floor(budget*.4)?slice.slice(0,lastNewline):slice}function buildNotice(opts){let lines=[`[DeepWiki contents truncated \u2014 ${opts.totalPages>0?`showing ${opts.shownPages} of ${opts.totalPages} pages`:"showing the beginning"} (${opts.keptChars} of ${opts.fullChars} chars).`];if(opts.partialLastPage&&lines.push("The last shown page is itself truncated."),opts.omittedTitles.length>0){let shown=opts.omittedTitles.slice(0,20).join("; "),more=opts.omittedTitles.length-20;lines.push(`Omitted pages: ${shown}${more>0?` \u2026 +${more} more`:""}.`),lines.push('Read an omitted page with {action: "contents", page: "<title>"}, or use action "question" for a targeted answer.]')}else lines.push('For the missing remainder, use action "question" with a focused question.]');return lines.join(`
|
|
1980
2041
|
`)}function truncateContentsByPages(text2,budget=12e4){let chunks=pageOffsets(text2),totalPages=chunks.length;if(text2.length<=budget)return{text:text2,truncated:!1,totalPages,shownPages:totalPages,truncatedChars:0};let kept,shownPages,partialLastPage=!1;if(totalPages===0)kept=cutAtLineBoundary(text2,budget),shownPages=0;else{let preambleEnd=chunks[0].start;shownPages=0;let end=preambleEnd;for(let i=0;i<chunks.length;i++){let pageEnd=i+1<chunks.length?chunks[i+1].start:text2.length;if(pageEnd>budget)break;end=pageEnd,shownPages++}shownPages===0?(kept=cutAtLineBoundary(text2,budget),shownPages=1,partialLastPage=!0):kept=text2.slice(0,end)}let omittedTitles=chunks.slice(shownPages).map(chunk=>chunk.title),notice=buildNotice({shownPages,totalPages,keptChars:kept.length,fullChars:text2.length,omittedTitles,partialLastPage});return{text:`${kept}
|
|
1981
2042
|
|
|
@@ -2006,11 +2067,11 @@ ${approval} at:
|
|
|
2006
2067
|
https://huggingface.co/${details.id}
|
|
2007
2068
|
|
|
2008
2069
|
The llama.cpp server needs HF_TOKEN with access.`,["Continue","Back"])!=="Continue")return}let quantization=parsed.quantization;if(!quantization&&details.quantizations.length>0){let options=details.quantizations.map(entry=>{let detail=[entry.size===void 0?void 0:formatBytes(entry.size),entry.name==="Q4_K_M"?"recommended":void 0].filter(value=>!!value).join(" \xB7 ");return detail?`${entry.name} \xB7 ${detail}`:entry.name}),choice=await ui.select(`Select quantization
|
|
2009
|
-
${details.id}`,options);if(!choice||(quantization=details.quantizations[options.indexOf(choice)]?.name,!quantization))return}let model=quantization?`${details.id}:${quantization}`:details.id,result2=await runWithProgress(ui,{title:"Downloading model",model,initialMessage:"Starting\u2026",cancelTitle:"Stop download?",cancelMessage:model,run:(signal,update)=>client.downloadAndWait(model,update,signal),cancel:()=>client.unload(model)});result2.cancelled||(await syncCatalog(ctx,client,result2.value),ctx.ui.notify(`Downloaded ${model}`))};pi.registerCommand("llama",{description:"Manage llama.cpp router models",handler:async(_args,ctx)=>{if(ctx.mode!=="tui"){ctx.ui.notify("/llama is available in interactive mode","warning");return}let client=await configuredClient(ctx);client&&await showLlamaUi(ctx,async ui=>{let readCatalog2=async()=>{for(;;)try{return await syncCatalog(ctx,client)}catch(error){if(await ui.connectionError(client.serverUrl,connectionErrorMessage(error))==="close")return}},catalog=await readCatalog2();if(catalog)for(;;){let action=await ui.showModels(client.serverUrl,catalog);if(action.type==="close")return;let actionError;try{action.type==="download"?await downloadModel(ctx,ui,client):modelIsLoaded(action.model)?await unloadModel(ctx,ui,client,action.model):action.model.status.value==="unloaded"?await loadModel(ctx,ui,client,catalog,action.model):ctx.ui.notify(`${action.model.id} is ${action.model.status.value}`,"warning")}catch(error){actionError=error}let refreshed=await readCatalog2();if(!refreshed)return;catalog=refreshed,actionError&&!isConnectionError(actionError)&&ctx.ui.notify(actionError instanceof Error?actionError.message:String(actionError),"error")}})}})}var COMMAND_NAME="provider",COMMAND_DESCRIPTION="Manage models.json providers: connection, API type, and models",NO_UI_WARNING="/provider requires interactive TUI mode.",NO_MODELS_FILE_WARNING="models.json is disabled for this runtime (custom SDK configuration), so /provider is unavailable.",API_TYPES=["openai-responses","openai-completions","anthropic-messages","google-generative-ai","azure-openai-responses","openai-codex-responses","mistral-conversations","google-vertex","bedrock-converse-stream","pi-messages"],INPUT_TYPES=["text","image"],THINKING_LEVELS4=["off","minimal","low","medium","high","xhigh","max"],PROBE_LIMITS={timeoutMs:1e4,maxBodyBytes:4194304,maxErrorBytes:4096,maxErrorChars:400,maxModels:2e3,maxPages:5},MAX_CANDIDATES=8,REFRESH_TIMEOUT_MS=15e3;function formatError2(error){return error instanceof Error?error.message:String(error)}function plural(count,word){return count===1?word:word.endsWith("y")?`${word.slice(0,-1)}ies`:`${word}s`}function truncate3(value,max){return value.length<=max?value:`${value.slice(0,Math.max(0,max-1))}\u2026`}function maskApiKey(value){return!value||value.startsWith("$")||value.startsWith("!")?value:value.length<=8?"\u2022\u2022\u2022\u2022\u2022\u2022":`\u2022\u2022\u2022\u2022\u2022\u2022${value.slice(-4)}`}var import_proper_lockfile5=__toESM(require_proper_lockfile(),1);import{randomUUID as randomUUID9}from"node:crypto";import{mkdir,readFile as readFile6,realpath as realpath2,rename,rm,writeFile as writeFile3}from"node:fs/promises";import{dirname as dirname25,join as join45}from"node:path";var indexCache;function builtinCatalogIndex(){if(indexCache)return indexCache;let entries=[];for(let providerId of getBuiltinProviders())for(let model of getBuiltinModels(providerId))entries.push({providerId,model});return indexCache=entries,entries}function isBuiltinProviderId(providerId){return getBuiltinProviders().includes(providerId)}function builtinDefaults(providerId,modelId,api){if(!isBuiltinProviderId(providerId))return{};let models=getBuiltinModels(providerId);if(models.length===0)return{};let found=(modelId?models.find(model=>model.id===modelId):void 0)??(api?models.find(model=>model.api===api):void 0)??models.find(model=>model.api==="openai-completions")??models[0];return{api:found.api,baseUrl:found.baseUrl}}function normalizeId(id){return(id.includes("/")?id.slice(id.lastIndexOf("/")+1):id).toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")}function sortTier(matches,preferredApi){return matches.sort((a,b2)=>{if(preferredApi){let aPreferred=a.entry.model.api===preferredApi?0:1,bPreferred=b2.entry.model.api===preferredApi?0:1;if(aPreferred!==bPreferred)return aPreferred-bPreferred}return a.entry.model.id.localeCompare(b2.entry.model.id)})}function matchBuiltinModels(query,preferredApi,max=MAX_CANDIDATES){let trimmed=query.trim();if(!trimmed)return[];let index3=builtinCatalogIndex(),normalizedQuery=normalizeId(trimmed),exact=[],normalized=[],consumed=new Set;for(let entry of index3)entry.model.id===trimmed?(exact.push({entry,tier:"exact"}),consumed.add(entry)):normalizeId(entry.model.id)===normalizedQuery&&(normalized.push({entry,tier:"normalized"}),consumed.add(entry));let remaining=sortTier(index3.filter(entry=>!consumed.has(entry)).map(entry=>({entry,tier:"fuzzy"})),preferredApi),fuzzy=fuzzyFilter(remaining,trimmed,({entry})=>`${entry.model.id} ${entry.model.name} ${entry.providerId}`);return[...sortTier(exact,preferredApi),...sortTier(normalized,preferredApi),...fuzzy].slice(0,max)}var DEFAULT_CONTEXT_WINDOW=128e3,DEFAULT_MAX_TOKENS=16384;function formatCostRates(cost){return`$${cost.input} / $${cost.output} in/out (cache $${cost.cacheRead} / $${cost.cacheWrite})`}function computeFieldChanges(current,reference,effectiveApi){let changes=[],unset=key=>current[key]===void 0;changes.push({field:"name",patches:[{path:["name"],value:reference.name}],checked:unset("name")&&reference.name!==reference.id,applicable:!0,currentText:current.name??`not set (falls back to id${current.id?` "${current.id}"`:""})`,referenceText:reference.name}),changes.push({field:"reasoning",patches:[{path:["reasoning"],value:reference.reasoning}],checked:unset("reasoning")&&reference.reasoning===!0,applicable:!0,currentText:current.reasoning===void 0?"false (default)":String(current.reasoning),referenceText:String(reference.reasoning)}),changes.push({field:"input",patches:[{path:["input"],value:reference.input}],checked:unset("input"),applicable:!0,currentText:current.input?current.input.join(", "):"text (default)",referenceText:reference.input.join(", ")}),changes.push({field:"contextWindow",patches:[{path:["contextWindow"],value:reference.contextWindow}],checked:unset("contextWindow"),applicable:!0,currentText:current.contextWindow===void 0?`${DEFAULT_CONTEXT_WINDOW} (default)`:String(current.contextWindow),referenceText:String(reference.contextWindow)}),changes.push({field:"maxTokens",patches:[{path:["maxTokens"],value:reference.maxTokens}],checked:unset("maxTokens"),applicable:!0,currentText:current.maxTokens===void 0?`${DEFAULT_MAX_TOKENS} (default)`:String(current.maxTokens),referenceText:String(reference.maxTokens)});let sameApi=effectiveApi!==void 0&&reference.api===effectiveApi;if(reference.thinkingLevelMap&&Object.keys(reference.thinkingLevelMap).length>0){let details=Object.entries(reference.thinkingLevelMap).map(([level,target])=>`${level}: ${target===null?"null (hidden)":target}`);changes.push({field:"thinkingLevelMap",patches:sameApi?Object.entries(reference.thinkingLevelMap).map(([level,value])=>({path:["thinkingLevelMap",level],value})):[],checked:!1,applicable:sameApi,currentText:current.thinkingLevelMap?`${Object.keys(current.thinkingLevelMap).length} ${plural(Object.keys(current.thinkingLevelMap).length,"mapping")}`:"not set",referenceText:`${details.length} ${plural(details.length,"mapping")}`,referenceDetails:details})}if(reference.compat&&Object.keys(reference.compat).length>0){let patches=[];if(sameApi)for(let[key,value]of Object.entries(reference.compat))if(["chatTemplateKwargs","chatTemplateArgs","openRouterRouting","vercelGatewayRouting"].includes(key)&&value!==null&&typeof value=="object"&&!Array.isArray(value))for(let[entry,item]of Object.entries(value))patches.push({path:["compat",key,entry],value:item});else patches.push({path:["compat",key],value});let details=Object.entries(reference.compat).map(([key,value])=>`${key}: ${JSON.stringify(value)}`);changes.push({field:"compat",patches,checked:!1,applicable:sameApi,currentText:current.compat?`${Object.keys(current.compat).length} ${plural(Object.keys(current.compat).length,"entry")}`:"not set",referenceText:`${details.length} ${plural(details.length,"entry")}`,referenceDetails:details})}if(reference.cost){let{input:input2,output,cacheRead,cacheWrite}=reference.cost,rates={input:input2,output,cacheRead,cacheWrite};changes.push({field:"cost",patches:current.cost?Object.entries(rates).map(([rate,value])=>({path:["cost",rate],value})):[{path:["cost"],value:rates}],checked:!1,applicable:!0,currentText:current.cost?formatCostRates(current.cost):"all 0 (default)",referenceText:formatCostRates(reference.cost),referenceDetails:[`input: $${reference.cost.input} / M tokens`,`output: $${reference.cost.output} / M tokens`,`cacheRead: $${reference.cost.cacheRead} / M tokens`,`cacheWrite: $${reference.cost.cacheWrite} / M tokens`],referenceHasTiers:Array.isArray(reference.cost.tiers)&&reference.cost.tiers.length>0})}return changes}function hasProviderSettings(provider){return!!(provider&&(provider.baseUrl||provider.apiKey||provider.headers||provider.compat||provider.oauth||provider.authHeader!==void 0||provider.models?.length||Object.keys(provider.modelOverrides??{}).length))}function effectiveModelSettings(providerId,provider,model={}){let fallback=builtinDefaults(providerId,model.id,model.api??provider?.api);return{api:model.api??provider?.api??fallback.api,baseUrl:model.baseUrl??provider?.baseUrl??fallback.baseUrl}}var DELETE=Symbol("provider-store-delete");function setPath(root,path14,value){let current=root;for(let segment2 of path14.slice(0,-1)){let next=Object.hasOwn(current,segment2)?current[segment2]:void 0;if(typeof next=="object"&&next!==null&&!Array.isArray(next))current=next;else{let created={};Object.defineProperty(current,segment2,{value:created,writable:!0,enumerable:!0,configurable:!0}),current=created}}let leaf=path14[path14.length-1];value===DELETE?delete current[leaf]:Object.defineProperty(current,leaf,{value:structuredClone(value),writable:!0,enumerable:!0,configurable:!0})}function isPlainObject(value){return typeof value=="object"&&value!==null&&!Array.isArray(value)}function jsonEquals(a,b2){if(a===b2)return!0;if(Array.isArray(a)&&Array.isArray(b2))return a.length===b2.length&&a.every((entry,index3)=>jsonEquals(entry,b2[index3]));if(isPlainObject(a)&&isPlainObject(b2)){let aKeys=Object.keys(a).sort(),bKeys=Object.keys(b2).sort();return aKeys.length===bKeys.length&&aKeys.every((key,index3)=>key===bKeys[index3]&&jsonEquals(a[key],b2[key]))}return!1}function cloneValue(value){return value===DELETE?value:structuredClone(value)}async function readDocument(path14){let rawText;try{rawText=await readFile6(path14,"utf8")}catch(error){if(error.code==="ENOENT")return{exists:!1,doc:{providers:{}}};throw error}let parsed=JSON.parse(stripJsonComments(stripBom(rawText)));if(!isPlainObject(parsed))throw new Error("models.json root must be a JSON object.");let doc=parsed;if(!isPlainObject(doc.providers))throw new Error('models.json "providers" must be an object.');return{exists:!0,doc,rawText}}var ModelsJsonStore=class _ModelsJsonStore{constructor(path14,baseline){this.ops=[],this.seq=0,this.backedUp=!1,this.batching=!1,this.saveChain=Promise.resolve(),this.drafts=new Set,this.lastSaveResult={kind:"clean"},this.path=path14,this.baseline=baseline,this.view=structuredClone(baseline)}static async load(path14){let normalized=normalizePath(path14),disk;try{normalized=await realpath2(normalized).catch(error=>{if(error.code==="ENOENT")return normalized;throw error}),disk=await readDocument(normalized)}catch(error){return{ok:!1,error:`Failed to parse models.json: ${formatError2(error)}
|
|
2070
|
+
${details.id}`,options);if(!choice||(quantization=details.quantizations[options.indexOf(choice)]?.name,!quantization))return}let model=quantization?`${details.id}:${quantization}`:details.id,result2=await runWithProgress(ui,{title:"Downloading model",model,initialMessage:"Starting\u2026",cancelTitle:"Stop download?",cancelMessage:model,run:(signal,update)=>client.downloadAndWait(model,update,signal),cancel:()=>client.unload(model)});result2.cancelled||(await syncCatalog(ctx,client,result2.value),ctx.ui.notify(`Downloaded ${model}`))};pi.registerCommand("llama",{description:"Manage llama.cpp router models",handler:async(_args,ctx)=>{if(ctx.mode!=="tui"){ctx.ui.notify("/llama is available in interactive mode","warning");return}let client=await configuredClient(ctx);client&&await showLlamaUi(ctx,async ui=>{let readCatalog2=async()=>{for(;;)try{return await syncCatalog(ctx,client)}catch(error){if(await ui.connectionError(client.serverUrl,connectionErrorMessage(error))==="close")return}},catalog=await readCatalog2();if(catalog)for(;;){let action=await ui.showModels(client.serverUrl,catalog);if(action.type==="close")return;let actionError;try{action.type==="download"?await downloadModel(ctx,ui,client):modelIsLoaded(action.model)?await unloadModel(ctx,ui,client,action.model):action.model.status.value==="unloaded"?await loadModel(ctx,ui,client,catalog,action.model):ctx.ui.notify(`${action.model.id} is ${action.model.status.value}`,"warning")}catch(error){actionError=error}let refreshed=await readCatalog2();if(!refreshed)return;catalog=refreshed,actionError&&!isConnectionError(actionError)&&ctx.ui.notify(actionError instanceof Error?actionError.message:String(actionError),"error")}})}})}var COMMAND_NAME="provider",COMMAND_DESCRIPTION="Manage models.json providers: connection, API type, and models",NO_UI_WARNING="/provider requires interactive TUI mode.",NO_MODELS_FILE_WARNING="models.json is disabled for this runtime (custom SDK configuration), so /provider is unavailable.",API_TYPES=["openai-responses","openai-completions","anthropic-messages","google-generative-ai","azure-openai-responses","openai-codex-responses","mistral-conversations","google-vertex","bedrock-converse-stream","pi-messages"],INPUT_TYPES=["text","image"],THINKING_LEVELS4=["off","minimal","low","medium","high","xhigh","max"],PROBE_LIMITS={timeoutMs:1e4,maxBodyBytes:4194304,maxErrorBytes:4096,maxErrorChars:400,maxModels:2e3,maxPages:5},MAX_CANDIDATES=8,REFRESH_TIMEOUT_MS=15e3;function formatError2(error){return error instanceof Error?error.message:String(error)}function plural(count,word){return count===1?word:word.endsWith("y")?`${word.slice(0,-1)}ies`:`${word}s`}function truncate3(value,max){return value.length<=max?value:`${value.slice(0,Math.max(0,max-1))}\u2026`}function maskApiKey(value){return!value||value.startsWith("$")||value.startsWith("!")?value:value.length<=8?"\u2022\u2022\u2022\u2022\u2022\u2022":`\u2022\u2022\u2022\u2022\u2022\u2022${value.slice(-4)}`}var import_proper_lockfile5=__toESM(require_proper_lockfile(),1);import{randomUUID as randomUUID9}from"node:crypto";import{mkdir,readFile as readFile6,realpath as realpath2,rename,rm,writeFile as writeFile3}from"node:fs/promises";import{dirname as dirname25,join as join45}from"node:path";var indexCache;function builtinCatalogIndex(){if(indexCache)return indexCache;let entries=[];for(let providerId of getBuiltinProviders())for(let model of getBuiltinModels(providerId))entries.push({providerId,model});return indexCache=entries,entries}function isBuiltinProviderId(providerId){return getBuiltinProviders().includes(providerId)}function builtinDefaults(providerId,modelId,api){if(!isBuiltinProviderId(providerId))return{};let models=getBuiltinModels(providerId);if(models.length===0)return{};let found=(modelId?models.find(model=>model.id===modelId):void 0)??(api?models.find(model=>model.api===api):void 0)??models.find(model=>model.api==="openai-completions")??models[0];return{api:found.api,baseUrl:found.baseUrl}}function normalizeId(id){return(id.includes("/")?id.slice(id.lastIndexOf("/")+1):id).toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")}function sortTier(matches,preferredApi){return matches.sort((a,b2)=>{if(preferredApi){let aPreferred=a.entry.model.api===preferredApi?0:1,bPreferred=b2.entry.model.api===preferredApi?0:1;if(aPreferred!==bPreferred)return aPreferred-bPreferred}return a.entry.model.id.localeCompare(b2.entry.model.id)})}function matchBuiltinModels(query,preferredApi,max=MAX_CANDIDATES){let trimmed=query.trim();if(!trimmed)return[];let index3=builtinCatalogIndex(),normalizedQuery=normalizeId(trimmed),exact=[],normalized=[],consumed=new Set;for(let entry of index3)entry.model.id===trimmed?(exact.push({entry,tier:"exact"}),consumed.add(entry)):normalizeId(entry.model.id)===normalizedQuery&&(normalized.push({entry,tier:"normalized"}),consumed.add(entry));let remaining=sortTier(index3.filter(entry=>!consumed.has(entry)).map(entry=>({entry,tier:"fuzzy"})),preferredApi),fuzzy=fuzzyFilter(remaining,trimmed,({entry})=>`${entry.model.id} ${entry.model.name} ${entry.providerId}`);return[...sortTier(exact,preferredApi),...sortTier(normalized,preferredApi),...fuzzy].slice(0,max)}var DEFAULT_CONTEXT_WINDOW=128e3,DEFAULT_MAX_TOKENS=16384;function formatCostRates(cost){return`$${cost.input} / $${cost.output} in/out (cache $${cost.cacheRead} / $${cost.cacheWrite})`}function computeFieldChanges(current,reference,effectiveApi){let changes=[],unset=key=>current[key]===void 0;changes.push({field:"name",patches:[{path:["name"],value:reference.name}],checked:unset("name")&&reference.name!==reference.id,applicable:!0,currentText:current.name??`not set (falls back to id${current.id?` "${current.id}"`:""})`,referenceText:reference.name}),changes.push({field:"reasoning",patches:[{path:["reasoning"],value:reference.reasoning}],checked:unset("reasoning")&&reference.reasoning===!0,applicable:!0,currentText:current.reasoning===void 0?"false (default)":String(current.reasoning),referenceText:String(reference.reasoning)}),changes.push({field:"input",patches:[{path:["input"],value:reference.input}],checked:unset("input"),applicable:!0,currentText:current.input?current.input.join(", "):"text (default)",referenceText:reference.input.join(", ")}),changes.push({field:"contextWindow",patches:[{path:["contextWindow"],value:reference.contextWindow}],checked:unset("contextWindow"),applicable:!0,currentText:current.contextWindow===void 0?`${DEFAULT_CONTEXT_WINDOW} (default)`:String(current.contextWindow),referenceText:String(reference.contextWindow)}),changes.push({field:"maxTokens",patches:[{path:["maxTokens"],value:reference.maxTokens}],checked:unset("maxTokens"),applicable:!0,currentText:current.maxTokens===void 0?`${DEFAULT_MAX_TOKENS} (default)`:String(current.maxTokens),referenceText:String(reference.maxTokens)});let sameApi=effectiveApi!==void 0&&reference.api===effectiveApi;if(reference.thinkingLevelMap&&Object.keys(reference.thinkingLevelMap).length>0){let details=Object.entries(reference.thinkingLevelMap).map(([level,target])=>`${level}: ${target===null?"null (hidden)":target}`);changes.push({field:"thinkingLevelMap",patches:sameApi?Object.entries(reference.thinkingLevelMap).map(([level,value])=>({path:["thinkingLevelMap",level],value})):[],checked:!1,applicable:sameApi,currentText:current.thinkingLevelMap?`${Object.keys(current.thinkingLevelMap).length} ${plural(Object.keys(current.thinkingLevelMap).length,"mapping")}`:"not set",referenceText:`${details.length} ${plural(details.length,"mapping")}`,referenceDetails:details})}if(reference.compat&&Object.keys(reference.compat).length>0){let patches=[];if(sameApi)for(let[key,value]of Object.entries(reference.compat))if(["chatTemplateKwargs","chatTemplateArgs","openRouterRouting","vercelGatewayRouting"].includes(key)&&value!==null&&typeof value=="object"&&!Array.isArray(value))for(let[entry,item]of Object.entries(value))patches.push({path:["compat",key,entry],value:item});else patches.push({path:["compat",key],value});let details=Object.entries(reference.compat).map(([key,value])=>`${key}: ${JSON.stringify(value)}`);changes.push({field:"compat",patches,checked:!1,applicable:sameApi,currentText:current.compat?`${Object.keys(current.compat).length} ${plural(Object.keys(current.compat).length,"entry")}`:"not set",referenceText:`${details.length} ${plural(details.length,"entry")}`,referenceDetails:details})}if(reference.cost){let{input:input2,output,cacheRead,cacheWrite}=reference.cost,rates={input:input2,output,cacheRead,cacheWrite};changes.push({field:"cost",patches:current.cost?Object.entries(rates).map(([rate,value])=>({path:["cost",rate],value})):[{path:["cost"],value:rates}],checked:!1,applicable:!0,currentText:current.cost?formatCostRates(current.cost):"all 0 (default)",referenceText:formatCostRates(reference.cost),referenceDetails:[`input: $${reference.cost.input} / M tokens`,`output: $${reference.cost.output} / M tokens`,`cacheRead: $${reference.cost.cacheRead} / M tokens`,`cacheWrite: $${reference.cost.cacheWrite} / M tokens`],referenceHasTiers:Array.isArray(reference.cost.tiers)&&reference.cost.tiers.length>0})}return changes}function hasProviderSettings(provider){return!!(provider&&(provider.baseUrl||provider.apiKey||provider.headers||provider.compat||provider.oauth||provider.authHeader!==void 0||provider.models?.length||Object.keys(provider.modelOverrides??{}).length))}function effectiveModelSettings(providerId,provider,model={}){let fallback=builtinDefaults(providerId,model.id,model.api??provider?.api);return{api:model.api??provider?.api??fallback.api,baseUrl:model.baseUrl??provider?.baseUrl??fallback.baseUrl}}var DELETE=Symbol("provider-store-delete");function setPath(root,path14,value){let current=root;for(let segment2 of path14.slice(0,-1)){let next=Object.hasOwn(current,segment2)?current[segment2]:void 0;if(typeof next=="object"&&next!==null&&!Array.isArray(next))current=next;else{let created={};Object.defineProperty(current,segment2,{value:created,writable:!0,enumerable:!0,configurable:!0}),current=created}}let leaf=path14[path14.length-1];value===DELETE?delete current[leaf]:Object.defineProperty(current,leaf,{value:structuredClone(value),writable:!0,enumerable:!0,configurable:!0})}function isPlainObject2(value){return typeof value=="object"&&value!==null&&!Array.isArray(value)}function jsonEquals(a,b2){if(a===b2)return!0;if(Array.isArray(a)&&Array.isArray(b2))return a.length===b2.length&&a.every((entry,index3)=>jsonEquals(entry,b2[index3]));if(isPlainObject2(a)&&isPlainObject2(b2)){let aKeys=Object.keys(a).sort(),bKeys=Object.keys(b2).sort();return aKeys.length===bKeys.length&&aKeys.every((key,index3)=>key===bKeys[index3]&&jsonEquals(a[key],b2[key]))}return!1}function cloneValue(value){return value===DELETE?value:structuredClone(value)}async function readDocument(path14){let rawText;try{rawText=await readFile6(path14,"utf8")}catch(error){if(error.code==="ENOENT")return{exists:!1,doc:{providers:{}}};throw error}let parsed=JSON.parse(stripJsonComments(stripBom(rawText)));if(!isPlainObject2(parsed))throw new Error("models.json root must be a JSON object.");let doc=parsed;if(!isPlainObject2(doc.providers))throw new Error('models.json "providers" must be an object.');return{exists:!0,doc,rawText}}var ModelsJsonStore=class _ModelsJsonStore{constructor(path14,baseline){this.ops=[],this.seq=0,this.backedUp=!1,this.batching=!1,this.saveChain=Promise.resolve(),this.drafts=new Set,this.lastSaveResult={kind:"clean"},this.path=path14,this.baseline=baseline,this.view=structuredClone(baseline)}static async load(path14){let normalized=normalizePath(path14),disk;try{normalized=await realpath2(normalized).catch(error=>{if(error.code==="ENOENT")return normalized;throw error}),disk=await readDocument(normalized)}catch(error){return{ok:!1,error:`Failed to parse models.json: ${formatError2(error)}
|
|
2010
2071
|
|
|
2011
2072
|
File: ${normalized}`}}if(disk.exists){let validationError=(await ModelConfig.load(normalized)).getError();if(validationError)return{ok:!1,error:validationError}}return{ok:!0,store:new _ModelsJsonStore(normalized,disk.doc)}}getDoc(){return this.view}getProviderIds(){return[...new Set([...Object.keys(this.view.providers),...this.ops.map(op=>op.providerId)])]}getProvider(providerId){return Object.hasOwn(this.view.providers,providerId)?this.view.providers[providerId]:void 0}ensureProviderView(providerId){Object.hasOwn(this.view.providers,providerId)||(this.drafts.add(providerId),this.recomputeView())}isDraftProvider(providerId){return!Object.hasOwn(this.baseline.providers,providerId)&&Object.hasOwn(this.view.providers,providerId)}getModels(providerId){let provider=this.getProvider(providerId);return Array.isArray(provider?.models)?provider.models:[]}getModel(providerId,modelId){return this.getModels(providerId).find(model=>model.id===modelId)}get pendingCount(){return this.ops.length}getPendingError(providerId){let pending=this.ops.filter(op=>providerId===void 0||op.providerId===providerId);if(pending.length!==0)return this.lastSaveResult.kind==="error"||this.lastSaveResult.kind==="invalid"?this.lastSaveResult.error:`${pending.length} change(s) are not saved; retry or discard before continuing.`}retrySave(){this.ops.length>0&&this.scheduleSave()}discardPending(){this.ops=[],this.drafts.clear(),this.recomputeView()}enqueue(op){this.ops.push(op),this.recomputeView(),this.scheduleSave()}nextSeq(){return++this.seq}setProviderField(providerId,path14,value){this.enqueue({kind:"set",seq:this.nextSeq(),providerId,path:path14,value:cloneValue(value),createProvider:!Object.hasOwn(this.baseline.providers,providerId)})}setModelField(providerId,modelId,path14,value){this.enqueue({kind:"set",seq:this.nextSeq(),providerId,modelId,path:path14,value:cloneValue(value),createProvider:!Object.hasOwn(this.baseline.providers,providerId)})}addModel(providerId,model){this.enqueue({kind:"addModel",seq:this.nextSeq(),providerId,model:structuredClone(model),createProvider:!Object.hasOwn(this.baseline.providers,providerId)})}removeModel(providerId,modelId){this.enqueue({kind:"removeModel",seq:this.nextSeq(),providerId,modelId})}async renameModel(providerId,oldId,newId){await this.flush();let pendingError=this.getPendingError(providerId);if(pendingError)return pendingError;let before=this.getModel(providerId,oldId);if(!before)return"The model no longer exists.";let seq=this.nextSeq();if(this.enqueue({kind:"renameModel",seq,providerId,oldId,newId}),await this.flush(),this.ops.some(op=>op.seq===seq))return this.ops=this.ops.filter(op=>op.seq!==seq),this.recomputeView(),this.getPendingError(providerId)??"Failed to save models.json.";let renamed=this.getModel(providerId,newId);return renamed&&jsonEquals(renamed,{...before,id:newId})?void 0:"The model changed on disk; reopen it before renaming."}removeProvider(providerId){this.enqueue({kind:"removeProvider",seq:this.nextSeq(),providerId})}batch(mutate){this.batching=!0;try{mutate()}finally{this.batching=!1}this.ops.length>0&&this.scheduleSave()}discardProviderDraft(providerId){this.drafts.delete(providerId),!Object.hasOwn(this.baseline.providers,providerId)&&(this.ops=this.ops.filter(op=>op.providerId!==providerId),this.recomputeView())}recomputeView(){let view=structuredClone(this.baseline);for(let id of this.drafts)ensureProvider(view,id);for(let op of this.ops)applyOp(view,op);this.view=view}scheduleSave(){this.batching||(this.saveChain=this.saveChain.catch(()=>{}).then(async()=>{let result2=await this.save();this.lastSaveResult=result2,result2.kind!=="clean"&&this.onSaveResult?.(result2)}))}async flush(){let pending;do pending=this.saveChain,await pending;while(pending!==this.saveChain)}async save(){if(this.ops.length===0)return{kind:"clean"};try{return await withFileMutationQueue(this.path,async()=>{await mkdir(dirname25(this.path),{recursive:!0});let compromised,release2=await import_proper_lockfile5.default.lock(this.path,{realpath:!1,stale:3e4,retries:{retries:20,factor:1.2,minTimeout:50,maxTimeout:250},onCompromised:error=>{compromised=error}}),result2;try{result2=await this.saveLocked(()=>{if(compromised)throw compromised})}catch(error){result2={kind:"error",error:`Failed to save models.json: ${formatError2(error)}`}}try{await release2()}catch(error){!compromised&&result2.kind!=="error"&&result2.kind!=="invalid"&&(result2={kind:"error",error:`Could not release the models.json lock: ${formatError2(error)}`})}return result2})}catch(error){return{kind:"error",error:`Failed to access models.json for saving: ${formatError2(error)}`}}}async saveLocked(assertLock){let tempPath=join45(dirname25(this.path),`.models.${randomUUID9()}.tmp`);try{assertLock();let disk;try{disk=await readDocument(this.path)}catch(error){return{kind:"error",error:`models.json changed on disk and is unreadable: ${formatError2(error)}`}}let working=structuredClone(disk.doc),batch=this.ops.filter(op=>{let provider=this.getProvider(op.providerId);return Object.hasOwn(disk.doc.providers,op.providerId)||!provider||Object.keys(provider).length===0||hasProviderSettings(provider)});for(let op of batch)applyOp(working,op);pruneEmptyNewProviders(working,disk.doc);let settle=()=>{let settled=new Set(batch.map(op=>op.seq));this.ops=this.ops.filter(op=>!settled.has(op.seq)),this.recomputeView()};if(jsonEquals(working,disk.doc))return this.baseline=disk.doc,settle(),{kind:"saved",applied:batch.length};let candidate=`${JSON.stringify(working,null,2)}
|
|
2012
|
-
`;await writeFile3(tempPath,candidate,{encoding:"utf8",mode:384});let validationError=(await ModelConfig.load(tempPath)).getError();if(validationError)return{kind:"invalid",error:validationError};let latest=await readDocument(this.path);if(latest.exists!==disk.exists||latest.rawText!==disk.rawText)throw new Error("models.json changed while saving; the edits were kept for retry.");return!this.backedUp&&disk.exists&&disk.rawText!==void 0&&(await writeFile3(`${this.path}.bak`,disk.rawText,{encoding:"utf8",mode:384}),this.backedUp=!0),assertLock(),await rename(tempPath,this.path),this.baseline=working,settle(),{kind:"saved",applied:batch.length}}finally{await rm(tempPath,{force:!0}).catch(()=>{})}}};function ensureProvider(doc,providerId){let existing=Object.hasOwn(doc.providers,providerId)?doc.providers[providerId]:void 0;if(existing)return existing;let created={};return Object.defineProperty(doc.providers,providerId,{value:created,writable:!0,enumerable:!0,configurable:!0}),created}function applyOp(doc,op){switch(op.kind){case"set":{let provider=ensureProvider(doc,op.providerId);if(op.modelId===void 0){setPath(provider,op.path,op.value);return}let model=(Array.isArray(provider.models)?provider.models:[]).find(entry=>entry.id===op.modelId);model&&setPath(model,op.path,op.value);return}case"addModel":{let provider=ensureProvider(doc,op.providerId),models=Array.isArray(provider.models)?provider.models:[],index3=models.findIndex(entry=>entry.id===op.model.id),clone=structuredClone(op.model);index3>=0?models[index3]=clone:models.push(clone),provider.models=models;return}case"removeModel":{let provider=doc.providers[op.providerId],models=Array.isArray(provider?.models)?provider.models:void 0;if(!provider||!models)return;provider.models=models.filter(entry=>entry.id!==op.modelId);return}case"renameModel":{let provider=doc.providers[op.providerId],models=Array.isArray(provider?.models)?provider.models:void 0;if(!models)return;let model=models.find(entry=>entry.id===op.oldId);model&&!models.some(entry=>entry.id===op.newId)&&(model.id=op.newId);return}case"removeProvider":{delete doc.providers[op.providerId];return}}}function pruneEmptyNewProviders(working,disk){for(let[providerId,provider]of Object.entries(working.providers))Object.hasOwn(disk.providers,providerId)||isPlainObject(provider)&&Object.keys(provider).length===0&&delete working.providers[providerId]}var RefreshCoordinator=class{constructor(runtime){this.pending=new Map,this.changed=new Set,this.revision=0,this.runtime=runtime}touch(providerId){this.pending.set(providerId,++this.revision),this.changed.add(providerId)}get touchedProviders(){return[...this.changed]}async refreshNow(providerId,signal){return this.run([providerId],signal)}async flush(signal){let providers=[...this.pending.keys()];return providers.length===0?{ok:!0,aborted:!1,errors:[]}:this.run(providers,signal)}async run(providers,signal){let revisions=new Map(providers.map(id=>[id,this.pending.get(id)])),combined=AbortSignal.any([...signal?[signal]:[],AbortSignal.timeout(REFRESH_TIMEOUT_MS)]),errors=[];try{let result2=await this.runtime.refresh({allowNetwork:!1,providers,signal:combined});for(let[providerId,error]of result2.errors)errors.push(`${providerId}: ${formatError2(error)}`);let configError=this.runtime.getError();configError&&errors.push(configError);let aborted=result2.aborted||combined.aborted;aborted&&errors.length===0&&errors.push("Refresh was cancelled or timed out.");let ok=errors.length===0&&!aborted;if(ok)for(let id of providers)this.pending.get(id)===revisions.get(id)&&this.pending.delete(id);return{ok,aborted,errors}}catch(error){return errors.push(formatError2(error)),{ok:!1,aborted:combined.aborted,errors}}}};function registerListKeybindings(){registerKeybindings({"app.list.toggle":{defaultKeys:"space",description:"Toggle selected list item"}})}registerListKeybindings();registerKeybindings({"app.provider.switchPaneLeft":{defaultKeys:"left",description:"/provider: focus the left pane"},"app.provider.switchPaneRight":{defaultKeys:"right",description:"/provider: focus the right pane"},"app.provider.removeEntry":{defaultKeys:"ctrl+x",description:"/provider: remove the selected compat or dictionary entry"}});async function probeProviderModels(opts){let baseUrl;try{baseUrl=new URL(opts.baseUrl)}catch{return{ok:!1,error:"Base URL is not a valid URL."}}if(baseUrl.protocol!=="http:"&&baseUrl.protocol!=="https:")return{ok:!1,error:`Unsupported protocol: ${baseUrl.protocol}`};if(baseUrl.username||baseUrl.password||baseUrl.hash)return{ok:!1,error:"Base URL must not contain credentials or a fragment."};if(opts.signal?.aborted)return{ok:!1,error:"Cancelled."};let controller=new AbortController,timeoutMs=opts.timeoutMs??PROBE_LIMITS.timeoutMs,timer=setTimeout(()=>controller.abort(),timeoutMs),onOuterAbort=()=>controller.abort();opts.signal?.addEventListener("abort",onOuterAbort,{once:!0});let doFetch=opts.fetch??globalThis.fetch,getPage=async(url,headers)=>{let response=await doFetch(url,{method:"GET",headers,signal:controller.signal});if(!response.ok){let body2=await readResponseTextBounded(response,{maxBytes:PROBE_LIMITS.maxErrorBytes,signal:controller.signal});return{ok:!1,status:response.status,error:`HTTP ${response.status}${body2?`: ${safeErrorText(body2,opts.auth).slice(0,PROBE_LIMITS.maxErrorChars)}`:""}`}}let text2=await readResponseTextBounded(response,{maxBytes:PROBE_LIMITS.maxBodyBytes,overflowMessage:`Response exceeds ${PROBE_LIMITS.maxBodyBytes} bytes.`,signal:controller.signal});try{return{ok:!0,json:JSON.parse(text2)}}catch{return{ok:!1,error:"Model catalog response is not JSON."}}};try{let url=modelCatalogUrl(baseUrl,opts.api),headers=buildHeaders(opts.auth,opts.api),page=await getPage(url,headers),retry=page.ok?void 0:openAIStyleRetry(baseUrl,opts.auth,opts.api,{url,headers,status:page.status});if(!page.ok&&retry){let retried=await getPage(retry.url,retry.headers);if(!retried.ok)return{ok:!1,error:safeErrorText(`${url.href} \u2192 HTTP ${page.status}; OpenAI-style retry ${retry.url.href} \u2192 ${retried.error}`,opts.auth)};({url,headers}=retry),page=retried}if(!page.ok)return{ok:!1,error:page.error};let models=parseCatalogModels(page.json);if(models===null)return{ok:!1,error:"JSON has no supported OpenAI-style data[] or models[] catalog with model ids. Add models manually if this endpoint uses another catalog format."};let json=page.json;for(let pages=1;opts.api==="anthropic-messages"&&pages<PROBE_LIMITS.maxPages&&models.length<PROBE_LIMITS.maxModels;pages++){let cursor=nextPageCursor(json);if(!cursor)break;let nextUrl=new URL(url.href);nextUrl.searchParams.set("after_id",cursor),nextUrl.searchParams.set("limit","1000");let next=await getPage(nextUrl,headers),more=next.ok?parseCatalogModels(next.json):null;if(!next.ok||!more||(models.push(...more),nextPageCursor(next.json)===cursor))break;json=next.json}let sorted=dedupeSort(models),truncated=sorted.length>PROBE_LIMITS.maxModels||declaresMorePages(json);return{ok:!0,models:sorted.slice(0,PROBE_LIMITS.maxModels),truncated}}catch(error){return controller.signal.aborted?{ok:!1,error:opts.signal?.aborted?"Cancelled.":`Timed out after ${timeoutMs}ms.`}:{ok:!1,error:safeErrorText(formatError2(error),opts.auth)}}finally{clearTimeout(timer),opts.signal?.removeEventListener("abort",onOuterAbort)}}function modelCatalogUrl(base,api){let url=new URL(base.href),path14=url.pathname.replace(/\/+$/,"");return url.pathname=api==="anthropic-messages"&&!path14.endsWith("/v1")?`${path14}/v1/models`:`${path14}/models`,url}function openAIStyleRetry(base,auth,api,first){if(api!=="anthropic-messages"||![401,403,404].includes(first.status??0)||Object.keys(auth?.headers??{}).some(key=>key.toLowerCase()==="authorization"))return;let root=new URL(base.href);root.pathname=root.pathname.replace(/\/+$/,"").replace(/\/anthropic$/i,"");let url=modelCatalogUrl(root,api),headers=buildHeaders(auth,void 0);return url.href===first.url.href&&headers.get("authorization")===first.headers.get("authorization")?void 0:{url,headers}}function safeErrorText(text2,auth){for(let value of[auth?.apiKey,...Object.values(auth?.headers??{})]){if(typeof value!="string"||!value)continue;text2=text2.replaceAll(value,"[redacted]");let token=value.replace(/^Bearer\s+/i,"");token!==value&&token&&(text2=text2.replaceAll(token,"[redacted]"))}return stripTerminalSequences(text2)}function buildHeaders(auth,api){let headers=new Headers;headers.set("accept","application/json");let configured=auth?.headers??{};api==="anthropic-messages"&&headers.set("anthropic-version","2023-06-01");let hasAuthorization=!1;for(let[key,value]of Object.entries(configured))key.toLowerCase()==="authorization"&&(hasAuthorization=!0),typeof value=="string"?headers.set(key,value):value===null&&headers.delete(key);if(!auth?.apiKey||hasAuthorization)return headers;let lower=name=>Object.keys(configured).some(key=>key.toLowerCase()===name);return api==="anthropic-messages"?(auth.apiKey.includes("sk-ant-oat")?headers.set("authorization",`Bearer ${auth.apiKey}`):(lower("x-api-key")||headers.set("x-api-key",auth.apiKey),lower("anthropic-version")||headers.set("anthropic-version","2023-06-01")),headers):api==="google-generative-ai"||api==="google-vertex"?(lower("x-goog-api-key")||headers.set("x-goog-api-key",auth.apiKey),headers):(headers.set("authorization",`Bearer ${auth.apiKey}`),headers)}function declaresMorePages(json){return typeof json=="object"&&json!==null&&"has_more"in json&&json.has_more===!0}function nextPageCursor(json){if(!declaresMorePages(json))return;let lastId=json.last_id;return typeof lastId=="string"&&lastId?lastId:void 0}var CONTEXT_WINDOW_FIELDS=["context_window","context_window.tokens","context_length","top_provider.context_length","max_input_tokens","max_context_length","max_model_len","context_size","metadata.context_length"],MAX_TOKENS_FIELDS=["max_output_tokens","max_completion_tokens","top_provider.max_completion_tokens","max_tokens","max_output_length"],INPUT_MODALITY_FIELDS=["input_modalities","architecture.input_modalities","modalities.input"],IMAGE_FLAG_FIELDS=["supports_vision","enable_vision_input","capabilities.vision","capabilities.image_input.supported"],REASONING_FLAG_FIELDS=["reasoning","supports_reasoning","enable_reason","capabilities.reasoning","capabilities.thinking.supported"],REASONING_LEVEL_FIELDS=["effort.supported_levels","reasoning_effort_support_list"],CAPABILITY_LIST_FIELDS=["supported_parameters","tags","features","supported_features","metadata.tags"];function fieldAt(record,path14){let value=record;for(let key of path14.split(".")){if(!value||typeof value!="object"||Array.isArray(value))return;value=value[key]}return value}function listAt(record,path14){let value=fieldAt(record,path14);return Array.isArray(value)?value.filter(entry=>typeof entry=="string").map(entry=>entry.toLowerCase()):[]}function declaredLimit(record,paths){let limit;for(let path14 of paths){let value=fieldAt(record,path14);typeof value=="number"&&Number.isSafeInteger(value)&&value>0&&(limit=Math.min(limit??value,value))}return limit}function declaresImageInput(record){return INPUT_MODALITY_FIELDS.some(path14=>listAt(record,path14).includes("image"))||IMAGE_FLAG_FIELDS.some(path14=>fieldAt(record,path14)===!0)||CAPABILITY_LIST_FIELDS.some(path14=>listAt(record,path14).includes("vision"))}function declaresReasoning(record){return REASONING_FLAG_FIELDS.some(path14=>fieldAt(record,path14)===!0)||REASONING_LEVEL_FIELDS.some(path14=>listAt(record,path14).length>0)||CAPABILITY_LIST_FIELDS.some(path14=>listAt(record,path14).includes("reasoning"))}function parseCatalogModels(json){if(!json||typeof json!="object")return null;let payload=json,data=Array.isArray(json)?json:Array.isArray(payload.models)?payload.models:payload.data;if(!Array.isArray(data))return null;let models=[];for(let item of data){if(!item||typeof item!="object")continue;let record=item,id=(typeof record.id=="string"?record.id.trim():"")||(typeof record.slug=="string"?record.slug.trim():"");if(!id)continue;let displayName=typeof record.name=="string"&&record.name.trim()?record.name.trim():void 0,anthropicName=typeof record.display_name=="string"&&record.display_name.trim()?record.display_name.trim():typeof record.displayName=="string"?record.displayName.trim():void 0,name=(displayName??anthropicName)!==id?displayName??anthropicName:void 0,model=name?{id,name}:{id},contextWindow=declaredLimit(record,CONTEXT_WINDOW_FIELDS);contextWindow&&(model.contextWindow=contextWindow);let maxTokens=declaredLimit(record,MAX_TOKENS_FIELDS);maxTokens&&(model.maxTokens=maxTokens),declaresImageInput(record)&&(model.input=["text","image"]),declaresReasoning(record)&&(model.reasoning=!0),models.push(model)}return data.length>0&&models.length===0?null:models}function dedupeSort(models){let map=new Map;for(let model of models)map.has(model.id)||map.set(model.id,model);return[...map.values()].sort((a,b2)=>a.id.localeCompare(b2.id))}async function fetchProviderModels(options,signal){let{store,refresher,runtime,providerId}=options,deadline=AbortSignal.any([signal,AbortSignal.timeout(PROBE_LIMITS.timeoutMs)]);try{await raceWithAbortSignal(store.flush(),deadline);let unsaved=store.getPendingError(providerId);if(unsaved)return{ok:!1,error:`Save the provider changes before fetching: ${unsaved}`};let provider=store.getProvider(providerId),settings2=effectiveModelSettings(providerId,provider);if(!settings2.baseUrl)return{ok:!1,error:"Set a baseUrl under API Auth first."};let sync=await refresher.refreshNow(providerId,deadline);if(deadline.throwIfAborted(),!sync.ok)return{ok:!1,error:`The provider did not reload: ${sync.errors.join("; ")}`};let resolved=await raceWithAbortSignal(runtime.getAuth(providerId,{signal:deadline}),deadline),configured=provider?.apiKey!==void 0||provider?.authHeader===!0||Object.keys(provider?.headers??{}).length>0||runtime.getProviderAuthStatus(providerId).configured;if(!resolved&&configured)return{ok:!1,error:"Configured credentials or headers did not resolve; check the provider authentication."};let result2=await probeProviderModels({baseUrl:resolved?.auth.baseUrl??settings2.baseUrl,auth:resolved?.auth,api:settings2.api,signal:deadline});return deadline.throwIfAborted(),result2}catch(error){return deadline.aborted?{ok:!1,error:signal.aborted?"Cancelled.":"Timed out while preparing or fetching the model catalog."}:{ok:!1,error:formatError2(error)}}}async function importProviderModels(options,models,signal){let{store,refresher,providerId}=options;await raceWithAbortSignal(store.flush(),signal);let unsaved=store.getPendingError(providerId);if(unsaved)return unsaved;let settings2=effectiveModelSettings(providerId,store.getProvider(providerId));if(!settings2.api||!settings2.baseUrl)return"Set baseUrl and API Type under API Auth before importing models.";let existing=new Set(store.getModels(providerId).map(model=>model.id)),fresh=models.filter(model=>existing.has(model.id)?!1:(existing.add(model.id),!0));if(fresh.length===0)return;signal.throwIfAborted(),options.edits.addModels(fresh),await store.flush();let saveError=store.getPendingError(providerId);if(saveError)return saveError;let outcome=await refresher.refreshNow(providerId,signal);if(!outcome.ok)return`Models were saved, but refresh failed: ${outcome.errors.join("; ")}`}var ProviderEdits=class{constructor(store,providerId,refresher,refresh){this.renaming=!1,this.store=store,this.providerId=providerId,this.refresher=refresher,this.refresh=refresh}changed(){(!this.store.isDraftProvider(this.providerId)||hasProviderSettings(this.store.getProvider(this.providerId)))&&this.refresher.touch(this.providerId),this.refresh()}setProviderField(path14,value){this.store.setProviderField(this.providerId,path14,value),this.changed()}removeProvider(){this.store.removeProvider(this.providerId),this.changed()}removeModel(modelId){this.store.removeModel(this.providerId,modelId),this.changed()}batch(apply){this.store.batch(apply)}addModels(models){this.store.batch(()=>{for(let model of models)this.store.addModel(this.providerId,model)}),models.length>0&&this.changed()}draft(){let fields={};return{isDraft:!0,read:()=>fields,setField:(path14,value)=>{setPath(fields,path14,value),this.refresh()}}}commitDraft(draft){let fields=draft.read(),id=(fields.id??"").trim();if(!id)return"Model id is required.";if(this.store.getModel(this.providerId,id))return`Model "${id}" already exists.`;let settings2=effectiveModelSettings(this.providerId,this.store.getProvider(this.providerId),fields);if(!settings2.api)return"Cannot resolve an api \u2014 set one under Model-Specific API or the provider's API Auth.";if(!settings2.baseUrl)return"Cannot resolve a baseUrl \u2014 set one under Model-Specific API or the provider's API Auth.";this.store.addModel(this.providerId,{...fields,id}),this.changed()}model(modelId,onRename){let id=modelId,snapshot;return{isDraft:!1,read:()=>snapshot??this.store.getModel(this.providerId,id)??{id},setField:(path14,value)=>{this.store.setModelField(this.providerId,id,path14,value),this.changed()},rename:async newId=>{let oldId=id;snapshot=this.store.getModel(this.providerId,id),this.renaming=!0;try{let error=await this.store.renameModel(this.providerId,id,newId);if(error)return error;id=newId,this.changed();return}finally{snapshot=void 0,this.renaming=!1,onRename(oldId,id)}}}}};var CURSOR2="\u203A",PASTE_START="\x1B[200~",PASTE_END="\x1B[201~",ValueEditor=class{constructor(callbacks){this.input=new Input({prompt:""}),this.input.onSubmit=callbacks.onCommit,this.input.onEscape=callbacks.onCancel}beginOverwrite(firstData){this.input.setValue(""),firstData&&this.input.handleInput(firstData)}reset(value){this.beginTweak(value)}beginTweak(current){this.input.setValue(""),this.input.handleInput(PASTE_START+current+PASTE_END),this.input.setValue(current)}get value(){return this.input.getValue()}handleInput(data){this.input.handleInput(data)}renderLine(width){return this.input.render(Math.max(1,width))[0]??""}get focused(){return this.input.focused}set focused(value){this.input.focused=value}};function renderKeyValueLine(theme2,opts){let lit=opts.active&&opts.paneFocused,marker=lit?theme2.fg("accent",`${CURSOR2} `):" ",keyPrefix=opts.keyLabel===void 0?"":`${opts.keyLabel}: `,keyColor=lit?"accent":"text",note=opts.note?theme2.fg("dim",` ${opts.note}`):"";if(opts.editing){let body2=opts.editing.renderLine(Math.max(1,opts.width-visibleWidth(marker)-visibleWidth(keyPrefix)));return truncateToWidth(marker+theme2.fg(keyColor,keyPrefix)+theme2.fg(keyColor,body2)+note,opts.width)}let valueColor=opts.unset?"dim":keyColor,line=marker+theme2.fg(keyColor,keyPrefix)+theme2.fg(valueColor,opts.valueText??"")+note;return truncateToWidth(line,opts.width)}function renderPlainLine(theme2,text2,opts){let lit=(opts.active??!1)&&(opts.paneFocused??!1),marker=lit?theme2.fg("accent",`${CURSOR2} `):" ",check=opts.checked===void 0?"":opts.checked?"[x] ":"[ ] ",color2=opts.dim?"dim":lit?"accent":"text",note=opts.note?theme2.fg("dim",` ${opts.note}`):"",line=marker+theme2.fg(color2,check+text2)+note;return truncateToWidth(line,opts.width)}function renderInfoLine(theme2,text2,width){return truncateToWidth(theme2.fg("dim",text2),width)}function windowLines(theme2,lines,height,scroll,indicator){let top=Math.max(0,Math.min(scroll?.top??0,lines.length)),bottom=Math.max(0,Math.min(scroll?.bottom??0,lines.length-top)),head=lines.slice(0,top),tail2=bottom>0?lines.slice(lines.length-bottom):[],middle=lines.slice(top,lines.length-bottom),cursor=Math.max(0,Math.min((scroll?.cursor??0)-top,Math.max(0,middle.length-1))),padToHeight=rows=>{let out=rows.slice(0,height);for(;out.length<height;)out.push("");return out},avail=height-head.length-tail2.length;if(middle.length<=avail)return padToHeight([...head,...middle,...tail2]);let slots=Math.max(1,avail-1),start=Math.max(0,Math.min(cursor-Math.floor(slots/2),middle.length-slots)),note=indicator?.(cursor+1,middle.length)??theme2.fg("dim",` (${cursor+1}/${middle.length})`);return padToHeight([...head,...middle.slice(start,start+slots),note,...tail2])}function isPrintableInput(data){if(!data)return!1;if(data.startsWith(PASTE_START)||decodeKittyPrintable(data)!==void 0)return!0;if(data.includes("\x1B")||data.includes("\r")||data.includes(`
|
|
2013
|
-
`))return!1;for(let char of data){let code=char.codePointAt(0);if(code<32||code===127)return!1}return!0}function truncateMiddle2(text2,maxWidth){if(visibleWidth(text2)<=maxWidth)return text2;if(maxWidth<=4)return truncateToWidth(text2,maxWidth);let headWidth=Math.ceil((maxWidth-1)/2),tailWidth=maxWidth-1-headWidth,head="",headUsed=0;for(let char of text2){let charWidth=visibleWidth(char);if(headUsed+charWidth>headWidth)break;head+=char,headUsed+=charWidth}let tail2="",tailUsed=0;for(let char of[...text2].reverse()){let charWidth=visibleWidth(char);if(tailUsed+charWidth>tailWidth)break;tail2=char+tail2,tailUsed+=charWidth}return`${head}\u2026${tail2}`}var InfoPane=class{constructor(host,lines,onConfirm){this.focused=!1,this.host=host,this.lines=lines,this.onConfirm=onConfirm}render(width){return this.focused&&this.onConfirm?this.lines.map((line,index3)=>index3>0?renderInfoLine(this.host.theme,line,width):truncateToWidth(this.host.theme.fg("accent",`${CURSOR2} `)+this.host.theme.fg("text",line),width)):this.lines.map(line=>renderInfoLine(this.host.theme,line,width))}handleInput(data){if(this.host.keybindings.matches(data,"tui.select.cancel")){this.host.popPane();return}this.onConfirm&&this.host.keybindings.matches(data,"tui.select.confirm")&&this.onConfirm()}setFocused(focused){this.focused=focused}hints(){let hints=[];return this.onConfirm&&hints.push(keyHint("tui.select.confirm","proceed")),hints.push(keyHint("tui.select.cancel","back")),hints.join(" ")}},ConfirmPane=class{constructor(host,message,actionLabel,action){this.crumb="Confirm",this.index=1,this.focused=!1,this.host=host,this.message=message,this.actionLabel=actionLabel,this.action=action}render(width){let theme2=this.host.theme;return[truncateToWidth(theme2.fg("warning",this.message),width),renderPlainLine(theme2,this.actionLabel,{active:this.index===0,paneFocused:this.focused,width}),renderPlainLine(theme2,"Cancel",{active:this.index===1,paneFocused:this.focused,width})]}handleInput(data){let kb=this.host.keybindings;if(kb.matches(data,"tui.select.up")||kb.matches(data,"tui.select.down")){this.index=this.index===0?1:0,this.host.refresh();return}if(kb.matches(data,"tui.select.cancel")){this.host.popPane();return}kb.matches(data,"tui.select.confirm")&&(this.index===0?this.action():this.host.popPane())}setFocused(focused){this.focused=focused}hints(){return[keyHint("tui.select.confirm","choose"),keyHint("tui.select.cancel","cancel")].join(" ")}};function moveSelection(keys,data,index3,count){let delta=keys.matches(data,"tui.select.up")?-1:keys.matches(data,"tui.select.down")?1:void 0;return delta===void 0?void 0:count===0?0:(index3+delta+count)%count}var ChoicePane=class{constructor(host,crumb,options){this.focused=!1,this.host=host,this.crumb=crumb,this.options=options,this.index=Math.max(0,options.choices().findIndex(choice=>choice.value===options.current()))}render(width){let lines=this.options.choices().map((choice,index3)=>renderPlainLine(this.host.theme,`${choice.value===this.options.current()?"\u25CF":"\u25CB"} ${choice.label}`,{active:index3===this.index,paneFocused:this.focused,dim:choice.dim,width}));return this.error&&lines.push(renderInfoLine(this.host.theme,this.error,width)),lines}scrollWindow(){return{cursor:this.index,bottom:this.error?1:0}}handleInput(data){let choices=this.options.choices(),next=moveSelection(this.host.keybindings,data,this.index,choices.length);if(next!==void 0)this.index=next,this.host.refresh();else if(this.host.keybindings.matches(data,"tui.select.cancel"))this.host.popPane();else if(this.host.keybindings.matches(data,"tui.select.confirm")||this.host.keybindings.matches(data,"app.list.toggle")){let choice=choices[this.index];if(!choice)return;this.error=this.options.choose(choice.value),this.error?this.host.refresh():this.host.popPane()}}setFocused(focused){this.focused=focused}hints(){return[rawKeyHint("\u2191\u2193","move"),keyHint("tui.select.confirm","select"),keyHint("tui.select.cancel","back")].join(" ")}},InlineEdit=class{constructor(refresh){this.refresh=refresh}get editing(){return this.active!==void 0}editor(key){return this.active?.key===key?this.active.editor:void 0}setFocused(focused){this.active&&(this.active.editor.focused=focused)}begin(key,current,mode,focused,commit,firstData){let editor=new ValueEditor({onCommit:value=>{this.error=commit(value),this.error||(this.active=void 0),this.refresh()},onCancel:()=>{this.active=void 0,this.error=void 0,this.refresh()}});this.active={key,editor},editor.focused=focused,mode==="overwrite"?editor.beginOverwrite(firstData):editor.beginTweak(current),this.refresh()}handleInput(data,keys){return this.active?(!keys.matches(data,"tui.select.up")&&!keys.matches(data,"tui.select.down")&&this.active.editor.handleInput(data),this.refresh(),!0):!1}};function formatTokens2(count){return count<1e3?count.toString():count<1e4?`${(count/1e3).toFixed(1)}k`:count<1e6?`${Math.round(count/1e3)}k`:count<1e7?`${(count/1e6).toFixed(1)}M`:`${Math.round(count/1e6)}M`}function metadataNote(model){let parts=[model.contextWindow?`${formatTokens2(model.contextWindow)} ctx`:"",model.maxTokens?`${formatTokens2(model.maxTokens)} out`:"",model.input?.includes("image")?"img":"",model.reasoning?"think":""].filter(Boolean);return parts.length>0?`\xB7 ${parts.join(" \xB7 ")}`:void 0}var FetchModelsPane=class{constructor(host){this.state={type:"idle"},this.query="",this.index=0,this.checked=new Set,this.focused=!1,this.disposed=!1,this.host=host,this.search=new ValueEditor({onCommit:()=>this.importChecked(),onCancel:()=>this.exitResults()})}start(){if(this.disposed||this.state.type==="loading"||this.state.type==="importing"||!this.catalogUrl())return;let controller=new AbortController;this.state={type:"loading",controller},this.host.refresh(),this.host.runFetch(controller.signal).then(result2=>{if(!(this.disposed||controller.signal.aborted||this.state.type!=="loading"||this.state.controller!==controller)){if(result2.ok)this.state={type:"results",catalog:result2},this.checked=new Set,this.query="",this.search.reset(""),this.index=0,this.search.focused=this.focused,this.host.setFetchStatus(`\xB7 ${result2.models.length} models`);else{if(result2.error==="Cancelled.")return;this.state={type:"error",message:result2.error},this.host.setFetchStatus("\xB7 failed")}this.host.refresh()}}).catch(error=>{this.disposed||controller.signal.aborted||this.state.type!=="loading"||this.state.controller!==controller||(this.state={type:"error",message:error instanceof Error?error.message:String(error)},this.host.setFetchStatus("\xB7 failed"),this.host.refresh())})}existingIds(){return new Set(this.host.store.getModels(this.host.providerId).map(model=>model.id))}catalogUrl(){let baseUrl=this.host.store.getProvider(this.host.providerId)?.baseUrl;try{return baseUrl?modelCatalogUrl(new URL(baseUrl),this.host.effectiveApi()).href:void 0}catch{return}}rows(){if(this.state.type!=="results"&&this.state.type!=="importing")return[];let existing=this.existingIds(),rows=this.state.catalog.models.map(model=>({model,added:existing.has(model.id)})),query=this.query.trim().toLowerCase();return query?rows.filter(row=>row.model.id.toLowerCase().includes(query)||row.model.name?.toLowerCase().includes(query)):rows}render(width){let theme2=this.host.theme,catalogUrl=this.catalogUrl();switch(this.state.type){case"idle":return catalogUrl?[renderPlainLine(theme2,"Fetch Models",{active:!0,paneFocused:this.focused,note:`\xB7 from ${truncateMiddle2(catalogUrl,Math.max(10,width-22))}`,width})]:[renderInfoLine(theme2,"Set a baseUrl under API Auth first.",width)];case"loading":return[renderInfoLine(theme2,`Fetching ${catalogUrl??""} \u2026`,width),renderInfoLine(theme2,"Esc cancels the request.",width)];case"error":return[theme2.fg("error",truncate3(this.state.message,Math.max(10,width-2))),renderInfoLine(theme2,"Enter retries; Esc goes back.",width)];case"importing":case"results":{let lines=[];this.state.catalog.truncated&&lines.push(renderInfoLine(theme2,"The catalog was truncated; refine manually if a model is missing.",width)),lines.push(this.search.renderLine(width));let rows=this.rows();for(let[rowIndex,row]of rows.entries()){if(row.added){lines.push(renderPlainLine(theme2,row.model.id,{active:rowIndex===this.index,paneFocused:this.focused,dim:!0,note:"\xB7 Added",width}));continue}lines.push(renderPlainLine(theme2,row.model.name?`${row.model.id} \xB7 ${row.model.name}`:row.model.id,{checked:this.checked.has(row.model.id),active:rowIndex===this.index,paneFocused:this.focused,note:metadataNote(row.model),width}))}rows.length===0&&lines.push(renderInfoLine(theme2,"No matching models.",width));let addedCount=rows.filter(row=>row.added).length;return lines.push(renderInfoLine(theme2,`${this.checked.size} selected \xB7 ${rows.length} shown${addedCount?` \xB7 ${addedCount} already added`:""}`,width)),this.state.type==="importing"&&lines.push(renderInfoLine(theme2,"Importing\u2026",width)),this.state.type==="results"&&this.state.error&&lines.push(theme2.fg("error",truncate3(this.state.error,Math.max(10,width-2)))),lines}}}scrollWindow(){if(this.state.type!=="results"&&this.state.type!=="importing")return{};let top=(this.state.catalog.truncated?1:0)+1,bottom=1+(this.state.type==="importing"||this.state.error?1:0);return{top,bottom,cursor:top+this.index}}handleInput(data){let kb=this.host.keybindings;switch(this.state.type){case"idle":if(kb.matches(data,"tui.select.confirm")){this.start();return}if(kb.matches(data,"tui.select.cancel")){this.host.popPane();return}return;case"loading":if(kb.matches(data,"tui.select.cancel")){this.state.controller.abort(),this.state={type:"idle"},this.host.refresh();return}return;case"error":if(kb.matches(data,"tui.select.confirm")){this.start();return}if(kb.matches(data,"tui.select.cancel")){this.host.popPane();return}return;case"importing":case"results":this.handleResultsInput(data);return}}handleResultsInput(data){let kb=this.host.keybindings,rows=this.rows(),next=moveSelection(kb,data,this.index,rows.length);if(next!==void 0){this.index=next,this.host.refresh();return}if(kb.matches(data,"app.list.toggle")){let row=rows[this.index];if(!row||row.added||this.state.type==="importing")return;this.checked.has(row.model.id)?this.checked.delete(row.model.id):this.checked.add(row.model.id),this.host.refresh();return}if(kb.matches(data,"tui.select.cancel")){this.exitResults();return}if(kb.matches(data,"tui.select.confirm")){this.importChecked();return}let before=this.query;this.search.handleInput(data),this.query=this.search.value,this.query!==before&&(this.index=0),this.host.refresh()}importChecked(){if(this.state.type!=="results")return;let chosen;if(this.checked.size===0){let row=this.rows()[this.index];if(!row||row.added)return;chosen=[row.model]}else chosen=this.state.catalog.models.filter(model=>this.checked.has(model.id));let controller=new AbortController,catalog=this.state.catalog;this.state={type:"importing",catalog,controller},this.host.refresh(),this.host.importModels(chosen,controller.signal).then(error=>{if(!(this.disposed||controller.signal.aborted||this.state.type!=="importing"||this.state.controller!==controller)){if(error)return this.state={type:"results",catalog,error},this.host.setFetchStatus("\xB7 import failed"),this.host.refresh();this.host.setFetchStatus(`\xB7 ${this.host.store.getModels(this.host.providerId).length} models`),this.state={type:"idle"},this.host.popPane()}}).catch(error=>{this.disposed||controller.signal.aborted||this.state.type!=="importing"||this.state.controller!==controller||(this.state={type:"results",catalog,error:error instanceof Error?error.message:String(error)},this.host.refresh())})}exitResults(){(this.state.type==="loading"||this.state.type==="importing")&&this.state.controller.abort(),this.state={type:"idle"},this.checked=new Set,this.host.popPane()}setFocused(focused){this.focused=focused,this.search.focused=focused&&(this.state.type==="results"||this.state.type==="importing")}isEditing(){return this.state.type==="results"||this.state.type==="importing"}dispose(){this.disposed=!0,(this.state.type==="loading"||this.state.type==="importing")&&this.state.controller.abort()}hints(){switch(this.state.type){case"loading":return keyHint("tui.select.cancel","cancel request");case"importing":case"results":return[rawKeyHint("type","filter"),keyHint("app.list.toggle","check"),keyHint("tui.select.confirm","import"),keyHint("tui.select.cancel","discard")].join(" ");case"error":return[keyHint("tui.select.confirm","retry"),keyHint("tui.select.cancel","back")].join(" ");default:return this.catalogUrl()?[keyHint("tui.select.confirm","fetch"),keyHint("tui.select.cancel","back")].join(" "):keyHint("tui.select.cancel","back")}}};function formatContext(model){let ctx=model.contextWindow>=1e3?`${Math.round(model.contextWindow/1024)}k`:String(model.contextWindow);return`${model.api} \xB7 ${ctx} ctx${model.reasoning?" \xB7 reasoning":""}`}var BuiltinCandidatesPane=class{constructor(host,model){this.crumb="Use Built-in Data",this.index=0,this.focused=!1,this.host=host,this.model=model,this.query=this.model.read().id??"",this.search=new ValueEditor({onCommit:()=>this.pickCurrent(),onCancel:()=>this.host.popPane()}),this.search.reset(this.query)}candidates(){return matchBuiltinModels(this.query,this.host.effectiveApi(this.model.read()))}render(width){let theme2=this.host.theme,lines=[this.search.renderLine(width)],matches=this.candidates();matches.length===0&&lines.push(renderInfoLine(theme2,"No builtin candidates \u2014 keep configuring manually.",width));for(let[rowIndex,match2]of matches.entries()){let{providerId,model}=match2.entry,label=`${providerId} / ${model.id}`,note=(match2.tier==="exact"?"exact \xB7 ":"")+`${model.name!==model.id?`${model.name} \xB7 `:""}${formatContext(model)}`;lines.push(renderPlainLine(theme2,label,{active:rowIndex===this.index,paneFocused:this.focused,note,width}))}return lines.push(renderInfoLine(theme2,"Candidates are a reference only; the configured id is never rewritten.",width)),lines}scrollWindow(){return{top:1,bottom:1,cursor:1+this.index}}pickCurrent(){let entry=this.candidates()[this.index]?.entry;entry&&this.host.pushPane(new BuiltinPreviewPane(this.host,this.model,entry))}handleInput(data){let kb=this.host.keybindings,count=this.candidates().length,next=moveSelection(kb,data,this.index,count);if(next!==void 0){this.index=next,this.host.refresh();return}if(kb.matches(data,"tui.select.cancel")){this.host.popPane();return}if(kb.matches(data,"tui.select.confirm")){this.pickCurrent();return}let before=this.query;this.search.handleInput(data),this.query=this.search.value,this.query!==before&&(this.index=0),this.host.refresh()}setFocused(focused){this.focused=focused,this.search.focused=focused}isEditing(){return!0}hints(){return[rawKeyHint("type","filter"),rawKeyHint("\u2191\u2193","move"),keyHint("tui.select.confirm","preview"),keyHint("tui.select.cancel","back")].join(" ")}},BuiltinPreviewPane=class{constructor(host,model,reference){this.crumb="Use Built-in Data \xB7 preview",this.index=0,this.focused=!1,this.host=host,this.model=model,this.reference=reference;let current=model.read();this.snapshot=structuredClone(current),this.snapshotApi=host.effectiveApi(current),this.changes=computeFieldChanges(current,reference.model,host.effectiveApi(current)),this.checked=this.changes.map(change=>change.checked&&change.applicable)}rowCount(){return this.changes.length+1}render(width){let theme2=this.host.theme,lines=[renderInfoLine(theme2,`reference: ${this.reference.providerId} / ${this.reference.model.id}`,width)];for(let[rowIndex,change]of this.changes.entries()){let active=rowIndex===this.index,expandable=change.referenceDetails!==void 0,note=change.applicable?void 0:"\xB7 view only";if(lines.push(renderPlainLine(theme2,`${change.field}: ${change.currentText} \u2192 ${change.referenceText}`,{checked:change.applicable?this.checked[rowIndex]:void 0,active,paneFocused:this.focused,note,width})),this.expanded===rowIndex&&expandable){for(let detail of change.referenceDetails)lines.push(renderInfoLine(theme2,` ${detail}`,width));change.referenceHasTiers&&lines.push(renderInfoLine(theme2," reference has cost tiers \u2014 tiers are never imported.",width))}}return lines.push(renderPlainLine(theme2,"Apply Selected Fields",{active:this.index===this.changes.length,paneFocused:this.focused,width})),this.error&&lines.push(theme2.fg("error",truncate3(this.error,Math.max(10,width-2)))),lines}scrollWindow(){let cursor=1+this.index;if(this.expanded!==void 0&&this.expanded<this.index){let change=this.changes[this.expanded];change.referenceDetails&&(cursor+=change.referenceDetails.length+(change.referenceHasTiers?1:0))}return{top:1,bottom:this.error?1:0,cursor}}handleInput(data){let kb=this.host.keybindings,next=moveSelection(kb,data,this.index,this.rowCount());if(next!==void 0){this.index=next,this.host.refresh();return}if(kb.matches(data,"tui.select.cancel")){this.host.popPane();return}if(kb.matches(data,"app.list.toggle")){let change=this.changes[this.index];if(!change)return;if(!change.applicable){this.expanded=this.expanded===this.index?void 0:this.index,this.host.refresh();return}this.checked[this.index]=!this.checked[this.index],this.host.refresh();return}if(kb.matches(data,"tui.select.confirm")){if(this.index===this.changes.length){this.apply();return}let change=this.changes[this.index];change.referenceDetails?this.expanded=this.expanded===this.index?void 0:this.index:change.applicable&&(this.checked[this.index]=!this.checked[this.index]),this.host.refresh();return}}apply(){let current=this.model.read();if(this.host.effectiveApi(current)!==this.snapshotApi){this.error="The API changed since this preview opened; reopen to continue.",this.host.refresh();return}if(!current.id||!jsonEquals(current,this.snapshot)){this.error="The model changed since this preview opened; reopen to continue.",this.host.refresh();return}let chosen=this.changes.filter((_2,rowIndex)=>this.checked[rowIndex]&&this.changes[rowIndex].applicable);if(chosen.length===0){this.host.popPane();return}this.host.edits.batch(()=>{for(let change of chosen)for(let patch of change.patches)this.model.setField(patch.path,patch.value)}),this.host.notify(`Applied ${chosen.length} field${chosen.length===1?"":"s"} from ${this.reference.providerId} / ${this.reference.model.id}.`,"info"),this.host.popPane(),this.host.popPane()}setFocused(focused){this.focused=focused}hints(){return[keyHint("app.list.toggle","check"),keyHint("tui.select.confirm","details / apply"),keyHint("tui.select.cancel","back")].join(" ")}};var THINKING_VARIABLES=["thinking.enabled","thinking.effort","thinking.budget"],SESSION_AFFINITY=["openai","openai-nosession","openrouter"],OPENAI_COMPLETIONS_FIELDS=[{key:"supportsStore",kind:"boolean",note:"Accepts the `store` parameter"},{key:"supportsDeveloperRole",kind:"boolean",note:"Accepts `developer` role messages"},{key:"supportsReasoningEffort",kind:"boolean",note:"Accepts `reasoning_effort`"},{key:"supportsUsageInStreaming",kind:"boolean",note:"Streams usage chunks"},{key:"supportsFinishReason",kind:"boolean",note:"Reports finish reasons"},{key:"maxTokensField",kind:"enum",options:["max_completion_tokens","max_tokens"],note:"Token limit field name"},{key:"requiresToolResultName",kind:"boolean",note:"Tool results need a `name`"},{key:"requiresAssistantAfterToolResult",kind:"boolean",note:"Needs assistant message after tool results"},{key:"requiresThinkingAsText",kind:"boolean",note:"Thinking must be plain text"},{key:"requiresReasoningContentOnAssistantMessages",kind:"boolean",note:"Assistant messages must carry reasoning content"},{key:"thinkingFormat",kind:"enum",options:["openai","openrouter","together","baseten","deepseek","zai","qwen","chat-template","qwen-chat-template","string-thinking","ant-ling"],note:"Reasoning payload format"},{key:"chatTemplateKwargs",kind:"stringMap",note:"Extra chat-template kwargs (open dictionary)"},{key:"chatTemplateArgs",kind:"stringMap",note:"Extra chat-template args (open dictionary)"},{key:"cacheControlFormat",kind:"enum",options:["anthropic"],note:"Cache-control payload format"},{key:"openRouterRouting",kind:"json",note:"OpenRouter routing preferences object"},{key:"vercelGatewayRouting",kind:"json",note:"Vercel AI Gateway routing object"},{key:"supportsOpenAIGrammarTools",kind:"boolean",note:"Grammar-constrained tool calls"},{key:"supportsStrictMode",kind:"boolean",note:"Strict tool schemas"},{key:"sendSessionAffinityHeaders",kind:"boolean",note:"Send session affinity headers"},{key:"supportsMidConvoSystemMessages",kind:"boolean",note:"Accepts mid-conversation system messages"},{key:"supportsMidConvoToolAdditions",kind:"boolean",note:"System messages can add tools mid-conversation"},{key:"sessionAffinityFormat",kind:"enum",options:SESSION_AFFINITY,note:"Affinity header format"},{key:"supportsLongCacheRetention",kind:"boolean",note:"Long-lived prompt cache retention"},{key:"vllmPriority",kind:"number",note:"vLLM scheduling priority"},{key:"zaiToolStream",kind:"boolean",note:"Z.AI streaming tool calls"},{key:"supportsThinkingTokenBudget",kind:"boolean",note:"Enable the thinking-token budget alias"},{key:"thinkingTokenBudgetField",kind:"enum",options:["thinking_token_budget","thinking_budget","thinking_budget_tokens"],note:"Thinking budget field"}],OPENAI_RESPONSES_FIELDS=[{key:"supportsDeveloperRole",kind:"boolean",note:"Accepts `developer` role messages"},{key:"sessionAffinityFormat",kind:"enum",options:SESSION_AFFINITY,note:"Affinity header format"},{key:"supportsLongCacheRetention",kind:"boolean",note:"Long-lived prompt cache retention"},{key:"supportsStrictMode",kind:"boolean",note:"Strict tool schemas"},{key:"supportsOpenAIGrammarTools",kind:"boolean",note:"Grammar-constrained tool calls"},{key:"supportsAdditionalTools",kind:"boolean",note:"Accepts additional hosted tools"},{key:"supportsToolSearch",kind:"boolean",note:"Tool search support"},{key:"supportsMaxOutputTokens",kind:"boolean",note:"Accepts `max_output_tokens`"},{key:"supportsExplicitPromptCacheMode",kind:"boolean",note:"Explicit prompt caching"}],ANTHROPIC_MESSAGES_FIELDS=[{key:"supportsEagerToolInputStreaming",kind:"boolean",note:"Streams tool input eagerly"},{key:"supportsLongCacheRetention",kind:"boolean",note:"Long-lived prompt cache retention"},{key:"sendSessionAffinityHeaders",kind:"boolean",note:"Send session affinity headers"},{key:"supportsCacheControlOnTools",kind:"boolean",note:"Cache control on tool definitions"},{key:"supportsTemperature",kind:"boolean",note:"Accepts `temperature`"},{key:"forceAdaptiveThinking",kind:"boolean",note:"Force adaptive thinking mode"},{key:"allowEmptySignature",kind:"boolean",note:"Tolerate empty thinking signatures"},{key:"supportsStrictTools",kind:"boolean",note:"Strict tool schemas"},{key:"supportsMidConvoEffort",kind:"boolean",note:"Effort changes mid-conversation"},{key:"supportsMidConvoSystemMessages",kind:"boolean",note:"Accepts mid-conversation system messages"},{key:"supportsMidConvoToolChanges",kind:"boolean",note:"Accepts mid-conversation tool changes"},{key:"allowedFallbackModels",kind:"json",note:"Server-side refusal fallback models"}],BEDROCK_FIELDS=[{key:"supportsStrictMode",kind:"boolean",note:"Strict tool schemas"}];function compatFieldsForApi(api){switch(api){case"openai-completions":return OPENAI_COMPLETIONS_FIELDS;case"openai-responses":return OPENAI_RESPONSES_FIELDS;case"azure-openai-responses":return OPENAI_RESPONSES_FIELDS.filter(field5=>["supportsDeveloperRole","supportsStrictMode","supportsOpenAIGrammarTools"].includes(field5.key));case"openai-codex-responses":return OPENAI_RESPONSES_FIELDS.filter(field5=>["supportsStrictMode","supportsOpenAIGrammarTools","supportsAdditionalTools","supportsToolSearch"].includes(field5.key));case"anthropic-messages":return ANTHROPIC_MESSAGES_FIELDS;case"bedrock-converse-stream":return BEDROCK_FIELDS;default:return[]}}function compatFieldFor(api,key){return compatFieldsForApi(api).find(field5=>field5.key===key)}var completionsCompatValidator=Compile(OpenAICompletionsCompatSchema);function validateCompletionsCompat(value){if(!completionsCompatValidator.Check(value))return completionsCompatValidator.Errors(value).slice(0,5).map(error=>{let path14=error.instancePath.replace(/^\//,"").replace(/\//g,"."),required=error.keyword==="required"?error.params.requiredProperties?.[0]:void 0;return`${required?path14?`${path14}.${required}`:required:path14||"root"}: ${error.message}`}).join("; ")}function validateJsonCompatValue(key,text2){let value;try{value=JSON.parse(text2)}catch{return"Value is not valid JSON."}return validateCompletionsCompat({[key]:value})}function validateChatTemplateKwarg(value){if(value!==null&&typeof value=="object"&&!Array.isArray(value)&&!Object.keys(value).every(key=>key==="$var"||key==="omitWhenOff"))return'Only "$var" and "omitWhenOff" are allowed.';let error=validateCompletionsCompat({chatTemplateKwargs:{value}});return error?`Value must be a scalar or valid $var reference: ${error}`:void 0}function compatObject(handle){let compat=handle.read().compat;return typeof compat=="object"&&compat!==null&&!Array.isArray(compat)?compat:{}}function scalarText(value){return value===null?"null":typeof value=="string"||typeof value=="number"||typeof value=="boolean"?String(value):JSON.stringify(value)??String(value)}var DICT_VALUE_KINDS=["string","number","boolean","null","$var"],VAR_OPTIONS=THINKING_VARIABLES,DictPane=class{constructor(host,model,dictKey){this.index=0,this.mode={type:"list"},this.focused=!1,this.host=host,this.model=model,this.dictKey=dictKey,this.crumb=`compat \xB7 ${dictKey}`}dict(){let value=compatObject(this.model)[this.dictKey];return typeof value=="object"&&value!==null&&!Array.isArray(value)?value:{}}entries(){return Object.entries(this.dict())}render(width){let theme2=this.host.theme,lines=[renderInfoLine(theme2,"free-form keys; values: string \xB7 number \xB7 boolean \xB7 null \xB7 $var",width)];if(this.mode.type!=="list")return lines.push(...this.renderMode(width)),this.error&&lines.push(renderInfoLine(theme2,this.error,width)),lines;let entries=this.entries();for(let[rowIndex,[key,value]]of entries.entries()){let active=rowIndex===this.index;lines.push(renderKeyValueLine(theme2,{keyLabel:key,valueText:scalarText(value),active,paneFocused:this.focused,width}))}return lines.push(renderPlainLine(theme2,"+ Add Entry",{active:this.index===entries.length&&this.mode.type==="list",paneFocused:this.focused,width})),this.error&&lines.push(theme2.fg("error",truncate3(this.error,Math.max(10,width-2)))),lines}scrollWindow(){return this.mode.type!=="list"?{top:1,bottom:this.error?1:0}:{top:1,bottom:this.error?1:0,cursor:1+this.index}}renderMode(width){let theme2=this.host.theme,mode=this.mode;switch(mode.type){case"keyEdit":return[renderInfoLine(theme2,"new key:",width),mode.editor.renderLine(width)];case"kindPick":return[renderInfoLine(theme2,`${mode.key} \xB7 value kind`,width),...DICT_VALUE_KINDS.map((kind,kindIndex)=>renderPlainLine(theme2,kind,{active:kindIndex===mode.index,paneFocused:this.focused,width}))];case"valueEdit":return[renderInfoLine(theme2,`${mode.key} \xB7 ${mode.kind}`,width),renderKeyValueLine(theme2,{keyLabel:mode.key,active:!0,paneFocused:this.focused,editing:mode.editor,width})];case"boolPick":return[renderInfoLine(theme2,`${mode.key} \xB7 boolean`,width),...["true","false"].map((option,optionIndex)=>renderPlainLine(theme2,option,{active:optionIndex===mode.index,paneFocused:this.focused,width}))];case"varPick":return[renderInfoLine(theme2,`${mode.key} \xB7 $var`,width),...VAR_OPTIONS.map((option,optionIndex)=>renderPlainLine(theme2,option,{active:optionIndex===mode.index,paneFocused:this.focused,width}))];case"omitPick":return[renderInfoLine(theme2,`${mode.key} \xB7 omitWhenOff`,width),...["default","true","false"].map((option,optionIndex)=>renderPlainLine(theme2,option,{active:optionIndex===mode.index,paneFocused:this.focused,width}))];default:return[]}}handleInput(data){let kb=this.host.keybindings,mode=this.mode;switch(mode.type){case"keyEdit":case"valueEdit":if(kb.matches(data,"tui.select.up")||kb.matches(data,"tui.select.down"))return;mode.editor.handleInput(data),this.host.refresh();return;case"kindPick":this.handlePick(data,mode,DICT_VALUE_KINDS.length,index3=>{let key=mode.key,kind=DICT_VALUE_KINDS[index3];this.startValueForKind(key,kind)});return;case"boolPick":this.handlePick(data,mode,2,index3=>{let key=mode.key;this.mode={type:"list"},this.writeEntry(key,index3===0)});return;case"varPick":this.handlePick(data,mode,VAR_OPTIONS.length,index3=>{let key=mode.key;this.mode={type:"omitPick",key,$var:VAR_OPTIONS[index3],index:0},this.host.refresh()});return;case"omitPick":this.handlePick(data,mode,3,index3=>{this.mode={type:"list"},this.writeEntry(mode.key,index3===0?{$var:mode.$var}:{$var:mode.$var,omitWhenOff:index3===1})});return;case"list":this.handleList(data);return}}handlePick(data,mode,count,choose2){let kb=this.host.keybindings,index3=mode.index;if(kb.matches(data,"tui.select.up")){mode.index=index3===0?count-1:index3-1,this.host.refresh();return}if(kb.matches(data,"tui.select.down")){mode.index=(index3+1)%count,this.host.refresh();return}if(kb.matches(data,"tui.select.cancel")){this.mode={type:"list"},this.host.refresh();return}kb.matches(data,"tui.select.confirm")&&choose2(index3)}handleList(data){let kb=this.host.keybindings,rowCount=this.entries().length+1,next=moveSelection(kb,data,this.index,rowCount);if(next!==void 0){this.index=next,this.host.refresh();return}if(kb.matches(data,"tui.select.cancel")){this.host.popPane();return}if(kb.matches(data,"app.provider.removeEntry")){let entry=this.entries()[this.index];if(!entry)return;this.model.setField(["compat",this.dictKey,entry[0]],DELETE),this.index=Math.max(0,Math.min(this.index,this.entries().length-1));return}if(kb.matches(data,"tui.select.confirm")||kb.matches(data,"app.list.toggle")){let entry=this.entries()[this.index];if(!entry){let editor2=new ValueEditor({onCommit:raw=>{let key2=raw.trim();if(!key2)return this.error="Key must be non-empty.",this.host.refresh();if(Object.hasOwn(this.dict(),key2))return this.error=`"${key2}" already exists.`,this.host.refresh();this.error=void 0,this.mode={type:"kindPick",key:key2,index:0},this.host.refresh()},onCancel:()=>{this.mode={type:"list"},this.error=void 0,this.host.refresh()}});editor2.focused=this.focused,this.mode={type:"keyEdit",editor:editor2},this.host.refresh();return}let[key,value]=entry;if(typeof value=="boolean"){this.writeEntry(key,!value);return}if(value===null)return;if(typeof value=="object"){let record=value;if(record.$var==="thinking.enabled"||record.$var==="thinking.effort"||record.$var==="thinking.budget"){this.mode={type:"omitPick",key,$var:record.$var,index:record.omitWhenOff===void 0?0:record.omitWhenOff?1:2},this.host.refresh();return}return}let kind=typeof value=="number"?"number":"string",editor=new ValueEditor({onCommit:raw=>this.commitScalar(key,kind,raw),onCancel:()=>{this.mode={type:"list"},this.error=void 0,this.host.refresh()}});editor.beginTweak(String(value)),editor.focused=this.focused,this.mode={type:"valueEdit",key,kind,editor},this.host.refresh();return}}startValueForKind(key,kind){switch(kind){case"string":case"number":{let editor=new ValueEditor({onCommit:raw=>this.commitScalar(key,kind,raw),onCancel:()=>{this.mode={type:"list"},this.error=void 0,this.host.refresh()}});editor.focused=this.focused,this.mode={type:"valueEdit",key,kind,editor},this.host.refresh();return}case"boolean":this.mode={type:"boolPick",key,index:0},this.host.refresh();return;case"null":this.mode={type:"list"},this.writeEntry(key,null);return;case"$var":this.mode={type:"varPick",key,index:0},this.host.refresh();return}}commitScalar(key,kind,raw){let value=raw;if(kind==="number"){let parsed=Number(raw.trim());if(!Number.isFinite(parsed)){this.error=`${key} must be a number.`,this.host.refresh();return}value=parsed}let invalid2=validateChatTemplateKwarg(value);if(invalid2){this.error=invalid2,this.host.refresh();return}this.error=void 0,this.mode={type:"list"},this.writeEntry(key,value)}writeEntry(key,value){let invalid2=validateChatTemplateKwarg(value);if(invalid2){this.error=invalid2,this.host.refresh();return}this.model.setField(["compat",this.dictKey,key],value)}setFocused(focused){this.focused=focused,(this.mode.type==="keyEdit"||this.mode.type==="valueEdit")&&(this.mode.editor.focused=focused)}isEditing(){return this.mode.type==="keyEdit"||this.mode.type==="valueEdit"}hints(){switch(this.mode.type){case"keyEdit":case"valueEdit":return[keyHint("tui.input.submit","save"),keyHint("tui.select.cancel","cancel")].join(" ");case"list":return[keyHint("tui.select.confirm","edit / add"),keyHint("app.provider.removeEntry","remove"),keyHint("tui.select.cancel","back")].join(" ");default:return[rawKeyHint("\u2191\u2193","move"),keyHint("tui.select.confirm","choose"),keyHint("tui.select.cancel","cancel")].join(" ")}}};function compatObject2(handle){let compat=handle.read().compat;return typeof compat=="object"&&compat!==null&&!Array.isArray(compat)?compat:{}}function scalarText2(value){return value===null?"null":typeof value=="string"||typeof value=="number"||typeof value=="boolean"?String(value):JSON.stringify(value)??String(value)}var CompatPane=class{constructor(host,model){this.crumb="compat",this.index=0,this.mode={type:"list"},this.focused=!1,this.host=host,this.model=model}entries(){return Object.entries(compatObject2(this.model))}effectiveApi(){return this.host.effectiveApi(this.model.read())}rowCount(){return this.entries().length+1}render(width){let theme2=this.host.theme,api=this.effectiveApi(),lines=[renderInfoLine(theme2,api?`effective api: ${api}`:"effective api: unresolved \u2014 set API Type",width)];if(this.mode.type==="chooseValue"){let mode=this.mode;lines.push(renderKeyValueLine(theme2,{keyLabel:mode.key,valueText:"choose a value",active:!0,paneFocused:this.focused,width}));for(let[index3,option]of mode.options.entries())lines.push(renderPlainLine(theme2,option,{active:index3===mode.index,paneFocused:this.focused,width}));return lines}let known=api?compatFieldsForApi(api):[],entries=this.entries(),editingKey=this.mode.type==="list"?void 0:this.mode.key;editingKey!==void 0&&!entries.some(([key])=>key===editingKey)&&entries.push([editingKey,void 0]),known.length===0&&entries.length===0&&lines.push(renderInfoLine(theme2,`No compat fields are known for ${api??"this api"}.`,width));for(let[rowIndex,[key,value]]of entries.entries()){let active=rowIndex===this.index,field5=api?compatFieldFor(api,key):void 0,editing=this.mode.type==="editValue"&&this.mode.key===key?this.mode.editor:void 0,note=field5?void 0:`\xB7 not used by ${api??"this api"}`;lines.push(renderKeyValueLine(theme2,{keyLabel:key,valueText:value===void 0?"not set":scalarText2(value),active,paneFocused:this.focused,editing,note,width}))}return lines.push(renderPlainLine(theme2,"+ Add Entry",{active:this.index===entries.length&&this.mode.type==="list",paneFocused:this.focused,width})),this.error&&lines.push(theme2.fg("error",truncate3(this.error,Math.max(10,width-2)))),lines}scrollWindow(){return this.mode.type==="chooseValue"?{top:1,cursor:2+this.mode.index}:{top:1,bottom:this.error?1:0,cursor:1+this.index}}handleInput(data){let kb=this.host.keybindings;if(this.mode.type==="editValue"){if(kb.matches(data,"tui.select.up")||kb.matches(data,"tui.select.down"))return;this.mode.editor.handleInput(data),this.host.refresh();return}if(this.mode.type==="chooseValue"){let mode=this.mode;if(kb.matches(data,"tui.select.up")){this.mode={...mode,index:mode.index===0?mode.options.length-1:mode.index-1},this.host.refresh();return}if(kb.matches(data,"tui.select.down")){this.mode={...mode,index:(mode.index+1)%mode.options.length},this.host.refresh();return}if(kb.matches(data,"tui.select.cancel")){this.mode={type:"list"},this.host.refresh();return}if(kb.matches(data,"tui.select.confirm")){let option=mode.options[mode.index];this.mode={type:"list"},this.writeValue(mode.key,this.parseChosen(option))}return}let next=moveSelection(kb,data,this.index,this.rowCount());if(next!==void 0){this.index=next,this.host.refresh();return}if(kb.matches(data,"tui.select.cancel")){this.host.popPane();return}if(kb.matches(data,"app.provider.removeEntry")){let entry=this.entries()[this.index];if(!entry)return;let[key]=entry;this.model.setField(["compat",key],DELETE),this.index=Math.min(this.index,this.rowCount()-2<0?0:this.rowCount()-2);return}if(kb.matches(data,"app.list.toggle")||kb.matches(data,"tui.select.confirm")){this.activateRow();return}}activateRow(){let entries=this.entries();if(this.index===entries.length){let api=this.effectiveApi();if(!api){this.fail("Set API Type first \u2014 compat fields depend on the effective api.");return}if(compatFieldsForApi(api).length===0){this.fail(`No compat fields are known for ${api}.`);return}let taken=new Set(entries.map(([key2])=>key2));this.host.pushPane(new CompatKeyPickerPane(this.host,api,taken,key2=>this.beginValueEntry(key2)));return}let[key,value]=entries[this.index],field5=this.effectiveApi()?compatFieldFor(this.effectiveApi(),key):void 0;if(!field5){this.beginJsonEdit(key,value);return}switch(field5.kind){case"boolean":this.writeValue(key,value!==!0);return;case"enum":this.mode={type:"chooseValue",key,options:field5.options,index:0},this.host.refresh();return;case"number":this.beginTextEdit(key,value);return;case"json":this.beginJsonEdit(key,value);return;case"stringMap":this.host.pushPane(new DictPane(this.host,this.model,key));return}}beginValueEntry(key){let api=this.effectiveApi(),field5=compatFieldFor(api,key);switch(field5.kind){case"boolean":this.mode={type:"chooseValue",key,options:["true","false"],index:0},this.host.refresh();return;case"enum":this.mode={type:"chooseValue",key,options:field5.options,index:0},this.host.refresh();return;case"number":this.beginTextEdit(key,void 0);return;case"json":this.beginJsonEdit(key,void 0);return;case"stringMap":this.writeValue(key,{}),this.host.pushPane(new DictPane(this.host,this.model,key));return}}beginTextEdit(key,current){let editor=new ValueEditor({onCommit:raw=>{let parsed=Number(raw.trim());if(!Number.isFinite(parsed))return this.error=`${key} must be a number.`,this.host.refresh();this.error=void 0,this.mode={type:"list"},this.writeValue(key,parsed)},onCancel:()=>{this.mode={type:"list"},this.error=void 0,this.host.refresh()}});current!==void 0&&editor.beginTweak(String(current)),editor.focused=this.focused,this.mode={type:"editValue",key,editor},this.host.refresh()}beginJsonEdit(key,current){let editor=new ValueEditor({onCommit:raw=>{let text2=raw.trim();if(!text2){this.mode={type:"list"},this.writeValue(key,DELETE);return}let shapeError=validateJsonCompatValue(key,text2);if(shapeError)return this.error=shapeError,this.host.refresh();this.error=void 0,this.mode={type:"list"},this.writeValue(key,JSON.parse(text2))},onCancel:()=>{this.mode={type:"list"},this.error=void 0,this.host.refresh()}});current!==void 0&&editor.beginTweak(JSON.stringify(current)),editor.focused=this.focused,this.mode={type:"editValue",key,editor},this.host.refresh()}parseChosen(option){return option==="true"?!0:option==="false"?!1:option}writeValue(key,value){this.model.setField(["compat",key],value)}fail(message){this.error=message,this.host.refresh()}setFocused(focused){this.focused=focused,this.mode.type==="editValue"&&(this.mode.editor.focused=focused)}isEditing(){return this.mode.type==="editValue"}hints(){return this.mode.type==="editValue"?[keyHint("tui.input.submit","save"),keyHint("tui.select.cancel","cancel")].join(" "):this.mode.type==="chooseValue"?[rawKeyHint("\u2191\u2193","move"),keyHint("tui.select.confirm","set"),keyHint("tui.select.cancel","cancel")].join(" "):[keyHint("tui.select.confirm","edit"),keyHint("app.list.toggle","toggle"),keyHint("app.provider.removeEntry","remove"),keyHint("tui.select.cancel","back")].join(" ")}},CompatKeyPickerPane=class{constructor(host,api,taken,onPick){this.crumb="compat \xB7 new entry",this.query="",this.index=0,this.focused=!1,this.host=host,this.api=api,this.taken=taken,this.onPick=onPick,this.editor=new ValueEditor({onCommit:()=>this.pickCurrent(),onCancel:()=>this.host.popPane()})}candidates(){let available=compatFieldsForApi(this.api).filter(field5=>!this.taken.has(field5.key)),query=this.query.trim();return query?fuzzyFilter(available,query,field5=>`${field5.key} ${field5.note??""}`):available}render(width){let theme2=this.host.theme,lines=[this.editor.renderLine(width)],candidates=this.candidates();candidates.length===0&&lines.push(renderInfoLine(theme2,"No remaining known fields.",width));for(let[rowIndex,field5]of candidates.entries())lines.push(renderPlainLine(theme2,field5.key,{active:rowIndex===this.index,paneFocused:this.focused,note:field5.note?`\xB7 ${field5.kind} \u2014 ${truncate3(field5.note,30)}`:`\xB7 ${field5.kind}`,width}));return lines}scrollWindow(){return{top:1,cursor:1+this.index}}pickCurrent(){let field5=this.candidates()[this.index];field5&&(this.host.popPane(),this.onPick(field5.key))}handleInput(data){let kb=this.host.keybindings;if(kb.matches(data,"tui.select.up")){let count=this.candidates().length;count>0&&(this.index=this.index===0?count-1:this.index-1),this.host.refresh();return}if(kb.matches(data,"tui.select.down")){let count=this.candidates().length;count>0&&(this.index=(this.index+1)%count),this.host.refresh();return}if(kb.matches(data,"tui.select.cancel")){this.host.popPane();return}if(kb.matches(data,"tui.select.confirm")){this.pickCurrent();return}let before=this.query;this.editor.handleInput(data),this.query=this.editor.value,this.query!==before&&(this.index=0),this.host.refresh()}setFocused(focused){this.focused=focused,this.editor.focused=focused}isEditing(){return!0}hints(){return[rawKeyHint("type","filter"),rawKeyHint("\u2191\u2193","move"),keyHint("tui.select.confirm","choose"),keyHint("tui.select.cancel","back")].join(" ")}};function baseUrlHint(api){switch(api){case"openai-responses":case"openai-completions":case"openai-codex-responses":return"baseUrl includes the version path, e.g. https://api.openai.com/v1";case"anthropic-messages":return"baseUrl is the bare origin \u2014 /v1/messages is added automatically";case"mistral-conversations":return"baseUrl is the bare origin \u2014 /v1 is added automatically";case"google-generative-ai":return"baseUrl includes the version path, e.g. https://generativelanguage.googleapis.com/v1beta";default:return}}function validateBaseUrlValue(value){let url;try{url=new URL(value)}catch{return"baseUrl must be a valid URL."}if(url.protocol!=="http:"&&url.protocol!=="https:")return`Unsupported protocol: ${url.protocol}`;if(url.username||url.password||url.hash)return"baseUrl must not contain credentials or a fragment."}var ApiAuthPane=class{constructor(host,registry){this.rows=["baseUrl","apiKey","apiType"],this.index=0,this.focused=!1,this.host=host,this.edit=new InlineEdit(()=>host.refresh()),this.registry=registry}provider(){return this.host.store.getProvider(this.host.providerId)}scrollWindow(){return{cursor:this.index,bottom:this.bottomNoteCount()}}bottomNoteCount(){let status=this.registry.getProviderAuthStatus(this.host.providerId),hint=baseUrlHint(this.provider()?.api);return(this.edit.error?1:0)+(status.configured?1:0)+1+(hint?1:0)}render(width){let theme2=this.host.theme,provider=this.provider(),lines=[];for(let[rowIndex,row]of this.rows.entries()){let active=rowIndex===this.index,value=provider?.[row==="apiType"?"api":row];lines.push(renderKeyValueLine(theme2,{keyLabel:row==="apiType"?"API Type":row,valueText:value?row==="apiKey"?maskApiKey(value):value:"not set",unset:!value,active,paneFocused:this.focused,editing:row==="apiType"?void 0:this.edit.editor(row),width}))}this.edit.error&&lines.push(theme2.fg("error",truncate3(this.edit.error,Math.max(10,width-2))));let status=this.registry.getProviderAuthStatus(this.host.providerId);status.configured&&status.source==="stored"?lines.push(renderInfoLine(theme2,"A stored credential (auth.json) takes precedence over the apiKey here.",width)):status.configured&&status.source==="environment"&&lines.push(renderInfoLine(theme2,`An environment variable (${status.label??"env"}) currently provides the key.`,width)),lines.push(renderInfoLine(theme2,"Values are stored raw; $VAR / !command references resolve at request time.",width));let hint=baseUrlHint(provider?.api);return hint&&lines.push(renderInfoLine(theme2,hint,width)),lines}handleInput(data){let kb=this.host.keybindings;if(this.edit.handleInput(data,kb))return;let next=moveSelection(kb,data,this.index,this.rows.length);if(next!==void 0){this.index=next,this.host.refresh();return}if(kb.matches(data,"tui.select.cancel")){this.host.popPane();return}if(kb.matches(data,"tui.select.confirm")){this.rows[this.index]==="apiType"?this.host.pushPane(createProviderApiPane(this.host)):this.beginEdit("tweak");return}if(isPrintableInput(data)){if(this.rows[this.index]==="apiType")return;this.beginEdit("overwrite",data);return}}beginEdit(mode,firstData){let row=this.rows[this.index];row!=="apiType"&&this.edit.begin(row,this.provider()?.[row]??"",mode,this.focused,value=>this.commit(row,value),firstData)}commit(row,raw){let value=raw.trim();if(row==="baseUrl"&&value){let invalid2=validateBaseUrlValue(value);if(invalid2)return invalid2}if(row==="baseUrl"&&!value){let builtin=builtinDefaults(this.host.providerId).baseUrl!==void 0,modelsCovered=this.host.store.getModels(this.host.providerId).every(model=>model.baseUrl!==void 0);if(!builtin&&!modelsCovered&&this.host.store.getModels(this.host.providerId).length>0)return"baseUrl cannot be removed while models rely on it."}this.host.edits.setProviderField([row],value===""?DELETE:value)}setFocused(focused){this.focused=focused,this.edit.setFocused(focused)}isEditing(){return this.edit.editing}hints(){return this.edit.editing?[keyHint("tui.input.submit","save"),keyHint("tui.select.cancel","cancel")].join(" "):[rawKeyHint("type","overwrite"),keyHint("tui.select.confirm","edit / open"),keyHint("tui.select.cancel","back")].join(" ")}};function createProviderApiPane(host){let current=()=>host.store.getProvider(host.providerId)?.api;return new ChoicePane(host,"API Type",{current,choices:()=>{let fallback=builtinDefaults(host.providerId).api,label=fallback?`not set (built-in default: ${fallback})`:"not set (models define their own)",values=[void 0,...API_TYPES],value=current();return value&&!values.includes(value)&&values.push(value),values.map(value2=>({value:value2,label:value2??label,dim:value2===void 0}))},choose:api=>{if(api===void 0){let uncovered=host.store.getModels(host.providerId).filter(model=>!model.api&&!builtinDefaults(host.providerId,model.id).api);if(uncovered.length)return uncovered.length===1?`Model "${uncovered[0].id}" resolves its API from here \u2014 give it a model-level API first.`:`${uncovered.length} ${plural(uncovered.length,"model")} resolve their API from here \u2014 give them model-level APIs first.`}host.edits.setProviderField(["api"],api??DELETE)}})}var REASONING_OPTIONS=[{label:"true",value:!0},{label:"false",value:!1},{label:"default (false)",value:void 0}];function createReasoningPane(host,model){return new ChoicePane(host,"reasoning",{current:()=>model.read().reasoning,choices:()=>REASONING_OPTIONS.map(option=>({...option,dim:option.value===void 0})),choose:value=>{model.setField(["reasoning"],value===void 0?DELETE:value)}})}var InputTypesPane=class{constructor(host,model){this.crumb="input",this.index=0,this.focused=!1,this.host=host,this.model=model}selected(){return new Set(this.model.read().input??["text"])}render(width){let theme2=this.host.theme,selected=this.selected(),lines=INPUT_TYPES.map((type,rowIndex)=>renderPlainLine(theme2,type,{checked:selected.has(type),active:rowIndex===this.index,paneFocused:this.focused,width}));return this.model.read().input===void 0&&lines.push(renderInfoLine(theme2,"Not set \u2014 the runtime default is [text].",width)),this.error&&lines.push(theme2.fg("error",truncate3(this.error,Math.max(10,width-2)))),lines}handleInput(data){let kb=this.host.keybindings,next=moveSelection(kb,data,this.index,INPUT_TYPES.length);if(next!==void 0){this.index=next,this.host.refresh();return}if(kb.matches(data,"app.list.toggle")){let type=INPUT_TYPES[this.index],selected=this.selected();if(selected.has(type)){if(selected.size===1){this.error="At least one input type must stay selected.",this.host.refresh();return}selected.delete(type)}else selected.add(type);this.error=void 0;let next2=INPUT_TYPES.filter(entry=>selected.has(entry));this.model.setField(["input"],[...next2]);return}if(kb.matches(data,"tui.select.confirm")||kb.matches(data,"tui.select.cancel")){this.host.popPane();return}}setFocused(focused){this.focused=focused}hints(){return[keyHint("app.list.toggle","toggle"),keyHint("tui.select.confirm","done"),keyHint("tui.select.cancel","back")].join(" ")}},COST_RATES=["input","output","cacheRead","cacheWrite"],CostPane=class{constructor(host,model){this.crumb="cost",this.index=0,this.focused=!1,this.host=host,this.edit=new InlineEdit(()=>host.refresh()),this.model=model}cost(){let cost=this.model.read().cost;if(cost)return{input:cost.input,output:cost.output,cacheRead:cost.cacheRead,cacheWrite:cost.cacheWrite}}render(width){let theme2=this.host.theme,cost=this.cost(),lines=[];for(let[rowIndex,rate]of COST_RATES.entries()){let value=cost?.[rate];lines.push(renderKeyValueLine(theme2,{keyLabel:rate,valueText:value===void 0?"0 (default)":`$${value} / M tokens`,unset:value===void 0,active:rowIndex===this.index,paneFocused:this.focused,editing:this.edit.editor(rate),width}))}let tiers=this.model.read().cost?.tiers;return tiers&&tiers.length>0&&lines.push(renderInfoLine(theme2,`tiers: ${tiers.length} (read-only; kept as-is)`,width)),this.edit.error&&lines.push(theme2.fg("error",truncate3(this.edit.error,Math.max(10,width-2)))),lines}handleInput(data){let kb=this.host.keybindings;if(this.edit.handleInput(data,kb))return;let next=moveSelection(kb,data,this.index,COST_RATES.length);if(next!==void 0){this.index=next,this.host.refresh();return}if(kb.matches(data,"tui.select.cancel")){this.host.popPane();return}if(kb.matches(data,"tui.select.confirm")){this.beginEdit("tweak");return}if(isPrintableInput(data)){this.beginEdit("overwrite",data);return}}beginEdit(mode,firstData){let rate=COST_RATES[this.index],current=this.cost()?.[rate];this.edit.begin(rate,current===void 0?"":String(current),mode,this.focused,value=>this.commit(rate,value),firstData)}commit(rate,raw){let value=raw.trim(),parsed=value===""?0:Number(value);if(!Number.isFinite(parsed)||parsed<0)return"cost rates must be finite non-negative numbers.";this.model.read().cost?this.model.setField(["cost",rate],parsed):this.model.setField(["cost"],{input:0,output:0,cacheRead:0,cacheWrite:0,[rate]:parsed})}setFocused(focused){this.focused=focused,this.edit.setFocused(focused)}isEditing(){return this.edit.editing}hints(){return this.edit.editing?[keyHint("tui.input.submit","save"),keyHint("tui.select.cancel","cancel")].join(" "):[rawKeyHint("type","overwrite"),keyHint("tui.select.confirm","edit"),keyHint("tui.select.cancel","back")].join(" ")}},ModelSpecificApiPane=class{constructor(host,model){this.crumb="Model-Specific API",this.rows=["baseUrl","apiType"],this.index=0,this.focused=!1,this.host=host,this.edit=new InlineEdit(()=>host.refresh()),this.model=model}inherited(key){let provider=this.host.store.getProvider(this.host.providerId),providerValue=key==="api"?provider?.api:provider?.baseUrl;if(providerValue)return{value:providerValue,via:"provider"};let current=this.model.read(),effective=key==="api"?this.host.effectiveApi(current):this.host.effectiveBaseUrl(current);return effective?{value:effective,via:"built-in"}:void 0}render(width){let theme2=this.host.theme,current=this.model.read(),lines=[];for(let[rowIndex,row]of this.rows.entries()){let active=rowIndex===this.index,key=row==="apiType"?"api":row,override=current[key],inherited=override?void 0:this.inherited(key);lines.push(renderKeyValueLine(theme2,{keyLabel:row==="apiType"?"API Type":row,valueText:override??inherited?.value??"not set",unset:!override,note:inherited?`\xB7 ${inherited.via}`:void 0,active,paneFocused:this.focused,editing:row==="baseUrl"?this.edit.editor(row):void 0,width}))}this.edit.error&&lines.push(theme2.fg("error",truncate3(this.edit.error,Math.max(10,width-2))));let hint=baseUrlHint(this.host.effectiveApi(current));return hint&&lines.push(renderInfoLine(theme2,hint,width)),lines}handleInput(data){let kb=this.host.keybindings;if(this.edit.handleInput(data,kb))return;let next=moveSelection(kb,data,this.index,this.rows.length);if(next!==void 0){this.index=next,this.host.refresh();return}if(kb.matches(data,"tui.select.cancel")){this.host.popPane();return}if(kb.matches(data,"tui.select.confirm")){this.rows[this.index]==="apiType"?this.host.pushPane(createModelApiPane(this.host,this.model)):this.beginEdit("tweak");return}if(isPrintableInput(data)){if(this.rows[this.index]==="apiType")return;this.beginEdit("overwrite",data);return}}beginEdit(mode,firstData){let base=this.model.read().baseUrl??this.inherited("baseUrl")?.value??"";this.edit.begin("baseUrl",base,mode,this.focused,value=>this.commit(value),firstData)}commit(raw){let value=raw.trim();if(value){let invalid2=validateBaseUrlValue(value);if(invalid2)return invalid2}this.model.setField(["baseUrl"],value===""?DELETE:value)}setFocused(focused){this.focused=focused,this.edit.setFocused(focused)}isEditing(){return this.edit.editing}hints(){return this.edit.editing?[keyHint("tui.input.submit","save"),keyHint("tui.select.cancel","cancel")].join(" "):[rawKeyHint("type","overwrite"),keyHint("tui.select.confirm","edit / open"),keyHint("tui.select.cancel","back")].join(" ")}};function createModelApiPane(host,model){let fallback=()=>{let provider=host.store.getProvider(host.providerId);return provider?.api??builtinDefaults(host.providerId,model.read().id,provider?.api).api};return new ChoicePane(host,"API Type",{current:()=>model.read().api,choices:()=>{let providerApi=host.store.getProvider(host.providerId)?.api,inherited=fallback(),label=providerApi?`provider: ${providerApi}`:inherited?`built-in: ${inherited}`:"no provider or built-in API",values=[void 0,...API_TYPES],current=model.read().api;return current&&!values.includes(current)&&values.push(current),values.map(value=>({value,label:value??label,dim:value===void 0}))},choose:value=>{if(value===void 0&&!fallback())return"Nothing to inherit \u2014 pick an API.";model.setField(["api"],value??DELETE)}})}var ThinkingMapPane=class{constructor(host,model){this.crumb="thinkingLevelMap",this.mode={type:"levels"},this.index=0,this.focused=!1,this.host=host,this.model=model}map(){return this.model.read().thinkingLevelMap??{}}render(width){let theme2=this.host.theme,lines=[];if(this.model.read().reasoning!==!0&&lines.push(renderInfoLine(theme2,"reasoning is not true \u2014 the map is stored but currently has no effect.",width)),this.mode.type==="levels")for(let[rowIndex,level]of THINKING_LEVELS4.entries()){let value=this.map()[level],status=value===void 0?"default":value===null?"null (hidden)":value;lines.push(renderKeyValueLine(theme2,{keyLabel:level,valueText:status,unset:value===void 0,active:rowIndex===this.index,paneFocused:this.focused,width}))}else if(this.mode.type==="choice"){lines.push(renderInfoLine(theme2,`${this.mode.level} \xB7 mapping`,width));for(let[choiceIndex,label]of["String target (provider effort)","Hidden (null)","Default (remove key)"].entries())lines.push(renderPlainLine(theme2,label,{active:choiceIndex===this.mode.index,paneFocused:this.focused,width}))}else lines.push(renderInfoLine(theme2,`${this.mode.level} \xB7 non-empty provider effort`,width)),lines.push(renderKeyValueLine(theme2,{keyLabel:this.mode.level,active:!0,paneFocused:this.focused,editing:this.editor,width}));return this.error&&lines.push(theme2.fg("error",truncate3(this.error,Math.max(10,width-2)))),lines}handleInput(data){let kb=this.host.keybindings;if(this.mode.type==="target"){if(kb.matches(data,"tui.select.up")||kb.matches(data,"tui.select.down"))return;this.editor?.handleInput(data),this.host.refresh();return}if(this.mode.type==="choice"){if(kb.matches(data,"tui.select.up")){this.mode={...this.mode,index:this.mode.index===0?2:this.mode.index-1},this.host.refresh();return}if(kb.matches(data,"tui.select.down")){this.mode={...this.mode,index:(this.mode.index+1)%3},this.host.refresh();return}if(kb.matches(data,"tui.select.cancel")){this.mode={type:"levels"},this.host.refresh();return}if(kb.matches(data,"tui.select.confirm")){let{level,index:index3}=this.mode;if(index3===0){let editor=new ValueEditor({onCommit:value=>{let target=value.trim();if(!target)return this.error="A string target must be non-empty; use Hidden for null.",this.host.refresh();this.error=void 0,this.mode={type:"levels"},this.editor=void 0,this.model.setField(["thinkingLevelMap",level],target)},onCancel:()=>{this.editor=void 0,this.mode={type:"levels"},this.host.refresh()}});this.editor=editor,editor.focused=this.focused;let existing=this.map()[level];typeof existing=="string"&&editor.beginTweak(existing),this.mode={type:"target",level},this.host.refresh();return}this.mode={type:"levels"},this.model.setField(["thinkingLevelMap",level],index3===1?null:DELETE);return}return}let next=moveSelection(kb,data,this.index,THINKING_LEVELS4.length);if(next!==void 0){this.index=next,this.host.refresh();return}if(kb.matches(data,"tui.select.confirm")){this.mode={type:"choice",level:THINKING_LEVELS4[this.index],index:0},this.host.refresh();return}if(kb.matches(data,"tui.select.cancel")){this.host.popPane();return}}setFocused(focused){this.focused=focused,this.editor&&(this.editor.focused=focused&&this.mode.type==="target")}isEditing(){return this.mode.type==="target"}hints(){return this.mode.type==="target"?[keyHint("tui.input.submit","save"),keyHint("tui.select.cancel","back")].join(" "):[rawKeyHint("\u2191\u2193","move"),keyHint("tui.select.confirm",this.mode.type==="choice"?"set":"edit"),keyHint("tui.select.cancel","back")].join(" ")}};var DEFAULT_CONTEXT_WINDOW2=128e3,DEFAULT_MAX_TOKENS2=16384,ModelFieldsPane=class{constructor(host,model){this.index=0,this.focused=!1,this.renaming=!1,this.disposed=!1,this.host=host,this.model=model;let rows=[{kind:"text",key:"id"},{kind:"text",key:"name"},{kind:"reasoning"},{kind:"subpage",key:"thinkingLevelMap"},{kind:"subpage",key:"input"},{kind:"subpage",key:"cost"},{kind:"number",key:"contextWindow"},{kind:"number",key:"maxTokens"},{kind:"subpage",key:"compat"}];model.isDraft?rows.push({kind:"modelApi"}):rows.push({kind:"builtin"},{kind:"modelApi"},{kind:"deleteModel"}),this.rows=rows}startEditingId(){this.index=0,this.beginEdit("overwrite")}draftEmpty(){return this.model.isDraft&&Object.keys(this.model.read()).length===0}render(width){let theme2=this.host.theme,current=this.model.read(),lines=[],api=this.host.effectiveApi(current);lines.push(renderInfoLine(theme2,api?`api: ${api}${current.api?" (model)":""}`:"api: none resolved \u2014 see Model-Specific API below",width));for(let[rowIndex,row]of this.rows.entries()){let active=rowIndex===this.index;lines.push(this.renderRow(row,current,active,width))}return this.error&&lines.push(theme2.fg("error",truncate3(this.error,Math.max(10,width-2)))),this.renaming&&lines.push(renderInfoLine(theme2,"Saving model id\u2026",width)),lines}scrollWindow(){return{top:1,bottom:(this.error?1:0)+(this.renaming?1:0),cursor:1+this.index}}renderRow(row,current,active,width){let theme2=this.host.theme,editing=this.editingRow===row?this.editing:void 0;switch(row.kind){case"text":{let value=current[row.key],unsetText=row.key==="id"?"required":"falls back to id";return renderKeyValueLine(theme2,{keyLabel:row.key,valueText:value??`not set (${unsetText})`,unset:!value,active,paneFocused:this.focused,editing,width})}case"reasoning":{let value=current.reasoning;return renderKeyValueLine(theme2,{keyLabel:"reasoning",valueText:value===void 0?"false (default)":String(value),unset:value===void 0,active,paneFocused:this.focused,width})}case"subpage":{let summary=this.subpageSummary(row.key,current);return renderKeyValueLine(theme2,{keyLabel:row.key,valueText:summary.text,unset:summary.unset,active,paneFocused:this.focused,width})}case"number":{let value=current[row.key],fallback=row.key==="contextWindow"?DEFAULT_CONTEXT_WINDOW2:DEFAULT_MAX_TOKENS2;return renderKeyValueLine(theme2,{keyLabel:row.key,valueText:value===void 0?`${fallback} (default)`:String(value),unset:value===void 0,active,paneFocused:this.focused,editing,width})}case"builtin":{let id=current.id,count=id?matchBuiltinModels(id,this.host.effectiveApi(current)).length:0;return renderKeyValueLine(theme2,{valueText:"Use Built-in Data",active,paneFocused:this.focused,note:id?`\xB7 ${count} ${plural(count,"candidate")}`:"\xB7 set id first",width})}case"modelApi":return renderKeyValueLine(theme2,{valueText:"Model-Specific API",active,paneFocused:this.focused,note:`\xB7 ${this.modelApiSummary(current)}`,width});case"deleteModel":return renderKeyValueLine(theme2,{valueText:"Delete Model",active,paneFocused:this.focused,width})}}modelApiSummary(current){let overrides=[current.baseUrl?"baseUrl":"",current.api?"API Type":""].filter(Boolean);if(overrides.length>0)return overrides.join(" + ");let provider=this.host.store.getProvider(this.host.providerId);return provider?.api||provider?.baseUrl?"provider defaults":this.host.effectiveApi(current)||this.host.effectiveBaseUrl(current)?"built-in defaults":"not set"}subpageSummary(key,current){switch(key){case"thinkingLevelMap":{let map=current.thinkingLevelMap,count=map?Object.keys(map).length:0;return count>0?{text:`${count} ${plural(count,"mapping")}`,unset:!1}:{text:"default",unset:!0}}case"input":return current.input?{text:`[${current.input.join(", ")}]`,unset:!1}:{text:"[text] (default)",unset:!0};case"cost":{let cost=current.cost;return cost?{text:`$${cost.input} / $${cost.output} in/out`,unset:!1}:{text:"all 0 (default)",unset:!0}}case"compat":{let compat=current.compat,count=compat?Object.keys(compat).length:0;if(count>0)return{text:`${count} ${count===1?"entry":"entries"}`,unset:!1};let inherited=this.host.store.getProvider(this.host.providerId)?.compat,inheritedCount=inherited?Object.keys(inherited).length:0;return inheritedCount>0?{text:`${inheritedCount} from provider`,unset:!0}:{text:"none",unset:!0}}}}handleInput(data){if(this.renaming||this.disposed)return;let kb=this.host.keybindings;if(this.editing){if(kb.matches(data,"tui.select.up")||kb.matches(data,"tui.select.down"))return;this.editing.handleInput(data),this.host.refresh();return}let next=moveSelection(kb,data,this.index,this.rows.length);if(next!==void 0){this.index=next,this.host.refresh();return}if(kb.matches(data,"tui.select.cancel")){if(!this.model.isDraft){this.host.popPane();return}if(this.draftEmpty()){this.host.discardModelDraft();return}let label=this.model.read().name??this.model.read().id??"New Model";this.host.confirm(`Discard the new model "${label}"? Its fields are not saved.`,"Discard Model",()=>this.host.discardModelDraft());return}if(kb.matches(data,"app.list.toggle")){this.toggleRow();return}if(kb.matches(data,"tui.select.confirm")){this.enterRow();return}if(isPrintableInput(data)){this.overwriteRow(data);return}}toggleRow(){if(this.rows[this.index].kind!=="reasoning")return;let current=this.model.read().reasoning;this.model.setField(["reasoning"],current!==!0)}enterRow(){let row=this.rows[this.index];switch(row.kind){case"text":case"number":this.beginEdit("tweak");return;case"reasoning":this.host.pushPane(createReasoningPane(this.host,this.model));return;case"subpage":this.pushSubpage(row.key);return;case"modelApi":this.host.pushPane(new ModelSpecificApiPane(this.host,this.model));return;case"builtin":{if(!this.model.read().id){this.host.notify("Set the model id first.","warning");return}this.host.pushPane(new BuiltinCandidatesPane(this.host,this.model));return}case"deleteModel":{let id=this.model.read().id;if(!id)return;if(this.host.isCurrentModel(id)){this.host.notify("The current model cannot be deleted; switch models with /model first.","error");return}this.host.confirm(`Delete model "${id}" from ${this.host.providerId}?`,"Delete Model",()=>{this.host.edits.removeModel(id),this.host.onModelRemoved(id)});return}}}overwriteRow(data){let row=this.rows[this.index];if(row.kind==="text"||row.kind==="number"){this.beginEdit("overwrite",data);return}}beginEdit(mode,firstData){let row=this.rows[this.index];if(row.kind!=="text"&&row.kind!=="number")return;let current=this.model.read()[row.key],editor=new ValueEditor({onCommit:value=>this.commitText(row,value),onCancel:()=>{if(this.editing=void 0,this.editingRow=void 0,this.error=void 0,this.draftEmpty()){this.host.discardModelDraft();return}this.host.refresh()}});this.editing=editor,this.editingRow=row,editor.focused=this.focused,mode==="overwrite"?editor.beginOverwrite(firstData):editor.beginTweak(current===void 0?"":String(current)),this.host.refresh()}commitText(row,raw){let value=raw.trim(),finish=error=>{if(this.error=error,error){this.host.refresh();return}this.editing=void 0,this.editingRow=void 0,this.host.refresh()};if(row.key==="id"){if(!value){finish("id is required and cannot be empty.");return}if(this.model.isDraft){this.model.setField(["id"],value),finish(this.host.commitModelDraft());return}let current=this.model.read().id;if(!current){finish("Missing current id.");return}if(value===current){finish();return}if(this.host.isCurrentModel(current)){finish("The current model's id cannot be renamed; switch models with /model first.");return}if(this.host.store.getModel(this.host.providerId,value)){finish(`Model "${value}" already exists.`);return}this.renaming=!0,this.host.refresh(),this.model.rename(value).then(error=>{this.renaming=!1,this.disposed||finish(error)},error=>{this.renaming=!1,this.disposed||finish(error instanceof Error?error.message:String(error))});return}if(row.key==="name"){this.model.setField(["name"],value===""?DELETE:value),finish();return}if(value===""){this.model.setField([row.key],DELETE),finish();return}let parsed=Number(value);if(!Number.isSafeInteger(parsed)||parsed<=0){finish(`${row.key} must be a positive integer.`);return}this.model.setField([row.key],parsed),finish()}pushSubpage(key){switch(key){case"thinkingLevelMap":this.host.pushPane(new ThinkingMapPane(this.host,this.model));return;case"input":this.host.pushPane(new InputTypesPane(this.host,this.model));return;case"cost":this.host.pushPane(new CostPane(this.host,this.model));return;case"compat":this.host.pushPane(new CompatPane(this.host,this.model));return}}setFocused(focused){this.focused=focused,this.editing&&(this.editing.focused=focused)}isEditing(){return this.editing!==void 0||this.renaming}dispose(){this.disposed=!0}hints(){return this.editing?[keyHint("tui.input.submit","save"),keyHint("tui.select.cancel","cancel")].join(" "):[rawKeyHint("type","overwrite"),keyHint("tui.select.confirm","edit / open"),keyHint("app.list.toggle","toggle"),keyHint("tui.select.cancel",this.model.isDraft?"discard":"back")].join(" ")}};var LEFT_WIDTH_MIN=16,LEFT_WIDTH_MAX=40,BODY_ROWS=14,MIN_WIDTH=56;function padTo(line,width){let missing=width-visibleWidth(line);return missing>0?line+" ".repeat(missing):line}function leftItemKey(item){return item?item.kind==="model"?`model:${item.modelId}`:item.kind:""}var ProviderEditorScreen=class{constructor(tui,theme2,keybindings,done,options){this.leftItems=[],this.leftIndex=0,this.focusPane="left",this.stack=[],this.disposed=!1,this._focused=!1,this.tui=tui,this.theme=theme2,this.keybindings=keybindings,this.done=done,this.options=options,this.edits=new ProviderEdits(options.store,options.providerId,options.refresher,()=>this.refresh()),this.host=this.createHost(),this.rebuildLeftItems(),this.resetRightStack()}get focused(){return this._focused}set focused(value){this._focused=value,this.topPane()?.setFocused(value&&this.focusPane==="right")}invalidate(){this.cache=void 0}dispose(){if(!this.disposed){this.disposed=!0;for(let pane of this.stack)pane.dispose?.();this.stack=[],hasProviderSettings(this.options.store.getProvider(this.options.providerId))||this.options.store.discardProviderDraft(this.options.providerId)}}render(width){if(this.cache&&this.cache.width===width)return this.cache.lines;let lines=this.renderFrame(width);return this.cache={width,lines},lines}handleInput(data){if(this.focusPane==="right"){let pane=this.topPane();if(pane&&!pane.isEditing?.()&&this.keybindings.matches(data,"app.provider.switchPaneLeft")){pane.setFocused(!1),this.focusPane="left",this.refresh();return}pane?.handleInput(data);return}let kb=this.keybindings;if(kb.matches(data,"tui.select.up")){this.moveLeft(-1);return}if(kb.matches(data,"tui.select.down")){this.moveLeft(1);return}if(kb.matches(data,"app.provider.switchPaneRight")){this.activateLeftItem("inspect");return}if(kb.matches(data,"tui.select.confirm")){this.activateLeftItem("activate");return}kb.matches(data,"tui.select.cancel")&&this.done("back")}syncFromStore(){if(this.disposed||this.edits.renaming)return;let selected=this.leftItems[this.leftIndex],selectedKey=leftItemKey(selected);this.rebuildLeftItems();let nextIndex=this.leftItems.findIndex(item=>leftItemKey(item)===selectedKey);this.leftIndex=nextIndex>=0?nextIndex:Math.min(this.leftIndex,this.selectableIndex(0)),nextIndex<0&&selected?.kind==="model"&&this.resetRightStack(),this.refresh()}rebuildLeftItems(){let items=[{kind:"apiAuth"},{kind:"fetch"},{kind:"separator"}];for(let model of this.options.store.getModels(this.options.providerId))items.push({kind:"model",modelId:model.id});this.draft&&items.push({kind:"draft"}),items.push({kind:"separator"},{kind:"addModel"},{kind:"deleteProvider"}),this.leftItems=items}selectableIndex(start){let index3=this.leftItems.findIndex((item,i)=>i>=start&&item.kind!=="separator");return index3>=0?index3:0}moveLeft(delta){let selectable=this.leftItems.map((item,index3)=>({item,index:index3})).filter(entry=>entry.item.kind!=="separator");if(selectable.length===0)return;let position=selectable.findIndex(entry=>entry.index===this.leftIndex),next=selectable[(position+delta+selectable.length)%selectable.length];next.index!==this.leftIndex&&(this.leftIndex=next.index,this.resetRightStack(),this.refresh())}activateLeftItem(via){let item=this.leftItems[this.leftIndex];if(item)switch(item.kind){case"apiAuth":case"model":case"draft":this.focusPane="right",this.topPane()?.setFocused(this._focused),this.refresh();return;case"fetch":if(this.focusPane="right",via==="activate"){let pane=this.topPane();pane instanceof FetchModelsPane&&pane.start()}this.topPane()?.setFocused(this._focused),this.refresh();return;case"addModel":{if(via==="inspect"){this.focusPane="right",this.topPane()?.setFocused(this._focused),this.refresh();return}this.draft||(this.draft=this.edits.draft(),this.rebuildLeftItems());let draftIndex=this.leftItems.findIndex(entry=>entry.kind==="draft");draftIndex>=0&&(this.leftIndex=draftIndex),this.resetRightStack(),this.focusPane="right";let pane=this.topPane();pane?.setFocused(this._focused),pane instanceof ModelFieldsPane&&!this.draft.read().id&&pane.startEditingId(),this.refresh();return}case"deleteProvider":{if(via==="inspect"){this.focusPane="right",this.topPane()?.setFocused(this._focused),this.refresh();return}if(this.host.isCurrentProvider()){this.host.notify("The current model's provider cannot be deleted; switch models with /model first.","error");return}let builtin=isBuiltinProviderId(this.options.providerId);this.host.confirm(`Delete provider "${this.options.providerId}" from models.json?`+(builtin?" The built-in catalog remains and its models may reappear.":"")+" Stored credentials in auth.json are kept.","Delete Provider",()=>{this.edits.removeProvider(),this.done("deleted")});return}default:return}}renderLeft(width){let theme2=this.theme,focused=this.focusPane==="left",rows=[],renderRow=index3=>{let item=this.leftItems[index3];return item.kind==="separator"?theme2.fg("borderMuted",` ${"\u2500".repeat(Math.max(1,width-4))}`):this.renderLeftItem(item,index3===this.leftIndex,focused,width)};if(this.leftItems.length<=BODY_ROWS)for(let index3=0;index3<this.leftItems.length;index3++)rows.push(renderRow(index3));else{let slots=BODY_ROWS-1,start=Math.max(0,Math.min(this.leftIndex-Math.floor(slots/2),this.leftItems.length-slots));for(let index3=start;index3<start+slots;index3++)rows.push(renderRow(index3));let selectable=this.leftItems.filter(item=>item.kind!=="separator"),position=selectable.indexOf(this.leftItems[this.leftIndex]);rows.push(theme2.fg("dim",` (${position+1}/${selectable.length})`))}for(;rows.length<BODY_ROWS;)rows.push("");return rows}leftItemContent(item){let store=this.options.store,text2,note;switch(item.kind){case"apiAuth":text2="API Auth";break;case"fetch":text2="Fetch Models",note=this.fetchStatus;break;case"model":{let model=store.getModel(this.options.providerId,item.modelId);text2=model?modelDisplayName(model):item.modelId;break}case"draft":{text2=this.draft?.read().name??this.draft?.read().id??"New Model",note="\xB7 draft";break}case"addModel":text2="+ Add Model";break;case"deleteProvider":text2="Delete Provider";break;default:text2=""}let dim=item.kind==="draft"&&!this.draft?.read().name&&!this.draft?.read().id;return{text:text2,note,dim}}renderLeftItem(item,active,focused,width){let theme2=this.theme,lit=active&&focused,marker=lit?theme2.fg("accent",`${CURSOR2} `):" ",style=(text3,dim2=!1)=>theme2.fg(lit?"accent":dim2?"dim":"text",text3),{text:label,note,dim}=this.leftItemContent(item),text2=label;if(item.kind==="model"||item.kind==="draft"){let budget=Math.max(8,width-2-(note?visibleWidth(note)+1:0));text2=truncateMiddle2(text2,budget)}let noteText=note?theme2.fg("dim",` ${note}`):"";return truncateToWidth(marker+style(text2,dim)+noteText,width)}topPane(){return this.stack[this.stack.length-1]}pushPane(pane){this.topPane()?.setFocused(!1),this.focusPane="right",this.stack.push(pane),pane.setFocused(this._focused&&this.focusPane==="right"),this.refresh()}popPane(){if(this.stack.length<=1){this.topPane()?.setFocused(!1),this.focusPane="left",this.refresh();return}let pane=this.stack.pop();pane?.setFocused(!1),pane?.dispose?.(),this.topPane()?.setFocused(this._focused&&this.focusPane==="right"),this.refresh()}resetRightStack(){for(let pane of this.stack)pane.dispose?.();let item=this.leftItems[this.leftIndex];this.stack=[this.createBasePane(item)],this.topPane()?.setFocused(this._focused&&this.focusPane==="right")}createBasePane(item){switch(item?.kind){case"apiAuth":return new ApiAuthPane(this.host,this.options.registry);case"fetch":return new FetchModelsPane(this.host);case"model":return new ModelFieldsPane(this.host,this.persistedHandle(item.modelId));case"draft":return new ModelFieldsPane(this.host,this.draft);case"addModel":return new InfoPane(this.host,["Press Enter to create a model.","A draft is kept in memory until its id is set; Esc on the draft discards it."],()=>this.activateLeftItem("activate"));case"deleteProvider":return new InfoPane(this.host,["Press Enter to delete this provider from models.json."],()=>this.activateLeftItem("activate"));default:return new InfoPane(this.host,[])}}persistedHandle(modelId){return this.edits.model(modelId,(oldId,newId)=>{let selected=this.leftItems[this.leftIndex];selected?.kind==="model"&&selected.modelId===oldId&&(selected.modelId=newId),this.syncFromStore()})}createHost(){let store=this.options.store,providerId=this.options.providerId;return{tui:this.tui,theme:this.theme,keybindings:this.keybindings,store,edits:this.edits,providerId,pushPane:pane=>this.pushPane(pane),popPane:()=>this.popPane(),refresh:()=>this.refresh(),notify:(message,type)=>this.options.notify(message,type),effectiveApi:model=>effectiveModelSettings(providerId,store.getProvider(providerId),model).api,effectiveBaseUrl:model=>effectiveModelSettings(providerId,store.getProvider(providerId),model).baseUrl,commitModelDraft:()=>this.commitModelDraft(),discardModelDraft:()=>this.discardModelDraft(),isCurrentModel:modelId=>this.options.currentModel?.provider===providerId&&this.options.currentModel.id===modelId,isCurrentProvider:()=>this.options.currentModel?.provider===providerId,setFetchStatus:status=>{this.fetchStatus=status,this.refresh()},runFetch:signal=>fetchProviderModels(this.options,signal),importModels:async(models,signal)=>{let error=await importProviderModels({...this.options,edits:this.edits},models,signal);return this.disposed||this.syncFromStore(),error},confirm:(message,actionLabel,action)=>this.pushPane(new ConfirmPane(this.host,message,actionLabel,action)),onModelRemoved:()=>{for(this.rebuildLeftItems(),this.leftIndex=Math.min(this.leftIndex,this.leftItems.length-1);this.leftIndex>0&&this.leftItems[this.leftIndex]?.kind==="separator";)this.leftIndex--;this.leftItems[this.leftIndex]?.kind==="separator"&&(this.leftIndex=this.selectableIndex(0)),this.focusPane="left",this.resetRightStack(),this.refresh()}}}discardModelDraft(){if(!this.draft)return;this.draft=void 0,this.rebuildLeftItems();let addIndex=this.leftItems.findIndex(item=>item.kind==="addModel");this.leftIndex=addIndex>=0?addIndex:this.selectableIndex(0),this.focusPane="left",this.resetRightStack(),this.refresh()}commitModelDraft(){let draft=this.draft;if(!draft)return"No model draft.";let error=this.edits.commitDraft(draft);if(error)return error;let id=draft.read().id.trim();this.draft=void 0,this.rebuildLeftItems();let index3=this.leftItems.findIndex(item=>item.kind==="model"&&item.modelId===id);index3>=0&&(this.leftIndex=index3),this.resetRightStack(),this.refresh()}refresh(){this.invalidate(),this.tui.requestRender()}renderFrame(width){let theme2=this.theme,border=new DynamicBorder(text2=>theme2.fg("border",text2)).render(width)[0];if(width<MIN_WIDTH)return[border,truncateToWidth(theme2.fg("warning",` /provider needs at least ${MIN_WIDTH} columns`),width),border];let leftWidth=this.computeLeftWidth(width),rightWidth=width-leftWidth-3,separator=theme2.fg("border"," \u2502 "),title=this.renderTitle(width),crumb=truncateToWidth(this.theme.fg("muted",this.topPane()?.crumb??""),rightWidth),leftLines=this.renderLeft(leftWidth),pane=this.topPane(),paneLines=pane?windowLines(theme2,pane.render(rightWidth),BODY_ROWS-1,pane.scrollWindow?.()):[],rightLines=[crumb,...paneLines],body2=[];for(let row=0;row<BODY_ROWS;row++){let left=padTo(truncateToWidth(leftLines[row]??"",leftWidth),leftWidth),right=truncateToWidth(rightLines[row]??"",rightWidth);body2.push(left+separator+right)}let footerLines=this.renderFooter(width);return[border,title,border,...body2,border,...footerLines,border]}computeLeftWidth(width){let longest=12;for(let item of this.leftItems){if(item.kind==="separator")continue;let{text:text2,note}=this.leftItemContent(item),label=text2+(note?` ${note}`:"");longest=Math.max(longest,visibleWidth(label))}let fit=Math.max(LEFT_WIDTH_MIN,Math.min(LEFT_WIDTH_MAX,longest+2));return Math.min(fit,Math.max(LEFT_WIDTH_MIN,Math.floor(width*.45)))}renderTitle(width){let theme2=this.theme,title=` /provider \xB7 ${this.options.providerId}`;return isBuiltinProviderId(this.options.providerId)&&(title+=" \xB7 overlays built-in catalog"),truncateToWidth(theme2.fg("accent",theme2.bold(title)),width)}renderFooter(width){if(this.focusPane==="right"){let hints2=[this.topPane()?.hints()??"",keyHint("app.provider.switchPaneLeft","focus left")].filter(Boolean).join(" ");return[truncateToWidth(hints2,width)]}let hints=[rawKeyHint("\u2191\u2193","move"),keyHint("tui.select.confirm",this.leftActivateLabel()),keyHint("app.provider.switchPaneRight","focus right"),keyHint("tui.select.cancel","back")].join(" ");return[truncateToWidth(hints,width)]}leftActivateLabel(){switch(this.leftItems[this.leftIndex]?.kind){case"fetch":return"fetch";case"addModel":return"create";case"deleteProvider":return"delete";default:return"open"}}};function modelDisplayName(model){return model.name??model.id}var LIST_ROWS=12,ProviderListScreen=class{constructor(tui,theme2,keybindings,done,store){this.mode="list",this.query="",this.index=0,this.active=!1,this.tui=tui,this.theme=theme2,this.keybindings=keybindings,this.done=done,this.store=store,this.input=new ValueEditor({onCommit:()=>this.confirm(),onCancel:()=>this.cancel()})}get focused(){return this.active}set focused(value){this.active=value,this.input.focused=value}invalidate(){}filtered(){let ids=this.store.getProviderIds();return this.query.trim()?fuzzyFilter(ids,this.query,id=>id):ids}render(width){let theme2=this.theme,border=new DynamicBorder(text2=>theme2.fg("border",text2)).render(width)[0]??"",lines=[border,truncateToWidth(theme2.fg("accent",theme2.bold(" /provider \u2014 models.json providers")),width),border,renderKeyValueLine(theme2,{keyLabel:this.mode==="list"?"Search":"Provider id",active:!1,paneFocused:this.active,editing:this.input,width}),""],area=[];if(this.mode==="list"){let entries=this.filtered(),total=entries.length+1;this.index=Math.min(this.index,total-1);let rows=[];for(let row=0;row<total;row++){let id=entries[row-1],provider=id===void 0?void 0:this.store.getProvider(id),note=id===void 0?void 0:provider?[`${String(provider.models?.length??0)} ${plural(provider.models?.length??0,"model")}`,provider.api].filter(Boolean).join(" \xB7 "):"pending deletion";rows.push(renderPlainLine(theme2,row===0?"+ Add Provider":id,{active:row===this.index,paneFocused:this.active,note,width}))}entries.length===0&&rows.push(renderInfoLine(theme2,this.query?"No matching providers.":"No providers yet.",width)),area.push(...windowLines(theme2,rows,LIST_ROWS,{cursor:this.index}))}else this.error&&area.push(truncateToWidth(theme2.fg("error",this.error),width));for(;area.length<LIST_ROWS;)area.push("");let hints=this.mode==="newProvider"?[keyHint("tui.input.submit","create"),keyHint("tui.select.cancel","cancel")]:[rawKeyHint("type","filter"),rawKeyHint("\u2191\u2193","move"),keyHint("tui.select.confirm","open"),keyHint("tui.select.cancel","close")];return[...lines,...area,border,truncateToWidth(hints.join(" "),width),border]}handleInput(data){let kb=this.keybindings;if(kb.matches(data,"tui.select.cancel")){this.cancel();return}if(this.mode==="list"){let total=this.filtered().length+1;if(kb.matches(data,"tui.select.up"))this.index=(this.index+total-1)%total;else if(kb.matches(data,"tui.select.down"))this.index=(this.index+1)%total;else if(kb.matches(data,"tui.select.confirm")){this.confirm();return}else{let previous=this.query;this.input.handleInput(data),this.query=this.input.value,this.query!==previous&&(this.index=this.query&&this.filtered().length>0?1:0)}}else this.input.handleInput(data);this.tui.requestRender()}confirm(){if(this.mode==="newProvider"){let id=this.input.value.trim();if(!id)this.error="Provider id must be non-empty.";else if(this.store.getProviderIds().includes(id))this.error="This provider id already exists.";else{this.store.ensureProviderView(id),this.done({kind:"open",providerId:id});return}}else if(this.index===0)this.mode="newProvider",this.error=void 0,this.input.reset(this.query);else{let id=this.filtered()[this.index-1];id&&this.done({kind:"open",providerId:id})}this.tui.requestRender()}cancel(){if(this.mode==="list"){this.done({kind:"close"});return}this.mode="list",this.error=void 0,this.input.reset(this.query),this.tui.requestRender()}};var ProviderTuiSession=class extends Container{constructor(tui){super(),this.controller=new AbortController,this.active=!1,this.tui=tui}get signal(){return this.controller.signal}get focused(){return this.active}set focused(value){this.active=value,this.screen&&isFocusable(this.screen)&&(this.screen.focused=value)}setScreen(screen){if(this.signal.aborted){screen.dispose?.();return}this.disposeScreen(),this.screen=screen,this.clear(),this.addChild(screen),this.tui.setFocus(this),this.tui.requestRender()}handleInput(data){this.signal.aborted||this.screen?.handleInput?.(data)}dispose(){this.signal.aborted||(this.controller.abort(),this.disposeScreen(),this.clear())}disposeScreen(){let previous=this.screen;this.screen=void 0,previous&&isFocusable(previous)&&(previous.focused=!1),previous?.dispose?.()}};var SavingScreen=class extends Container{constructor(theme2,keybindings,onCancel){super(),this.keybindings=keybindings,this.onCancel=onCancel,this.addChild(new DynamicBorder(text2=>theme2.fg("border",text2))),this.addChild(new Text(theme2.fg("muted","Saving provider changes and updating models\u2026"),1,1)),this.addChild(new Text(keyHint("tui.select.cancel","return to providers"),1,0)),this.addChild(new DynamicBorder(text2=>theme2.fg("border",text2)))}handleInput(data){this.keybindings.matches(data,"tui.select.cancel")&&this.onCancel()}};function createProviderErrorScreen(tui,done,error){return new ExtensionSelectorComponent("models.json cannot be edited",["Back"],done,done,{tui,description:`${truncate3(error,2400)}
|
|
2073
|
+
`;await writeFile3(tempPath,candidate,{encoding:"utf8",mode:384});let validationError=(await ModelConfig.load(tempPath)).getError();if(validationError)return{kind:"invalid",error:validationError};let latest=await readDocument(this.path);if(latest.exists!==disk.exists||latest.rawText!==disk.rawText)throw new Error("models.json changed while saving; the edits were kept for retry.");return!this.backedUp&&disk.exists&&disk.rawText!==void 0&&(await writeFile3(`${this.path}.bak`,disk.rawText,{encoding:"utf8",mode:384}),this.backedUp=!0),assertLock(),await rename(tempPath,this.path),this.baseline=working,settle(),{kind:"saved",applied:batch.length}}finally{await rm(tempPath,{force:!0}).catch(()=>{})}}};function ensureProvider(doc,providerId){let existing=Object.hasOwn(doc.providers,providerId)?doc.providers[providerId]:void 0;if(existing)return existing;let created={};return Object.defineProperty(doc.providers,providerId,{value:created,writable:!0,enumerable:!0,configurable:!0}),created}function applyOp(doc,op){switch(op.kind){case"set":{let provider=ensureProvider(doc,op.providerId);if(op.modelId===void 0){setPath(provider,op.path,op.value);return}let model=(Array.isArray(provider.models)?provider.models:[]).find(entry=>entry.id===op.modelId);model&&setPath(model,op.path,op.value);return}case"addModel":{let provider=ensureProvider(doc,op.providerId),models=Array.isArray(provider.models)?provider.models:[],index3=models.findIndex(entry=>entry.id===op.model.id),clone=structuredClone(op.model);index3>=0?models[index3]=clone:models.push(clone),provider.models=models;return}case"removeModel":{let provider=doc.providers[op.providerId],models=Array.isArray(provider?.models)?provider.models:void 0;if(!provider||!models)return;provider.models=models.filter(entry=>entry.id!==op.modelId);return}case"renameModel":{let provider=doc.providers[op.providerId],models=Array.isArray(provider?.models)?provider.models:void 0;if(!models)return;let model=models.find(entry=>entry.id===op.oldId);model&&!models.some(entry=>entry.id===op.newId)&&(model.id=op.newId);return}case"removeProvider":{delete doc.providers[op.providerId];return}}}function pruneEmptyNewProviders(working,disk){for(let[providerId,provider]of Object.entries(working.providers))Object.hasOwn(disk.providers,providerId)||isPlainObject2(provider)&&Object.keys(provider).length===0&&delete working.providers[providerId]}var RefreshCoordinator=class{constructor(runtime){this.pending=new Map,this.changed=new Set,this.revision=0,this.runtime=runtime}touch(providerId){this.pending.set(providerId,++this.revision),this.changed.add(providerId)}get touchedProviders(){return[...this.changed]}async refreshNow(providerId,signal){return this.run([providerId],signal)}async flush(signal){let providers=[...this.pending.keys()];return providers.length===0?{ok:!0,aborted:!1,errors:[]}:this.run(providers,signal)}async run(providers,signal){let revisions=new Map(providers.map(id=>[id,this.pending.get(id)])),combined=AbortSignal.any([...signal?[signal]:[],AbortSignal.timeout(REFRESH_TIMEOUT_MS)]),errors=[];try{let result2=await this.runtime.refresh({allowNetwork:!1,providers,signal:combined});for(let[providerId,error]of result2.errors)errors.push(`${providerId}: ${formatError2(error)}`);let configError=this.runtime.getError();configError&&errors.push(configError);let aborted=result2.aborted||combined.aborted;aborted&&errors.length===0&&errors.push("Refresh was cancelled or timed out.");let ok=errors.length===0&&!aborted;if(ok)for(let id of providers)this.pending.get(id)===revisions.get(id)&&this.pending.delete(id);return{ok,aborted,errors}}catch(error){return errors.push(formatError2(error)),{ok:!1,aborted:combined.aborted,errors}}}};function registerListKeybindings(){registerKeybindings({"app.list.toggle":{defaultKeys:"space",description:"Toggle selected list item"}})}registerListKeybindings();registerKeybindings({"app.provider.switchPaneLeft":{defaultKeys:"left",description:"/provider: focus the left pane"},"app.provider.switchPaneRight":{defaultKeys:"right",description:"/provider: focus the right pane"},"app.provider.removeEntry":{defaultKeys:"ctrl+x",description:"/provider: remove the selected compat or dictionary entry"}});async function probeProviderModels(opts){let baseUrl;try{baseUrl=new URL(opts.baseUrl)}catch{return{ok:!1,error:"Base URL is not a valid URL."}}if(baseUrl.protocol!=="http:"&&baseUrl.protocol!=="https:")return{ok:!1,error:`Unsupported protocol: ${baseUrl.protocol}`};if(baseUrl.username||baseUrl.password||baseUrl.hash)return{ok:!1,error:"Base URL must not contain credentials or a fragment."};if(opts.signal?.aborted)return{ok:!1,error:"Cancelled."};let controller=new AbortController,timeoutMs=opts.timeoutMs??PROBE_LIMITS.timeoutMs,timer=setTimeout(()=>controller.abort(),timeoutMs),onOuterAbort=()=>controller.abort();opts.signal?.addEventListener("abort",onOuterAbort,{once:!0});let doFetch=opts.fetch??globalThis.fetch,getPage=async(url,headers)=>{let response=await doFetch(url,{method:"GET",headers,signal:controller.signal});if(!response.ok){let body2=await readResponseTextBounded(response,{maxBytes:PROBE_LIMITS.maxErrorBytes,signal:controller.signal});return{ok:!1,status:response.status,error:`HTTP ${response.status}${body2?`: ${safeErrorText(body2,opts.auth).slice(0,PROBE_LIMITS.maxErrorChars)}`:""}`}}let text2=await readResponseTextBounded(response,{maxBytes:PROBE_LIMITS.maxBodyBytes,overflowMessage:`Response exceeds ${PROBE_LIMITS.maxBodyBytes} bytes.`,signal:controller.signal});try{return{ok:!0,json:JSON.parse(text2)}}catch{return{ok:!1,error:"Model catalog response is not JSON."}}};try{let url=modelCatalogUrl(baseUrl,opts.api),headers=buildHeaders(opts.auth,opts.api),page=await getPage(url,headers),retry=page.ok?void 0:openAIStyleRetry(baseUrl,opts.auth,opts.api,{url,headers,status:page.status});if(!page.ok&&retry){let retried=await getPage(retry.url,retry.headers);if(!retried.ok)return{ok:!1,error:safeErrorText(`${url.href} \u2192 HTTP ${page.status}; OpenAI-style retry ${retry.url.href} \u2192 ${retried.error}`,opts.auth)};({url,headers}=retry),page=retried}if(!page.ok)return{ok:!1,error:page.error};let models=parseCatalogModels(page.json);if(models===null)return{ok:!1,error:"JSON has no supported OpenAI-style data[] or models[] catalog with model ids. Add models manually if this endpoint uses another catalog format."};let json=page.json;for(let pages=1;opts.api==="anthropic-messages"&&pages<PROBE_LIMITS.maxPages&&models.length<PROBE_LIMITS.maxModels;pages++){let cursor=nextPageCursor(json);if(!cursor)break;let nextUrl=new URL(url.href);nextUrl.searchParams.set("after_id",cursor),nextUrl.searchParams.set("limit","1000");let next=await getPage(nextUrl,headers),more=next.ok?parseCatalogModels(next.json):null;if(!next.ok||!more||(models.push(...more),nextPageCursor(next.json)===cursor))break;json=next.json}let sorted=dedupeSort(models),truncated=sorted.length>PROBE_LIMITS.maxModels||declaresMorePages(json);return{ok:!0,models:sorted.slice(0,PROBE_LIMITS.maxModels),truncated}}catch(error){return controller.signal.aborted?{ok:!1,error:opts.signal?.aborted?"Cancelled.":`Timed out after ${timeoutMs}ms.`}:{ok:!1,error:safeErrorText(formatError2(error),opts.auth)}}finally{clearTimeout(timer),opts.signal?.removeEventListener("abort",onOuterAbort)}}function modelCatalogUrl(base,api){let url=new URL(base.href),path14=url.pathname.replace(/\/+$/,"");return url.pathname=api==="anthropic-messages"&&!path14.endsWith("/v1")?`${path14}/v1/models`:`${path14}/models`,url}function openAIStyleRetry(base,auth,api,first){if(api!=="anthropic-messages"||![401,403,404].includes(first.status??0)||Object.keys(auth?.headers??{}).some(key=>key.toLowerCase()==="authorization"))return;let root=new URL(base.href);root.pathname=root.pathname.replace(/\/+$/,"").replace(/\/anthropic$/i,"");let url=modelCatalogUrl(root,api),headers=buildHeaders(auth,void 0);return url.href===first.url.href&&headers.get("authorization")===first.headers.get("authorization")?void 0:{url,headers}}function safeErrorText(text2,auth){for(let value of[auth?.apiKey,...Object.values(auth?.headers??{})]){if(typeof value!="string"||!value)continue;text2=text2.replaceAll(value,"[redacted]");let token=value.replace(/^Bearer\s+/i,"");token!==value&&token&&(text2=text2.replaceAll(token,"[redacted]"))}return stripTerminalSequences(text2)}function buildHeaders(auth,api){let headers=new Headers;headers.set("accept","application/json");let configured=auth?.headers??{};api==="anthropic-messages"&&headers.set("anthropic-version","2023-06-01");let hasAuthorization=!1;for(let[key,value]of Object.entries(configured))key.toLowerCase()==="authorization"&&(hasAuthorization=!0),typeof value=="string"?headers.set(key,value):value===null&&headers.delete(key);if(!auth?.apiKey||hasAuthorization)return headers;let lower=name=>Object.keys(configured).some(key=>key.toLowerCase()===name);return api==="anthropic-messages"?(auth.apiKey.includes("sk-ant-oat")?headers.set("authorization",`Bearer ${auth.apiKey}`):(lower("x-api-key")||headers.set("x-api-key",auth.apiKey),lower("anthropic-version")||headers.set("anthropic-version","2023-06-01")),headers):api==="google-generative-ai"||api==="google-vertex"?(lower("x-goog-api-key")||headers.set("x-goog-api-key",auth.apiKey),headers):(headers.set("authorization",`Bearer ${auth.apiKey}`),headers)}function declaresMorePages(json){return typeof json=="object"&&json!==null&&"has_more"in json&&json.has_more===!0}function nextPageCursor(json){if(!declaresMorePages(json))return;let lastId=json.last_id;return typeof lastId=="string"&&lastId?lastId:void 0}var CONTEXT_WINDOW_FIELDS=["context_window","context_window.tokens","context_length","top_provider.context_length","max_input_tokens","max_context_length","max_model_len","context_size","metadata.context_length"],MAX_TOKENS_FIELDS=["max_output_tokens","max_completion_tokens","top_provider.max_completion_tokens","max_tokens","max_output_length"],INPUT_MODALITY_FIELDS=["input_modalities","architecture.input_modalities","modalities.input"],IMAGE_FLAG_FIELDS=["supports_vision","enable_vision_input","capabilities.vision","capabilities.image_input.supported"],REASONING_FLAG_FIELDS=["reasoning","supports_reasoning","enable_reason","capabilities.reasoning","capabilities.thinking.supported"],REASONING_LEVEL_FIELDS=["effort.supported_levels","reasoning_effort_support_list"],CAPABILITY_LIST_FIELDS=["supported_parameters","tags","features","supported_features","metadata.tags"];function fieldAt(record,path14){let value=record;for(let key of path14.split(".")){if(!value||typeof value!="object"||Array.isArray(value))return;value=value[key]}return value}function listAt(record,path14){let value=fieldAt(record,path14);return Array.isArray(value)?value.filter(entry=>typeof entry=="string").map(entry=>entry.toLowerCase()):[]}function declaredLimit(record,paths){let limit;for(let path14 of paths){let value=fieldAt(record,path14);typeof value=="number"&&Number.isSafeInteger(value)&&value>0&&(limit=Math.min(limit??value,value))}return limit}function declaresImageInput(record){return INPUT_MODALITY_FIELDS.some(path14=>listAt(record,path14).includes("image"))||IMAGE_FLAG_FIELDS.some(path14=>fieldAt(record,path14)===!0)||CAPABILITY_LIST_FIELDS.some(path14=>listAt(record,path14).includes("vision"))}function declaresReasoning(record){return REASONING_FLAG_FIELDS.some(path14=>fieldAt(record,path14)===!0)||REASONING_LEVEL_FIELDS.some(path14=>listAt(record,path14).length>0)||CAPABILITY_LIST_FIELDS.some(path14=>listAt(record,path14).includes("reasoning"))}function parseCatalogModels(json){if(!json||typeof json!="object")return null;let payload=json,data=Array.isArray(json)?json:Array.isArray(payload.models)?payload.models:payload.data;if(!Array.isArray(data))return null;let models=[];for(let item of data){if(!item||typeof item!="object")continue;let record=item,id=(typeof record.id=="string"?record.id.trim():"")||(typeof record.slug=="string"?record.slug.trim():"");if(!id)continue;let displayName=typeof record.name=="string"&&record.name.trim()?record.name.trim():void 0,anthropicName=typeof record.display_name=="string"&&record.display_name.trim()?record.display_name.trim():typeof record.displayName=="string"?record.displayName.trim():void 0,name=(displayName??anthropicName)!==id?displayName??anthropicName:void 0,model=name?{id,name}:{id},contextWindow=declaredLimit(record,CONTEXT_WINDOW_FIELDS);contextWindow&&(model.contextWindow=contextWindow);let maxTokens=declaredLimit(record,MAX_TOKENS_FIELDS);maxTokens&&(model.maxTokens=maxTokens),declaresImageInput(record)&&(model.input=["text","image"]),declaresReasoning(record)&&(model.reasoning=!0),models.push(model)}return data.length>0&&models.length===0?null:models}function dedupeSort(models){let map=new Map;for(let model of models)map.has(model.id)||map.set(model.id,model);return[...map.values()].sort((a,b2)=>a.id.localeCompare(b2.id))}async function fetchProviderModels(options,signal){let{store,refresher,runtime,providerId}=options,deadline=AbortSignal.any([signal,AbortSignal.timeout(PROBE_LIMITS.timeoutMs)]);try{await raceWithAbortSignal(store.flush(),deadline);let unsaved=store.getPendingError(providerId);if(unsaved)return{ok:!1,error:`Save the provider changes before fetching: ${unsaved}`};let provider=store.getProvider(providerId),settings2=effectiveModelSettings(providerId,provider);if(!settings2.baseUrl)return{ok:!1,error:"Set a baseUrl under API Auth first."};let sync=await refresher.refreshNow(providerId,deadline);if(deadline.throwIfAborted(),!sync.ok)return{ok:!1,error:`The provider did not reload: ${sync.errors.join("; ")}`};let resolved=await raceWithAbortSignal(runtime.getAuth(providerId,{signal:deadline}),deadline),configured=provider?.apiKey!==void 0||provider?.authHeader===!0||Object.keys(provider?.headers??{}).length>0||runtime.getProviderAuthStatus(providerId).configured;if(!resolved&&configured)return{ok:!1,error:"Configured credentials or headers did not resolve; check the provider authentication."};let result2=await probeProviderModels({baseUrl:resolved?.auth.baseUrl??settings2.baseUrl,auth:resolved?.auth,api:settings2.api,signal:deadline});return deadline.throwIfAborted(),result2}catch(error){return deadline.aborted?{ok:!1,error:signal.aborted?"Cancelled.":"Timed out while preparing or fetching the model catalog."}:{ok:!1,error:formatError2(error)}}}async function importProviderModels(options,models,signal){let{store,refresher,providerId}=options;await raceWithAbortSignal(store.flush(),signal);let unsaved=store.getPendingError(providerId);if(unsaved)return unsaved;let settings2=effectiveModelSettings(providerId,store.getProvider(providerId));if(!settings2.api||!settings2.baseUrl)return"Set baseUrl and API Type under API Auth before importing models.";let existing=new Set(store.getModels(providerId).map(model=>model.id)),fresh=models.filter(model=>existing.has(model.id)?!1:(existing.add(model.id),!0));if(fresh.length===0)return;signal.throwIfAborted(),options.edits.addModels(fresh),await store.flush();let saveError=store.getPendingError(providerId);if(saveError)return saveError;let outcome=await refresher.refreshNow(providerId,signal);if(!outcome.ok)return`Models were saved, but refresh failed: ${outcome.errors.join("; ")}`}var ProviderEdits=class{constructor(store,providerId,refresher,refresh){this.renaming=!1,this.store=store,this.providerId=providerId,this.refresher=refresher,this.refresh=refresh}changed(){(!this.store.isDraftProvider(this.providerId)||hasProviderSettings(this.store.getProvider(this.providerId)))&&this.refresher.touch(this.providerId),this.refresh()}setProviderField(path14,value){this.store.setProviderField(this.providerId,path14,value),this.changed()}removeProvider(){this.store.removeProvider(this.providerId),this.changed()}removeModel(modelId){this.store.removeModel(this.providerId,modelId),this.changed()}batch(apply){this.store.batch(apply)}addModels(models){this.store.batch(()=>{for(let model of models)this.store.addModel(this.providerId,model)}),models.length>0&&this.changed()}draft(){let fields={};return{isDraft:!0,read:()=>fields,setField:(path14,value)=>{setPath(fields,path14,value),this.refresh()}}}commitDraft(draft){let fields=draft.read(),id=(fields.id??"").trim();if(!id)return"Model id is required.";if(this.store.getModel(this.providerId,id))return`Model "${id}" already exists.`;let settings2=effectiveModelSettings(this.providerId,this.store.getProvider(this.providerId),fields);if(!settings2.api)return"Cannot resolve an api \u2014 set one under Model-Specific API or the provider's API Auth.";if(!settings2.baseUrl)return"Cannot resolve a baseUrl \u2014 set one under Model-Specific API or the provider's API Auth.";this.store.addModel(this.providerId,{...fields,id}),this.changed()}model(modelId,onRename){let id=modelId,snapshot;return{isDraft:!1,read:()=>snapshot??this.store.getModel(this.providerId,id)??{id},setField:(path14,value)=>{this.store.setModelField(this.providerId,id,path14,value),this.changed()},rename:async newId=>{let oldId=id;snapshot=this.store.getModel(this.providerId,id),this.renaming=!0;try{let error=await this.store.renameModel(this.providerId,id,newId);if(error)return error;id=newId,this.changed();return}finally{snapshot=void 0,this.renaming=!1,onRename(oldId,id)}}}}};var CURSOR2="\u203A",PASTE_START="\x1B[200~",PASTE_END="\x1B[201~",ValueEditor=class{constructor(callbacks){this.input=new Input({prompt:""}),this.input.onSubmit=callbacks.onCommit,this.input.onEscape=callbacks.onCancel}beginOverwrite(firstData){this.input.setValue(""),firstData&&this.input.handleInput(firstData)}reset(value){this.beginTweak(value)}beginTweak(current){this.input.setValue(""),this.input.handleInput(PASTE_START+current+PASTE_END),this.input.setValue(current)}get value(){return this.input.getValue()}handleInput(data){this.input.handleInput(data)}renderLine(width){return this.input.render(Math.max(1,width))[0]??""}get focused(){return this.input.focused}set focused(value){this.input.focused=value}};function renderKeyValueLine(theme2,opts){let lit=opts.active&&opts.paneFocused,marker=lit?theme2.fg("accent",`${CURSOR2} `):" ",keyPrefix=opts.keyLabel===void 0?"":`${opts.keyLabel}: `,keyColor=lit?"accent":"text",note=opts.note?theme2.fg("dim",` ${opts.note}`):"";if(opts.editing){let body2=opts.editing.renderLine(Math.max(1,opts.width-visibleWidth(marker)-visibleWidth(keyPrefix)));return truncateToWidth(marker+theme2.fg(keyColor,keyPrefix)+theme2.fg(keyColor,body2)+note,opts.width)}let valueColor=opts.unset?"dim":keyColor,line=marker+theme2.fg(keyColor,keyPrefix)+theme2.fg(valueColor,opts.valueText??"")+note;return truncateToWidth(line,opts.width)}function renderPlainLine(theme2,text2,opts){let lit=(opts.active??!1)&&(opts.paneFocused??!1),marker=lit?theme2.fg("accent",`${CURSOR2} `):" ",check=opts.checked===void 0?"":opts.checked?"[x] ":"[ ] ",color2=opts.dim?"dim":lit?"accent":"text",note=opts.note?theme2.fg("dim",` ${opts.note}`):"",line=marker+theme2.fg(color2,check+text2)+note;return truncateToWidth(line,opts.width)}function renderInfoLine(theme2,text2,width){return truncateToWidth(theme2.fg("dim",text2),width)}function windowLines(theme2,lines,height,scroll,indicator){let top=Math.max(0,Math.min(scroll?.top??0,lines.length)),bottom=Math.max(0,Math.min(scroll?.bottom??0,lines.length-top)),head=lines.slice(0,top),tail2=bottom>0?lines.slice(lines.length-bottom):[],middle=lines.slice(top,lines.length-bottom),cursor=Math.max(0,Math.min((scroll?.cursor??0)-top,Math.max(0,middle.length-1))),padToHeight=rows=>{let out=rows.slice(0,height);for(;out.length<height;)out.push("");return out},avail=height-head.length-tail2.length;if(middle.length<=avail)return padToHeight([...head,...middle,...tail2]);let slots=Math.max(1,avail-1),start=Math.max(0,Math.min(cursor-Math.floor(slots/2),middle.length-slots)),note=indicator?.(cursor+1,middle.length)??theme2.fg("dim",` (${cursor+1}/${middle.length})`);return padToHeight([...head,...middle.slice(start,start+slots),note,...tail2])}function isPrintableInput(data){if(!data)return!1;if(data.startsWith(PASTE_START)||decodeKittyPrintable(data)!==void 0)return!0;if(data.includes("\x1B")||data.includes("\r")||data.includes(`
|
|
2074
|
+
`))return!1;for(let char of data){let code=char.codePointAt(0);if(code<32||code===127)return!1}return!0}function truncateMiddle2(text2,maxWidth){if(visibleWidth(text2)<=maxWidth)return text2;if(maxWidth<=4)return truncateToWidth(text2,maxWidth);let headWidth=Math.ceil((maxWidth-1)/2),tailWidth=maxWidth-1-headWidth,head="",headUsed=0;for(let char of text2){let charWidth=visibleWidth(char);if(headUsed+charWidth>headWidth)break;head+=char,headUsed+=charWidth}let tail2="",tailUsed=0;for(let char of[...text2].reverse()){let charWidth=visibleWidth(char);if(tailUsed+charWidth>tailWidth)break;tail2=char+tail2,tailUsed+=charWidth}return`${head}\u2026${tail2}`}var InfoPane=class{constructor(host,lines,onConfirm){this.focused=!1,this.host=host,this.lines=lines,this.onConfirm=onConfirm}render(width){return this.focused&&this.onConfirm?this.lines.map((line,index3)=>index3>0?renderInfoLine(this.host.theme,line,width):truncateToWidth(this.host.theme.fg("accent",`${CURSOR2} `)+this.host.theme.fg("text",line),width)):this.lines.map(line=>renderInfoLine(this.host.theme,line,width))}handleInput(data){if(this.host.keybindings.matches(data,"tui.select.cancel")){this.host.popPane();return}this.onConfirm&&this.host.keybindings.matches(data,"tui.select.confirm")&&this.onConfirm()}setFocused(focused){this.focused=focused}hints(){let hints=[];return this.onConfirm&&hints.push(keyHint("tui.select.confirm","proceed")),hints.push(keyHint("tui.select.cancel","back")),hints.join(" ")}},ConfirmPane=class{constructor(host,message,actionLabel,action){this.crumb="Confirm",this.index=1,this.focused=!1,this.host=host,this.message=message,this.actionLabel=actionLabel,this.action=action}render(width){let theme2=this.host.theme;return[truncateToWidth(theme2.fg("warning",this.message),width),renderPlainLine(theme2,this.actionLabel,{active:this.index===0,paneFocused:this.focused,width}),renderPlainLine(theme2,"Cancel",{active:this.index===1,paneFocused:this.focused,width})]}handleInput(data){let kb=this.host.keybindings;if(kb.matches(data,"tui.select.up")||kb.matches(data,"tui.select.down")){this.index=this.index===0?1:0,this.host.refresh();return}if(kb.matches(data,"tui.select.cancel")){this.host.popPane();return}kb.matches(data,"tui.select.confirm")&&(this.index===0?this.action():this.host.popPane())}setFocused(focused){this.focused=focused}hints(){return[keyHint("tui.select.confirm","choose"),keyHint("tui.select.cancel","cancel")].join(" ")}};function moveSelection(keys,data,index3,count){let delta=keys.matches(data,"tui.select.up")?-1:keys.matches(data,"tui.select.down")?1:void 0;return delta===void 0?void 0:count===0?0:(index3+delta+count)%count}var ChoicePane=class{constructor(host,crumb,options){this.focused=!1,this.host=host,this.crumb=crumb,this.options=options,this.index=Math.max(0,options.choices().findIndex(choice=>choice.value===options.current()))}render(width){let lines=this.options.choices().map((choice,index3)=>renderPlainLine(this.host.theme,`${choice.value===this.options.current()?"\u25CF":"\u25CB"} ${choice.label}`,{active:index3===this.index,paneFocused:this.focused,dim:choice.dim,width}));return this.error&&lines.push(renderInfoLine(this.host.theme,this.error,width)),lines}scrollWindow(){return{cursor:this.index,bottom:this.error?1:0}}handleInput(data){let choices=this.options.choices(),next=moveSelection(this.host.keybindings,data,this.index,choices.length);if(next!==void 0)this.index=next,this.host.refresh();else if(this.host.keybindings.matches(data,"tui.select.cancel"))this.host.popPane();else if(this.host.keybindings.matches(data,"tui.select.confirm")||this.host.keybindings.matches(data,"app.list.toggle")){let choice=choices[this.index];if(!choice)return;this.error=this.options.choose(choice.value),this.error?this.host.refresh():this.host.popPane()}}setFocused(focused){this.focused=focused}hints(){return[rawKeyHint("\u2191\u2193","move"),keyHint("tui.select.confirm","select"),keyHint("tui.select.cancel","back")].join(" ")}},InlineEdit=class{constructor(refresh){this.refresh=refresh}get editing(){return this.active!==void 0}editor(key){return this.active?.key===key?this.active.editor:void 0}setFocused(focused){this.active&&(this.active.editor.focused=focused)}begin(key,current,mode,focused,commit,firstData){let editor=new ValueEditor({onCommit:value=>{this.error=commit(value),this.error||(this.active=void 0),this.refresh()},onCancel:()=>{this.active=void 0,this.error=void 0,this.refresh()}});this.active={key,editor},editor.focused=focused,mode==="overwrite"?editor.beginOverwrite(firstData):editor.beginTweak(current),this.refresh()}handleInput(data,keys){return this.active?(!keys.matches(data,"tui.select.up")&&!keys.matches(data,"tui.select.down")&&this.active.editor.handleInput(data),this.refresh(),!0):!1}};function formatTokens3(count){return count<1e3?count.toString():count<1e4?`${(count/1e3).toFixed(1)}k`:count<1e6?`${Math.round(count/1e3)}k`:count<1e7?`${(count/1e6).toFixed(1)}M`:`${Math.round(count/1e6)}M`}function metadataNote(model){let parts=[model.contextWindow?`${formatTokens3(model.contextWindow)} ctx`:"",model.maxTokens?`${formatTokens3(model.maxTokens)} out`:"",model.input?.includes("image")?"img":"",model.reasoning?"think":""].filter(Boolean);return parts.length>0?`\xB7 ${parts.join(" \xB7 ")}`:void 0}var FetchModelsPane=class{constructor(host){this.state={type:"idle"},this.query="",this.index=0,this.checked=new Set,this.focused=!1,this.disposed=!1,this.host=host,this.search=new ValueEditor({onCommit:()=>this.importChecked(),onCancel:()=>this.exitResults()})}start(){if(this.disposed||this.state.type==="loading"||this.state.type==="importing"||!this.catalogUrl())return;let controller=new AbortController;this.state={type:"loading",controller},this.host.refresh(),this.host.runFetch(controller.signal).then(result2=>{if(!(this.disposed||controller.signal.aborted||this.state.type!=="loading"||this.state.controller!==controller)){if(result2.ok)this.state={type:"results",catalog:result2},this.checked=new Set,this.query="",this.search.reset(""),this.index=0,this.search.focused=this.focused,this.host.setFetchStatus(`\xB7 ${result2.models.length} models`);else{if(result2.error==="Cancelled.")return;this.state={type:"error",message:result2.error},this.host.setFetchStatus("\xB7 failed")}this.host.refresh()}}).catch(error=>{this.disposed||controller.signal.aborted||this.state.type!=="loading"||this.state.controller!==controller||(this.state={type:"error",message:error instanceof Error?error.message:String(error)},this.host.setFetchStatus("\xB7 failed"),this.host.refresh())})}existingIds(){return new Set(this.host.store.getModels(this.host.providerId).map(model=>model.id))}catalogUrl(){let baseUrl=this.host.store.getProvider(this.host.providerId)?.baseUrl;try{return baseUrl?modelCatalogUrl(new URL(baseUrl),this.host.effectiveApi()).href:void 0}catch{return}}rows(){if(this.state.type!=="results"&&this.state.type!=="importing")return[];let existing=this.existingIds(),rows=this.state.catalog.models.map(model=>({model,added:existing.has(model.id)})),query=this.query.trim().toLowerCase();return query?rows.filter(row=>row.model.id.toLowerCase().includes(query)||row.model.name?.toLowerCase().includes(query)):rows}render(width){let theme2=this.host.theme,catalogUrl=this.catalogUrl();switch(this.state.type){case"idle":return catalogUrl?[renderPlainLine(theme2,"Fetch Models",{active:!0,paneFocused:this.focused,note:`\xB7 from ${truncateMiddle2(catalogUrl,Math.max(10,width-22))}`,width})]:[renderInfoLine(theme2,"Set a baseUrl under API Auth first.",width)];case"loading":return[renderInfoLine(theme2,`Fetching ${catalogUrl??""} \u2026`,width),renderInfoLine(theme2,"Esc cancels the request.",width)];case"error":return[theme2.fg("error",truncate3(this.state.message,Math.max(10,width-2))),renderInfoLine(theme2,"Enter retries; Esc goes back.",width)];case"importing":case"results":{let lines=[];this.state.catalog.truncated&&lines.push(renderInfoLine(theme2,"The catalog was truncated; refine manually if a model is missing.",width)),lines.push(this.search.renderLine(width));let rows=this.rows();for(let[rowIndex,row]of rows.entries()){if(row.added){lines.push(renderPlainLine(theme2,row.model.id,{active:rowIndex===this.index,paneFocused:this.focused,dim:!0,note:"\xB7 Added",width}));continue}lines.push(renderPlainLine(theme2,row.model.name?`${row.model.id} \xB7 ${row.model.name}`:row.model.id,{checked:this.checked.has(row.model.id),active:rowIndex===this.index,paneFocused:this.focused,note:metadataNote(row.model),width}))}rows.length===0&&lines.push(renderInfoLine(theme2,"No matching models.",width));let addedCount=rows.filter(row=>row.added).length;return lines.push(renderInfoLine(theme2,`${this.checked.size} selected \xB7 ${rows.length} shown${addedCount?` \xB7 ${addedCount} already added`:""}`,width)),this.state.type==="importing"&&lines.push(renderInfoLine(theme2,"Importing\u2026",width)),this.state.type==="results"&&this.state.error&&lines.push(theme2.fg("error",truncate3(this.state.error,Math.max(10,width-2)))),lines}}}scrollWindow(){if(this.state.type!=="results"&&this.state.type!=="importing")return{};let top=(this.state.catalog.truncated?1:0)+1,bottom=1+(this.state.type==="importing"||this.state.error?1:0);return{top,bottom,cursor:top+this.index}}handleInput(data){let kb=this.host.keybindings;switch(this.state.type){case"idle":if(kb.matches(data,"tui.select.confirm")){this.start();return}if(kb.matches(data,"tui.select.cancel")){this.host.popPane();return}return;case"loading":if(kb.matches(data,"tui.select.cancel")){this.state.controller.abort(),this.state={type:"idle"},this.host.refresh();return}return;case"error":if(kb.matches(data,"tui.select.confirm")){this.start();return}if(kb.matches(data,"tui.select.cancel")){this.host.popPane();return}return;case"importing":case"results":this.handleResultsInput(data);return}}handleResultsInput(data){let kb=this.host.keybindings,rows=this.rows(),next=moveSelection(kb,data,this.index,rows.length);if(next!==void 0){this.index=next,this.host.refresh();return}if(kb.matches(data,"app.list.toggle")){let row=rows[this.index];if(!row||row.added||this.state.type==="importing")return;this.checked.has(row.model.id)?this.checked.delete(row.model.id):this.checked.add(row.model.id),this.host.refresh();return}if(kb.matches(data,"tui.select.cancel")){this.exitResults();return}if(kb.matches(data,"tui.select.confirm")){this.importChecked();return}let before=this.query;this.search.handleInput(data),this.query=this.search.value,this.query!==before&&(this.index=0),this.host.refresh()}importChecked(){if(this.state.type!=="results")return;let chosen;if(this.checked.size===0){let row=this.rows()[this.index];if(!row||row.added)return;chosen=[row.model]}else chosen=this.state.catalog.models.filter(model=>this.checked.has(model.id));let controller=new AbortController,catalog=this.state.catalog;this.state={type:"importing",catalog,controller},this.host.refresh(),this.host.importModels(chosen,controller.signal).then(error=>{if(!(this.disposed||controller.signal.aborted||this.state.type!=="importing"||this.state.controller!==controller)){if(error)return this.state={type:"results",catalog,error},this.host.setFetchStatus("\xB7 import failed"),this.host.refresh();this.host.setFetchStatus(`\xB7 ${this.host.store.getModels(this.host.providerId).length} models`),this.state={type:"idle"},this.host.popPane()}}).catch(error=>{this.disposed||controller.signal.aborted||this.state.type!=="importing"||this.state.controller!==controller||(this.state={type:"results",catalog,error:error instanceof Error?error.message:String(error)},this.host.refresh())})}exitResults(){(this.state.type==="loading"||this.state.type==="importing")&&this.state.controller.abort(),this.state={type:"idle"},this.checked=new Set,this.host.popPane()}setFocused(focused){this.focused=focused,this.search.focused=focused&&(this.state.type==="results"||this.state.type==="importing")}isEditing(){return this.state.type==="results"||this.state.type==="importing"}dispose(){this.disposed=!0,(this.state.type==="loading"||this.state.type==="importing")&&this.state.controller.abort()}hints(){switch(this.state.type){case"loading":return keyHint("tui.select.cancel","cancel request");case"importing":case"results":return[rawKeyHint("type","filter"),keyHint("app.list.toggle","check"),keyHint("tui.select.confirm","import"),keyHint("tui.select.cancel","discard")].join(" ");case"error":return[keyHint("tui.select.confirm","retry"),keyHint("tui.select.cancel","back")].join(" ");default:return this.catalogUrl()?[keyHint("tui.select.confirm","fetch"),keyHint("tui.select.cancel","back")].join(" "):keyHint("tui.select.cancel","back")}}};function formatContext(model){let ctx=model.contextWindow>=1e3?`${Math.round(model.contextWindow/1024)}k`:String(model.contextWindow);return`${model.api} \xB7 ${ctx} ctx${model.reasoning?" \xB7 reasoning":""}`}var BuiltinCandidatesPane=class{constructor(host,model){this.crumb="Use Built-in Data",this.index=0,this.focused=!1,this.host=host,this.model=model,this.query=this.model.read().id??"",this.search=new ValueEditor({onCommit:()=>this.pickCurrent(),onCancel:()=>this.host.popPane()}),this.search.reset(this.query)}candidates(){return matchBuiltinModels(this.query,this.host.effectiveApi(this.model.read()))}render(width){let theme2=this.host.theme,lines=[this.search.renderLine(width)],matches=this.candidates();matches.length===0&&lines.push(renderInfoLine(theme2,"No builtin candidates \u2014 keep configuring manually.",width));for(let[rowIndex,match2]of matches.entries()){let{providerId,model}=match2.entry,label=`${providerId} / ${model.id}`,note=(match2.tier==="exact"?"exact \xB7 ":"")+`${model.name!==model.id?`${model.name} \xB7 `:""}${formatContext(model)}`;lines.push(renderPlainLine(theme2,label,{active:rowIndex===this.index,paneFocused:this.focused,note,width}))}return lines.push(renderInfoLine(theme2,"Candidates are a reference only; the configured id is never rewritten.",width)),lines}scrollWindow(){return{top:1,bottom:1,cursor:1+this.index}}pickCurrent(){let entry=this.candidates()[this.index]?.entry;entry&&this.host.pushPane(new BuiltinPreviewPane(this.host,this.model,entry))}handleInput(data){let kb=this.host.keybindings,count=this.candidates().length,next=moveSelection(kb,data,this.index,count);if(next!==void 0){this.index=next,this.host.refresh();return}if(kb.matches(data,"tui.select.cancel")){this.host.popPane();return}if(kb.matches(data,"tui.select.confirm")){this.pickCurrent();return}let before=this.query;this.search.handleInput(data),this.query=this.search.value,this.query!==before&&(this.index=0),this.host.refresh()}setFocused(focused){this.focused=focused,this.search.focused=focused}isEditing(){return!0}hints(){return[rawKeyHint("type","filter"),rawKeyHint("\u2191\u2193","move"),keyHint("tui.select.confirm","preview"),keyHint("tui.select.cancel","back")].join(" ")}},BuiltinPreviewPane=class{constructor(host,model,reference){this.crumb="Use Built-in Data \xB7 preview",this.index=0,this.focused=!1,this.host=host,this.model=model,this.reference=reference;let current=model.read();this.snapshot=structuredClone(current),this.snapshotApi=host.effectiveApi(current),this.changes=computeFieldChanges(current,reference.model,host.effectiveApi(current)),this.checked=this.changes.map(change=>change.checked&&change.applicable)}rowCount(){return this.changes.length+1}render(width){let theme2=this.host.theme,lines=[renderInfoLine(theme2,`reference: ${this.reference.providerId} / ${this.reference.model.id}`,width)];for(let[rowIndex,change]of this.changes.entries()){let active=rowIndex===this.index,expandable=change.referenceDetails!==void 0,note=change.applicable?void 0:"\xB7 view only";if(lines.push(renderPlainLine(theme2,`${change.field}: ${change.currentText} \u2192 ${change.referenceText}`,{checked:change.applicable?this.checked[rowIndex]:void 0,active,paneFocused:this.focused,note,width})),this.expanded===rowIndex&&expandable){for(let detail of change.referenceDetails)lines.push(renderInfoLine(theme2,` ${detail}`,width));change.referenceHasTiers&&lines.push(renderInfoLine(theme2," reference has cost tiers \u2014 tiers are never imported.",width))}}return lines.push(renderPlainLine(theme2,"Apply Selected Fields",{active:this.index===this.changes.length,paneFocused:this.focused,width})),this.error&&lines.push(theme2.fg("error",truncate3(this.error,Math.max(10,width-2)))),lines}scrollWindow(){let cursor=1+this.index;if(this.expanded!==void 0&&this.expanded<this.index){let change=this.changes[this.expanded];change.referenceDetails&&(cursor+=change.referenceDetails.length+(change.referenceHasTiers?1:0))}return{top:1,bottom:this.error?1:0,cursor}}handleInput(data){let kb=this.host.keybindings,next=moveSelection(kb,data,this.index,this.rowCount());if(next!==void 0){this.index=next,this.host.refresh();return}if(kb.matches(data,"tui.select.cancel")){this.host.popPane();return}if(kb.matches(data,"app.list.toggle")){let change=this.changes[this.index];if(!change)return;if(!change.applicable){this.expanded=this.expanded===this.index?void 0:this.index,this.host.refresh();return}this.checked[this.index]=!this.checked[this.index],this.host.refresh();return}if(kb.matches(data,"tui.select.confirm")){if(this.index===this.changes.length){this.apply();return}let change=this.changes[this.index];change.referenceDetails?this.expanded=this.expanded===this.index?void 0:this.index:change.applicable&&(this.checked[this.index]=!this.checked[this.index]),this.host.refresh();return}}apply(){let current=this.model.read();if(this.host.effectiveApi(current)!==this.snapshotApi){this.error="The API changed since this preview opened; reopen to continue.",this.host.refresh();return}if(!current.id||!jsonEquals(current,this.snapshot)){this.error="The model changed since this preview opened; reopen to continue.",this.host.refresh();return}let chosen=this.changes.filter((_2,rowIndex)=>this.checked[rowIndex]&&this.changes[rowIndex].applicable);if(chosen.length===0){this.host.popPane();return}this.host.edits.batch(()=>{for(let change of chosen)for(let patch of change.patches)this.model.setField(patch.path,patch.value)}),this.host.notify(`Applied ${chosen.length} field${chosen.length===1?"":"s"} from ${this.reference.providerId} / ${this.reference.model.id}.`,"info"),this.host.popPane(),this.host.popPane()}setFocused(focused){this.focused=focused}hints(){return[keyHint("app.list.toggle","check"),keyHint("tui.select.confirm","details / apply"),keyHint("tui.select.cancel","back")].join(" ")}};var THINKING_VARIABLES=["thinking.enabled","thinking.effort","thinking.budget"],SESSION_AFFINITY=["openai","openai-nosession","openrouter"],OPENAI_COMPLETIONS_FIELDS=[{key:"supportsStore",kind:"boolean",note:"Accepts the `store` parameter"},{key:"supportsDeveloperRole",kind:"boolean",note:"Accepts `developer` role messages"},{key:"supportsReasoningEffort",kind:"boolean",note:"Accepts `reasoning_effort`"},{key:"supportsUsageInStreaming",kind:"boolean",note:"Streams usage chunks"},{key:"supportsFinishReason",kind:"boolean",note:"Reports finish reasons"},{key:"maxTokensField",kind:"enum",options:["max_completion_tokens","max_tokens"],note:"Token limit field name"},{key:"requiresToolResultName",kind:"boolean",note:"Tool results need a `name`"},{key:"requiresAssistantAfterToolResult",kind:"boolean",note:"Needs assistant message after tool results"},{key:"requiresThinkingAsText",kind:"boolean",note:"Thinking must be plain text"},{key:"requiresReasoningContentOnAssistantMessages",kind:"boolean",note:"Assistant messages must carry reasoning content"},{key:"thinkingFormat",kind:"enum",options:["openai","openrouter","together","baseten","deepseek","zai","qwen","chat-template","qwen-chat-template","string-thinking","ant-ling"],note:"Reasoning payload format"},{key:"chatTemplateKwargs",kind:"stringMap",note:"Extra chat-template kwargs (open dictionary)"},{key:"chatTemplateArgs",kind:"stringMap",note:"Extra chat-template args (open dictionary)"},{key:"cacheControlFormat",kind:"enum",options:["anthropic"],note:"Cache-control payload format"},{key:"openRouterRouting",kind:"json",note:"OpenRouter routing preferences object"},{key:"vercelGatewayRouting",kind:"json",note:"Vercel AI Gateway routing object"},{key:"supportsOpenAIGrammarTools",kind:"boolean",note:"Grammar-constrained tool calls"},{key:"supportsStrictMode",kind:"boolean",note:"Strict tool schemas"},{key:"sendSessionAffinityHeaders",kind:"boolean",note:"Send session affinity headers"},{key:"supportsMidConvoSystemMessages",kind:"boolean",note:"Accepts mid-conversation system messages"},{key:"supportsMidConvoToolAdditions",kind:"boolean",note:"System messages can add tools mid-conversation"},{key:"sessionAffinityFormat",kind:"enum",options:SESSION_AFFINITY,note:"Affinity header format"},{key:"supportsLongCacheRetention",kind:"boolean",note:"Long-lived prompt cache retention"},{key:"vllmPriority",kind:"number",note:"vLLM scheduling priority"},{key:"zaiToolStream",kind:"boolean",note:"Z.AI streaming tool calls"},{key:"supportsThinkingTokenBudget",kind:"boolean",note:"Enable the thinking-token budget alias"},{key:"thinkingTokenBudgetField",kind:"enum",options:["thinking_token_budget","thinking_budget","thinking_budget_tokens"],note:"Thinking budget field"}],OPENAI_RESPONSES_FIELDS=[{key:"supportsDeveloperRole",kind:"boolean",note:"Accepts `developer` role messages"},{key:"sessionAffinityFormat",kind:"enum",options:SESSION_AFFINITY,note:"Affinity header format"},{key:"supportsLongCacheRetention",kind:"boolean",note:"Long-lived prompt cache retention"},{key:"supportsStrictMode",kind:"boolean",note:"Strict tool schemas"},{key:"supportsOpenAIGrammarTools",kind:"boolean",note:"Grammar-constrained tool calls"},{key:"supportsAdditionalTools",kind:"boolean",note:"Accepts additional hosted tools"},{key:"supportsToolSearch",kind:"boolean",note:"Tool search support"},{key:"supportsMaxOutputTokens",kind:"boolean",note:"Accepts `max_output_tokens`"},{key:"supportsExplicitPromptCacheMode",kind:"boolean",note:"Explicit prompt caching"}],ANTHROPIC_MESSAGES_FIELDS=[{key:"supportsEagerToolInputStreaming",kind:"boolean",note:"Streams tool input eagerly"},{key:"supportsLongCacheRetention",kind:"boolean",note:"Long-lived prompt cache retention"},{key:"sendSessionAffinityHeaders",kind:"boolean",note:"Send session affinity headers"},{key:"supportsCacheControlOnTools",kind:"boolean",note:"Cache control on tool definitions"},{key:"supportsTemperature",kind:"boolean",note:"Accepts `temperature`"},{key:"forceAdaptiveThinking",kind:"boolean",note:"Force adaptive thinking mode"},{key:"allowEmptySignature",kind:"boolean",note:"Tolerate empty thinking signatures"},{key:"supportsStrictTools",kind:"boolean",note:"Strict tool schemas"},{key:"supportsMidConvoEffort",kind:"boolean",note:"Effort changes mid-conversation"},{key:"supportsMidConvoSystemMessages",kind:"boolean",note:"Accepts mid-conversation system messages"},{key:"supportsMidConvoToolChanges",kind:"boolean",note:"Accepts mid-conversation tool changes"},{key:"allowedFallbackModels",kind:"json",note:"Server-side refusal fallback models"}],BEDROCK_FIELDS=[{key:"supportsStrictMode",kind:"boolean",note:"Strict tool schemas"}];function compatFieldsForApi(api){switch(api){case"openai-completions":return OPENAI_COMPLETIONS_FIELDS;case"openai-responses":return OPENAI_RESPONSES_FIELDS;case"azure-openai-responses":return OPENAI_RESPONSES_FIELDS.filter(field5=>["supportsDeveloperRole","supportsStrictMode","supportsOpenAIGrammarTools"].includes(field5.key));case"openai-codex-responses":return OPENAI_RESPONSES_FIELDS.filter(field5=>["supportsStrictMode","supportsOpenAIGrammarTools","supportsAdditionalTools","supportsToolSearch"].includes(field5.key));case"anthropic-messages":return ANTHROPIC_MESSAGES_FIELDS;case"bedrock-converse-stream":return BEDROCK_FIELDS;default:return[]}}function compatFieldFor(api,key){return compatFieldsForApi(api).find(field5=>field5.key===key)}var completionsCompatValidator=Compile(OpenAICompletionsCompatSchema);function validateCompletionsCompat(value){if(!completionsCompatValidator.Check(value))return completionsCompatValidator.Errors(value).slice(0,5).map(error=>{let path14=error.instancePath.replace(/^\//,"").replace(/\//g,"."),required=error.keyword==="required"?error.params.requiredProperties?.[0]:void 0;return`${required?path14?`${path14}.${required}`:required:path14||"root"}: ${error.message}`}).join("; ")}function validateJsonCompatValue(key,text2){let value;try{value=JSON.parse(text2)}catch{return"Value is not valid JSON."}return validateCompletionsCompat({[key]:value})}function validateChatTemplateKwarg(value){if(value!==null&&typeof value=="object"&&!Array.isArray(value)&&!Object.keys(value).every(key=>key==="$var"||key==="omitWhenOff"))return'Only "$var" and "omitWhenOff" are allowed.';let error=validateCompletionsCompat({chatTemplateKwargs:{value}});return error?`Value must be a scalar or valid $var reference: ${error}`:void 0}function compatObject(handle){let compat=handle.read().compat;return typeof compat=="object"&&compat!==null&&!Array.isArray(compat)?compat:{}}function scalarText(value){return value===null?"null":typeof value=="string"||typeof value=="number"||typeof value=="boolean"?String(value):JSON.stringify(value)??String(value)}var DICT_VALUE_KINDS=["string","number","boolean","null","$var"],VAR_OPTIONS=THINKING_VARIABLES,DictPane=class{constructor(host,model,dictKey){this.index=0,this.mode={type:"list"},this.focused=!1,this.host=host,this.model=model,this.dictKey=dictKey,this.crumb=`compat \xB7 ${dictKey}`}dict(){let value=compatObject(this.model)[this.dictKey];return typeof value=="object"&&value!==null&&!Array.isArray(value)?value:{}}entries(){return Object.entries(this.dict())}render(width){let theme2=this.host.theme,lines=[renderInfoLine(theme2,"free-form keys; values: string \xB7 number \xB7 boolean \xB7 null \xB7 $var",width)];if(this.mode.type!=="list")return lines.push(...this.renderMode(width)),this.error&&lines.push(renderInfoLine(theme2,this.error,width)),lines;let entries=this.entries();for(let[rowIndex,[key,value]]of entries.entries()){let active=rowIndex===this.index;lines.push(renderKeyValueLine(theme2,{keyLabel:key,valueText:scalarText(value),active,paneFocused:this.focused,width}))}return lines.push(renderPlainLine(theme2,"+ Add Entry",{active:this.index===entries.length&&this.mode.type==="list",paneFocused:this.focused,width})),this.error&&lines.push(theme2.fg("error",truncate3(this.error,Math.max(10,width-2)))),lines}scrollWindow(){return this.mode.type!=="list"?{top:1,bottom:this.error?1:0}:{top:1,bottom:this.error?1:0,cursor:1+this.index}}renderMode(width){let theme2=this.host.theme,mode=this.mode;switch(mode.type){case"keyEdit":return[renderInfoLine(theme2,"new key:",width),mode.editor.renderLine(width)];case"kindPick":return[renderInfoLine(theme2,`${mode.key} \xB7 value kind`,width),...DICT_VALUE_KINDS.map((kind,kindIndex)=>renderPlainLine(theme2,kind,{active:kindIndex===mode.index,paneFocused:this.focused,width}))];case"valueEdit":return[renderInfoLine(theme2,`${mode.key} \xB7 ${mode.kind}`,width),renderKeyValueLine(theme2,{keyLabel:mode.key,active:!0,paneFocused:this.focused,editing:mode.editor,width})];case"boolPick":return[renderInfoLine(theme2,`${mode.key} \xB7 boolean`,width),...["true","false"].map((option,optionIndex)=>renderPlainLine(theme2,option,{active:optionIndex===mode.index,paneFocused:this.focused,width}))];case"varPick":return[renderInfoLine(theme2,`${mode.key} \xB7 $var`,width),...VAR_OPTIONS.map((option,optionIndex)=>renderPlainLine(theme2,option,{active:optionIndex===mode.index,paneFocused:this.focused,width}))];case"omitPick":return[renderInfoLine(theme2,`${mode.key} \xB7 omitWhenOff`,width),...["default","true","false"].map((option,optionIndex)=>renderPlainLine(theme2,option,{active:optionIndex===mode.index,paneFocused:this.focused,width}))];default:return[]}}handleInput(data){let kb=this.host.keybindings,mode=this.mode;switch(mode.type){case"keyEdit":case"valueEdit":if(kb.matches(data,"tui.select.up")||kb.matches(data,"tui.select.down"))return;mode.editor.handleInput(data),this.host.refresh();return;case"kindPick":this.handlePick(data,mode,DICT_VALUE_KINDS.length,index3=>{let key=mode.key,kind=DICT_VALUE_KINDS[index3];this.startValueForKind(key,kind)});return;case"boolPick":this.handlePick(data,mode,2,index3=>{let key=mode.key;this.mode={type:"list"},this.writeEntry(key,index3===0)});return;case"varPick":this.handlePick(data,mode,VAR_OPTIONS.length,index3=>{let key=mode.key;this.mode={type:"omitPick",key,$var:VAR_OPTIONS[index3],index:0},this.host.refresh()});return;case"omitPick":this.handlePick(data,mode,3,index3=>{this.mode={type:"list"},this.writeEntry(mode.key,index3===0?{$var:mode.$var}:{$var:mode.$var,omitWhenOff:index3===1})});return;case"list":this.handleList(data);return}}handlePick(data,mode,count,choose2){let kb=this.host.keybindings,index3=mode.index;if(kb.matches(data,"tui.select.up")){mode.index=index3===0?count-1:index3-1,this.host.refresh();return}if(kb.matches(data,"tui.select.down")){mode.index=(index3+1)%count,this.host.refresh();return}if(kb.matches(data,"tui.select.cancel")){this.mode={type:"list"},this.host.refresh();return}kb.matches(data,"tui.select.confirm")&&choose2(index3)}handleList(data){let kb=this.host.keybindings,rowCount=this.entries().length+1,next=moveSelection(kb,data,this.index,rowCount);if(next!==void 0){this.index=next,this.host.refresh();return}if(kb.matches(data,"tui.select.cancel")){this.host.popPane();return}if(kb.matches(data,"app.provider.removeEntry")){let entry=this.entries()[this.index];if(!entry)return;this.model.setField(["compat",this.dictKey,entry[0]],DELETE),this.index=Math.max(0,Math.min(this.index,this.entries().length-1));return}if(kb.matches(data,"tui.select.confirm")||kb.matches(data,"app.list.toggle")){let entry=this.entries()[this.index];if(!entry){let editor2=new ValueEditor({onCommit:raw=>{let key2=raw.trim();if(!key2)return this.error="Key must be non-empty.",this.host.refresh();if(Object.hasOwn(this.dict(),key2))return this.error=`"${key2}" already exists.`,this.host.refresh();this.error=void 0,this.mode={type:"kindPick",key:key2,index:0},this.host.refresh()},onCancel:()=>{this.mode={type:"list"},this.error=void 0,this.host.refresh()}});editor2.focused=this.focused,this.mode={type:"keyEdit",editor:editor2},this.host.refresh();return}let[key,value]=entry;if(typeof value=="boolean"){this.writeEntry(key,!value);return}if(value===null)return;if(typeof value=="object"){let record=value;if(record.$var==="thinking.enabled"||record.$var==="thinking.effort"||record.$var==="thinking.budget"){this.mode={type:"omitPick",key,$var:record.$var,index:record.omitWhenOff===void 0?0:record.omitWhenOff?1:2},this.host.refresh();return}return}let kind=typeof value=="number"?"number":"string",editor=new ValueEditor({onCommit:raw=>this.commitScalar(key,kind,raw),onCancel:()=>{this.mode={type:"list"},this.error=void 0,this.host.refresh()}});editor.beginTweak(String(value)),editor.focused=this.focused,this.mode={type:"valueEdit",key,kind,editor},this.host.refresh();return}}startValueForKind(key,kind){switch(kind){case"string":case"number":{let editor=new ValueEditor({onCommit:raw=>this.commitScalar(key,kind,raw),onCancel:()=>{this.mode={type:"list"},this.error=void 0,this.host.refresh()}});editor.focused=this.focused,this.mode={type:"valueEdit",key,kind,editor},this.host.refresh();return}case"boolean":this.mode={type:"boolPick",key,index:0},this.host.refresh();return;case"null":this.mode={type:"list"},this.writeEntry(key,null);return;case"$var":this.mode={type:"varPick",key,index:0},this.host.refresh();return}}commitScalar(key,kind,raw){let value=raw;if(kind==="number"){let parsed=Number(raw.trim());if(!Number.isFinite(parsed)){this.error=`${key} must be a number.`,this.host.refresh();return}value=parsed}let invalid2=validateChatTemplateKwarg(value);if(invalid2){this.error=invalid2,this.host.refresh();return}this.error=void 0,this.mode={type:"list"},this.writeEntry(key,value)}writeEntry(key,value){let invalid2=validateChatTemplateKwarg(value);if(invalid2){this.error=invalid2,this.host.refresh();return}this.model.setField(["compat",this.dictKey,key],value)}setFocused(focused){this.focused=focused,(this.mode.type==="keyEdit"||this.mode.type==="valueEdit")&&(this.mode.editor.focused=focused)}isEditing(){return this.mode.type==="keyEdit"||this.mode.type==="valueEdit"}hints(){switch(this.mode.type){case"keyEdit":case"valueEdit":return[keyHint("tui.input.submit","save"),keyHint("tui.select.cancel","cancel")].join(" ");case"list":return[keyHint("tui.select.confirm","edit / add"),keyHint("app.provider.removeEntry","remove"),keyHint("tui.select.cancel","back")].join(" ");default:return[rawKeyHint("\u2191\u2193","move"),keyHint("tui.select.confirm","choose"),keyHint("tui.select.cancel","cancel")].join(" ")}}};function compatObject2(handle){let compat=handle.read().compat;return typeof compat=="object"&&compat!==null&&!Array.isArray(compat)?compat:{}}function scalarText2(value){return value===null?"null":typeof value=="string"||typeof value=="number"||typeof value=="boolean"?String(value):JSON.stringify(value)??String(value)}var CompatPane=class{constructor(host,model){this.crumb="compat",this.index=0,this.mode={type:"list"},this.focused=!1,this.host=host,this.model=model}entries(){return Object.entries(compatObject2(this.model))}effectiveApi(){return this.host.effectiveApi(this.model.read())}rowCount(){return this.entries().length+1}render(width){let theme2=this.host.theme,api=this.effectiveApi(),lines=[renderInfoLine(theme2,api?`effective api: ${api}`:"effective api: unresolved \u2014 set API Type",width)];if(this.mode.type==="chooseValue"){let mode=this.mode;lines.push(renderKeyValueLine(theme2,{keyLabel:mode.key,valueText:"choose a value",active:!0,paneFocused:this.focused,width}));for(let[index3,option]of mode.options.entries())lines.push(renderPlainLine(theme2,option,{active:index3===mode.index,paneFocused:this.focused,width}));return lines}let known=api?compatFieldsForApi(api):[],entries=this.entries(),editingKey=this.mode.type==="list"?void 0:this.mode.key;editingKey!==void 0&&!entries.some(([key])=>key===editingKey)&&entries.push([editingKey,void 0]),known.length===0&&entries.length===0&&lines.push(renderInfoLine(theme2,`No compat fields are known for ${api??"this api"}.`,width));for(let[rowIndex,[key,value]]of entries.entries()){let active=rowIndex===this.index,field5=api?compatFieldFor(api,key):void 0,editing=this.mode.type==="editValue"&&this.mode.key===key?this.mode.editor:void 0,note=field5?void 0:`\xB7 not used by ${api??"this api"}`;lines.push(renderKeyValueLine(theme2,{keyLabel:key,valueText:value===void 0?"not set":scalarText2(value),active,paneFocused:this.focused,editing,note,width}))}return lines.push(renderPlainLine(theme2,"+ Add Entry",{active:this.index===entries.length&&this.mode.type==="list",paneFocused:this.focused,width})),this.error&&lines.push(theme2.fg("error",truncate3(this.error,Math.max(10,width-2)))),lines}scrollWindow(){return this.mode.type==="chooseValue"?{top:1,cursor:2+this.mode.index}:{top:1,bottom:this.error?1:0,cursor:1+this.index}}handleInput(data){let kb=this.host.keybindings;if(this.mode.type==="editValue"){if(kb.matches(data,"tui.select.up")||kb.matches(data,"tui.select.down"))return;this.mode.editor.handleInput(data),this.host.refresh();return}if(this.mode.type==="chooseValue"){let mode=this.mode;if(kb.matches(data,"tui.select.up")){this.mode={...mode,index:mode.index===0?mode.options.length-1:mode.index-1},this.host.refresh();return}if(kb.matches(data,"tui.select.down")){this.mode={...mode,index:(mode.index+1)%mode.options.length},this.host.refresh();return}if(kb.matches(data,"tui.select.cancel")){this.mode={type:"list"},this.host.refresh();return}if(kb.matches(data,"tui.select.confirm")){let option=mode.options[mode.index];this.mode={type:"list"},this.writeValue(mode.key,this.parseChosen(option))}return}let next=moveSelection(kb,data,this.index,this.rowCount());if(next!==void 0){this.index=next,this.host.refresh();return}if(kb.matches(data,"tui.select.cancel")){this.host.popPane();return}if(kb.matches(data,"app.provider.removeEntry")){let entry=this.entries()[this.index];if(!entry)return;let[key]=entry;this.model.setField(["compat",key],DELETE),this.index=Math.min(this.index,this.rowCount()-2<0?0:this.rowCount()-2);return}if(kb.matches(data,"app.list.toggle")||kb.matches(data,"tui.select.confirm")){this.activateRow();return}}activateRow(){let entries=this.entries();if(this.index===entries.length){let api=this.effectiveApi();if(!api){this.fail("Set API Type first \u2014 compat fields depend on the effective api.");return}if(compatFieldsForApi(api).length===0){this.fail(`No compat fields are known for ${api}.`);return}let taken=new Set(entries.map(([key2])=>key2));this.host.pushPane(new CompatKeyPickerPane(this.host,api,taken,key2=>this.beginValueEntry(key2)));return}let[key,value]=entries[this.index],field5=this.effectiveApi()?compatFieldFor(this.effectiveApi(),key):void 0;if(!field5){this.beginJsonEdit(key,value);return}switch(field5.kind){case"boolean":this.writeValue(key,value!==!0);return;case"enum":this.mode={type:"chooseValue",key,options:field5.options,index:0},this.host.refresh();return;case"number":this.beginTextEdit(key,value);return;case"json":this.beginJsonEdit(key,value);return;case"stringMap":this.host.pushPane(new DictPane(this.host,this.model,key));return}}beginValueEntry(key){let api=this.effectiveApi(),field5=compatFieldFor(api,key);switch(field5.kind){case"boolean":this.mode={type:"chooseValue",key,options:["true","false"],index:0},this.host.refresh();return;case"enum":this.mode={type:"chooseValue",key,options:field5.options,index:0},this.host.refresh();return;case"number":this.beginTextEdit(key,void 0);return;case"json":this.beginJsonEdit(key,void 0);return;case"stringMap":this.writeValue(key,{}),this.host.pushPane(new DictPane(this.host,this.model,key));return}}beginTextEdit(key,current){let editor=new ValueEditor({onCommit:raw=>{let parsed=Number(raw.trim());if(!Number.isFinite(parsed))return this.error=`${key} must be a number.`,this.host.refresh();this.error=void 0,this.mode={type:"list"},this.writeValue(key,parsed)},onCancel:()=>{this.mode={type:"list"},this.error=void 0,this.host.refresh()}});current!==void 0&&editor.beginTweak(String(current)),editor.focused=this.focused,this.mode={type:"editValue",key,editor},this.host.refresh()}beginJsonEdit(key,current){let editor=new ValueEditor({onCommit:raw=>{let text2=raw.trim();if(!text2){this.mode={type:"list"},this.writeValue(key,DELETE);return}let shapeError=validateJsonCompatValue(key,text2);if(shapeError)return this.error=shapeError,this.host.refresh();this.error=void 0,this.mode={type:"list"},this.writeValue(key,JSON.parse(text2))},onCancel:()=>{this.mode={type:"list"},this.error=void 0,this.host.refresh()}});current!==void 0&&editor.beginTweak(JSON.stringify(current)),editor.focused=this.focused,this.mode={type:"editValue",key,editor},this.host.refresh()}parseChosen(option){return option==="true"?!0:option==="false"?!1:option}writeValue(key,value){this.model.setField(["compat",key],value)}fail(message){this.error=message,this.host.refresh()}setFocused(focused){this.focused=focused,this.mode.type==="editValue"&&(this.mode.editor.focused=focused)}isEditing(){return this.mode.type==="editValue"}hints(){return this.mode.type==="editValue"?[keyHint("tui.input.submit","save"),keyHint("tui.select.cancel","cancel")].join(" "):this.mode.type==="chooseValue"?[rawKeyHint("\u2191\u2193","move"),keyHint("tui.select.confirm","set"),keyHint("tui.select.cancel","cancel")].join(" "):[keyHint("tui.select.confirm","edit"),keyHint("app.list.toggle","toggle"),keyHint("app.provider.removeEntry","remove"),keyHint("tui.select.cancel","back")].join(" ")}},CompatKeyPickerPane=class{constructor(host,api,taken,onPick){this.crumb="compat \xB7 new entry",this.query="",this.index=0,this.focused=!1,this.host=host,this.api=api,this.taken=taken,this.onPick=onPick,this.editor=new ValueEditor({onCommit:()=>this.pickCurrent(),onCancel:()=>this.host.popPane()})}candidates(){let available=compatFieldsForApi(this.api).filter(field5=>!this.taken.has(field5.key)),query=this.query.trim();return query?fuzzyFilter(available,query,field5=>`${field5.key} ${field5.note??""}`):available}render(width){let theme2=this.host.theme,lines=[this.editor.renderLine(width)],candidates=this.candidates();candidates.length===0&&lines.push(renderInfoLine(theme2,"No remaining known fields.",width));for(let[rowIndex,field5]of candidates.entries())lines.push(renderPlainLine(theme2,field5.key,{active:rowIndex===this.index,paneFocused:this.focused,note:field5.note?`\xB7 ${field5.kind} \u2014 ${truncate3(field5.note,30)}`:`\xB7 ${field5.kind}`,width}));return lines}scrollWindow(){return{top:1,cursor:1+this.index}}pickCurrent(){let field5=this.candidates()[this.index];field5&&(this.host.popPane(),this.onPick(field5.key))}handleInput(data){let kb=this.host.keybindings;if(kb.matches(data,"tui.select.up")){let count=this.candidates().length;count>0&&(this.index=this.index===0?count-1:this.index-1),this.host.refresh();return}if(kb.matches(data,"tui.select.down")){let count=this.candidates().length;count>0&&(this.index=(this.index+1)%count),this.host.refresh();return}if(kb.matches(data,"tui.select.cancel")){this.host.popPane();return}if(kb.matches(data,"tui.select.confirm")){this.pickCurrent();return}let before=this.query;this.editor.handleInput(data),this.query=this.editor.value,this.query!==before&&(this.index=0),this.host.refresh()}setFocused(focused){this.focused=focused,this.editor.focused=focused}isEditing(){return!0}hints(){return[rawKeyHint("type","filter"),rawKeyHint("\u2191\u2193","move"),keyHint("tui.select.confirm","choose"),keyHint("tui.select.cancel","back")].join(" ")}};function baseUrlHint(api){switch(api){case"openai-responses":case"openai-completions":case"openai-codex-responses":return"baseUrl includes the version path, e.g. https://api.openai.com/v1";case"anthropic-messages":return"baseUrl is the bare origin \u2014 /v1/messages is added automatically";case"mistral-conversations":return"baseUrl is the bare origin \u2014 /v1 is added automatically";case"google-generative-ai":return"baseUrl includes the version path, e.g. https://generativelanguage.googleapis.com/v1beta";default:return}}function validateBaseUrlValue(value){let url;try{url=new URL(value)}catch{return"baseUrl must be a valid URL."}if(url.protocol!=="http:"&&url.protocol!=="https:")return`Unsupported protocol: ${url.protocol}`;if(url.username||url.password||url.hash)return"baseUrl must not contain credentials or a fragment."}var ApiAuthPane=class{constructor(host,registry){this.rows=["baseUrl","apiKey","apiType"],this.index=0,this.focused=!1,this.host=host,this.edit=new InlineEdit(()=>host.refresh()),this.registry=registry}provider(){return this.host.store.getProvider(this.host.providerId)}scrollWindow(){return{cursor:this.index,bottom:this.bottomNoteCount()}}bottomNoteCount(){let status=this.registry.getProviderAuthStatus(this.host.providerId),hint=baseUrlHint(this.provider()?.api);return(this.edit.error?1:0)+(status.configured?1:0)+1+(hint?1:0)}render(width){let theme2=this.host.theme,provider=this.provider(),lines=[];for(let[rowIndex,row]of this.rows.entries()){let active=rowIndex===this.index,value=provider?.[row==="apiType"?"api":row];lines.push(renderKeyValueLine(theme2,{keyLabel:row==="apiType"?"API Type":row,valueText:value?row==="apiKey"?maskApiKey(value):value:"not set",unset:!value,active,paneFocused:this.focused,editing:row==="apiType"?void 0:this.edit.editor(row),width}))}this.edit.error&&lines.push(theme2.fg("error",truncate3(this.edit.error,Math.max(10,width-2))));let status=this.registry.getProviderAuthStatus(this.host.providerId);status.configured&&status.source==="stored"?lines.push(renderInfoLine(theme2,"A stored credential (auth.json) takes precedence over the apiKey here.",width)):status.configured&&status.source==="environment"&&lines.push(renderInfoLine(theme2,`An environment variable (${status.label??"env"}) currently provides the key.`,width)),lines.push(renderInfoLine(theme2,"Values are stored raw; $VAR / !command references resolve at request time.",width));let hint=baseUrlHint(provider?.api);return hint&&lines.push(renderInfoLine(theme2,hint,width)),lines}handleInput(data){let kb=this.host.keybindings;if(this.edit.handleInput(data,kb))return;let next=moveSelection(kb,data,this.index,this.rows.length);if(next!==void 0){this.index=next,this.host.refresh();return}if(kb.matches(data,"tui.select.cancel")){this.host.popPane();return}if(kb.matches(data,"tui.select.confirm")){this.rows[this.index]==="apiType"?this.host.pushPane(createProviderApiPane(this.host)):this.beginEdit("tweak");return}if(isPrintableInput(data)){if(this.rows[this.index]==="apiType")return;this.beginEdit("overwrite",data);return}}beginEdit(mode,firstData){let row=this.rows[this.index];row!=="apiType"&&this.edit.begin(row,this.provider()?.[row]??"",mode,this.focused,value=>this.commit(row,value),firstData)}commit(row,raw){let value=raw.trim();if(row==="baseUrl"&&value){let invalid2=validateBaseUrlValue(value);if(invalid2)return invalid2}if(row==="baseUrl"&&!value){let builtin=builtinDefaults(this.host.providerId).baseUrl!==void 0,modelsCovered=this.host.store.getModels(this.host.providerId).every(model=>model.baseUrl!==void 0);if(!builtin&&!modelsCovered&&this.host.store.getModels(this.host.providerId).length>0)return"baseUrl cannot be removed while models rely on it."}this.host.edits.setProviderField([row],value===""?DELETE:value)}setFocused(focused){this.focused=focused,this.edit.setFocused(focused)}isEditing(){return this.edit.editing}hints(){return this.edit.editing?[keyHint("tui.input.submit","save"),keyHint("tui.select.cancel","cancel")].join(" "):[rawKeyHint("type","overwrite"),keyHint("tui.select.confirm","edit / open"),keyHint("tui.select.cancel","back")].join(" ")}};function createProviderApiPane(host){let current=()=>host.store.getProvider(host.providerId)?.api;return new ChoicePane(host,"API Type",{current,choices:()=>{let fallback=builtinDefaults(host.providerId).api,label=fallback?`not set (built-in default: ${fallback})`:"not set (models define their own)",values=[void 0,...API_TYPES],value=current();return value&&!values.includes(value)&&values.push(value),values.map(value2=>({value:value2,label:value2??label,dim:value2===void 0}))},choose:api=>{if(api===void 0){let uncovered=host.store.getModels(host.providerId).filter(model=>!model.api&&!builtinDefaults(host.providerId,model.id).api);if(uncovered.length)return uncovered.length===1?`Model "${uncovered[0].id}" resolves its API from here \u2014 give it a model-level API first.`:`${uncovered.length} ${plural(uncovered.length,"model")} resolve their API from here \u2014 give them model-level APIs first.`}host.edits.setProviderField(["api"],api??DELETE)}})}var REASONING_OPTIONS=[{label:"true",value:!0},{label:"false",value:!1},{label:"default (false)",value:void 0}];function createReasoningPane(host,model){return new ChoicePane(host,"reasoning",{current:()=>model.read().reasoning,choices:()=>REASONING_OPTIONS.map(option=>({...option,dim:option.value===void 0})),choose:value=>{model.setField(["reasoning"],value===void 0?DELETE:value)}})}var InputTypesPane=class{constructor(host,model){this.crumb="input",this.index=0,this.focused=!1,this.host=host,this.model=model}selected(){return new Set(this.model.read().input??["text"])}render(width){let theme2=this.host.theme,selected=this.selected(),lines=INPUT_TYPES.map((type,rowIndex)=>renderPlainLine(theme2,type,{checked:selected.has(type),active:rowIndex===this.index,paneFocused:this.focused,width}));return this.model.read().input===void 0&&lines.push(renderInfoLine(theme2,"Not set \u2014 the runtime default is [text].",width)),this.error&&lines.push(theme2.fg("error",truncate3(this.error,Math.max(10,width-2)))),lines}handleInput(data){let kb=this.host.keybindings,next=moveSelection(kb,data,this.index,INPUT_TYPES.length);if(next!==void 0){this.index=next,this.host.refresh();return}if(kb.matches(data,"app.list.toggle")){let type=INPUT_TYPES[this.index],selected=this.selected();if(selected.has(type)){if(selected.size===1){this.error="At least one input type must stay selected.",this.host.refresh();return}selected.delete(type)}else selected.add(type);this.error=void 0;let next2=INPUT_TYPES.filter(entry=>selected.has(entry));this.model.setField(["input"],[...next2]);return}if(kb.matches(data,"tui.select.confirm")||kb.matches(data,"tui.select.cancel")){this.host.popPane();return}}setFocused(focused){this.focused=focused}hints(){return[keyHint("app.list.toggle","toggle"),keyHint("tui.select.confirm","done"),keyHint("tui.select.cancel","back")].join(" ")}},COST_RATES=["input","output","cacheRead","cacheWrite"],CostPane=class{constructor(host,model){this.crumb="cost",this.index=0,this.focused=!1,this.host=host,this.edit=new InlineEdit(()=>host.refresh()),this.model=model}cost(){let cost=this.model.read().cost;if(cost)return{input:cost.input,output:cost.output,cacheRead:cost.cacheRead,cacheWrite:cost.cacheWrite}}render(width){let theme2=this.host.theme,cost=this.cost(),lines=[];for(let[rowIndex,rate]of COST_RATES.entries()){let value=cost?.[rate];lines.push(renderKeyValueLine(theme2,{keyLabel:rate,valueText:value===void 0?"0 (default)":`$${value} / M tokens`,unset:value===void 0,active:rowIndex===this.index,paneFocused:this.focused,editing:this.edit.editor(rate),width}))}let tiers=this.model.read().cost?.tiers;return tiers&&tiers.length>0&&lines.push(renderInfoLine(theme2,`tiers: ${tiers.length} (read-only; kept as-is)`,width)),this.edit.error&&lines.push(theme2.fg("error",truncate3(this.edit.error,Math.max(10,width-2)))),lines}handleInput(data){let kb=this.host.keybindings;if(this.edit.handleInput(data,kb))return;let next=moveSelection(kb,data,this.index,COST_RATES.length);if(next!==void 0){this.index=next,this.host.refresh();return}if(kb.matches(data,"tui.select.cancel")){this.host.popPane();return}if(kb.matches(data,"tui.select.confirm")){this.beginEdit("tweak");return}if(isPrintableInput(data)){this.beginEdit("overwrite",data);return}}beginEdit(mode,firstData){let rate=COST_RATES[this.index],current=this.cost()?.[rate];this.edit.begin(rate,current===void 0?"":String(current),mode,this.focused,value=>this.commit(rate,value),firstData)}commit(rate,raw){let value=raw.trim(),parsed=value===""?0:Number(value);if(!Number.isFinite(parsed)||parsed<0)return"cost rates must be finite non-negative numbers.";this.model.read().cost?this.model.setField(["cost",rate],parsed):this.model.setField(["cost"],{input:0,output:0,cacheRead:0,cacheWrite:0,[rate]:parsed})}setFocused(focused){this.focused=focused,this.edit.setFocused(focused)}isEditing(){return this.edit.editing}hints(){return this.edit.editing?[keyHint("tui.input.submit","save"),keyHint("tui.select.cancel","cancel")].join(" "):[rawKeyHint("type","overwrite"),keyHint("tui.select.confirm","edit"),keyHint("tui.select.cancel","back")].join(" ")}},ModelSpecificApiPane=class{constructor(host,model){this.crumb="Model-Specific API",this.rows=["baseUrl","apiType"],this.index=0,this.focused=!1,this.host=host,this.edit=new InlineEdit(()=>host.refresh()),this.model=model}inherited(key){let provider=this.host.store.getProvider(this.host.providerId),providerValue=key==="api"?provider?.api:provider?.baseUrl;if(providerValue)return{value:providerValue,via:"provider"};let current=this.model.read(),effective=key==="api"?this.host.effectiveApi(current):this.host.effectiveBaseUrl(current);return effective?{value:effective,via:"built-in"}:void 0}render(width){let theme2=this.host.theme,current=this.model.read(),lines=[];for(let[rowIndex,row]of this.rows.entries()){let active=rowIndex===this.index,key=row==="apiType"?"api":row,override=current[key],inherited=override?void 0:this.inherited(key);lines.push(renderKeyValueLine(theme2,{keyLabel:row==="apiType"?"API Type":row,valueText:override??inherited?.value??"not set",unset:!override,note:inherited?`\xB7 ${inherited.via}`:void 0,active,paneFocused:this.focused,editing:row==="baseUrl"?this.edit.editor(row):void 0,width}))}this.edit.error&&lines.push(theme2.fg("error",truncate3(this.edit.error,Math.max(10,width-2))));let hint=baseUrlHint(this.host.effectiveApi(current));return hint&&lines.push(renderInfoLine(theme2,hint,width)),lines}handleInput(data){let kb=this.host.keybindings;if(this.edit.handleInput(data,kb))return;let next=moveSelection(kb,data,this.index,this.rows.length);if(next!==void 0){this.index=next,this.host.refresh();return}if(kb.matches(data,"tui.select.cancel")){this.host.popPane();return}if(kb.matches(data,"tui.select.confirm")){this.rows[this.index]==="apiType"?this.host.pushPane(createModelApiPane(this.host,this.model)):this.beginEdit("tweak");return}if(isPrintableInput(data)){if(this.rows[this.index]==="apiType")return;this.beginEdit("overwrite",data);return}}beginEdit(mode,firstData){let base=this.model.read().baseUrl??this.inherited("baseUrl")?.value??"";this.edit.begin("baseUrl",base,mode,this.focused,value=>this.commit(value),firstData)}commit(raw){let value=raw.trim();if(value){let invalid2=validateBaseUrlValue(value);if(invalid2)return invalid2}this.model.setField(["baseUrl"],value===""?DELETE:value)}setFocused(focused){this.focused=focused,this.edit.setFocused(focused)}isEditing(){return this.edit.editing}hints(){return this.edit.editing?[keyHint("tui.input.submit","save"),keyHint("tui.select.cancel","cancel")].join(" "):[rawKeyHint("type","overwrite"),keyHint("tui.select.confirm","edit / open"),keyHint("tui.select.cancel","back")].join(" ")}};function createModelApiPane(host,model){let fallback=()=>{let provider=host.store.getProvider(host.providerId);return provider?.api??builtinDefaults(host.providerId,model.read().id,provider?.api).api};return new ChoicePane(host,"API Type",{current:()=>model.read().api,choices:()=>{let providerApi=host.store.getProvider(host.providerId)?.api,inherited=fallback(),label=providerApi?`provider: ${providerApi}`:inherited?`built-in: ${inherited}`:"no provider or built-in API",values=[void 0,...API_TYPES],current=model.read().api;return current&&!values.includes(current)&&values.push(current),values.map(value=>({value,label:value??label,dim:value===void 0}))},choose:value=>{if(value===void 0&&!fallback())return"Nothing to inherit \u2014 pick an API.";model.setField(["api"],value??DELETE)}})}var ThinkingMapPane=class{constructor(host,model){this.crumb="thinkingLevelMap",this.mode={type:"levels"},this.index=0,this.focused=!1,this.host=host,this.model=model}map(){return this.model.read().thinkingLevelMap??{}}render(width){let theme2=this.host.theme,lines=[];if(this.model.read().reasoning!==!0&&lines.push(renderInfoLine(theme2,"reasoning is not true \u2014 the map is stored but currently has no effect.",width)),this.mode.type==="levels")for(let[rowIndex,level]of THINKING_LEVELS4.entries()){let value=this.map()[level],status=value===void 0?"default":value===null?"null (hidden)":value;lines.push(renderKeyValueLine(theme2,{keyLabel:level,valueText:status,unset:value===void 0,active:rowIndex===this.index,paneFocused:this.focused,width}))}else if(this.mode.type==="choice"){lines.push(renderInfoLine(theme2,`${this.mode.level} \xB7 mapping`,width));for(let[choiceIndex,label]of["String target (provider effort)","Hidden (null)","Default (remove key)"].entries())lines.push(renderPlainLine(theme2,label,{active:choiceIndex===this.mode.index,paneFocused:this.focused,width}))}else lines.push(renderInfoLine(theme2,`${this.mode.level} \xB7 non-empty provider effort`,width)),lines.push(renderKeyValueLine(theme2,{keyLabel:this.mode.level,active:!0,paneFocused:this.focused,editing:this.editor,width}));return this.error&&lines.push(theme2.fg("error",truncate3(this.error,Math.max(10,width-2)))),lines}handleInput(data){let kb=this.host.keybindings;if(this.mode.type==="target"){if(kb.matches(data,"tui.select.up")||kb.matches(data,"tui.select.down"))return;this.editor?.handleInput(data),this.host.refresh();return}if(this.mode.type==="choice"){if(kb.matches(data,"tui.select.up")){this.mode={...this.mode,index:this.mode.index===0?2:this.mode.index-1},this.host.refresh();return}if(kb.matches(data,"tui.select.down")){this.mode={...this.mode,index:(this.mode.index+1)%3},this.host.refresh();return}if(kb.matches(data,"tui.select.cancel")){this.mode={type:"levels"},this.host.refresh();return}if(kb.matches(data,"tui.select.confirm")){let{level,index:index3}=this.mode;if(index3===0){let editor=new ValueEditor({onCommit:value=>{let target=value.trim();if(!target)return this.error="A string target must be non-empty; use Hidden for null.",this.host.refresh();this.error=void 0,this.mode={type:"levels"},this.editor=void 0,this.model.setField(["thinkingLevelMap",level],target)},onCancel:()=>{this.editor=void 0,this.mode={type:"levels"},this.host.refresh()}});this.editor=editor,editor.focused=this.focused;let existing=this.map()[level];typeof existing=="string"&&editor.beginTweak(existing),this.mode={type:"target",level},this.host.refresh();return}this.mode={type:"levels"},this.model.setField(["thinkingLevelMap",level],index3===1?null:DELETE);return}return}let next=moveSelection(kb,data,this.index,THINKING_LEVELS4.length);if(next!==void 0){this.index=next,this.host.refresh();return}if(kb.matches(data,"tui.select.confirm")){this.mode={type:"choice",level:THINKING_LEVELS4[this.index],index:0},this.host.refresh();return}if(kb.matches(data,"tui.select.cancel")){this.host.popPane();return}}setFocused(focused){this.focused=focused,this.editor&&(this.editor.focused=focused&&this.mode.type==="target")}isEditing(){return this.mode.type==="target"}hints(){return this.mode.type==="target"?[keyHint("tui.input.submit","save"),keyHint("tui.select.cancel","back")].join(" "):[rawKeyHint("\u2191\u2193","move"),keyHint("tui.select.confirm",this.mode.type==="choice"?"set":"edit"),keyHint("tui.select.cancel","back")].join(" ")}};var DEFAULT_CONTEXT_WINDOW2=128e3,DEFAULT_MAX_TOKENS2=16384,ModelFieldsPane=class{constructor(host,model){this.index=0,this.focused=!1,this.renaming=!1,this.disposed=!1,this.host=host,this.model=model;let rows=[{kind:"text",key:"id"},{kind:"text",key:"name"},{kind:"reasoning"},{kind:"subpage",key:"thinkingLevelMap"},{kind:"subpage",key:"input"},{kind:"subpage",key:"cost"},{kind:"number",key:"contextWindow"},{kind:"number",key:"maxTokens"},{kind:"subpage",key:"compat"}];model.isDraft?rows.push({kind:"modelApi"}):rows.push({kind:"builtin"},{kind:"modelApi"},{kind:"deleteModel"}),this.rows=rows}startEditingId(){this.index=0,this.beginEdit("overwrite")}draftEmpty(){return this.model.isDraft&&Object.keys(this.model.read()).length===0}render(width){let theme2=this.host.theme,current=this.model.read(),lines=[],api=this.host.effectiveApi(current);lines.push(renderInfoLine(theme2,api?`api: ${api}${current.api?" (model)":""}`:"api: none resolved \u2014 see Model-Specific API below",width));for(let[rowIndex,row]of this.rows.entries()){let active=rowIndex===this.index;lines.push(this.renderRow(row,current,active,width))}return this.error&&lines.push(theme2.fg("error",truncate3(this.error,Math.max(10,width-2)))),this.renaming&&lines.push(renderInfoLine(theme2,"Saving model id\u2026",width)),lines}scrollWindow(){return{top:1,bottom:(this.error?1:0)+(this.renaming?1:0),cursor:1+this.index}}renderRow(row,current,active,width){let theme2=this.host.theme,editing=this.editingRow===row?this.editing:void 0;switch(row.kind){case"text":{let value=current[row.key],unsetText=row.key==="id"?"required":"falls back to id";return renderKeyValueLine(theme2,{keyLabel:row.key,valueText:value??`not set (${unsetText})`,unset:!value,active,paneFocused:this.focused,editing,width})}case"reasoning":{let value=current.reasoning;return renderKeyValueLine(theme2,{keyLabel:"reasoning",valueText:value===void 0?"false (default)":String(value),unset:value===void 0,active,paneFocused:this.focused,width})}case"subpage":{let summary=this.subpageSummary(row.key,current);return renderKeyValueLine(theme2,{keyLabel:row.key,valueText:summary.text,unset:summary.unset,active,paneFocused:this.focused,width})}case"number":{let value=current[row.key],fallback=row.key==="contextWindow"?DEFAULT_CONTEXT_WINDOW2:DEFAULT_MAX_TOKENS2;return renderKeyValueLine(theme2,{keyLabel:row.key,valueText:value===void 0?`${fallback} (default)`:String(value),unset:value===void 0,active,paneFocused:this.focused,editing,width})}case"builtin":{let id=current.id,count=id?matchBuiltinModels(id,this.host.effectiveApi(current)).length:0;return renderKeyValueLine(theme2,{valueText:"Use Built-in Data",active,paneFocused:this.focused,note:id?`\xB7 ${count} ${plural(count,"candidate")}`:"\xB7 set id first",width})}case"modelApi":return renderKeyValueLine(theme2,{valueText:"Model-Specific API",active,paneFocused:this.focused,note:`\xB7 ${this.modelApiSummary(current)}`,width});case"deleteModel":return renderKeyValueLine(theme2,{valueText:"Delete Model",active,paneFocused:this.focused,width})}}modelApiSummary(current){let overrides=[current.baseUrl?"baseUrl":"",current.api?"API Type":""].filter(Boolean);if(overrides.length>0)return overrides.join(" + ");let provider=this.host.store.getProvider(this.host.providerId);return provider?.api||provider?.baseUrl?"provider defaults":this.host.effectiveApi(current)||this.host.effectiveBaseUrl(current)?"built-in defaults":"not set"}subpageSummary(key,current){switch(key){case"thinkingLevelMap":{let map=current.thinkingLevelMap,count=map?Object.keys(map).length:0;return count>0?{text:`${count} ${plural(count,"mapping")}`,unset:!1}:{text:"default",unset:!0}}case"input":return current.input?{text:`[${current.input.join(", ")}]`,unset:!1}:{text:"[text] (default)",unset:!0};case"cost":{let cost=current.cost;return cost?{text:`$${cost.input} / $${cost.output} in/out`,unset:!1}:{text:"all 0 (default)",unset:!0}}case"compat":{let compat=current.compat,count=compat?Object.keys(compat).length:0;if(count>0)return{text:`${count} ${count===1?"entry":"entries"}`,unset:!1};let inherited=this.host.store.getProvider(this.host.providerId)?.compat,inheritedCount=inherited?Object.keys(inherited).length:0;return inheritedCount>0?{text:`${inheritedCount} from provider`,unset:!0}:{text:"none",unset:!0}}}}handleInput(data){if(this.renaming||this.disposed)return;let kb=this.host.keybindings;if(this.editing){if(kb.matches(data,"tui.select.up")||kb.matches(data,"tui.select.down"))return;this.editing.handleInput(data),this.host.refresh();return}let next=moveSelection(kb,data,this.index,this.rows.length);if(next!==void 0){this.index=next,this.host.refresh();return}if(kb.matches(data,"tui.select.cancel")){if(!this.model.isDraft){this.host.popPane();return}if(this.draftEmpty()){this.host.discardModelDraft();return}let label=this.model.read().name??this.model.read().id??"New Model";this.host.confirm(`Discard the new model "${label}"? Its fields are not saved.`,"Discard Model",()=>this.host.discardModelDraft());return}if(kb.matches(data,"app.list.toggle")){this.toggleRow();return}if(kb.matches(data,"tui.select.confirm")){this.enterRow();return}if(isPrintableInput(data)){this.overwriteRow(data);return}}toggleRow(){if(this.rows[this.index].kind!=="reasoning")return;let current=this.model.read().reasoning;this.model.setField(["reasoning"],current!==!0)}enterRow(){let row=this.rows[this.index];switch(row.kind){case"text":case"number":this.beginEdit("tweak");return;case"reasoning":this.host.pushPane(createReasoningPane(this.host,this.model));return;case"subpage":this.pushSubpage(row.key);return;case"modelApi":this.host.pushPane(new ModelSpecificApiPane(this.host,this.model));return;case"builtin":{if(!this.model.read().id){this.host.notify("Set the model id first.","warning");return}this.host.pushPane(new BuiltinCandidatesPane(this.host,this.model));return}case"deleteModel":{let id=this.model.read().id;if(!id)return;if(this.host.isCurrentModel(id)){this.host.notify("The current model cannot be deleted; switch models with /model first.","error");return}this.host.confirm(`Delete model "${id}" from ${this.host.providerId}?`,"Delete Model",()=>{this.host.edits.removeModel(id),this.host.onModelRemoved(id)});return}}}overwriteRow(data){let row=this.rows[this.index];if(row.kind==="text"||row.kind==="number"){this.beginEdit("overwrite",data);return}}beginEdit(mode,firstData){let row=this.rows[this.index];if(row.kind!=="text"&&row.kind!=="number")return;let current=this.model.read()[row.key],editor=new ValueEditor({onCommit:value=>this.commitText(row,value),onCancel:()=>{if(this.editing=void 0,this.editingRow=void 0,this.error=void 0,this.draftEmpty()){this.host.discardModelDraft();return}this.host.refresh()}});this.editing=editor,this.editingRow=row,editor.focused=this.focused,mode==="overwrite"?editor.beginOverwrite(firstData):editor.beginTweak(current===void 0?"":String(current)),this.host.refresh()}commitText(row,raw){let value=raw.trim(),finish=error=>{if(this.error=error,error){this.host.refresh();return}this.editing=void 0,this.editingRow=void 0,this.host.refresh()};if(row.key==="id"){if(!value){finish("id is required and cannot be empty.");return}if(this.model.isDraft){this.model.setField(["id"],value),finish(this.host.commitModelDraft());return}let current=this.model.read().id;if(!current){finish("Missing current id.");return}if(value===current){finish();return}if(this.host.isCurrentModel(current)){finish("The current model's id cannot be renamed; switch models with /model first.");return}if(this.host.store.getModel(this.host.providerId,value)){finish(`Model "${value}" already exists.`);return}this.renaming=!0,this.host.refresh(),this.model.rename(value).then(error=>{this.renaming=!1,this.disposed||finish(error)},error=>{this.renaming=!1,this.disposed||finish(error instanceof Error?error.message:String(error))});return}if(row.key==="name"){this.model.setField(["name"],value===""?DELETE:value),finish();return}if(value===""){this.model.setField([row.key],DELETE),finish();return}let parsed=Number(value);if(!Number.isSafeInteger(parsed)||parsed<=0){finish(`${row.key} must be a positive integer.`);return}this.model.setField([row.key],parsed),finish()}pushSubpage(key){switch(key){case"thinkingLevelMap":this.host.pushPane(new ThinkingMapPane(this.host,this.model));return;case"input":this.host.pushPane(new InputTypesPane(this.host,this.model));return;case"cost":this.host.pushPane(new CostPane(this.host,this.model));return;case"compat":this.host.pushPane(new CompatPane(this.host,this.model));return}}setFocused(focused){this.focused=focused,this.editing&&(this.editing.focused=focused)}isEditing(){return this.editing!==void 0||this.renaming}dispose(){this.disposed=!0}hints(){return this.editing?[keyHint("tui.input.submit","save"),keyHint("tui.select.cancel","cancel")].join(" "):[rawKeyHint("type","overwrite"),keyHint("tui.select.confirm","edit / open"),keyHint("app.list.toggle","toggle"),keyHint("tui.select.cancel",this.model.isDraft?"discard":"back")].join(" ")}};var LEFT_WIDTH_MIN=16,LEFT_WIDTH_MAX=40,BODY_ROWS=14,MIN_WIDTH=56;function padTo(line,width){let missing=width-visibleWidth(line);return missing>0?line+" ".repeat(missing):line}function leftItemKey(item){return item?item.kind==="model"?`model:${item.modelId}`:item.kind:""}var ProviderEditorScreen=class{constructor(tui,theme2,keybindings,done,options){this.leftItems=[],this.leftIndex=0,this.focusPane="left",this.stack=[],this.disposed=!1,this._focused=!1,this.tui=tui,this.theme=theme2,this.keybindings=keybindings,this.done=done,this.options=options,this.edits=new ProviderEdits(options.store,options.providerId,options.refresher,()=>this.refresh()),this.host=this.createHost(),this.rebuildLeftItems(),this.resetRightStack()}get focused(){return this._focused}set focused(value){this._focused=value,this.topPane()?.setFocused(value&&this.focusPane==="right")}invalidate(){this.cache=void 0}dispose(){if(!this.disposed){this.disposed=!0;for(let pane of this.stack)pane.dispose?.();this.stack=[],hasProviderSettings(this.options.store.getProvider(this.options.providerId))||this.options.store.discardProviderDraft(this.options.providerId)}}render(width){if(this.cache&&this.cache.width===width)return this.cache.lines;let lines=this.renderFrame(width);return this.cache={width,lines},lines}handleInput(data){if(this.focusPane==="right"){let pane=this.topPane();if(pane&&!pane.isEditing?.()&&this.keybindings.matches(data,"app.provider.switchPaneLeft")){pane.setFocused(!1),this.focusPane="left",this.refresh();return}pane?.handleInput(data);return}let kb=this.keybindings;if(kb.matches(data,"tui.select.up")){this.moveLeft(-1);return}if(kb.matches(data,"tui.select.down")){this.moveLeft(1);return}if(kb.matches(data,"app.provider.switchPaneRight")){this.activateLeftItem("inspect");return}if(kb.matches(data,"tui.select.confirm")){this.activateLeftItem("activate");return}kb.matches(data,"tui.select.cancel")&&this.done("back")}syncFromStore(){if(this.disposed||this.edits.renaming)return;let selected=this.leftItems[this.leftIndex],selectedKey=leftItemKey(selected);this.rebuildLeftItems();let nextIndex=this.leftItems.findIndex(item=>leftItemKey(item)===selectedKey);this.leftIndex=nextIndex>=0?nextIndex:Math.min(this.leftIndex,this.selectableIndex(0)),nextIndex<0&&selected?.kind==="model"&&this.resetRightStack(),this.refresh()}rebuildLeftItems(){let items=[{kind:"apiAuth"},{kind:"fetch"},{kind:"separator"}];for(let model of this.options.store.getModels(this.options.providerId))items.push({kind:"model",modelId:model.id});this.draft&&items.push({kind:"draft"}),items.push({kind:"separator"},{kind:"addModel"},{kind:"deleteProvider"}),this.leftItems=items}selectableIndex(start){let index3=this.leftItems.findIndex((item,i)=>i>=start&&item.kind!=="separator");return index3>=0?index3:0}moveLeft(delta){let selectable=this.leftItems.map((item,index3)=>({item,index:index3})).filter(entry=>entry.item.kind!=="separator");if(selectable.length===0)return;let position=selectable.findIndex(entry=>entry.index===this.leftIndex),next=selectable[(position+delta+selectable.length)%selectable.length];next.index!==this.leftIndex&&(this.leftIndex=next.index,this.resetRightStack(),this.refresh())}activateLeftItem(via){let item=this.leftItems[this.leftIndex];if(item)switch(item.kind){case"apiAuth":case"model":case"draft":this.focusPane="right",this.topPane()?.setFocused(this._focused),this.refresh();return;case"fetch":if(this.focusPane="right",via==="activate"){let pane=this.topPane();pane instanceof FetchModelsPane&&pane.start()}this.topPane()?.setFocused(this._focused),this.refresh();return;case"addModel":{if(via==="inspect"){this.focusPane="right",this.topPane()?.setFocused(this._focused),this.refresh();return}this.draft||(this.draft=this.edits.draft(),this.rebuildLeftItems());let draftIndex=this.leftItems.findIndex(entry=>entry.kind==="draft");draftIndex>=0&&(this.leftIndex=draftIndex),this.resetRightStack(),this.focusPane="right";let pane=this.topPane();pane?.setFocused(this._focused),pane instanceof ModelFieldsPane&&!this.draft.read().id&&pane.startEditingId(),this.refresh();return}case"deleteProvider":{if(via==="inspect"){this.focusPane="right",this.topPane()?.setFocused(this._focused),this.refresh();return}if(this.host.isCurrentProvider()){this.host.notify("The current model's provider cannot be deleted; switch models with /model first.","error");return}let builtin=isBuiltinProviderId(this.options.providerId);this.host.confirm(`Delete provider "${this.options.providerId}" from models.json?`+(builtin?" The built-in catalog remains and its models may reappear.":"")+" Stored credentials in auth.json are kept.","Delete Provider",()=>{this.edits.removeProvider(),this.done("deleted")});return}default:return}}renderLeft(width){let theme2=this.theme,focused=this.focusPane==="left",rows=[],renderRow=index3=>{let item=this.leftItems[index3];return item.kind==="separator"?theme2.fg("borderMuted",` ${"\u2500".repeat(Math.max(1,width-4))}`):this.renderLeftItem(item,index3===this.leftIndex,focused,width)};if(this.leftItems.length<=BODY_ROWS)for(let index3=0;index3<this.leftItems.length;index3++)rows.push(renderRow(index3));else{let slots=BODY_ROWS-1,start=Math.max(0,Math.min(this.leftIndex-Math.floor(slots/2),this.leftItems.length-slots));for(let index3=start;index3<start+slots;index3++)rows.push(renderRow(index3));let selectable=this.leftItems.filter(item=>item.kind!=="separator"),position=selectable.indexOf(this.leftItems[this.leftIndex]);rows.push(theme2.fg("dim",` (${position+1}/${selectable.length})`))}for(;rows.length<BODY_ROWS;)rows.push("");return rows}leftItemContent(item){let store=this.options.store,text2,note;switch(item.kind){case"apiAuth":text2="API Auth";break;case"fetch":text2="Fetch Models",note=this.fetchStatus;break;case"model":{let model=store.getModel(this.options.providerId,item.modelId);text2=model?modelDisplayName(model):item.modelId;break}case"draft":{text2=this.draft?.read().name??this.draft?.read().id??"New Model",note="\xB7 draft";break}case"addModel":text2="+ Add Model";break;case"deleteProvider":text2="Delete Provider";break;default:text2=""}let dim=item.kind==="draft"&&!this.draft?.read().name&&!this.draft?.read().id;return{text:text2,note,dim}}renderLeftItem(item,active,focused,width){let theme2=this.theme,lit=active&&focused,marker=lit?theme2.fg("accent",`${CURSOR2} `):" ",style=(text3,dim2=!1)=>theme2.fg(lit?"accent":dim2?"dim":"text",text3),{text:label,note,dim}=this.leftItemContent(item),text2=label;if(item.kind==="model"||item.kind==="draft"){let budget=Math.max(8,width-2-(note?visibleWidth(note)+1:0));text2=truncateMiddle2(text2,budget)}let noteText=note?theme2.fg("dim",` ${note}`):"";return truncateToWidth(marker+style(text2,dim)+noteText,width)}topPane(){return this.stack[this.stack.length-1]}pushPane(pane){this.topPane()?.setFocused(!1),this.focusPane="right",this.stack.push(pane),pane.setFocused(this._focused&&this.focusPane==="right"),this.refresh()}popPane(){if(this.stack.length<=1){this.topPane()?.setFocused(!1),this.focusPane="left",this.refresh();return}let pane=this.stack.pop();pane?.setFocused(!1),pane?.dispose?.(),this.topPane()?.setFocused(this._focused&&this.focusPane==="right"),this.refresh()}resetRightStack(){for(let pane of this.stack)pane.dispose?.();let item=this.leftItems[this.leftIndex];this.stack=[this.createBasePane(item)],this.topPane()?.setFocused(this._focused&&this.focusPane==="right")}createBasePane(item){switch(item?.kind){case"apiAuth":return new ApiAuthPane(this.host,this.options.registry);case"fetch":return new FetchModelsPane(this.host);case"model":return new ModelFieldsPane(this.host,this.persistedHandle(item.modelId));case"draft":return new ModelFieldsPane(this.host,this.draft);case"addModel":return new InfoPane(this.host,["Press Enter to create a model.","A draft is kept in memory until its id is set; Esc on the draft discards it."],()=>this.activateLeftItem("activate"));case"deleteProvider":return new InfoPane(this.host,["Press Enter to delete this provider from models.json."],()=>this.activateLeftItem("activate"));default:return new InfoPane(this.host,[])}}persistedHandle(modelId){return this.edits.model(modelId,(oldId,newId)=>{let selected=this.leftItems[this.leftIndex];selected?.kind==="model"&&selected.modelId===oldId&&(selected.modelId=newId),this.syncFromStore()})}createHost(){let store=this.options.store,providerId=this.options.providerId;return{tui:this.tui,theme:this.theme,keybindings:this.keybindings,store,edits:this.edits,providerId,pushPane:pane=>this.pushPane(pane),popPane:()=>this.popPane(),refresh:()=>this.refresh(),notify:(message,type)=>this.options.notify(message,type),effectiveApi:model=>effectiveModelSettings(providerId,store.getProvider(providerId),model).api,effectiveBaseUrl:model=>effectiveModelSettings(providerId,store.getProvider(providerId),model).baseUrl,commitModelDraft:()=>this.commitModelDraft(),discardModelDraft:()=>this.discardModelDraft(),isCurrentModel:modelId=>this.options.currentModel?.provider===providerId&&this.options.currentModel.id===modelId,isCurrentProvider:()=>this.options.currentModel?.provider===providerId,setFetchStatus:status=>{this.fetchStatus=status,this.refresh()},runFetch:signal=>fetchProviderModels(this.options,signal),importModels:async(models,signal)=>{let error=await importProviderModels({...this.options,edits:this.edits},models,signal);return this.disposed||this.syncFromStore(),error},confirm:(message,actionLabel,action)=>this.pushPane(new ConfirmPane(this.host,message,actionLabel,action)),onModelRemoved:()=>{for(this.rebuildLeftItems(),this.leftIndex=Math.min(this.leftIndex,this.leftItems.length-1);this.leftIndex>0&&this.leftItems[this.leftIndex]?.kind==="separator";)this.leftIndex--;this.leftItems[this.leftIndex]?.kind==="separator"&&(this.leftIndex=this.selectableIndex(0)),this.focusPane="left",this.resetRightStack(),this.refresh()}}}discardModelDraft(){if(!this.draft)return;this.draft=void 0,this.rebuildLeftItems();let addIndex=this.leftItems.findIndex(item=>item.kind==="addModel");this.leftIndex=addIndex>=0?addIndex:this.selectableIndex(0),this.focusPane="left",this.resetRightStack(),this.refresh()}commitModelDraft(){let draft=this.draft;if(!draft)return"No model draft.";let error=this.edits.commitDraft(draft);if(error)return error;let id=draft.read().id.trim();this.draft=void 0,this.rebuildLeftItems();let index3=this.leftItems.findIndex(item=>item.kind==="model"&&item.modelId===id);index3>=0&&(this.leftIndex=index3),this.resetRightStack(),this.refresh()}refresh(){this.invalidate(),this.tui.requestRender()}renderFrame(width){let theme2=this.theme,border=new DynamicBorder(text2=>theme2.fg("border",text2)).render(width)[0];if(width<MIN_WIDTH)return[border,truncateToWidth(theme2.fg("warning",` /provider needs at least ${MIN_WIDTH} columns`),width),border];let leftWidth=this.computeLeftWidth(width),rightWidth=width-leftWidth-3,separator=theme2.fg("border"," \u2502 "),title=this.renderTitle(width),crumb=truncateToWidth(this.theme.fg("muted",this.topPane()?.crumb??""),rightWidth),leftLines=this.renderLeft(leftWidth),pane=this.topPane(),paneLines=pane?windowLines(theme2,pane.render(rightWidth),BODY_ROWS-1,pane.scrollWindow?.()):[],rightLines=[crumb,...paneLines],body2=[];for(let row=0;row<BODY_ROWS;row++){let left=padTo(truncateToWidth(leftLines[row]??"",leftWidth),leftWidth),right=truncateToWidth(rightLines[row]??"",rightWidth);body2.push(left+separator+right)}let footerLines=this.renderFooter(width);return[border,title,border,...body2,border,...footerLines,border]}computeLeftWidth(width){let longest=12;for(let item of this.leftItems){if(item.kind==="separator")continue;let{text:text2,note}=this.leftItemContent(item),label=text2+(note?` ${note}`:"");longest=Math.max(longest,visibleWidth(label))}let fit=Math.max(LEFT_WIDTH_MIN,Math.min(LEFT_WIDTH_MAX,longest+2));return Math.min(fit,Math.max(LEFT_WIDTH_MIN,Math.floor(width*.45)))}renderTitle(width){let theme2=this.theme,title=` /provider \xB7 ${this.options.providerId}`;return isBuiltinProviderId(this.options.providerId)&&(title+=" \xB7 overlays built-in catalog"),truncateToWidth(theme2.fg("accent",theme2.bold(title)),width)}renderFooter(width){if(this.focusPane==="right"){let hints2=[this.topPane()?.hints()??"",keyHint("app.provider.switchPaneLeft","focus left")].filter(Boolean).join(" ");return[truncateToWidth(hints2,width)]}let hints=[rawKeyHint("\u2191\u2193","move"),keyHint("tui.select.confirm",this.leftActivateLabel()),keyHint("app.provider.switchPaneRight","focus right"),keyHint("tui.select.cancel","back")].join(" ");return[truncateToWidth(hints,width)]}leftActivateLabel(){switch(this.leftItems[this.leftIndex]?.kind){case"fetch":return"fetch";case"addModel":return"create";case"deleteProvider":return"delete";default:return"open"}}};function modelDisplayName(model){return model.name??model.id}var LIST_ROWS=12,ProviderListScreen=class{constructor(tui,theme2,keybindings,done,store){this.mode="list",this.query="",this.index=0,this.active=!1,this.tui=tui,this.theme=theme2,this.keybindings=keybindings,this.done=done,this.store=store,this.input=new ValueEditor({onCommit:()=>this.confirm(),onCancel:()=>this.cancel()})}get focused(){return this.active}set focused(value){this.active=value,this.input.focused=value}invalidate(){}filtered(){let ids=this.store.getProviderIds();return this.query.trim()?fuzzyFilter(ids,this.query,id=>id):ids}render(width){let theme2=this.theme,border=new DynamicBorder(text2=>theme2.fg("border",text2)).render(width)[0]??"",lines=[border,truncateToWidth(theme2.fg("accent",theme2.bold(" /provider \u2014 models.json providers")),width),border,renderKeyValueLine(theme2,{keyLabel:this.mode==="list"?"Search":"Provider id",active:!1,paneFocused:this.active,editing:this.input,width}),""],area=[];if(this.mode==="list"){let entries=this.filtered(),total=entries.length+1;this.index=Math.min(this.index,total-1);let rows=[];for(let row=0;row<total;row++){let id=entries[row-1],provider=id===void 0?void 0:this.store.getProvider(id),note=id===void 0?void 0:provider?[`${String(provider.models?.length??0)} ${plural(provider.models?.length??0,"model")}`,provider.api].filter(Boolean).join(" \xB7 "):"pending deletion";rows.push(renderPlainLine(theme2,row===0?"+ Add Provider":id,{active:row===this.index,paneFocused:this.active,note,width}))}entries.length===0&&rows.push(renderInfoLine(theme2,this.query?"No matching providers.":"No providers yet.",width)),area.push(...windowLines(theme2,rows,LIST_ROWS,{cursor:this.index}))}else this.error&&area.push(truncateToWidth(theme2.fg("error",this.error),width));for(;area.length<LIST_ROWS;)area.push("");let hints=this.mode==="newProvider"?[keyHint("tui.input.submit","create"),keyHint("tui.select.cancel","cancel")]:[rawKeyHint("type","filter"),rawKeyHint("\u2191\u2193","move"),keyHint("tui.select.confirm","open"),keyHint("tui.select.cancel","close")];return[...lines,...area,border,truncateToWidth(hints.join(" "),width),border]}handleInput(data){let kb=this.keybindings;if(kb.matches(data,"tui.select.cancel")){this.cancel();return}if(this.mode==="list"){let total=this.filtered().length+1;if(kb.matches(data,"tui.select.up"))this.index=(this.index+total-1)%total;else if(kb.matches(data,"tui.select.down"))this.index=(this.index+1)%total;else if(kb.matches(data,"tui.select.confirm")){this.confirm();return}else{let previous=this.query;this.input.handleInput(data),this.query=this.input.value,this.query!==previous&&(this.index=this.query&&this.filtered().length>0?1:0)}}else this.input.handleInput(data);this.tui.requestRender()}confirm(){if(this.mode==="newProvider"){let id=this.input.value.trim();if(!id)this.error="Provider id must be non-empty.";else if(this.store.getProviderIds().includes(id))this.error="This provider id already exists.";else{this.store.ensureProviderView(id),this.done({kind:"open",providerId:id});return}}else if(this.index===0)this.mode="newProvider",this.error=void 0,this.input.reset(this.query);else{let id=this.filtered()[this.index-1];id&&this.done({kind:"open",providerId:id})}this.tui.requestRender()}cancel(){if(this.mode==="list"){this.done({kind:"close"});return}this.mode="list",this.error=void 0,this.input.reset(this.query),this.tui.requestRender()}};var ProviderTuiSession=class extends Container{constructor(tui){super(),this.controller=new AbortController,this.active=!1,this.tui=tui}get signal(){return this.controller.signal}get focused(){return this.active}set focused(value){this.active=value,this.screen&&isFocusable(this.screen)&&(this.screen.focused=value)}setScreen(screen){if(this.signal.aborted){screen.dispose?.();return}this.disposeScreen(),this.screen=screen,this.clear(),this.addChild(screen),this.tui.setFocus(this),this.tui.requestRender()}handleInput(data){this.signal.aborted||this.screen?.handleInput?.(data)}dispose(){this.signal.aborted||(this.controller.abort(),this.disposeScreen(),this.clear())}disposeScreen(){let previous=this.screen;this.screen=void 0,previous&&isFocusable(previous)&&(previous.focused=!1),previous?.dispose?.()}};var SavingScreen=class extends Container{constructor(theme2,keybindings,onCancel){super(),this.keybindings=keybindings,this.onCancel=onCancel,this.addChild(new DynamicBorder(text2=>theme2.fg("border",text2))),this.addChild(new Text(theme2.fg("muted","Saving provider changes and updating models\u2026"),1,1)),this.addChild(new Text(keyHint("tui.select.cancel","return to providers"),1,0)),this.addChild(new DynamicBorder(text2=>theme2.fg("border",text2)))}handleInput(data){this.keybindings.matches(data,"tui.select.cancel")&&this.onCancel()}};function createProviderErrorScreen(tui,done,error){return new ExtensionSelectorComponent("models.json cannot be edited",["Back"],done,done,{tui,description:`${truncate3(error,2400)}
|
|
2014
2075
|
|
|
2015
2076
|
Fix the file manually and open /provider again.`})}function createProviderApp(tui,theme2,keybindings,done,options){let{store,registry,runtime}=options,session=new ProviderTuiSession(tui),refresher=new RefreshCoordinator(runtime),activeEditor,closing;function notify(message,type){session.signal.aborted||options.notify(message,type)}store.onSaveResult=result2=>{session.signal.aborted||((result2.kind==="invalid"||result2.kind==="error")&¬ify(result2.error,"error"),activeEditor?.syncFromStore(),tui.requestRender())};function showList(){session.signal.aborted||(activeEditor=void 0,session.setScreen(new ProviderListScreen(tui,theme2,keybindings,result2=>{result2.kind==="close"?requestClose():openProvider(result2.providerId)},store)))}function openProvider(providerId){if(!store.getProviderIds().includes(providerId)){notify(`No provider ${JSON.stringify(providerId)} in models.json.`,"warning"),showList();return}activeEditor=new ProviderEditorScreen(tui,theme2,keybindings,showList,{store,refresher,providerId,registry,runtime,currentModel:options.getCurrentModel(),notify}),session.setScreen(activeEditor)}function showUnsaved(error){let back="Return to providers",retry="Retry saving",discard3="Discard unsaved changes and close";session.setScreen(new ExtensionSelectorComponent("Some changes are not saved",[back,retry,discard3],choice=>{if(choice===back){showList();return}choice===retry&&store.retrySave(),choice===discard3&&store.discardPending(),requestClose()},showList,{tui,description:truncate3(error,2400)}))}function requestClose(){if(closing||session.signal.aborted)return;let controller=new AbortController;closing=controller;let signal=AbortSignal.any([session.signal,controller.signal]);activeEditor=void 0,session.setScreen(new SavingScreen(theme2,keybindings,()=>{controller.abort(),closing=void 0,showList()})),finishClose(controller,signal)}async function finishClose(controller,signal){try{if(await store.flush(),signal.aborted)return;let unsaved=store.getPendingError();if(unsaved){closing=void 0,showUnsaved(unsaved);return}let outcome=await refresher.flush(signal);if(signal.aborted)return;outcome.ok||notify(`Changes saved, but model refresh failed: ${outcome.errors.join("; ")}`,"warning");let current=options.getCurrentModel();if(current&&refresher.touchedProviders.includes(current.provider)){let refreshed=registry.find(current.provider,current.id);refreshed&&!await options.setModel(refreshed)&¬ify("Reselect the current model with /model to apply its updated configuration.","warning"),refreshed||notify("The current model is no longer available; select another with /model.","warning")}signal.aborted||done()}catch(error){signal.aborted||(notify(formatError2(error),"error"),showList())}finally{closing===controller&&(closing=void 0)}}return options.initialProviderId?openProvider(options.initialProviderId):showList(),session}function providerExtension(pi){let modelsPath;pi.on("session_start",(_event,ctx)=>{modelsPath=ctx.modelRuntime.getModelsPath()}),pi.registerCommand(COMMAND_NAME,{description:COMMAND_DESCRIPTION,getArgumentCompletions:async prefix=>{if(!modelsPath)return null;let load=await ModelsJsonStore.load(modelsPath);if(!load.ok)return null;let query=prefix.trim().toLowerCase(),items=load.store.getProviderIds().filter(id=>id.toLowerCase().startsWith(query)).map(id=>{let count=load.store.getModels(id).length;return{value:id,label:id,description:`${String(count)} ${plural(count,"model")}`}});return items.length?items:null},handler:async(args,ctx)=>{if(!ctx.hasUI||ctx.mode!=="tui"){ctx.ui.notify(NO_UI_WARNING,"warning");return}let path14=ctx.modelRuntime.getModelsPath();if(modelsPath=path14,!path14){ctx.ui.notify(NO_MODELS_FILE_WARNING,"warning");return}try{let load=await ModelsJsonStore.load(path14);if(!load.ok){await ctx.ui.custom((tui,_theme,_keybindings,done)=>createProviderErrorScreen(tui,done,load.error));return}await ctx.ui.custom((tui,theme2,keybindings,done)=>createProviderApp(tui,theme2,keybindings,done,{store:load.store,runtime:ctx.modelRuntime,registry:ctx.modelRegistry,getCurrentModel:()=>ctx.model,setModel:model=>pi.setModel(model),notify:(message,type)=>ctx.ui.notify(message,type),initialProviderId:args.trim()||void 0}))}catch(error){ctx.ui.notify(formatError2(error),"error")}}})}var QUESTION_TOOL_NAME="question",QUESTION_LABEL="Question",QUESTION_DESCRIPTION="Ask the user 1-4 structured multiple-choice questions and return their selections. Never author an 'Other'-style option or a vague label like 'Option A' \u2014 the UI adds a custom-answer path itself. If you recommend an option, put it first and append ' (Recommended)' to its label.",QUESTION_PROMPT_SNIPPET="Ask the user structured multiple-choice questions when blocked on a decision only they can make",QUESTION_PROMPT_GUIDELINES=["Use `question` only for decisions you cannot resolve from the request, the code, or sensible defaults (direction, preference, permissions, destructive choices); for everything else choose a reasonable default and state it.","Batch related decisions into one `question` call (1-4 questions); ask no more than needed to unblock the next step.","Treat `question` answers as decisions: act on them without re-litigating, and do not re-ask unless circumstances change."];registerListKeybindings();var DetailPane=class{constructor(){this.key="",this.offset=0,this.maxOffset=0,this.pageRows=1,this.pendingPages=0}reset(){this.key="",this.offset=0,this.maxOffset=0,this.pendingPages=0}page(key,direction){this.key!==key&&this.reset(),this.key=key,this.pendingPages+=direction}render(key,title,content,width,rows,scrollHint,theme2){this.key!==key&&(this.reset(),this.key=key);let bodyRows=Math.max(1,rows-2),wasAtEnd=this.maxOffset>0&&this.offset===this.maxOffset;this.maxOffset=Math.max(0,content.length-bodyRows),this.pageRows=Math.max(1,bodyRows-1);let anchored2=wasAtEnd?this.maxOffset:this.offset;this.offset=Math.max(0,Math.min(this.maxOffset,anchored2+this.pendingPages*this.pageRows)),this.pendingPages=0;let body2=content.slice(this.offset,this.offset+bodyRows);if(rows<3)return body2.slice(0,rows);let lines=[theme2.fg("muted",truncateToWidth(` ${title.replace(/\s+/gu," ")}`,width)),...body2];if(this.maxOffset>0){for(;lines.length<rows-1;)lines.push("");let range2=`${this.offset+1}\u2013${this.offset+body2.length}/${content.length}`;lines.push(theme2.fg("dim",truncateToWidth(` ${range2}${scrollHint?` \u2022 ${scrollHint}`:""}`,width)))}return lines}};function ruleBorder(theme2,width,color2="accent"){return theme2.fg(color2,"\u2500".repeat(Math.max(0,width)))}function wrapWithPrefix(prefix,text2,width,outputLines){let prefixWidth=visibleWidth(prefix);if(prefixWidth>=width){for(let line of wrapTextWithAnsi(prefix+text2,width))outputLines.push(line);return}let wrappedLines=wrapTextWithAnsi(text2,width-prefixWidth),continuationPrefix=" ".repeat(prefixWidth);for(let lineIndex=0;lineIndex<wrappedLines.length;lineIndex++)outputLines.push(`${lineIndex===0?prefix:continuationPrefix}${wrappedLines[lineIndex]}`)}function moreOptionsHint(direction,count){let arrow=direction==="up"?"\u2191":"\u2193";return count<=0?`${arrow} more ${direction==="up"?"above":"below"}`:`${arrow} ${count} more option${count===1?"":"s"}`}function windowItems(items,focus,rows){let count=items.length,total=items.reduce((sum,item)=>sum+item.height,0),build=(first,last,contentRows)=>({first,last,contentRows,showAbove:first>0,showBelow:last<count-1,hiddenAbove:items.slice(0,first).filter(item=>item.countsAsOption).length,hiddenBelow:items.slice(last+1).filter(item=>item.countsAsOption).length});if(total<=rows)return build(0,count-1,rows);let windowFor=contentRows=>{let first=focus,last=focus,used=items[focus].height;for(let grew=!0;grew;)grew=!1,last+1<count&&used+items[last+1].height<=contentRows&&(last++,used+=items[last].height,grew=!0),first>0&&used+items[first-1].height<=contentRows&&(first--,used+=items[first].height,grew=!0);return build(first,last,contentRows)};if(rows<=2)return{...windowFor(Math.max(1,rows)),showAbove:!1,showBelow:!1};let window2=windowFor(rows-2);return window2.first===0||window2.last===count-1?windowFor(rows-1):window2}var PreviewLinesCache=class{constructor(){this.cache=new Map}get(previewText,width,compute){let byWidth=this.cache.get(previewText);byWidth||(byWidth=new Map,this.cache.set(previewText,byWidth));let lines=byWidth.get(width);return lines||(lines=compute(),byWidth.set(width,lines)),lines}},WidthCachedRender=class{invalidate(){this.cachedLines=void 0}get(width,height,compute){return this.cachedLines!==void 0&&this.cachedWidth===width&&this.cachedHeight===height?this.cachedLines:(this.cachedLines=compute(width,height),this.cachedWidth=width,this.cachedHeight=height,this.cachedLines)}};var QUESTION_LIMITS={questionChars:400,headerChars:32,optionLabelChars:80,optionDescriptionChars:300,previewChars:8e3,userTextChars:4e3,modelResultChars:12e3},TRUNCATION_FOLLOW_UP="Ask the user a focused follow-up question to clarify the omitted portion.";var DECLINE_MESSAGE="User declined to answer the questions.",CLARIFICATION_MESSAGE="The user wants to discuss these questions before choosing an answer.",ENVELOPE_PREFIX="User decisions:",ENVELOPE_SUFFIX="Continue with these decisions in mind.",CLARIFICATION_FOLLOW_UP="Explain the trade-offs or ask what the user would like clarified.",SHORTENED_NOTICE=`
|
|
2016
2077
|
|
|
@@ -2156,7 +2217,7 @@ ${lines.join(`
|
|
|
2156
2217
|
|
|
2157
2218
|
${blocks.join(`
|
|
2158
2219
|
|
|
2159
|
-
`)}`).content}function search(pi){pi.registerTool({name:"code_search",label:"Code Search",description:"Find where behavior lives in the local repository from a description of it. Returns candidate files with line ranges.",promptSnippet:"Find code by describing its behavior",promptGuidelines:["Use `code_search` when you cannot name the file or symbol you need; use `read`, `grep`, or `find` when you can.","Read the returned ranges before editing; the locations are candidates, not answers."],parameters:CodeSearchParams,renderCall:renderCodeSearchCall,renderResult:renderCodeSearchResult,async execute(_toolCallId,params,signal,onUpdate,ctx){let root=resolve17(ctx.cwd,params.path??".");if(!isInside(ctx.cwd,root))throw new Error(`path must be inside the working directory (${ctx.cwd}).`);let locations=await withDevin(apiKey=>codeSearch({apiKey,query:params.query.trim(),root,cwd:ctx.cwd,signal,onProgress:text2=>onUpdate?.({content:[{type:"text",text:text2}],details:{locations:[]}})}));return{content:[{type:"text",text:formatLocations(locations)}],details:{locations}}}});let currentMonth=new Date().toLocaleDateString("en-US",{month:"long",year:"numeric"});pi.registerTool({name:"web_search",label:"Web Search",description:"Search the live web for current information. Returns titles, URLs, and the page excerpts that match the query.",promptSnippet:"Search the live web for current information",promptGuidelines:["Use `web_search` for information beyond your knowledge cutoff.",`It is ${currentMonth}; put this year in \`web_search\` queries for recent releases, versions, or events, not the year your training data suggests.`,"When an answer relies on `web_search` results, cite each result you used as a markdown link: [Title](URL)."],parameters:WebSearchParams,renderCall:renderWebSearchCall,renderResult:renderWebSearchResult,async execute(_toolCallId,params,signal){let query=params.query.trim(),results=await withDevin(apiKey=>webSearch(apiKey,query,params.max_results??5,signal));return{content:[{type:"text",text:formatWebResults(query,results)}],details:{results:results.map(({url,title})=>({url,title}))}}}}),registerSearchCommand(pi),pi.on("session_start",async()=>syncTools(pi))}var CONTEXT_WARNING_PERCENT=40,CONTEXT_ERROR_PERCENT=80,MIN_GAP=1;function formatWorkingDirectory(cwd,home){let homeDirectory=home.replace(/[\\/]+$/,"");if(!homeDirectory)return cwd;let normalizePath3=filePath=>filePath.replace(/\\/g,"/").replace(/\/+$/,"").toLowerCase(),normalizedHomeDirectory=normalizePath3(homeDirectory),normalizedCwd=normalizePath3(cwd);return normalizedCwd===normalizedHomeDirectory?"~":normalizedCwd.startsWith(`${normalizedHomeDirectory}/`)?`~${cwd.slice(homeDirectory.length).replace(/\\/g,"/")}`:cwd}function pathBasename(displayPath2){let normalized=displayPath2.replace(/\\/g,"/").replace(/\/+$/,"");if(!normalized||normalized==="~")return normalized||displayPath2;let slash=normalized.lastIndexOf("/");if(slash<0)return normalized;let base=normalized.slice(slash+1);return normalized.startsWith("~/")?`~/${base}`:base}function formatTokenCount2(count){return count<1e3?`${count}`:count<1e4?`${(count/1e3).toFixed(1)}k`:count<1e6?`${Math.round(count/1e3)}k`:count<1e7?`${(count/1e6).toFixed(1)}M`:`${Math.round(count/1e6)}M`}function joinSegments(segments,separator){return segments.filter(Boolean).join(separator)}function formatContextUsage(data,theme2){let contextWindow=data.contextUsage?.contextWindow??data.model?.contextWindow,suffix=contextWindow?`/${formatTokenCount2(contextWindow)}`:"",percent=data.contextUsage?.percent,label=`CTX ${percent==null?"?":percent.toFixed(1)}%${suffix}`;return percent!=null&&percent>CONTEXT_ERROR_PERCENT?theme2.fg("error",label):percent!=null&&percent>CONTEXT_WARNING_PERCENT?theme2.fg("warning",label):theme2.fg("accent",label)}function formatUsageCandidates(summary,subscription,theme2){let tokens2=[summary.input>0?`\u2191${formatTokenCount2(summary.input)}`:"",summary.output>0?`\u2193${formatTokenCount2(summary.output)}`:""],read=summary.cacheRead>0?`R${formatTokenCount2(summary.cacheRead)}`:"",write=summary.cacheWrite>0?`W${formatTokenCount2(summary.cacheWrite)}`:"",suffix=[summary.latestCacheHitPercent===void 0?"":`CH${summary.latestCacheHitPercent.toFixed(1)}%`,summary.cost>0?`$${summary.cost.toFixed(3)}${subscription?" (sub)":""}`:""],candidates=[[read,write],[read],[]].map(cache=>joinSegments([...tokens2,...cache,...suffix]," "));return[...new Set(candidates.filter(Boolean))].map(text2=>theme2.fg("dim",text2))}function formatExtensionStatuses(statuses,theme2){return[...statuses.entries()].sort(([first],[second])=>first.localeCompare(second)).map(([,text2])=>text2.replace(/[\r\n\t]/g," ").replace(/ +/g," ").trim()).filter(Boolean).map(text2=>text2.includes("\x1B[")?text2:theme2.fg("muted",text2)).join(" ")}function fitsLeftRight(left,right,width){return visibleWidth(left)+visibleWidth(right)+(left&&right?MIN_GAP:0)<=width}function layoutLeftRight(left,right,width,ellipsis){if(width<=0)return"";if(!right)return truncateToWidth(left,width,ellipsis);let rightWidth=visibleWidth(right);if(!left)return`${" ".repeat(Math.max(0,width-rightWidth))}${truncateToWidth(right,width,ellipsis)}`;let leftWidth=visibleWidth(left);if(leftWidth+rightWidth+MIN_GAP>width){let maxRightWidth=Math.min(rightWidth,Math.max(8,Math.floor(width*.45)));right=truncateToWidth(right,maxRightWidth,ellipsis),rightWidth=visibleWidth(right);let maxLeftWidth=width-rightWidth-MIN_GAP;if(maxLeftWidth<1)return truncateToWidth(right,width,ellipsis);left=truncateToWidth(left,maxLeftWidth,ellipsis),leftWidth=visibleWidth(left)}return`${left}${" ".repeat(Math.max(MIN_GAP,width-leftWidth-rightWidth))}${right}`}function layoutSecondaryLine(left,status,right,width,ellipsis){let leftWidth=visibleWidth(left),statusWidth=visibleWidth(status),rightWidth=visibleWidth(right),free=width-leftWidth-statusWidth-rightWidth;if(!status||free<MIN_GAP*2)return layoutLeftRight(left,right,width,ellipsis);let leftPad=Math.floor((width-statusWidth)/2)-leftWidth;return(leftPad<MIN_GAP||free-leftPad<MIN_GAP)&&(leftPad=Math.floor(free/2)),`${left}${" ".repeat(leftPad)}${status}${" ".repeat(free-leftPad)}${right}`}function renderPrimaryLine(data,theme2,width,ellipsis){let{model,thinkingLevel}=data,name=theme2.fg("toolTitle",theme2.bold(model?.name??model?.id??"no-model")),provider=model?.provider?theme2.fg("muted",`(${model.provider})`):"",effort=model?.reasoning&&thinkingLevel!=="off"?theme2.getThinkingBorderColor(thinkingLevel)(thinkingLevel):"",separator=theme2.fg("dim"," \xB7 "),rich=joinSegments([joinSegments([name,provider]," "),effort],separator),plain=joinSegments([name,effort],separator),cwd=formatWorkingDirectory(data.cwd,data.home),full=theme2.fg("success",cwd),short=theme2.fg("success",pathBasename(cwd)),branch=data.gitBranch?theme2.fg("accent",data.gitBranch):"",chosen=[{left:rich,right:joinSegments([full,branch],separator)},{left:rich,right:full},{left:rich,right:joinSegments([short,branch],separator)},{left:rich,right:short},{left:plain,right:joinSegments([short,branch],separator)},{left:plain,right:short},{left:plain,right:""}].find(({left,right})=>fitsLeftRight(left,right,width))??{left:plain,right:short};return layoutLeftRight(chosen.left,chosen.right,width,ellipsis)}function renderStatusline(data,theme2,width){let ellipsis=theme2.fg("dim","..."),primary=renderPrimaryLine(data,theme2,width,ellipsis),context=formatContextUsage(data,theme2),status=formatExtensionStatuses(data.statuses,theme2),candidates=formatUsageCandidates(data.usage,data.usesSubscription,theme2),usage=candidates.find(candidate=>fitsLeftRight(context,candidate,width)),secondary=candidates.length>0&&usage===void 0?layoutLeftRight(context,candidates[0],width,ellipsis):layoutSecondaryLine(context,status,usage??"",width,ellipsis);return[primary,secondary]}var BranchUsage=class{invalidate(){this.cached=void 0}read(manager){let sessionId=manager.getSessionId(),leafId=manager.getLeafId();if(this.cached?.manager===manager&&this.cached.sessionId===sessionId&&this.cached.leafId===leafId)return this.cached.usage;let entries=manager.getBranch(),totals=createUsageTotals();for(let usage2 of getAccountedUsages(entries))addUsageToTotals(totals,usage2);let latestCacheHitPercent;for(let index3=entries.length-1;index3>=0;index3--){let entry=entries[index3];if(entry.type!=="message"||entry.message.role!=="assistant")continue;let{input:input2,cacheRead,cacheWrite}=entry.message.usage,promptTokens=input2+cacheRead+cacheWrite;(cacheRead>0||cacheWrite>0)&&promptTokens>0&&(latestCacheHitPercent=cacheRead/promptTokens*100);break}let usage={...totals,latestCacheHitPercent};return this.cached={manager,sessionId,leafId,usage},usage}};function statusline(pi){pi.on("session_start",(_event,ctx)=>{ctx.mode==="tui"&&ctx.ui.setFooter((tui,theme2,footerData)=>{let usage=new BranchUsage;return{dispose:footerData.onBranchChange(()=>tui.requestRender()),invalidate(){usage.invalidate()},render(width){let model=ctx.model;return renderStatusline({model,thinkingLevel:ctx.thinkingLevel??"off",cwd:ctx.cwd,home:process.env.USERPROFILE||process.env.HOME||"",gitBranch:footerData.getGitBranch(),contextUsage:ctx.getContextUsage(),usage:usage.read(ctx.sessionManager),usesSubscription:model?ctx.modelRegistry.isUsingOAuth(model):!1,statuses:footerData.getExtensionStatuses()},theme2,width)}}})}),pi.on("session_shutdown",(_event,ctx)=>{ctx.mode==="tui"&&ctx.ui.setFooter(void 0)})}var builtInExtensions=[{name:"codemode",factory:codemode_default,replaceable:!0,builtin:!0},{name:"mcp",factory:mcp_default,replaceable:!0,builtin:!0},{name:"tool-search",factory:tool_search_default,replaceable:!0,builtin:!0},{name:"llama.cpp",factory:llamaExtension,builtin:!0},{name:"btw",factory:btwExtension,builtin:!0},{name:"deepwiki",factory:deepwiki,builtin:!0},{name:"provider",factory:providerExtension,builtin:!0},{name:"question",factory:question,builtin:!0},{name:"statusline",factory:statusline,builtin:!0},{name:"search",factory:search,builtin:!0}];var cli_exports={};__export(cli_exports,{runMcpCommand:()=>runMcpCommand});import{existsSync as existsSync26}from"node:fs";import{join as join47}from"node:path";import{createInterface as createInterface5}from"node:readline/promises";var HELP=`${source_default.bold("Usage:")}
|
|
2220
|
+
`)}`).content}function search(pi){pi.registerTool({name:"code_search",label:"Code Search",description:"Find where behavior lives in the local repository from a description of it. Returns candidate files with line ranges.",promptSnippet:"Find code by describing its behavior",promptGuidelines:["Use `code_search` when you cannot name the file or symbol you need; use `read`, `grep`, or `find` when you can.","Read the returned ranges before editing; the locations are candidates, not answers."],parameters:CodeSearchParams,renderCall:renderCodeSearchCall,renderResult:renderCodeSearchResult,async execute(_toolCallId,params,signal,onUpdate,ctx){let root=resolve17(ctx.cwd,params.path??".");if(!isInside(ctx.cwd,root))throw new Error(`path must be inside the working directory (${ctx.cwd}).`);let locations=await withDevin(apiKey=>codeSearch({apiKey,query:params.query.trim(),root,cwd:ctx.cwd,signal,onProgress:text2=>onUpdate?.({content:[{type:"text",text:text2}],details:{locations:[]}})}));return{content:[{type:"text",text:formatLocations(locations)}],details:{locations}}}});let currentMonth=new Date().toLocaleDateString("en-US",{month:"long",year:"numeric"});pi.registerTool({name:"web_search",label:"Web Search",description:"Search the live web for current information. Returns titles, URLs, and the page excerpts that match the query.",promptSnippet:"Search the live web for current information",promptGuidelines:["Use `web_search` for information beyond your knowledge cutoff.",`It is ${currentMonth}; put this year in \`web_search\` queries for recent releases, versions, or events, not the year your training data suggests.`,"When an answer relies on `web_search` results, cite each result you used as a markdown link: [Title](URL)."],parameters:WebSearchParams,renderCall:renderWebSearchCall,renderResult:renderWebSearchResult,async execute(_toolCallId,params,signal){let query=params.query.trim(),results=await withDevin(apiKey=>webSearch(apiKey,query,params.max_results??5,signal));return{content:[{type:"text",text:formatWebResults(query,results)}],details:{results:results.map(({url,title})=>({url,title}))}}}}),registerSearchCommand(pi),pi.on("session_start",async()=>syncTools(pi))}var CONTEXT_WARNING_PERCENT=40,CONTEXT_ERROR_PERCENT=80,MIN_GAP=1;function formatWorkingDirectory(cwd,home){let homeDirectory=home.replace(/[\\/]+$/,"");if(!homeDirectory)return cwd;let normalizePath3=filePath=>filePath.replace(/\\/g,"/").replace(/\/+$/,"").toLowerCase(),normalizedHomeDirectory=normalizePath3(homeDirectory),normalizedCwd=normalizePath3(cwd);return normalizedCwd===normalizedHomeDirectory?"~":normalizedCwd.startsWith(`${normalizedHomeDirectory}/`)?`~${cwd.slice(homeDirectory.length).replace(/\\/g,"/")}`:cwd}function pathBasename(displayPath2){let normalized=displayPath2.replace(/\\/g,"/").replace(/\/+$/,"");if(!normalized||normalized==="~")return normalized||displayPath2;let slash=normalized.lastIndexOf("/");if(slash<0)return normalized;let base=normalized.slice(slash+1);return normalized.startsWith("~/")?`~/${base}`:base}function formatTokenCount2(count){return count<1e3?`${count}`:count<1e4?`${(count/1e3).toFixed(1)}k`:count<1e6?`${Math.round(count/1e3)}k`:count<1e7?`${(count/1e6).toFixed(1)}M`:`${Math.round(count/1e6)}M`}function joinSegments(segments,separator){return segments.filter(Boolean).join(separator)}function formatContextUsage(data,theme2){let contextWindow=data.contextUsage?.contextWindow??data.model?.contextWindow,suffix=contextWindow?`/${formatTokenCount2(contextWindow)}`:"",percent=data.contextUsage?.percent,label=`CTX ${percent==null?"?":percent.toFixed(1)}%${suffix}`;return percent!=null&&percent>CONTEXT_ERROR_PERCENT?theme2.fg("error",label):percent!=null&&percent>CONTEXT_WARNING_PERCENT?theme2.fg("warning",label):theme2.fg("accent",label)}function formatUsageCandidates(summary,subscription,theme2){let tokens2=[summary.input>0?`\u2191${formatTokenCount2(summary.input)}`:"",summary.output>0?`\u2193${formatTokenCount2(summary.output)}`:""],read=summary.cacheRead>0?`R${formatTokenCount2(summary.cacheRead)}`:"",write=summary.cacheWrite>0?`W${formatTokenCount2(summary.cacheWrite)}`:"",suffix=[summary.latestCacheHitPercent===void 0?"":`CH${summary.latestCacheHitPercent.toFixed(1)}%`,summary.cost>0?`$${summary.cost.toFixed(3)}${subscription?" (sub)":""}`:""],candidates=[[read,write],[read],[]].map(cache=>joinSegments([...tokens2,...cache,...suffix]," "));return[...new Set(candidates.filter(Boolean))].map(text2=>theme2.fg("dim",text2))}function formatExtensionStatuses(statuses,theme2){return[...statuses.entries()].sort(([first],[second])=>first.localeCompare(second)).map(([,text2])=>text2.replace(/[\r\n\t]/g," ").replace(/ +/g," ").trim()).filter(Boolean).map(text2=>text2.includes("\x1B[")?text2:theme2.fg("muted",text2)).join(" ")}function fitsLeftRight(left,right,width){return visibleWidth(left)+visibleWidth(right)+(left&&right?MIN_GAP:0)<=width}function layoutLeftRight(left,right,width,ellipsis){if(width<=0)return"";if(!right)return truncateToWidth(left,width,ellipsis);let rightWidth=visibleWidth(right);if(!left)return`${" ".repeat(Math.max(0,width-rightWidth))}${truncateToWidth(right,width,ellipsis)}`;let leftWidth=visibleWidth(left);if(leftWidth+rightWidth+MIN_GAP>width){let maxRightWidth=Math.min(rightWidth,Math.max(8,Math.floor(width*.45)));right=truncateToWidth(right,maxRightWidth,ellipsis),rightWidth=visibleWidth(right);let maxLeftWidth=width-rightWidth-MIN_GAP;if(maxLeftWidth<1)return truncateToWidth(right,width,ellipsis);left=truncateToWidth(left,maxLeftWidth,ellipsis),leftWidth=visibleWidth(left)}return`${left}${" ".repeat(Math.max(MIN_GAP,width-leftWidth-rightWidth))}${right}`}function layoutSecondaryLine(left,status,right,width,ellipsis){let leftWidth=visibleWidth(left),statusWidth=visibleWidth(status),rightWidth=visibleWidth(right),free=width-leftWidth-statusWidth-rightWidth;if(!status||free<MIN_GAP*2)return layoutLeftRight(left,right,width,ellipsis);let leftPad=Math.floor((width-statusWidth)/2)-leftWidth;return(leftPad<MIN_GAP||free-leftPad<MIN_GAP)&&(leftPad=Math.floor(free/2)),`${left}${" ".repeat(leftPad)}${status}${" ".repeat(free-leftPad)}${right}`}function renderPrimaryLine(data,theme2,width,ellipsis){let{model,thinkingLevel}=data,name=theme2.fg("toolTitle",theme2.bold(model?.name??model?.id??"no-model")),provider=model?.provider?theme2.fg("muted",`(${model.provider})`):"",effort=model?.reasoning&&thinkingLevel!=="off"?theme2.getThinkingBorderColor(thinkingLevel)(thinkingLevel):"",separator=theme2.fg("dim"," \xB7 "),rich=joinSegments([joinSegments([name,provider]," "),effort],separator),plain=joinSegments([name,effort],separator),cwd=formatWorkingDirectory(data.cwd,data.home),full=theme2.fg("success",cwd),short=theme2.fg("success",pathBasename(cwd)),branch=data.gitBranch?theme2.fg("accent",data.gitBranch):"",chosen=[{left:rich,right:joinSegments([full,branch],separator)},{left:rich,right:full},{left:rich,right:joinSegments([short,branch],separator)},{left:rich,right:short},{left:plain,right:joinSegments([short,branch],separator)},{left:plain,right:short},{left:plain,right:""}].find(({left,right})=>fitsLeftRight(left,right,width))??{left:plain,right:short};return layoutLeftRight(chosen.left,chosen.right,width,ellipsis)}function renderStatusline(data,theme2,width){let ellipsis=theme2.fg("dim","..."),primary=renderPrimaryLine(data,theme2,width,ellipsis),context=formatContextUsage(data,theme2),status=formatExtensionStatuses(data.statuses,theme2),candidates=formatUsageCandidates(data.usage,data.usesSubscription,theme2),usage=candidates.find(candidate=>fitsLeftRight(context,candidate,width)),secondary=candidates.length>0&&usage===void 0?layoutLeftRight(context,candidates[0],width,ellipsis):layoutSecondaryLine(context,status,usage??"",width,ellipsis);return[primary,secondary]}var BranchUsage=class{invalidate(){this.cached=void 0}read(manager){let sessionId=manager.getSessionId(),leafId=manager.getLeafId();if(this.cached?.manager===manager&&this.cached.sessionId===sessionId&&this.cached.leafId===leafId)return this.cached.usage;let entries=manager.getBranch(),totals=createUsageTotals();for(let usage2 of getAccountedUsages(entries))addUsageToTotals(totals,usage2);let latestCacheHitPercent;for(let index3=entries.length-1;index3>=0;index3--){let entry=entries[index3];if(entry.type!=="message"||entry.message.role!=="assistant")continue;let{input:input2,cacheRead,cacheWrite}=entry.message.usage,promptTokens=input2+cacheRead+cacheWrite;(cacheRead>0||cacheWrite>0)&&promptTokens>0&&(latestCacheHitPercent=cacheRead/promptTokens*100);break}let usage={...totals,latestCacheHitPercent};return this.cached={manager,sessionId,leafId,usage},usage}};function statusline(pi){pi.on("session_start",(_event,ctx)=>{ctx.mode==="tui"&&ctx.ui.setFooter((tui,theme2,footerData)=>{let usage=new BranchUsage;return{dispose:footerData.onBranchChange(()=>tui.requestRender()),invalidate(){usage.invalidate()},render(width){let model=ctx.model;return renderStatusline({model,thinkingLevel:ctx.thinkingLevel??"off",cwd:ctx.cwd,home:process.env.USERPROFILE||process.env.HOME||"",gitBranch:footerData.getGitBranch(),contextUsage:ctx.getContextUsage(),usage:usage.read(ctx.sessionManager),usesSubscription:model?ctx.modelRegistry.isUsingOAuth(model):!1,statuses:footerData.getExtensionStatuses()},theme2,width)}}})}),pi.on("session_shutdown",(_event,ctx)=>{ctx.mode==="tui"&&ctx.ui.setFooter(void 0)})}function formatFallbackArgs(args){if(!args||typeof args!="object")return"";let entries=Object.entries(args);if(entries.length===0)return"";let summary=entries.map(([key,value])=>{try{return`${key}=${JSON.stringify(value)??String(value)}`}catch{return`${key}=${String(value)}`}}).join(" ").replace(/\s+/g," ");return truncateToWidth(summary,toolStyle.fallbackArgsWidth,"...")}function createCallFallback(toolName,args,expanded=!1){if(expanded)return new Text(formatToolCallWithArgs(toolName,args,theme,!0),0,0);let summary=formatFallbackArgs(args),suffix=summary?theme.fg("dim",`(${summary})`):"";return new Text(`${theme.fg("toolTitle",theme.bold(toolName))}${suffix}`,0,0)}var FallbackResultComponent=class{constructor(output,expanded){this.output=output,this.expanded=expanded}render(width){let styledOutput=theme.fg("toolOutput",this.output);if(this.expanded)return new Text(styledOutput,0,0).render(width);let preview=truncateToVisualLines(styledOutput,toolStyle.collapsed.fallbackLines,width);if(preview.skippedCount<=0)return preview.visualLines;let noun=preview.skippedCount===1?"line":"lines",hint=theme.fg("muted",`... (${preview.skippedCount} earlier ${noun},`)+` ${keyHint("app.tools.expand","to expand")}${theme.fg("muted",")")}`;return[truncateToWidth(hint,width,"..."),...preview.visualLines]}invalidate(){}};var builtInRenderers;function builtInResultRenderer(toolName){return builtInRenderers??=createAllToolRenderers(),builtInRenderers[toolName]?.renderResult}function createToolShell(toolName,definition){let resultRenderer=definition?.renderResult;return{get gap(){return toolStyle.gap},frame(component,kind,context){return new FramedComponent(component,kind,()=>toolMarkerColor(toolStatus(context)))},renderCall(args,_theme,context){return createCallFallback(toolName,args,context.expanded)},renderResult(result2,_options,_theme,context){let output=getTextOutput(result2,context.showImages);return output?new FallbackResultComponent(output,context.expanded):new Container},shouldHideResult(context){if(context.expanded||context.isError||!toolStyle.collapsed.headerOnly.has(toolName))return!1;let builtIn=builtInResultRenderer(toolName);return builtIn!==void 0&&builtIn===resultRenderer}}}function withToolShell(toolName,definition){return definition?.renderShell==="self"||definition?.shell?definition:{...definition??{},shell:createToolShell(toolName,definition)}}function toolPresentation(pi){pi.registerToolRenderer((toolName,next)=>withToolShell(toolName,next()))}var builtInExtensions=[{name:"codemode",factory:codemode_default,replaceable:!0,builtin:!0},{name:"mcp",factory:mcp_default,replaceable:!0,builtin:!0},{name:"tool-search",factory:tool_search_default,replaceable:!0,builtin:!0},{name:"cached-compaction",factory:cachedCompaction,replaceable:!0,builtin:!0},{name:"llama.cpp",factory:llamaExtension,builtin:!0},{name:"btw",factory:btwExtension,builtin:!0},{name:"deepwiki",factory:deepwiki,builtin:!0},{name:"provider",factory:providerExtension,builtin:!0},{name:"question",factory:question,builtin:!0},{name:"statusline",factory:statusline,builtin:!0},{name:"tool-presentation",factory:toolPresentation,builtin:!0},{name:"search",factory:search,builtin:!0}];var cli_exports={};__export(cli_exports,{runMcpCommand:()=>runMcpCommand});import{existsSync as existsSync26}from"node:fs";import{join as join47}from"node:path";import{createInterface as createInterface5}from"node:readline/promises";var HELP=`${source_default.bold("Usage:")}
|
|
2160
2221
|
${APP_NAME} mcp add <server> [options] -- <command> [args...]
|
|
2161
2222
|
${APP_NAME} mcp add <server> [options] --url <url>
|
|
2162
2223
|
${APP_NAME} mcp remove <server> [-l]
|
|
@@ -2297,4 +2358,4 @@ Options:
|
|
|
2297
2358
|
`))});try{switch(options.command){case"install":return await packageManager.installAndPersist(source,{local:options.local}),console.log(source_default.green(`Installed ${source}`)),!0;case"remove":return await packageManager.removeAndPersist(source,{local:options.local})?(console.log(source_default.green(`Removed ${source}`)),!0):(console.error(source_default.red(`No matching package found for ${source}`)),process.exitCode=1,!0);case"list":{let configuredPackages=packageManager.listConfiguredPackages(),userPackages=configuredPackages.filter(pkg2=>pkg2.scope==="user"),projectPackages=configuredPackages.filter(pkg2=>pkg2.scope==="project");if(configuredPackages.length===0)return console.log(source_default.dim("No packages installed.")),!0;let formatPackage=pkg2=>{let display=pkg2.filtered?`${pkg2.source} (filtered)`:pkg2.source;console.log(` ${display}`),pkg2.installedPath&&console.log(source_default.dim(` ${pkg2.installedPath}`))};if(userPackages.length>0){console.log(source_default.bold("User packages:"));for(let pkg2 of userPackages)formatPackage(pkg2)}if(projectPackages.length>0){userPackages.length>0&&console.log(),console.log(source_default.bold("Project packages:"));for(let pkg2 of projectPackages)formatPackage(pkg2)}return!0}case"update":{let target=options.updateTarget??{type:"self"};if(options.showExtensionsSkippedNote&&console.log(source_default.dim(`Extensions are skipped. Run ${APP_NAME} update --extensions to update extensions.`)),updateTargetIncludesExtensions(target)){let updateSource=target.type==="extensions"?target.source:void 0;await packageManager.update(updateSource),console.log(updateSource?source_default.green(`Updated ${updateSource}`):source_default.green("Updated packages"))}if(updateTargetIncludesSelf(target)){let managedInstallRoot=getActiveManagedInstallRoot();if(managedInstallRoot&&options.force)return console.error(source_default.red(`Managed ${APP_NAME} installations do not support --force; rerun the installer to repair this installation.`)),process.exitCode=1,!0;let selfUpdatePlan=await getSelfUpdatePlan(options.force);if(!selfUpdatePlan.shouldRun)return!0;if(managedInstallRoot){selfUpdatePlan.note&&printSelfUpdateNote(selfUpdatePlan.note);try{console.log(source_default.dim(`Updating managed ${APP_NAME} installation...`)),await runManagedSelfUpdate(managedInstallRoot,selfUpdatePlan.version)}catch(error){let message=error instanceof Error?error.message:"Unknown managed update error";return console.error(source_default.red(`Error: ${message}`)),process.exitCode=1,!0}return console.log(source_default.green(`Updated ${APP_NAME} from ${VERSION} to ${selfUpdatePlan.version}`)),!0}let installMethod=detectInstallMethod();if(process.platform==="win32"&&installMethod!=="npm"&&installMethod!=="pnpm")return console.error(source_default.red(`${APP_NAME} self-update on Windows is only supported for npm and pnpm installs.`)),console.error(source_default.dim(`Detected install method: ${installMethod}. Update ${APP_NAME} manually.`)),process.exitCode=1,!0;let selfUpdateTarget={packageName:selfUpdatePlan.packageName,installSpec:selfUpdatePlan.installSpec},selfUpdateCommand=getSelfUpdateCommand(PACKAGE_NAME,selfUpdateNpmCommand,selfUpdateTarget);if(!selfUpdateCommand)return printSelfUpdateUnavailable(selfUpdateNpmCommand,selfUpdateTarget),process.exitCode=1,!0;selfUpdatePlan.note&&printSelfUpdateNote(selfUpdatePlan.note);try{installMethod==="npm"&&prepareWindowsNpmSelfUpdate(),await runSelfUpdate(selfUpdateCommand)}catch(error){let message=error instanceof Error?error.message:"Unknown package command error";return console.error(source_default.red(`Error: ${message}`)),installMethod==="pnpm"&&printPnpmSelfUpdateMetadataHint(),printSelfUpdateFallback(selfUpdateCommand),process.exitCode=1,!0}console.log(source_default.green(`Updated ${APP_NAME} from ${VERSION} to ${selfUpdatePlan.version}`))}return!0}}}catch(error){let message=error instanceof Error?error.message:"Unknown package command error";return console.error(source_default.red(`Error: ${message}`)),process.exitCode=1,!0}}var EXTENSION_LOAD_FAILURE_HINT=`Hint: Start without extensions using "${APP_NAME} -ne".`;async function readPipedStdin(){if(!process.stdin.isTTY)return new Promise(resolve20=>{let data="";process.stdin.setEncoding("utf8"),process.stdin.on("data",chunk=>{data+=chunk}),process.stdin.on("end",()=>{resolve20(data.trim()||void 0)}),process.stdin.resume()})}function reportDiagnostics(diagnostics){for(let diagnostic of diagnostics){let color2=diagnostic.type==="error"?source_default.red:diagnostic.type==="warning"?source_default.yellow:source_default.dim,prefix=diagnostic.type==="error"?"Error: ":diagnostic.type==="warning"?"Warning: ":"";console.error(color2(`${prefix}${diagnostic.message}`))}}function isTruthyEnvFlag2(value){return value?value==="1"||value.toLowerCase()==="true"||value.toLowerCase()==="yes":!1}function resolveAppMode(parsed,stdinIsTTY,stdoutIsTTY){return parsed.mode==="rpc"?"rpc":parsed.mode==="json"?"json":parsed.print||!stdinIsTTY||!stdoutIsTTY?"print":"interactive"}function toPrintOutputMode(appMode){return appMode==="json"?"json":"text"}function isPlainRuntimeMetadataCommand(parsed){return!parsed.print&&parsed.mode===void 0&&(parsed.help===!0||parsed.listModels!==void 0)}async function runAuthCommand(args){if(isAuthCommandHelp(args))return printAuthCommandHelp(),!0;let command;try{command=parseAuthCommand(args)}catch(error){let message=error instanceof AuthCommandError?error.message:"Failed to parse auth command";return console.error(source_default.red(`Error: ${message}`)),process.exitCode=1,!0}if(!command)return!1;let parsed=parseArgs(command.args);if(parsed.unknownFlags.size>0){let option=parsed.unknownFlags.keys().next().value;return console.error(source_default.red(`Unknown option --${option} for "${getAuthCommandName(command.kind)}".`)),console.error(source_default.dim(`Use "${APP_NAME} --help" or "${getAuthCommandUsage(command.kind)}".`)),process.exitCode=1,!0}try{if(parsed.diagnostics.length>0)throw new AuthCommandError(parsed.diagnostics.map(diagnostic=>diagnostic.message).join(`
|
|
2298
2359
|
`));if(command.kind!=="check"){let signal=AbortSignal.timeout(15e3),modelRuntime=await ModelRuntime.create({allowModelNetwork:!1,signal}),credential2=await resolveCredentialForPrint(parsed,modelRuntime,command.kind,command.minExpiryMs,signal);return process.stdout.write(`${credential2}
|
|
2299
2360
|
`),!0}let requestedAuth=validateAuthCommandArgs(parsed,command.kind),result2,credential;try{let credentials=command.noRefresh?new ReadOnlyAuthStorage:AuthStorage.create(),modelRuntime=await createAuthCheckModelRuntime(credentials);result2=await checkProviderAuth(parsed,modelRuntime,{refresh:!command.noRefresh}),command.credentials&&result2.status==="ready"&&(credential=await getProviderCredential(result2.provider,modelRuntime,credentials,{refresh:!command.noRefresh}),credential||(result2={status:"not_ready",provider:result2.provider,reason:"credential_not_available"}))}catch{result2={status:"invalid",provider:requestedAuth.provider??requestedAuth.model,reason:"invalid_state"}}let output=command.json?JSON.stringify({...result2,...credential?{credentials:credential}:{}}):credential??result2.status;process.stdout.write(`${output}
|
|
2300
|
-
`),process.exitCode=result2.status==="ready"?0:result2.status==="not_ready"?1:2}catch(error){let message=error instanceof AuthCommandError?error.message:"Failed to resolve credential";console.error(source_default.red(`Error: ${message}`)),process.exitCode=command.kind==="check"?2:1}return!0}async function prepareInitialMessage(parsed,stdinContent){if(parsed.fileArgs.length===0)return buildInitialMessage({parsed,stdinContent});let{text:text2,images}=await processFileArguments(parsed.fileArgs,{autoResizeImages:!1});return buildInitialMessage({parsed,fileText:text2,fileImages:images,stdinContent})}function findLocalSessionByExactId(sessionId,cwd,sessionDir){let path14=SessionManager.findById(cwd,sessionId,sessionDir);return path14?{type:"local",path:path14}:void 0}async function resolveSessionPath(sessionArg,cwd,sessionDir){if(sessionArg.includes("/")||sessionArg.includes("\\")||sessionArg.endsWith(".jsonl"))return{type:"path",path:resolvePath(sessionArg,cwd)};let exactLocalMatch=findLocalSessionByExactId(sessionArg,cwd,sessionDir);if(exactLocalMatch)return exactLocalMatch;let localMatch=(await SessionManager.list(cwd,sessionDir)).find(s=>s.id.startsWith(sessionArg));if(localMatch)return{type:"local",path:localMatch.path};let allSessions=await SessionManager.listAll(sessionDir),globalMatch=allSessions.find(s=>s.id===sessionArg)??allSessions.find(s=>s.id.startsWith(sessionArg));return globalMatch?{type:"global",path:globalMatch.path,cwd:globalMatch.cwd}:{type:"not_found",arg:sessionArg}}async function promptConfirm(message){return new Promise(resolve20=>{let rl=createInterface6({input:process.stdin,output:process.stdout});rl.question(`${message} [y/N] `,answer=>{rl.close(),resolve20(answer.toLowerCase()==="y"||answer.toLowerCase()==="yes")})})}function validateForkFlags(parsed){if(!parsed.fork)return;let conflictingFlags=[parsed.session?"--session":void 0,parsed.continue?"--continue":void 0,parsed.resume?"--resume":void 0,parsed.noSession?"--no-session":void 0].filter(flag=>flag!==void 0);conflictingFlags.length>0&&(console.error(source_default.red(`Error: --fork cannot be combined with ${conflictingFlags.join(", ")}`)),process.exit(1))}function validateSessionIdFlags(parsed){if(parsed.sessionId===void 0)return;let conflictingFlags=[parsed.session?"--session":void 0,parsed.continue?"--continue":void 0,parsed.resume?"--resume":void 0].filter(flag=>flag!==void 0);conflictingFlags.length>0&&(console.error(source_default.red(`Error: --session-id cannot be combined with ${conflictingFlags.join(", ")}`)),process.exit(1));try{assertValidSessionId(parsed.sessionId)}catch(error){let message=error instanceof Error?error.message:String(error);console.error(source_default.red(`Error: ${message}`)),process.exit(1)}}function openSessionOrExit(path14,sessionDir){try{return SessionManager.open(path14,sessionDir)}catch(error){let message=error instanceof Error?error.message:String(error);console.error(source_default.red(`Error: ${message}`)),process.exit(1)}}function forkSessionOrExit(sourcePath,cwd,sessionDir,sessionId){try{return SessionManager.forkFrom(sourcePath,cwd,sessionDir,{id:sessionId})}catch(error){let message=error instanceof Error?error.message:String(error);console.error(source_default.red(`Error: ${message}`)),process.exit(1)}}async function createSessionManager(parsed,cwd,sessionDir,settingsManager){if(parsed.noSession||parsed.help||parsed.listModels!==void 0)return SessionManager.inMemory(cwd,parsed.sessionId!==void 0?{id:parsed.sessionId}:void 0);if(parsed.fork){parsed.sessionId&&findLocalSessionByExactId(parsed.sessionId,cwd,sessionDir)&&(console.error(source_default.red(`Session already exists with id '${parsed.sessionId}'`)),process.exit(1));let resolved=await resolveSessionPath(parsed.fork,cwd,sessionDir);switch(resolved.type){case"path":case"local":case"global":return forkSessionOrExit(resolved.path,cwd,sessionDir,parsed.sessionId);case"not_found":console.error(source_default.red(`No session found matching '${resolved.arg}'`)),process.exit(1)}}if(parsed.session){let resolved=await resolveSessionPath(parsed.session,cwd,sessionDir);switch(resolved.type){case"path":case"local":return openSessionOrExit(resolved.path,sessionDir);case"global":return console.log(source_default.yellow(`Session found in different project: ${resolved.cwd}`)),await promptConfirm("Fork this session into current directory?")||(console.log(source_default.dim("Aborted.")),process.exit(0)),forkSessionOrExit(resolved.path,cwd,sessionDir);case"not_found":console.error(source_default.red(`No session found matching '${resolved.arg}'`)),process.exit(1)}}if(parsed.resume)try{let selectedPath=await selectSession((onProgress,signal)=>SessionManager.list(cwd,sessionDir,onProgress,signal),(onProgress,signal)=>SessionManager.listAll(sessionDir,onProgress,signal),settingsManager);return selectedPath||(console.log(source_default.dim("No session selected")),process.exit(0)),SessionManager.open(selectedPath,sessionDir)}finally{stopThemeWatcher()}if(parsed.continue)return SessionManager.continueRecent(cwd,sessionDir);if(parsed.sessionId){let existingSession=findLocalSessionByExactId(parsed.sessionId,cwd,sessionDir);if(existingSession)return SessionManager.open(existingSession.path,sessionDir);console.error(source_default.yellow(`Warning: No project session found with id '${parsed.sessionId}'; creating a new session with that id.`))}return SessionManager.create(cwd,sessionDir,{id:parsed.sessionId})}function buildSessionOptions(parsed,scopedModels,hasExistingSession,modelRuntime,settingsManager){let options={},diagnostics=[],cliThinkingFromModel=!1;if(parsed.provider&&!parsed.model&&diagnostics.push({type:"error",message:`--provider requires --model (for example: --provider ${parsed.provider} --model <pattern>)`}),parsed.model){let resolved=resolveCliModel({cliProvider:parsed.provider,cliModel:parsed.model,cliThinking:parsed.thinking,inlineApiKey:!!parsed.apiKey,modelRuntime});resolved.warning&&diagnostics.push({type:"warning",message:resolved.warning}),resolved.error&&diagnostics.push({type:"error",message:resolved.error}),resolved.model&&(options.model=resolved.model,!parsed.thinking&&resolved.thinkingLevel&&(options.thinkingLevel=resolved.thinkingLevel,cliThinkingFromModel=!0))}if(!options.model&&scopedModels.length>0&&!hasExistingSession){let savedProvider=settingsManager.getDefaultProvider(),savedModelId=settingsManager.getDefaultModel(),savedModel=savedProvider&&savedModelId?modelRuntime.getModel(savedProvider,savedModelId):void 0,savedInScope=savedModel?scopedModels.find(sm=>modelsAreEqual(sm.model,savedModel)):void 0;savedInScope?(options.model=savedInScope.model,!parsed.thinking&&savedInScope.thinkingLevel&&(options.thinkingLevel=savedInScope.thinkingLevel)):(options.model=scopedModels[0].model,!parsed.thinking&&scopedModels[0].thinkingLevel&&(options.thinkingLevel=scopedModels[0].thinkingLevel))}return parsed.thinking&&(options.thinkingLevel=parsed.thinking),scopedModels.length>0&&(options.scopedModels=scopedModels.map(sm=>({model:sm.model,thinkingLevel:sm.thinkingLevel}))),parsed.noTools?options.noTools="all":parsed.noBuiltinTools&&(options.noTools="builtin"),parsed.tools&&(options.tools=[...parsed.tools]),parsed.excludeTools&&(options.excludeTools=[...parsed.excludeTools]),{options,cliThinkingFromModel,diagnostics}}function resolveCliPaths(cwd,paths){return paths?.map(value=>isLocalPath(value)?resolvePath(value,cwd):value)}async function promptForMissingSessionCwd(issue,settingsManager){return showStartupSelector(settingsManager,formatMissingSessionCwdPrompt(issue),[{label:"Continue",value:issue.fallbackCwd},{label:"Cancel",value:void 0}])}async function main(args,options){resetTimings(),setThemeJsonValidator(validateThemeJson);let extensionFactories=[...builtInExtensions,...options?.extensionFactories??[]],offlineMode=args.includes("--offline")||isTruthyEnvFlag2(process.env.PI_OFFLINE);if(offlineMode&&(process.env.PI_OFFLINE="1",process.env.PI_SKIP_VERSION_CHECK="1"),await runAuthCommand(args))return;process.platform==="win32"&&cleanupWindowsSelfUpdateQuarantine(getPackageDir()),cleanupManagedInstall();let cwd=process.cwd(),agentDir=getAgentDir(),bootstrapSettingsManager=SettingsManager.create(cwd,agentDir,{projectTrusted:!1});if(applyHttpProxySettings(bootstrapSettingsManager.getGlobalSettings().httpProxy),configureHttpDispatcher(),await handlePackageCommand(args,{extensionFactories})){let exitCode=process.exitCode??0;if(process.platform==="win32"&&exitCode===0&&args[0]==="update")return;process.exit(exitCode);return}if(await handleConfigCommand(args,{extensionFactories}))return;if(args[0]==="mcp"){let{runMcpCommand:runMcpCommand2}=await loadMcpCommand();process.exitCode=await runMcpCommand2(args.slice(1),{cwd,agentDir});return}let parsed=parseArgs(args);if(parsed.diagnostics.length>0){for(let d of parsed.diagnostics){let color2=d.type==="error"?source_default.red:source_default.yellow;console.error(color2(`${d.type==="error"?"Error":"Warning"}: ${d.message}`))}parsed.diagnostics.some(d=>d.type==="error")&&process.exit(1)}if(time("parseArgs"),parsed.version&&(console.log(VERSION),process.exit(0)),parsed.export){let result2;try{let outputPath=parsed.messages.length>0?parsed.messages[0]:void 0;result2=await exportFromFile(parsed.export,outputPath)}catch(error){let message=error instanceof Error?error.message:"Failed to export session";console.error(source_default.red(`Error: ${message}`)),process.exit(1)}console.log(`Exported to: ${result2}`),process.exit(0)}let appMode=resolveAppMode(parsed,process.stdin.isTTY,process.stdout.isTTY);appMode!=="interactive"&&!isPlainRuntimeMetadataCommand(parsed)&&takeOverStdout(),parsed.mode==="rpc"&&parsed.fileArgs.length>0&&(console.error(source_default.red("Error: @file arguments are not supported in RPC mode")),process.exit(1)),validateForkFlags(parsed),validateSessionIdFlags(parsed);let{migratedAuthProviders:migratedProviders,deprecationWarnings}=runMigrations(cwd);time("runMigrations");let startupSettingsManager=SettingsManager.create(cwd,agentDir),startupSettingsDiagnostics=collectSettingsDiagnostics(startupSettingsManager);appMode==="interactive"&&!parsed.help&&parsed.listModels===void 0&&shouldRunFirstTimeSetup()&&(await showFirstTimeSetup(startupSettingsManager),time("firstTimeSetup")),appMode==="interactive"&&parsed.useTheme!==void 0&&startupSettingsManager.applyOverrides({theme:parsed.useTheme});let envSessionDir=process.env[ENV_SESSION_DIR],sessionDir=(parsed.sessionDir?normalizePath(parsed.sessionDir):void 0)??(envSessionDir?expandTildePath(envSessionDir):void 0)??startupSettingsManager.getSessionDir(),sessionManager=await createSessionManager(parsed,cwd,sessionDir,startupSettingsManager),missingSessionCwdIssue=getMissingSessionCwdIssue(sessionManager,cwd);if(missingSessionCwdIssue)if(appMode==="interactive"){let selectedCwd=await promptForMissingSessionCwd(missingSessionCwdIssue,startupSettingsManager);selectedCwd||process.exit(0),sessionManager=SessionManager.open(missingSessionCwdIssue.sessionFile,sessionDir,selectedCwd)}else console.error(source_default.red(new MissingSessionCwdError(missingSessionCwdIssue).message)),process.exit(1);if(parsed.name!==void 0){let name=normalizeSessionName(parsed.name);name===void 0&&(console.error(source_default.red("Error: --name requires a non-empty value")),process.exit(1)),sessionManager.appendSessionInfo(name)}time("createSessionManager");let trustStore=new ProjectTrustStore(agentDir),sessionCwd=sessionManager.getCwd(),autoTrustOnReloadCwd=parsed.projectTrustOverride===void 0&&!hasTrustRequiringProjectResources(sessionCwd)?sessionCwd:void 0,trustPromptMode=parsed.help||parsed.listModels!==void 0?"print":appMode,projectTrustByCwd=new Map,resolvedExtensionPaths=resolveCliPaths(cwd,parsed.extensions),resolvedSkillPaths=resolveCliPaths(cwd,parsed.skills),resolvedPromptTemplatePaths=resolveCliPaths(cwd,parsed.promptTemplates),resolvedThemePaths=resolveCliPaths(cwd,parsed.themes),createRuntime=async({cwd:cwd2,agentDir:agentDir2,sessionManager:sessionManager2,sessionStartEvent,projectTrustContext})=>{let isInitialRuntime=sessionStartEvent===void 0,projectTrustDiagnostics=[],cachedProjectTrust=projectTrustByCwd.get(cwd2),hasTrustRequiringResources=hasTrustRequiringProjectResources(cwd2),shouldResolveProjectTrust=parsed.projectTrustOverride===void 0&&cachedProjectTrust===void 0&&hasTrustRequiringResources,projectTrusted=shouldResolveProjectTrust?!1:cachedProjectTrust??parsed.projectTrustOverride??(!hasTrustRequiringResources||trustStore.get(cwd2)===!0),runtimeSettingsManager=SettingsManager.create(cwd2,agentDir2,{projectTrusted}),services2=await createAgentSessionServices({cwd:cwd2,agentDir:agentDir2,settingsManager:runtimeSettingsManager,modelRuntimeSignal:AbortSignal.timeout(15e3),extensionFlagValues:parsed.unknownFlags,resourceLoaderReloadOptions:shouldResolveProjectTrust?{resolveProjectTrust:async({extensionsResult})=>{let trusted=await resolveProjectTrusted({cwd:cwd2,trustStore,trustOverride:parsed.projectTrustOverride,defaultProjectTrust:startupSettingsManager.getDefaultProjectTrust(),extensionsResult,projectTrustContext:projectTrustContext??createProjectTrustContext({cwd:cwd2,mode:isInitialRuntime?trustPromptMode:appMode,settingsManager:startupSettingsManager,hasUI:isInitialRuntime&&trustPromptMode==="interactive"}),onExtensionError:message=>projectTrustDiagnostics.push({type:"warning",message})});return projectTrustByCwd.set(cwd2,trusted),trusted}}:void 0,resourceLoaderOptions:{additionalExtensionPaths:resolvedExtensionPaths,additionalSkillPaths:resolvedSkillPaths,additionalPromptTemplatePaths:resolvedPromptTemplatePaths,additionalThemePaths:resolvedThemePaths,noExtensions:parsed.noExtensions,disabledBuiltinExtensions:parsed.noMcp?["mcp"]:void 0,noSkills:parsed.noSkills,noPromptTemplates:parsed.noPromptTemplates,noThemes:parsed.noThemes,noContextFiles:parsed.noContextFiles,systemPrompt:parsed.systemPrompt,appendSystemPrompt:parsed.appendSystemPrompt,extensionFactories}}),{settingsManager:settingsManager2,modelRuntime:modelRuntime2,resourceLoader:resourceLoader2}=services2,diagnostics=[...projectTrustDiagnostics,...services2.diagnostics,...collectSettingsDiagnostics(settingsManager2),...resourceLoader2.getExtensions().errors.map(({path:path14,error})=>({type:"error",message:`Failed to load extension "${path14}": ${error}`})),...(resourceLoader2.getExtensions().warnings??[]).map(({path:path14,warning})=>({type:"warning",message:`Extension package "${path14}": ${warning}`}))],modelPatterns=parsed.models??settingsManager2.getEnabledModels(),scopedModels=modelPatterns&&modelPatterns.length>0?await resolveModelScope(modelPatterns,modelRuntime2,{signal:AbortSignal.timeout(15e3)}):[],{options:sessionOptions,cliThinkingFromModel,diagnostics:sessionOptionDiagnostics}=buildSessionOptions(parsed,scopedModels,sessionManager2.buildSessionContext().messages.length>0,modelRuntime2,settingsManager2);diagnostics.push(...sessionOptionDiagnostics),parsed.apiKey&&(sessionOptions.model?await modelRuntime2.setRuntimeApiKey(sessionOptions.model.provider,parsed.apiKey):diagnostics.push({type:"error",message:"--api-key requires a model to be specified via --model, --provider/--model, or --models"}));let created=await createAgentSessionFromServices({services:services2,sessionManager:sessionManager2,sessionStartEvent,model:sessionOptions.model,thinkingLevel:sessionOptions.thinkingLevel,scopedModels:sessionOptions.scopedModels,tools:sessionOptions.tools,excludeTools:sessionOptions.excludeTools,noTools:sessionOptions.noTools,customTools:sessionOptions.customTools}),cliThinkingOverride=parsed.thinking!==void 0||cliThinkingFromModel;return created.session.model&&cliThinkingOverride&&created.session.setThinkingLevel(created.session.thinkingLevel),{...created,services:services2,diagnostics}};time("createRuntime");let runtime=await createAgentSessionRuntime(createRuntime,{cwd:sessionManager.getCwd(),agentDir,sessionManager});time("createAgentSessionRuntime");let{services,session,modelFallbackMessage}=runtime,{settingsManager,modelRuntime,resourceLoader}=services;if(setCapabilityOverrides(settingsManager.getTerminalCapabilityOverrides()),applyHttpProxySettings(settingsManager.getGlobalSettings().httpProxy),configureHttpDispatcher(settingsManager.getHttpIdleTimeoutMs()),parsed.help){reportDiagnostics(startupSettingsDiagnostics);let extensionFlags=resourceLoader.getExtensions().extensions.flatMap(extension=>Array.from(extension.flags.values()));printHelp(extensionFlags),process.exit(0)}if(parsed.listModels!==void 0){reportDiagnostics(startupSettingsDiagnostics);let searchPattern=typeof parsed.listModels=="string"?parsed.listModels:void 0;await listModels(modelRuntime,searchPattern,AbortSignal.timeout(15e3)),process.exit(0)}let stdinContent;appMode!=="rpc"&&(stdinContent=await readPipedStdin(),stdinContent!==void 0&&appMode==="interactive"&&(appMode="print")),time("readPipedStdin");let{initialMessage,initialImages}=await prepareInitialMessage(parsed,stdinContent);time("prepareInitialMessage"),initTheme(settingsManager.getTheme(),appMode==="interactive"),time("initTheme"),appMode==="interactive"&&deprecationWarnings.length>0&&await showDeprecationWarnings(deprecationWarnings),time("resolveModelScope");let startupDiagnostics=deduplicateDiagnostics([...startupSettingsDiagnostics,...runtime.diagnostics]),hasRuntimeErrors=runtime.diagnostics.some(diagnostic=>diagnostic.type==="error");(appMode!=="interactive"||hasRuntimeErrors)&&reportDiagnostics(startupDiagnostics),hasRuntimeErrors&&(runtime.diagnostics.some(diagnostic=>diagnostic.message.includes("Failed to load extension"))&&console.error(source_default.yellow(EXTENSION_LOAD_FAILURE_HINT)),process.exit(1)),time("createAgentSession"),appMode!=="interactive"&&!session.model&&(console.error(source_default.red(formatNoModelsAvailableMessage())),process.exit(1));let startupBenchmark=isTruthyEnvFlag2(process.env.PI_STARTUP_BENCHMARK);if(startupBenchmark&&appMode!=="interactive"&&(console.error(source_default.red("Error: PI_STARTUP_BENCHMARK only supports interactive mode")),process.exit(1)),!offlineMode&&appMode==="rpc"){let controller=new AbortController,timeout=setTimeout(()=>controller.abort(),15e3);modelRuntime.refresh({signal:controller.signal}).catch(()=>{}).finally(()=>clearTimeout(timeout))}if(appMode==="rpc")printTimings(),await runRpcMode(runtime);else if(appMode==="interactive"){let interactiveMode=new InteractiveMode(runtime,{migratedProviders,startupDiagnostics,modelFallbackMessage,autoTrustOnReloadCwd,initialMessage,initialImages,initialMessages:parsed.messages,verbose:parsed.verbose,tuiMode:parsed.tuiMode,initialThemeSetting:parsed.useTheme});if(startupBenchmark){await interactiveMode.init(),time("interactiveMode.init"),await new Promise(resolve20=>setTimeout(resolve20,150)),interactiveMode.stop(),stopThemeWatcher(),printTimings(),process.stdout.writableLength>0&&await new Promise(resolve20=>process.stdout.once("drain",resolve20)),process.stderr.writableLength>0&&await new Promise(resolve20=>process.stderr.once("drain",resolve20));return}printTimings(),await interactiveMode.run()}else{printTimings();let exitCode=await runPrintMode(runtime,{mode:toPrintOutputMode(appMode),messages:parsed.messages,initialMessage,initialImages});stopThemeWatcher(),restoreStdout(),exitCode!==0&&(process.exitCode=exitCode);return}}export{getPackageDir,getReadmePath,getDocsPath,getExamplesPath,DISTRIBUTION_PACKAGE_NAME,APP_NAME,CONFIG_DIR_NAME,VERSION,getAgentDir,configureHttpDispatcher,build_exports,value_exports2 as value_exports,compile_exports,Container,SelectList,dist_exports,SettingsManager,parseArgs,resolveModelScopeWithDiagnostics,resolveCliModel,all_exports,getShellConfig,getPowerShellConfig,readStoredCredential,compat_exports,VIRTUAL_MODEL_STATE_ENTRY,CredentialSynchronizationError,ModelRuntime,convertToPng,resizeImage,formatDimensionNote,detectSupportedImageMimeTypeFromFile,createSyntheticSourceInfo,DefaultPackageManager,Theme,getAvailableThemes,initTheme,highlightCode,getLanguageFromPath,getMarkdownTheme,getSelectListTheme,getSettingsListTheme,DynamicBorder,keyText,keyHint,rawKeyHint,ExtensionInputComponent,ExtensionSelectorComponent,SessionSelectorComponent,parseFrontmatter,stripFrontmatter,loadSkillsFromDir,formatSkillsForPrompt,loadSkills,TaskRuntime,ExtensionRunner,convertToLlm,CURRENT_SESSION_VERSION,migrateSessionEntries,parseSessionEntries,getLatestCompactionEntry,sessionEntryToContextMessages,buildContextEntries,buildSessionProjection,buildSessionContext,SessionManager,createEventBus,dist_exports2,DEFAULT_MAX_LINES,DEFAULT_MAX_BYTES2 as DEFAULT_MAX_BYTES,formatSize,truncateHead,truncateTail,truncateLine,serializeConversation,DEFAULT_COMPACTION_SETTINGS,calculateContextTokens,getLastAssistantUsage,shouldCompact,estimateTokens2 as estimateTokens,findTurnStartIndex,findCutPoint,generateSummary,generateSummaryWithUsage,compact,collectEntriesForBranchSummary,prepareBranchEntries,generateBranchSummary,defineTool,isBashToolResult,isPowerShellToolResult,isReadToolResult,isEditToolResult,isWriteToolResult,isGrepToolResult,isFindToolResult,isLsToolResult,isToolCallEventType,wrapRegisteredTool,wrapRegisteredTools,ModelRegistry,truncateToVisualLines,formatReadLineRange,createLocalBashOperations,createBashToolDefinition,createBashTool,generateUnifiedPatch,generateDiffString,withFileMutationQueue,renderDiff,createEditToolDefinition,createEditTool,createFindToolDefinition,createFindTool,createGrepToolDefinition,createGrepTool,createLsToolDefinition,createLsTool,createLocalPowerShellOperations,createPowerShellToolDefinition,createPowerShellTool,createReadToolDefinition,createReadTool,createWriteToolDefinition,createWriteTool,createCodingTools,createReadOnlyTools,parseSkillBlock,AgentSession,createAgentSession,hasTrustRequiringProjectResources,ProjectTrustStore,createCodemodeExtension,copyToClipboard,createMcpExtension,createToolSearchExtension,BorderedLoader,ExtensionEditorComponent,ArminComponent,AssistantMessageComponent,BashExecutionComponent,BranchSummaryMessageComponent,CompactionSummaryMessageComponent,CustomEditor,CustomMessageComponent,FooterComponent,LoginDialogComponent,ModelSelectorComponent,OAuthSelectorComponent,SettingsSelectorComponent,SkillInvocationMessageComponent,ThinkingSelectorComponent,TreeSelectorComponent,UserMessageComponent,UserMessageSelectorComponent,ToolExecutionComponent,InteractiveMode,runPrintMode,RpcClient,runRpcMode,createExtensionRuntime,discoverAndLoadExtensions,loadProjectContextFiles,DefaultResourceLoader,createAgentSessionServices,createAgentSessionFromServices,AgentSessionRuntime,createAgentSessionRuntime,main};
|
|
2361
|
+
`),process.exitCode=result2.status==="ready"?0:result2.status==="not_ready"?1:2}catch(error){let message=error instanceof AuthCommandError?error.message:"Failed to resolve credential";console.error(source_default.red(`Error: ${message}`)),process.exitCode=command.kind==="check"?2:1}return!0}async function prepareInitialMessage(parsed,stdinContent){if(parsed.fileArgs.length===0)return buildInitialMessage({parsed,stdinContent});let{text:text2,images}=await processFileArguments(parsed.fileArgs,{autoResizeImages:!1});return buildInitialMessage({parsed,fileText:text2,fileImages:images,stdinContent})}function findLocalSessionByExactId(sessionId,cwd,sessionDir){let path14=SessionManager.findById(cwd,sessionId,sessionDir);return path14?{type:"local",path:path14}:void 0}async function resolveSessionPath(sessionArg,cwd,sessionDir){if(sessionArg.includes("/")||sessionArg.includes("\\")||sessionArg.endsWith(".jsonl"))return{type:"path",path:resolvePath(sessionArg,cwd)};let exactLocalMatch=findLocalSessionByExactId(sessionArg,cwd,sessionDir);if(exactLocalMatch)return exactLocalMatch;let localMatch=(await SessionManager.list(cwd,sessionDir)).find(s=>s.id.startsWith(sessionArg));if(localMatch)return{type:"local",path:localMatch.path};let allSessions=await SessionManager.listAll(sessionDir),globalMatch=allSessions.find(s=>s.id===sessionArg)??allSessions.find(s=>s.id.startsWith(sessionArg));return globalMatch?{type:"global",path:globalMatch.path,cwd:globalMatch.cwd}:{type:"not_found",arg:sessionArg}}async function promptConfirm(message){return new Promise(resolve20=>{let rl=createInterface6({input:process.stdin,output:process.stdout});rl.question(`${message} [y/N] `,answer=>{rl.close(),resolve20(answer.toLowerCase()==="y"||answer.toLowerCase()==="yes")})})}function validateForkFlags(parsed){if(!parsed.fork)return;let conflictingFlags=[parsed.session?"--session":void 0,parsed.continue?"--continue":void 0,parsed.resume?"--resume":void 0,parsed.noSession?"--no-session":void 0].filter(flag=>flag!==void 0);conflictingFlags.length>0&&(console.error(source_default.red(`Error: --fork cannot be combined with ${conflictingFlags.join(", ")}`)),process.exit(1))}function validateSessionIdFlags(parsed){if(parsed.sessionId===void 0)return;let conflictingFlags=[parsed.session?"--session":void 0,parsed.continue?"--continue":void 0,parsed.resume?"--resume":void 0].filter(flag=>flag!==void 0);conflictingFlags.length>0&&(console.error(source_default.red(`Error: --session-id cannot be combined with ${conflictingFlags.join(", ")}`)),process.exit(1));try{assertValidSessionId(parsed.sessionId)}catch(error){let message=error instanceof Error?error.message:String(error);console.error(source_default.red(`Error: ${message}`)),process.exit(1)}}function openSessionOrExit(path14,sessionDir){try{return SessionManager.open(path14,sessionDir)}catch(error){let message=error instanceof Error?error.message:String(error);console.error(source_default.red(`Error: ${message}`)),process.exit(1)}}function forkSessionOrExit(sourcePath,cwd,sessionDir,sessionId){try{return SessionManager.forkFrom(sourcePath,cwd,sessionDir,{id:sessionId})}catch(error){let message=error instanceof Error?error.message:String(error);console.error(source_default.red(`Error: ${message}`)),process.exit(1)}}async function createSessionManager(parsed,cwd,sessionDir,settingsManager){if(parsed.noSession||parsed.help||parsed.listModels!==void 0)return SessionManager.inMemory(cwd,parsed.sessionId!==void 0?{id:parsed.sessionId}:void 0);if(parsed.fork){parsed.sessionId&&findLocalSessionByExactId(parsed.sessionId,cwd,sessionDir)&&(console.error(source_default.red(`Session already exists with id '${parsed.sessionId}'`)),process.exit(1));let resolved=await resolveSessionPath(parsed.fork,cwd,sessionDir);switch(resolved.type){case"path":case"local":case"global":return forkSessionOrExit(resolved.path,cwd,sessionDir,parsed.sessionId);case"not_found":console.error(source_default.red(`No session found matching '${resolved.arg}'`)),process.exit(1)}}if(parsed.session){let resolved=await resolveSessionPath(parsed.session,cwd,sessionDir);switch(resolved.type){case"path":case"local":return openSessionOrExit(resolved.path,sessionDir);case"global":return console.log(source_default.yellow(`Session found in different project: ${resolved.cwd}`)),await promptConfirm("Fork this session into current directory?")||(console.log(source_default.dim("Aborted.")),process.exit(0)),forkSessionOrExit(resolved.path,cwd,sessionDir);case"not_found":console.error(source_default.red(`No session found matching '${resolved.arg}'`)),process.exit(1)}}if(parsed.resume)try{let selectedPath=await selectSession((onProgress,signal)=>SessionManager.list(cwd,sessionDir,onProgress,signal),(onProgress,signal)=>SessionManager.listAll(sessionDir,onProgress,signal),settingsManager);return selectedPath||(console.log(source_default.dim("No session selected")),process.exit(0)),SessionManager.open(selectedPath,sessionDir)}finally{stopThemeWatcher()}if(parsed.continue)return SessionManager.continueRecent(cwd,sessionDir);if(parsed.sessionId){let existingSession=findLocalSessionByExactId(parsed.sessionId,cwd,sessionDir);if(existingSession)return SessionManager.open(existingSession.path,sessionDir);console.error(source_default.yellow(`Warning: No project session found with id '${parsed.sessionId}'; creating a new session with that id.`))}return SessionManager.create(cwd,sessionDir,{id:parsed.sessionId})}function buildSessionOptions(parsed,scopedModels,hasExistingSession,modelRuntime,settingsManager){let options={},diagnostics=[],cliThinkingFromModel=!1;if(parsed.provider&&!parsed.model&&diagnostics.push({type:"error",message:`--provider requires --model (for example: --provider ${parsed.provider} --model <pattern>)`}),parsed.model){let resolved=resolveCliModel({cliProvider:parsed.provider,cliModel:parsed.model,cliThinking:parsed.thinking,inlineApiKey:!!parsed.apiKey,modelRuntime});resolved.warning&&diagnostics.push({type:"warning",message:resolved.warning}),resolved.error&&diagnostics.push({type:"error",message:resolved.error}),resolved.model&&(options.model=resolved.model,!parsed.thinking&&resolved.thinkingLevel&&(options.thinkingLevel=resolved.thinkingLevel,cliThinkingFromModel=!0))}if(!options.model&&scopedModels.length>0&&!hasExistingSession){let savedProvider=settingsManager.getDefaultProvider(),savedModelId=settingsManager.getDefaultModel(),savedModel=savedProvider&&savedModelId?modelRuntime.getModel(savedProvider,savedModelId):void 0,savedInScope=savedModel?scopedModels.find(sm=>modelsAreEqual(sm.model,savedModel)):void 0;savedInScope?(options.model=savedInScope.model,!parsed.thinking&&savedInScope.thinkingLevel&&(options.thinkingLevel=savedInScope.thinkingLevel)):(options.model=scopedModels[0].model,!parsed.thinking&&scopedModels[0].thinkingLevel&&(options.thinkingLevel=scopedModels[0].thinkingLevel))}return parsed.thinking&&(options.thinkingLevel=parsed.thinking),scopedModels.length>0&&(options.scopedModels=scopedModels.map(sm=>({model:sm.model,thinkingLevel:sm.thinkingLevel}))),parsed.noTools?options.noTools="all":parsed.noBuiltinTools&&(options.noTools="builtin"),parsed.tools&&(options.tools=[...parsed.tools]),parsed.excludeTools&&(options.excludeTools=[...parsed.excludeTools]),{options,cliThinkingFromModel,diagnostics}}function resolveCliPaths(cwd,paths){return paths?.map(value=>isLocalPath(value)?resolvePath(value,cwd):value)}async function promptForMissingSessionCwd(issue,settingsManager){return showStartupSelector(settingsManager,formatMissingSessionCwdPrompt(issue),[{label:"Continue",value:issue.fallbackCwd},{label:"Cancel",value:void 0}])}async function main(args,options){resetTimings(),setThemeJsonValidator(validateThemeJson);let extensionFactories=[...builtInExtensions,...options?.extensionFactories??[]],offlineMode=args.includes("--offline")||isTruthyEnvFlag2(process.env.PI_OFFLINE);if(offlineMode&&(process.env.PI_OFFLINE="1",process.env.PI_SKIP_VERSION_CHECK="1"),await runAuthCommand(args))return;process.platform==="win32"&&cleanupWindowsSelfUpdateQuarantine(getPackageDir()),cleanupManagedInstall();let cwd=process.cwd(),agentDir=getAgentDir(),bootstrapSettingsManager=SettingsManager.create(cwd,agentDir,{projectTrusted:!1});if(applyHttpProxySettings(bootstrapSettingsManager.getGlobalSettings().httpProxy),configureHttpDispatcher(),await handlePackageCommand(args,{extensionFactories})){let exitCode=process.exitCode??0;if(process.platform==="win32"&&exitCode===0&&args[0]==="update")return;process.exit(exitCode);return}if(await handleConfigCommand(args,{extensionFactories}))return;if(args[0]==="mcp"){let{runMcpCommand:runMcpCommand2}=await loadMcpCommand();process.exitCode=await runMcpCommand2(args.slice(1),{cwd,agentDir});return}let parsed=parseArgs(args);if(parsed.diagnostics.length>0){for(let d of parsed.diagnostics){let color2=d.type==="error"?source_default.red:source_default.yellow;console.error(color2(`${d.type==="error"?"Error":"Warning"}: ${d.message}`))}parsed.diagnostics.some(d=>d.type==="error")&&process.exit(1)}if(time("parseArgs"),parsed.version&&(console.log(VERSION),process.exit(0)),parsed.export){let result2;try{let outputPath=parsed.messages.length>0?parsed.messages[0]:void 0;result2=await exportFromFile(parsed.export,outputPath)}catch(error){let message=error instanceof Error?error.message:"Failed to export session";console.error(source_default.red(`Error: ${message}`)),process.exit(1)}console.log(`Exported to: ${result2}`),process.exit(0)}let appMode=resolveAppMode(parsed,process.stdin.isTTY,process.stdout.isTTY);appMode!=="interactive"&&!isPlainRuntimeMetadataCommand(parsed)&&takeOverStdout(),parsed.mode==="rpc"&&parsed.fileArgs.length>0&&(console.error(source_default.red("Error: @file arguments are not supported in RPC mode")),process.exit(1)),validateForkFlags(parsed),validateSessionIdFlags(parsed);let{migratedAuthProviders:migratedProviders,deprecationWarnings}=runMigrations(cwd);time("runMigrations");let startupSettingsManager=SettingsManager.create(cwd,agentDir),startupSettingsDiagnostics=collectSettingsDiagnostics(startupSettingsManager);appMode==="interactive"&&!parsed.help&&parsed.listModels===void 0&&shouldRunFirstTimeSetup()&&(await showFirstTimeSetup(startupSettingsManager),time("firstTimeSetup")),appMode==="interactive"&&parsed.useTheme!==void 0&&startupSettingsManager.applyOverrides({theme:parsed.useTheme});let envSessionDir=process.env[ENV_SESSION_DIR],sessionDir=(parsed.sessionDir?normalizePath(parsed.sessionDir):void 0)??(envSessionDir?expandTildePath(envSessionDir):void 0)??startupSettingsManager.getSessionDir(),sessionManager=await createSessionManager(parsed,cwd,sessionDir,startupSettingsManager),missingSessionCwdIssue=getMissingSessionCwdIssue(sessionManager,cwd);if(missingSessionCwdIssue)if(appMode==="interactive"){let selectedCwd=await promptForMissingSessionCwd(missingSessionCwdIssue,startupSettingsManager);selectedCwd||process.exit(0),sessionManager=SessionManager.open(missingSessionCwdIssue.sessionFile,sessionDir,selectedCwd)}else console.error(source_default.red(new MissingSessionCwdError(missingSessionCwdIssue).message)),process.exit(1);if(parsed.name!==void 0){let name=normalizeSessionName(parsed.name);name===void 0&&(console.error(source_default.red("Error: --name requires a non-empty value")),process.exit(1)),sessionManager.appendSessionInfo(name)}time("createSessionManager");let trustStore=new ProjectTrustStore(agentDir),sessionCwd=sessionManager.getCwd(),autoTrustOnReloadCwd=parsed.projectTrustOverride===void 0&&!hasTrustRequiringProjectResources(sessionCwd)?sessionCwd:void 0,trustPromptMode=parsed.help||parsed.listModels!==void 0?"print":appMode,projectTrustByCwd=new Map,resolvedExtensionPaths=resolveCliPaths(cwd,parsed.extensions),resolvedSkillPaths=resolveCliPaths(cwd,parsed.skills),resolvedPromptTemplatePaths=resolveCliPaths(cwd,parsed.promptTemplates),resolvedThemePaths=resolveCliPaths(cwd,parsed.themes),createRuntime=async({cwd:cwd2,agentDir:agentDir2,sessionManager:sessionManager2,sessionStartEvent,projectTrustContext})=>{let isInitialRuntime=sessionStartEvent===void 0,projectTrustDiagnostics=[],cachedProjectTrust=projectTrustByCwd.get(cwd2),hasTrustRequiringResources=hasTrustRequiringProjectResources(cwd2),shouldResolveProjectTrust=parsed.projectTrustOverride===void 0&&cachedProjectTrust===void 0&&hasTrustRequiringResources,projectTrusted=shouldResolveProjectTrust?!1:cachedProjectTrust??parsed.projectTrustOverride??(!hasTrustRequiringResources||trustStore.get(cwd2)===!0),runtimeSettingsManager=SettingsManager.create(cwd2,agentDir2,{projectTrusted}),services2=await createAgentSessionServices({cwd:cwd2,agentDir:agentDir2,settingsManager:runtimeSettingsManager,modelRuntimeSignal:AbortSignal.timeout(15e3),extensionFlagValues:parsed.unknownFlags,resourceLoaderReloadOptions:shouldResolveProjectTrust?{resolveProjectTrust:async({extensionsResult})=>{let trusted=await resolveProjectTrusted({cwd:cwd2,trustStore,trustOverride:parsed.projectTrustOverride,defaultProjectTrust:startupSettingsManager.getDefaultProjectTrust(),extensionsResult,projectTrustContext:projectTrustContext??createProjectTrustContext({cwd:cwd2,mode:isInitialRuntime?trustPromptMode:appMode,settingsManager:startupSettingsManager,hasUI:isInitialRuntime&&trustPromptMode==="interactive"}),onExtensionError:message=>projectTrustDiagnostics.push({type:"warning",message})});return projectTrustByCwd.set(cwd2,trusted),trusted}}:void 0,resourceLoaderOptions:{additionalExtensionPaths:resolvedExtensionPaths,additionalSkillPaths:resolvedSkillPaths,additionalPromptTemplatePaths:resolvedPromptTemplatePaths,additionalThemePaths:resolvedThemePaths,noExtensions:parsed.noExtensions,disabledBuiltinExtensions:parsed.noMcp?["mcp"]:void 0,noSkills:parsed.noSkills,noPromptTemplates:parsed.noPromptTemplates,noThemes:parsed.noThemes,noContextFiles:parsed.noContextFiles,systemPrompt:parsed.systemPrompt,appendSystemPrompt:parsed.appendSystemPrompt,extensionFactories}}),{settingsManager:settingsManager2,modelRuntime:modelRuntime2,resourceLoader:resourceLoader2}=services2,diagnostics=[...projectTrustDiagnostics,...services2.diagnostics,...collectSettingsDiagnostics(settingsManager2),...resourceLoader2.getExtensions().errors.map(({path:path14,error})=>({type:"error",message:`Failed to load extension "${path14}": ${error}`})),...(resourceLoader2.getExtensions().warnings??[]).map(({path:path14,warning})=>({type:"warning",message:`Extension package "${path14}": ${warning}`}))],modelPatterns=parsed.models??settingsManager2.getEnabledModels(),scopedModels=modelPatterns&&modelPatterns.length>0?await resolveModelScope(modelPatterns,modelRuntime2,{signal:AbortSignal.timeout(15e3)}):[],{options:sessionOptions,cliThinkingFromModel,diagnostics:sessionOptionDiagnostics}=buildSessionOptions(parsed,scopedModels,sessionManager2.buildSessionContext().messages.length>0,modelRuntime2,settingsManager2);diagnostics.push(...sessionOptionDiagnostics),parsed.apiKey&&(sessionOptions.model?await modelRuntime2.setRuntimeApiKey(sessionOptions.model.provider,parsed.apiKey):diagnostics.push({type:"error",message:"--api-key requires a model to be specified via --model, --provider/--model, or --models"}));let created=await createAgentSessionFromServices({services:services2,sessionManager:sessionManager2,sessionStartEvent,model:sessionOptions.model,thinkingLevel:sessionOptions.thinkingLevel,scopedModels:sessionOptions.scopedModels,tools:sessionOptions.tools,excludeTools:sessionOptions.excludeTools,noTools:sessionOptions.noTools,customTools:sessionOptions.customTools}),cliThinkingOverride=parsed.thinking!==void 0||cliThinkingFromModel;return created.session.model&&cliThinkingOverride&&created.session.setThinkingLevel(created.session.thinkingLevel),{...created,services:services2,diagnostics}};time("createRuntime");let runtime=await createAgentSessionRuntime(createRuntime,{cwd:sessionManager.getCwd(),agentDir,sessionManager});time("createAgentSessionRuntime");let{services,session,modelFallbackMessage}=runtime,{settingsManager,modelRuntime,resourceLoader}=services;if(setCapabilityOverrides(settingsManager.getTerminalCapabilityOverrides()),applyHttpProxySettings(settingsManager.getGlobalSettings().httpProxy),configureHttpDispatcher(settingsManager.getHttpIdleTimeoutMs()),parsed.help){reportDiagnostics(startupSettingsDiagnostics);let extensionFlags=resourceLoader.getExtensions().extensions.flatMap(extension=>Array.from(extension.flags.values()));printHelp(extensionFlags),process.exit(0)}if(parsed.listModels!==void 0){reportDiagnostics(startupSettingsDiagnostics);let searchPattern=typeof parsed.listModels=="string"?parsed.listModels:void 0;await listModels(modelRuntime,searchPattern,AbortSignal.timeout(15e3)),process.exit(0)}let stdinContent;appMode!=="rpc"&&(stdinContent=await readPipedStdin(),stdinContent!==void 0&&appMode==="interactive"&&(appMode="print")),time("readPipedStdin");let{initialMessage,initialImages}=await prepareInitialMessage(parsed,stdinContent);time("prepareInitialMessage"),initTheme(settingsManager.getTheme(),appMode==="interactive"),time("initTheme"),appMode==="interactive"&&deprecationWarnings.length>0&&await showDeprecationWarnings(deprecationWarnings),time("resolveModelScope");let startupDiagnostics=deduplicateDiagnostics([...startupSettingsDiagnostics,...runtime.diagnostics]),hasRuntimeErrors=runtime.diagnostics.some(diagnostic=>diagnostic.type==="error");(appMode!=="interactive"||hasRuntimeErrors)&&reportDiagnostics(startupDiagnostics),hasRuntimeErrors&&(runtime.diagnostics.some(diagnostic=>diagnostic.message.includes("Failed to load extension"))&&console.error(source_default.yellow(EXTENSION_LOAD_FAILURE_HINT)),process.exit(1)),time("createAgentSession"),appMode!=="interactive"&&!session.model&&(console.error(source_default.red(formatNoModelsAvailableMessage())),process.exit(1));let startupBenchmark=isTruthyEnvFlag2(process.env.PI_STARTUP_BENCHMARK);if(startupBenchmark&&appMode!=="interactive"&&(console.error(source_default.red("Error: PI_STARTUP_BENCHMARK only supports interactive mode")),process.exit(1)),!offlineMode&&appMode==="rpc"){let controller=new AbortController,timeout=setTimeout(()=>controller.abort(),15e3);modelRuntime.refresh({signal:controller.signal}).catch(()=>{}).finally(()=>clearTimeout(timeout))}if(appMode==="rpc")printTimings(),await runRpcMode(runtime);else if(appMode==="interactive"){let interactiveMode=new InteractiveMode(runtime,{migratedProviders,startupDiagnostics,modelFallbackMessage,autoTrustOnReloadCwd,initialMessage,initialImages,initialMessages:parsed.messages,verbose:parsed.verbose,tuiMode:parsed.tuiMode,initialThemeSetting:parsed.useTheme});if(startupBenchmark){await interactiveMode.init(),time("interactiveMode.init"),await new Promise(resolve20=>setTimeout(resolve20,150)),interactiveMode.stop(),stopThemeWatcher(),printTimings(),process.stdout.writableLength>0&&await new Promise(resolve20=>process.stdout.once("drain",resolve20)),process.stderr.writableLength>0&&await new Promise(resolve20=>process.stderr.once("drain",resolve20));return}printTimings(),await interactiveMode.run()}else{printTimings();let exitCode=await runPrintMode(runtime,{mode:toPrintOutputMode(appMode),messages:parsed.messages,initialMessage,initialImages});stopThemeWatcher(),restoreStdout(),exitCode!==0&&(process.exitCode=exitCode);return}}export{getPackageDir,getReadmePath,getDocsPath,getExamplesPath,DISTRIBUTION_PACKAGE_NAME,APP_NAME,CONFIG_DIR_NAME,VERSION,getAgentDir,configureHttpDispatcher,build_exports,value_exports2 as value_exports,compile_exports,Container,SelectList,dist_exports,SettingsManager,parseArgs,resolveModelScopeWithDiagnostics,resolveCliModel,all_exports,getShellConfig,getPowerShellConfig,readStoredCredential,compat_exports,VIRTUAL_MODEL_STATE_ENTRY,CredentialSynchronizationError,ModelRuntime,convertToPng,resizeImage,formatDimensionNote,detectSupportedImageMimeTypeFromFile,createSyntheticSourceInfo,DefaultPackageManager,Theme,getAvailableThemes,initTheme,highlightCode,getLanguageFromPath,getMarkdownTheme,getSelectListTheme,getSettingsListTheme,DynamicBorder,keyText,keyHint,rawKeyHint,ExtensionInputComponent,ExtensionSelectorComponent,SessionSelectorComponent,parseFrontmatter,stripFrontmatter,loadSkillsFromDir,formatSkillsForPrompt,loadSkills,TaskRuntime,ExtensionRunner,convertToLlm,CURRENT_SESSION_VERSION,migrateSessionEntries,parseSessionEntries,getLatestCompactionEntry,sessionEntryToContextMessages,buildContextEntries,buildSessionProjection,buildSessionContext,SessionManager,createEventBus,dist_exports2,DEFAULT_MAX_LINES,DEFAULT_MAX_BYTES2 as DEFAULT_MAX_BYTES,formatSize,truncateHead,truncateTail,truncateLine,serializeConversation,DEFAULT_COMPACTION_SETTINGS,calculateContextTokens,getLastAssistantUsage,shouldCompact,estimateTokens2 as estimateTokens,findTurnStartIndex,findCutPoint,generateSummary,generateSummaryWithUsage,compact,collectEntriesForBranchSummary,prepareBranchEntries,generateBranchSummary,defineTool,isBashToolResult,isPowerShellToolResult,isReadToolResult,isEditToolResult,isWriteToolResult,isGrepToolResult,isFindToolResult,isLsToolResult,isToolCallEventType,wrapRegisteredTool,wrapRegisteredTools,ModelRegistry,truncateToVisualLines,formatReadLineRange,createLocalBashOperations,createBashToolDefinition,createBashTool,generateUnifiedPatch,generateDiffString,withFileMutationQueue,renderDiff,createEditToolDefinition,createEditTool,createFindToolDefinition,createFindTool,createGrepToolDefinition,createGrepTool,createLsToolDefinition,createLsTool,createLocalPowerShellOperations,createPowerShellToolDefinition,createPowerShellTool,createReadToolDefinition,createReadTool,createWriteToolDefinition,createWriteTool,createCodingTools,createReadOnlyTools,parseSkillBlock,AgentSession,createAgentSession,hasTrustRequiringProjectResources,ProjectTrustStore,createCodemodeExtension,copyToClipboard,createMcpExtension,createToolSearchExtension,BorderedLoader,ExtensionEditorComponent,ArminComponent,AssistantMessageComponent,BashExecutionComponent,BranchSummaryMessageComponent,CompactionSummaryMessageComponent,CustomEditor,CustomMessageComponent,FooterComponent,LoginDialogComponent,ModelSelectorComponent,OAuthSelectorComponent,SettingsSelectorComponent,SkillInvocationMessageComponent,ThinkingSelectorComponent,ToolExecutionComponent,TreeSelectorComponent,UserMessageComponent,UserMessageSelectorComponent,InteractiveMode,runPrintMode,RpcClient,runRpcMode,createExtensionRuntime,discoverAndLoadExtensions,loadProjectContextFiles,DefaultResourceLoader,createAgentSessionServices,createAgentSessionFromServices,AgentSessionRuntime,createAgentSessionRuntime,main};
|