@iaforged/context-code 2.3.3 → 2.3.6
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/context-bootstrap.js +7 -5
- package/dist/src/cli/handlers/auth.js +1 -1
- package/dist/src/cli/handlers/modelList.js +1 -1
- package/dist/src/commands/agent/agent.js +1 -1
- package/dist/src/commands/login/login.js +1 -1
- package/dist/src/commands/profile/profile.js +1 -1
- package/dist/src/commands/provider/index.js +1 -1
- package/dist/src/commands/provider/provider.js +1 -1
- package/dist/src/components/BaseTextInput.js +1 -1
- package/dist/src/components/LogoV2/AnimatedClawd.js +1 -1
- package/dist/src/components/LogoV2/Clawd.js +1 -1
- package/dist/src/components/LogoV2/LogoV2.js +1 -1
- package/dist/src/components/LogoV2/WelcomeV2.js +1 -1
- package/dist/src/components/PromptInput/PromptInputFooterLeftSide.js +1 -1
- package/dist/src/components/SessionTokenFooter.js +1 -1
- package/dist/src/components/Spinner.js +1 -1
- package/dist/src/components/Stats.js +1 -1
- package/dist/src/components/TeleportProgress.js +1 -1
- package/dist/src/components/TextInput.js +1 -1
- package/dist/src/components/design-system/ThemeProvider.js +1 -1
- package/dist/src/components/permissions/AskUserQuestionPermissionRequest/AskUserQuestionPermissionRequest.js +1 -1
- package/dist/src/core/auth/loginCore.js +1 -1
- package/dist/src/core/providers/llmCore.js +1 -1
- package/dist/src/core/providers/providerModelCompatibility.js +1 -1
- package/dist/src/main.js +1 -1
- package/dist/src/query/stopHooks.js +1 -1
- package/dist/src/screens/REPL.js +1 -1
- package/dist/src/services/PromptSuggestion/promptSuggestion.js +1 -1
- package/dist/src/services/analytics/config.js +1 -1
- package/dist/src/services/analytics/datadog.js +1 -1
- package/dist/src/services/api/openai.js +1 -1
- package/dist/src/services/mcp/config.js +1 -1
- package/dist/src/services/orchestration/execution/AgentTaskExecutor.js +1 -1
- package/dist/src/services/tips/tipRegistry.js +1 -1
- package/dist/src/services/toolUseSummary/toolUseSummaryGenerator.js +1 -1
- package/dist/src/tools/BriefTool/UI.js +1 -1
- package/dist/src/utils/computerControlMcp/mcpServer.js +1 -1
- package/dist/src/utils/computerControlMcp/server/.gitattributes +18 -0
- package/dist/src/utils/computerControlMcp/server/Dockerfile +25 -0
- package/dist/src/utils/computerControlMcp/server/LICENSE +21 -0
- package/dist/src/utils/computerControlMcp/server/MANIFEST.in +10 -0
- package/dist/src/utils/computerControlMcp/server/README.md +193 -0
- package/dist/src/utils/computerControlMcp/server/demonstration.gif +0 -0
- package/dist/src/utils/computerControlMcp/server/icon.png +0 -0
- package/dist/src/utils/computerControlMcp/server/pyproject.toml +52 -0
- package/dist/src/utils/computerControlMcp/server/smithery.yaml +13 -0
- package/dist/src/utils/computerControlMcp/server/src/README.md +12 -0
- package/dist/src/utils/computerControlMcp/server/src/computer_control_mcp/FZYTK.TTF +0 -0
- package/dist/src/utils/computerControlMcp/server/src/computer_control_mcp/__init__.py +11 -0
- package/dist/src/utils/computerControlMcp/server/src/computer_control_mcp/__main__.py +21 -0
- package/dist/src/utils/computerControlMcp/server/src/computer_control_mcp/cli.py +128 -0
- package/dist/src/utils/computerControlMcp/server/src/computer_control_mcp/core.py +1008 -0
- package/dist/src/utils/computerControlMcp/server/src/computer_control_mcp/gui.py +126 -0
- package/dist/src/utils/computerControlMcp/server/src/computer_control_mcp/server.py +15 -0
- package/dist/src/utils/computerControlMcp/server/src/computer_control_mcp/test.py +346 -0
- package/dist/src/utils/computerControlMcp/server/src/computer_control_mcp/test_image.png +0 -0
- package/dist/src/utils/computerControlMcp/server/tests/README.md +22 -0
- package/dist/src/utils/computerControlMcp/server/tests/conftest.py +10 -0
- package/dist/src/utils/computerControlMcp/server/tests/rapidocr_test.py +21 -0
- package/dist/src/utils/computerControlMcp/server/tests/run_cli.py +9 -0
- package/dist/src/utils/computerControlMcp/server/tests/run_server.py +15 -0
- package/dist/src/utils/computerControlMcp/server/tests/setup.py +16 -0
- package/dist/src/utils/computerControlMcp/server/tests/test_computer_control.py +161 -0
- package/dist/src/utils/computerControlMcp/server/tests/test_screenshot.py +14 -0
- package/dist/src/utils/computerControlMcp/server/tests/test_wgc_env_var.py +42 -0
- package/dist/src/utils/computerControlMcp/server/tests/test_wgc_screenshot.py +67 -0
- package/dist/src/utils/computerControlMcp/server/uv.lock +4986 -0
- package/dist/src/utils/computerControlMcp/setup.js +1 -1
- package/dist/src/utils/logoV2Utils.js +1 -1
- package/dist/src/utils/model/configs.js +1 -1
- package/dist/src/utils/model/model.js +1 -1
- package/dist/src/utils/model/modelOptions.js +1 -1
- package/dist/src/utils/model/providerBaseUrls.js +1 -1
- package/dist/src/utils/model/providerCatalog.js +1 -1
- package/dist/src/utils/model/providerModels.js +1 -1
- package/dist/src/utils/model/providerProfiles.js +1 -1
- package/dist/src/utils/model/providerProfilesDb.js +1 -1
- package/dist/src/utils/sembleMcp/setup.js +1 -1
- package/dist/src/utils/status.js +1 -1
- package/dist/src/utils/theme.js +1 -1
- package/dist/src/utils/themes/bootstrap.js +1 -1
- package/dist/src/utils/themes/opencodeMapper.js +1 -1
- package/dist/webapp/chunk-OJZNEHPP.js +1 -1
- package/dist/webapp/chunk-VAB2VXFI.js +1 -1
- package/dist/webapp/main-MTQLKGXD.js +1 -1
- package/dist/webapp/ngsw-worker.js +1 -1
- package/dist/webapp/ngsw.json +1 -1
- package/dist/webapp/polyfills-7R4CRVNH.js +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
import{APIUserAbortError as e}from"@anthropic-ai/sdk/error.js";import{randomUUID as t}from"node:crypto";import{checkAndRefreshOpenAIOAuthTokenIfNeeded as n,getGeminiGoogleAuthHeaders as o,getOpenAICompatibleAccessToken as r,getOpenAIAccessToken as s,handleOpenAIOAuth401Error as i}from"../../utils/auth.js";import{getAPIProvider as a,isOpenAICompatibleProvider as u}from"../../utils/model/providers.js";import{getConfiguredProviderBaseUrl as l}from"../../utils/model/providerBaseUrls.js";import{getOpenAIOriginator as c}from"../../constants/oauth.js";import{errorMessage as p}from"../../utils/errors.js";import{logForDebugging as m}from"../../utils/debug.js";import{logError as d}from"../../utils/log.js";import{createAssistantAPIErrorMessage as f,createAssistantMessage as g,createUserMessage as y}from"../../utils/messages.js";import{addToTotalSessionCost as h}from"../../cost-tracker.js";import{calculateUSDCost as _}from"../../utils/modelCost.js";import{toolToAPISchema as A}from"../../utils/api.js";import{jsonStringify as O}from"../../utils/slowOperations.js";function getOpenAIMaxTimeoutRetries(){const e=process.env.CONTEXT_CODE_MAX_RETRIES;if(!e)return 10;const t=Number.parseInt(e,10);return!Number.isFinite(t)||t<0?10:t}function isRecord(e){return"object"==typeof e&&null!==e&&!Array.isArray(e)}function isPlainObject(e){if(!isRecord(e))return!1;const t=Object.getPrototypeOf(e);return t===Object.prototype||null===t}function isJwtToken(e){return 3===e.split(".").length}function getOpenAICompatibleProvider(){const e=a();return u(e)?e:"openai"}function getOpenAICompatibleProviderLabel(e=getOpenAICompatibleProvider()){switch(e){case"openrouter":return"OpenRouter";case"ollama":return"Ollama";case"ollama-cloud":return"Ollama Cloud";case"gemini-api":return"Gemini API";case"gemini-google":return"Gemini Google";case"zai":return"Z.AI";case"nvidia":return"NVIDIA NIM";case"custom-openai":return"Custom OpenAI";default:return"OpenAI"}}function getOpenAIBaseUrl(e=getOpenAICompatibleProvider()){if("openrouter"===e){const e=process.env.OPENROUTER_BASE_URL||l("openrouter")||"https://openrouter.ai/api/v1";return e.endsWith("/v1")?e:e.endsWith("/")?`${e}v1`:`${e}/v1`}if("ollama"===e){const e=process.env.OLLAMA_BASE_URL||l("ollama")||"http://localhost:11434/v1";return e.endsWith("/v1")?e:e.endsWith("/")?`${e}v1`:`${e}/v1`}if("ollama-cloud"===e){const e=process.env.OLLAMA_CLOUD_BASE_URL||process.env.OLLAMA_BASE_URL||l("ollama-cloud")||"http://localhost:11434/v1";return e.endsWith("/v1")?e:e.endsWith("/")?`${e}v1`:`${e}/v1`}if("zai"===e){const e=process.env.ZAI_BASE_URL||l("zai")||"https://api.z.ai/api/coding/paas/v4";return e.endsWith("/")?e.slice(0,-1):e}if("gemini-api"===e||"gemini-google"===e){const t=("gemini-api"===e?process.env.GEMINI_BASE_URL||process.env.GEMINI_API_BASE_URL:process.env.GEMINI_GOOGLE_BASE_URL||process.env.GEMINI_BASE_URL)||l(e)||"https://generativelanguage.googleapis.com/v1beta/openai";return t.endsWith("/")?t.slice(0,-1):t}if("nvidia"===e){const e=process.env.NVIDIA_BASE_URL||l("nvidia")||"https://integrate.api.nvidia.com/v1";return e.endsWith("/")?e.slice(0,-1):e}if("custom-openai"===e){let e=l("custom-openai")||"https://api.openai.com/v1";return e.startsWith("http://chinai.iaforged.com")&&(e=e.replace("http://chinai.iaforged.com","https://chinai.iaforged.com")),e.endsWith("/")?e.slice(0,-1):e}if("openai"!==e&&"custom-openai"!==e){const t=l(e);return t.endsWith("/")?t.slice(0,-1):t}const t=process.env.OPENAI_API_BASE_URL||process.env.OPENAI_BASE_URL||"https://api.openai.com/v1";return t.endsWith("/v1")?t:t.endsWith("/")?`${t}v1`:`${t}/v1`}async function getOpenAIRequestHeaders(e=getOpenAICompatibleProvider()){return"gemini-google"===e?o():function(e=getOpenAICompatibleProvider()){const t=r(e);if(isLocalOllamaProviderHost(e,getOpenAIBaseUrl(e)))return{"Content-Type":"application/json"};if(!t)throw new Error(`${getOpenAICompatibleProviderLabel(e)} is selected but no credentials were found.`);return"custom-openai"===e?{Authorization:`Bearer ${t}`,"X-API-Key":t,"api-key":t,"Content-Type":"application/json"}:{Authorization:`Bearer ${t}`,"Content-Type":"application/json"}}(e)}function isLocalOllamaProviderHost(e,t=getOpenAIBaseUrl(e)){return("ollama"===e||"ollama-cloud"===e)&&(t.includes("localhost")||t.includes("127.0.0.1"))}function getOpenAIAccessTokenOrThrow(e=getOpenAICompatibleProvider()){if(isLocalOllamaProviderHost(e))return"ollama";if("gemini-google"===e)return r(e)||"google-application-default-credentials";const t=r(e);if(!t)throw new Error(`${getOpenAICompatibleProviderLabel(e)} is selected but no credentials were found.`);return t}async function maybeRefreshOpenAICompatibleAuth(e=getOpenAICompatibleProvider()){"openai"===e&&await n()}async function maybeRecoverOpenAICompatible401(e,t=getOpenAICompatibleProvider()){if("openai"!==t)return null;if(!await i(e))return null;const n=s();return n&&n!==e?n:null}function toInputText(e){return{type:"input_text",text:e}}function toOutputText(e){return{type:"output_text",text:e}}function normalizeBlocksForRole(e,t){return"assistant"!==t?e:e.map(e=>"input_text"===e.type?toOutputText(e.text):e)}function stringifyBlockContent(e){return"string"==typeof e?e:Array.isArray(e)?e.map(e=>"string"==typeof e?e:e&&"object"==typeof e&&"type"in e&&"text"===e.type&&"text"in e&&"string"==typeof e.text?e.text:O(e)).join("\n"):null==e?"":O(e)}function normalizeResponseContent(e){return Array.isArray(e)?e:null==e?[]:[e]}function blockToOpenAIContentBlocks(e){if(!isRecord(e))return null;if("text"===e.type&&"string"==typeof e.text)return[toInputText(e.text)];if("image"===e.type){const t=isRecord(e.source)?e.source:null,n=t?function(e){if("base64"===e.type){const t=e.media_type,n=e.data;return"string"!=typeof t||"string"!=typeof n?null:{type:"input_image",image_url:`data:${t};base64,${n}`}}return"url"===e.type&&"string"==typeof e.url?{type:"input_image",image_url:e.url}:"file"===e.type&&"string"==typeof e.file_id?{type:"input_image",file_id:e.file_id}:null}(t):null;return n?[n]:null}if("document"===e.type){const t=isRecord(e.source)?e.source:null;if(!t)return null;const n=function(e,t){return"file"===e.type&&"string"==typeof e.file_id?{type:"input_file",file_id:e.file_id}:"base64"===e.type&&"string"==typeof e.data?"string"!=typeof e.media_type?null:{type:"input_file",file_data:e.data,..."string"==typeof t&&t?{filename:t}:{}}:"url"===e.type&&"string"==typeof e.url?{type:"input_file",file_url:e.url,..."string"==typeof t&&t?{filename:t}:{}}:"text"===e.type&&"string"==typeof e.data?toInputText(e.data):null}(t,"string"==typeof e.title?e.title:void 0);if(n)return[n];if("content"===t.type&&"string"==typeof t.content)return[toInputText(t.content)];if("content"===t.type&&Array.isArray(t.content)){const e=[];for(const n of t.content){const t=blockToOpenAIContentBlocks(n);t&&e.push(...t)}return e.length>0?e:null}return null}if("search_result"===e.type&&Array.isArray(e.content)){const t=[];"string"==typeof e.title&&e.title.trim()&&t.push(e.title.trim()),"string"==typeof e.source&&e.source.trim()&&t.push(e.source.trim());for(const n of e.content)if(n&&"object"==typeof n&&"text"in n){const e=n.text;"string"==typeof e&&e.trim()&&t.push(e.trim())}return[toInputText(t.join("\n\n"))]}if("container_upload"===e.type&&"string"==typeof e.file_id)return[{type:"input_file",file_id:e.file_id}];if(("bash_code_execution_output"===e.type||"mcp_tool_result"===e.type||"code_execution_tool_result"===e.type||"web_search_tool_result"===e.type||"web_fetch_tool_result"===e.type||"text_editor_code_execution_tool_result"===e.type||"tool_search_tool_result"===e.type)&&"content"in e){const t=e.content;if("string"==typeof t)return[toInputText(t)];if(Array.isArray(t)){const e=[];for(const n of t){const t=blockToOpenAIContentBlocks(n);t&&e.push(...t)}return e.length>0?e:null}}if("content"in e&&("string"==typeof e.content||Array.isArray(e.content))){const t=e.content;if("string"==typeof t)return[toInputText(t)];const n=[];for(const e of t){const t=blockToOpenAIContentBlocks(e);t&&n.push(...t)}return n.length>0?n:null}return"data"in e&&"string"==typeof e.data?[toInputText(e.data)]:null}function toolResultContentToOpenAIOutput(e){if("string"==typeof e)return e;if(!Array.isArray(e))return stringifyBlockContent(e);const t=[];for(const n of e){const e=blockToOpenAIContentBlocks(n);if(e&&e.length>0){t.push(...e);continue}const o=stringifyBlockContent(n).trim();o&&t.push(toInputText(o))}return 0===t.length?"":t.every(e=>"input_text"===e.type)?t.map(e=>e.text).join("\n\n"):t}function messageToOpenAIInput(e){if(!e.message||"user"!==e.type&&"assistant"!==e.type)return[];const t=Array.isArray(e.message.content)?e.message.content:[{type:"text",text:String(e.message.content??"")}],n="assistant"===e.type?"assistant":"user",o=[],r=[],flushMessage=()=>{0!==r.length&&(o.push({type:"message",role:n,content:[...r]}),r.length=0)};for(const s of t){if("assistant"===e.type&&"tool_use"===s.type&&"string"==typeof s.id&&"string"==typeof s.name){flushMessage(),o.push({type:"function_call",call_id:s.id,name:s.name,arguments:O(s.input??{})});continue}if("user"===e.type&&"tool_result"===s.type&&"string"==typeof s.tool_use_id){flushMessage(),o.push({type:"function_call_output",call_id:s.tool_use_id,output:toolResultContentToOpenAIOutput(s.content)});continue}if("thinking"===s.type||"redacted_thinking"===s.type)continue;const t=blockToOpenAIContentBlocks(s);t&&t.length>0?r.push(...normalizeBlocksForRole(t,n)):r.push(..."assistant"===n?[toOutputText(stringifyBlockContent(s))]:[toInputText(stringifyBlockContent(s))])}return flushMessage(),o}async function readOpenAIResponseBody(e){const t=await e.text();if(!t.trim())return{};const n=t.trim();if(n.startsWith("data:")||n.startsWith("event:"))return function(e){const t=[];for(const n of e.split(/\r?\n\r?\n/)){const e=n.split(/\r?\n/).map(e=>e.trim()).filter(Boolean);if(0===e.length)continue;const o=e.filter(e=>e.startsWith("data:")).map(e=>e.slice(5).trim());if(0===o.length)continue;const r=o.join("\n").trim();if(r&&"[DONE]"!==r)try{const e=JSON.parse(r);isRecord(e)&&t.push(e)}catch{}}let n=null,o=null;const r=[];let s="";for(const i of t){const t="string"==typeof i.type?i.type:"";"response.completed"===t&&isRecord(i.response)?n={...i.response,raw_error_text:e}:"error"!==t?"response.output_item.done"===t&&isRecord(i.item)?r.push(i.item):"response.output_text.delta"!==t||"string"!=typeof i.delta?"response.output_text.done"===t&&"string"==typeof i.text&&(s=i.text):s+=i.delta:"string"==typeof i.message&&i.message.trim()?o=i.message:isRecord(i.error)&&"string"==typeof i.error.message&&(o=i.error.message)}if(n)return(!n.output||0===n.output.length)&&r.length>0&&(n.output=r),!n.output_text&&s&&(n.output_text=s),!n.error&&o&&(n.error={message:o}),n;if(r.length>0||s||o)return{output:r.length>0?r:void 0,output_text:s||void 0,error:o?{message:o}:void 0,raw_error_text:e};return{error:{message:e},raw_error_text:e}}(t);try{const e=JSON.parse(t);return isRecord(e)&&"string"==typeof e.error?{...e,error:{message:e.error},raw_error_text:t}:isRecord(e)?{...e,raw_error_text:t}:{error:{message:t},raw_error_text:t}}catch{return{error:{message:t},raw_error_text:t}}}function buildOpenAIErrorMessage(e){const t=e.data.error?.message?.trim()||e.data.raw_error_text?.trim()||`OpenAI request failed (${e.status} ${e.statusText})`,n=/requires a subscription|upgrade for access/i.test(t)?`El modelo ${e.model??"seleccionado"} requiere una suscripcion de Ollama Cloud. Cambia a otro modelo en /model o actualiza tu plan de Ollama.`:t,o=e.data.raw_error_text?.trim(),r=o&&o!==t&&o!==n?o.replace(/\s+/g," ").slice(0,400):null;return r?`${n} [model=${e.model??"unknown"} endpoint=${e.url}] ${r}`:`${n} [model=${e.model??"unknown"} endpoint=${e.url}]`}function blockToChatContentPart(e){if("text"===e.type&&"string"==typeof e.text)return{type:"text",text:e.text};if("image"===e.type){const t=isRecord(e.source)?e.source:null;if(!t)return null;if("base64"===t.type&&"string"==typeof t.data&&"string"==typeof t.media_type)return{type:"image_url",image_url:{url:`data:${t.media_type};base64,${t.data}`}};if("url"===t.type&&"string"==typeof t.url)return{type:"image_url",image_url:{url:t.url}}}const t=stringifyBlockContent(e);return t?{type:"text",text:t}:null}function toolResultToString(e){return"string"==typeof e?e:Array.isArray(e)?e.map(e=>"string"==typeof e?e:isRecord(e)&&"string"==typeof e.text?e.text:stringifyBlockContent(e)).filter(Boolean).join("\n"):stringifyBlockContent(e)}function messageToChatMessages(e){if(!e.message||"user"!==e.type&&"assistant"!==e.type)return[];const t=e.message.content,n=Array.isArray(t)?t:[{type:"text",text:String(t??"")}];if("assistant"===e.type){const e=[],t=[];for(const o of n)"thinking"!==o.type&&"redacted_thinking"!==o.type&&("tool_use"===o.type&&"string"==typeof o.id&&"string"==typeof o.name?e.push({id:o.id,type:"function",function:{name:o.name,arguments:O(o.input??{})}}):"text"===o.type&&"string"==typeof o.text&&o.text.trim()&&t.push(o.text));const o={role:"assistant",content:t.join("\n")};return e.length>0&&(o.tool_calls=e),[o]}const o=[],r=[];for(const e of n)if("tool_result"===e.type&&"string"==typeof e.tool_use_id)o.push({role:"tool",tool_call_id:e.tool_use_id,content:toolResultToString(e.content)});else{const t=blockToChatContentPart(e);t&&r.push(t)}const s=[...o];if(r.length>0){const e=r.every(e=>"text"===e.type);s.push({role:"user",content:e?r.map(e=>e.text).join("\n"):r})}return s}function parseChatCompletionResponse(e){const t=[];for(const n of e.choices??[]){const e=n.message;if(e){"string"==typeof e.content&&e.content.trim()&&t.push({type:"text",text:e.content});for(const n of e.tool_calls??[])t.push({type:"tool_use",id:n.id,name:n.function?.name??"tool",input:parseFunctionCallArguments(n.function?.arguments)})}}return{content:t}}function getChatUsage(e){if("number"==typeof e.usage?.prompt_tokens||"number"==typeof e.usage?.completion_tokens)return{input_tokens:e.usage?.prompt_tokens??0,output_tokens:e.usage?.completion_tokens??0}}function buildChatToolChoice(e){if(!e.toolChoice)return"auto";switch(e.toolChoice.type){case"auto":default:return"auto";case"any":return"required";case"none":return"none";case"tool":return"string"==typeof e.toolChoice.name?{type:"function",function:{name:e.toolChoice.name}}:"auto"}}function chatContentToGeminiParts(e){return"string"==typeof e?e?[{text:e}]:[]:Array.isArray(e)?e.map(e=>"text"===e.type?e.text?{text:e.text}:null:"image_url"===e.type?{text:`[Image input: ${e.image_url.url}]`}:null).filter(e=>null!==e):[]}function buildGeminiContents(e){const t=new Map,n=[];for(const o of e){if("system"===o.role)continue;if("assistant"===o.role){const e=chatContentToGeminiParts(o.content);for(const n of o.tool_calls??[]){t.set(n.id,n.function.name);const o=parseFunctionCallArguments(n.function.arguments);e.push({functionCall:{name:n.function.name,args:isPlainObject(o)?o:{raw:o}}})}e.length>0&&n.push({role:"model",parts:e});continue}if("tool"===o.role){const e=o.tool_call_id?t.get(o.tool_call_id)??"tool":"tool";n.push({role:"function",parts:[{functionResponse:{name:e,response:{result:o.content??""}}}]});continue}const e=chatContentToGeminiParts(o.content);e.length>0&&n.push({role:"user",parts:e})}return n.length>0?n:[{role:"user",parts:[{text:""}]}]}function getGeminiEnumType(e){switch(typeof e){case"string":return"string";case"number":return Number.isInteger(e)?"integer":"number";case"boolean":return"boolean";default:return}}function sanitizeGeminiSchema(e){if(!isRecord(e))return{type:"object",properties:{}};const t=Array.isArray(e.anyOf)?e.anyOf:Array.isArray(e.any_of)?e.any_of:null,n=Array.isArray(e.oneOf)?e.oneOf:Array.isArray(e.one_of)?e.one_of:null;if(t||n){const e=function(e){const t=[];let n,o=!1;for(const r of e){if(!isRecord(r))return null;if("null"===r.type){o=!0;continue}const e=void 0!==r.const?[r.const]:Array.isArray(r.enum)?r.enum:null;if(!e)return null;for(const o of e){const e=getGeminiEnumType(o);if(!e)return null;if(n&&n!==e)return null;n=e,t.push(o)}}return n&&0!==t.length?{type:n,enum:Array.from(new Set(t)),...o?{nullable:!0}:{}}:null}(t??n??[]);return e||{anyOf:(t??n??[]).map(sanitizeGeminiSchema)}}const o={},r=e.type;if(Array.isArray(r)){const e=r.find(e=>"null"!==e);"string"==typeof e&&(o.type=e),r.includes("null")&&(o.nullable=!0)}else"string"==typeof r&&(o.type=r);for(const t of["title","description","format","nullable","minimum","maximum","minItems","maxItems","minLength","maxLength","pattern"])void 0!==e[t]&&(o[t]=e[t]);if(Array.isArray(e.enum)?o.enum=e.enum:void 0!==e.const&&(o.enum=[e.const]),!o.type&&Array.isArray(o.enum)&&o.enum.length>0&&(o.type=getGeminiEnumType(o.enum[0])),void 0!==e.exclusiveMinimum&&void 0===o.minimum&&(o.minimum="number"==typeof e.exclusiveMinimum?e.exclusiveMinimum:e.minimum),void 0!==e.exclusiveMaximum&&void 0===o.maximum&&(o.maximum="number"==typeof e.exclusiveMaximum?e.exclusiveMaximum:e.maximum),isRecord(e.items)?o.items=sanitizeGeminiSchema(e.items):Array.isArray(e.items)&&e.items.length>0&&(o.items=sanitizeGeminiSchema(e.items[0])),isRecord(e.properties)){const t={};for(const[n,o]of Object.entries(e.properties))t[n]=sanitizeGeminiSchema(o);o.properties=t}return Array.isArray(e.required)&&(o.required=e.required.filter(e=>"string"==typeof e)),o.type||(o.type=o.properties?"object":o.items?"array":"object"),"object"!==o.type||o.properties||(o.properties={}),o}async function postGeminiCodeAssist(e,t,n,o){const r=await fetch(`https://cloudcode-pa.googleapis.com/v1internal:${e}`,{method:"POST",headers:t,body:O(n),signal:o});return{response:r,data:await readOpenAIResponseBody(r)}}function getGeminiCodeAssistMetadata(e){return{ideType:"IDE_UNSPECIFIED",platform:"PLATFORM_UNSPECIFIED",pluginType:"GEMINI",...e?{duetProject:e}:{}}}async function resolveGeminiCodeAssistProject(e,t){const n=process.env.GEMINI_GOOGLE_PROJECT_ID?.trim()||void 0,o={...n?{cloudaicompanionProject:n}:{},metadata:getGeminiCodeAssistMetadata(n)},{response:r,data:s}=await postGeminiCodeAssist("loadCodeAssist",e,o,t);if(!r.ok)return n;if("string"==typeof s.cloudaicompanionProject)return s.cloudaicompanionProject;if(n)return n;const i=Array.isArray(s.allowedTiers)?s.allowedTiers.filter(isRecord):[],a=i.find(e=>!0===e.isDefault)??i[0],u="string"==typeof a?.id?a.id:void 0;if(!u)return;const{response:l,data:c}=await postGeminiCodeAssist("onboardUser",e,{tierId:u,metadata:getGeminiCodeAssistMetadata()},t);if(!l.ok)return;const p=isRecord(c.response)?c.response:c,m=isRecord(p.cloudaicompanionProject)?p.cloudaicompanionProject:null;return"string"==typeof m?.id?m.id:void 0}async function createGeminiGoogleChatCompletionResponse(e){const{model:n,chatMessages:r,chatTools:s,toolChoice:i,signal:a,maxOutputTokens:u,temperature:l}=e,c=await o(),p=await resolveGeminiCodeAssistProject(c,a),d={};u&&(d.maxOutputTokens=u),void 0!==l&&(d.temperature=l);const f={contents:buildGeminiContents(r),session_id:t()},g=r.filter(e=>"system"===e.role&&"string"==typeof e.content).map(e=>e.content).join("\n\n");g&&(f.systemInstruction={role:"user",parts:[{text:g}]});const y=function(e){if(0!==e.length)return[{functionDeclarations:e.map(e=>({name:e.function.name,description:e.function.description,parameters:sanitizeGeminiSchema(e.function.parameters??{type:"object",properties:{}})}))}]}(s);y&&(f.tools=y);const h=function(e){if("auto"!==e)return"none"===e?{functionCallingConfig:{mode:"NONE"}}:"required"===e?{functionCallingConfig:{mode:"ANY"}}:{functionCallingConfig:{mode:"ANY",allowedFunctionNames:[e.function.name]}}}(i);h&&(f.toolConfig=h),Object.keys(d).length>0&&(f.generationConfig=d);let _=n;const A=n.toLowerCase();_=A.includes("flash")?"gemini-3-flash-preview":(A.includes("pro"),"gemini-3.1-pro-preview");const C={model:_,...p?{project:p}:{},user_prompt_id:t(),request:f},b="https://cloudcode-pa.googleapis.com/v1internal:generateContent";m(`[Gemini Google] codeassist generateContent request model=${_} (original=${n}) messages=${r.length} tools=${s.length} endpoint=${b}`);const{response:x,data:I}=await postGeminiCodeAssist("generateContent",c,C,a);if(!x.ok)throw m(`[Gemini Google] codeassist generateContent error status=${x.status} model=${n} endpoint=${b} body=${(I.error?.message??"").replace(/\s+/g," ").slice(0,500)}`,{level:"error"}),new Error(buildOpenAIErrorMessage({status:x.status,statusText:x.statusText,url:b,model:n,data:I}));return function(e){const n=e.response?.candidates??[];return{id:e.traceId,choices:n.map(e=>{const n=[],o=[];for(const r of e.content?.parts??[])"text"in r&&"string"==typeof r.text&&n.push(r.text),"functionCall"in r&&r.functionCall?.name&&o.push({id:`call_${t().replace(/-/g,"")}`,type:"function",function:{name:r.functionCall.name,arguments:O(r.functionCall.args??{})}});return{message:{content:n.join("")||null,tool_calls:o.length>0?o:void 0},finish_reason:e.finishReason}}),usage:{prompt_tokens:e.response?.usageMetadata?.promptTokenCount,completion_tokens:e.response?.usageMetadata?.candidatesTokenCount}}}(I)}async function createChatCompletionResponse({messages:e,systemPrompt:t,tools:n,signal:o,options:s}){const i=getOpenAICompatibleProvider();await maybeRefreshOpenAICompatibleAuth(i);const a=t.join("\n\n"),u=[...a?[{role:"system",content:a}]:[],...e.flatMap(messageToChatMessages)],l=function(e){return e.map(e=>({type:"function",function:{name:e.name,description:e.description,parameters:e.parameters,...e.strict?{strict:!0}:{}}}))}(await buildOpenAITools(n,s)),c={model:s.model,messages:u,stream:"custom-openai"!==i,..."custom-openai"!==i?{stream_options:{include_usage:!0}}:{}};if(l.length>0&&(c.tools=l,c.tool_choice=buildChatToolChoice(s)),shouldDisableParallelToolCalls(s)&&(c.parallel_tool_calls=!1),s.maxOutputTokensOverride&&(c.max_tokens=s.maxOutputTokensOverride),void 0!==s.temperatureOverride&&(c.temperature=s.temperatureOverride),s.effortValue&&(c.reasoning_effort=s.effortValue),"gemini-google"===i)return createGeminiGoogleChatCompletionResponse({model:String(s.model),chatMessages:u,chatTools:l,toolChoice:buildChatToolChoice(s),signal:o,maxOutputTokens:s.maxOutputTokensOverride,temperature:s.temperatureOverride});const p=getOpenAIMaxTimeoutRetries(),sendRequest=async(e=r(i)??"",t=0)=>{const n=`${getOpenAIBaseUrl(i)}/chat/completions`;m(`[${getOpenAICompatibleProviderLabel(i)}] chat.completions request model=${s.model} messages=${u.length} tools=${l.length} endpoint=${n}${t>0?` (retry ${t})`:""}`);const a=12e4,d=new AbortController,f=setTimeout(()=>d.abort(),a),onAbort=()=>d.abort();o?.addEventListener("abort",onAbort);try{if("custom-openai"===i)try{const e=require("fs"),t=`--- NUEVA SOLICITUD A CHINAI ---\nFecha: ${(new Date).toISOString()}\nURL: ${n}\nHeaders: ${JSON.stringify(await getOpenAIRequestHeaders(i),null,2)}\nBody: ${JSON.stringify(c,null,2)}\n\n`;e.writeFileSync("d:/Documents/GitHub/Claude/claude-code_V1/Context_Code_V1/chat-debug.txt",t)}catch(e){}m(`[${getOpenAICompatibleProviderLabel(i)}] chat.completions REQUEST BODY: ${O(c).slice(0,3e3)}`);const o=await fetch(n,{method:"POST",headers:await getOpenAIRequestHeaders(i),body:O(c),signal:d.signal}),r=await o.text();if("custom-openai"===i)try{const e=require("fs"),t=`--- RESPUESTA DE CHINAI ---\nStatus: ${o.status} ${o.statusText}\nBody: ${r}\n\n`;e.appendFileSync("d:/Documents/GitHub/Claude/claude-code_V1/Context_Code_V1/chat-debug.txt",t)}catch(e){}let a;m(`[${getOpenAICompatibleProviderLabel(i)}] chat.completions RAW response status=${o.status} bodyLength=${r.length} bodyPreview=${r.slice(0,3e3)}`);const u=r.trim();if(u.startsWith("data:")||u.startsWith("event:")){const e=function(e){const t=[];for(const n of e.split(/\r?\n\r?\n/)){const e=n.split(/\r?\n/).map(e=>e.trim()).filter(e=>e.startsWith("data:")).map(e=>e.slice(5).trim());if(0===e.length)continue;const o=e.join("\n").trim();if(o&&"[DONE]"!==o)try{const e=JSON.parse(o);isRecord(e)&&t.push(e)}catch{}}if(0===t.length)return null;if(!t.some(e=>{const t=e.object;return"string"==typeof t&&t.startsWith("chat.completion")}))return null;let n,o,r,s,i="",a="";const u=new Map;for(const e of t){if(n||"string"!=typeof e.id||(n=e.id),isRecord(e.usage)){const t=e.usage;"number"==typeof t.prompt_tokens&&(r=t.prompt_tokens),"number"==typeof t.completion_tokens&&(s=t.completion_tokens)}const t=Array.isArray(e.choices)?e.choices:[];for(const e of t){if(!isRecord(e))continue;"string"==typeof e.finish_reason&&(o=e.finish_reason);const t=isRecord(e.delta)?e.delta:null,n=isRecord(e.message)?e.message:null,r=t??n;if(!r)continue;"string"==typeof r.content&&(i+=r.content),"string"==typeof r.reasoning_content&&(a+=r.reasoning_content);const s=Array.isArray(r.tool_calls)?r.tool_calls:[];for(const e of s){if(!isRecord(e))continue;const t="number"==typeof e.index?e.index:0,n=u.get(t)??{arguments:""};"string"==typeof e.id&&(n.id=e.id);const o=isRecord(e.function)?e.function:null;o&&("string"==typeof o.name&&(n.name=o.name),"string"==typeof o.arguments&&(n.arguments+=o.arguments)),u.set(t,n)}}}const l=i||(a?a.trim():""),c=[];for(const[,e]of[...u.entries()].sort((e,t)=>e[0]-t[0]))e.name&&c.push({id:e.id??`call_${c.length}`,type:"function",function:{name:e.name,arguments:e.arguments}});return{id:n,choices:[{message:{content:l||null,...c.length>0?{tool_calls:c}:{}},finish_reason:o}],usage:{prompt_tokens:r,completion_tokens:s}}}(r);if(e)a=e;else try{a=JSON.parse(r)}catch{a={error:{message:r.slice(0,500)}}}}else if(u)try{a=JSON.parse(r)}catch{a={error:{message:r.slice(0,500)}}}else a={};if(504===o.status&&t<1)return m(`[${getOpenAICompatibleProviderLabel(i)}] 504 Gateway Timeout, reintentando...`,{level:"warn"}),sendRequest(e,t+1);if(401===o.status){const n=await maybeRecoverOpenAICompatible401(e,i);if(n)return sendRequest(n,t)}if(!o.ok)throw m(`[${getOpenAICompatibleProviderLabel(i)}] chat.completions error status=${o.status} model=${s.model} endpoint=${n} body=${(a.error?.message??"").replace(/\s+/g," ").slice(0,500)}`,{level:"error"}),new Error(buildOpenAIErrorMessage({status:o.status,statusText:o.statusText,url:n,model:String(s.model),data:a}));return a}catch(n){if(n instanceof Error&&"AbortError"===n.name&&!o?.aborted){if(t<p){const n=1e3*Math.pow(2,t);return m(`[${getOpenAICompatibleProviderLabel(i)}] timeout local tras 120000ms, reintentando en ${n}ms (intento ${t+1}/${p})`,{level:"warn"}),await new Promise(e=>setTimeout(e,n)),sendRequest(e,t+1)}throw new Error("La solicitud expiró tras 120s. El servidor tardó demasiado en responder.")}throw n}finally{clearTimeout(f),o?.removeEventListener("abort",onAbort)}};return getOpenAIAccessTokenOrThrow(i),sendRequest()}async function buildOpenAITools(e,t){return(await Promise.all(e.map(n=>A(n,{getToolPermissionContext:t.getToolPermissionContext,tools:e,agents:t.agents,allowedAgentTypes:t.allowedAgentTypes,model:t.model})))).map(e=>({type:"function",name:e.name,description:e.description,parameters:e.input_schema,...e.strict?{strict:!0}:{}}))}function buildToolChoice(e){if(!e.toolChoice)return"auto";switch(e.toolChoice.type){case"auto":default:return"auto";case"any":return"required";case"none":return"none";case"tool":return"string"==typeof e.toolChoice.name?{type:"function",name:e.toolChoice.name}:"auto"}}function shouldDisableParallelToolCalls(e){const t=e.toolChoice;return Boolean(t&&"disable_parallel_tool_use"in t&&!0===t.disable_parallel_tool_use)}function parseFunctionCallArguments(e){if(isPlainObject(e))return e;if("string"!=typeof e)return null==e?{}:{raw:e};try{const t=JSON.parse(e);return isPlainObject(t)?t:{raw:t}}catch{return{raw:e}}}function parseOutputItems(e){const t=[];for(const n of e.output??[])if(n&&"object"==typeof n){if("function_call"===n.type){const e=parseFunctionCallArguments(n.arguments);t.push({type:"tool_use",id:String(n.call_id??n.id??""),name:String(n.name??"tool"),input:e});continue}if("message"===n.type)for(const e of normalizeResponseContent(n.content)){if("string"==typeof e){t.push({type:"text",text:e});continue}if(!e||"object"!=typeof e||!("type"in e))continue;const n=String(e.type??""),o="string"==typeof e.text?e.text??"":"string"==typeof e.refusal?e.refusal??"":"";"output_text"!==n&&"text"!==n&&"refusal"!==n||!o||t.push({type:"text",text:o})}}return 0===t.length&&"string"==typeof e.output_text&&t.push({type:"text",text:e.output_text}),{content:t}}function getUsage(e){if("number"==typeof e.usage?.input_tokens||"number"==typeof e.usage?.output_tokens)return{input_tokens:e.usage?.input_tokens??0,output_tokens:e.usage?.output_tokens??0}}function sideQueryMessageToOpenAIInput(e){const t=Array.isArray(e.content)?e.content.filter(e=>"text"===e?.type&&"string"==typeof e.text).map(e=>toInputText(e.text)):[toInputText(String(e.content??""))];return[{type:"message",role:e.role,content:t.length>0?t:[toInputText("")]}]}function sideQueryToolToOpenAITool(e){return{type:"function",name:e.name,description:e.description,parameters:e.input_schema??{type:"object",properties:{}}}}function buildSideQueryToolChoice(e){return e&&"auto"!==e?"none"===e||"none"===e.type?"none":"any"===e.type?"required":"auto"===e.type?"auto":"string"==typeof e.name&&e.name?{type:"function",name:e.name}:"auto":"auto"}function sideQueryMessageToChatMessage(e){const t=Array.isArray(e.content)?e.content.filter(e=>"text"===e?.type&&"string"==typeof e.text).map(e=>e.text).join("\n"):String(e.content??"");return{role:e.role,content:t}}function sideQueryToolToChatTool(e){return{type:"function",function:{name:e.name,description:e.description,parameters:e.input_schema??{type:"object",properties:{}}}}}export async function queryOpenAISideQuery({model:e,systemPrompt:t,messages:n,tools:o,toolChoice:s,outputFormat:i,signal:a,maxOutputTokens:u,temperature:l}){const c=getOpenAICompatibleProvider();await maybeRefreshOpenAICompatibleAuth(c);const p=getOpenAIBaseUrl(c),d=r(c);if(!("openai"===c&&d&&isJwtToken(d))){const r=[...t?[{role:"system",content:t}]:[],...n.map(sideQueryMessageToChatMessage)],d={model:e,messages:r,stream:!1},f=o?.map(sideQueryToolToChatTool)??[],g=function(e){const t=buildSideQueryToolChoice(e);return"auto"===t||"none"===t?t:"required"===t?"required":{type:"function",function:{name:t.name}}}(s);if(f.length>0&&(d.tools=f,d.tool_choice=g),"json_schema"===i?.type&&(d.response_format={type:"json_schema",json_schema:{name:"side_query_output",strict:!0,schema:i.schema}}),u&&(d.max_tokens=u),void 0!==l&&(d.temperature=l),"gemini-google"===c){const t=await createGeminiGoogleChatCompletionResponse({model:e,chatMessages:r,chatTools:f,toolChoice:g,signal:a,maxOutputTokens:u,temperature:l});return{id:t.id,content:parseChatCompletionResponse(t).content,usage:getChatUsage(t)}}const y=`${p}/chat/completions`,h=await getOpenAIRequestHeaders(c);if("custom-openai"===c)try{const e=require("fs"),t=`--- NUEVA SOLICITUD DE VALIDACION DE MODELO A CHINAI ---\nFecha: ${(new Date).toISOString()}\nURL: ${y}\nHeaders: ${JSON.stringify(h,null,2)}\nBody: ${JSON.stringify(d,null,2)}\n\n`;e.appendFileSync("d:/Documents/GitHub/Claude/claude-code_V1/Context_Code_V1/chat-debug.txt",t)}catch(e){}const _=await fetch(y,{method:"POST",headers:h,body:O(d),signal:a});if("custom-openai"===c)try{const e=_.clone(),t=await e.text(),n=require("fs"),o=`--- RESPUESTA DE VALIDACION DE MODELO DE CHINAI ---\nStatus: ${_.status} ${_.statusText}\nBody: ${t}\n\n`;n.appendFileSync("d:/Documents/GitHub/Claude/claude-code_V1/Context_Code_V1/chat-debug.txt",o)}catch(e){}const A=await readOpenAIResponseBody(_);if(!_.ok)throw m(`[${getOpenAICompatibleProviderLabel(c)}] sideQuery chat.completions error status=${_.status} model=${e} endpoint=${y} body=${(A.error?.message??"").replace(/\s+/g," ").slice(0,500)}`,{level:"error"}),new Error(buildOpenAIErrorMessage({status:_.status,statusText:_.statusText,url:y,model:e,data:A}));return{id:A.id,content:parseChatCompletionResponse(A).content,usage:getChatUsage(A)}}const f={model:e,input:n.flatMap(sideQueryMessageToOpenAIInput),instructions:t,stream:!1,store:!1};o&&o.length>0&&(f.tools=o.map(sideQueryToolToOpenAITool),f.tool_choice=buildSideQueryToolChoice(s)),"json_schema"===i?.type&&(f.text={format:{type:"json_schema",name:"side_query_output",strict:!0,schema:i.schema}}),u&&(f.max_output_tokens=u),void 0!==l&&(f.temperature=l);const g=`${p}/responses`,y=await fetch(g,{method:"POST",headers:await getOpenAIRequestHeaders(c),body:O(f),signal:a}),h=await readOpenAIResponseBody(y);if(!y.ok)throw m(`[${getOpenAICompatibleProviderLabel(c)}] sideQuery error status=${y.status} model=${e} endpoint=${p}/responses body=${(h.raw_error_text??"").replace(/\s+/g," ").slice(0,500)}`,{level:"error"}),new Error(buildOpenAIErrorMessage({status:y.status,statusText:y.statusText,url:`${p}/responses`,model:e,data:h}));return{id:h.id,content:parseOutputItems(h).content,usage:getUsage(h)}}async function createOpenAIResponse(e){const{messages:t,systemPrompt:n,tools:o,signal:r,options:s}=e,i=getOpenAICompatibleProvider();await maybeRefreshOpenAICompatibleAuth(i);const a=getOpenAIAccessTokenOrThrow(i),u="openai"===i&&isJwtToken(a);if(!u){const t=await createChatCompletionResponse(e);return{id:t.id,output:t.choices?.flatMap(e=>{const t=[];if(e.message?.content&&t.push({type:"message",role:"assistant",content:[e.message.content]}),e.message?.tool_calls)for(const n of e.message.tool_calls)t.push({type:"function_call",call_id:n.id,name:n.function.name,arguments:n.function.arguments});return t})??[],usage:{input_tokens:t.usage?.prompt_tokens,output_tokens:t.usage?.completion_tokens}}}const l=t.flatMap(messageToOpenAIInput),p=await buildOpenAITools(o,s),d={model:s.model,input:l,instructions:n.join("\n\n"),tools:p,tool_choice:buildToolChoice(s),stream:!1,store:!1};shouldDisableParallelToolCalls(s)&&(d.parallel_tool_calls=!1),s.maxOutputTokensOverride&&(d.max_output_tokens=s.maxOutputTokensOverride),void 0!==s.temperatureOverride&&(d.temperature=s.temperatureOverride),s.effortValue&&(d.reasoning={effort:s.effortValue});const f=getOpenAIMaxTimeoutRetries(),sendRequest=async(e,t=0)=>{const n=u?{...d,stream:!0}:d;let o,a;if(u){const t=function(e){try{const t=JSON.parse(atob(e.split(".")[1])),n=t?.["https://api.openai.com/auth"]?.chatgpt_account_id;if(!n)throw new Error("No account ID in token");return n}catch{throw new Error("Failed to extract chatgpt-account-id from OAuth token")}}(e);o=function(){const e=(process.env.OPENAI_OAUTH_BASE_URL||"https://chatgpt.com/backend-api").replace(/\/+$/,"");return e.endsWith("/codex/responses")?e:e.endsWith("/codex")?`${e}/responses`:`${e}/codex/responses`}(),a={Authorization:`Bearer ${e}`,"chatgpt-account-id":t,"OpenAI-Beta":"responses=experimental",originator:c(),"content-type":"application/json",accept:"application/json"}}else o=`${getOpenAIBaseUrl(i)}/responses`,a={Authorization:`Bearer ${e}`,"Content-Type":"application/json"};const l=12e4,p=new AbortController,g=setTimeout(()=>p.abort(),l),onAbort=()=>p.abort();r?.addEventListener("abort",onAbort);try{const r=await fetch(o,{method:"POST",headers:a,body:O(n),signal:p.signal}),l=await readOpenAIResponseBody(r);if(504===r.status&&t<1)return m(`[${getOpenAICompatibleProviderLabel(i)}] responses 504 Gateway Timeout, reintentando...`,{level:"warn"}),sendRequest(e,t+1);if(401===r.status){const n=await maybeRecoverOpenAICompatible401(e,i);if(n)return sendRequest(n,t)}if(!r.ok)throw m(`[${getOpenAICompatibleProviderLabel(i)}] responses error status=${r.status} model=${s.model} endpoint=${o} oauth=${u} body=${(l.raw_error_text??"").replace(/\s+/g," ").slice(0,500)}`,{level:"error"}),new Error(buildOpenAIErrorMessage({status:r.status,statusText:r.statusText,url:o,model:String(s.model),data:l}));return l}catch(n){if(n instanceof Error&&"AbortError"===n.name&&!r?.aborted){if(t<f){const n=1e3*Math.pow(2,t);return m(`[${getOpenAICompatibleProviderLabel(i)}] responses timeout local tras 120000ms, reintentando en ${n}ms (intento ${t+1}/${f})`,{level:"warn"}),await new Promise(e=>setTimeout(e,n)),sendRequest(e,t+1)}throw new Error("La solicitud expiró tras 120s. El servidor tardó demasiado en responder.")}throw n}finally{clearTimeout(g),r?.removeEventListener("abort",onAbort)}};return sendRequest(a)}export async function*queryOpenAIModelWithStreaming({messages:t,systemPrompt:n,thinkingConfig:o,tools:r,signal:s,options:i}){try{for(let e=1;e<=2;e++){const o=await createOpenAIResponse({messages:1===e?t:[...t,y({content:"System reminder: your previous response for this turn was empty. Continue the current task without asking the user to repeat themselves. If a tool call is needed, emit the appropriate tool call now. Do not return an empty response.",isMeta:!0})],systemPrompt:n,tools:r,signal:s,options:i}),{content:a}=parseOutputItems(o),u=getUsage(o);if(u)try{const e={input_tokens:u.input_tokens??0,output_tokens:u.output_tokens??0,cache_read_input_tokens:0,cache_creation_input_tokens:0},t=String(i.model),n=_(t,e);h(n,e,t)}catch(e){d(e)}if(a.length>0)return void(yield g({content:a,usage:u}));if(!(e<2))return void(yield f({content:"OpenAI returned no content after retrying."}));m(`[${getOpenAICompatibleProviderLabel(getOpenAICompatibleProvider())}] empty model response with no content; retrying request (${e}/1)`,{level:"warn"})}}catch(t){if(s.aborted)throw new e;d(t),yield f({content:p(t),errorDetails:p(t)})}}
|
|
1
|
+
import{APIUserAbortError as e}from"@anthropic-ai/sdk/error.js";import{randomUUID as t}from"node:crypto";import{checkAndRefreshOpenAIOAuthTokenIfNeeded as n,getGeminiGoogleAuthHeaders as o,getOpenAICompatibleAccessToken as r,getOpenAIAccessToken as s,handleOpenAIOAuth401Error as i}from"../../utils/auth.js";import{getAPIProvider as a,isOpenAICompatibleProvider as u}from"../../utils/model/providers.js";import{getConfiguredProviderBaseUrl as l}from"../../utils/model/providerBaseUrls.js";import{getOpenAIOriginator as c}from"../../constants/oauth.js";import{errorMessage as p}from"../../utils/errors.js";import{logForDebugging as m}from"../../utils/debug.js";import{logError as d}from"../../utils/log.js";import{createAssistantAPIErrorMessage as f,createAssistantMessage as g,createUserMessage as y}from"../../utils/messages.js";import{addToTotalSessionCost as h}from"../../cost-tracker.js";import{calculateUSDCost as _}from"../../utils/modelCost.js";import{toolToAPISchema as A}from"../../utils/api.js";import{jsonStringify as O}from"../../utils/slowOperations.js";function getOpenAIMaxTimeoutRetries(){const e=process.env.CONTEXT_CODE_MAX_RETRIES;if(!e)return 10;const t=Number.parseInt(e,10);return!Number.isFinite(t)||t<0?10:t}function isRecord(e){return"object"==typeof e&&null!==e&&!Array.isArray(e)}function isPlainObject(e){if(!isRecord(e))return!1;const t=Object.getPrototypeOf(e);return t===Object.prototype||null===t}function isJwtToken(e){return 3===e.split(".").length}function getOpenAICompatibleProvider(){const e=a();return u(e)?e:"openai"}function getOpenAICompatibleProviderLabel(e=getOpenAICompatibleProvider()){switch(e){case"openrouter":return"OpenRouter";case"ollama":return"Ollama";case"ollama-cloud":return"Ollama Cloud";case"lmstudio":return"LM Studio";case"gemini-api":return"Gemini API";case"gemini-google":return"Gemini Google";case"zai":return"Z.AI";case"nvidia":return"NVIDIA NIM";case"custom-openai":return"Custom OpenAI";default:return"OpenAI"}}function getOpenAIBaseUrl(e=getOpenAICompatibleProvider()){if("openrouter"===e){const e=process.env.OPENROUTER_BASE_URL||l("openrouter")||"https://openrouter.ai/api/v1";return e.endsWith("/v1")?e:e.endsWith("/")?`${e}v1`:`${e}/v1`}if("ollama"===e){const e=process.env.OLLAMA_BASE_URL||l("ollama")||"http://localhost:11434/v1";return e.endsWith("/v1")?e:e.endsWith("/")?`${e}v1`:`${e}/v1`}if("ollama-cloud"===e){const e=process.env.OLLAMA_CLOUD_BASE_URL||process.env.OLLAMA_BASE_URL||l("ollama-cloud")||"http://localhost:11434/v1";return e.endsWith("/v1")?e:e.endsWith("/")?`${e}v1`:`${e}/v1`}if("lmstudio"===e){const e=process.env.LMSTUDIO_BASE_URL||process.env.LM_STUDIO_BASE_URL||l("lmstudio")||"http://localhost:1234/v1";return e.endsWith("/v1")?e:e.endsWith("/")?`${e}v1`:`${e}/v1`}if("zai"===e){const e=process.env.ZAI_BASE_URL||l("zai")||"https://api.z.ai/api/coding/paas/v4";return e.endsWith("/")?e.slice(0,-1):e}if("gemini-api"===e||"gemini-google"===e){const t=("gemini-api"===e?process.env.GEMINI_BASE_URL||process.env.GEMINI_API_BASE_URL:process.env.GEMINI_GOOGLE_BASE_URL||process.env.GEMINI_BASE_URL)||l(e)||"https://generativelanguage.googleapis.com/v1beta/openai";return t.endsWith("/")?t.slice(0,-1):t}if("nvidia"===e){const e=process.env.NVIDIA_BASE_URL||l("nvidia")||"https://integrate.api.nvidia.com/v1";return e.endsWith("/")?e.slice(0,-1):e}if("custom-openai"===e){let e=l("custom-openai")||"https://api.openai.com/v1";return e.startsWith("http://chinai.iaforged.com")&&(e=e.replace("http://chinai.iaforged.com","https://chinai.iaforged.com")),e.endsWith("/")?e.slice(0,-1):e}if("openai"!==e&&"custom-openai"!==e){const t=l(e);return t.endsWith("/")?t.slice(0,-1):t}const t=process.env.OPENAI_API_BASE_URL||process.env.OPENAI_BASE_URL||"https://api.openai.com/v1";return t.endsWith("/v1")?t:t.endsWith("/")?`${t}v1`:`${t}/v1`}async function getOpenAIRequestHeaders(e=getOpenAICompatibleProvider()){return"gemini-google"===e?o():function(e=getOpenAICompatibleProvider()){const t=r(e);if(isLocalOllamaProviderHost(e,getOpenAIBaseUrl(e)))return{"Content-Type":"application/json"};if(!t)throw new Error(`${getOpenAICompatibleProviderLabel(e)} is selected but no credentials were found.`);return"custom-openai"===e?{Authorization:`Bearer ${t}`,"X-API-Key":t,"api-key":t,"Content-Type":"application/json"}:{Authorization:`Bearer ${t}`,"Content-Type":"application/json"}}(e)}function isLocalOllamaProviderHost(e,t=getOpenAIBaseUrl(e)){return("ollama"===e||"ollama-cloud"===e)&&(t.includes("localhost")||t.includes("127.0.0.1"))}function getOpenAIAccessTokenOrThrow(e=getOpenAICompatibleProvider()){if(isLocalOllamaProviderHost(e))return"ollama";if("gemini-google"===e)return r(e)||"google-application-default-credentials";const t=r(e);if(!t)throw new Error(`${getOpenAICompatibleProviderLabel(e)} is selected but no credentials were found.`);return t}async function maybeRefreshOpenAICompatibleAuth(e=getOpenAICompatibleProvider()){"openai"===e&&await n()}async function maybeRecoverOpenAICompatible401(e,t=getOpenAICompatibleProvider()){if("openai"!==t)return null;if(!await i(e))return null;const n=s();return n&&n!==e?n:null}function toInputText(e){return{type:"input_text",text:e}}function toOutputText(e){return{type:"output_text",text:e}}function normalizeBlocksForRole(e,t){return"assistant"!==t?e:e.map(e=>"input_text"===e.type?toOutputText(e.text):e)}function stringifyBlockContent(e){return"string"==typeof e?e:Array.isArray(e)?e.map(e=>"string"==typeof e?e:e&&"object"==typeof e&&"type"in e&&"text"===e.type&&"text"in e&&"string"==typeof e.text?e.text:O(e)).join("\n"):null==e?"":O(e)}function normalizeResponseContent(e){return Array.isArray(e)?e:null==e?[]:[e]}function blockToOpenAIContentBlocks(e){if(!isRecord(e))return null;if("text"===e.type&&"string"==typeof e.text)return[toInputText(e.text)];if("image"===e.type){const t=isRecord(e.source)?e.source:null,n=t?function(e){if("base64"===e.type){const t=e.media_type,n=e.data;return"string"!=typeof t||"string"!=typeof n?null:{type:"input_image",image_url:`data:${t};base64,${n}`}}return"url"===e.type&&"string"==typeof e.url?{type:"input_image",image_url:e.url}:"file"===e.type&&"string"==typeof e.file_id?{type:"input_image",file_id:e.file_id}:null}(t):null;return n?[n]:null}if("document"===e.type){const t=isRecord(e.source)?e.source:null;if(!t)return null;const n=function(e,t){return"file"===e.type&&"string"==typeof e.file_id?{type:"input_file",file_id:e.file_id}:"base64"===e.type&&"string"==typeof e.data?"string"!=typeof e.media_type?null:{type:"input_file",file_data:e.data,..."string"==typeof t&&t?{filename:t}:{}}:"url"===e.type&&"string"==typeof e.url?{type:"input_file",file_url:e.url,..."string"==typeof t&&t?{filename:t}:{}}:"text"===e.type&&"string"==typeof e.data?toInputText(e.data):null}(t,"string"==typeof e.title?e.title:void 0);if(n)return[n];if("content"===t.type&&"string"==typeof t.content)return[toInputText(t.content)];if("content"===t.type&&Array.isArray(t.content)){const e=[];for(const n of t.content){const t=blockToOpenAIContentBlocks(n);t&&e.push(...t)}return e.length>0?e:null}return null}if("search_result"===e.type&&Array.isArray(e.content)){const t=[];"string"==typeof e.title&&e.title.trim()&&t.push(e.title.trim()),"string"==typeof e.source&&e.source.trim()&&t.push(e.source.trim());for(const n of e.content)if(n&&"object"==typeof n&&"text"in n){const e=n.text;"string"==typeof e&&e.trim()&&t.push(e.trim())}return[toInputText(t.join("\n\n"))]}if("container_upload"===e.type&&"string"==typeof e.file_id)return[{type:"input_file",file_id:e.file_id}];if(("bash_code_execution_output"===e.type||"mcp_tool_result"===e.type||"code_execution_tool_result"===e.type||"web_search_tool_result"===e.type||"web_fetch_tool_result"===e.type||"text_editor_code_execution_tool_result"===e.type||"tool_search_tool_result"===e.type)&&"content"in e){const t=e.content;if("string"==typeof t)return[toInputText(t)];if(Array.isArray(t)){const e=[];for(const n of t){const t=blockToOpenAIContentBlocks(n);t&&e.push(...t)}return e.length>0?e:null}}if("content"in e&&("string"==typeof e.content||Array.isArray(e.content))){const t=e.content;if("string"==typeof t)return[toInputText(t)];const n=[];for(const e of t){const t=blockToOpenAIContentBlocks(e);t&&n.push(...t)}return n.length>0?n:null}return"data"in e&&"string"==typeof e.data?[toInputText(e.data)]:null}function toolResultContentToOpenAIOutput(e){if("string"==typeof e)return e;if(!Array.isArray(e))return stringifyBlockContent(e);const t=[];for(const n of e){const e=blockToOpenAIContentBlocks(n);if(e&&e.length>0){t.push(...e);continue}const o=stringifyBlockContent(n).trim();o&&t.push(toInputText(o))}return 0===t.length?"":t.every(e=>"input_text"===e.type)?t.map(e=>e.text).join("\n\n"):t}function messageToOpenAIInput(e){if(!e.message||"user"!==e.type&&"assistant"!==e.type)return[];const t=Array.isArray(e.message.content)?e.message.content:[{type:"text",text:String(e.message.content??"")}],n="assistant"===e.type?"assistant":"user",o=[],r=[],flushMessage=()=>{0!==r.length&&(o.push({type:"message",role:n,content:[...r]}),r.length=0)};for(const s of t){if("assistant"===e.type&&"tool_use"===s.type&&"string"==typeof s.id&&"string"==typeof s.name){flushMessage(),o.push({type:"function_call",call_id:s.id,name:s.name,arguments:O(s.input??{})});continue}if("user"===e.type&&"tool_result"===s.type&&"string"==typeof s.tool_use_id){flushMessage(),o.push({type:"function_call_output",call_id:s.tool_use_id,output:toolResultContentToOpenAIOutput(s.content)});continue}if("thinking"===s.type||"redacted_thinking"===s.type)continue;const t=blockToOpenAIContentBlocks(s);t&&t.length>0?r.push(...normalizeBlocksForRole(t,n)):r.push(..."assistant"===n?[toOutputText(stringifyBlockContent(s))]:[toInputText(stringifyBlockContent(s))])}return flushMessage(),o}async function readOpenAIResponseBody(e){const t=await e.text();if(!t.trim())return{};const n=t.trim();if(n.startsWith("data:")||n.startsWith("event:"))return function(e){const t=[];for(const n of e.split(/\r?\n\r?\n/)){const e=n.split(/\r?\n/).map(e=>e.trim()).filter(Boolean);if(0===e.length)continue;const o=e.filter(e=>e.startsWith("data:")).map(e=>e.slice(5).trim());if(0===o.length)continue;const r=o.join("\n").trim();if(r&&"[DONE]"!==r)try{const e=JSON.parse(r);isRecord(e)&&t.push(e)}catch{}}let n=null,o=null;const r=[];let s="";for(const i of t){const t="string"==typeof i.type?i.type:"";"response.completed"===t&&isRecord(i.response)?n={...i.response,raw_error_text:e}:"error"!==t?"response.output_item.done"===t&&isRecord(i.item)?r.push(i.item):"response.output_text.delta"!==t||"string"!=typeof i.delta?"response.output_text.done"===t&&"string"==typeof i.text&&(s=i.text):s+=i.delta:"string"==typeof i.message&&i.message.trim()?o=i.message:isRecord(i.error)&&"string"==typeof i.error.message&&(o=i.error.message)}if(n)return(!n.output||0===n.output.length)&&r.length>0&&(n.output=r),!n.output_text&&s&&(n.output_text=s),!n.error&&o&&(n.error={message:o}),n;if(r.length>0||s||o)return{output:r.length>0?r:void 0,output_text:s||void 0,error:o?{message:o}:void 0,raw_error_text:e};return{error:{message:e},raw_error_text:e}}(t);try{const e=JSON.parse(t);return isRecord(e)&&"string"==typeof e.error?{...e,error:{message:e.error},raw_error_text:t}:isRecord(e)?{...e,raw_error_text:t}:{error:{message:t},raw_error_text:t}}catch{return{error:{message:t},raw_error_text:t}}}function buildOpenAIErrorMessage(e){const t=e.data.error?.message?.trim()||e.data.raw_error_text?.trim()||`OpenAI request failed (${e.status} ${e.statusText})`,n=/requires a subscription|upgrade for access/i.test(t)?`El modelo ${e.model??"seleccionado"} requiere una suscripcion de Ollama Cloud. Cambia a otro modelo en /model o actualiza tu plan de Ollama.`:t,o=e.data.raw_error_text?.trim(),r=o&&o!==t&&o!==n?o.replace(/\s+/g," ").slice(0,400):null;return r?`${n} [model=${e.model??"unknown"} endpoint=${e.url}] ${r}`:`${n} [model=${e.model??"unknown"} endpoint=${e.url}]`}function blockToChatContentPart(e){if("text"===e.type&&"string"==typeof e.text)return{type:"text",text:e.text};if("image"===e.type){const t=isRecord(e.source)?e.source:null;if(!t)return null;if("base64"===t.type&&"string"==typeof t.data&&"string"==typeof t.media_type)return{type:"image_url",image_url:{url:`data:${t.media_type};base64,${t.data}`}};if("url"===t.type&&"string"==typeof t.url)return{type:"image_url",image_url:{url:t.url}}}const t=stringifyBlockContent(e);return t?{type:"text",text:t}:null}function toolResultToString(e){return"string"==typeof e?e:Array.isArray(e)?e.map(e=>"string"==typeof e?e:isRecord(e)&&"string"==typeof e.text?e.text:stringifyBlockContent(e)).filter(Boolean).join("\n"):stringifyBlockContent(e)}function messageToChatMessages(e){if(!e.message||"user"!==e.type&&"assistant"!==e.type)return[];const t=e.message.content,n=Array.isArray(t)?t:[{type:"text",text:String(t??"")}];if("assistant"===e.type){const e=[],t=[];for(const o of n)"thinking"!==o.type&&"redacted_thinking"!==o.type&&("tool_use"===o.type&&"string"==typeof o.id&&"string"==typeof o.name?e.push({id:o.id,type:"function",function:{name:o.name,arguments:O(o.input??{})}}):"text"===o.type&&"string"==typeof o.text&&o.text.trim()&&t.push(o.text));const o={role:"assistant",content:t.join("\n")};return e.length>0&&(o.tool_calls=e),[o]}const o=[],r=[];for(const e of n)if("tool_result"===e.type&&"string"==typeof e.tool_use_id)o.push({role:"tool",tool_call_id:e.tool_use_id,content:toolResultToString(e.content)});else{const t=blockToChatContentPart(e);t&&r.push(t)}const s=[...o];if(r.length>0){const e=r.every(e=>"text"===e.type);s.push({role:"user",content:e?r.map(e=>e.text).join("\n"):r})}return s}function parseChatCompletionResponse(e){const t=[];for(const n of e.choices??[]){const e=n.message;if(e){"string"==typeof e.content&&e.content.trim()&&t.push({type:"text",text:e.content});for(const n of e.tool_calls??[])t.push({type:"tool_use",id:n.id,name:n.function?.name??"tool",input:parseFunctionCallArguments(n.function?.arguments)})}}return{content:t}}function getChatUsage(e){if("number"==typeof e.usage?.prompt_tokens||"number"==typeof e.usage?.completion_tokens)return{input_tokens:e.usage?.prompt_tokens??0,output_tokens:e.usage?.completion_tokens??0}}function buildChatToolChoice(e){if(!e.toolChoice)return"auto";switch(e.toolChoice.type){case"auto":default:return"auto";case"any":return"required";case"none":return"none";case"tool":return"string"==typeof e.toolChoice.name?{type:"function",function:{name:e.toolChoice.name}}:"auto"}}function chatContentToGeminiParts(e){return"string"==typeof e?e?[{text:e}]:[]:Array.isArray(e)?e.map(e=>"text"===e.type?e.text?{text:e.text}:null:"image_url"===e.type?{text:`[Image input: ${e.image_url.url}]`}:null).filter(e=>null!==e):[]}function buildGeminiContents(e){const t=new Map,n=[];for(const o of e){if("system"===o.role)continue;if("assistant"===o.role){const e=chatContentToGeminiParts(o.content);for(const n of o.tool_calls??[]){t.set(n.id,n.function.name);const o=parseFunctionCallArguments(n.function.arguments);e.push({functionCall:{name:n.function.name,args:isPlainObject(o)?o:{raw:o}}})}e.length>0&&n.push({role:"model",parts:e});continue}if("tool"===o.role){const e=o.tool_call_id?t.get(o.tool_call_id)??"tool":"tool";n.push({role:"function",parts:[{functionResponse:{name:e,response:{result:o.content??""}}}]});continue}const e=chatContentToGeminiParts(o.content);e.length>0&&n.push({role:"user",parts:e})}return n.length>0?n:[{role:"user",parts:[{text:""}]}]}function getGeminiEnumType(e){switch(typeof e){case"string":return"string";case"number":return Number.isInteger(e)?"integer":"number";case"boolean":return"boolean";default:return}}function sanitizeGeminiSchema(e){if(!isRecord(e))return{type:"object",properties:{}};const t=Array.isArray(e.anyOf)?e.anyOf:Array.isArray(e.any_of)?e.any_of:null,n=Array.isArray(e.oneOf)?e.oneOf:Array.isArray(e.one_of)?e.one_of:null;if(t||n){const e=function(e){const t=[];let n,o=!1;for(const r of e){if(!isRecord(r))return null;if("null"===r.type){o=!0;continue}const e=void 0!==r.const?[r.const]:Array.isArray(r.enum)?r.enum:null;if(!e)return null;for(const o of e){const e=getGeminiEnumType(o);if(!e)return null;if(n&&n!==e)return null;n=e,t.push(o)}}return n&&0!==t.length?{type:n,enum:Array.from(new Set(t)),...o?{nullable:!0}:{}}:null}(t??n??[]);return e||{anyOf:(t??n??[]).map(sanitizeGeminiSchema)}}const o={},r=e.type;if(Array.isArray(r)){const e=r.find(e=>"null"!==e);"string"==typeof e&&(o.type=e),r.includes("null")&&(o.nullable=!0)}else"string"==typeof r&&(o.type=r);for(const t of["title","description","format","nullable","minimum","maximum","minItems","maxItems","minLength","maxLength","pattern"])void 0!==e[t]&&(o[t]=e[t]);if(Array.isArray(e.enum)?o.enum=e.enum:void 0!==e.const&&(o.enum=[e.const]),!o.type&&Array.isArray(o.enum)&&o.enum.length>0&&(o.type=getGeminiEnumType(o.enum[0])),void 0!==e.exclusiveMinimum&&void 0===o.minimum&&(o.minimum="number"==typeof e.exclusiveMinimum?e.exclusiveMinimum:e.minimum),void 0!==e.exclusiveMaximum&&void 0===o.maximum&&(o.maximum="number"==typeof e.exclusiveMaximum?e.exclusiveMaximum:e.maximum),isRecord(e.items)?o.items=sanitizeGeminiSchema(e.items):Array.isArray(e.items)&&e.items.length>0&&(o.items=sanitizeGeminiSchema(e.items[0])),isRecord(e.properties)){const t={};for(const[n,o]of Object.entries(e.properties))t[n]=sanitizeGeminiSchema(o);o.properties=t}return Array.isArray(e.required)&&(o.required=e.required.filter(e=>"string"==typeof e)),o.type||(o.type=o.properties?"object":o.items?"array":"object"),"object"!==o.type||o.properties||(o.properties={}),o}async function postGeminiCodeAssist(e,t,n,o){const r=await fetch(`https://cloudcode-pa.googleapis.com/v1internal:${e}`,{method:"POST",headers:t,body:O(n),signal:o});return{response:r,data:await readOpenAIResponseBody(r)}}function getGeminiCodeAssistMetadata(e){return{ideType:"IDE_UNSPECIFIED",platform:"PLATFORM_UNSPECIFIED",pluginType:"GEMINI",...e?{duetProject:e}:{}}}async function resolveGeminiCodeAssistProject(e,t){const n=process.env.GEMINI_GOOGLE_PROJECT_ID?.trim()||void 0,o={...n?{cloudaicompanionProject:n}:{},metadata:getGeminiCodeAssistMetadata(n)},{response:r,data:s}=await postGeminiCodeAssist("loadCodeAssist",e,o,t);if(!r.ok)return n;if("string"==typeof s.cloudaicompanionProject)return s.cloudaicompanionProject;if(n)return n;const i=Array.isArray(s.allowedTiers)?s.allowedTiers.filter(isRecord):[],a=i.find(e=>!0===e.isDefault)??i[0],u="string"==typeof a?.id?a.id:void 0;if(!u)return;const{response:l,data:c}=await postGeminiCodeAssist("onboardUser",e,{tierId:u,metadata:getGeminiCodeAssistMetadata()},t);if(!l.ok)return;const p=isRecord(c.response)?c.response:c,m=isRecord(p.cloudaicompanionProject)?p.cloudaicompanionProject:null;return"string"==typeof m?.id?m.id:void 0}async function createGeminiGoogleChatCompletionResponse(e){const{model:n,chatMessages:r,chatTools:s,toolChoice:i,signal:a,maxOutputTokens:u,temperature:l}=e,c=await o(),p=await resolveGeminiCodeAssistProject(c,a),d={};u&&(d.maxOutputTokens=u),void 0!==l&&(d.temperature=l);const f={contents:buildGeminiContents(r),session_id:t()},g=r.filter(e=>"system"===e.role&&"string"==typeof e.content).map(e=>e.content).join("\n\n");g&&(f.systemInstruction={role:"user",parts:[{text:g}]});const y=function(e){if(0!==e.length)return[{functionDeclarations:e.map(e=>({name:e.function.name,description:e.function.description,parameters:sanitizeGeminiSchema(e.function.parameters??{type:"object",properties:{}})}))}]}(s);y&&(f.tools=y);const h=function(e){if("auto"!==e)return"none"===e?{functionCallingConfig:{mode:"NONE"}}:"required"===e?{functionCallingConfig:{mode:"ANY"}}:{functionCallingConfig:{mode:"ANY",allowedFunctionNames:[e.function.name]}}}(i);h&&(f.toolConfig=h),Object.keys(d).length>0&&(f.generationConfig=d);let _=n;const A=n.toLowerCase();_=A.includes("flash")?"gemini-3-flash-preview":(A.includes("pro"),"gemini-3.1-pro-preview");const C={model:_,...p?{project:p}:{},user_prompt_id:t(),request:f},b="https://cloudcode-pa.googleapis.com/v1internal:generateContent";m(`[Gemini Google] codeassist generateContent request model=${_} (original=${n}) messages=${r.length} tools=${s.length} endpoint=${b}`);const{response:x,data:I}=await postGeminiCodeAssist("generateContent",c,C,a);if(!x.ok)throw m(`[Gemini Google] codeassist generateContent error status=${x.status} model=${n} endpoint=${b} body=${(I.error?.message??"").replace(/\s+/g," ").slice(0,500)}`,{level:"error"}),new Error(buildOpenAIErrorMessage({status:x.status,statusText:x.statusText,url:b,model:n,data:I}));return function(e){const n=e.response?.candidates??[];return{id:e.traceId,choices:n.map(e=>{const n=[],o=[];for(const r of e.content?.parts??[])"text"in r&&"string"==typeof r.text&&n.push(r.text),"functionCall"in r&&r.functionCall?.name&&o.push({id:`call_${t().replace(/-/g,"")}`,type:"function",function:{name:r.functionCall.name,arguments:O(r.functionCall.args??{})}});return{message:{content:n.join("")||null,tool_calls:o.length>0?o:void 0},finish_reason:e.finishReason}}),usage:{prompt_tokens:e.response?.usageMetadata?.promptTokenCount,completion_tokens:e.response?.usageMetadata?.candidatesTokenCount}}}(I)}async function createChatCompletionResponse({messages:e,systemPrompt:t,tools:n,signal:o,options:s}){const i=getOpenAICompatibleProvider();await maybeRefreshOpenAICompatibleAuth(i);const a=t.join("\n\n"),u=[...a?[{role:"system",content:a}]:[],...e.flatMap(messageToChatMessages)],l=function(e){return e.map(e=>({type:"function",function:{name:e.name,description:e.description,parameters:e.parameters,...e.strict?{strict:!0}:{}}}))}(await buildOpenAITools(n,s)),c={model:s.model,messages:u,stream:"custom-openai"!==i,..."custom-openai"!==i?{stream_options:{include_usage:!0}}:{}};if(l.length>0&&(c.tools=l,c.tool_choice=buildChatToolChoice(s)),shouldDisableParallelToolCalls(s)&&(c.parallel_tool_calls=!1),s.maxOutputTokensOverride&&(c.max_tokens=s.maxOutputTokensOverride),void 0!==s.temperatureOverride&&(c.temperature=s.temperatureOverride),s.effortValue&&(c.reasoning_effort=s.effortValue),"gemini-google"===i)return createGeminiGoogleChatCompletionResponse({model:String(s.model),chatMessages:u,chatTools:l,toolChoice:buildChatToolChoice(s),signal:o,maxOutputTokens:s.maxOutputTokensOverride,temperature:s.temperatureOverride});const p=getOpenAIMaxTimeoutRetries(),sendRequest=async(e=r(i)??"",t=0)=>{const n=`${getOpenAIBaseUrl(i)}/chat/completions`;m(`[${getOpenAICompatibleProviderLabel(i)}] chat.completions request model=${s.model} messages=${u.length} tools=${l.length} endpoint=${n}${t>0?` (retry ${t})`:""}`);const a=12e4,d=new AbortController,f=setTimeout(()=>d.abort(),a),onAbort=()=>d.abort();o?.addEventListener("abort",onAbort);try{if("custom-openai"===i)try{const e=require("fs"),t=`--- NUEVA SOLICITUD A CHINAI ---\nFecha: ${(new Date).toISOString()}\nURL: ${n}\nHeaders: ${JSON.stringify(await getOpenAIRequestHeaders(i),null,2)}\nBody: ${JSON.stringify(c,null,2)}\n\n`;e.writeFileSync("d:/Documents/GitHub/Claude/claude-code_V1/Context_Code_V1/chat-debug.txt",t)}catch(e){}m(`[${getOpenAICompatibleProviderLabel(i)}] chat.completions REQUEST BODY: ${O(c).slice(0,3e3)}`);const o=await fetch(n,{method:"POST",headers:await getOpenAIRequestHeaders(i),body:O(c),signal:d.signal}),r=await o.text();if("custom-openai"===i)try{const e=require("fs"),t=`--- RESPUESTA DE CHINAI ---\nStatus: ${o.status} ${o.statusText}\nBody: ${r}\n\n`;e.appendFileSync("d:/Documents/GitHub/Claude/claude-code_V1/Context_Code_V1/chat-debug.txt",t)}catch(e){}let a;m(`[${getOpenAICompatibleProviderLabel(i)}] chat.completions RAW response status=${o.status} bodyLength=${r.length} bodyPreview=${r.slice(0,3e3)}`);const u=r.trim();if(u.startsWith("data:")||u.startsWith("event:")){const e=function(e){const t=[];for(const n of e.split(/\r?\n\r?\n/)){const e=n.split(/\r?\n/).map(e=>e.trim()).filter(e=>e.startsWith("data:")).map(e=>e.slice(5).trim());if(0===e.length)continue;const o=e.join("\n").trim();if(o&&"[DONE]"!==o)try{const e=JSON.parse(o);isRecord(e)&&t.push(e)}catch{}}if(0===t.length)return null;if(!t.some(e=>{const t=e.object;return"string"==typeof t&&t.startsWith("chat.completion")}))return null;let n,o,r,s,i="",a="";const u=new Map;for(const e of t){if(n||"string"!=typeof e.id||(n=e.id),isRecord(e.usage)){const t=e.usage;"number"==typeof t.prompt_tokens&&(r=t.prompt_tokens),"number"==typeof t.completion_tokens&&(s=t.completion_tokens)}const t=Array.isArray(e.choices)?e.choices:[];for(const e of t){if(!isRecord(e))continue;"string"==typeof e.finish_reason&&(o=e.finish_reason);const t=isRecord(e.delta)?e.delta:null,n=isRecord(e.message)?e.message:null,r=t??n;if(!r)continue;"string"==typeof r.content&&(i+=r.content),"string"==typeof r.reasoning_content&&(a+=r.reasoning_content);const s=Array.isArray(r.tool_calls)?r.tool_calls:[];for(const e of s){if(!isRecord(e))continue;const t="number"==typeof e.index?e.index:0,n=u.get(t)??{arguments:""};"string"==typeof e.id&&(n.id=e.id);const o=isRecord(e.function)?e.function:null;o&&("string"==typeof o.name&&(n.name=o.name),"string"==typeof o.arguments&&(n.arguments+=o.arguments)),u.set(t,n)}}}const l=i||(a?a.trim():""),c=[];for(const[,e]of[...u.entries()].sort((e,t)=>e[0]-t[0]))e.name&&c.push({id:e.id??`call_${c.length}`,type:"function",function:{name:e.name,arguments:e.arguments}});return{id:n,choices:[{message:{content:l||null,...c.length>0?{tool_calls:c}:{}},finish_reason:o}],usage:{prompt_tokens:r,completion_tokens:s}}}(r);if(e)a=e;else try{a=JSON.parse(r)}catch{a={error:{message:r.slice(0,500)}}}}else if(u)try{a=JSON.parse(r)}catch{a={error:{message:r.slice(0,500)}}}else a={};if(504===o.status&&t<1)return m(`[${getOpenAICompatibleProviderLabel(i)}] 504 Gateway Timeout, reintentando...`,{level:"warn"}),sendRequest(e,t+1);if(401===o.status){const n=await maybeRecoverOpenAICompatible401(e,i);if(n)return sendRequest(n,t)}if(!o.ok)throw m(`[${getOpenAICompatibleProviderLabel(i)}] chat.completions error status=${o.status} model=${s.model} endpoint=${n} body=${(a.error?.message??"").replace(/\s+/g," ").slice(0,500)}`,{level:"error"}),new Error(buildOpenAIErrorMessage({status:o.status,statusText:o.statusText,url:n,model:String(s.model),data:a}));return a}catch(n){if(n instanceof Error&&"AbortError"===n.name&&!o?.aborted){if(t<p){const n=1e3*Math.pow(2,t);return m(`[${getOpenAICompatibleProviderLabel(i)}] timeout local tras 120000ms, reintentando en ${n}ms (intento ${t+1}/${p})`,{level:"warn"}),await new Promise(e=>setTimeout(e,n)),sendRequest(e,t+1)}throw new Error("La solicitud expiró tras 120s. El servidor tardó demasiado en responder.")}throw n}finally{clearTimeout(f),o?.removeEventListener("abort",onAbort)}};return getOpenAIAccessTokenOrThrow(i),sendRequest()}async function buildOpenAITools(e,t){return(await Promise.all(e.map(n=>A(n,{getToolPermissionContext:t.getToolPermissionContext,tools:e,agents:t.agents,allowedAgentTypes:t.allowedAgentTypes,model:t.model})))).map(e=>({type:"function",name:e.name,description:e.description,parameters:e.input_schema,...e.strict?{strict:!0}:{}}))}function buildToolChoice(e){if(!e.toolChoice)return"auto";switch(e.toolChoice.type){case"auto":default:return"auto";case"any":return"required";case"none":return"none";case"tool":return"string"==typeof e.toolChoice.name?{type:"function",name:e.toolChoice.name}:"auto"}}function shouldDisableParallelToolCalls(e){const t=e.toolChoice;return Boolean(t&&"disable_parallel_tool_use"in t&&!0===t.disable_parallel_tool_use)}function parseFunctionCallArguments(e){if(isPlainObject(e))return e;if("string"!=typeof e)return null==e?{}:{raw:e};try{const t=JSON.parse(e);return isPlainObject(t)?t:{raw:t}}catch{return{raw:e}}}function parseOutputItems(e){const t=[];for(const n of e.output??[])if(n&&"object"==typeof n){if("function_call"===n.type){const e=parseFunctionCallArguments(n.arguments);t.push({type:"tool_use",id:String(n.call_id??n.id??""),name:String(n.name??"tool"),input:e});continue}if("message"===n.type)for(const e of normalizeResponseContent(n.content)){if("string"==typeof e){t.push({type:"text",text:e});continue}if(!e||"object"!=typeof e||!("type"in e))continue;const n=String(e.type??""),o="string"==typeof e.text?e.text??"":"string"==typeof e.refusal?e.refusal??"":"";"output_text"!==n&&"text"!==n&&"refusal"!==n||!o||t.push({type:"text",text:o})}}return 0===t.length&&"string"==typeof e.output_text&&t.push({type:"text",text:e.output_text}),{content:t}}function getUsage(e){if("number"==typeof e.usage?.input_tokens||"number"==typeof e.usage?.output_tokens)return{input_tokens:e.usage?.input_tokens??0,output_tokens:e.usage?.output_tokens??0}}function sideQueryMessageToOpenAIInput(e){const t=Array.isArray(e.content)?e.content.filter(e=>"text"===e?.type&&"string"==typeof e.text).map(e=>toInputText(e.text)):[toInputText(String(e.content??""))];return[{type:"message",role:e.role,content:t.length>0?t:[toInputText("")]}]}function sideQueryToolToOpenAITool(e){return{type:"function",name:e.name,description:e.description,parameters:e.input_schema??{type:"object",properties:{}}}}function buildSideQueryToolChoice(e){return e&&"auto"!==e?"none"===e||"none"===e.type?"none":"any"===e.type?"required":"auto"===e.type?"auto":"string"==typeof e.name&&e.name?{type:"function",name:e.name}:"auto":"auto"}function sideQueryMessageToChatMessage(e){const t=Array.isArray(e.content)?e.content.filter(e=>"text"===e?.type&&"string"==typeof e.text).map(e=>e.text).join("\n"):String(e.content??"");return{role:e.role,content:t}}function sideQueryToolToChatTool(e){return{type:"function",function:{name:e.name,description:e.description,parameters:e.input_schema??{type:"object",properties:{}}}}}export async function queryOpenAISideQuery({model:e,systemPrompt:t,messages:n,tools:o,toolChoice:s,outputFormat:i,signal:a,maxOutputTokens:u,temperature:l}){const c=getOpenAICompatibleProvider();await maybeRefreshOpenAICompatibleAuth(c);const p=getOpenAIBaseUrl(c),d=r(c);if(!("openai"===c&&d&&isJwtToken(d))){const r=[...t?[{role:"system",content:t}]:[],...n.map(sideQueryMessageToChatMessage)],d={model:e,messages:r,stream:!1},f=o?.map(sideQueryToolToChatTool)??[],g=function(e){const t=buildSideQueryToolChoice(e);return"auto"===t||"none"===t?t:"required"===t?"required":{type:"function",function:{name:t.name}}}(s);if(f.length>0&&(d.tools=f,d.tool_choice=g),"json_schema"===i?.type&&(d.response_format={type:"json_schema",json_schema:{name:"side_query_output",strict:!0,schema:i.schema}}),u&&(d.max_tokens=u),void 0!==l&&(d.temperature=l),"gemini-google"===c){const t=await createGeminiGoogleChatCompletionResponse({model:e,chatMessages:r,chatTools:f,toolChoice:g,signal:a,maxOutputTokens:u,temperature:l});return{id:t.id,content:parseChatCompletionResponse(t).content,usage:getChatUsage(t)}}const y=`${p}/chat/completions`,h=await getOpenAIRequestHeaders(c);if("custom-openai"===c)try{const e=require("fs"),t=`--- NUEVA SOLICITUD DE VALIDACION DE MODELO A CHINAI ---\nFecha: ${(new Date).toISOString()}\nURL: ${y}\nHeaders: ${JSON.stringify(h,null,2)}\nBody: ${JSON.stringify(d,null,2)}\n\n`;e.appendFileSync("d:/Documents/GitHub/Claude/claude-code_V1/Context_Code_V1/chat-debug.txt",t)}catch(e){}const _=await fetch(y,{method:"POST",headers:h,body:O(d),signal:a});if("custom-openai"===c)try{const e=_.clone(),t=await e.text(),n=require("fs"),o=`--- RESPUESTA DE VALIDACION DE MODELO DE CHINAI ---\nStatus: ${_.status} ${_.statusText}\nBody: ${t}\n\n`;n.appendFileSync("d:/Documents/GitHub/Claude/claude-code_V1/Context_Code_V1/chat-debug.txt",o)}catch(e){}const A=await readOpenAIResponseBody(_);if(!_.ok)throw m(`[${getOpenAICompatibleProviderLabel(c)}] sideQuery chat.completions error status=${_.status} model=${e} endpoint=${y} body=${(A.error?.message??"").replace(/\s+/g," ").slice(0,500)}`,{level:"error"}),new Error(buildOpenAIErrorMessage({status:_.status,statusText:_.statusText,url:y,model:e,data:A}));return{id:A.id,content:parseChatCompletionResponse(A).content,usage:getChatUsage(A)}}const f={model:e,input:n.flatMap(sideQueryMessageToOpenAIInput),instructions:t,stream:!1,store:!1};o&&o.length>0&&(f.tools=o.map(sideQueryToolToOpenAITool),f.tool_choice=buildSideQueryToolChoice(s)),"json_schema"===i?.type&&(f.text={format:{type:"json_schema",name:"side_query_output",strict:!0,schema:i.schema}}),u&&(f.max_output_tokens=u),void 0!==l&&(f.temperature=l);const g=`${p}/responses`,y=await fetch(g,{method:"POST",headers:await getOpenAIRequestHeaders(c),body:O(f),signal:a}),h=await readOpenAIResponseBody(y);if(!y.ok)throw m(`[${getOpenAICompatibleProviderLabel(c)}] sideQuery error status=${y.status} model=${e} endpoint=${p}/responses body=${(h.raw_error_text??"").replace(/\s+/g," ").slice(0,500)}`,{level:"error"}),new Error(buildOpenAIErrorMessage({status:y.status,statusText:y.statusText,url:`${p}/responses`,model:e,data:h}));return{id:h.id,content:parseOutputItems(h).content,usage:getUsage(h)}}async function createOpenAIResponse(e){const{messages:t,systemPrompt:n,tools:o,signal:r,options:s}=e,i=getOpenAICompatibleProvider();await maybeRefreshOpenAICompatibleAuth(i);const a=getOpenAIAccessTokenOrThrow(i),u="openai"===i&&isJwtToken(a);if(!u){const t=await createChatCompletionResponse(e);return{id:t.id,output:t.choices?.flatMap(e=>{const t=[];if(e.message?.content&&t.push({type:"message",role:"assistant",content:[e.message.content]}),e.message?.tool_calls)for(const n of e.message.tool_calls)t.push({type:"function_call",call_id:n.id,name:n.function.name,arguments:n.function.arguments});return t})??[],usage:{input_tokens:t.usage?.prompt_tokens,output_tokens:t.usage?.completion_tokens}}}const l=t.flatMap(messageToOpenAIInput),p=await buildOpenAITools(o,s),d={model:s.model,input:l,instructions:n.join("\n\n"),tools:p,tool_choice:buildToolChoice(s),stream:!1,store:!1};shouldDisableParallelToolCalls(s)&&(d.parallel_tool_calls=!1),s.maxOutputTokensOverride&&(d.max_output_tokens=s.maxOutputTokensOverride),void 0!==s.temperatureOverride&&(d.temperature=s.temperatureOverride),s.effortValue&&(d.reasoning={effort:s.effortValue});const f=getOpenAIMaxTimeoutRetries(),sendRequest=async(e,t=0)=>{const n=u?{...d,stream:!0}:d;let o,a;if(u){const t=function(e){try{const t=JSON.parse(atob(e.split(".")[1])),n=t?.["https://api.openai.com/auth"]?.chatgpt_account_id;if(!n)throw new Error("No account ID in token");return n}catch{throw new Error("Failed to extract chatgpt-account-id from OAuth token")}}(e);o=function(){const e=(process.env.OPENAI_OAUTH_BASE_URL||"https://chatgpt.com/backend-api").replace(/\/+$/,"");return e.endsWith("/codex/responses")?e:e.endsWith("/codex")?`${e}/responses`:`${e}/codex/responses`}(),a={Authorization:`Bearer ${e}`,"chatgpt-account-id":t,"OpenAI-Beta":"responses=experimental",originator:c(),"content-type":"application/json",accept:"application/json"}}else o=`${getOpenAIBaseUrl(i)}/responses`,a={Authorization:`Bearer ${e}`,"Content-Type":"application/json"};const l=12e4,p=new AbortController,g=setTimeout(()=>p.abort(),l),onAbort=()=>p.abort();r?.addEventListener("abort",onAbort);try{const r=await fetch(o,{method:"POST",headers:a,body:O(n),signal:p.signal}),l=await readOpenAIResponseBody(r);if(504===r.status&&t<1)return m(`[${getOpenAICompatibleProviderLabel(i)}] responses 504 Gateway Timeout, reintentando...`,{level:"warn"}),sendRequest(e,t+1);if(401===r.status){const n=await maybeRecoverOpenAICompatible401(e,i);if(n)return sendRequest(n,t)}if(!r.ok)throw m(`[${getOpenAICompatibleProviderLabel(i)}] responses error status=${r.status} model=${s.model} endpoint=${o} oauth=${u} body=${(l.raw_error_text??"").replace(/\s+/g," ").slice(0,500)}`,{level:"error"}),new Error(buildOpenAIErrorMessage({status:r.status,statusText:r.statusText,url:o,model:String(s.model),data:l}));return l}catch(n){if(n instanceof Error&&"AbortError"===n.name&&!r?.aborted){if(t<f){const n=1e3*Math.pow(2,t);return m(`[${getOpenAICompatibleProviderLabel(i)}] responses timeout local tras 120000ms, reintentando en ${n}ms (intento ${t+1}/${f})`,{level:"warn"}),await new Promise(e=>setTimeout(e,n)),sendRequest(e,t+1)}throw new Error("La solicitud expiró tras 120s. El servidor tardó demasiado en responder.")}throw n}finally{clearTimeout(g),r?.removeEventListener("abort",onAbort)}};return sendRequest(a)}export async function*queryOpenAIModelWithStreaming({messages:t,systemPrompt:n,thinkingConfig:o,tools:r,signal:s,options:i}){try{for(let e=1;e<=2;e++){const o=await createOpenAIResponse({messages:1===e?t:[...t,y({content:"System reminder: your previous response for this turn was empty. Continue the current task without asking the user to repeat themselves. If a tool call is needed, emit the appropriate tool call now. Do not return an empty response.",isMeta:!0})],systemPrompt:n,tools:r,signal:s,options:i}),{content:a}=parseOutputItems(o),u=getUsage(o);if(u)try{const e={input_tokens:u.input_tokens??0,output_tokens:u.output_tokens??0,cache_read_input_tokens:0,cache_creation_input_tokens:0},t=String(i.model),n=_(t,e);h(n,e,t)}catch(e){d(e)}if(a.length>0)return void(yield g({content:a,usage:u}));if(!(e<2))return void(yield f({content:"OpenAI returned no content after retrying."}));m(`[${getOpenAICompatibleProviderLabel(getOpenAICompatibleProvider())}] empty model response with no content; retrying request (${e}/1)`,{level:"warn"})}}catch(t){if(s.aborted)throw new e;d(t),yield f({content:p(t),errorDetails:p(t)})}}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{feature as e}from"../../recovery/bunBundleShim.js";import{createRequire as r}from"module";const s=r(import.meta.url);import{chmod as o,open as t,rename as n,stat as i,unlink as c}from"fs/promises";import a from"lodash-es/mapValues.js";import p from"lodash-es/memoize.js";import{dirname as l,join as f,parse as u}from"path";import{getPlatform as d}from"../../utils/platform.js";import{getPluginErrorMessage as m}from"../../types/plugin.js";import{isClaudeInChromeMCPServer as g}from"../../utils/claudeInChrome/common.js";import{getCurrentProjectConfig as v,getGlobalConfig as M,saveCurrentProjectConfig as S,saveGlobalConfig as h}from"../../utils/config.js";import{getCwd as w}from"../../utils/cwd.js";import{logForDebugging as C}from"../../utils/debug.js";import{getErrnoCode as y}from"../../utils/errors.js";import{getFsImplementation as j}from"../../utils/fsOperations.js";import{safeParseJSON as P}from"../../utils/json.js";import{logError as b}from"../../utils/log.js";import{getPluginMcpServers as x}from"../../utils/plugins/mcpPluginIntegration.js";import{loadAllPluginsCacheOnly as $}from"../../utils/plugins/pluginLoader.js";import{isSettingSourceEnabled as E}from"../../utils/settings/constants.js";import{getManagedFilePath as O}from"../../utils/settings/managedPath.js";import{isRestrictedToPluginOnly as F}from"../../utils/settings/pluginOnlyPolicy.js";import{getInitialSettings as A,getSettingsForSource as B}from"../../utils/settings/settings.js";import{isMcpServerCommandEntry as N,isMcpServerNameEntry as D,isMcpServerUrlEntry as k}from"../../utils/settings/types.js";import{jsonStringify as V}from"../../utils/slowOperations.js";import{logEvent as U}from"../analytics/index.js";import{fetchClaudeAIMcpConfigsIfEligible as _}from"./claudeai.js";import{expandEnvVarsInString as T}from"./envExpansion.js";import{McpJsonConfigSchema as W,McpServerConfigSchema as I}from"./types.js";import{getProjectMcpServerStatus as R}from"./utils.js";export function getEnterpriseMcpFilePath(){return f(O(),"managed-mcp.json")}function addScopeToServers(e,r){if(!e)return{};const s={};for(const[o,t]of Object.entries(e))s[o]={...t,scope:r};return s}async function writeMcpjsonFile(e){const r=f(w(),".mcp.json");let s;try{s=(await i(r)).mode}catch(e){if("ENOENT"!==y(e))throw e}const a=`${r}.tmp.${process.pid}.${Date.now()}`,p=await t(a,"w",s??420);try{await p.writeFile(V(e,null,2),{encoding:"utf8"}),await p.datasync()}finally{await p.close()}try{void 0!==s&&await o(a,s),await n(a,r)}catch(e){try{await c(a)}catch{}throw e}}function getServerCommandArray(e){if(void 0!==e.type&&"stdio"!==e.type)return null;const r=e;return[r.command,...r.args??[]]}function commandArraysMatch(e,r){return e.length===r.length&&e.every((e,s)=>e===r[s])}function getServerUrl(e){return"url"in e?e.url:null}const J=["/v2/session_ingress/shttp/mcp/","/v2/ccr-sessions/"];export function unwrapCcrProxyUrl(e){if(!J.some(r=>e.includes(r)))return e;try{const r=new URL(e);return r.searchParams.get("mcp_url")||e}catch{return e}}export function getMcpServerSignature(e){const r=getServerCommandArray(e);if(r)return`stdio:${V(r)}`;const s=getServerUrl(e);return s?`url:${unwrapCcrProxyUrl(s)}`:null}export function dedupPluginMcpServers(e,r){const s=new Map;for(const[e,o]of Object.entries(r)){const r=getMcpServerSignature(o);r&&!s.has(r)&&s.set(r,e)}const o={},t=[],n=new Map;for(const[r,i]of Object.entries(e)){const e=getMcpServerSignature(i);if(null===e){o[r]=i;continue}const c=s.get(e);if(void 0!==c){C(`Suppressing plugin MCP server "${r}": duplicates manually-configured "${c}"`),t.push({name:r,duplicateOf:c});continue}const a=n.get(e);void 0===a?(n.set(e,r),o[r]=i):(C(`Suppressing plugin MCP server "${r}": duplicates earlier plugin server "${a}"`),t.push({name:r,duplicateOf:a}))}return{servers:o,suppressed:t}}export function dedupClaudeAiMcpServers(e,r){const s=new Map;for(const[e,o]of Object.entries(r)){if(isMcpServerDisabled(e))continue;const r=getMcpServerSignature(o);r&&!s.has(r)&&s.set(r,e)}const o={},t=[];for(const[r,n]of Object.entries(e)){const e=getMcpServerSignature(n),i=null!==e?s.get(e):void 0;void 0===i?o[r]=n:(C(`Suppressing claude.ai connector "${r}": duplicates manually-configured "${i}"`),t.push({name:r,duplicateOf:i}))}return{servers:o,suppressed:t}}function urlMatchesPattern(e,r){const s=function(e){const r=e.replace(/[.+?^${}()|[\]\\]/g,"\\$&").replace(/\*/g,".*");return new RegExp(`^${r}$`)}(r);return s.test(e)}function isMcpServerDenied(e,r){const s=A();if(!s.deniedMcpServers)return!1;for(const r of s.deniedMcpServers)if(D(r)&&r.serverName===e)return!0;if(r){const e=getServerCommandArray(r);if(e)for(const r of s.deniedMcpServers)if(N(r)&&commandArraysMatch(r.serverCommand,e))return!0;const o=getServerUrl(r);if(o)for(const e of s.deniedMcpServers)if(k(e)&&urlMatchesPattern(o,e.serverUrl))return!0}return!1}function isMcpServerAllowedByPolicy(e,r){if(isMcpServerDenied(e,r))return!1;const s=shouldAllowManagedMcpServersOnly()?B("policySettings")??{}:A();if(!s.allowedMcpServers)return!0;if(0===s.allowedMcpServers.length)return!1;const o=s.allowedMcpServers.some(N),t=s.allowedMcpServers.some(k);if(r){const n=getServerCommandArray(r),i=getServerUrl(r);if(n){if(o){for(const e of s.allowedMcpServers)if(N(e)&&commandArraysMatch(e.serverCommand,n))return!0;return!1}for(const r of s.allowedMcpServers)if(D(r)&&r.serverName===e)return!0;return!1}if(i){if(t){for(const e of s.allowedMcpServers)if(k(e)&&urlMatchesPattern(i,e.serverUrl))return!0;return!1}for(const r of s.allowedMcpServers)if(D(r)&&r.serverName===e)return!0;return!1}for(const r of s.allowedMcpServers)if(D(r)&&r.serverName===e)return!0;return!1}for(const r of s.allowedMcpServers)if(D(r)&&r.serverName===e)return!0;return!1}export function filterMcpServersByPolicy(e){const r={},s=[];for(const[o,t]of Object.entries(e)){const e=t;"sdk"===e.type||isMcpServerAllowedByPolicy(o,e)?r[o]=t:s.push(o)}return{allowed:r,blocked:s}}function expandEnvVars(e){const r=[];function expandString(e){const{expanded:s,missingVars:o}=T(e);return r.push(...o),s}let s;switch(e.type){case void 0:case"stdio":{const r=e;s={...r,command:expandString(r.command),args:r.args.map(expandString),env:r.env?a(r.env,expandString):void 0};break}case"sse":case"http":case"ws":{const r=e;s={...r,url:expandString(r.url),headers:r.headers?a(r.headers,expandString):void 0};break}case"sse-ide":case"ws-ide":case"sdk":case"claudeai-proxy":s=e}return{expanded:s,missingVars:[...new Set(r)]}}export async function addMcpConfig(r,s,o){if(r.match(/[^a-zA-Z0-9_-]/))throw new Error(`Invalid name ${r}. Names can only contain letters, numbers, hyphens, and underscores.`);if(g(r))throw new Error(`Cannot add MCP server "${r}": this name is reserved.`);if(e("CHICAGO_MCP")){const{isComputerUseMCPServer:e}=await import("../../utils/computerUse/common.js");if(e(r))throw new Error(`Cannot add MCP server "${r}": this name is reserved.`)}const{isDatabaseMCPServer:t}=await import("../../utils/databaseMcp/common.js");if(t(r))throw new Error(`Cannot add MCP server "${r}": this name is reserved.`);if(doesEnterpriseMcpConfigExist())throw new Error("Cannot add MCP server: enterprise MCP configuration is active and has exclusive control over MCP servers");const n=I().safeParse(s);if(!n.success){const e=n.error.issues.map(e=>`${e.path.join(".")}: ${e.message}`).join(", ");throw new Error(`Invalid configuration: ${e}`)}const i=n.data;if(isMcpServerDenied(r,i))throw new Error(`Cannot add MCP server "${r}": server is explicitly blocked by enterprise policy`);if(!isMcpServerAllowedByPolicy(r,i))throw new Error(`Cannot add MCP server "${r}": not allowed by enterprise policy`);switch(o){case"project":{const{servers:e}=getProjectMcpConfigsFromCwd();if(e[r])throw new Error(`MCP server ${r} already exists in .mcp.json`);break}case"user":{const e=M();if(e.mcpServers?.[r])throw new Error(`MCP server ${r} already exists in user config`);break}case"local":{const e=v();if(e.mcpServers?.[r])throw new Error(`MCP server ${r} already exists in local config`);break}case"dynamic":throw new Error("Cannot add MCP server to scope: dynamic");case"enterprise":throw new Error("Cannot add MCP server to scope: enterprise");case"claudeai":throw new Error("Cannot add MCP server to scope: claudeai")}switch(o){case"project":{const{servers:e}=getProjectMcpConfigsFromCwd(),s={};for(const[r,o]of Object.entries(e)){const{scope:e,...t}=o;s[r]=t}s[r]=i;const o={mcpServers:s};try{await writeMcpjsonFile(o)}catch(e){throw new Error(`Failed to write to .mcp.json: ${e}`)}break}case"user":h(e=>({...e,mcpServers:{...e.mcpServers,[r]:i}}));break;case"local":S(e=>({...e,mcpServers:{...e.mcpServers,[r]:i}}));break;default:throw new Error(`Cannot add MCP server to scope: ${o}`)}}export async function removeMcpConfig(e,r){switch(r){case"project":{const{servers:r}=getProjectMcpConfigsFromCwd();if(!r[e])throw new Error(`No MCP server found with name: ${e} in .mcp.json`);const s={};for(const[o,t]of Object.entries(r))if(o!==e){const{scope:e,...r}=t;s[o]=r}const o={mcpServers:s};try{await writeMcpjsonFile(o)}catch(e){throw new Error(`Failed to remove from .mcp.json: ${e}`)}break}case"user":{const r=M();if(!r.mcpServers?.[e])throw new Error(`No user-scoped MCP server found with name: ${e}`);h(r=>{const{[e]:s,...o}=r.mcpServers??{};return{...r,mcpServers:o}});break}case"local":{const r=v();if(!r.mcpServers?.[e])throw new Error(`No project-local MCP server found with name: ${e}`);S(r=>{const{[e]:s,...o}=r.mcpServers??{};return{...r,mcpServers:o}});break}default:throw new Error(`Cannot remove MCP server from scope: ${r}`)}}export function getProjectMcpConfigsFromCwd(){if(!E("projectSettings"))return{servers:{},errors:[]};const e=f(w(),".mcp.json"),{config:r,errors:s}=parseMcpConfigFromFilePath({filePath:e,expandVars:!0,scope:"project"});if(!r){const r=s.filter(e=>!e.message.startsWith("MCP config file not found"));return r.length>0?(C(`MCP config errors for ${e}: ${V(r.map(e=>e.message))}`,{level:"error"}),{servers:{},errors:r}):{servers:{},errors:[]}}return{servers:r.mcpServers?addScopeToServers(r.mcpServers,"project"):{},errors:s||[]}}export function getMcpConfigsByScope(e){const r={project:"projectSettings",user:"userSettings",local:"localSettings"};if(e in r&&!E(r[e]))return{servers:{},errors:[]};switch(e){case"project":{const r={},s=[],o=[];let t=w();for(;t!==u(t).root;)o.push(t),t=l(t);for(const t of o.reverse()){const o=f(t,".mcp.json"),{config:n,errors:i}=parseMcpConfigFromFilePath({filePath:o,expandVars:!0,scope:"project"});if(!n){const e=i.filter(e=>!e.message.startsWith("MCP config file not found"));e.length>0&&(C(`MCP config errors for ${o}: ${V(e.map(e=>e.message))}`,{level:"error"}),s.push(...e));continue}n.mcpServers&&Object.assign(r,addScopeToServers(n.mcpServers,e)),i.length>0&&s.push(...i)}return{servers:r,errors:s}}case"user":{const r=M().mcpServers;if(!r)return{servers:{},errors:[]};const{config:s,errors:o}=parseMcpConfig({configObject:{mcpServers:r},expandVars:!0,scope:"user"});return{servers:addScopeToServers(s?.mcpServers,e),errors:o}}case"local":{const r=v().mcpServers;if(!r)return{servers:{},errors:[]};const{config:s,errors:o}=parseMcpConfig({configObject:{mcpServers:r},expandVars:!0,scope:"local"});return{servers:addScopeToServers(s?.mcpServers,e),errors:o}}case"enterprise":{const r=getEnterpriseMcpFilePath(),{config:s,errors:o}=parseMcpConfigFromFilePath({filePath:r,expandVars:!0,scope:"enterprise"});if(!s){const e=o.filter(e=>!e.message.startsWith("MCP config file not found"));return e.length>0?(C(`Enterprise MCP config errors for ${r}: ${V(e.map(e=>e.message))}`,{level:"error"}),{servers:{},errors:e}):{servers:{},errors:[]}}return{servers:addScopeToServers(s.mcpServers,e),errors:o}}}}export function getMcpConfigByName(e){const{servers:r}=getMcpConfigsByScope("enterprise");if(F("mcp"))return r[e]??null;const{servers:s}=getMcpConfigsByScope("user"),{servers:o}=getMcpConfigsByScope("project"),{servers:t}=getMcpConfigsByScope("local");return r[e]?r[e]:t[e]?t[e]:o[e]?o[e]:s[e]?s[e]:null}export async function getClaudeCodeMcpConfigs(e={},r=Promise.resolve({})){const{servers:s}=getMcpConfigsByScope("enterprise");if(doesEnterpriseMcpConfigExist()){const e={};for(const[r,o]of Object.entries(s))isMcpServerAllowedByPolicy(r,o)&&(e[r]=o);return{servers:e,errors:[]}}const o=F("mcp"),t={servers:{}},{servers:n}=o?t:getMcpConfigsByScope("user"),{servers:i}=o?t:getMcpConfigsByScope("project"),{servers:c}=o?t:getMcpConfigsByScope("local"),a={},p=await $(),l=[];if(p.errors.length>0)for(const e of p.errors)if("mcp-config-invalid"===e.type||"mcpb-download-failed"===e.type||"mcpb-extract-failed"===e.type||"mcpb-invalid-manifest"===e.type){const r=`Plugin MCP loading error - ${e.type}: ${m(e)}`;b(new Error(r))}else{const r=e.type;C(`Plugin not available for MCP: ${e.source} - error type: ${r}`)}const f=await Promise.all(p.enabled.map(e=>x(e,l)));for(const e of f)e&&Object.assign(a,e);if(l.length>0)for(const e of l){const r=`Plugin MCP server error - ${e.type}: ${m(e)}`;b(new Error(r))}const u={};for(const[e,r]of Object.entries(i))"approved"===R(e)&&(u[e]=r);const d=await r,g={};for(const[r,s]of Object.entries({...n,...u,...c,...e,...d}))!isMcpServerDisabled(r)&&isMcpServerAllowedByPolicy(r,s)&&(g[r]=s);const v={},M={};for(const[e,r]of Object.entries(a))isMcpServerDisabled(e)||!isMcpServerAllowedByPolicy(e,r)?M[e]=r:v[e]=r;const{servers:S,suppressed:h}=dedupPluginMcpServers(v,g);Object.assign(S,M);for(const{name:e,duplicateOf:r}of h){const s=e.split(":");"plugin"!==s[0]||s.length<3||l.push({type:"mcp-server-suppressed-duplicate",source:e,plugin:s[1],serverName:s.slice(2).join(":"),duplicateOf:r})}const w=Object.assign({},S,n,u,c),y={};for(const[e,r]of Object.entries(w))isMcpServerAllowedByPolicy(e,r)&&(y[e]=r);return{servers:y,errors:l}}export async function getAllMcpConfigs(){if(doesEnterpriseMcpConfigExist())return getClaudeCodeMcpConfigs();const e=_(),{servers:r,errors:s}=await getClaudeCodeMcpConfigs({},e),{allowed:o}=filterMcpServersByPolicy(await e),{servers:t}=dedupClaudeAiMcpServers(o,r);return{servers:Object.assign({},t,r),errors:s}}export function parseMcpConfig(e){const{configObject:r,expandVars:s,scope:o,filePath:t}=e,n=W().safeParse(r);if(!n.success)return{config:null,errors:n.error.issues.map(e=>({...t&&{file:t},path:e.path.join("."),message:"Does not adhere to MCP server configuration schema",mcpErrorMetadata:{scope:o,severity:"fatal"}}))};const i=[],c={};for(const[e,r]of Object.entries(n.data.mcpServers)){let n=r;if(s){const{expanded:s,missingVars:c}=expandEnvVars(r);c.length>0&&i.push({...t&&{file:t},path:`mcpServers.${e}`,message:`Missing environment variables: ${c.join(", ")}`,suggestion:`Set the following environment variables: ${c.join(", ")}`,mcpErrorMetadata:{scope:o,serverName:e,severity:"warning"}}),n=s}"windows"!==d()||n.type&&"stdio"!==n.type||"npx"!==n.command&&!n.command.endsWith("\\npx")&&!n.command.endsWith("/npx")||i.push({...t&&{file:t},path:`mcpServers.${e}`,message:"Windows requires 'cmd /c' wrapper to execute npx",suggestion:'Change command to "cmd" with args ["/c", "npx", ...]',mcpErrorMetadata:{scope:o,serverName:e,severity:"warning"}}),c[e]=n}return{config:{mcpServers:c},errors:i}}export function parseMcpConfigFromFilePath(e){const{filePath:r,expandVars:s,scope:o}=e,t=j();let n;try{n=t.readFileSync(r,{encoding:"utf8"})}catch(e){return"ENOENT"===y(e)?{config:null,errors:[{file:r,path:"",message:`MCP config file not found: ${r}`,suggestion:"Check that the file path is correct",mcpErrorMetadata:{scope:o,severity:"fatal"}}]}:(C(`MCP config read error for ${r} (scope=${o}): ${e}`,{level:"error"}),{config:null,errors:[{file:r,path:"",message:`Failed to read file: ${e}`,suggestion:"Check file permissions and ensure the file exists",mcpErrorMetadata:{scope:o,severity:"fatal"}}]})}const i=P(n);return i?parseMcpConfig({configObject:i,expandVars:s,scope:o,filePath:r}):(C(`MCP config is not valid JSON: ${r} (scope=${o}, length=${n.length}, first100=${V(n.slice(0,100))})`,{level:"error"}),{config:null,errors:[{file:r,path:"",message:"MCP config is not a valid JSON",suggestion:"Fix the JSON syntax errors in the file",mcpErrorMetadata:{scope:o,severity:"fatal"}}]})}export const doesEnterpriseMcpConfigExist=p(()=>{const{config:e}=parseMcpConfigFromFilePath({filePath:getEnterpriseMcpFilePath(),expandVars:!0,scope:"enterprise"});return null!==e});export function shouldAllowManagedMcpServersOnly(){return!0===B("policySettings")?.allowManagedMcpServersOnly}export function areMcpConfigsAllowedWithEnterpriseMcpConfig(e){return Object.values(e).every(e=>"sdk"===e.type&&"claude-vscode"===e.name)}const z=e("CHICAGO_MCP")?s("../../utils/computerUse/common.js").COMPUTER_USE_MCP_SERVER_NAME:null;function isDefaultDisabledBuiltin(e){return null!==z&&e===z}export function isMcpServerDisabled(e){const r=v();if(isDefaultDisabledBuiltin(e)){return!(r.enabledMcpServers||[]).includes(e)}return(r.disabledMcpServers||[]).includes(e)}function toggleMembership(e,r,s){return e.includes(r)===s?e:s?[...e,r]:e.filter(e=>e!==r)}export function setMcpServerEnabled(e,r){const s=isDefaultDisabledBuiltin(e)&&isMcpServerDisabled(e)===r;S(s=>{if(isDefaultDisabledBuiltin(e)){const o=s.enabledMcpServers||[],t=toggleMembership(o,e,r);return t===o?s:{...s,enabledMcpServers:t}}const o=s.disabledMcpServers||[],t=toggleMembership(o,e,!r);return t===o?s:{...s,disabledMcpServers:t}}),s&&U("tengu_builtin_mcp_toggle",{serverName:e,enabled:r})}
|
|
1
|
+
import{feature as e}from"../../recovery/bunBundleShim.js";import{createRequire as r}from"module";const s=r(import.meta.url);import{chmod as o,open as t,rename as n,stat as i,unlink as c}from"fs/promises";import a from"lodash-es/mapValues.js";import p from"lodash-es/memoize.js";import{dirname as l,join as f,parse as u}from"path";import{getPlatform as d}from"../../utils/platform.js";import{getPluginErrorMessage as m}from"../../types/plugin.js";import{isClaudeInChromeMCPServer as g}from"../../utils/claudeInChrome/common.js";import{getCurrentProjectConfig as v,getGlobalConfig as M,saveCurrentProjectConfig as S,saveGlobalConfig as h}from"../../utils/config.js";import{getCwd as w}from"../../utils/cwd.js";import{logForDebugging as C}from"../../utils/debug.js";import{getErrnoCode as y}from"../../utils/errors.js";import{getFsImplementation as j}from"../../utils/fsOperations.js";import{safeParseJSON as P}from"../../utils/json.js";import{logError as b}from"../../utils/log.js";import{getPluginMcpServers as x}from"../../utils/plugins/mcpPluginIntegration.js";import{loadAllPluginsCacheOnly as $}from"../../utils/plugins/pluginLoader.js";import{isSettingSourceEnabled as E}from"../../utils/settings/constants.js";import{getManagedFilePath as O}from"../../utils/settings/managedPath.js";import{isRestrictedToPluginOnly as F}from"../../utils/settings/pluginOnlyPolicy.js";import{getInitialSettings as A,getSettingsForSource as B}from"../../utils/settings/settings.js";import{isMcpServerCommandEntry as N,isMcpServerNameEntry as D,isMcpServerUrlEntry as k}from"../../utils/settings/types.js";import{jsonStringify as V}from"../../utils/slowOperations.js";import{logEvent as U}from"../analytics/index.js";import{fetchClaudeAIMcpConfigsIfEligible as _}from"./claudeai.js";import{expandEnvVarsInString as T}from"./envExpansion.js";import{McpJsonConfigSchema as W,McpServerConfigSchema as I}from"./types.js";import{getProjectMcpServerStatus as R}from"./utils.js";export function getEnterpriseMcpFilePath(){return f(O(),"managed-mcp.json")}function addScopeToServers(e,r){if(!e)return{};const s={};for(const[o,t]of Object.entries(e))s[o]={...t,scope:r};return s}async function writeMcpjsonFile(e){const r=f(w(),".mcp.json");let s;try{s=(await i(r)).mode}catch(e){if("ENOENT"!==y(e))throw e}const a=`${r}.tmp.${process.pid}.${Date.now()}`,p=await t(a,"w",s??420);try{await p.writeFile(V(e,null,2),{encoding:"utf8"}),await p.datasync()}finally{await p.close()}try{void 0!==s&&await o(a,s),await n(a,r)}catch(e){try{await c(a)}catch{}throw e}}function getServerCommandArray(e){if(void 0!==e.type&&"stdio"!==e.type)return null;const r=e;return[r.command,...r.args??[]]}function commandArraysMatch(e,r){return e.length===r.length&&e.every((e,s)=>e===r[s])}function getServerUrl(e){return"url"in e?e.url:null}const J=["/v2/session_ingress/shttp/mcp/","/v2/ccr-sessions/"];export function unwrapCcrProxyUrl(e){if(!J.some(r=>e.includes(r)))return e;try{const r=new URL(e);return r.searchParams.get("mcp_url")||e}catch{return e}}export function getMcpServerSignature(e){const r=getServerCommandArray(e);if(r)return`stdio:${V(r)}`;const s=getServerUrl(e);return s?`url:${unwrapCcrProxyUrl(s)}`:null}export function dedupPluginMcpServers(e,r){const s=new Map;for(const[e,o]of Object.entries(r)){const r=getMcpServerSignature(o);r&&!s.has(r)&&s.set(r,e)}const o={},t=[],n=new Map;for(const[r,i]of Object.entries(e)){const e=getMcpServerSignature(i);if(null===e){o[r]=i;continue}const c=s.get(e);if(void 0!==c){C(`Suppressing plugin MCP server "${r}": duplicates manually-configured "${c}"`),t.push({name:r,duplicateOf:c});continue}const a=n.get(e);void 0===a?(n.set(e,r),o[r]=i):(C(`Suppressing plugin MCP server "${r}": duplicates earlier plugin server "${a}"`),t.push({name:r,duplicateOf:a}))}return{servers:o,suppressed:t}}export function dedupClaudeAiMcpServers(e,r){const s=new Map;for(const[e,o]of Object.entries(r)){if(isMcpServerDisabled(e))continue;const r=getMcpServerSignature(o);r&&!s.has(r)&&s.set(r,e)}const o={},t=[];for(const[r,n]of Object.entries(e)){const e=getMcpServerSignature(n),i=null!==e?s.get(e):void 0;void 0===i?o[r]=n:(C(`Suppressing claude.ai connector "${r}": duplicates manually-configured "${i}"`),t.push({name:r,duplicateOf:i}))}return{servers:o,suppressed:t}}function urlMatchesPattern(e,r){const s=function(e){const r=e.replace(/[.+?^${}()|[\]\\]/g,"\\$&").replace(/\*/g,".*");return new RegExp(`^${r}$`)}(r);return s.test(e)}function isMcpServerDenied(e,r){const s=A();if(!s.deniedMcpServers)return!1;for(const r of s.deniedMcpServers)if(D(r)&&r.serverName===e)return!0;if(r){const e=getServerCommandArray(r);if(e)for(const r of s.deniedMcpServers)if(N(r)&&commandArraysMatch(r.serverCommand,e))return!0;const o=getServerUrl(r);if(o)for(const e of s.deniedMcpServers)if(k(e)&&urlMatchesPattern(o,e.serverUrl))return!0}return!1}function isMcpServerAllowedByPolicy(e,r){if(isMcpServerDenied(e,r))return!1;const s=shouldAllowManagedMcpServersOnly()?B("policySettings")??{}:A();if(!s.allowedMcpServers)return!0;if(0===s.allowedMcpServers.length)return!1;const o=s.allowedMcpServers.some(N),t=s.allowedMcpServers.some(k);if(r){const n=getServerCommandArray(r),i=getServerUrl(r);if(n){if(o){for(const e of s.allowedMcpServers)if(N(e)&&commandArraysMatch(e.serverCommand,n))return!0;return!1}for(const r of s.allowedMcpServers)if(D(r)&&r.serverName===e)return!0;return!1}if(i){if(t){for(const e of s.allowedMcpServers)if(k(e)&&urlMatchesPattern(i,e.serverUrl))return!0;return!1}for(const r of s.allowedMcpServers)if(D(r)&&r.serverName===e)return!0;return!1}for(const r of s.allowedMcpServers)if(D(r)&&r.serverName===e)return!0;return!1}for(const r of s.allowedMcpServers)if(D(r)&&r.serverName===e)return!0;return!1}export function filterMcpServersByPolicy(e){const r={},s=[];for(const[o,t]of Object.entries(e)){const e=t;"sdk"===e.type||isMcpServerAllowedByPolicy(o,e)?r[o]=t:s.push(o)}return{allowed:r,blocked:s}}function expandEnvVars(e){const r=[];function expandString(e){const{expanded:s,missingVars:o}=T(e);return r.push(...o),s}let s;switch(e.type){case void 0:case"stdio":{const r=e;s={...r,command:expandString(r.command),args:r.args.map(expandString),env:r.env?a(r.env,expandString):void 0};break}case"sse":case"http":case"ws":{const r=e;s={...r,url:expandString(r.url),headers:r.headers?a(r.headers,expandString):void 0};break}case"sse-ide":case"ws-ide":case"sdk":case"claudeai-proxy":s=e}return{expanded:s,missingVars:[...new Set(r)]}}export async function addMcpConfig(r,s,o){if(r.match(/[^a-zA-Z0-9_-]/))throw new Error(`Invalid name ${r}. Names can only contain letters, numbers, hyphens, and underscores.`);if(g(r))throw new Error(`Cannot add MCP server "${r}": this name is reserved.`);if(e("CHICAGO_MCP")){const{isComputerUseMCPServer:e}=await import("../../utils/computerUse/common.js");if(e(r))throw new Error(`Cannot add MCP server "${r}": this name is reserved.`)}const{isDatabaseMCPServer:t}=await import("../../utils/databaseMcp/common.js");if(t(r))throw new Error(`Cannot add MCP server "${r}": this name is reserved.`);const{isComputerControlMCPServer:n}=await import("../../utils/computerControlMcp/common.js");if(n(r))throw new Error(`Cannot add MCP server "${r}": this name is reserved.`);if(doesEnterpriseMcpConfigExist())throw new Error("Cannot add MCP server: enterprise MCP configuration is active and has exclusive control over MCP servers");const i=I().safeParse(s);if(!i.success){const e=i.error.issues.map(e=>`${e.path.join(".")}: ${e.message}`).join(", ");throw new Error(`Invalid configuration: ${e}`)}const c=i.data;if(isMcpServerDenied(r,c))throw new Error(`Cannot add MCP server "${r}": server is explicitly blocked by enterprise policy`);if(!isMcpServerAllowedByPolicy(r,c))throw new Error(`Cannot add MCP server "${r}": not allowed by enterprise policy`);switch(o){case"project":{const{servers:e}=getProjectMcpConfigsFromCwd();if(e[r])throw new Error(`MCP server ${r} already exists in .mcp.json`);break}case"user":{const e=M();if(e.mcpServers?.[r])throw new Error(`MCP server ${r} already exists in user config`);break}case"local":{const e=v();if(e.mcpServers?.[r])throw new Error(`MCP server ${r} already exists in local config`);break}case"dynamic":throw new Error("Cannot add MCP server to scope: dynamic");case"enterprise":throw new Error("Cannot add MCP server to scope: enterprise");case"claudeai":throw new Error("Cannot add MCP server to scope: claudeai")}switch(o){case"project":{const{servers:e}=getProjectMcpConfigsFromCwd(),s={};for(const[r,o]of Object.entries(e)){const{scope:e,...t}=o;s[r]=t}s[r]=c;const o={mcpServers:s};try{await writeMcpjsonFile(o)}catch(e){throw new Error(`Failed to write to .mcp.json: ${e}`)}break}case"user":h(e=>({...e,mcpServers:{...e.mcpServers,[r]:c}}));break;case"local":S(e=>({...e,mcpServers:{...e.mcpServers,[r]:c}}));break;default:throw new Error(`Cannot add MCP server to scope: ${o}`)}}export async function removeMcpConfig(e,r){switch(r){case"project":{const{servers:r}=getProjectMcpConfigsFromCwd();if(!r[e])throw new Error(`No MCP server found with name: ${e} in .mcp.json`);const s={};for(const[o,t]of Object.entries(r))if(o!==e){const{scope:e,...r}=t;s[o]=r}const o={mcpServers:s};try{await writeMcpjsonFile(o)}catch(e){throw new Error(`Failed to remove from .mcp.json: ${e}`)}break}case"user":{const r=M();if(!r.mcpServers?.[e])throw new Error(`No user-scoped MCP server found with name: ${e}`);h(r=>{const{[e]:s,...o}=r.mcpServers??{};return{...r,mcpServers:o}});break}case"local":{const r=v();if(!r.mcpServers?.[e])throw new Error(`No project-local MCP server found with name: ${e}`);S(r=>{const{[e]:s,...o}=r.mcpServers??{};return{...r,mcpServers:o}});break}default:throw new Error(`Cannot remove MCP server from scope: ${r}`)}}export function getProjectMcpConfigsFromCwd(){if(!E("projectSettings"))return{servers:{},errors:[]};const e=f(w(),".mcp.json"),{config:r,errors:s}=parseMcpConfigFromFilePath({filePath:e,expandVars:!0,scope:"project"});if(!r){const r=s.filter(e=>!e.message.startsWith("MCP config file not found"));return r.length>0?(C(`MCP config errors for ${e}: ${V(r.map(e=>e.message))}`,{level:"error"}),{servers:{},errors:r}):{servers:{},errors:[]}}return{servers:r.mcpServers?addScopeToServers(r.mcpServers,"project"):{},errors:s||[]}}export function getMcpConfigsByScope(e){const r={project:"projectSettings",user:"userSettings",local:"localSettings"};if(e in r&&!E(r[e]))return{servers:{},errors:[]};switch(e){case"project":{const r={},s=[],o=[];let t=w();for(;t!==u(t).root;)o.push(t),t=l(t);for(const t of o.reverse()){const o=f(t,".mcp.json"),{config:n,errors:i}=parseMcpConfigFromFilePath({filePath:o,expandVars:!0,scope:"project"});if(!n){const e=i.filter(e=>!e.message.startsWith("MCP config file not found"));e.length>0&&(C(`MCP config errors for ${o}: ${V(e.map(e=>e.message))}`,{level:"error"}),s.push(...e));continue}n.mcpServers&&Object.assign(r,addScopeToServers(n.mcpServers,e)),i.length>0&&s.push(...i)}return{servers:r,errors:s}}case"user":{const r=M().mcpServers;if(!r)return{servers:{},errors:[]};const{config:s,errors:o}=parseMcpConfig({configObject:{mcpServers:r},expandVars:!0,scope:"user"});return{servers:addScopeToServers(s?.mcpServers,e),errors:o}}case"local":{const r=v().mcpServers;if(!r)return{servers:{},errors:[]};const{config:s,errors:o}=parseMcpConfig({configObject:{mcpServers:r},expandVars:!0,scope:"local"});return{servers:addScopeToServers(s?.mcpServers,e),errors:o}}case"enterprise":{const r=getEnterpriseMcpFilePath(),{config:s,errors:o}=parseMcpConfigFromFilePath({filePath:r,expandVars:!0,scope:"enterprise"});if(!s){const e=o.filter(e=>!e.message.startsWith("MCP config file not found"));return e.length>0?(C(`Enterprise MCP config errors for ${r}: ${V(e.map(e=>e.message))}`,{level:"error"}),{servers:{},errors:e}):{servers:{},errors:[]}}return{servers:addScopeToServers(s.mcpServers,e),errors:o}}}}export function getMcpConfigByName(e){const{servers:r}=getMcpConfigsByScope("enterprise");if(F("mcp"))return r[e]??null;const{servers:s}=getMcpConfigsByScope("user"),{servers:o}=getMcpConfigsByScope("project"),{servers:t}=getMcpConfigsByScope("local");return r[e]?r[e]:t[e]?t[e]:o[e]?o[e]:s[e]?s[e]:null}export async function getClaudeCodeMcpConfigs(e={},r=Promise.resolve({})){const{servers:s}=getMcpConfigsByScope("enterprise");if(doesEnterpriseMcpConfigExist()){const e={};for(const[r,o]of Object.entries(s))isMcpServerAllowedByPolicy(r,o)&&(e[r]=o);return{servers:e,errors:[]}}const o=F("mcp"),t={servers:{}},{servers:n}=o?t:getMcpConfigsByScope("user"),{servers:i}=o?t:getMcpConfigsByScope("project"),{servers:c}=o?t:getMcpConfigsByScope("local"),a={},p=await $(),l=[];if(p.errors.length>0)for(const e of p.errors)if("mcp-config-invalid"===e.type||"mcpb-download-failed"===e.type||"mcpb-extract-failed"===e.type||"mcpb-invalid-manifest"===e.type){const r=`Plugin MCP loading error - ${e.type}: ${m(e)}`;b(new Error(r))}else{const r=e.type;C(`Plugin not available for MCP: ${e.source} - error type: ${r}`)}const f=await Promise.all(p.enabled.map(e=>x(e,l)));for(const e of f)e&&Object.assign(a,e);if(l.length>0)for(const e of l){const r=`Plugin MCP server error - ${e.type}: ${m(e)}`;b(new Error(r))}const u={};for(const[e,r]of Object.entries(i))"approved"===R(e)&&(u[e]=r);const d=await r,g={};for(const[r,s]of Object.entries({...n,...u,...c,...e,...d}))!isMcpServerDisabled(r)&&isMcpServerAllowedByPolicy(r,s)&&(g[r]=s);const v={},M={};for(const[e,r]of Object.entries(a))isMcpServerDisabled(e)||!isMcpServerAllowedByPolicy(e,r)?M[e]=r:v[e]=r;const{servers:S,suppressed:h}=dedupPluginMcpServers(v,g);Object.assign(S,M);for(const{name:e,duplicateOf:r}of h){const s=e.split(":");"plugin"!==s[0]||s.length<3||l.push({type:"mcp-server-suppressed-duplicate",source:e,plugin:s[1],serverName:s.slice(2).join(":"),duplicateOf:r})}const w=Object.assign({},S,n,u,c),y={};for(const[e,r]of Object.entries(w))isMcpServerAllowedByPolicy(e,r)&&(y[e]=r);return{servers:y,errors:l}}export async function getAllMcpConfigs(){if(doesEnterpriseMcpConfigExist())return getClaudeCodeMcpConfigs();const e=_(),{servers:r,errors:s}=await getClaudeCodeMcpConfigs({},e),{allowed:o}=filterMcpServersByPolicy(await e),{servers:t}=dedupClaudeAiMcpServers(o,r);return{servers:Object.assign({},t,r),errors:s}}export function parseMcpConfig(e){const{configObject:r,expandVars:s,scope:o,filePath:t}=e,n=W().safeParse(r);if(!n.success)return{config:null,errors:n.error.issues.map(e=>({...t&&{file:t},path:e.path.join("."),message:"Does not adhere to MCP server configuration schema",mcpErrorMetadata:{scope:o,severity:"fatal"}}))};const i=[],c={};for(const[e,r]of Object.entries(n.data.mcpServers)){let n=r;if(s){const{expanded:s,missingVars:c}=expandEnvVars(r);c.length>0&&i.push({...t&&{file:t},path:`mcpServers.${e}`,message:`Missing environment variables: ${c.join(", ")}`,suggestion:`Set the following environment variables: ${c.join(", ")}`,mcpErrorMetadata:{scope:o,serverName:e,severity:"warning"}}),n=s}"windows"!==d()||n.type&&"stdio"!==n.type||"npx"!==n.command&&!n.command.endsWith("\\npx")&&!n.command.endsWith("/npx")||i.push({...t&&{file:t},path:`mcpServers.${e}`,message:"Windows requires 'cmd /c' wrapper to execute npx",suggestion:'Change command to "cmd" with args ["/c", "npx", ...]',mcpErrorMetadata:{scope:o,serverName:e,severity:"warning"}}),c[e]=n}return{config:{mcpServers:c},errors:i}}export function parseMcpConfigFromFilePath(e){const{filePath:r,expandVars:s,scope:o}=e,t=j();let n;try{n=t.readFileSync(r,{encoding:"utf8"})}catch(e){return"ENOENT"===y(e)?{config:null,errors:[{file:r,path:"",message:`MCP config file not found: ${r}`,suggestion:"Check that the file path is correct",mcpErrorMetadata:{scope:o,severity:"fatal"}}]}:(C(`MCP config read error for ${r} (scope=${o}): ${e}`,{level:"error"}),{config:null,errors:[{file:r,path:"",message:`Failed to read file: ${e}`,suggestion:"Check file permissions and ensure the file exists",mcpErrorMetadata:{scope:o,severity:"fatal"}}]})}const i=P(n);return i?parseMcpConfig({configObject:i,expandVars:s,scope:o,filePath:r}):(C(`MCP config is not valid JSON: ${r} (scope=${o}, length=${n.length}, first100=${V(n.slice(0,100))})`,{level:"error"}),{config:null,errors:[{file:r,path:"",message:"MCP config is not a valid JSON",suggestion:"Fix the JSON syntax errors in the file",mcpErrorMetadata:{scope:o,severity:"fatal"}}]})}export const doesEnterpriseMcpConfigExist=p(()=>{const{config:e}=parseMcpConfigFromFilePath({filePath:getEnterpriseMcpFilePath(),expandVars:!0,scope:"enterprise"});return null!==e});export function shouldAllowManagedMcpServersOnly(){return!0===B("policySettings")?.allowManagedMcpServersOnly}export function areMcpConfigsAllowedWithEnterpriseMcpConfig(e){return Object.values(e).every(e=>"sdk"===e.type&&"claude-vscode"===e.name)}const z=e("CHICAGO_MCP")?s("../../utils/computerUse/common.js").COMPUTER_USE_MCP_SERVER_NAME:null;function isDefaultDisabledBuiltin(e){return null!==z&&e===z}export function isMcpServerDisabled(e){const r=v();if(isDefaultDisabledBuiltin(e)){return!(r.enabledMcpServers||[]).includes(e)}return(r.disabledMcpServers||[]).includes(e)}function toggleMembership(e,r,s){return e.includes(r)===s?e:s?[...e,r]:e.filter(e=>e!==r)}export function setMcpServerEnabled(e,r){const s=isDefaultDisabledBuiltin(e)&&isMcpServerDisabled(e)===r;S(s=>{if(isDefaultDisabledBuiltin(e)){const o=s.enabledMcpServers||[],t=toggleMembership(o,e,r);return t===o?s:{...s,enabledMcpServers:t}}const o=s.disabledMcpServers||[],t=toggleMembership(o,e,!r);return t===o?s:{...s,disabledMcpServers:t}}),s&&U("tengu_builtin_mcp_toggle",{serverName:e,enabled:r})}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{getProviderProfile as e}from"../../../utils/model/providerProfiles.js";import{getSecureStorage as t}from"../../../utils/secureStorage/index.js";const o={claude:"https://api.anthropic.com",openai:"https://api.openai.com/v1",openrouter:"https://openrouter.ai/api/v1",ollama:"http://localhost:11434/v1","ollama-cloud":"http://localhost:11434/v1","gemini-api":"https://generativelanguage.googleapis.com/v1beta/openai","gemini-google":"https://generativelanguage.googleapis.com/v1beta/openai",zai:"https://api.z.ai/api/coding/paas/v4",minimax:"https://api.minimax.io/anthropic"};function trimTrailingSlash(e){return e.endsWith("/")?e.slice(0,-1):e}function tryParseJson(e){try{return JSON.parse(e)}catch{return null}}function resolveCredential(e,o){if("ollama"===e)return{kind:"none",token:null};const r=function(){try{return t().read()??{}}catch{return{}}}(),n=r.providerProfileApiKeys?.[o];if(n?.trim())return{kind:"api-key",token:n.trim()};const a=r.providerProfileOauth?.[o]?.accessToken;if(a?.trim())return{kind:"oauth",token:a.trim()};const i=r.providerApiKeys?.[e];if(i?.trim())return{kind:"api-key",token:i.trim()};const s="claude"===e?r.claudeAiOauth?.accessToken:"openai"===e?r.openAiOauth?.accessToken:null;return s?.trim()?{kind:"oauth",token:s.trim()}:{kind:"none",token:null}}function buildSystemPrompt(e){const t=e.domain?.domainName??e.task.scopeType,o=e.capabilities.length>0?e.capabilities.join(", "):"sin declarar";return[e.agent.systemPrompt?.trim()||`Eres ${e.agent.name}, agente del equipo ${t}.`,`Rol: ${e.agent.roleKind??"general"}.`,`Capacidades: ${o}.`,"Responde con un reporte ejecutivo y accionable para el orquestador global.","No modifiques archivos. Solo entrega resultado, riesgos y siguientes pasos."].join("\n")}function buildUserPrompt(e){const t=e.domain?.domainName??e.task.scopeType,o=e.members.length>0?e.members.map(e=>`${e.agentId}:${e.duty??"member"}`).join(", "):"sin miembros internos";return[`Objetivo global: ${e.run.goal}`,`Equipo: ${t}`,`Tarea: ${e.task.title}`,`Instrucciones: ${e.task.instructions}`,`Miembros del escuadron: ${o}`,"","Entrega:","1. Resultado del equipo.","2. Decisiones tomadas.","3. Riesgos o bloqueos.","4. Siguientes pasos recomendados."].join("\n")}async function postJson(e,t,o,r=3){let n=null;for(let a=0;a<=r;a++){if(a>0){const e=1e3*Math.pow(2,a)+1e3*Math.random();await new Promise(t=>setTimeout(t,e))}try{const r=await fetch(e,{method:"POST",headers:{"Content-Type":"application/json",...t},body:JSON.stringify(o)}),a=await r.text(),i=tryParseJson(a)??a;if(!r.ok){if(n={status:r.status,error:"string"==typeof i?i:JSON.stringify(i)},429===r.status||r.status>=500)continue;return{ok:!1,...n}}return{ok:!0,data:i}}catch(e){n={status:0,error:e instanceof Error?e.message:String(e)};continue}}return{ok:!1,...n}}async function executeOpenAICompatible(e,t,o,r){const n={};r.token&&(n.Authorization=`Bearer ${r.token}`),"openrouter"===e.workspace.provider&&(n["HTTP-Referer"]="https://context.iaforged.com",n["X-Title"]="Context Code");const a=await postJson(`${trimTrailingSlash(o)}/chat/completions`,n,{model:t,temperature:.2,messages:[{role:"system",content:buildSystemPrompt(e)},{role:"user",content:buildUserPrompt(e)}]});if(!a.ok)return{ok:!1,error:`HTTP ${a.status}: ${a.error}`};const i=function(e){if(!e||"object"!=typeof e)return null;const t=e,o=t.choices?.[0]?.message?.content??t.choices?.[0]?.text;return"string"==typeof o?o:Array.isArray(o)?o.map(e=>"string"==typeof e?e:"object"==typeof e&&e&&"text"in e?String(e.text??""):"").filter(Boolean).join("\n"):"string"==typeof t.output_text?t.output_text:null}(a.data);return i?.trim()?{ok:!0,output:i}:{ok:!1,error:"El proveedor no devolvio contenido de texto."}}async function executeAnthropicCompatible(e,t,o,r){const n={"anthropic-version":"2023-06-01"};"api-key"===r.kind&&r.token?(n["x-api-key"]=r.token,"minimax"===e.workspace.provider&&(n.Authorization=`Bearer ${r.token}`)):"oauth"===r.kind&&r.token&&(n.Authorization=`Bearer ${r.token}`);const a=await postJson(`${trimTrailingSlash(o)}/v1/messages`,n,{model:t,max_tokens:2048,system:buildSystemPrompt(e),messages:[{role:"user",content:buildUserPrompt(e)}]});if(!a.ok)return{ok:!1,error:`HTTP ${a.status}: ${a.error}`};const i=function(e){if(!e||"object"!=typeof e)return null;const t=e;return t.content?.map(e=>"text"===e.type&&"string"==typeof e.text?e.text:"").filter(Boolean).join("\n")||null}(a.data);return i?.trim()?{ok:!0,output:i}:{ok:!1,error:"El proveedor no devolvio contenido de texto."}}export async function executeAgentDomainTask(t){const r=e(t.agent.profileId),n=t.workspace.provider,a=function(t){const o=e(t.agent.profileId);return t.agent.modelOverride?.trim()||o?.lastModel?.trim()||null}(t);if(!r)return{status:"blocked",summary:`No existe el perfil ${t.agent.profileId} para el agente ${t.agent.name}.`,output:null,provider:n,profileId:t.agent.profileId,model:a,messageType:"task.blocked",blockers:["Perfil del agente no encontrado."],metadata:{reason:"missing-profile"}};if(r.provider!==n)return{status:"blocked",summary:`El perfil ${r.id} pertenece a ${r.provider}, pero el workspace es ${n}.`,output:null,provider:n,profileId:r.id,model:a,messageType:"task.blocked",blockers:["Perfil y workspace no coinciden."],metadata:{reason:"provider-profile-mismatch",profileProvider:r.provider}};if(!a)return{status:"blocked",summary:`El agente ${t.agent.name} no tiene modelo configurado.`,output:null,provider:n,profileId:r.id,model:a,messageType:"task.blocked",blockers:["Modelo no configurado."],metadata:{reason:"missing-model"}};const i=resolveCredential(n,r.id);if("ollama"!==n&&"none"===i.kind)return{status:"blocked",summary:`El perfil ${r.id} no tiene credenciales para ${n}.`,output:null,provider:n,profileId:r.id,model:a,messageType:"task.blocked",blockers:["Credenciales no configuradas."],metadata:{reason:"missing-credentials"}};const s=r.baseUrl||o[n];try{const e="claude"===n||"minimax"===n?await executeAnthropicCompatible(t,a,s,i):await executeOpenAICompatible(t,a,s,i);if(!e.ok)return{status:"failed",summary:`El agente ${t.agent.name} fallo ejecutando ${a}: ${e.error}`,output:null,provider:n,profileId:r.id,model:a,messageType:"task.failed",blockers:[e.error],metadata:{reason:"provider-error",baseUrl:s}};const o=function(e,t=12e3){return e.length>t?`${e.slice(0,t)}\n\n[output truncado a ${t} caracteres]`:e}(e.output.trim());return{status:"completed",summary:o.split("\n").find(e=>e.trim())?.trim()||o,output:o,provider:n,profileId:r.id,model:a,messageType:"task.completed",blockers:[],metadata:{baseUrl:s,credentialKind:i.kind}}}catch(e){const o=function(e){return e instanceof Error?e.message:String(e)}(e);return{status:"failed",summary:`El agente ${t.agent.name} no pudo ejecutar la tarea: ${o}`,output:null,provider:n,profileId:r.id,model:a,messageType:"task.failed",blockers:[o],metadata:{reason:"execution-exception",baseUrl:s}}}}
|
|
1
|
+
import{getProviderProfile as e}from"../../../utils/model/providerProfiles.js";import{getSecureStorage as t}from"../../../utils/secureStorage/index.js";const o={claude:"https://api.anthropic.com",openai:"https://api.openai.com/v1",openrouter:"https://openrouter.ai/api/v1",ollama:"http://localhost:11434/v1","ollama-cloud":"http://localhost:11434/v1",lmstudio:"http://localhost:1234/v1","gemini-api":"https://generativelanguage.googleapis.com/v1beta/openai","gemini-google":"https://generativelanguage.googleapis.com/v1beta/openai",zai:"https://api.z.ai/api/coding/paas/v4",minimax:"https://api.minimax.io/anthropic"};function trimTrailingSlash(e){return e.endsWith("/")?e.slice(0,-1):e}function tryParseJson(e){try{return JSON.parse(e)}catch{return null}}function resolveCredential(e,o){if("ollama"===e)return{kind:"none",token:null};const r=function(){try{return t().read()??{}}catch{return{}}}(),n=r.providerProfileApiKeys?.[o];if(n?.trim())return{kind:"api-key",token:n.trim()};const a=r.providerProfileOauth?.[o]?.accessToken;if(a?.trim())return{kind:"oauth",token:a.trim()};const i=r.providerApiKeys?.[e];if(i?.trim())return{kind:"api-key",token:i.trim()};const s="claude"===e?r.claudeAiOauth?.accessToken:"openai"===e?r.openAiOauth?.accessToken:null;return s?.trim()?{kind:"oauth",token:s.trim()}:{kind:"none",token:null}}function buildSystemPrompt(e){const t=e.domain?.domainName??e.task.scopeType,o=e.capabilities.length>0?e.capabilities.join(", "):"sin declarar";return[e.agent.systemPrompt?.trim()||`Eres ${e.agent.name}, agente del equipo ${t}.`,`Rol: ${e.agent.roleKind??"general"}.`,`Capacidades: ${o}.`,"Responde con un reporte ejecutivo y accionable para el orquestador global.","No modifiques archivos. Solo entrega resultado, riesgos y siguientes pasos."].join("\n")}function buildUserPrompt(e){const t=e.domain?.domainName??e.task.scopeType,o=e.members.length>0?e.members.map(e=>`${e.agentId}:${e.duty??"member"}`).join(", "):"sin miembros internos";return[`Objetivo global: ${e.run.goal}`,`Equipo: ${t}`,`Tarea: ${e.task.title}`,`Instrucciones: ${e.task.instructions}`,`Miembros del escuadron: ${o}`,"","Entrega:","1. Resultado del equipo.","2. Decisiones tomadas.","3. Riesgos o bloqueos.","4. Siguientes pasos recomendados."].join("\n")}async function postJson(e,t,o,r=3){let n=null;for(let a=0;a<=r;a++){if(a>0){const e=1e3*Math.pow(2,a)+1e3*Math.random();await new Promise(t=>setTimeout(t,e))}try{const r=await fetch(e,{method:"POST",headers:{"Content-Type":"application/json",...t},body:JSON.stringify(o)}),a=await r.text(),i=tryParseJson(a)??a;if(!r.ok){if(n={status:r.status,error:"string"==typeof i?i:JSON.stringify(i)},429===r.status||r.status>=500)continue;return{ok:!1,...n}}return{ok:!0,data:i}}catch(e){n={status:0,error:e instanceof Error?e.message:String(e)};continue}}return{ok:!1,...n}}async function executeOpenAICompatible(e,t,o,r){const n={};r.token&&(n.Authorization=`Bearer ${r.token}`),"openrouter"===e.workspace.provider&&(n["HTTP-Referer"]="https://context.iaforged.com",n["X-Title"]="Context Code");const a=await postJson(`${trimTrailingSlash(o)}/chat/completions`,n,{model:t,temperature:.2,messages:[{role:"system",content:buildSystemPrompt(e)},{role:"user",content:buildUserPrompt(e)}]});if(!a.ok)return{ok:!1,error:`HTTP ${a.status}: ${a.error}`};const i=function(e){if(!e||"object"!=typeof e)return null;const t=e,o=t.choices?.[0]?.message?.content??t.choices?.[0]?.text;return"string"==typeof o?o:Array.isArray(o)?o.map(e=>"string"==typeof e?e:"object"==typeof e&&e&&"text"in e?String(e.text??""):"").filter(Boolean).join("\n"):"string"==typeof t.output_text?t.output_text:null}(a.data);return i?.trim()?{ok:!0,output:i}:{ok:!1,error:"El proveedor no devolvio contenido de texto."}}async function executeAnthropicCompatible(e,t,o,r){const n={"anthropic-version":"2023-06-01"};"api-key"===r.kind&&r.token?(n["x-api-key"]=r.token,"minimax"===e.workspace.provider&&(n.Authorization=`Bearer ${r.token}`)):"oauth"===r.kind&&r.token&&(n.Authorization=`Bearer ${r.token}`);const a=await postJson(`${trimTrailingSlash(o)}/v1/messages`,n,{model:t,max_tokens:2048,system:buildSystemPrompt(e),messages:[{role:"user",content:buildUserPrompt(e)}]});if(!a.ok)return{ok:!1,error:`HTTP ${a.status}: ${a.error}`};const i=function(e){if(!e||"object"!=typeof e)return null;const t=e;return t.content?.map(e=>"text"===e.type&&"string"==typeof e.text?e.text:"").filter(Boolean).join("\n")||null}(a.data);return i?.trim()?{ok:!0,output:i}:{ok:!1,error:"El proveedor no devolvio contenido de texto."}}export async function executeAgentDomainTask(t){const r=e(t.agent.profileId),n=t.workspace.provider,a=function(t){const o=e(t.agent.profileId);return t.agent.modelOverride?.trim()||o?.lastModel?.trim()||null}(t);if(!r)return{status:"blocked",summary:`No existe el perfil ${t.agent.profileId} para el agente ${t.agent.name}.`,output:null,provider:n,profileId:t.agent.profileId,model:a,messageType:"task.blocked",blockers:["Perfil del agente no encontrado."],metadata:{reason:"missing-profile"}};if(r.provider!==n)return{status:"blocked",summary:`El perfil ${r.id} pertenece a ${r.provider}, pero el workspace es ${n}.`,output:null,provider:n,profileId:r.id,model:a,messageType:"task.blocked",blockers:["Perfil y workspace no coinciden."],metadata:{reason:"provider-profile-mismatch",profileProvider:r.provider}};if(!a)return{status:"blocked",summary:`El agente ${t.agent.name} no tiene modelo configurado.`,output:null,provider:n,profileId:r.id,model:a,messageType:"task.blocked",blockers:["Modelo no configurado."],metadata:{reason:"missing-model"}};const i=resolveCredential(n,r.id);if("ollama"!==n&&"none"===i.kind)return{status:"blocked",summary:`El perfil ${r.id} no tiene credenciales para ${n}.`,output:null,provider:n,profileId:r.id,model:a,messageType:"task.blocked",blockers:["Credenciales no configuradas."],metadata:{reason:"missing-credentials"}};const s=r.baseUrl||o[n];try{const e="claude"===n||"minimax"===n?await executeAnthropicCompatible(t,a,s,i):await executeOpenAICompatible(t,a,s,i);if(!e.ok)return{status:"failed",summary:`El agente ${t.agent.name} fallo ejecutando ${a}: ${e.error}`,output:null,provider:n,profileId:r.id,model:a,messageType:"task.failed",blockers:[e.error],metadata:{reason:"provider-error",baseUrl:s}};const o=function(e,t=12e3){return e.length>t?`${e.slice(0,t)}\n\n[output truncado a ${t} caracteres]`:e}(e.output.trim());return{status:"completed",summary:o.split("\n").find(e=>e.trim())?.trim()||o,output:o,provider:n,profileId:r.id,model:a,messageType:"task.completed",blockers:[],metadata:{baseUrl:s,credentialKind:i.kind}}}catch(e){const o=function(e){return e instanceof Error?e.message:String(e)}(e);return{status:"failed",summary:`El agente ${t.agent.name} no pudo ejecutar la tarea: ${o}`,output:null,provider:n,profileId:r.id,model:a,messageType:"task.failed",blockers:[o],metadata:{reason:"execution-exception",baseUrl:s}}}}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import e from"chalk";import{logForDebugging as n}from"../../utils/debug.js";import{fileHistoryEnabled as a}from"../../utils/fileHistory.js";import{getInitialSettings as s,getSettings_DEPRECATED as t,getSettingsForSource as o}from"../../utils/settings/settings.js";import{shouldOfferTerminalSetup as i}from"../../commands/terminalSetup/terminalSetup.js";import{getDesktopUpsellConfig as r}from"../../components/DesktopUpsell/DesktopUpsellStartup.js";import{color as l}from"../../components/design-system/color.js";import{shouldShowOverageCreditUpsell as c}from"../../components/LogoV2/OverageCreditUpsell.js";import{getShortcutDisplay as d}from"../../keybindings/shortcutFormat.js";import{isKairosCronEnabled as u}from"../../tools/ScheduleCronTool/prompt.js";import{is1PApiCustomer as p}from"../../utils/auth.js";import{countConcurrentSessions as m}from"../../utils/concurrentSessions.js";import{getGlobalConfig as f}from"../../utils/config.js";import{getEffortEnvOverride as y,modelSupportsEffort as g}from"../../utils/effort.js";import{env as v}from"../../utils/env.js";import{cacheKeys as S}from"../../utils/fileStateCache.js";import{getWorktreeCount as h}from"../../utils/git.js";import{detectRunningIDEsCached as w,getSortedIdeLockfiles as R,isCursorInstalled as b,isSupportedTerminal as C,isSupportedVSCodeTerminal as j,isVSCodeInstalled as E,isWindsurfInstalled as P}from"../../utils/ide.js";import{getMainLoopModel as _,getUserSpecifiedModelSetting as T}from"../../utils/model/model.js";import{getPlatform as U}from"../../utils/platform.js";import{isPluginInstalled as k}from"../../utils/plugins/installedPluginsManager.js";import{loadKnownMarketplacesConfigSafe as x}from"../../utils/plugins/marketplaceManager.js";import{OFFICIAL_MARKETPLACE_NAME as O}from"../../utils/plugins/officialMarketplace.js";import{getCurrentSessionAgentColor as $,isCustomTitleEnabled as M}from"../../utils/sessionStorage.js";import{getFeatureValue_CACHED_MAY_BE_STALE as L}from"../analytics/growthbook.js";import{formatGrantAmount as A,getCachedOverageCreditGrant as D}from"../api/overageCreditGrant.js";import{checkCachedPassesEligibility as I,formatCreditAmount as q,getCachedReferrerReward as z}from"../api/referral.js";import{getSessionsSinceLastShown as H}from"./tipHistory.js";let N;async function isMarketplacePluginRelevant(e,n,a){if(!await async function(){if(void 0!==N)return N;const e=await x();return N=O in e,N}())return!1;if(k(`${e}@${O}`))return!1;const{bashTools:s}=n??{};if(a.cli&&s?.size&&a.cli.some(e=>s.has(e)))return!0;if(a.filePath&&n?.readFileState){if(S(n.readFileState).some(e=>a.filePath.test(e)))return!0}return!1}const Y=[{id:"new-user-warmup",content:async()=>"Comienza con pequeñas funciones o correcciones, pide a Context que proponga un plan y verifica sus ediciones sugeridas",cooldownSessions:3,isRelevant:async()=>f().numStartups<10},{id:"plan-mode-for-complex-tasks",content:async()=>`Usa el Modo Plan para preparar una solicitud compleja antes de realizar cambios. Presiona ${d("chat:cycleMode","Chat","shift+tab")} dos veces para activarlo.`,cooldownSessions:5,isRelevant:async()=>{if("ant"===process.env.USER_TYPE)return!1;const e=f();return(e.lastPlanModeUse?(Date.now()-e.lastPlanModeUse)/864e5:1/0)>7}},{id:"default-permission-mode-config",content:async()=>"Usa /config para cambiar tu modo de permisos predeterminado (incluyendo el Modo Plan)",cooldownSessions:10,isRelevant:async()=>{try{const e=f(),n=t(),a=Boolean(e.lastPlanModeUse),s=Boolean(n?.permissions?.defaultMode);return a&&!s}catch(e){return n(`Failed to check default-permission-mode-config tip relevance: ${e}`,{level:"warn"}),!1}}},{id:"git-worktrees",content:async()=>"Usa git worktrees para ejecutar múltiples sesiones de Context en paralelo.",cooldownSessions:10,isRelevant:async()=>{try{const e=f();return await h()<=1&&e.numStartups>50}catch(e){return!1}}},{id:"color-when-multi-clauding",content:async()=>"¿Ejecutando múltiples sesiones de Context? Usa /color y /rename para distinguirlas de un vistazo.",cooldownSessions:10,isRelevant:async()=>{if($())return!1;return await m()>=2}},{id:"terminal-setup",content:async()=>"Apple_Terminal"===v.terminal?"Ejecuta /terminal-setup para habilitar la integración del terminal, como Option + Enter para nueva línea y más":"Ejecuta /terminal-setup para habilitar la integración del terminal, como Shift + Enter para nueva línea y más",cooldownSessions:10,async isRelevant(){const e=f();return"Apple_Terminal"===v.terminal?!e.optionAsMetaKeyInstalled:!e.shiftEnterKeyBindingInstalled}},{id:"shift-enter",content:async()=>"Apple_Terminal"===v.terminal?"Presiona Option+Enter para enviar un mensaje multilínea":"Presiona Shift+Enter para enviar un mensaje multilínea",cooldownSessions:10,async isRelevant(){const e=f();return Boolean(("Apple_Terminal"===v.terminal?e.optionAsMetaKeyInstalled:e.shiftEnterKeyBindingInstalled)&&e.numStartups>3)}},{id:"shift-enter-setup",content:async()=>"Apple_Terminal"===v.terminal?"Ejecuta /terminal-setup para habilitar Option+Enter para nuevas líneas":"Ejecuta /terminal-setup para habilitar Shift+Enter para nuevas líneas",cooldownSessions:10,async isRelevant(){if(!i())return!1;const e=f();return!("Apple_Terminal"===v.terminal?e.optionAsMetaKeyInstalled:e.shiftEnterKeyBindingInstalled)}},{id:"memory-command",content:async()=>"Usa /memory para ver y gestionar la memoria de Context",cooldownSessions:15,isRelevant:async()=>f().memoryUsageCount<=0},{id:"theme-command",content:async()=>"Usa /theme para cambiar el tema de color",cooldownSessions:20,isRelevant:async()=>!0},{id:"colorterm-truecolor",content:async()=>"Prueba a configurar la variable de entorno COLORTERM=truecolor para obtener colores más vivos",cooldownSessions:30,isRelevant:async()=>!process.env.COLORTERM&&e.level<3},{id:"powershell-tool-env",content:async()=>"Configura CONTEXT_CODE_USE_POWERSHELL_TOOL=1 para habilitar la herramienta PowerShell (vista previa)",cooldownSessions:10,isRelevant:async()=>"windows"===U()&&void 0===process.env.CONTEXT_CODE_USE_POWERSHELL_TOOL&&void 0===process.env.CLAUDE_CODE_USE_POWERSHELL_TOOL},{id:"status-line",content:async()=>"Usa /statusline para configurar una línea de estado personalizada que se mostrará debajo del cuadro de entrada",cooldownSessions:25,isRelevant:async()=>void 0===t().statusLine},{id:"prompt-queue",content:async()=>"Pulsa Enter para poner en cola mensajes adicionales mientras Context está trabajando.",cooldownSessions:5,isRelevant:async()=>f().promptQueueUseCount<=3},{id:"enter-to-steer-in-relatime",content:async()=>"Envía mensajes a Context mientras trabaja para guiarlo en tiempo real",cooldownSessions:20,isRelevant:async()=>!0},{id:"todo-list",content:async()=>"Pide a Context que cree una lista de tareas cuando trabajes en tareas complejas para seguir el progreso",cooldownSessions:20,isRelevant:async()=>!0},{id:"vscode-command-install",content:async()=>`Abre la Paleta de Comandos (Cmd+Shift+P) y ejecuta "Shell Command: Install '${"vscode"===v.terminal?"code":v.terminal}' command in PATH" para habilitar la integración con el IDE`,cooldownSessions:0,async isRelevant(){if(!j())return!1;if("macos"!==U())return!1;switch(v.terminal){case"vscode":return!await E();case"cursor":return!await b();case"windsurf":return!await P();default:return!1}}},{id:"ide-upsell-external-terminal",content:async()=>"Conecta Context a tu IDE · /ide",cooldownSessions:4,async isRelevant(){if(C())return!1;if(0!==(await R()).length)return!1;return(await w()).length>0}},{id:"install-github-app",content:async()=>"Ejecuta /install-github-app para etiquetar a @claude directamente desde tus issues y PRs de Github",cooldownSessions:10,isRelevant:async()=>!f().githubActionSetupCount},{id:"install-slack-app",content:async()=>"Ejecuta /install-slack-app para usar Context en Slack",cooldownSessions:10,isRelevant:async()=>!f().slackAppInstallCount},{id:"permissions",content:async()=>"Usa /permissions para pre-aprobar y pre-denegar herramientas de bash, edición y MCP",cooldownSessions:10,isRelevant:async()=>f().numStartups>10},{id:"drag-and-drop-images",content:async()=>"¿Sabías que puedes arrastrar y soltar archivos de imagen en tu terminal?",cooldownSessions:10,isRelevant:async()=>!v.isSSH()},{id:"paste-images-mac",content:async()=>"Pega imágenes en Context Code usando control+v (¡no cmd+v!)",cooldownSessions:10,isRelevant:async()=>"macos"===U()},{id:"double-esc",content:async()=>"Pulsa dos veces esc para rebobinar la conversación a un punto anterior en el tiempo",cooldownSessions:10,isRelevant:async()=>!a()},{id:"double-esc-code-restore",content:async()=>"Pulsa dos veces esc para rebobinar el código y/o la conversación a un punto anterior en el tiempo",cooldownSessions:10,isRelevant:async()=>a()},{id:"continue",content:async()=>"Ejecuta context --continue o context --resume para reanudar una conversación",cooldownSessions:10,isRelevant:async()=>!0},{id:"rename-conversation",content:async()=>"Nombra tus conversaciones con /rename para encontrarlas fácilmente en /resume más tarde",cooldownSessions:15,isRelevant:async()=>M()&&f().numStartups>10},{id:"custom-commands",content:async()=>"Crea habilidades añadiendo archivos .md a .context/skills/ en tu proyecto o ~/.context/skills/ para habilidades globales",cooldownSessions:15,isRelevant:async()=>f().numStartups>10},{id:"shift-tab",content:async()=>"ant"===process.env.USER_TYPE?`Pulsa ${d("chat:cycleMode","Chat","shift+tab")} para alternar entre el modo predeterminado y el modo automático`:`Pulsa ${d("chat:cycleMode","Chat","shift+tab")} para alternar entre el modo predeterminado, el modo de edición con auto-aceptación y el modo de planificación`,cooldownSessions:10,isRelevant:async()=>!0},{id:"image-paste",content:async()=>`Usa ${d("chat:imagePaste","Chat","ctrl+v")} para pegar imágenes desde tu portapapeles`,cooldownSessions:20,isRelevant:async()=>!0},{id:"custom-agents",content:async()=>"Usa /agents para optimizar tareas específicas. Ej: Arquitecto de Software, Escritor de Código, Revisor de Código",cooldownSessions:15,isRelevant:async()=>f().numStartups>5},{id:"agent-flag",content:async()=>"Usa --agent <nombre_agente> para iniciar directamente una conversación con un subagente",cooldownSessions:15,isRelevant:async()=>f().numStartups>5},{id:"desktop-app",content:async()=>"Ejecuta Context Code local o remotamente usando la aplicación de escritorio: clau.de/desktop",cooldownSessions:15,isRelevant:async()=>"linux"!==U()},{id:"desktop-shortcut",content:async e=>`Continúa tu sesión en Context Code Desktop con ${l("suggestion",e.theme)("/desktop")}`,cooldownSessions:15,isRelevant:async()=>!!r().enable_shortcut_tip&&("darwin"===process.platform||"win32"===process.platform&&"x64"===process.arch)},{id:"web-app",content:async()=>"Ejecuta tareas en la nube mientras sigues programando localmente · clau.de/web",cooldownSessions:15,isRelevant:async()=>!0},{id:"mobile-app",content:async()=>"/mobile para usar Context Code desde la aplicación de Context en tu teléfono",cooldownSessions:15,isRelevant:async()=>!0},{id:"opusplan-mode-reminder",content:async()=>`Tu modelo predeterminado es Opus Plan Mode. Presiona ${d("chat:cycleMode","Chat","shift+tab")} dos veces para activar el Modo Plan y planificar con Context Opus.`,cooldownSessions:2,async isRelevant(){if("ant"===process.env.USER_TYPE)return!1;const e=f(),n="opusplan"===T(),a=e.lastPlanModeUse?(Date.now()-e.lastPlanModeUse)/864e5:1/0;return n&&a>3}},{id:"frontend-design-plugin",content:async e=>`¿Trabajando con HTML/CSS? Instala el plugin frontend-design:\n${l("suggestion",e.theme)(`/plugin install frontend-design@${O}`)}`,cooldownSessions:3,isRelevant:async e=>isMarketplacePluginRelevant("frontend-design",e,{filePath:/\.(html|css|htm)$/i})},{id:"vercel-plugin",content:async e=>`¿Trabajando con Vercel? Instala el plugin vercel:\n${l("suggestion",e.theme)(`/plugin install vercel@${O}`)}`,cooldownSessions:3,isRelevant:async e=>isMarketplacePluginRelevant("vercel",e,{filePath:/(?:^|[/\\])vercel\.json$/i,cli:["vercel"]})},{id:"effort-high-nudge",content:async e=>{const n=l("suggestion",e.theme)("/effort high");return"copy_b"===L("tengu_tide_elm","off")?`Usa ${n} para obtener mejores respuestas directas. Context lo analiza profundamente primero.`:`¿Trabajando en algo difícil? ${n} ofrece mejores respuestas iniciales`},cooldownSessions:3,isRelevant:async()=>{if(!p())return!1;if(!g(_()))return!1;if(void 0!==o("policySettings")?.effortLevel)return!1;if(void 0!==y())return!1;const e=s().effortLevel;return"high"!==e&&"max"!==e&&"off"!==L("tengu_tide_elm","off")}},{id:"subagent-fanout-nudge",content:async e=>{const n=l("suggestion",e.theme);return"copy_b"===L("tengu_tern_alloy","off")?`Para tareas grandes, pide a Context que ${n("use subagentes")}. Trabajan en paralelo y mantienen limpia la conversación principal.`:`Di ${n('"fan out subagents"')} y Context enviará un equipo. Cada uno profundiza para que no se escape nada.`},cooldownSessions:3,isRelevant:async()=>!!p()&&"off"!==L("tengu_tern_alloy","off")},{id:"loop-command-nudge",content:async e=>{const n=l("suggestion",e.theme);return"copy_b"===L("tengu_timber_lark","off")?`Usa ${n("/loop 5m check the deploy")} para ejecutar cualquier prompt de forma programada. Configúralo y olvídate.`:`${n("/loop")} ejecuta cualquier prompt de forma recurrente. Ideal para monitorear despliegues o estados de PR.`},cooldownSessions:3,isRelevant:async()=>!!p()&&(!!u()&&"off"!==L("tengu_timber_lark","off"))},{id:"guest-passes",content:async e=>{const n=l("claude",e.theme),a=z();return a?`Comparte Context Code y gana ${n(q(a))} de uso extra · ${n("/passes")}`:`Tienes pases de invitado gratuitos para compartir · ${n("/passes")}`},cooldownSessions:3,isRelevant:async()=>{if(f().hasVisitedPasses)return!1;const{eligible:e}=I();return e}},{id:"overage-credit",content:async e=>{const n=l("claude",e.theme),a=D(),s=a?A(a):null;return s?`${n(`${s} en uso extra, por nuestra cuenta`)} · aplicaciones de terceros · ${n("/extra-usage")}`:""},cooldownSessions:3,isRelevant:async()=>c()},{id:"feedback-command",content:async()=>"¡Usa /feedback para ayudarnos a mejorar!",cooldownSessions:15,async isRelevant(){if("ant"===process.env.USER_TYPE)return!1;return f().numStartups>5}}],B="ant"===process.env.USER_TYPE?[{id:"important-claudemd",content:async()=>'[ANT-ONLY] Use "IMPORTANT:" prefix for must-follow CLAUDE.md rules',cooldownSessions:30,isRelevant:async()=>!0},{id:"skillify",content:async()=>"[ANT-ONLY] Use /skillify at the end of a workflow to turn it into a reusable skill",cooldownSessions:15,isRelevant:async()=>!0}]:[];export async function getRelevantTips(e){const n=s().spinnerTipsOverride,a=function(){const e=s().spinnerTipsOverride;return e?.tips?.length?e.tips.map((e,n)=>({id:`custom-tip-${n}`,content:async()=>e,cooldownSessions:0,isRelevant:async()=>!0})):[]}();if(n?.excludeDefault&&a.length>0)return a;const t=[...Y,...B],o=await Promise.all(t.map(n=>n.isRelevant(e)));return[...t.filter((e,n)=>o[n]).filter(e=>H(e.id)>=e.cooldownSessions),...a]}
|
|
1
|
+
import e from"chalk";import{logForDebugging as n}from"../../utils/debug.js";import{fileHistoryEnabled as a}from"../../utils/fileHistory.js";import{getInitialSettings as s,getSettings_DEPRECATED as t,getSettingsForSource as o}from"../../utils/settings/settings.js";import{shouldOfferTerminalSetup as i}from"../../commands/terminalSetup/terminalSetup.js";import{getDesktopUpsellConfig as r}from"../../components/DesktopUpsell/DesktopUpsellStartup.js";import{color as l}from"../../components/design-system/color.js";import{shouldShowOverageCreditUpsell as c}from"../../components/LogoV2/OverageCreditUpsell.js";import{getShortcutDisplay as d}from"../../keybindings/shortcutFormat.js";import{isKairosCronEnabled as u}from"../../tools/ScheduleCronTool/prompt.js";import{is1PApiCustomer as p}from"../../utils/auth.js";import{countConcurrentSessions as m}from"../../utils/concurrentSessions.js";import{getGlobalConfig as f}from"../../utils/config.js";import{getEffortEnvOverride as y,modelSupportsEffort as g}from"../../utils/effort.js";import{env as v}from"../../utils/env.js";import{cacheKeys as S}from"../../utils/fileStateCache.js";import{getWorktreeCount as h}from"../../utils/git.js";import{detectRunningIDEsCached as w,getSortedIdeLockfiles as R,isCursorInstalled as b,isSupportedTerminal as C,isSupportedVSCodeTerminal as j,isVSCodeInstalled as E,isWindsurfInstalled as P}from"../../utils/ide.js";import{getMainLoopModel as _,getUserSpecifiedModelSetting as T}from"../../utils/model/model.js";import{getPlatform as x}from"../../utils/platform.js";import{isPluginInstalled as U}from"../../utils/plugins/installedPluginsManager.js";import{loadKnownMarketplacesConfigSafe as k}from"../../utils/plugins/marketplaceManager.js";import{OFFICIAL_MARKETPLACE_NAME as O}from"../../utils/plugins/officialMarketplace.js";import{getCurrentSessionAgentColor as $,isCustomTitleEnabled as M}from"../../utils/sessionStorage.js";import{getFeatureValue_CACHED_MAY_BE_STALE as L}from"../analytics/growthbook.js";import{formatGrantAmount as A,getCachedOverageCreditGrant as D}from"../api/overageCreditGrant.js";import{checkCachedPassesEligibility as I,formatCreditAmount as q,getCachedReferrerReward as z}from"../api/referral.js";import{getSessionsSinceLastShown as H}from"./tipHistory.js";let N;async function isMarketplacePluginRelevant(e,n,a){if(!await async function(){if(void 0!==N)return N;const e=await k();return N=O in e,N}())return!1;if(U(`${e}@${O}`))return!1;const{bashTools:s}=n??{};if(a.cli&&s?.size&&a.cli.some(e=>s.has(e)))return!0;if(a.filePath&&n?.readFileState){if(S(n.readFileState).some(e=>a.filePath.test(e)))return!0}return!1}const Y=[{id:"new-user-warmup",content:async()=>"Comienza con pequeñas funciones o correcciones, pide a Context que proponga un plan y verifica sus ediciones sugeridas",cooldownSessions:3,isRelevant:async()=>f().numStartups<10},{id:"plan-mode-for-complex-tasks",content:async()=>`Usa el Modo Plan para preparar una solicitud compleja antes de realizar cambios. Presiona ${d("chat:cycleMode","Chat","shift+tab")} dos veces para activarlo.`,cooldownSessions:5,isRelevant:async()=>{if("ant"===process.env.USER_TYPE)return!1;const e=f();return(e.lastPlanModeUse?(Date.now()-e.lastPlanModeUse)/864e5:1/0)>7}},{id:"default-permission-mode-config",content:async()=>"Usa /config para cambiar tu modo de permisos predeterminado (incluyendo el Modo Plan)",cooldownSessions:10,isRelevant:async()=>{try{const e=f(),n=t(),a=Boolean(e.lastPlanModeUse),s=Boolean(n?.permissions?.defaultMode);return a&&!s}catch(e){return n(`Failed to check default-permission-mode-config tip relevance: ${e}`,{level:"warn"}),!1}}},{id:"git-worktrees",content:async()=>"Usa git worktrees para ejecutar múltiples sesiones de Context en paralelo.",cooldownSessions:10,isRelevant:async()=>{try{const e=f();return await h()<=1&&e.numStartups>50}catch(e){return!1}}},{id:"color-when-multi-clauding",content:async()=>"¿Ejecutando múltiples sesiones de Context? Usa /color y /rename para distinguirlas de un vistazo.",cooldownSessions:10,isRelevant:async()=>{if($())return!1;return await m()>=2}},{id:"terminal-setup",content:async()=>"Apple_Terminal"===v.terminal?"Ejecuta /terminal-setup para habilitar la integración del terminal, como Option + Enter para nueva línea y más":"Ejecuta /terminal-setup para habilitar la integración del terminal, como Shift + Enter para nueva línea y más",cooldownSessions:10,async isRelevant(){const e=f();return"Apple_Terminal"===v.terminal?!e.optionAsMetaKeyInstalled:!e.shiftEnterKeyBindingInstalled}},{id:"shift-enter",content:async()=>"Apple_Terminal"===v.terminal?"Presiona Option+Enter para enviar un mensaje multilínea":"Presiona Shift+Enter para enviar un mensaje multilínea",cooldownSessions:10,async isRelevant(){const e=f();return Boolean(("Apple_Terminal"===v.terminal?e.optionAsMetaKeyInstalled:e.shiftEnterKeyBindingInstalled)&&e.numStartups>3)}},{id:"shift-enter-setup",content:async()=>"Apple_Terminal"===v.terminal?"Ejecuta /terminal-setup para habilitar Option+Enter para nuevas líneas":"Ejecuta /terminal-setup para habilitar Shift+Enter para nuevas líneas",cooldownSessions:10,async isRelevant(){if(!i())return!1;const e=f();return!("Apple_Terminal"===v.terminal?e.optionAsMetaKeyInstalled:e.shiftEnterKeyBindingInstalled)}},{id:"memory-command",content:async()=>"Usa /memory para ver y gestionar la memoria de Context",cooldownSessions:15,isRelevant:async()=>f().memoryUsageCount<=0},{id:"theme-command",content:async()=>"Usa /theme para cambiar el tema de color",cooldownSessions:20,isRelevant:async()=>!0},{id:"colorterm-truecolor",content:async()=>"Prueba a configurar la variable de entorno COLORTERM=truecolor para obtener colores más vivos",cooldownSessions:30,isRelevant:async()=>!process.env.COLORTERM&&e.level<3},{id:"powershell-tool-env",content:async()=>"Configura CONTEXT_CODE_USE_POWERSHELL_TOOL=1 para habilitar la herramienta PowerShell (vista previa)",cooldownSessions:10,isRelevant:async()=>"windows"===x()&&void 0===process.env.CONTEXT_CODE_USE_POWERSHELL_TOOL&&void 0===process.env.CLAUDE_CODE_USE_POWERSHELL_TOOL},{id:"status-line",content:async()=>"Usa /statusline para configurar una línea de estado personalizada que se mostrará debajo del cuadro de entrada",cooldownSessions:25,isRelevant:async()=>void 0===t().statusLine},{id:"prompt-queue",content:async()=>"Pulsa Enter para poner en cola mensajes adicionales mientras Context está trabajando.",cooldownSessions:5,isRelevant:async()=>f().promptQueueUseCount<=3},{id:"enter-to-steer-in-relatime",content:async()=>"Envía mensajes a Context mientras trabaja para guiarlo en tiempo real",cooldownSessions:20,isRelevant:async()=>!0},{id:"todo-list",content:async()=>"Pide a Context que cree una lista de tareas cuando trabajes en tareas complejas para seguir el progreso",cooldownSessions:20,isRelevant:async()=>!0},{id:"vscode-command-install",content:async()=>`Abre la Paleta de Comandos (Cmd+Shift+P) y ejecuta "Shell Command: Install '${"vscode"===v.terminal?"code":v.terminal}' command in PATH" para habilitar la integración con el IDE`,cooldownSessions:0,async isRelevant(){if(!j())return!1;if("macos"!==x())return!1;switch(v.terminal){case"vscode":return!await E();case"cursor":return!await b();case"windsurf":return!await P();default:return!1}}},{id:"ide-upsell-external-terminal",content:async()=>"Conecta Context a tu IDE · /ide",cooldownSessions:4,async isRelevant(){if(C())return!1;if(0!==(await R()).length)return!1;return(await w()).length>0}},{id:"install-github-app",content:async()=>"Ejecuta /install-github-app para etiquetar a @claude directamente desde tus issues y PRs de Github",cooldownSessions:10,isRelevant:async()=>!f().githubActionSetupCount},{id:"install-slack-app",content:async()=>"Ejecuta /install-slack-app para usar Context en Slack",cooldownSessions:10,isRelevant:async()=>!f().slackAppInstallCount},{id:"permissions",content:async()=>"Usa /permissions para pre-aprobar y pre-denegar herramientas de bash, edición y MCP",cooldownSessions:10,isRelevant:async()=>f().numStartups>10},{id:"drag-and-drop-images",content:async()=>"¿Sabías que puedes arrastrar y soltar archivos de imagen en tu terminal?",cooldownSessions:10,isRelevant:async()=>!v.isSSH()},{id:"paste-images-mac",content:async()=>"Pega imágenes en Context Code usando control+v (¡no cmd+v!)",cooldownSessions:10,isRelevant:async()=>"macos"===x()},{id:"double-esc",content:async()=>"Pulsa dos veces esc para rebobinar la conversación a un punto anterior en el tiempo",cooldownSessions:10,isRelevant:async()=>!a()},{id:"double-esc-code-restore",content:async()=>"Pulsa dos veces esc para rebobinar el código y/o la conversación a un punto anterior en el tiempo",cooldownSessions:10,isRelevant:async()=>a()},{id:"continue",content:async()=>"Ejecuta context --continue o context --resume para reanudar una conversación",cooldownSessions:10,isRelevant:async()=>!0},{id:"rename-conversation",content:async()=>"Nombra tus conversaciones con /rename para encontrarlas fácilmente en /resume más tarde",cooldownSessions:15,isRelevant:async()=>M()&&f().numStartups>10},{id:"custom-commands",content:async()=>"Crea habilidades añadiendo archivos .md a .context/skills/ en tu proyecto o ~/.context/skills/ para habilidades globales",cooldownSessions:15,isRelevant:async()=>f().numStartups>10},{id:"shift-tab",content:async()=>"ant"===process.env.USER_TYPE?`Pulsa ${d("chat:cycleMode","Chat","shift+tab")} para alternar entre el modo predeterminado y el modo automático`:`Pulsa ${d("chat:cycleMode","Chat","shift+tab")} para alternar entre el modo predeterminado, el modo de edición con auto-aceptación y el modo de planificación`,cooldownSessions:10,isRelevant:async()=>!0},{id:"image-paste",content:async()=>`Usa ${d("chat:imagePaste","Chat","ctrl+v")} para pegar imágenes desde tu portapapeles`,cooldownSessions:20,isRelevant:async()=>!0},{id:"custom-agents",content:async()=>"Usa /agents para optimizar tareas específicas. Ej: Arquitecto de Software, Escritor de Código, Revisor de Código",cooldownSessions:15,isRelevant:async()=>f().numStartups>5},{id:"agent-flag",content:async()=>"Usa --agent <nombre_agente> para iniciar directamente una conversación con un subagente",cooldownSessions:15,isRelevant:async()=>f().numStartups>5},{id:"desktop-app",content:async()=>"Ejecuta Context Code local o remotamente usando la aplicación de escritorio: clau.de/desktop",cooldownSessions:15,isRelevant:async()=>"linux"!==x()},{id:"desktop-shortcut",content:async e=>`Continúa tu sesión en Context Code Desktop con ${l("suggestion",e.theme)("/desktop")}`,cooldownSessions:15,isRelevant:async()=>!!r().enable_shortcut_tip&&("darwin"===process.platform||"win32"===process.platform&&"x64"===process.arch)},{id:"web-app",content:async()=>"Ejecuta tareas en la nube mientras sigues programando localmente · clau.de/web",cooldownSessions:15,isRelevant:async()=>!0},{id:"mobile-app",content:async()=>"/mobile para usar Context Code desde la aplicación de Context en tu teléfono",cooldownSessions:15,isRelevant:async()=>!0},{id:"opusplan-mode-reminder",content:async()=>`Tu modelo predeterminado es Opus Plan Mode. Presiona ${d("chat:cycleMode","Chat","shift+tab")} dos veces para activar el Modo Plan y planificar con Context Opus.`,cooldownSessions:2,async isRelevant(){if("ant"===process.env.USER_TYPE)return!1;const e=f(),n="opusplan"===T(),a=e.lastPlanModeUse?(Date.now()-e.lastPlanModeUse)/864e5:1/0;return n&&a>3}},{id:"frontend-design-plugin",content:async e=>`¿Trabajando con HTML/CSS? Instala el plugin frontend-design:\n${l("suggestion",e.theme)(`/plugin install frontend-design@${O}`)}`,cooldownSessions:3,isRelevant:async e=>isMarketplacePluginRelevant("frontend-design",e,{filePath:/\.(html|css|htm)$/i})},{id:"vercel-plugin",content:async e=>`¿Trabajando con Vercel? Instala el plugin vercel:\n${l("suggestion",e.theme)(`/plugin install vercel@${O}`)}`,cooldownSessions:3,isRelevant:async e=>isMarketplacePluginRelevant("vercel",e,{filePath:/(?:^|[/\\])vercel\.json$/i,cli:["vercel"]})},{id:"effort-high-nudge",content:async e=>{const n=l("suggestion",e.theme)("/effort high");return"copy_b"===L("tengu_tide_elm","off")?`Usa ${n} para obtener mejores respuestas directas. Context lo analiza profundamente primero.`:`¿Trabajando en algo difícil? ${n} ofrece mejores respuestas iniciales`},cooldownSessions:3,isRelevant:async()=>{if(!p())return!1;if(!g(_()))return!1;if(void 0!==o("policySettings")?.effortLevel)return!1;if(void 0!==y())return!1;const e=s().effortLevel;return"high"!==e&&"max"!==e&&"off"!==L("tengu_tide_elm","off")}},{id:"subagent-fanout-nudge",content:async e=>{const n=l("suggestion",e.theme);return"copy_b"===L("tengu_tern_alloy","off")?`Para tareas grandes, pide a Context que ${n("use subagentes")}. Trabajan en paralelo y mantienen limpia la conversación principal.`:`Di ${n('"fan out subagents"')} y Context enviará un equipo. Cada uno profundiza para que no se escape nada.`},cooldownSessions:3,isRelevant:async()=>!!p()&&"off"!==L("tengu_tern_alloy","off")},{id:"loop-command-nudge",content:async e=>{const n=l("suggestion",e.theme);return"copy_b"===L("tengu_timber_lark","off")?`Usa ${n("/loop 5m check the deploy")} para ejecutar cualquier prompt de forma programada. Configúralo y olvídate.`:`${n("/loop")} ejecuta cualquier prompt de forma recurrente. Ideal para monitorear despliegues o estados de PR.`},cooldownSessions:3,isRelevant:async()=>!!p()&&(!!u()&&"off"!==L("tengu_timber_lark","off"))},{id:"guest-passes",content:async e=>{const n=l("context",e.theme),a=z();return a?`Comparte Context Code y gana ${n(q(a))} de uso extra · ${n("/passes")}`:`Tienes pases de invitado gratuitos para compartir · ${n("/passes")}`},cooldownSessions:3,isRelevant:async()=>{if(f().hasVisitedPasses)return!1;const{eligible:e}=I();return e}},{id:"overage-credit",content:async e=>{const n=l("context",e.theme),a=D(),s=a?A(a):null;return s?`${n(`${s} en uso extra, por nuestra cuenta`)} · aplicaciones de terceros · ${n("/extra-usage")}`:""},cooldownSessions:3,isRelevant:async()=>c()},{id:"feedback-command",content:async()=>"¡Usa /feedback para ayudarnos a mejorar!",cooldownSessions:15,async isRelevant(){if("ant"===process.env.USER_TYPE)return!1;return f().numStartups>5}}],B="ant"===process.env.USER_TYPE?[{id:"important-claudemd",content:async()=>'[ANT-ONLY] Use "IMPORTANT:" prefix for must-follow CLAUDE.md rules',cooldownSessions:30,isRelevant:async()=>!0},{id:"skillify",content:async()=>"[ANT-ONLY] Use /skillify at the end of a workflow to turn it into a reusable skill",cooldownSessions:15,isRelevant:async()=>!0}]:[];export async function getRelevantTips(e){const n=s().spinnerTipsOverride,a=function(){const e=s().spinnerTipsOverride;return e?.tips?.length?e.tips.map((e,n)=>({id:`custom-tip-${n}`,content:async()=>e,cooldownSessions:0,isRelevant:async()=>!0})):[]}();if(n?.excludeDefault&&a.length>0)return a;const t=[...Y,...B],o=await Promise.all(t.map(n=>n.isRelevant(e)));return[...t.filter((e,n)=>o[n]).filter(e=>H(e.id)>=e.cooldownSessions),...a]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
const e=30;export async function generateToolUseSummary({tools:n}){return 0===n.length?null:1===n.length?function(n){const o=t[n.name]??n.name,i=pickNoun(n.input);return clipTo(i?`${o} ${i}`:o,e)}(n[0]):function(n){const o=new Map,i=new Map;let s="";for(const e of n){const n=t[e.name]??e.name;if(o.set(n,(o.get(n)??0)+1),!s&&"object"==typeof e.input&&e.input){const t=e.input,n=t.file_path??t.path??t.filepath;"string"==typeof n&&(s=dirname(n))}if(!i.has(n)){const t=pickNoun(e.input);t&&i.set(n,basename(t))}}if(1===o.size){const[t,n]=[...o.entries()][0],r=i.get(t);if("Read"===t||"Wrote"===t||"Edited"===t){return clipTo(`${t} ${n} file${n>1?"s":""}${s?` in ${s}`:""}`,e)}return clipTo(r?`${t} ${r}`:`${t} ${n}`,e)}const r=[];for(const[e,t]of o){const n=i.get(e);if(n?r.push(`${e} ${n}`):r.push(`${e} ${t}`),3===r.length&&o.size>3){r.push(`+${o.size-3} more`);break}}return clipTo(r.join(", "),e)}(n)}const t={Read:"Read",Write:"Wrote",Edit:"Edited",Glob:"Listed paths in",Grep:"Searched in",Bash:"Ran",PowerShell:"Ran",WebFetch:"Fetched",WebSearch:"Searched",Agent:"Delegated to",TodoWrite:"Updated todos",ToolSearch:"Discovered tools",NotebookEdit:"Edited notebook",ListMcpResources:"Listed MCP resources",mcp__database__query:"Queried DB",mcp__database__list_tables:"Listed DB tables",mcp__database__describe_table:"Described table"};function pickNoun(e){if(!e||"object"!=typeof e)return"";const t=e;for(const e of["file_path","filepath","path","filePath"])if("string"==typeof t[e])return t[e];return"string"==typeof t.command?t.command:"string"==typeof t.pattern?t.pattern:"string"==typeof t.query?t.query:"string"==typeof t.url?t.url:"string"==typeof t.resource?t.resource:""}function clipTo(e,t){const n=e.trim();return n?n.length<=t?n:n.slice(0,t-1)+"…":null}function dirname(e){const t=Math.max(e.lastIndexOf("/"),e.lastIndexOf("\\"));return-1===t?"":e.slice(0,t)}function basename(e){const t=Math.max(e.lastIndexOf("/"),e.lastIndexOf("\\"));return-1===t?e:e.slice(t+1)}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{jsx as e,jsxs as t}from"react/jsx-runtime";import{c as r}from"react/compiler-runtime";import n from"figures";import{Markdown as i}from"../../components/Markdown.js";import{BLACK_CIRCLE as o}from"../../constants/figures.js";import{Box as l,Text as m}from"../../ink.js";import{getDisplayPath as s}from"../../utils/file.js";import{formatFileSize as c}from"../../utils/format.js";import{formatBriefTimestamp as a}from"../../utils/formatBriefTimestamp.js";export function renderToolUseMessage(){return""}export function renderToolResultMessage(r,n,s){const c=(r.attachments?.length??0)>0;if(!r.message&&!c)return null;if(s?.isTranscriptMode)return t(l,{flexDirection:"row",marginTop:1,children:[e(l,{minWidth:2,children:e(m,{color:"text",children:o})}),t(l,{flexDirection:"column",children:[r.message?e(i,{children:r.message}):null,e(AttachmentList,{attachments:r.attachments})]})]});if(s?.isBriefOnly){const n=r.sentAt?a(r.sentAt):"";return t(l,{flexDirection:"column",marginTop:1,paddingLeft:2,children:[t(l,{flexDirection:"row",children:[e(m,{color:"
|
|
1
|
+
import{jsx as e,jsxs as t}from"react/jsx-runtime";import{c as r}from"react/compiler-runtime";import n from"figures";import{Markdown as i}from"../../components/Markdown.js";import{BLACK_CIRCLE as o}from"../../constants/figures.js";import{Box as l,Text as m}from"../../ink.js";import{getDisplayPath as s}from"../../utils/file.js";import{formatFileSize as c}from"../../utils/format.js";import{formatBriefTimestamp as a}from"../../utils/formatBriefTimestamp.js";export function renderToolUseMessage(){return""}export function renderToolResultMessage(r,n,s){const c=(r.attachments?.length??0)>0;if(!r.message&&!c)return null;if(s?.isTranscriptMode)return t(l,{flexDirection:"row",marginTop:1,children:[e(l,{minWidth:2,children:e(m,{color:"text",children:o})}),t(l,{flexDirection:"column",children:[r.message?e(i,{children:r.message}):null,e(AttachmentList,{attachments:r.attachments})]})]});if(s?.isBriefOnly){const n=r.sentAt?a(r.sentAt):"";return t(l,{flexDirection:"column",marginTop:1,paddingLeft:2,children:[t(l,{flexDirection:"row",children:[e(m,{color:"briefLabelContext",children:"Claude"}),n?t(m,{dimColor:!0,children:[" ",n]}):null]}),t(l,{flexDirection:"column",children:[r.message?e(i,{children:r.message}):null,e(AttachmentList,{attachments:r.attachments})]})]})}return t(l,{flexDirection:"row",marginTop:1,children:[e(l,{minWidth:2}),t(l,{flexDirection:"column",children:[r.message?e(i,{children:r.message}):null,e(AttachmentList,{attachments:r.attachments})]})]})}export function AttachmentList(t){const n=r(4),{attachments:i}=t;if(!i||0===i.length)return null;let o,m;return n[0]!==i?(o=i.map(_temp),n[0]=i,n[1]=o):o=n[1],n[2]!==o?(m=e(l,{flexDirection:"column",marginTop:1,children:o}),n[2]=o,n[3]=m):m=n[3],m}function _temp(r){return t(l,{flexDirection:"row",children:[t(m,{dimColor:!0,children:[n.pointerSmall," ",r.isImage?"[image]":"[file]"," "]}),e(m,{children:s(r.path)}),t(m,{dimColor:!0,children:[" (",c(r.size),")"]})]},r.path)}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{spawn as r}from"child_process";import{join as o}from"path";import{
|
|
1
|
+
import{spawn as r}from"child_process";import{join as o,dirname as e}from"path";import{fileURLToPath as t}from"url";import{COMPUTER_CONTROL_MCP_SERVER_NAME as m}from"./common.js";import{ensureUvAvailable as p}from"../sembleMcp/setup.js";export function runComputerControlMcpServer(){const s=e(t(import.meta.url)),c=o(s,"server"),n=p(),i=r(n,["run","--project",c,"-m","computer_control_mcp.server"],{cwd:c,stdio:"inherit",env:{...process.env,PYTHONPATH:o(c,"src"),UV_SKIP_WHEEL_FILENAME_CHECK:"1"}});return i.on("error",r=>{console.error(`Failed to start ${m} server:`,r)}),i}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Auto detect text files and perform LF normalization
|
|
2
|
+
* text=auto
|
|
3
|
+
|
|
4
|
+
# Python files
|
|
5
|
+
*.py text diff=python
|
|
6
|
+
|
|
7
|
+
# Documentation
|
|
8
|
+
*.md text
|
|
9
|
+
*.rst text
|
|
10
|
+
*.txt text
|
|
11
|
+
|
|
12
|
+
# Exclude files from exporting
|
|
13
|
+
.gitattributes export-ignore
|
|
14
|
+
.gitignore export-ignore
|
|
15
|
+
.github export-ignore
|
|
16
|
+
.pytest_cache export-ignore
|
|
17
|
+
__pycache__ export-ignore
|
|
18
|
+
*.pyc export-ignore
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# Use a lightweight Python base image
|
|
2
|
+
FROM python:3.12-slim
|
|
3
|
+
|
|
4
|
+
# Set environment variables for Python
|
|
5
|
+
ENV PYTHONDONTWRITEBYTECODE=1 \
|
|
6
|
+
PYTHONUNBUFFERED=1
|
|
7
|
+
|
|
8
|
+
# Set working directory
|
|
9
|
+
WORKDIR /app
|
|
10
|
+
|
|
11
|
+
# Copy dependency file(s)
|
|
12
|
+
COPY pyproject.toml .
|
|
13
|
+
COPY src/ src/
|
|
14
|
+
COPY README.md README.md
|
|
15
|
+
|
|
16
|
+
# Install build backend (Hatchling)
|
|
17
|
+
RUN pip install --upgrade pip && \
|
|
18
|
+
pip install hatchling && \
|
|
19
|
+
pip install -e .
|
|
20
|
+
|
|
21
|
+
# Copy any additional files (e.g. configs, CLI, entrypoints)
|
|
22
|
+
COPY . .
|
|
23
|
+
|
|
24
|
+
# Default command (can be overridden)
|
|
25
|
+
CMD ["python", "-m", "computer_control_mcp"]
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 AB498 <abcd49800@gmail.com>
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|