pi-namespace-patch 1.0.3-namespace.1 → 1.0.4-namespace.1

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.
Files changed (100) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/README.md +3 -3
  3. package/dist/bundle/chunks/{chunk-PSQJVYXD.js → chunk-2QSWSXFK.js} +4 -4
  4. package/dist/bundle/chunks/{chunk-AXOERKKW.js → chunk-64GOPQSC.js} +3 -1
  5. package/dist/bundle/chunks/{chunk-ITAWMMSC.js → chunk-ERIW6MDO.js} +28 -24
  6. package/dist/bundle/chunks/{chunk-UBHCV62G.js → chunk-F4TCZWQO.js} +1 -1
  7. package/dist/bundle/chunks/{chunk-7TP2J6F2.js → chunk-FKGBRPJC.js} +1 -1
  8. package/dist/bundle/chunks/{chunk-ZSQEXT6X.js → chunk-VLMAON6X.js} +4 -4
  9. package/dist/bundle/chunks/{chunk-6DBOMCBS.js → chunk-XXKX4I4Z.js} +1 -1
  10. package/dist/bundle/chunks/{chunk-2VBQLN7Y.js → chunk-YKYP4C4A.js} +8 -5
  11. package/dist/bundle/chunks/{chunk-DEVCTHZR.js → chunk-YTMEKMOC.js} +1 -1
  12. package/dist/bundle/chunks/{cli-HTJP6F6Z.js → cli-FRW732V6.js} +1 -1
  13. package/dist/bundle/chunks/codemode-worker.js +99 -3
  14. package/dist/bundle/chunks/{easter-egg-3d-6YCNESG3.js → easter-egg-3d-GBYHZI2E.js} +1 -1
  15. package/dist/bundle/chunks/{execute-JRUOLYDA.js → execute-MNHU53Y5.js} +101 -5
  16. package/dist/bundle/chunks/{runtime-NW7GPWKS.js → runtime-FW2HXAJ6.js} +1 -1
  17. package/dist/bundle/chunks/{virtual-modules-U4SEX4TD.js → virtual-modules-3HQKVCRO.js} +1 -1
  18. package/dist/bundle/cli-runtime.js +1 -1
  19. package/dist/bundle/index.js +1 -1
  20. package/dist/bundle/rpc-entry.js +1 -1
  21. package/dist/cli/args.d.ts +1 -0
  22. package/dist/cli/args.d.ts.map +1 -1
  23. package/dist/cli/args.js +11 -4
  24. package/dist/cli/args.js.map +1 -1
  25. package/dist/core/agent-session.d.ts +26 -4
  26. package/dist/core/agent-session.d.ts.map +1 -1
  27. package/dist/core/agent-session.js +47 -14
  28. package/dist/core/agent-session.js.map +1 -1
  29. package/dist/core/extensions/types.d.ts +2 -0
  30. package/dist/core/extensions/types.d.ts.map +1 -1
  31. package/dist/core/extensions/types.js.map +1 -1
  32. package/dist/core/mcp-servers.d.ts +8 -0
  33. package/dist/core/mcp-servers.d.ts.map +1 -1
  34. package/dist/core/mcp-servers.js +30 -7
  35. package/dist/core/mcp-servers.js.map +1 -1
  36. package/dist/core/resource-loader.d.ts +3 -0
  37. package/dist/core/resource-loader.d.ts.map +1 -1
  38. package/dist/core/resource-loader.js +4 -3
  39. package/dist/core/resource-loader.js.map +1 -1
  40. package/dist/core/sdk.d.ts +9 -4
  41. package/dist/core/sdk.d.ts.map +1 -1
  42. package/dist/core/sdk.js +3 -2
  43. package/dist/core/sdk.js.map +1 -1
  44. package/dist/core/skills.d.ts +4 -1
  45. package/dist/core/skills.d.ts.map +1 -1
  46. package/dist/core/skills.js +6 -1
  47. package/dist/core/skills.js.map +1 -1
  48. package/dist/core/system-prompt.d.ts +6 -0
  49. package/dist/core/system-prompt.d.ts.map +1 -1
  50. package/dist/core/system-prompt.js +9 -4
  51. package/dist/core/system-prompt.js.map +1 -1
  52. package/dist/core/tools/read.d.ts +13 -0
  53. package/dist/core/tools/read.d.ts.map +1 -1
  54. package/dist/core/tools/read.js +18 -1
  55. package/dist/core/tools/read.js.map +1 -1
  56. package/dist/extensions/codemode/execute.d.ts.map +1 -1
  57. package/dist/extensions/codemode/execute.js +2 -1
  58. package/dist/extensions/codemode/execute.js.map +1 -1
  59. package/dist/extensions/codemode/index.d.ts.map +1 -1
  60. package/dist/extensions/codemode/index.js +1 -0
  61. package/dist/extensions/codemode/index.js.map +1 -1
  62. package/dist/extensions/codemode/tool.d.ts +9 -2
  63. package/dist/extensions/codemode/tool.d.ts.map +1 -1
  64. package/dist/extensions/codemode/tool.js +12 -4
  65. package/dist/extensions/codemode/tool.js.map +1 -1
  66. package/dist/extensions/mcp/resources.d.ts +3 -4
  67. package/dist/extensions/mcp/resources.d.ts.map +1 -1
  68. package/dist/extensions/mcp/resources.js +3 -4
  69. package/dist/extensions/mcp/resources.js.map +1 -1
  70. package/dist/extensions/mcp/runtime.d.ts +4 -1
  71. package/dist/extensions/mcp/runtime.d.ts.map +1 -1
  72. package/dist/extensions/mcp/runtime.js +22 -5
  73. package/dist/extensions/mcp/runtime.js.map +1 -1
  74. package/dist/extensions/mcp/tools.d.ts +2 -1
  75. package/dist/extensions/mcp/tools.d.ts.map +1 -1
  76. package/dist/extensions/mcp/tools.js +2 -1
  77. package/dist/extensions/mcp/tools.js.map +1 -1
  78. package/dist/main.d.ts.map +1 -1
  79. package/dist/main.js +1 -0
  80. package/dist/main.js.map +1 -1
  81. package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  82. package/dist/modes/interactive/theme/theme.js +1 -0
  83. package/dist/modes/interactive/theme/theme.js.map +1 -1
  84. package/dist/utils/syntax-highlight.d.ts.map +1 -1
  85. package/dist/utils/syntax-highlight.js +6 -1
  86. package/dist/utils/syntax-highlight.js.map +1 -1
  87. package/docs/cli.md +15 -3
  88. package/docs/codemode.md +3 -2
  89. package/docs/extensions.md +1 -1
  90. package/docs/mcp.md +3 -1
  91. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  92. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  93. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  94. package/examples/extensions/gondolin/package-lock.json +2 -2
  95. package/examples/extensions/gondolin/package.json +1 -1
  96. package/examples/extensions/sandbox/package-lock.json +2 -2
  97. package/examples/extensions/sandbox/package.json +1 -1
  98. package/examples/extensions/with-deps/package-lock.json +2 -2
  99. package/examples/extensions/with-deps/package.json +1 -1
  100. package/package.json +10 -10
package/CHANGELOG.md CHANGED
@@ -1,5 +1,28 @@
1
1
  # Changelog
2
2
 
3
+ ## [1.0.4] - 2026-10-05
4
+
5
+ ### New Features
6
+
7
+ - **Tool patterns and `--no-mcp`**: `--tools` and `--exclude-tools` accept `*` patterns, for example `--tools read,codemode,'mcp__radius__*'` keeps only one MCP server's tools. `--tools` now keeps MCP tools unless an entry starts with `mcp__`, and `--no-mcp` turns off MCP for one run. See [Tools](docs/cli.md#tools) and [MCP tools](docs/cli.md#mcp-tools).
8
+ - **Codemode persists images**: `tools.read()` on an image file now gives back an image block that `image()` can show. See [Call tools](docs/codemode.md#call-tools).
9
+
10
+ ### Added
11
+
12
+ - Added `*` patterns to `--tools` and `--exclude-tools`, for example `--tools read,codemode,'mcp__radius__*'`
13
+ - Added `--no-mcp` to disable the built-in MCP support for one run
14
+
15
+ ### Fixed
16
+
17
+ - Fixed syntax highlighting losing colors after the first line of multiline strings and comments in fenced code blocks ([#10143](https://github.com/earendil-works/pi/issues/10143))
18
+ - Fixed codemode scripts not receiving images from `read`: `tools.read()` now resolves to an image block for image files, which `image()` shows ([#10251](https://github.com/earendil-works/pi/issues/10251))
19
+ - Fixed MCP OAuth sign-in failing with `invalid_redirect_uri` on servers with OpenID Connect client registration, such as `mcp.modem.dev`: pi now registers as a native client ([#10493](https://github.com/earendil-works/pi/issues/10493))
20
+ - Fixed `--tools` removing MCP tools, which left `pi --tools codemode` without any MCP servers. `--tools` now keeps MCP tools unless an entry starts with `mcp__`
21
+ - Fixed MCP session shutdown returning while a server was still connecting, leaving its transport open until the server answered or timed out ([#10249](https://github.com/earendil-works/pi/issues/10249))
22
+ - Fixed system prompt rules and the skills hint naming tools hidden by `prepareLoadout`. Hidden tools are left out of the rules, the skills hint names no tool when the file reader is hidden, and `codemode` shows each tool's prompt guidelines with its declaration; `ToolLoadout` gains `getPromptGuidelines()` ([#10343](https://github.com/earendil-works/pi/issues/10343))
23
+ - Fixed Bedrock requests that fail with `The pending stream has been canceled` after a stalled HTTP/2 connection not being retried automatically ([#10379](https://github.com/earendil-works/pi/issues/10379))
24
+ - Fixed codemode scripts that patch built-ins (for example `Array.prototype.toJSON = ...`) crashing pi and leaving the tool call unsettled. Built-ins are now frozen before the script runs, so such patches have no effect ([#10444](https://github.com/earendil-works/pi/issues/10444))
25
+
3
26
  ## [1.0.3] - 2026-10-05
4
27
 
5
28
  ### New Features
package/README.md CHANGED
@@ -7,7 +7,7 @@
7
7
  _Your package ships `review`; your users invoke `/acme:review` — no collisions, no renamed frontmatter, no silent shadowing._
8
8
 
9
9
  [![npm](https://img.shields.io/npm/v/pi-namespace-patch.svg)](https://www.npmjs.com/package/pi-namespace-patch)
10
- [![pi base](https://img.shields.io/badge/pi%20base-1.0.3-blueviolet)](https://github.com/earendil-works/pi/releases)
10
+ [![pi base](https://img.shields.io/badge/pi%20base-1.0.4-blueviolet)](https://github.com/earendil-works/pi/releases)
11
11
  [![license](https://img.shields.io/badge/license-MIT-blue)](#license)
12
12
 
13
13
  </div>
@@ -60,7 +60,7 @@ As a **user** there is nothing to learn — install, and packages that declare a
60
60
 
61
61
  ```bash
62
62
  npm install -g pi-namespace-patch
63
- pi --version # 1.0.3-namespace.1
63
+ pi --version # 1.0.4-namespace.1
64
64
  ```
65
65
 
66
66
  As a **package author**, add the `pi.namespace` field (two lines above), publish, and your resources are invocable in-session:
@@ -107,7 +107,7 @@ The mechanics, in order of depth:
107
107
 
108
108
  - The version scheme `X.Y.Z-namespace.N` mirrors the upstream release it tracks (`X.Y.Z`) plus the fork patch revision (`N`). **Pin exact versions** — never ranges.
109
109
  - Each upstream release flows through an automated pipeline: release detection, mechanical re-base, agent repair on conflict, and the full check chain with touched suites. The pipeline then publishes via OIDC trusted publishing with signed provenance.
110
- - `pi --version` on this alias reports `1.0.3-namespace.1` (registry-stamped); the [GitHub tarball](https://github.com/maskshell/pi/releases/download/v1.0.3-namespace.1/earendil-works-pi-coding-agent-1.0.3-namespace.1.tgz) reports the workspace form `1.0.3+namespace.1` — same build, never rebuilt.
110
+ - `pi --version` on this alias reports `1.0.4-namespace.1` (registry-stamped); the [GitHub tarball](https://github.com/maskshell/pi/releases/download/v1.0.4-namespace.1/earendil-works-pi-coding-agent-1.0.4-namespace.1.tgz) reports the workspace form `1.0.4+namespace.1` — same build, never rebuilt.
111
111
 
112
112
  ## Provenance and trust
113
113
 
@@ -1,7 +1,7 @@
1
1
  import { createRequire as __piCreateRequire } from "node:module"; const require = __piCreateRequire(import.meta.url);
2
- import{FileAuthStorageBackend,JSON_RPC_ERROR_CODES,LATEST_PROTOCOL_VERSION,McpAuthRequiredError,McpClient,McpError,McpHttpError,McpSessionExpiredError,StdioTransport,StreamableHttpTransport,isMcpAppResource,isObject,mcpNamespace,require_proper_lockfile,resolveConfigValueOrThrow,resolveHeadersOrThrow}from"./chunk-ZSQEXT6X.js";import{APP_NAME,VERSION,getAgentDir}from"./chunk-AXOERKKW.js";import{__toESM}from"./chunk-4L3WN2XY.js";import{homedir}from"node:os";import{basename,join as join2,resolve}from"node:path";import{pathToFileURL}from"node:url";import{createServer}from"node:http";function plainText(page){return page.ok?"Authorization complete. You may close this window.":page.details?`${page.message}
2
+ import{FileAuthStorageBackend,JSON_RPC_ERROR_CODES,LATEST_PROTOCOL_VERSION,McpAuthRequiredError,McpClient,McpError,McpHttpError,McpSessionExpiredError,StdioTransport,StreamableHttpTransport,isMcpAppResource,isObject,mcpNamespace,require_proper_lockfile,resolveConfigValueOrThrow,resolveHeadersOrThrow}from"./chunk-VLMAON6X.js";import{APP_NAME,VERSION,getAgentDir}from"./chunk-64GOPQSC.js";import{__toESM}from"./chunk-4L3WN2XY.js";import{homedir}from"node:os";import{basename,join as join2,resolve}from"node:path";import{setTimeout as sleep}from"node:timers/promises";import{pathToFileURL}from"node:url";import{createServer}from"node:http";function plainText(page){return page.ok?"Authorization complete. You may close this window.":page.details?`${page.message}
3
3
 
4
- ${page.details}`:page.message}var OAuthCallbackServer=class _OAuthCallbackServer{redirectUrl;server;paths;timeoutMs;renderPage;pending=new Map;constructor(server,redirectUrl,paths,timeoutMs,renderPage2){this.server=server,this.redirectUrl=redirectUrl,this.paths=paths,this.timeoutMs=timeoutMs,this.renderPage=renderPage2}static async listen(options={}){let host=options.host??"127.0.0.1",redirectHost=options.redirectHost??host,path=options.path??"/callback",instance,server=createServer((request,response)=>instance?.handle(request.url??"/",response));await new Promise((resolve2,reject)=>{server.once("error",reject),server.listen(options.port??0,host,()=>{server.off("error",reject),resolve2()})});let address=server.address();if(!address||typeof address=="string")throw new Error("OAuth callback server did not bind to TCP");return instance=new _OAuthCallbackServer(server,`http://${redirectHost.includes(":")?`[${redirectHost}]`:redirectHost}:${address.port}${path}`,[path,...options.extraPaths??[]],options.timeoutMs??5*6e4,options.renderPage),instance}waitForCallback(state,path){if(this.pending.has(state))throw new Error("OAuth state is already pending");return new Promise((resolve2,reject)=>{let timer=setTimeout(()=>{this.pending.delete(state),reject(new Error("OAuth callback timed out"))},this.timeoutMs);this.pending.set(state,{resolve:resolve2,reject,timer,path})})}async close(){for(let pending of this.pending.values())clearTimeout(pending.timer),pending.reject(new Error("OAuth callback server closed"));this.pending.clear(),await new Promise((resolve2,reject)=>{this.server.close(error=>error?reject(error):resolve2())})}reply(response,status,page){this.renderPage?(response.writeHead(status,{"content-type":"text/html; charset=utf-8","cache-control":"no-store"}),response.end(this.renderPage(page))):response.writeHead(status,{"content-type":"text/plain; charset=utf-8"}).end(plainText(page))}handle(rawUrl,response){let url=new URL(rawUrl,this.redirectUrl);if(!this.paths.includes(url.pathname)){this.reply(response,404,{ok:!1,message:"Not found"});return}let state=url.searchParams.get("state"),pending=state?this.pending.get(state):void 0;if(!state||!pending){this.reply(response,400,{ok:!1,message:"Invalid or expired OAuth state"});return}if(clearTimeout(pending.timer),this.pending.delete(state),pending.path!==void 0&&url.pathname!==pending.path){pending.reject(new Error("The authorization response arrived on another redirect URI")),this.reply(response,400,{ok:!1,message:"Unexpected redirect URI"});return}let error=url.searchParams.get("error");if(error){let description=url.searchParams.get("error_description")??error;pending.reject(new Error(description)),this.reply(response,200,{ok:!1,message:"Authorization failed. You may close this window.",details:description});return}let code=url.searchParams.get("code");if(!code){pending.reject(new Error("OAuth callback did not include an authorization code")),this.reply(response,400,{ok:!1,message:"Missing authorization code"});return}let iss=url.searchParams.get("iss");pending.resolve({code,state,...iss?{iss}:{}}),this.reply(response,200,{ok:!0})}};var OAuthError=class extends Error{code;errorUri;constructor(code,message,errorUri){super(message||code),this.name="OAuthError",this.code=code,this.errorUri=errorUri}},OAuthIssuerMismatchError=class extends Error{expected;received;constructor(expected,received){super(`OAuth issuer mismatch: expected ${JSON.stringify(expected)}, received ${received===void 0?"none":JSON.stringify(received)}`),this.name="OAuthIssuerMismatchError",this.expected=expected,this.received=received}},OAuthInsecureEndpointError=class extends Error{endpoint;constructor(endpoint){super(`Refusing to send OAuth credentials to non-HTTPS endpoint ${endpoint}`),this.name="OAuthInsecureEndpointError",this.endpoint=endpoint}},OAuthRegistrationError=class extends Error{status;body;constructor(status,body){super(`OAuth dynamic client registration failed with status ${status}: ${body}`),this.name="OAuthRegistrationError",this.status=status,this.body=body}},McpOAuthAuthorizationRequiredError=class extends Error{constructor(){super("MCP OAuth authorization requires user interaction"),this.name="McpOAuthAuthorizationRequiredError"}};function object(value,name){if(!isObject(value))throw new Error(`Invalid ${name}`);return value}function compact(value){return Object.fromEntries(Object.entries(value).filter(([,item])=>item!==void 0))}function requiredString(value,name){if(typeof value!="string"||value.length===0)throw new Error(`Invalid ${name}`);return value}function absent(value){return value==null||value===""}function optionalString(value,name){if(!absent(value))return requiredString(value,name)}function optionalStrings(value,name){if(value!=null){if(!Array.isArray(value)||value.some(item=>typeof item!="string"))throw new Error(`Invalid ${name}`);return[...value]}}function safeUrl(value,name){let text=requiredString(value,name);if(!URL.canParse(text))throw new Error(`Invalid ${name}`);let url=new URL(text);if(["javascript:","data:","vbscript:"].includes(url.protocol))throw new Error(`Invalid ${name}`);return text}function optionalUrl(value,name){return absent(value)?void 0:safeUrl(value,name)}function parseProtectedResourceMetadata(value){let input=object(value,"OAuth protected resource metadata");return compact({...input,resource:safeUrl(input.resource,"OAuth protected resource metadata resource"),authorization_servers:optionalStrings(input.authorization_servers,"authorization_servers")?.map(url=>safeUrl(url,"authorization server URL")),scopes_supported:optionalStrings(input.scopes_supported,"scopes_supported")})}function parseAuthorizationServerMetadata(value){let input=object(value,"authorization server metadata"),responseTypes=optionalStrings(input.response_types_supported,"response_types_supported");if(!responseTypes)throw new Error("Invalid response_types_supported");return compact({...input,issuer:safeUrl(input.issuer,"authorization server issuer"),authorization_endpoint:safeUrl(input.authorization_endpoint,"authorization endpoint"),token_endpoint:safeUrl(input.token_endpoint,"token endpoint"),registration_endpoint:optionalUrl(input.registration_endpoint,"registration endpoint"),scopes_supported:optionalStrings(input.scopes_supported,"scopes_supported"),response_types_supported:responseTypes,grant_types_supported:optionalStrings(input.grant_types_supported,"grant_types_supported"),token_endpoint_auth_methods_supported:optionalStrings(input.token_endpoint_auth_methods_supported,"token_endpoint_auth_methods_supported"),code_challenge_methods_supported:optionalStrings(input.code_challenge_methods_supported,"code_challenge_methods_supported"),client_id_metadata_document_supported:typeof input.client_id_metadata_document_supported=="boolean"?input.client_id_metadata_document_supported:void 0,authorization_response_iss_parameter_supported:typeof input.authorization_response_iss_parameter_supported=="boolean"?input.authorization_response_iss_parameter_supported:void 0})}function parseOAuthTokens(value){let input=object(value,"OAuth token response"),expires=absent(input.expires_in)?void 0:Number(input.expires_in);if(expires!==void 0&&!Number.isFinite(expires))throw new Error("Invalid expires_in");return compact({access_token:requiredString(input.access_token,"access_token"),token_type:requiredString(input.token_type,"token_type"),expires_in:expires,scope:optionalString(input.scope,"scope"),refresh_token:optionalString(input.refresh_token,"refresh_token"),id_token:optionalString(input.id_token,"id_token")})}function parseClientInformation(value){let input=object(value,"OAuth client registration response");return compact({...input,client_id:requiredString(input.client_id,"client_id"),client_secret:optionalString(input.client_secret,"client_secret"),client_id_issued_at:typeof input.client_id_issued_at=="number"?input.client_id_issued_at:void 0,client_secret_expires_at:typeof input.client_secret_expires_at=="number"?input.client_secret_expires_at:void 0,redirect_uris:optionalStrings(input.redirect_uris,"redirect_uris")??[]})}function discard(response){response?.body?.cancel().catch(()=>{})}function isDiscoveryMiss(status){return status>=400&&status<500||status===502}function pathSuffix(pathname){return pathname.endsWith("/")?pathname.slice(0,-1):pathname}function field(header,name){let match=header.match(new RegExp(String.raw`(?:^|[,\s])${name}=(?:"([^"]*)"|([^\s,]+))`,"i"));return match?.[1]||match?.[2]||void 0}function parseWwwAuthenticate(header){if(!header)return{};let scheme=header.trimStart().split(/\s+/,1)[0]?.toLowerCase();if(scheme!=="bearer"&&scheme!=="dpop")return{};let resourceMetadata=field(header,"resource_metadata"),resourceMetadataUrl;if(resourceMetadata)try{resourceMetadataUrl=new URL(resourceMetadata)}catch{}return{resourceMetadataUrl,scope:field(header,"scope"),error:field(header,"error"),errorDescription:field(header,"error_description")}}async function fetchMetadata(url,fetch,protocolVersion){return fetch(url,{headers:{Accept:"application/json","MCP-Protocol-Version":protocolVersion}})}async function discoverProtectedResourceMetadata(serverUrl,options={}){let server=new URL(serverUrl),fetch=options.fetch??globalThis.fetch,version=options.protocolVersion??LATEST_PROTOCOL_VERSION,response=await fetchMetadata(options.resourceMetadataUrl?new URL(options.resourceMetadataUrl):new URL(`/.well-known/oauth-protected-resource${pathSuffix(server.pathname)}`,server.origin),fetch,version);if(!options.resourceMetadataUrl&&server.pathname!=="/"&&isDiscoveryMiss(response.status)&&(discard(response),response=await fetchMetadata(new URL("/.well-known/oauth-protected-resource",server.origin),fetch,version)),!response.ok)throw discard(response),new Error(`HTTP ${response.status} loading OAuth protected resource metadata`);return parseProtectedResourceMetadata(await response.json())}function buildAuthorizationServerDiscoveryUrls(authorizationServerUrl){let issuer=new URL(authorizationServerUrl),path=pathSuffix(issuer.pathname),urls=[{url:new URL(`/.well-known/oauth-authorization-server${path}`,issuer.origin),type:"oauth"},{url:new URL(`/.well-known/openid-configuration${path}`,issuer.origin),type:"oidc"}];return path&&urls.push({url:new URL(`${path}/.well-known/openid-configuration`,issuer.origin),type:"oidc"}),urls}async function discoverAuthorizationServerMetadata(authorizationServerUrl,options={}){let fetch=options.fetch??globalThis.fetch;for(let{url}of buildAuthorizationServerDiscoveryUrls(authorizationServerUrl)){let response=await fetchMetadata(url,fetch,options.protocolVersion??LATEST_PROTOCOL_VERSION);if(!response.ok){if(discard(response),isDiscoveryMiss(response.status))continue;throw new Error(`HTTP ${response.status} loading authorization server metadata from ${url}`)}let metadata=parseAuthorizationServerMetadata(await response.json());if(!options.skipIssuerValidation){let expected=String(authorizationServerUrl),trim=value=>value.endsWith("/")?value.slice(0,-1):value;if(trim(metadata.issuer)!==trim(expected))throw new OAuthIssuerMismatchError(expected,metadata.issuer)}return metadata}}async function discoverOAuthServerInfo(serverUrl,options={}){let resourceMetadata;try{resourceMetadata=await discoverProtectedResourceMetadata(serverUrl,{resourceMetadataUrl:options.resourceMetadataUrl,fetch:options.fetch})}catch(error){if(error instanceof TypeError)throw error}if(options.authorizationServerMetadataUrl){let url=options.authorizationServerMetadataUrl,response=await fetchMetadata(url,options.fetch??globalThis.fetch,LATEST_PROTOCOL_VERSION);if(!response.ok)throw discard(response),new Error(`HTTP ${response.status} loading authorization server metadata from ${url}`);let metadata=parseAuthorizationServerMetadata(await response.json());return{authorizationServerUrl:metadata.issuer,authorizationServerMetadata:metadata,resourceMetadata}}let authorizationServerUrl=resourceMetadata?.authorization_servers?.[0]??String(new URL("/",serverUrl));return{authorizationServerUrl,authorizationServerMetadata:await discoverAuthorizationServerMetadata(authorizationServerUrl,{fetch:options.fetch,skipIssuerValidation:options.skipIssuerValidation}),resourceMetadata}}function resourceUrlFromServerUrl(value){let url=new URL(value);return url.hash="",url}function selectResource(serverUrl,metadata){if(!metadata)return;let requested=resourceUrlFromServerUrl(serverUrl),configured=new URL(metadata.resource);if(requested.origin!==configured.origin)throw new Error(`Protected resource ${metadata.resource} does not match MCP server ${requested}`);let requestedPath=requested.pathname.endsWith("/")?requested.pathname:`${requested.pathname}/`,configuredPath=configured.pathname.endsWith("/")?configured.pathname:`${configured.pathname}/`;if(!requestedPath.startsWith(configuredPath))throw new Error(`Protected resource ${metadata.resource} does not match MCP server ${requested}`);return metadata.resource}function loopback(hostname){return hostname==="localhost"||hostname==="127.0.0.1"||hostname==="[::1]"||hostname==="::1"}function secureEndpoint(value){let url=new URL(value);if(url.protocol!=="https:"&&!loopback(url.hostname))throw new OAuthInsecureEndpointError(url.href);return url}function selectClientAuthMethod(information,supported){let hinted="token_endpoint_auth_method"in information?information.token_endpoint_auth_method:void 0;return hinted&&["client_secret_basic","client_secret_post","none"].includes(hinted)&&(supported.length===0||supported.includes(hinted))?hinted:supported.length===0?information.client_secret?"client_secret_basic":"none":information.client_secret&&supported.includes("client_secret_basic")?"client_secret_basic":information.client_secret&&supported.includes("client_secret_post")?"client_secret_post":supported.includes("none")?"none":information.client_secret?"client_secret_post":"none"}function applyClientAuthentication(method,information,headers,params){if(method==="client_secret_basic"){if(!information.client_secret)throw new Error("client_secret_basic requires a client secret");headers.set("Authorization",`Basic ${Buffer.from(`${information.client_id}:${information.client_secret}`).toString("base64")}`)}else params.set("client_id",information.client_id),method==="client_secret_post"&&information.client_secret&&params.set("client_secret",information.client_secret)}async function pkce(){let bytes=crypto.getRandomValues(new Uint8Array(32)),verifier=Buffer.from(bytes).toString("base64url"),digest=await crypto.subtle.digest("SHA-256",new TextEncoder().encode(verifier));return{verifier,challenge:Buffer.from(digest).toString("base64url")}}async function startAuthorization(authorizationServerUrl,options){let metadata=options.metadata;if(metadata&&!metadata.response_types_supported.includes("code"))throw new Error("Authorization server does not support authorization codes");if(metadata?.code_challenge_methods_supported&&!metadata.code_challenge_methods_supported.includes("S256"))throw new Error("Authorization server does not support PKCE S256");let url=new URL(metadata?.authorization_endpoint??new URL("/authorize",authorizationServerUrl)),{verifier,challenge}=await pkce();return url.searchParams.set("response_type","code"),url.searchParams.set("client_id",options.clientInformation.client_id),url.searchParams.set("code_challenge",challenge),url.searchParams.set("code_challenge_method","S256"),url.searchParams.set("redirect_uri",String(options.redirectUrl)),options.state&&url.searchParams.set("state",options.state),options.scope&&url.searchParams.set("scope",options.scope),options.scope?.split(/\s+/).includes("offline_access")&&url.searchParams.set("prompt","consent"),options.resource&&url.searchParams.set("resource",options.resource),{authorizationUrl:url,codeVerifier:verifier}}async function tokenRequest(authorizationServerUrl,options,params){let url=secureEndpoint(options.metadata?.token_endpoint??new URL("/token",authorizationServerUrl)),headers=new Headers({Accept:"application/json","content-type":"application/x-www-form-urlencoded"});options.resource&&params.set("resource",options.resource),options.addClientAuthentication?await options.addClientAuthentication(headers,params,url,options.metadata):applyClientAuthentication(selectClientAuthMethod(options.clientInformation,options.metadata?.token_endpoint_auth_methods_supported??[]),options.clientInformation,headers,params);let response=await(options.fetch??globalThis.fetch)(url,{method:"POST",headers,body:params}),text=await response.text(),value;try{value=JSON.parse(text)}catch{}if(isObject(value)&&typeof value.error=="string")throw new OAuthError(value.error,typeof value.error_description=="string"?value.error_description:value.error,typeof value.error_uri=="string"?value.error_uri:void 0);if(!response.ok)throw new OAuthError("server_error",`HTTP ${response.status}: ${text}`);return parseOAuthTokens(value)}async function registerClient(authorizationServerUrl,options){let endpoint=options.metadata?.registration_endpoint;if(options.metadata&&!endpoint)throw new Error("Authorization server does not support dynamic client registration");let response=await(options.fetch??globalThis.fetch)(new URL(endpoint??new URL("/register",authorizationServerUrl)),{method:"POST",headers:{Accept:"application/json","content-type":"application/json"},body:JSON.stringify({...options.clientMetadata,...options.scope?{scope:options.scope}:{}})});if(!response.ok)throw new OAuthRegistrationError(response.status,await response.text());return parseClientInformation(await response.json())}async function exchangeAuthorizationCode(authorizationServerUrl,options){return tokenRequest(authorizationServerUrl,options,new URLSearchParams({grant_type:"authorization_code",code:options.code,code_verifier:options.codeVerifier,redirect_uri:String(options.redirectUrl)}))}async function refreshAuthorization(authorizationServerUrl,options){let tokens=await tokenRequest(authorizationServerUrl,options,new URLSearchParams({grant_type:"refresh_token",refresh_token:options.refreshToken}));return{refresh_token:options.refreshToken,...tokens}}function withScope(tokens,scope){return tokens.scope===void 0&&scope?{...tokens,scope}:tokens}function stepUpScope(granted,challenged){if(!challenged)return;let scopes=[granted,challenged].flatMap(scope=>scope?.split(/\s+/).filter(Boolean)??[]);return[...new Set(scopes)].join(" ")}async function runFlow(provider,options){let metadataUrl=options.authorizationServerMetadataUrl&&secureEndpoint(options.authorizationServerMetadataUrl),cached=metadataUrl?void 0:await provider.discoveryState?.(),discovered=cached?.authorizationServerUrl?{authorizationServerUrl:cached.authorizationServerUrl,authorizationServerMetadata:cached.authorizationServerMetadata??await discoverAuthorizationServerMetadata(cached.authorizationServerUrl,{fetch:options.fetch,skipIssuerValidation:options.skipIssuerValidation}),resourceMetadata:cached.resourceMetadata}:await discoverOAuthServerInfo(options.serverUrl,{resourceMetadataUrl:options.resourceMetadataUrl,authorizationServerMetadataUrl:metadataUrl,fetch:options.fetch,skipIssuerValidation:options.skipIssuerValidation});metadataUrl||await provider.saveDiscoveryState?.({...discovered,...options.resourceMetadataUrl?{resourceMetadataUrl:options.resourceMetadataUrl.href}:{}});let metadata=discovered.authorizationServerMetadata,resource=selectResource(options.serverUrl,discovered.resourceMetadata),scope=options.scope||discovered.resourceMetadata?.scopes_supported?.join(" ")||provider.clientMetadata.scope,stored=await provider.clientInformation(),clientDocument=stored?void 0:provider.clientMetadataDocument?.(metadata);if(clientDocument){let url=new URL(clientDocument.url);if(url.protocol!=="https:"||url.pathname==="/")throw new Error("Invalid OAuth client metadata URL")}let client=stored??(clientDocument&&{client_id:clientDocument.url});if(!client){if(options.authorizationCode)throw new Error("OAuth client information is missing during code exchange");if(!provider.saveClientInformation)throw new Error("OAuth client information cannot be persisted");client=await registerClient(discovered.authorizationServerUrl,{metadata,clientMetadata:provider.clientMetadata,scope,fetch:options.fetch}),await provider.saveClientInformation(client)}let redirectUrl=clientDocument?.redirectUrl??provider.redirectUrl,tokenOptions={metadata,clientInformation:client,resource,addClientAuthentication:provider.addClientAuthentication,fetch:options.fetch};if(options.authorizationCode){let iss=options.iss;if(metadata&&(iss!==void 0||metadata.authorization_response_iss_parameter_supported)&&iss!==metadata.issuer)throw new OAuthIssuerMismatchError(metadata.issuer,iss);let tokens=await exchangeAuthorizationCode(discovered.authorizationServerUrl,{...tokenOptions,code:options.authorizationCode,codeVerifier:await provider.codeVerifier(),redirectUrl});return await provider.saveTokens(withScope(tokens,scope)),"AUTHORIZED"}let existing=options.skipRefresh?void 0:await provider.tokens();if(existing?.refresh_token)try{let tokens=await refreshAuthorization(discovered.authorizationServerUrl,{...tokenOptions,refreshToken:existing.refresh_token});return await provider.saveTokens(withScope(tokens,existing.scope)),"AUTHORIZED"}catch(error){if(error instanceof OAuthInsecureEndpointError||error instanceof OAuthError&&error.code!=="server_error")throw error}let state=await provider.state?.(),authorization=await startAuthorization(discovered.authorizationServerUrl,{metadata,clientInformation:client,redirectUrl,scope,state,resource});return await provider.saveCodeVerifier(authorization.codeVerifier),await provider.redirectToAuthorization(authorization.authorizationUrl),"REDIRECT"}async function authorizeMcp(provider,options){try{return await runFlow(provider,options)}catch(error){if(error instanceof OAuthError&&["invalid_client","unauthorized_client"].includes(error.code))return await provider.invalidateCredentials?.("all"),runFlow(provider,options);if(error instanceof OAuthError&&error.code==="invalid_grant")return await provider.invalidateCredentials?.("tokens"),runFlow(provider,options);throw error}}var MemoryOAuthStateStore=class{value;load(){return this.value===void 0?void 0:structuredClone(this.value)}save(state){this.value=structuredClone(state)}},McpOAuthProvider=class{redirectUrl;clientMetadata;clientMetadataDocument;serverUrl;configuredClient;store;onRedirect;writes=Promise.resolve();constructor(options){this.serverUrl=String(new URL(options.serverUrl)),this.redirectUrl=String(options.redirectUrl),this.clientMetadata={...options.clientMetadata,redirect_uris:options.clientMetadata.redirect_uris??[this.redirectUrl],grant_types:options.clientMetadata.grant_types??["authorization_code","refresh_token"],response_types:options.clientMetadata.response_types??["code"],token_endpoint_auth_method:options.clientMetadata.token_endpoint_auth_method??(options.clientSecret?"client_secret_post":"none")},this.clientMetadataDocument=options.clientMetadataDocument,this.configuredClient=options.clientId?{client_id:options.clientId,...options.clientSecret?{client_secret:options.clientSecret}:{}}:void 0,this.store=options.store??new MemoryOAuthStateStore,this.onRedirect=options.onRedirect}async state(){let existing=(await this.load()).oauthState;if(existing)return existing;let state=Buffer.from(crypto.getRandomValues(new Uint8Array(32))).toString("hex");return await this.update(value=>({...value,oauthState:state})),state}async clientInformation(){return this.configuredClient??(await this.load()).clientInformation}async saveClientInformation(information){this.configuredClient||await this.update(value=>({...value,clientInformation:information}))}async tokens(){return(await this.load()).tokens}async saveTokens(tokens){let expiresAt=tokens.expires_in===void 0?void 0:Date.now()+tokens.expires_in*1e3;await this.update(value=>{let next={...value,tokens};return expiresAt===void 0?delete next.tokensExpireAt:next.tokensExpireAt=expiresAt,next})}async redirectToAuthorization(url){await this.onRedirect(url)}async saveCodeVerifier(verifier){await this.update(value=>({...value,codeVerifier:verifier}))}async codeVerifier(){let verifier=(await this.load()).codeVerifier;if(!verifier)throw new Error("No OAuth PKCE code verifier is stored");return verifier}async invalidateCredentials(kind){await this.update(value=>{let next={...value};return(kind==="all"||kind==="client")&&delete next.clientInformation,(kind==="all"||kind==="tokens")&&(delete next.tokens,delete next.tokensExpireAt),(kind==="all"||kind==="verifier")&&delete next.codeVerifier,(kind==="all"||kind==="discovery")&&delete next.discovery,kind==="all"&&delete next.oauthState,next})}async saveDiscoveryState(discovery){await this.update(value=>({...value,discovery}))}async discoveryState(){return(await this.load()).discovery}async load(){return await this.writes,this.own(await this.store.load())}async update(update){this.writes=this.writes.then(async()=>{await this.store.save(update(this.own(await this.store.load())))}),await this.writes}own(state){return state?.serverUrl===this.serverUrl?state:{serverUrl:this.serverUrl}}};import{createHash}from"node:crypto";import{mkdirSync}from"node:fs";import{join}from"node:path";var LOGO_SVG='<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 800 800" aria-hidden="true"><path fill="#F09082" d="M165.29 165.29H517.36V400H400V282.65H165.29Z"/><path fill="#4D9ABF" d="M165.29 282.65H282.65V400H400V517.36H282.65V634.72H165.29Z"/><path fill="#F1BE58" d="M517.36 400H634.72V634.72H517.36Z"/></svg>';function escapeHtml(value){return value.replaceAll("&","&amp;").replaceAll("<","&lt;").replaceAll(">","&gt;").replaceAll('"',"&quot;").replaceAll("'","&#39;")}function renderPage(options){let title=escapeHtml(options.title),heading=escapeHtml(options.heading),message=escapeHtml(options.message),details=options.details?escapeHtml(options.details):void 0;return`<!doctype html>
4
+ ${page.details}`:page.message}var OAuthCallbackServer=class _OAuthCallbackServer{redirectUrl;server;paths;timeoutMs;renderPage;pending=new Map;constructor(server,redirectUrl,paths,timeoutMs,renderPage2){this.server=server,this.redirectUrl=redirectUrl,this.paths=paths,this.timeoutMs=timeoutMs,this.renderPage=renderPage2}static async listen(options={}){let host=options.host??"127.0.0.1",redirectHost=options.redirectHost??host,path=options.path??"/callback",instance,server=createServer((request,response)=>instance?.handle(request.url??"/",response));await new Promise((resolve2,reject)=>{server.once("error",reject),server.listen(options.port??0,host,()=>{server.off("error",reject),resolve2()})});let address=server.address();if(!address||typeof address=="string")throw new Error("OAuth callback server did not bind to TCP");return instance=new _OAuthCallbackServer(server,`http://${redirectHost.includes(":")?`[${redirectHost}]`:redirectHost}:${address.port}${path}`,[path,...options.extraPaths??[]],options.timeoutMs??5*6e4,options.renderPage),instance}waitForCallback(state,path){if(this.pending.has(state))throw new Error("OAuth state is already pending");return new Promise((resolve2,reject)=>{let timer=setTimeout(()=>{this.pending.delete(state),reject(new Error("OAuth callback timed out"))},this.timeoutMs);this.pending.set(state,{resolve:resolve2,reject,timer,path})})}async close(){for(let pending of this.pending.values())clearTimeout(pending.timer),pending.reject(new Error("OAuth callback server closed"));this.pending.clear(),await new Promise((resolve2,reject)=>{this.server.close(error=>error?reject(error):resolve2())})}reply(response,status,page){this.renderPage?(response.writeHead(status,{"content-type":"text/html; charset=utf-8","cache-control":"no-store"}),response.end(this.renderPage(page))):response.writeHead(status,{"content-type":"text/plain; charset=utf-8"}).end(plainText(page))}handle(rawUrl,response){let url=new URL(rawUrl,this.redirectUrl);if(!this.paths.includes(url.pathname)){this.reply(response,404,{ok:!1,message:"Not found"});return}let state=url.searchParams.get("state"),pending=state?this.pending.get(state):void 0;if(!state||!pending){this.reply(response,400,{ok:!1,message:"Invalid or expired OAuth state"});return}if(clearTimeout(pending.timer),this.pending.delete(state),pending.path!==void 0&&url.pathname!==pending.path){pending.reject(new Error("The authorization response arrived on another redirect URI")),this.reply(response,400,{ok:!1,message:"Unexpected redirect URI"});return}let error=url.searchParams.get("error");if(error){let description=url.searchParams.get("error_description")??error;pending.reject(new Error(description)),this.reply(response,200,{ok:!1,message:"Authorization failed. You may close this window.",details:description});return}let code=url.searchParams.get("code");if(!code){pending.reject(new Error("OAuth callback did not include an authorization code")),this.reply(response,400,{ok:!1,message:"Missing authorization code"});return}let iss=url.searchParams.get("iss");pending.resolve({code,state,...iss?{iss}:{}}),this.reply(response,200,{ok:!0})}};var OAuthError=class extends Error{code;errorUri;constructor(code,message,errorUri){super(message||code),this.name="OAuthError",this.code=code,this.errorUri=errorUri}},OAuthIssuerMismatchError=class extends Error{expected;received;constructor(expected,received){super(`OAuth issuer mismatch: expected ${JSON.stringify(expected)}, received ${received===void 0?"none":JSON.stringify(received)}`),this.name="OAuthIssuerMismatchError",this.expected=expected,this.received=received}},OAuthInsecureEndpointError=class extends Error{endpoint;constructor(endpoint){super(`Refusing to send OAuth credentials to non-HTTPS endpoint ${endpoint}`),this.name="OAuthInsecureEndpointError",this.endpoint=endpoint}},OAuthRegistrationError=class extends Error{status;body;constructor(status,body){super(`OAuth dynamic client registration failed with status ${status}: ${body}`),this.name="OAuthRegistrationError",this.status=status,this.body=body}},McpOAuthAuthorizationRequiredError=class extends Error{constructor(){super("MCP OAuth authorization requires user interaction"),this.name="McpOAuthAuthorizationRequiredError"}};function object(value,name){if(!isObject(value))throw new Error(`Invalid ${name}`);return value}function compact(value){return Object.fromEntries(Object.entries(value).filter(([,item])=>item!==void 0))}function requiredString(value,name){if(typeof value!="string"||value.length===0)throw new Error(`Invalid ${name}`);return value}function absent(value){return value==null||value===""}function optionalString(value,name){if(!absent(value))return requiredString(value,name)}function optionalStrings(value,name){if(value!=null){if(!Array.isArray(value)||value.some(item=>typeof item!="string"))throw new Error(`Invalid ${name}`);return[...value]}}function safeUrl(value,name){let text=requiredString(value,name);if(!URL.canParse(text))throw new Error(`Invalid ${name}`);let url=new URL(text);if(["javascript:","data:","vbscript:"].includes(url.protocol))throw new Error(`Invalid ${name}`);return text}function optionalUrl(value,name){return absent(value)?void 0:safeUrl(value,name)}function parseProtectedResourceMetadata(value){let input=object(value,"OAuth protected resource metadata");return compact({...input,resource:safeUrl(input.resource,"OAuth protected resource metadata resource"),authorization_servers:optionalStrings(input.authorization_servers,"authorization_servers")?.map(url=>safeUrl(url,"authorization server URL")),scopes_supported:optionalStrings(input.scopes_supported,"scopes_supported")})}function parseAuthorizationServerMetadata(value){let input=object(value,"authorization server metadata"),responseTypes=optionalStrings(input.response_types_supported,"response_types_supported");if(!responseTypes)throw new Error("Invalid response_types_supported");return compact({...input,issuer:safeUrl(input.issuer,"authorization server issuer"),authorization_endpoint:safeUrl(input.authorization_endpoint,"authorization endpoint"),token_endpoint:safeUrl(input.token_endpoint,"token endpoint"),registration_endpoint:optionalUrl(input.registration_endpoint,"registration endpoint"),scopes_supported:optionalStrings(input.scopes_supported,"scopes_supported"),response_types_supported:responseTypes,grant_types_supported:optionalStrings(input.grant_types_supported,"grant_types_supported"),token_endpoint_auth_methods_supported:optionalStrings(input.token_endpoint_auth_methods_supported,"token_endpoint_auth_methods_supported"),code_challenge_methods_supported:optionalStrings(input.code_challenge_methods_supported,"code_challenge_methods_supported"),client_id_metadata_document_supported:typeof input.client_id_metadata_document_supported=="boolean"?input.client_id_metadata_document_supported:void 0,authorization_response_iss_parameter_supported:typeof input.authorization_response_iss_parameter_supported=="boolean"?input.authorization_response_iss_parameter_supported:void 0})}function parseOAuthTokens(value){let input=object(value,"OAuth token response"),expires=absent(input.expires_in)?void 0:Number(input.expires_in);if(expires!==void 0&&!Number.isFinite(expires))throw new Error("Invalid expires_in");return compact({access_token:requiredString(input.access_token,"access_token"),token_type:requiredString(input.token_type,"token_type"),expires_in:expires,scope:optionalString(input.scope,"scope"),refresh_token:optionalString(input.refresh_token,"refresh_token"),id_token:optionalString(input.id_token,"id_token")})}function parseClientInformation(value){let input=object(value,"OAuth client registration response");return compact({...input,client_id:requiredString(input.client_id,"client_id"),client_secret:optionalString(input.client_secret,"client_secret"),client_id_issued_at:typeof input.client_id_issued_at=="number"?input.client_id_issued_at:void 0,client_secret_expires_at:typeof input.client_secret_expires_at=="number"?input.client_secret_expires_at:void 0,redirect_uris:optionalStrings(input.redirect_uris,"redirect_uris")??[]})}function discard(response){response?.body?.cancel().catch(()=>{})}function isDiscoveryMiss(status){return status>=400&&status<500||status===502}function pathSuffix(pathname){return pathname.endsWith("/")?pathname.slice(0,-1):pathname}function field(header,name){let match=header.match(new RegExp(String.raw`(?:^|[,\s])${name}=(?:"([^"]*)"|([^\s,]+))`,"i"));return match?.[1]||match?.[2]||void 0}function parseWwwAuthenticate(header){if(!header)return{};let scheme=header.trimStart().split(/\s+/,1)[0]?.toLowerCase();if(scheme!=="bearer"&&scheme!=="dpop")return{};let resourceMetadata=field(header,"resource_metadata"),resourceMetadataUrl;if(resourceMetadata)try{resourceMetadataUrl=new URL(resourceMetadata)}catch{}return{resourceMetadataUrl,scope:field(header,"scope"),error:field(header,"error"),errorDescription:field(header,"error_description")}}async function fetchMetadata(url,fetch,protocolVersion){return fetch(url,{headers:{Accept:"application/json","MCP-Protocol-Version":protocolVersion}})}async function discoverProtectedResourceMetadata(serverUrl,options={}){let server=new URL(serverUrl),fetch=options.fetch??globalThis.fetch,version=options.protocolVersion??LATEST_PROTOCOL_VERSION,response=await fetchMetadata(options.resourceMetadataUrl?new URL(options.resourceMetadataUrl):new URL(`/.well-known/oauth-protected-resource${pathSuffix(server.pathname)}`,server.origin),fetch,version);if(!options.resourceMetadataUrl&&server.pathname!=="/"&&isDiscoveryMiss(response.status)&&(discard(response),response=await fetchMetadata(new URL("/.well-known/oauth-protected-resource",server.origin),fetch,version)),!response.ok)throw discard(response),new Error(`HTTP ${response.status} loading OAuth protected resource metadata`);return parseProtectedResourceMetadata(await response.json())}function buildAuthorizationServerDiscoveryUrls(authorizationServerUrl){let issuer=new URL(authorizationServerUrl),path=pathSuffix(issuer.pathname),urls=[{url:new URL(`/.well-known/oauth-authorization-server${path}`,issuer.origin),type:"oauth"},{url:new URL(`/.well-known/openid-configuration${path}`,issuer.origin),type:"oidc"}];return path&&urls.push({url:new URL(`${path}/.well-known/openid-configuration`,issuer.origin),type:"oidc"}),urls}async function discoverAuthorizationServerMetadata(authorizationServerUrl,options={}){let fetch=options.fetch??globalThis.fetch;for(let{url}of buildAuthorizationServerDiscoveryUrls(authorizationServerUrl)){let response=await fetchMetadata(url,fetch,options.protocolVersion??LATEST_PROTOCOL_VERSION);if(!response.ok){if(discard(response),isDiscoveryMiss(response.status))continue;throw new Error(`HTTP ${response.status} loading authorization server metadata from ${url}`)}let metadata=parseAuthorizationServerMetadata(await response.json());if(!options.skipIssuerValidation){let expected=String(authorizationServerUrl),trim=value=>value.endsWith("/")?value.slice(0,-1):value;if(trim(metadata.issuer)!==trim(expected))throw new OAuthIssuerMismatchError(expected,metadata.issuer)}return metadata}}async function discoverOAuthServerInfo(serverUrl,options={}){let resourceMetadata;try{resourceMetadata=await discoverProtectedResourceMetadata(serverUrl,{resourceMetadataUrl:options.resourceMetadataUrl,fetch:options.fetch})}catch(error){if(error instanceof TypeError)throw error}if(options.authorizationServerMetadataUrl){let url=options.authorizationServerMetadataUrl,response=await fetchMetadata(url,options.fetch??globalThis.fetch,LATEST_PROTOCOL_VERSION);if(!response.ok)throw discard(response),new Error(`HTTP ${response.status} loading authorization server metadata from ${url}`);let metadata=parseAuthorizationServerMetadata(await response.json());return{authorizationServerUrl:metadata.issuer,authorizationServerMetadata:metadata,resourceMetadata}}let authorizationServerUrl=resourceMetadata?.authorization_servers?.[0]??String(new URL("/",serverUrl));return{authorizationServerUrl,authorizationServerMetadata:await discoverAuthorizationServerMetadata(authorizationServerUrl,{fetch:options.fetch,skipIssuerValidation:options.skipIssuerValidation}),resourceMetadata}}function resourceUrlFromServerUrl(value){let url=new URL(value);return url.hash="",url}function selectResource(serverUrl,metadata){if(!metadata)return;let requested=resourceUrlFromServerUrl(serverUrl),configured=new URL(metadata.resource);if(requested.origin!==configured.origin)throw new Error(`Protected resource ${metadata.resource} does not match MCP server ${requested}`);let requestedPath=requested.pathname.endsWith("/")?requested.pathname:`${requested.pathname}/`,configuredPath=configured.pathname.endsWith("/")?configured.pathname:`${configured.pathname}/`;if(!requestedPath.startsWith(configuredPath))throw new Error(`Protected resource ${metadata.resource} does not match MCP server ${requested}`);return metadata.resource}function loopback(hostname){return hostname==="localhost"||hostname==="127.0.0.1"||hostname==="[::1]"||hostname==="::1"}function applicationType(redirectUris){return redirectUris.some(uri=>{if(!URL.canParse(uri))return!1;let url=new URL(uri);return url.protocol!=="http:"&&url.protocol!=="https:"||loopback(url.hostname)})?"native":"web"}function secureEndpoint(value){let url=new URL(value);if(url.protocol!=="https:"&&!loopback(url.hostname))throw new OAuthInsecureEndpointError(url.href);return url}function selectClientAuthMethod(information,supported){let hinted="token_endpoint_auth_method"in information?information.token_endpoint_auth_method:void 0;return hinted&&["client_secret_basic","client_secret_post","none"].includes(hinted)&&(supported.length===0||supported.includes(hinted))?hinted:supported.length===0?information.client_secret?"client_secret_basic":"none":information.client_secret&&supported.includes("client_secret_basic")?"client_secret_basic":information.client_secret&&supported.includes("client_secret_post")?"client_secret_post":supported.includes("none")?"none":information.client_secret?"client_secret_post":"none"}function applyClientAuthentication(method,information,headers,params){if(method==="client_secret_basic"){if(!information.client_secret)throw new Error("client_secret_basic requires a client secret");headers.set("Authorization",`Basic ${Buffer.from(`${information.client_id}:${information.client_secret}`).toString("base64")}`)}else params.set("client_id",information.client_id),method==="client_secret_post"&&information.client_secret&&params.set("client_secret",information.client_secret)}async function pkce(){let bytes=crypto.getRandomValues(new Uint8Array(32)),verifier=Buffer.from(bytes).toString("base64url"),digest=await crypto.subtle.digest("SHA-256",new TextEncoder().encode(verifier));return{verifier,challenge:Buffer.from(digest).toString("base64url")}}async function startAuthorization(authorizationServerUrl,options){let metadata=options.metadata;if(metadata&&!metadata.response_types_supported.includes("code"))throw new Error("Authorization server does not support authorization codes");if(metadata?.code_challenge_methods_supported&&!metadata.code_challenge_methods_supported.includes("S256"))throw new Error("Authorization server does not support PKCE S256");let url=new URL(metadata?.authorization_endpoint??new URL("/authorize",authorizationServerUrl)),{verifier,challenge}=await pkce();return url.searchParams.set("response_type","code"),url.searchParams.set("client_id",options.clientInformation.client_id),url.searchParams.set("code_challenge",challenge),url.searchParams.set("code_challenge_method","S256"),url.searchParams.set("redirect_uri",String(options.redirectUrl)),options.state&&url.searchParams.set("state",options.state),options.scope&&url.searchParams.set("scope",options.scope),options.scope?.split(/\s+/).includes("offline_access")&&url.searchParams.set("prompt","consent"),options.resource&&url.searchParams.set("resource",options.resource),{authorizationUrl:url,codeVerifier:verifier}}async function tokenRequest(authorizationServerUrl,options,params){let url=secureEndpoint(options.metadata?.token_endpoint??new URL("/token",authorizationServerUrl)),headers=new Headers({Accept:"application/json","content-type":"application/x-www-form-urlencoded"});options.resource&&params.set("resource",options.resource),options.addClientAuthentication?await options.addClientAuthentication(headers,params,url,options.metadata):applyClientAuthentication(selectClientAuthMethod(options.clientInformation,options.metadata?.token_endpoint_auth_methods_supported??[]),options.clientInformation,headers,params);let response=await(options.fetch??globalThis.fetch)(url,{method:"POST",headers,body:params}),text=await response.text(),value;try{value=JSON.parse(text)}catch{}if(isObject(value)&&typeof value.error=="string")throw new OAuthError(value.error,typeof value.error_description=="string"?value.error_description:value.error,typeof value.error_uri=="string"?value.error_uri:void 0);if(!response.ok)throw new OAuthError("server_error",`HTTP ${response.status}: ${text}`);return parseOAuthTokens(value)}async function registerClient(authorizationServerUrl,options){let endpoint=options.metadata?.registration_endpoint;if(options.metadata&&!endpoint)throw new Error("Authorization server does not support dynamic client registration");let response=await(options.fetch??globalThis.fetch)(new URL(endpoint??new URL("/register",authorizationServerUrl)),{method:"POST",headers:{Accept:"application/json","content-type":"application/json"},body:JSON.stringify({...options.clientMetadata,application_type:options.clientMetadata.application_type??applicationType(options.clientMetadata.redirect_uris),...options.scope?{scope:options.scope}:{}})});if(!response.ok)throw new OAuthRegistrationError(response.status,await response.text());return parseClientInformation(await response.json())}async function exchangeAuthorizationCode(authorizationServerUrl,options){return tokenRequest(authorizationServerUrl,options,new URLSearchParams({grant_type:"authorization_code",code:options.code,code_verifier:options.codeVerifier,redirect_uri:String(options.redirectUrl)}))}async function refreshAuthorization(authorizationServerUrl,options){let tokens=await tokenRequest(authorizationServerUrl,options,new URLSearchParams({grant_type:"refresh_token",refresh_token:options.refreshToken}));return{refresh_token:options.refreshToken,...tokens}}function withScope(tokens,scope){return tokens.scope===void 0&&scope?{...tokens,scope}:tokens}function stepUpScope(granted,challenged){if(!challenged)return;let scopes=[granted,challenged].flatMap(scope=>scope?.split(/\s+/).filter(Boolean)??[]);return[...new Set(scopes)].join(" ")}async function runFlow(provider,options){let metadataUrl=options.authorizationServerMetadataUrl&&secureEndpoint(options.authorizationServerMetadataUrl),cached=metadataUrl?void 0:await provider.discoveryState?.(),discovered=cached?.authorizationServerUrl?{authorizationServerUrl:cached.authorizationServerUrl,authorizationServerMetadata:cached.authorizationServerMetadata??await discoverAuthorizationServerMetadata(cached.authorizationServerUrl,{fetch:options.fetch,skipIssuerValidation:options.skipIssuerValidation}),resourceMetadata:cached.resourceMetadata}:await discoverOAuthServerInfo(options.serverUrl,{resourceMetadataUrl:options.resourceMetadataUrl,authorizationServerMetadataUrl:metadataUrl,fetch:options.fetch,skipIssuerValidation:options.skipIssuerValidation});metadataUrl||await provider.saveDiscoveryState?.({...discovered,...options.resourceMetadataUrl?{resourceMetadataUrl:options.resourceMetadataUrl.href}:{}});let metadata=discovered.authorizationServerMetadata,resource=selectResource(options.serverUrl,discovered.resourceMetadata),scope=options.scope||discovered.resourceMetadata?.scopes_supported?.join(" ")||provider.clientMetadata.scope,stored=await provider.clientInformation(),clientDocument=stored?void 0:provider.clientMetadataDocument?.(metadata);if(clientDocument){let url=new URL(clientDocument.url);if(url.protocol!=="https:"||url.pathname==="/")throw new Error("Invalid OAuth client metadata URL")}let client=stored??(clientDocument&&{client_id:clientDocument.url});if(!client){if(options.authorizationCode)throw new Error("OAuth client information is missing during code exchange");if(!provider.saveClientInformation)throw new Error("OAuth client information cannot be persisted");client=await registerClient(discovered.authorizationServerUrl,{metadata,clientMetadata:provider.clientMetadata,scope,fetch:options.fetch}),await provider.saveClientInformation(client)}let redirectUrl=clientDocument?.redirectUrl??provider.redirectUrl,tokenOptions={metadata,clientInformation:client,resource,addClientAuthentication:provider.addClientAuthentication,fetch:options.fetch};if(options.authorizationCode){let iss=options.iss;if(metadata&&(iss!==void 0||metadata.authorization_response_iss_parameter_supported)&&iss!==metadata.issuer)throw new OAuthIssuerMismatchError(metadata.issuer,iss);let tokens=await exchangeAuthorizationCode(discovered.authorizationServerUrl,{...tokenOptions,code:options.authorizationCode,codeVerifier:await provider.codeVerifier(),redirectUrl});return await provider.saveTokens(withScope(tokens,scope)),"AUTHORIZED"}let existing=options.skipRefresh?void 0:await provider.tokens();if(existing?.refresh_token)try{let tokens=await refreshAuthorization(discovered.authorizationServerUrl,{...tokenOptions,refreshToken:existing.refresh_token});return await provider.saveTokens(withScope(tokens,existing.scope)),"AUTHORIZED"}catch(error){if(error instanceof OAuthInsecureEndpointError||error instanceof OAuthError&&error.code!=="server_error")throw error}let state=await provider.state?.(),authorization=await startAuthorization(discovered.authorizationServerUrl,{metadata,clientInformation:client,redirectUrl,scope,state,resource});return await provider.saveCodeVerifier(authorization.codeVerifier),await provider.redirectToAuthorization(authorization.authorizationUrl),"REDIRECT"}async function authorizeMcp(provider,options){try{return await runFlow(provider,options)}catch(error){if(error instanceof OAuthError&&["invalid_client","unauthorized_client"].includes(error.code))return await provider.invalidateCredentials?.("all"),runFlow(provider,options);if(error instanceof OAuthError&&error.code==="invalid_grant")return await provider.invalidateCredentials?.("tokens"),runFlow(provider,options);throw error}}var MemoryOAuthStateStore=class{value;load(){return this.value===void 0?void 0:structuredClone(this.value)}save(state){this.value=structuredClone(state)}},McpOAuthProvider=class{redirectUrl;clientMetadata;clientMetadataDocument;serverUrl;configuredClient;store;onRedirect;writes=Promise.resolve();constructor(options){this.serverUrl=String(new URL(options.serverUrl)),this.redirectUrl=String(options.redirectUrl),this.clientMetadata={...options.clientMetadata,redirect_uris:options.clientMetadata.redirect_uris??[this.redirectUrl],grant_types:options.clientMetadata.grant_types??["authorization_code","refresh_token"],response_types:options.clientMetadata.response_types??["code"],token_endpoint_auth_method:options.clientMetadata.token_endpoint_auth_method??(options.clientSecret?"client_secret_post":"none")},this.clientMetadataDocument=options.clientMetadataDocument,this.configuredClient=options.clientId?{client_id:options.clientId,...options.clientSecret?{client_secret:options.clientSecret}:{}}:void 0,this.store=options.store??new MemoryOAuthStateStore,this.onRedirect=options.onRedirect}async state(){let existing=(await this.load()).oauthState;if(existing)return existing;let state=Buffer.from(crypto.getRandomValues(new Uint8Array(32))).toString("hex");return await this.update(value=>({...value,oauthState:state})),state}async clientInformation(){return this.configuredClient??(await this.load()).clientInformation}async saveClientInformation(information){this.configuredClient||await this.update(value=>({...value,clientInformation:information}))}async tokens(){return(await this.load()).tokens}async saveTokens(tokens){let expiresAt=tokens.expires_in===void 0?void 0:Date.now()+tokens.expires_in*1e3;await this.update(value=>{let next={...value,tokens};return expiresAt===void 0?delete next.tokensExpireAt:next.tokensExpireAt=expiresAt,next})}async redirectToAuthorization(url){await this.onRedirect(url)}async saveCodeVerifier(verifier){await this.update(value=>({...value,codeVerifier:verifier}))}async codeVerifier(){let verifier=(await this.load()).codeVerifier;if(!verifier)throw new Error("No OAuth PKCE code verifier is stored");return verifier}async invalidateCredentials(kind){await this.update(value=>{let next={...value};return(kind==="all"||kind==="client")&&delete next.clientInformation,(kind==="all"||kind==="tokens")&&(delete next.tokens,delete next.tokensExpireAt),(kind==="all"||kind==="verifier")&&delete next.codeVerifier,(kind==="all"||kind==="discovery")&&delete next.discovery,kind==="all"&&delete next.oauthState,next})}async saveDiscoveryState(discovery){await this.update(value=>({...value,discovery}))}async discoveryState(){return(await this.load()).discovery}async load(){return await this.writes,this.own(await this.store.load())}async update(update){this.writes=this.writes.then(async()=>{await this.store.save(update(this.own(await this.store.load())))}),await this.writes}own(state){return state?.serverUrl===this.serverUrl?state:{serverUrl:this.serverUrl}}};import{createHash}from"node:crypto";import{mkdirSync}from"node:fs";import{join}from"node:path";var LOGO_SVG='<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 800 800" aria-hidden="true"><path fill="#F09082" d="M165.29 165.29H517.36V400H400V282.65H165.29Z"/><path fill="#4D9ABF" d="M165.29 282.65H282.65V400H400V517.36H282.65V634.72H165.29Z"/><path fill="#F1BE58" d="M517.36 400H634.72V634.72H517.36Z"/></svg>';function escapeHtml(value){return value.replaceAll("&","&amp;").replaceAll("<","&lt;").replaceAll(">","&gt;").replaceAll('"',"&quot;").replaceAll("'","&#39;")}function renderPage(options){let title=escapeHtml(options.title),heading=escapeHtml(options.heading),message=escapeHtml(options.message),details=options.details?escapeHtml(options.details):void 0;return`<!doctype html>
5
5
  <html lang="en">
6
6
  <head>
7
7
  <meta charset="utf-8" />
@@ -77,6 +77,6 @@ ${page.details}`:page.message}var OAuthCallbackServer=class _OAuthCallbackServer
77
77
  </html>`}function oauthSuccessHtml(message){return renderPage({title:"Authentication successful",heading:"Authentication successful",message})}function oauthErrorHtml(message,details){return renderPage({title:"Authentication failed",heading:"Authentication failed",message,details})}var import_proper_lockfile=__toESM(require_proper_lockfile(),1);var CALLBACK_HOST="127.0.0.1",CALLBACK_PATH="/callback",CLIENT_METADATA_BASE_URL="https://pi.dev/oauth",FALLBACK_REDIRECT_URL=`http://${CALLBACK_HOST}${CALLBACK_PATH}`,REFRESH_SKEW_MS=3e4,REFRESH_REQUEST_TIMEOUT_MS=15e3,REFRESH_LOCK_STALE_MS=2e4,REFRESH_LOCK_WAIT_MS=25e3,REFRESH_LOCK_RETRY_MS=100;function callbackSettings(settings){let url=new URL(settings.callbackUrl??`http://${CALLBACK_HOST}${CALLBACK_PATH}`),address=url.hostname.replace(/^\[|\]$/g,""),port=url.port?Number(url.port):settings.callbackPort,fixedRedirectUrl;return url.port?fixedRedirectUrl=settings.callbackUrl:port!==void 0&&(url.port=String(port),fixedRedirectUrl=url.href),{host:address==="localhost"?CALLBACK_HOST:address,redirectHost:address,port,path:url.pathname,fixedRedirectUrl}}function mergeScopes(...scopes){let merged=[...new Set(scopes.flatMap(scope=>scope?.split(/\s+/).filter(Boolean)??[]))];return merged.length>0?merged.join(" "):void 0}function parseStates(content){if(!content?.trim())return{};let parsed=JSON.parse(content);return typeof parsed=="object"&&parsed!==null&&!Array.isArray(parsed)?parsed:{}}function serializeStates(states){return`${JSON.stringify(states,null,2)}
78
78
  `}function storeKeys(name,serverUrl){let legacyKey=String(new URL(serverUrl));return{key:`${mcpNamespace(name)}|${legacyKey}`,legacyKey}}var McpOAuthCredentialStore=class{backend;lockDir;constructor(backend,lockDir){this.backend=backend??new FileAuthStorageBackend(join(getAgentDir(),"mcp-auth.json")),this.lockDir=backend?lockDir:getAgentDir()}forServer(name,serverUrl){let{key,legacyKey}=storeKeys(name,serverUrl);return{load:()=>this.backend.withLock(current=>{let states=parseStates(current);return states[key]||!states[legacyKey]?{result:states[key]}:(states[key]=states[legacyKey],delete states[legacyKey],{result:states[key],next:serializeStates(states)})}),save:state=>this.write(states=>{states[key]=state}),withRefreshLock:fn=>this.withRefreshLock(key,fn)}}async withRefreshLock(key,fn){if(!this.lockDir)return fn();mkdirSync(this.lockDir,{recursive:!0,mode:448});let hash=createHash("sha256").update(key).digest("hex").slice(0,16),release=await import_proper_lockfile.default.lock(join(this.lockDir,`mcp-auth-refresh-${hash}`),{realpath:!1,stale:REFRESH_LOCK_STALE_MS,retries:{retries:REFRESH_LOCK_WAIT_MS/REFRESH_LOCK_RETRY_MS,factor:1,minTimeout:REFRESH_LOCK_RETRY_MS,maxTimeout:REFRESH_LOCK_RETRY_MS},onCompromised:()=>{}});try{return await fn()}finally{await release().catch(()=>{})}}tokens(name,serverUrl){let{key,legacyKey}=storeKeys(name,serverUrl),states=this.backend.withLock(current=>({result:parseStates(current)}));return(states[key]??states[legacyKey])?.tokens}remove(name,serverUrl){let{key,legacyKey}=storeKeys(name,serverUrl);return this.backend.withLock(current=>{let states=parseStates(current),stored=key in states?key:legacyKey in states?legacyKey:void 0;return stored?(delete states[stored],{result:!0,next:serializeStates(states)}):{result:!1}})}write(update){this.backend.withLock(current=>{let states=parseStates(current);return update(states),{result:void 0,next:serializeStates(states)}})}};function registeredRedirectUrls(client){return client&&"redirect_uris"in client?client.redirect_uris:[]}function callbackId(serverUrl){let url=new URL(serverUrl);return url.hash="",createHash("sha256").update(url.href).digest().subarray(0,9).toString("base64url")}function clientMetadataDocument(serverUrl,redirectUrl,metadata){if(!metadata?.client_id_metadata_document_supported||!metadata.token_endpoint_auth_methods_supported?.includes("none"))throw new Error('The authorization server does not support Client ID Metadata Documents for public clients; remove oauth.clientRegistration "cimd"');if(metadata.authorization_response_iss_parameter_supported)return{url:`${CLIENT_METADATA_BASE_URL}/client.json`,redirectUrl};let id=callbackId(serverUrl),redirect=new URL(redirectUrl);return redirect.pathname=`${CALLBACK_PATH}/${id}`,{url:`${CLIENT_METADATA_BASE_URL}/${id}/client.json`,redirectUrl:redirect.href}}function createProvider(serverUrl,store,settings,redirectUrl,onRedirect){return new McpOAuthProvider({serverUrl,redirectUrl,clientMetadata:{client_name:settings.clientName??APP_NAME},clientMetadataDocument:settings.clientRegistration==="cimd"?metadata=>clientMetadataDocument(serverUrl,redirectUrl,metadata):void 0,clientId:settings.clientId,clientSecret:settings.clientSecret,store,onRedirect})}function createMcpAuthProvider(options){let{serverUrl,store}=options,refreshing,refresh=(staleToken,fetch=globalThis.fetch,challenge)=>(refreshing??=store.withRefreshLock(async()=>{let state=await store.load();if(state?.tokens?.access_token!==staleToken)return;if(!state?.tokens?.refresh_token)throw new McpOAuthAuthorizationRequiredError;let settings=options.settings(),redirectUrl=callbackSettings(settings).fixedRedirectUrl??registeredRedirectUrls(state.clientInformation)[0]??FALLBACK_REDIRECT_URL,provider=createProvider(serverUrl,store,settings,redirectUrl,()=>{});if(await authorizeMcp(provider,{serverUrl,resourceMetadataUrl:challenge?.resourceMetadataUrl,authorizationServerMetadataUrl:settings.authServerMetadataUrl,scope:challenge?.scope,fetch:(input,init)=>fetch(input,{...init,signal:AbortSignal.timeout(REFRESH_REQUEST_TIMEOUT_MS)})})==="REDIRECT")throw new McpOAuthAuthorizationRequiredError}).finally(()=>{refreshing=void 0}),refreshing);return{token:async()=>{await refreshing?.catch(()=>{});let state=await store.load(),token=state?.tokens?.access_token;return!(state?.tokensExpireAt!==void 0&&state.tokensExpireAt-REFRESH_SKEW_MS<=Date.now())||!state?.tokens?.refresh_token?token:(await refresh(token).catch(()=>{}),(await store.load())?.tokens?.access_token)},onUnauthorized:async context=>{let challenge=parseWwwAuthenticate(context.response.headers.get("www-authenticate"));if(options.onChallenge(challenge),challenge.error==="insufficient_scope")throw new McpOAuthAuthorizationRequiredError;await refresh(context.token,context.fetch,challenge)},settled:async()=>{await refreshing?.catch(()=>{})}}}var McpSignInCancelledError=class extends Error{constructor(){super("Sign-in cancelled"),this.name="McpSignInCancelledError"}};function responseFromRedirectUrl(input,state,redirectUrl){let url;try{url=new URL(input.trim())}catch{throw new Error("Expected the full redirect URL from the browser address bar")}if(url.origin!==redirectUrl.origin||url.pathname!==redirectUrl.pathname)throw new Error("The redirect URL does not match this sign-in's redirect URI");let error=url.searchParams.get("error");if(error)throw new Error(url.searchParams.get("error_description")??error);if(url.searchParams.get("state")!==state)throw new Error("The redirect URL belongs to a different sign-in");let code=url.searchParams.get("code");if(!code)throw new Error("The redirect URL does not contain an authorization code");return{code,iss:url.searchParams.get("iss")??void 0}}async function waitForAuthorizationResponse(callback,state,redirectUrl,prompt){let controller=new AbortController,fromBrowser=callback.waitForCallback(state,redirectUrl.pathname),fromUser=prompt.promptForRedirectUrl(controller.signal).then(input=>{if(!input?.trim())throw new McpSignInCancelledError;return responseFromRedirectUrl(input,state,redirectUrl)});try{return await Promise.race([fromBrowser,fromUser])}finally{controller.abort(),fromBrowser.catch(()=>{}),fromUser.catch(()=>{})}}async function listenForCallback(settings,extraPaths,port,required){let options={host:settings.host,redirectHost:settings.redirectHost,path:settings.path,extraPaths,renderPage:page=>page.ok?oauthSuccessHtml("Signed in to the MCP server. You may now close this page."):oauthErrorHtml(page.message,page.details)};try{return await OAuthCallbackServer.listen({...options,port:port??0})}catch(error){if(required||port===void 0)throw error;return OAuthCallbackServer.listen(options)}}async function signInMcpServer(options){let{serverUrl,store,settings}=options,stored=await store.load(),stepUp=options.challenge?.error==="insufficient_scope",callbackOptions=callbackSettings(settings),registered=registeredRedirectUrls(stored?.clientInformation)[0],preferredPort=callbackOptions.port??(registered&&Number(new URL(registered).port)||void 0),cimd=settings.clientRegistration==="cimd",callback=await listenForCallback(callbackOptions,cimd?[`${CALLBACK_PATH}/${callbackId(serverUrl)}`]:[],preferredPort,callbackOptions.port!==void 0),redirectUrl=callbackOptions.fixedRedirectUrl??callback.redirectUrl;try{if(stored){let next={...stored};delete next.oauthState,settings.clientId||(cimd?!stored.clientInformation:registeredRedirectUrls(stored.clientInformation).includes(redirectUrl))||(delete next.clientInformation,delete next.tokens,delete next.tokensExpireAt),await store.save(next)}let authorizationUrl,provider=createProvider(serverUrl,store,settings,redirectUrl,url=>{authorizationUrl=url}),flow={serverUrl,resourceMetadataUrl:options.challenge?.resourceMetadataUrl,authorizationServerMetadataUrl:settings.authServerMetadataUrl,scope:mergeScopes(settings.scope,stepUp?stepUpScope(stored?.tokens?.scope,options.challenge?.scope):options.challenge?.scope)};if(await authorizeMcp(provider,{...flow,skipRefresh:stepUp})==="AUTHORIZED")return;if(!authorizationUrl)throw new Error("OAuth flow did not produce an authorization URL");let state=await provider.state(),authorizationRedirectUrl=new URL(authorizationUrl.searchParams.get("redirect_uri")??redirectUrl);options.prompt.showAuthorizationUrl(authorizationUrl);let{code,iss}=await waitForAuthorizationResponse(callback,state,authorizationRedirectUrl,options.prompt);await authorizeMcp(provider,{...flow,authorizationCode:code,iss})}finally{await callback.close()}}import{appendFileSync,mkdirSync as mkdirSync2,renameSync,statSync}from"node:fs";import{dirname}from"node:path";var MAX_LOG_BYTES=5*1024*1024;function isRecord(value){return typeof value=="object"&&value!==null&&!Array.isArray(value)}function formatData(data){if(typeof data=="string")return data;try{return JSON.stringify(data)??String(data)}catch{return String(data)}}function formatMcpLogMessage(server,params,now=new Date){let message=isRecord(params)?params:{data:params},level=typeof message.level=="string"?message.level:"info",logger=typeof message.logger=="string"&&message.logger?` ${message.logger}:`:"",text=formatData(message.data).replace(/\r?\n/g,`
79
79
  `);return`${now.toISOString()} [${server}] ${level}${logger} ${text}
80
- `}var McpServerLog=class{path;size;constructor(path){this.path=path}write(server,params){let line=formatMcpLogMessage(server,params);try{this.size===void 0&&(mkdirSync2(dirname(this.path),{recursive:!0}),this.size=this.currentSize()),this.size>MAX_LOG_BYTES&&(this.currentSize()>MAX_LOG_BYTES&&renameSync(this.path,`${this.path}.1`),this.size=this.currentSize()),appendFileSync(this.path,line),this.size+=Buffer.byteLength(line)}catch{}}currentSize(){try{return statSync(this.path).size}catch{return 0}}};var DEFAULT_TIMEOUT_SECONDS=60,STDERR_TAIL_CHARS=2e3,CONNECT_RETRY_DELAYS_MS=[250,1e3];function errorMessage(error){return error instanceof Error?error.message:String(error)}function isTransientError(error){return error instanceof McpHttpError?error.status===408||error.status===429||error.status>=500&&error.status!==501:error instanceof TypeError}function signInRequiredMessage(entry){let provider="url"in entry.config?entry.config.auth?.provider:void 0;return`MCP server "${entry.name}" requires sign-in. Run ${provider?`/login ${provider}`:"/mcp"} to sign in.`}function usesOAuth(entry){let{config}=entry;return!("url"in config)||config.auth?!1:!Object.keys(config.headers??{}).some(header=>header.toLowerCase()==="authorization")}function expandHome(value){return value==="~"?homedir():value.startsWith("~/")||process.platform==="win32"&&value.startsWith("~\\")?join2(homedir(),value.slice(2)):value}function createDefaultTransport(entry,cwd,authProvider){let{config,name}=entry;if("url"in config)return new StreamableHttpTransport({url:config.url,headers:resolveHeadersOrThrow(config.headers,`MCP server "${name}"`),authProvider});let env={};for(let[key,value]of Object.entries(config.env??{}))env[key]=resolveConfigValueOrThrow(value,`MCP server "${name}" env "${key}"`);return new StdioTransport({command:expandHome(config.command),args:config.args?.map(expandHome),cwd:resolve(cwd,expandHome(config.cwd??".")),env,stderr:"pipe"})}async function withoutTemplates(list,empty){try{return await list()}catch(error){if(error instanceof McpError&&error.code===JSON_RPC_ERROR_CODES.methodNotFound)return empty;throw error}}function listTemplates(client,options={}){return withoutTemplates(()=>client.listResourceTemplates(options),[])}async function fetchResources(client){let[resources,resourceTemplates]=await Promise.all([client.listResources().catch(()=>[]),listTemplates(client).catch(()=>[])]);return{resources:resources.filter(resource=>!isMcpAppResource(resource)),resourceTemplates:resourceTemplates.filter(template=>!isMcpAppResource(template))}}var McpServerConnection=class{entry;state="connecting";error;tools=[];hasResources=!1;resources=[];resourceTemplates=[];instructions;challenge;client;opening;closed=!1;stderrTail;cwd;createTransport;authProvider;onTools;onChange;log;constructor(options){this.entry=options.entry,this.cwd=options.cwd,this.createTransport=options.createTransport,this.onTools=options.onTools,this.onChange=options.onChange,this.log=options.log;let url=this.oauthUrl,provider="url"in this.entry.config?this.entry.config.auth?.provider:void 0;this.authProvider=url?createMcpAuthProvider({serverUrl:url,store:options.credentials.forServer(this.entry.name,url),settings:()=>this.oauthSettings(),onChallenge:challenge=>{this.challenge=challenge}}):provider?{token:async()=>options.providerToken?.(provider),settled:async()=>{}}:void 0}get name(){return this.entry.name}get timeoutMs(){return(this.entry.config.timeout??DEFAULT_TIMEOUT_SECONDS)*1e3}get oauthUrl(){return usesOAuth(this.entry)&&"url"in this.entry.config?this.entry.config.url:void 0}oauthSettings(){let oauth="url"in this.entry.config?this.entry.config.oauth:void 0;return oauth?{clientId:oauth.clientId,clientSecret:oauth.clientSecret===void 0?void 0:resolveConfigValueOrThrow(oauth.clientSecret,`MCP server "${this.entry.name}" oauth.clientSecret`),callbackPort:oauth.callbackPort,callbackUrl:oauth.callbackUrl,scope:oauth.scope,clientName:oauth.clientName,clientRegistration:oauth.clientRegistration,authServerMetadataUrl:oauth.authServerMetadataUrl?new URL(oauth.authServerMetadataUrl):void 0}:{}}getClient(){return this.closed?Promise.reject(new Error(`MCP server "${this.entry.name}" is shut down`)):this.client?.connectionState==="connected"?Promise.resolve(this.client):(this.opening??=this.open().finally(()=>{this.opening=void 0}),this.opening)}callTool(name,args,options){return this.withClient(client=>client.callTool(name,args,options))}readResource(uri,options){return this.withClient(client=>client.readResource(uri,options),!0)}resourcesPage(cursor,options){return this.withClient(client=>client.listResourcesPage(cursor,options),!0)}resourceTemplatesPage(cursor,options){return this.withClient(client=>withoutTemplates(()=>client.listResourceTemplatesPage(cursor,options),{resourceTemplates:[]}),!0)}allResources(options){return this.withClient(client=>client.listResources(options),!0)}allResourceTemplates(options){return this.withClient(client=>listTemplates(client,options),!0)}async withClient(run,readOnly=!1){for(let attempt=1;;attempt++){let client=await this.getClient();try{return await run(client)}catch(error){if(readOnly&&attempt===1&&error instanceof McpHttpError&&isTransientError(error)){await new Promise(resolve2=>setTimeout(resolve2,CONNECT_RETRY_DELAYS_MS[0]));continue}if(error instanceof McpSessionExpiredError&&attempt===1){this.client===client&&(this.client=void 0);continue}throw this.needsSignIn(error)?(await this.dropClient(client),this.markNeedsAuth(),new Error(signInRequiredMessage(this.entry))):error}}}async reconnect(){await this.opening?.catch(()=>{}),this.client&&await this.dropClient(this.client),await this.getClient()}async signOut(){await this.opening?.catch(()=>{}),this.client&&await this.dropClient(this.client),this.closed||this.markNeedsAuth()}needsSignIn(error){return error instanceof McpOAuthAuthorizationRequiredError||this.authProvider!==void 0&&error instanceof McpAuthRequiredError}markNeedsAuth(){this.state="needs-auth",this.error=void 0,this.changed()}changed(){this.onChange?.(this)}async dropClient(client){this.client===client&&(this.client=void 0),await client.close().catch(()=>{})}async open(){this.state="connecting",this.changed();let retries="url"in this.entry.config?CONNECT_RETRY_DELAYS_MS:[];for(let attempt=0;;attempt++){this.stderrTail=void 0;try{return await this.connectOnce()}catch(error){let delay=retries[attempt];if(this.closed||delay===void 0||!isTransientError(error))throw this.connectFailed(error);if(await new Promise(resolve2=>setTimeout(resolve2,delay)),this.closed)throw this.connectFailed(error)}}}async connectOnce(){let client=new McpClient({name:"pi",version:VERSION,requestTimeoutMs:this.timeoutMs,roots:[{uri:pathToFileURL(this.cwd).href,name:basename(this.cwd)}]}),log=this.log;log&&client.onNotification("notifications/message",params=>log.write(this.entry.name,params));let transport;try{transport=this.createTransport(this.entry,this.cwd,this.authProvider),await client.connect(transport),client.onNotification("notifications/tools/list_changed",()=>{this.refreshTools(client)}),client.onNotification("notifications/resources/list_changed",()=>{this.refreshResources(client)});let stdio=transport instanceof StdioTransport?transport:void 0;client.onClose(()=>this.handleClientClose(client,stdio));let hasResources=client.serverCapabilities?.resources!==void 0,[tools,resources]=await Promise.all([client.serverCapabilities?.tools?client.listTools():[],hasResources?fetchResources(client):{resources:[],resourceTemplates:[]}]);if(this.closed)throw new Error("shut down while connecting");if(client.connectionState!=="connected")throw new Error("connection closed during setup");return this.client=client,this.tools=tools,this.hasResources=hasResources,this.resources=resources.resources,this.resourceTemplates=resources.resourceTemplates,this.instructions=client.instructions?.trim()||void 0,this.state="connected",this.error=void 0,this.onTools(this),this.changed(),client}catch(error){throw await client.close().catch(()=>{}),transport instanceof StdioTransport&&(this.stderrTail=transport.stderr.trim().slice(-STDERR_TAIL_CHARS)||void 0),error}}connectFailed(error){return this.needsSignIn(error)&&!this.closed?(this.markNeedsAuth(),new Error(signInRequiredMessage(this.entry))):(this.state=this.closed?"closed":"failed",this.error=this.stderrTail?`${errorMessage(error)}
80
+ `}var McpServerLog=class{path;size;constructor(path){this.path=path}write(server,params){let line=formatMcpLogMessage(server,params);try{this.size===void 0&&(mkdirSync2(dirname(this.path),{recursive:!0}),this.size=this.currentSize()),this.size>MAX_LOG_BYTES&&(this.currentSize()>MAX_LOG_BYTES&&renameSync(this.path,`${this.path}.1`),this.size=this.currentSize()),appendFileSync(this.path,line),this.size+=Buffer.byteLength(line)}catch{}}currentSize(){try{return statSync(this.path).size}catch{return 0}}};var DEFAULT_TIMEOUT_SECONDS=60,STDERR_TAIL_CHARS=2e3,CONNECT_RETRY_DELAYS_MS=[250,1e3];function errorMessage(error){return error instanceof Error?error.message:String(error)}function isTransientError(error){return error instanceof McpHttpError?error.status===408||error.status===429||error.status>=500&&error.status!==501:error instanceof TypeError}function signInRequiredMessage(entry){let provider="url"in entry.config?entry.config.auth?.provider:void 0;return`MCP server "${entry.name}" requires sign-in. Run ${provider?`/login ${provider}`:"/mcp"} to sign in.`}function usesOAuth(entry){let{config}=entry;return!("url"in config)||config.auth?!1:!Object.keys(config.headers??{}).some(header=>header.toLowerCase()==="authorization")}function expandHome(value){return value==="~"?homedir():value.startsWith("~/")||process.platform==="win32"&&value.startsWith("~\\")?join2(homedir(),value.slice(2)):value}function createDefaultTransport(entry,cwd,authProvider){let{config,name}=entry;if("url"in config)return new StreamableHttpTransport({url:config.url,headers:resolveHeadersOrThrow(config.headers,`MCP server "${name}"`),authProvider});let env={};for(let[key,value]of Object.entries(config.env??{}))env[key]=resolveConfigValueOrThrow(value,`MCP server "${name}" env "${key}"`);return new StdioTransport({command:expandHome(config.command),args:config.args?.map(expandHome),cwd:resolve(cwd,expandHome(config.cwd??".")),env,stderr:"pipe"})}async function withoutTemplates(list,empty){try{return await list()}catch(error){if(error instanceof McpError&&error.code===JSON_RPC_ERROR_CODES.methodNotFound)return empty;throw error}}function listTemplates(client,options={}){return withoutTemplates(()=>client.listResourceTemplates(options),[])}async function fetchResources(client){let[resources,resourceTemplates]=await Promise.all([client.listResources().catch(()=>[]),listTemplates(client).catch(()=>[])]);return{resources:resources.filter(resource=>!isMcpAppResource(resource)),resourceTemplates:resourceTemplates.filter(template=>!isMcpAppResource(template))}}var McpServerConnection=class{entry;state="connecting";error;tools=[];hasResources=!1;resources=[];resourceTemplates=[];instructions;challenge;client;opening;shutdown=new AbortController;stderrTail;cwd;createTransport;authProvider;onTools;onChange;log;constructor(options){this.entry=options.entry,this.cwd=options.cwd,this.createTransport=options.createTransport,this.onTools=options.onTools,this.onChange=options.onChange,this.log=options.log;let url=this.oauthUrl,provider="url"in this.entry.config?this.entry.config.auth?.provider:void 0;this.authProvider=url?createMcpAuthProvider({serverUrl:url,store:options.credentials.forServer(this.entry.name,url),settings:()=>this.oauthSettings(),onChallenge:challenge=>{this.challenge=challenge}}):provider?{token:async()=>options.providerToken?.(provider),settled:async()=>{}}:void 0}get name(){return this.entry.name}get closed(){return this.shutdown.signal.aborted}get timeoutMs(){return(this.entry.config.timeout??DEFAULT_TIMEOUT_SECONDS)*1e3}get oauthUrl(){return usesOAuth(this.entry)&&"url"in this.entry.config?this.entry.config.url:void 0}oauthSettings(){let oauth="url"in this.entry.config?this.entry.config.oauth:void 0;return oauth?{clientId:oauth.clientId,clientSecret:oauth.clientSecret===void 0?void 0:resolveConfigValueOrThrow(oauth.clientSecret,`MCP server "${this.entry.name}" oauth.clientSecret`),callbackPort:oauth.callbackPort,callbackUrl:oauth.callbackUrl,scope:oauth.scope,clientName:oauth.clientName,clientRegistration:oauth.clientRegistration,authServerMetadataUrl:oauth.authServerMetadataUrl?new URL(oauth.authServerMetadataUrl):void 0}:{}}getClient(){return this.closed?Promise.reject(new Error(`MCP server "${this.entry.name}" is shut down`)):this.client?.connectionState==="connected"?Promise.resolve(this.client):(this.opening??=this.open().finally(()=>{this.opening=void 0}),this.opening)}callTool(name,args,options){return this.withClient(client=>client.callTool(name,args,options))}readResource(uri,options){return this.withClient(client=>client.readResource(uri,options),!0)}resourcesPage(cursor,options){return this.withClient(client=>client.listResourcesPage(cursor,options),!0)}resourceTemplatesPage(cursor,options){return this.withClient(client=>withoutTemplates(()=>client.listResourceTemplatesPage(cursor,options),{resourceTemplates:[]}),!0)}allResources(options){return this.withClient(client=>client.listResources(options),!0)}allResourceTemplates(options){return this.withClient(client=>listTemplates(client,options),!0)}async withClient(run,readOnly=!1){for(let attempt=1;;attempt++){let client=await this.getClient();try{return await run(client)}catch(error){if(readOnly&&attempt===1&&error instanceof McpHttpError&&isTransientError(error)){await new Promise(resolve2=>setTimeout(resolve2,CONNECT_RETRY_DELAYS_MS[0]));continue}if(error instanceof McpSessionExpiredError&&attempt===1){this.client===client&&(this.client=void 0);continue}throw this.needsSignIn(error)?(await this.dropClient(client),this.markNeedsAuth(),new Error(signInRequiredMessage(this.entry))):error}}}async reconnect(){await this.opening?.catch(()=>{}),this.client&&await this.dropClient(this.client),await this.getClient()}async signOut(){await this.opening?.catch(()=>{}),this.client&&await this.dropClient(this.client),this.closed||this.markNeedsAuth()}needsSignIn(error){return error instanceof McpOAuthAuthorizationRequiredError||this.authProvider!==void 0&&error instanceof McpAuthRequiredError}markNeedsAuth(){this.state="needs-auth",this.error=void 0,this.changed()}changed(){this.onChange?.(this)}async dropClient(client){this.client===client&&(this.client=void 0),await client.close().catch(()=>{})}async open(){this.state="connecting",this.changed();let retries="url"in this.entry.config?CONNECT_RETRY_DELAYS_MS:[];for(let attempt=0;;attempt++){this.stderrTail=void 0;try{return await this.connectOnce()}catch(error){let delay=retries[attempt];if(this.closed||delay===void 0||!isTransientError(error))throw this.connectFailed(error);if(await sleep(delay,void 0,{signal:this.shutdown.signal}).catch(()=>{}),this.closed)throw this.connectFailed(error)}}}async connectOnce(){let client=new McpClient({name:"pi",version:VERSION,requestTimeoutMs:this.timeoutMs,roots:[{uri:pathToFileURL(this.cwd).href,name:basename(this.cwd)}]}),log=this.log;log&&client.onNotification("notifications/message",params=>log.write(this.entry.name,params));let closing,closeClient=()=>(closing??=client.close().catch(()=>{}),closing);this.shutdown.signal.addEventListener("abort",closeClient,{once:!0});let transport;try{transport=this.createTransport(this.entry,this.cwd,this.authProvider),await client.connect(transport),client.onNotification("notifications/tools/list_changed",()=>{this.refreshTools(client)}),client.onNotification("notifications/resources/list_changed",()=>{this.refreshResources(client)});let stdio=transport instanceof StdioTransport?transport:void 0;client.onClose(()=>this.handleClientClose(client,stdio));let hasResources=client.serverCapabilities?.resources!==void 0,[tools,resources]=await Promise.all([client.serverCapabilities?.tools?client.listTools():[],hasResources?fetchResources(client):{resources:[],resourceTemplates:[]}]);if(this.closed)throw new Error("shut down while connecting");if(client.connectionState!=="connected")throw new Error("connection closed during setup");return this.client=client,this.tools=tools,this.hasResources=hasResources,this.resources=resources.resources,this.resourceTemplates=resources.resourceTemplates,this.instructions=client.instructions?.trim()||void 0,this.state="connected",this.error=void 0,this.onTools(this),this.changed(),client}catch(error){throw await closeClient(),transport instanceof StdioTransport&&(this.stderrTail=transport.stderr.trim().slice(-STDERR_TAIL_CHARS)||void 0),error}finally{this.shutdown.signal.removeEventListener("abort",closeClient)}}connectFailed(error){return this.needsSignIn(error)&&!this.closed?(this.markNeedsAuth(),new Error(signInRequiredMessage(this.entry))):(this.state=this.closed?"closed":"failed",this.error=this.stderrTail?`${errorMessage(error)}
81
81
  ${this.stderrTail}`:errorMessage(error),this.changed(),new Error(`MCP server "${this.entry.name}" failed to connect: ${this.error}`))}handleClientClose(client,stdio){if(this.client!==client||this.closed)return;this.client=void 0,this.state="disconnected";let stderr=stdio?.stderr.trim().slice(-STDERR_TAIL_CHARS);this.error=stderr?`Connection closed
82
- ${stderr}`:"Connection closed",this.changed()}async refreshTools(client){try{let tools=await client.listTools();if(this.client!==client||this.closed)return;this.tools=tools,this.onTools(this)}catch(error){this.error=`Failed to refresh tools: ${errorMessage(error)}`}this.changed()}async refreshResources(client){let{resources,resourceTemplates}=await fetchResources(client);this.client!==client||this.closed||(this.resources=resources,this.resourceTemplates=resourceTemplates,this.onTools(this),this.changed())}async close(){this.closed=!0,this.state="closed",this.changed();let client=this.client;this.client=void 0,await client?.close().catch(()=>{}),await this.authProvider?.settled()}};export{McpOAuthCredentialStore,McpSignInCancelledError,signInMcpServer,McpServerLog,createDefaultTransport,McpServerConnection};
82
+ ${stderr}`:"Connection closed",this.changed()}async refreshTools(client){try{let tools=await client.listTools();if(this.client!==client||this.closed)return;this.tools=tools,this.onTools(this)}catch(error){this.error=`Failed to refresh tools: ${errorMessage(error)}`}this.changed()}async refreshResources(client){let{resources,resourceTemplates}=await fetchResources(client);this.client!==client||this.closed||(this.resources=resources,this.resourceTemplates=resourceTemplates,this.onTools(this),this.changed())}async close(){this.shutdown.abort(),this.state="closed",this.changed();let client=this.client;this.client=void 0,await Promise.all([client?.close().catch(()=>{}),this.opening?.catch(()=>{})]),await this.authProvider?.settled()}};export{McpOAuthCredentialStore,McpSignInCancelledError,signInMcpServer,McpServerLog,createDefaultTransport,McpServerConnection};
@@ -123,7 +123,9 @@ Please report this to https://github.com/markedjs/marked.`,e){let s="<p>An error
123
123
  `)+postfix,endIndex=index+1,index=string.indexOf(`
124
124
  `,endIndex)}while(index!==-1);return returnValue+=string.slice(endIndex),returnValue}var wrapAnsi16=(offset=0)=>code=>`\x1B[${code+offset}m`,wrapAnsi256=(offset=0)=>code=>`\x1B[${38+offset};5;${code}m`,wrapAnsi16m=(offset=0)=>(red,green,blue)=>`\x1B[${38+offset};2;${red};${green};${blue}m`,wrapUnderlineAnsi=code=>`\x1B[58;5;${code<90?code-30:code-90+8}m`,styles={modifier:{reset:[0,0],bold:[1,22],dim:[2,22],italic:[3,23],underline:[4,24],underlineDouble:["4:2",24],underlineCurly:["4:3",24],underlineDotted:["4:4",24],underlineDashed:["4:5",24],overline:[53,55],inverse:[7,27],hidden:[8,28],strikethrough:[9,29]},color:{black:[30,39],red:[31,39],green:[32,39],yellow:[33,39],blue:[34,39],magenta:[35,39],cyan:[36,39],white:[37,39],blackBright:[90,39],gray:[90,39],grey:[90,39],redBright:[91,39],greenBright:[92,39],yellowBright:[93,39],blueBright:[94,39],magentaBright:[95,39],cyanBright:[96,39],whiteBright:[97,39]},bgColor:{bgBlack:[40,49],bgRed:[41,49],bgGreen:[42,49],bgYellow:[43,49],bgBlue:[44,49],bgMagenta:[45,49],bgCyan:[46,49],bgWhite:[47,49],bgBlackBright:[100,49],bgGray:[100,49],bgGrey:[100,49],bgRedBright:[101,49],bgGreenBright:[102,49],bgYellowBright:[103,49],bgBlueBright:[104,49],bgMagentaBright:[105,49],bgCyanBright:[106,49],bgWhiteBright:[107,49]},underlineColor:{underlineBlack:["58;5;0",59],underlineRed:["58;5;1",59],underlineGreen:["58;5;2",59],underlineYellow:["58;5;3",59],underlineBlue:["58;5;4",59],underlineMagenta:["58;5;5",59],underlineCyan:["58;5;6",59],underlineWhite:["58;5;7",59],underlineBlackBright:["58;5;8",59],underlineGray:["58;5;8",59],underlineGrey:["58;5;8",59],underlineRedBright:["58;5;9",59],underlineGreenBright:["58;5;10",59],underlineYellowBright:["58;5;11",59],underlineBlueBright:["58;5;12",59],underlineMagentaBright:["58;5;13",59],underlineCyanBright:["58;5;14",59],underlineWhiteBright:["58;5;15",59]}},modifierNames=Object.keys(styles.modifier),foregroundColorNames=Object.keys(styles.color),backgroundColorNames=Object.keys(styles.bgColor),underlineColorNames=Object.keys(styles.underlineColor),colorNames=[...foregroundColorNames,...backgroundColorNames];function assembleStyles(){let codes=new Map;for(let[groupName,group]of Object.entries(styles)){for(let[styleName,style]of Object.entries(group))styles[styleName]={open:`\x1B[${style[0]}m`,close:`\x1B[${style[1]}m`},group[styleName]=styles[styleName],codes.set(Number.parseInt(style[0],10),style[1]);Object.defineProperty(styles,groupName,{value:group,enumerable:!1})}return Object.defineProperty(styles,"codes",{value:codes,enumerable:!1}),styles.color.close="\x1B[39m",styles.bgColor.close="\x1B[49m",styles.underlineColor.close="\x1B[59m",styles.color.ansi=wrapAnsi16(),styles.color.ansi256=wrapAnsi256(),styles.color.ansi16m=wrapAnsi16m(),styles.bgColor.ansi=wrapAnsi16(10),styles.bgColor.ansi256=wrapAnsi256(10),styles.bgColor.ansi16m=wrapAnsi16m(10),styles.underlineColor.ansi=wrapUnderlineAnsi,styles.underlineColor.ansi256=wrapAnsi256(20),styles.underlineColor.ansi16m=wrapAnsi16m(20),Object.defineProperties(styles,{rgbToAnsi256:{value(red,green,blue){return red===green&&green===blue?red<8?16:red>248?231:Math.round((red-8)/247*24)+232:16+36*Math.round(red/255*5)+6*Math.round(green/255*5)+Math.round(blue/255*5)},enumerable:!1},hexToRgb:{value(hex){let matches=/[\da-f]{6}|[\da-f]{3}/i.exec(hex.toString(16));if(!matches)return[0,0,0];let[colorString]=matches;colorString.length===3&&(colorString=[...colorString].map(character=>character+character).join(""));let integer=Number.parseInt(colorString,16);return[integer>>16&255,integer>>8&255,integer&255]},enumerable:!1},hexToAnsi256:{value:hex=>styles.rgbToAnsi256(...styles.hexToRgb(hex)),enumerable:!1},ansi256ToAnsi:{value(code){if(code<8)return 30+code;if(code<16)return 90+(code-8);let red,green,blue;if(code>=232)red=((code-232)*10+8)/255,green=red,blue=red;else{code-=16;let remainder=code%36;red=Math.floor(code/36)/5,green=Math.floor(remainder/6)/5,blue=remainder%6/5}let value=Math.max(red,green,blue)*2;if(value===0)return 30;let result=30+(Math.round(blue)<<2|Math.round(green)<<1|Math.round(red));return value===2&&(result+=60),result},enumerable:!1},rgbToAnsi:{value:(red,green,blue)=>styles.ansi256ToAnsi(styles.rgbToAnsi256(red,green,blue)),enumerable:!1},hexToAnsi:{value:hex=>styles.ansi256ToAnsi(styles.hexToAnsi256(hex)),enumerable:!1}}),styles}var ansiStyles=assembleStyles(),ansi_styles_default=ansiStyles;import process2 from"node:process";import os2 from"node:os";import tty from"node:tty";function hasFlag(flag,argv=globalThis.Deno?globalThis.Deno.args:process2.argv){let prefix=flag.startsWith("-")?"":flag.length===1?"-":"--",position=argv.indexOf(prefix+flag),terminatorPosition=argv.indexOf("--");return position!==-1&&(terminatorPosition===-1||position<terminatorPosition)}var{env}=process2,flagForceColor;hasFlag("no-color")||hasFlag("no-colors")||hasFlag("color=false")||hasFlag("color=never")?flagForceColor=0:(hasFlag("color")||hasFlag("colors")||hasFlag("color=true")||hasFlag("color=always"))&&(flagForceColor=1);function hasNumericForceColor(){return/^\d+$/.test(env.FORCE_COLOR)}function envForceColor(){if("FORCE_COLOR"in env){if(env.FORCE_COLOR==="false")return 0;if(env.FORCE_COLOR==="true"||env.FORCE_COLOR.length===0)return 1;if(hasNumericForceColor())return Math.min(Number.parseInt(env.FORCE_COLOR,10),3)}}function translateLevel(level){return level===0?!1:{level,hasBasic:!0,has256:level>=2,has16m:level>=3}}function _supportsColor(haveStream,{streamIsTTY,sniffFlags=!0}={}){let noFlagForceColor=envForceColor();noFlagForceColor!==void 0&&(flagForceColor=noFlagForceColor);let forceColor=sniffFlags?flagForceColor:noFlagForceColor;if(forceColor===0)return 0;if(sniffFlags){if(hasFlag("color=16m")||hasFlag("color=full")||hasFlag("color=truecolor"))return 3;if(hasFlag("color=256"))return 2}if(forceColor!==void 0&&hasNumericForceColor())return forceColor;if("TF_BUILD"in env&&"AGENT_NAME"in env)return 1;if(haveStream&&!streamIsTTY&&forceColor===void 0)return 0;let min=forceColor||0;if(env.TERM==="dumb")return min;if(process2.platform==="win32"){let osRelease=os2.release().split(".");return Number(osRelease[0])>=10&&Number(osRelease[2])>=10586?Number(osRelease[2])>=14931?3:2:1}if("CI"in env)return["GITHUB_ACTIONS","GITEA_ACTIONS","CIRCLECI"].some(key=>key in env)?3:["TRAVIS","APPVEYOR","GITLAB_CI","BUILDKITE","DRONE"].some(sign=>sign in env)||env.CI_NAME==="codeship"?1:min;if("TEAMCITY_VERSION"in env)return/^(?:9\.0*[1-9]\d*\.|\d{2,}\.)/.test(env.TEAMCITY_VERSION)?1:0;if(env.COLORTERM==="truecolor"||env.TERM==="xterm-kitty"||env.TERM==="xterm-ghostty"||env.TERM==="wezterm")return 3;if("TERM_PROGRAM"in env){let version=Number.parseInt((env.TERM_PROGRAM_VERSION||"").split(".",1)[0],10);switch(env.TERM_PROGRAM){case"iTerm.app":return version>=3?3:2;case"Apple_Terminal":return 2}}return/-256(?:color)?$/i.test(env.TERM)?2:/^screen|^xterm|^vt100|^vt220|^rxvt|color|ansi|cygwin|linux/i.test(env.TERM)||"COLORTERM"in env?1:min}function createSupportsColor(stream,options={}){let level=_supportsColor(stream,{streamIsTTY:stream&&stream.isTTY,...options});return translateLevel(level)}var supportsColor={stdout:createSupportsColor({isTTY:tty.isatty(1)}),stderr:createSupportsColor({isTTY:tty.isatty(2)})},supports_color_default=supportsColor;var{stdout:stdoutColor,stderr:stderrColor}=supports_color_default,GENERATOR=Symbol("GENERATOR"),STYLER=Symbol("STYLER"),IS_EMPTY=Symbol("IS_EMPTY"),LEVEL=Symbol("LEVEL"),styles2=Object.create(null),assertValidLevel=level=>{if(!Number.isSafeInteger(level)||level<0||level>3)throw new Error("The `level` should be an integer from 0 to 3")},levelDescriptor={enumerable:!0,get(){return this[LEVEL]},set(level){assertValidLevel(level),this[LEVEL]=level}},applyOptions=(object,options={})=>{options.level!==void 0&&assertValidLevel(options.level);let colorLevel=stdoutColor?stdoutColor.level:0;object[LEVEL]=options.level===void 0?colorLevel:options.level};var chalkFactory=options=>{let chalk2=(...strings)=>strings.join(" ");return applyOptions(chalk2,options),Object.setPrototypeOf(chalk2,createChalk.prototype),chalk2};function createChalk(options){return chalkFactory(options)}Object.setPrototypeOf(createChalk.prototype,Function.prototype);for(let[styleName,style]of Object.entries(ansi_styles_default))styles2[styleName]={get(){let builder=createBuilder(this,createStyler(style.open,style.close,this[STYLER]),this[IS_EMPTY]);return Object.defineProperty(this,styleName,{value:builder}),builder}};styles2.visible={get(){let builder=createBuilder(this,this[STYLER],!0);return Object.defineProperty(this,"visible",{value:builder}),builder}};var createModelConverters=(model,type)=>{let style=ansi_styles_default[type];if(model==="rgb"){let ansi2=(red,green,blue)=>style.ansi(ansi_styles_default.rgbToAnsi(red,green,blue));return[ansi2,ansi2,(red,green,blue)=>style.ansi256(ansi_styles_default.rgbToAnsi256(red,green,blue)),style.ansi16m]}if(model==="hex"){let ansi2=hex=>style.ansi(ansi_styles_default.hexToAnsi(hex));return[ansi2,ansi2,hex=>style.ansi256(ansi_styles_default.hexToAnsi256(hex)),hex=>style.ansi16m(...ansi_styles_default.hexToRgb(hex))]}let ansi=code=>style.ansi(ansi_styles_default.ansi256ToAnsi(code));return[ansi,ansi,style.ansi256,style.ansi256]},usedModels=["rgb","hex","ansi256"];for(let model of usedModels){let capitalizedModel=model[0].toUpperCase()+model.slice(1);for(let[styleName,type]of[[model,"color"],["bg"+capitalizedModel,"bgColor"],["underline"+capitalizedModel,"underlineColor"]]){let{close}=ansi_styles_default[type],converters=createModelConverters(model,type);styles2[styleName]={get(){let styleFunction=function(first,second,third){let open=converters[this.level](first,second,third);return createBuilder(this,createStyler(open,close,this[STYLER]),this[IS_EMPTY])};return Object.defineProperty(this,styleName,{value:styleFunction}),styleFunction}}}}var proto=Object.defineProperties(()=>{},{...styles2,level:{enumerable:!0,get(){return this[GENERATOR].level},set(level){this[GENERATOR].level=level}}}),createStyler=(open,close,parent)=>{let openAll,closeAll;return parent===void 0?(openAll=open,closeAll=close):(openAll=parent.openAll+open,closeAll=close+parent.closeAll),{open,close,openAll,closeAll,parent}},createBuilder=(self,_styler,_isEmpty)=>{let builder=(...arguments_)=>arguments_.length===1?applyStyle(builder,""+arguments_[0]):arguments_.length===2?applyStyle(builder,arguments_[0]+" "+arguments_[1]):applyStyle(builder,arguments_.join(" "));return Object.setPrototypeOf(builder,proto),builder[GENERATOR]=self[GENERATOR]??self,builder[STYLER]=_styler,builder[IS_EMPTY]=_isEmpty,builder},applyStyle=(self,string)=>{if(self[GENERATOR][LEVEL]<=0||!string)return self[IS_EMPTY]?"":string;let styler=self[STYLER];if(styler===void 0)return string;let{openAll,closeAll}=styler;if(string.includes("\x1B"))for(;styler!==void 0;)string=stringReplaceAll(string,styler.close,styler.open),styler=styler.parent;let lfIndex=string.indexOf(`
125
125
  `);return lfIndex!==-1&&(string=stringEncaseCRLFWithFirstIndex(string,closeAll,openAll,lfIndex)),openAll+string+closeAll};Object.defineProperties(createChalk.prototype,{...styles2,level:levelDescriptor});var chalk=createChalk(),chalkStderr=createChalk({level:stderrColor?stderrColor.level:0});var source_default=chalk;import*as fs3 from"node:fs";import*as path4 from"node:path";import{watch}from"node:fs";var FS_WATCH_RETRY_DELAY_MS=5e3;function closeWatcher(watcher){if(watcher)try{watcher.close()}catch{}}function watchWithErrorHandler(path5,listener,onError){try{let watcher=watch(path5,listener);return watcher.on("error",onError),watcher}catch{return onError(),null}}var import_core=__toESM(require_core(),1),import_bash=__toESM(require_bash(),1),import_c=__toESM(require_c(),1),import_cpp=__toESM(require_cpp(),1),import_csharp=__toESM(require_csharp(),1),import_dart=__toESM(require_dart(),1),import_go=__toESM(require_go(),1),import_groovy=__toESM(require_groovy(),1),import_java=__toESM(require_java(),1),import_javascript=__toESM(require_javascript(),1),import_json=__toESM(require_json(),1),import_kotlin=__toESM(require_kotlin(),1),import_lua=__toESM(require_lua(),1),import_nix=__toESM(require_nix(),1),import_perl=__toESM(require_perl(),1),import_php=__toESM(require_php(),1),import_python=__toESM(require_python(),1),import_ruby=__toESM(require_ruby(),1),import_rust=__toESM(require_rust(),1),import_scala=__toESM(require_scala(),1),import_swift=__toESM(require_swift(),1),import_typescript=__toESM(require_typescript(),1);function decodeCodePoint(codePoint){if(!(!Number.isInteger(codePoint)||codePoint<0||codePoint>1114111))return String.fromCodePoint(codePoint)}function decodeHtmlEntity(entity){switch(entity){case"amp":return"&";case"lt":return"<";case"gt":return">";case"quot":return'"';case"apos":return"'"}if(entity.startsWith("#x")||entity.startsWith("#X"))return decodeCodePoint(Number.parseInt(entity.slice(2),16));if(entity.startsWith("#"))return decodeCodePoint(Number.parseInt(entity.slice(1),10))}function decodeHtmlEntityAt(html,index){let semicolonIndex=html.indexOf(";",index+1);if(semicolonIndex===-1||semicolonIndex-index>16)return;let entity=html.slice(index+1,semicolonIndex),decoded=decodeHtmlEntity(entity);if(decoded!==void 0)return{text:decoded,length:semicolonIndex-index+1}}var eagerLanguages={python:import_python.default,java:import_java.default,go:import_go.default,javascript:import_javascript.default,json:import_json.default,cpp:import_cpp.default,typescript:import_typescript.default,php:import_php.default,ruby:import_ruby.default,c:import_c.default,csharp:import_csharp.default,nix:import_nix.default,bash:import_bash.default,rust:import_rust.default,scala:import_scala.default,kotlin:import_kotlin.default,swift:import_swift.default,dart:import_dart.default,groovy:import_groovy.default,perl:import_perl.default,lua:import_lua.default};for(let[name,language]of Object.entries(eagerLanguages))import_core.default.registerLanguage(name,language);var allLanguagesPromise;function loadAllHighlightLanguages(){return allLanguagesPromise||(allLanguagesPromise=new Promise(resolve2=>{setImmediate(()=>{import("./lib-TEDK3E5I.js").then(()=>resolve2(),()=>{resolve2()})})})),allLanguagesPromise}var SPAN_CLOSE="</span>",HIGHLIGHT_CLASS_PREFIX="hljs-";function getScopeFromSpanTag(tag){let match=/\sclass\s*=\s*(?:"([^"]*)"|'([^']*)')/.exec(tag),classValue=match?.[1]??match?.[2];if(classValue){for(let className of classValue.split(/\s+/))if(className.startsWith(HIGHLIGHT_CLASS_PREFIX))return className.slice(HIGHLIGHT_CLASS_PREFIX.length)}}function getScopeFormatter(scope,theme2){let exact=theme2[scope];if(exact)return exact;let dotIndex=scope.indexOf(".");if(dotIndex!==-1){let prefixFormatter=theme2[scope.slice(0,dotIndex)];if(prefixFormatter)return prefixFormatter}let dashIndex=scope.indexOf("-");if(dashIndex!==-1){let prefixFormatter=theme2[scope.slice(0,dashIndex)];if(prefixFormatter)return prefixFormatter}}function getActiveFormatter(scopes,theme2){for(let i=scopes.length-1;i>=0;i--){let scope=scopes[i];if(!scope)continue;let formatter=getScopeFormatter(scope,theme2);if(formatter)return formatter}return theme2.default}function isSpanOpenTagStart(html,index){if(!html.startsWith("<span",index))return!1;let nextChar=html[index+5];return nextChar===">"||nextChar===" "||nextChar===" "||nextChar===`
126
- `||nextChar==="\r"}function renderHighlightedHtml(html,theme2={}){let output="",textBuffer="",scopes=[],flushText=()=>{if(!textBuffer)return;let formatter=getActiveFormatter(scopes,theme2);output+=formatter?formatter(textBuffer):textBuffer,textBuffer=""},index=0;for(;index<html.length;){if(isSpanOpenTagStart(html,index)){let tagEndIndex=html.indexOf(">",index+5);if(tagEndIndex!==-1){flushText();let tag=html.slice(index,tagEndIndex+1),scope=getScopeFromSpanTag(tag);scopes.push(scope),index=tagEndIndex+1;continue}}if(html.startsWith(SPAN_CLOSE,index)){flushText(),scopes.length>0&&scopes.pop(),index+=SPAN_CLOSE.length;continue}if(html[index]==="&"){let decoded=decodeHtmlEntityAt(html,index);if(decoded){textBuffer+=decoded.text,index+=decoded.length;continue}}textBuffer+=html[index],index++}return flushText(),output}function highlight(code,options={}){let html=options.language?import_core.default.highlight(code,{language:options.language,ignoreIllegals:options.ignoreIllegals}).value:import_core.default.highlightAuto(code,options.languageSubset).value;return renderHighlightedHtml(html,options.theme)}function supportsLanguage(name){return import_core.default.getLanguage(name)!==void 0}var SYSTEM_THEME_NAME="system",FAMILIES={neutral:{hue:231.49,saturation:{min:.02,max:.08},slot:8},blue:{hue:231.49,saturation:{min:.1,max:.68},slot:4},green:{hue:158.68,saturation:{min:.1,max:.76},slot:2},red:{hue:20,saturation:{min:.1,max:.92},slot:1},yellow:{hue:82.36,saturation:{min:.5,max:1},slot:3},orange:{hue:52,saturation:{min:.12,max:.85},slot:3},violet:{hue:295,saturation:{min:.2,max:.6},slot:5},calamine:{hue:202.43,saturation:{min:.1,max:.74},slot:6},thinkingSlate:{hue:231.49,saturation:{min:.08,max:.2},slot:4},thinkingBlue:{hue:231.49,saturation:{min:.2,max:.45},slot:4},thinkingPeriwinkle:{hue:263.25,saturation:{min:.3,max:.6},slot:6},thinkingViolet:{hue:295,saturation:{min:.4,max:.75},slot:5},thinkingMagenta:{hue:337.5,saturation:{min:.5,max:.85},slot:13},thinkingRed:{hue:20,saturation:{min:.95,max:1},slot:1}},TOKEN_FAMILIES={selectedBg:"blue",searchMatchBg:"orange",userMessageBg:"blue",customMessageBg:"violet",toolPendingBg:"neutral",toolSuccessBg:"green",toolErrorBg:"red",text:"neutral",userMessageText:"neutral",customMessageText:"neutral",toolTitle:"neutral",syntaxOperator:"neutral",syntaxPunctuation:"neutral",muted:"neutral",dim:"neutral",thinkingText:"neutral",toolOutput:"neutral",mdLinkUrl:"neutral",mdQuote:"neutral",mdQuoteBorder:"neutral",mdHr:"neutral",mdCodeBlockBorder:"neutral",toolDiffContext:"neutral",syntaxComment:"neutral",scrollbarTrack:"neutral",scrollbarThumb:"neutral",searchMatchText:"neutral",borderMuted:"neutral",accent:"violet",borderAccent:"violet",customMessageLabel:"violet",mdCode:"violet",mdListBullet:"violet",syntaxType:"violet",border:"blue",mdLink:"blue",syntaxKeyword:"blue",syntaxVariable:"calamine",success:"green",mdCodeBlock:"green",toolDiffAdded:"green",bashMode:"green",syntaxNumber:"green",error:"red",toolDiffRemoved:"red",warning:"yellow",mdHeading:"yellow",syntaxFunction:"yellow",syntaxString:"orange",thinkingOff:"neutral",thinkingMinimal:"thinkingSlate",thinkingLow:"thinkingBlue",thinkingMedium:"thinkingPeriwinkle",thinkingHigh:"thinkingViolet",thinkingXhigh:"thinkingMagenta",thinkingMax:"thinkingRed"},TOKEN_SLOTS={syntaxString:2,syntaxNumber:5,searchMatchBg:3},LEVELS={panel:{dark:{coefficients:[.29131,-.39746,2.33185,-.85524,-1.2076,.86276],reachable:[0,.979]},light:{coefficients:[-3.74073,27.94549,-78.44258,112.6798,-79.60015,22.11277],reachable:[.348,1]}},track:{dark:{coefficients:[.39028,-.23015,.83573,2.43829,-4.38292,2.01582],reachable:[0,.946]},light:{coefficients:[-5.24921,38.37322,-107.28833,152.10005,-106.17127,29.18061],reachable:[.368,1]}},thinking0:{dark:{coefficients:[.52988,-.05809,-.30924,4.63567,-6.52933,2.89108],reachable:[0,.873]},light:{coefficients:[-28.27749,182.85284,-469.62416,603.15916,-384.59976,97.35147],reachable:[.51,1]}},thinking1:{dark:{coefficients:[.55278,-.03667,-.45659,4.95347,-6.90265,3.0706],reachable:[0,.858]},light:{coefficients:[-37.10484,235.86282,-596.62344,754.3633,-474.00763,118.3551],reachable:[.535,1]}},thinking2:{dark:{coefficients:[.57486,-.01765,-.58987,5.25227,-7.27175,3.25532],reachable:[0,.842]},light:{coefficients:[-59.89653,377.05024,-945.07843,1182.03145,-734.96375,181.68658],reachable:[.556,1]}},thinking3:{dark:{coefficients:[.59621,-62e-5,-.71148,5.53588,-7.6392,3.44606],reachable:[0,.827]},light:{coefficients:[-72.07122,445.84082,-1099.57352,1353.88793,-829.53392,202.26164],reachable:[.58,1]}},thinking4:{dark:{coefficients:[.61691,.01462,-.82288,5.80651,-8.00641,3.64333],reachable:[0,.811]},light:{coefficients:[-110.14338,674.21488,-1645.75941,2004.32367,-1215.15899,293.3183],reachable:[.6,1]}},thinking5:{dark:{coefficients:[.63702,.02826,-.92498,6.06465,-8.37246,3.84651],reachable:[0,.795]},light:{coefficients:[-175.47701,1063.54495,-2570.70594,3098.80776,-1860.15527,444.76392],reachable:[.62,1]}},thinking6:{dark:{coefficients:[.65658,.04044,-1.01835,6.30989,-8.73529,4.05439],reachable:[0,.779]},light:{coefficients:[-183.81712,1094.70055,-2602.68539,3088.71276,-1826.91131,430.75931],reachable:[.643,1]}},subtle:{dark:{coefficients:[.56762,-.02475,-.5383,5.12628,-7.10931,3.17324],reachable:[0,.848]},light:{coefficients:[-232.85459,1376.54473,-3249.11801,3827.91186,-2248.29472,526.55751],reachable:[.657,1]}},thumb:{dark:{coefficients:[.60323,.00278,-.73328,5.57157,-7.68067,3.46933],reachable:[0,.823]},light:{coefficients:[-82.89897,511.01355,-1255.98095,1540.76821,-940.68087,228.58523],reachable:[.586,1]}},readable:{dark:{coefficients:[.66937,.04704,-1.06871,6.43941,-8.9332,4.17229],reachable:[0,.77]},light:{coefficients:[-1554.52576,8733.56817,-19604.93507,21977.72696,-12300.99599,2749.81288],reachable:[.751,1]}},emphasis:{dark:{coefficients:[.7303,.07695,-1.31626,7.1681,-10.14436,4.92846],reachable:[0,.712]},light:{coefficients:[-4948.31942,26870.91986,-58334.48399,63280.17197,-34298.01053,7430.30146],reachable:[.811,1]}},textOnPanel:{dark:{coefficients:[.86713,.05232,-.89428,4.79014,-5.5432,1.75023],reachable:[0,.542]},light:{coefficients:[-8570.89457,43954.60805,-90084.00702,92220.6791,-47152.15802,9632.27113],reachable:[.867,1]}},text:{dark:{coefficients:[.89242,.02311,-.44862,2.34417,-.06084,-2.63844],reachable:[0,.5]},light:{coefficients:[-2004.67048,6664.47299,-6060.70202,-1792.61209,5133.82359,-1939.85583],reachable:[.894,1]}}},TOOL_PANELS=["toolPendingBg","toolSuccessBg","toolErrorBg"],MESSAGE_PANELS=["userMessageBg","customMessageBg"],PANELS=["userMessageBg","toolPendingBg","toolSuccessBg","toolErrorBg","selectedBg","searchMatchBg","customMessageBg"],THINKING=["thinkingOff","thinkingMinimal","thinkingLow","thinkingMedium","thinkingHigh","thinkingXhigh","thinkingMax"],THINKING_LEVELS=["thinking0","thinking1","thinking2","thinking3","thinking4","thinking5","thinking6"],each=(tokens,on2,level)=>tokens.map(token=>({token,on:on2,level})),RULES=[...each(PANELS,["background"],"panel"),{token:"text",on:["background"],level:"text"},{token:"text",on:["selectedBg"],level:"textOnPanel"},{token:"userMessageText",on:["userMessageBg"],level:"textOnPanel"},{token:"toolTitle",on:TOOL_PANELS,level:"textOnPanel"},...each(["accent","success","error","warning"],["background","selectedBg",...TOOL_PANELS],"readable"),{token:"muted",on:["background","selectedBg","customMessageBg",...TOOL_PANELS],level:"readable"},{token:"dim",on:["background","selectedBg","customMessageBg",...TOOL_PANELS],level:"subtle"},{token:"thinkingText",on:["background"],level:"readable"},{token:"customMessageText",on:["customMessageBg",...TOOL_PANELS],level:"readable"},{token:"customMessageLabel",on:["background","customMessageBg","selectedBg",...TOOL_PANELS],level:"readable"},{token:"toolOutput",on:["background",...TOOL_PANELS],level:"readable"},...each(["mdHeading","mdLink","mdLinkUrl","mdCode","mdQuote","mdCodeBlockBorder","mdListBullet"],["background",...MESSAGE_PANELS],"readable"),{token:"mdCodeBlock",on:["background",...MESSAGE_PANELS,...TOOL_PANELS],level:"readable"},...each(["toolDiffAdded","toolDiffRemoved","toolDiffContext"],["background",...TOOL_PANELS],"readable"),...each(["syntaxComment","syntaxKeyword","syntaxFunction","syntaxVariable","syntaxString","syntaxNumber","syntaxType","syntaxOperator","syntaxPunctuation"],["background",...MESSAGE_PANELS,...TOOL_PANELS],"readable"),{token:"searchMatchText",on:["searchMatchBg"],level:"readable"},...each(["bashMode","border","borderAccent"],["background"],"readable"),{token:"borderMuted",on:["background"],level:"subtle"},...each(["mdQuoteBorder","mdHr"],["background",...MESSAGE_PANELS,...TOOL_PANELS],"readable"),{token:"scrollbarTrack",on:["background"],level:"track"},{token:"scrollbarThumb",on:["scrollbarTrack"],level:"thumb"},...THINKING.map((token,index)=>({token,on:["background"],level:THINKING_LEVELS[index]}))],READABLE_FLOOR={dark:"readable",light:"subtle"},FOREGROUND_LEVEL="emphasis",FOREGROUND_TOKENS=["text","userMessageText","toolTitle"],TEXT_MINIMUM_WCAG_CONTRAST=4.5,SOLVE_ORDER=(()=>{let order=[],visit=token=>{if(!order.includes(token)){for(let rule of RULES)if(rule.token===token)for(let surface of rule.on)surface!=="background"&&visit(surface);order.push(token)}};for(let rule of RULES)visit(rule.token);return order})();function oklabLightness(color){return colorToOklch(rgbColor(color.r,color.g,color.b)).l}function relativeLuminance({r,g,b:b2}){let linear=channel=>{let value=channel/255;return value<=.04045?value/12.92:((value+.055)/1.055)**2.4};return .2126*linear(r)+.7152*linear(g)+.0722*linear(b2)}function wcagContrast(first,second){let a=relativeLuminance(first),b2=relativeLuminance(second);return(Math.max(a,b2)+.05)/(Math.min(a,b2)+.05)}function terminalAppearance(background,foreground){let white={r:255,g:255,b:255},black={r:0,g:0,b:0},whiteContrast=wcagContrast(white,background),blackContrast=wcagContrast(black,background);if(foreground){let foregroundL=oklabLightness(foreground),backgroundL=oklabLightness(background);if(Math.abs(foregroundL-backgroundL)>.05){let appearance=foregroundL>backgroundL?"dark":"light";if((appearance==="dark"?whiteContrast:blackContrast)>=TEXT_MINIMUM_WCAG_CONTRAST)return appearance}}return whiteContrast>=blackContrast?"dark":"light"}var clamp2=(value,min,max)=>Math.min(max,Math.max(min,value));function hexOf({r,g,b:b2}){return`#${[r,g,b2].map(channel=>Math.round(channel).toString(16).padStart(2,"0")).join("")}`}function bellWeight(lightness){let gaussian=x2=>Math.exp(-((x2-.5)**2)/.125);return(gaussian(lightness)-gaussian(0))/(1-gaussian(0))}function saturationCurve({saturation:{min,max}},lightness){let floor=max>0?min/max:1;return floor+(1-floor)*bellWeight(lightness)}function levelTarget(level,appearance,surfaceL){let curve=LEVELS[level][appearance];if(!(surfaceL<curve.reachable[0]||surfaceL>curve.reachable[1]))return curve.coefficients.reduce((sum,coefficient,power)=>sum+coefficient*surfaceL**power,0)}function generateSystemThemeColors(input){let saturation=clamp2(input.saturation??1,0,1),{background,foreground}=input;if(!background)return indexedColors(saturation,input.appearanceHint);let palette=input.palette?.length===16?input.palette.map(sourceOf):void 0,appearance=terminalAppearance(background,foreground),lighter=appearance==="dark",extreme=lighter?1:0,backgroundL=oklabLightness(background),paint=(token,oklabL)=>{let lightness=oklabToOkhslLightness(oklabL),family=FAMILIES[TOKEN_FAMILIES[token]];if(!palette){let{min,max}=family.saturation;return okhslColor(family.hue,(min+(max-min)*bellWeight(lightness))*saturation,lightness)}return anchored(palette[TOKEN_SLOTS[token]??family.slot],family,lightness,saturation)},target=(level,surfaceL,t)=>{let reached=levelTarget(level,appearance,surfaceL);if(reached===void 0&&t===0)return;let distance=(reached??extreme)-surfaceL,floor=(levelTarget(READABLE_FLOOR[appearance],appearance,surfaceL)??extreme)-surfaceL,compressed=Math.abs(distance)>Math.abs(floor)?distance-(distance-floor)*Math.min(t,1):distance;return surfaceL+compressed*(1-Math.max(0,t-1))},extremeText=lighter?{r:255,g:255,b:255}:{r:0,g:0,b:0},readable=color=>wcagContrast(extremeText,color)>=TEXT_MINIMUM_WCAG_CONTRAST,limitPanel=(token,l3)=>{let color=paint(token,l3);if(readable(color))return color;let[low,high]=[backgroundL,l3];for(let index=0;index<20;index++){let middle=(low+high)/2;readable(paint(token,middle))?low=middle:high=middle}return paint(token,low)},solve=t=>{let colors2=new Map([["background",background]]);for(let token of SOLVE_ORDER){let targets=[];for(let rule of RULES)if(rule.token===token)for(let surface of rule.on){let value=target(rule.level,oklabLightness(colors2.get(surface)??background),t);if(value===void 0||value<0||value>1)return;targets.push(value)}let l3=lighter?Math.max(...targets):Math.min(...targets);colors2.set(token,PANELS.includes(token)?limitPanel(token,l3):paint(token,l3))}return colors2},relaxation=0,colors=solve(0);if(!colors){let[low,high]=[0,2];colors=solve(high);for(let index=0;index<20;index++){let middle=(low+high)/2,attempt=solve(middle);attempt?[high,colors]=[middle,attempt]:low=middle}relaxation=high}let solved=colors??new Map,surfacesOf=token=>RULES.filter(rule=>rule.token===token).flatMap(rule=>rule.on.map(surface=>solved.get(surface)??background)),result={};for(let token of Object.keys(TOKEN_FAMILIES)){let color=solved.get(token);result[token]=color?hexOf(color):""}for(let token of FOREGROUND_TOKENS){let surfaces=surfacesOf(token),text=solved.get(token);if(foreground){let targets=surfaces.map(surface=>target(FOREGROUND_LEVEL,oklabLightness(surface),relaxation));if(targets.every(value=>value!==void 0&&value>=0&&value<=1)){let needed=lighter?Math.max(...targets):Math.min(...targets),foregroundL=oklabLightness(foreground);if(lighter?foregroundL>=needed:foregroundL<=needed){result[token]="";continue}text=anchored(sourceOf(foreground),FAMILIES.neutral,oklabToOkhslLightness(needed),saturation)}}text&&(result[token]=hexOf(withTextContrast(text,surfaces,lighter)))}return{colors:result,dim:[],appearance}}function okhslOf({r,g,b:b2}){return colorToOkhsl(rgbColor(r,g,b2))}function sourceOf(color){return{...okhslOf(color),chroma:colorToOklch(rgbColor(color.r,color.g,color.b)).c}}function anchored(source,family,lightness,saturation){let anchor=saturationCurve(family,source.l),falloff=anchor>0?Math.min(1,saturationCurve(family,lightness)/anchor):1,color=okhslColor(source.h,source.s*falloff*saturation,lightness),cap=source.chroma*falloff*saturation,{l:l3,c:c2}=colorToOklch(color);return c2<=cap?color:colorToRgb(oklchColor(l3,cap,source.h))}function withTextContrast(color,surfaces,lighter){let meets=candidate=>surfaces.every(surface=>wcagContrast(candidate,surface)>=TEXT_MINIMUM_WCAG_CONTRAST);if(meets(color))return color;let{h,s,l:l3}=okhslOf(color),at2=lightness=>okhslColor(h,s,lightness),extreme=lighter?1:0;if(!meets(at2(extreme)))return at2(extreme);let[low,high]=[l3,extreme];for(let index=0;index<20;index++){let middle=(low+high)/2;meets(at2(middle))?high=middle:low=middle}return at2(high)}function indexedColors(saturation,appearance){let colors={},dim=[];for(let[token,familyName]of Object.entries(TOKEN_FAMILIES)){if(PANELS.includes(token)){colors[token]="";continue}let neutral=familyName==="neutral";colors[token]=!neutral&&saturation>0?TOKEN_SLOTS[token]??FAMILIES[familyName].slot:"",neutral&&!FOREGROUND_TOKENS.includes(token)&&dim.push(token)}return{colors,dim,appearance}}var themeJsonValidator;function setThemeJsonValidator(validator){themeJsonValidator=validator}function resolveVarRefs(value,vars,visited=new Set){if(typeof value=="number"||value===""||value.startsWith("#")||/^ok(lch|hsl)\(/i.test(value))return value;if(visited.has(value))throw new Error(`Circular variable reference detected: ${value}`);if(!(value in vars))throw new Error(`Variable reference not found: ${value}`);return visited.add(value),resolveVarRefs(vars[value],vars,visited)}function resolveThemeColors(colors,vars={}){let resolved={};for(let[key,value]of Object.entries(colors))resolved[key]=resolveVarRefs(value,vars);return resolved}function withThemeColorFallbacks(colors){return{...colors,scrollbarTrack:colors.scrollbarTrack??colors.muted,scrollbarThumb:colors.scrollbarThumb??colors.text,thinkingMax:colors.thinkingMax??colors.thinkingXhigh,searchMatchBg:colors.searchMatchBg??colors.selectedBg,searchMatchText:colors.searchMatchText??colors.text}}var terminalColors={},terminalColorsPending=!1,terminalColorScheme;function setTerminalColors(colors){terminalColors={...colors},terminalColorsPending=!1}function setTerminalColorScheme(scheme){terminalColorScheme=scheme}function markTerminalColorsPending(){terminalColorsPending=!0}var GUESSED_DEFAULT_COLORS={dark:{foreground:parseColor("#e5e5e7"),background:parseColor("#000000")},light:{foreground:parseColor("#000000"),background:parseColor("#ffffff")}};function averageLightness(colors){let fixed=colors.filter(color=>color.kind!=="indexed"||color.index>=16);if(fixed.length!==0)return fixed.reduce((sum,color)=>sum+colorToOklch(color).l,0)/fixed.length}function detectAppearance(foregrounds,backgrounds){let fg=averageLightness(foregrounds),bg=averageLightness(backgrounds);if(fg!==void 0&&bg!==void 0)return bg<fg?"dark":"light";if(bg!==void 0)return bg<.5?"dark":"light";if(fg!==void 0)return fg>.5?"dark":"light"}var Theme=class{name;sourcePath;sourceInfo;mode;fgAnsi=new Map;bgAnsi=new Map;concreteColors={};defaultForegroundTokens=[];defaultBackgroundTokens=[];dimTokens;ownAppearance;resolvedColors;constructor(fgColors,bgColors,mode,options={}){this.name=options.name,this.sourcePath=options.sourcePath,this.sourceInfo=options.sourceInfo,this.mode=mode,this.dimTokens=new Set(options.dim);let foregrounds={...fgColors,scrollbarTrack:fgColors.scrollbarTrack??fgColors.muted,scrollbarThumb:fgColors.scrollbarThumb??fgColors.text,thinkingMax:fgColors.thinkingMax??fgColors.thinkingXhigh,searchMatchText:fgColors.searchMatchText??fgColors.text},backgrounds={...bgColors,searchMatchBg:bgColors.searchMatchBg??bgColors.selectedBg},concreteForegrounds=[],concreteBackgrounds=[],addToken=(token,value,isBackground)=>{if(value==="")return(isBackground?this.defaultBackgroundTokens:this.defaultForegroundTokens).push(token),isBackground?"\x1B[49m":"\x1B[39m";let color=parseColor(value);return this.concreteColors[token]=color,(isBackground?concreteBackgrounds:concreteForegrounds).push(color),isBackground?backgroundAnsi(color,mode):foregroundAnsi(color,mode)};for(let[token,value]of Object.entries(foregrounds))this.fgAnsi.set(token,addToken(token,value,!1));for(let[token,value]of Object.entries(backgrounds))this.bgAnsi.set(token,addToken(token,value,!0));this.ownAppearance=options.appearance??detectAppearance(concreteForegrounds,concreteBackgrounds)}get appearance(){return this.ownAppearance??getTerminalTheme()}get colors(){let terminal=terminalColors;if(this.resolvedColors?.terminal!==terminal){let guess=GUESSED_DEFAULT_COLORS[this.appearance],toColor=(rgb,fallback)=>rgb?rgbColor(rgb.r,rgb.g,rgb.b):fallback,foreground=toColor(terminal.foreground,guess.foreground),background=toColor(terminal.background,guess.background),colors={...this.concreteColors};for(let token of this.defaultForegroundTokens)colors[token]=foreground;for(let token of this.defaultBackgroundTokens)colors[token]=background;for(let token of this.dimTokens){let color=colors[token];color&&(colors[token]=mixColors(color,background,.4))}this.resolvedColors={terminal,colors:Object.freeze(colors)}}return this.resolvedColors.colors}style(text,options){let{fg,bg}=options;return typeof fg=="string"&&this.dimTokens.has(fg)&&(options={...options,dim:!0}),styleTextWithAnsi(text,fg===void 0?void 0:typeof fg=="string"?this.tokenAnsi(this.fgAnsi,fg):foregroundAnsi(fg,this.mode),bg===void 0?void 0:typeof bg=="string"?this.tokenAnsi(this.bgAnsi,bg):backgroundAnsi(bg,this.mode),options)}fg(color,text){let ansi=this.tokenAnsi(this.fgAnsi,color);return this.dimTokens.has(color)?`${ansi}\x1B[2m${text}\x1B[22;39m`:`${ansi}${text}\x1B[39m`}bg(color,text){return`${this.tokenAnsi(this.bgAnsi,color)}${text}\x1B[49m`}tokenAnsi(ansi,token){let value=ansi.get(token);if(value===void 0)throw new Error(`Unknown theme color: ${token}`);return value}bold(text){return source_default.bold(text)}italic(text){return source_default.italic(text)}underline(text){return source_default.underline(text)}inverse(text){return source_default.inverse(text)}strikethrough(text){return source_default.strikethrough(text)}getFgAnsi(color){let ansi=this.tokenAnsi(this.fgAnsi,color);return this.dimTokens.has(color)?`${ansi}\x1B[2m`:ansi}getBgAnsi(color){return this.tokenAnsi(this.bgAnsi,color)}getColorMode(){return this.mode}getThinkingBorderColor(level){switch(level){case"off":return str=>this.fg("thinkingOff",str);case"minimal":return str=>this.fg("thinkingMinimal",str);case"low":return str=>this.fg("thinkingLow",str);case"medium":return str=>this.fg("thinkingMedium",str);case"high":return str=>this.fg("thinkingHigh",str);case"xhigh":return str=>this.fg("thinkingXhigh",str);case"max":return str=>this.fg("thinkingMax",str);default:return str=>this.fg("thinkingOff",str)}}getBashModeBorderColor(){return str=>this.fg("bashMode",str)}},BUILTIN_THEMES;function getBuiltinThemes(){if(!BUILTIN_THEMES){let themesDir=getThemesDir(),darkPath=path4.join(themesDir,"dark.json"),lightPath=path4.join(themesDir,"light.json");BUILTIN_THEMES={dark:JSON.parse(stripBom(fs3.readFileSync(darkPath,"utf-8"))),light:JSON.parse(stripBom(fs3.readFileSync(lightPath,"utf-8")))}}return BUILTIN_THEMES}function getAvailableThemes(){return getAvailableThemesWithPaths().map(({name})=>name)}function getAvailableThemesWithPaths(){let themesDir=getThemesDir(),result=[],seen=new Set,addTheme=themeInfo=>{seen.has(themeInfo.name)||(seen.add(themeInfo.name),result.push(themeInfo))};addTheme({name:SYSTEM_THEME_NAME,path:void 0});for(let name of Object.keys(getBuiltinThemes()))addTheme({name,path:path4.join(themesDir,`${name}.json`)});for(let themeInfo of getCustomThemeInfos())addTheme(themeInfo);for(let[name,theme2]of registeredThemes.entries())addTheme({name,path:theme2.sourcePath});return result.sort((a,b2)=>a.name===SYSTEM_THEME_NAME?-1:b2.name===SYSTEM_THEME_NAME?1:a.name.localeCompare(b2.name))}function getCustomThemeInfos(){let customThemesDir=getCustomThemesDir(),result=[];if(!fs3.existsSync(customThemesDir))return result;for(let file of fs3.readdirSync(customThemesDir)){if(!file.endsWith(".json"))continue;let themePath=path4.join(customThemesDir,file);try{let customTheme=loadThemeFromPath(themePath);customTheme.name&&result.push({name:customTheme.name,path:themePath})}catch{}}return result}function assertThemeNameIsValid(name){if(name.includes("/"))throw new Error(`Invalid theme name "${name}": theme names cannot contain "/" because it is reserved for automatic light/dark theme settings.`)}function parseThemeJson(label,json2){if(themeJsonValidator)return themeJsonValidator(label,json2);if(typeof json2!="object"||json2===null||!("colors"in json2))throw new Error(`Invalid theme "${label}": expected an object with a "colors" map.`);return json2}function parseThemeJsonContent(label,content){let json2;try{json2=JSON.parse(stripBom(content))}catch(error){throw new Error(`Failed to parse theme ${label}: ${error}`)}return parseThemeJson(label,json2)}function loadThemeJson(name){let builtinThemes=getBuiltinThemes();if(name in builtinThemes)return builtinThemes[name];let registeredTheme=registeredThemes.get(name);if(registeredTheme?.sourcePath){let content2=fs3.readFileSync(registeredTheme.sourcePath,"utf-8");return parseThemeJsonContent(registeredTheme.sourcePath,content2)}if(registeredTheme)throw new Error(`Theme "${name}" does not have a source path for export`);let customThemesDir=getCustomThemesDir(),themePath=path4.join(customThemesDir,`${name}.json`);if(!fs3.existsSync(themePath))throw new Error(`Theme not found: ${name}`);let content=fs3.readFileSync(themePath,"utf-8");return parseThemeJsonContent(name,content)}var BACKGROUND_TOKENS=new Set(["selectedBg","searchMatchBg","userMessageBg","customMessageBg","toolPendingBg","toolSuccessBg","toolErrorBg"]);function splitThemeColors(colors){let fgColors={},bgColors={};for(let[key,value]of Object.entries(colors))BACKGROUND_TOKENS.has(key)?bgColors[key]=value:fgColors[key]=value;return{fgColors,bgColors}}function createTheme(themeJson,mode,sourcePath){let colorMode=mode??getTerminalColorMode(),resolvedColors=resolveThemeColors(withThemeColorFallbacks(themeJson.colors),themeJson.vars),{fgColors,bgColors}=splitThemeColors(resolvedColors);return new Theme(fgColors,bgColors,colorMode,{name:themeJson.name,sourcePath,appearance:themeJson.appearance})}function createSystemTheme(mode){let generated=generateSystemThemeColors({...terminalColors,saturation:terminalColorsPending?0:1,appearanceHint:getTerminalTheme()}),{fgColors,bgColors}=splitThemeColors(generated.colors);return new Theme(fgColors,bgColors,mode??getTerminalColorMode(),{name:SYSTEM_THEME_NAME,appearance:generated.appearance,dim:generated.dim})}function loadThemeFromPath(themePath,mode){let content=fs3.readFileSync(themePath,"utf-8"),themeJson=parseThemeJsonContent(themePath,content);return createTheme(themeJson,mode,themePath)}function loadTheme(name,mode){if(name===SYSTEM_THEME_NAME)return createSystemTheme(mode);let registeredTheme=registeredThemes.get(name);if(registeredTheme)return registeredTheme;let themeJson=loadThemeJson(name);return createTheme(themeJson,mode)}function getThemeByName(name){try{return loadTheme(name)}catch{return}}function parseAutoThemeSetting(themeSetting){if(!themeSetting)return;let slashIndex=themeSetting.indexOf("/");if(slashIndex===-1||themeSetting.indexOf("/",slashIndex+1)!==-1)return;let lightTheme=themeSetting.slice(0,slashIndex).trim(),darkTheme=themeSetting.slice(slashIndex+1).trim();if(!(!lightTheme||!darkTheme))return{lightTheme,darkTheme}}function resolveThemeSetting(themeSetting,terminalTheme){let autoTheme=parseAutoThemeSetting(themeSetting);if(autoTheme)return terminalTheme==="light"?autoTheme.lightTheme:autoTheme.darkTheme;if(!themeSetting?.includes("/")&&typeof themeSetting=="string")return themeSetting}function detectColorFgBgTheme(env2=process.env){let bg=env2.COLORFGBG?.split(";").at(-1)?.trim();if(!bg||!/^\d{1,2}$/.test(bg))return;let index=Number(bg);if(!(index>15))return index<=6||index===8?"dark":"light"}function detectTerminalTheme(colors={},reportedScheme,env2=process.env){let{background,foreground}=colors;return background?terminalAppearance(background,foreground):reportedScheme??detectColorFgBgTheme(env2)??"dark"}function getTerminalTheme(){return detectTerminalTheme(terminalColors,terminalColorScheme)}var THEME_KEY=Symbol.for("@earendil-works/pi-coding-agent:theme"),THEME_KEY_OLD=Symbol.for("@mariozechner/pi-coding-agent:theme"),theme=new Proxy({},{get(_target,prop){let t=globalThis[THEME_KEY];if(!t)throw new Error("Theme not initialized. Call initTheme() first.");return t[prop]}});function setGlobalTheme(t){globalThis[THEME_KEY]=t,globalThis[THEME_KEY_OLD]=t}var currentThemeName,themeWatcher,themeReloadTimer,onThemeChangeCallback,registeredThemes=new Map;function setRegisteredThemes(themes){registeredThemes.clear();for(let theme2 of themes)theme2.name&&(assertThemeNameIsValid(theme2.name),registeredThemes.set(theme2.name,theme2))}function initTheme(themeName,enableWatcher=!1){let name=themeName??SYSTEM_THEME_NAME;currentThemeName=name;try{setGlobalTheme(loadTheme(name)),enableWatcher&&startThemeWatcher()}catch{currentThemeName=SYSTEM_THEME_NAME,setGlobalTheme(loadTheme(SYSTEM_THEME_NAME))}}function setTheme(name,enableWatcher=!1){currentThemeName=name;try{return setGlobalTheme(loadTheme(name)),enableWatcher&&startThemeWatcher(),onThemeChangeCallback&&onThemeChangeCallback(),{success:!0}}catch(error){return currentThemeName=SYSTEM_THEME_NAME,setGlobalTheme(loadTheme(SYSTEM_THEME_NAME)),{success:!1,error:error instanceof Error?error.message:String(error)}}}function setThemeInstance(themeInstance){setGlobalTheme(themeInstance),currentThemeName="<in-memory>",stopThemeWatcher(),onThemeChangeCallback&&onThemeChangeCallback()}function onThemeChange(callback){onThemeChangeCallback=callback}function startThemeWatcher(){if(stopThemeWatcher(),!currentThemeName||currentThemeName==="dark"||currentThemeName==="light"||currentThemeName===SYSTEM_THEME_NAME)return;let customThemesDir=getCustomThemesDir(),watchedThemeName=currentThemeName,watchedFileName=`${watchedThemeName}.json`,themeFile=path4.join(customThemesDir,watchedFileName);if(!fs3.existsSync(themeFile))return;let scheduleReload=()=>{themeReloadTimer&&clearTimeout(themeReloadTimer),themeReloadTimer=setTimeout(()=>{if(themeReloadTimer=void 0,currentThemeName===watchedThemeName&&fs3.existsSync(themeFile))try{let reloadedTheme=loadThemeFromPath(themeFile);registeredThemes.set(watchedThemeName,reloadedTheme),setGlobalTheme(reloadedTheme),onThemeChangeCallback&&onThemeChangeCallback()}catch{}},100)};themeWatcher=watchWithErrorHandler(customThemesDir,(_eventType,filename)=>{if(currentThemeName===watchedThemeName){if(!filename){scheduleReload();return}filename===watchedFileName&&scheduleReload()}},()=>{closeWatcher(themeWatcher),themeWatcher=void 0})??void 0}function stopThemeWatcher(){themeReloadTimer&&(clearTimeout(themeReloadTimer),themeReloadTimer=void 0),closeWatcher(themeWatcher),themeWatcher=void 0}function getResolvedThemeColors(themeName){let colors=loadTheme(themeName??currentThemeName??SYSTEM_THEME_NAME).colors;return Object.fromEntries(Object.entries(colors).map(([token,color])=>[token,colorToHex(color)]))}function getThemeExportColors(themeName){let name=themeName??currentThemeName??SYSTEM_THEME_NAME;if(name===SYSTEM_THEME_NAME)return{};try{let themeJson=loadThemeJson(name),exportSection=themeJson.export;if(!exportSection)return{};let vars=themeJson.vars??{},resolve2=value=>{if(value===void 0)return;let resolved=resolveVarRefs(value,vars);if(typeof resolved=="number")return colorToHex(indexedColor(resolved));if(resolved!=="")return/^okhsl\(/i.test(resolved)?colorToHex(parseColor(resolved)):resolved};return{pageBg:resolve2(exportSection.pageBg),cardBg:resolve2(exportSection.cardBg),infoBg:resolve2(exportSection.infoBg)}}catch{return{}}}var cachedHighlightThemeFor,cachedCliHighlightTheme;function buildCliHighlightTheme(t){return{keyword:s=>t.fg("syntaxKeyword",s),built_in:s=>t.fg("syntaxType",s),literal:s=>t.fg("syntaxNumber",s),number:s=>t.fg("syntaxNumber",s),regexp:s=>t.fg("syntaxString",s),string:s=>t.fg("syntaxString",s),comment:s=>t.fg("syntaxComment",s),doctag:s=>t.fg("syntaxComment",s),meta:s=>t.fg("muted",s),function:s=>t.fg("syntaxFunction",s),title:s=>t.fg("syntaxFunction",s),class:s=>t.fg("syntaxType",s),type:s=>t.fg("syntaxType",s),tag:s=>t.fg("syntaxPunctuation",s),name:s=>t.fg("syntaxKeyword",s),attr:s=>t.fg("syntaxVariable",s),variable:s=>t.fg("syntaxVariable",s),params:s=>t.fg("syntaxVariable",s),operator:s=>t.fg("syntaxOperator",s),punctuation:s=>t.fg("syntaxPunctuation",s),emphasis:s=>t.italic(s),strong:s=>t.bold(s),link:s=>t.underline(s),addition:s=>t.fg("toolDiffAdded",s),deletion:s=>t.fg("toolDiffRemoved",s)}}function getCliHighlightTheme(t){return(cachedHighlightThemeFor!==t||!cachedCliHighlightTheme)&&(cachedHighlightThemeFor=t,cachedCliHighlightTheme=buildCliHighlightTheme(t)),cachedCliHighlightTheme}function highlightCode(code,lang){let validLang=lang&&supportsLanguage(lang)?lang:void 0;if(!validLang)return code.split(`
126
+ `||nextChar==="\r"}function renderHighlightedHtml(html,theme2={}){let output="",textBuffer="",scopes=[],flushText=()=>{if(!textBuffer)return;let formatter=getActiveFormatter(scopes,theme2);output+=formatter?textBuffer.split(`
127
+ `).map(line=>line&&formatter(line)).join(`
128
+ `):textBuffer,textBuffer=""},index=0;for(;index<html.length;){if(isSpanOpenTagStart(html,index)){let tagEndIndex=html.indexOf(">",index+5);if(tagEndIndex!==-1){flushText();let tag=html.slice(index,tagEndIndex+1),scope=getScopeFromSpanTag(tag);scopes.push(scope),index=tagEndIndex+1;continue}}if(html.startsWith(SPAN_CLOSE,index)){flushText(),scopes.length>0&&scopes.pop(),index+=SPAN_CLOSE.length;continue}if(html[index]==="&"){let decoded=decodeHtmlEntityAt(html,index);if(decoded){textBuffer+=decoded.text,index+=decoded.length;continue}}textBuffer+=html[index],index++}return flushText(),output}function highlight(code,options={}){let html=options.language?import_core.default.highlight(code,{language:options.language,ignoreIllegals:options.ignoreIllegals}).value:import_core.default.highlightAuto(code,options.languageSubset).value;return renderHighlightedHtml(html,options.theme)}function supportsLanguage(name){return import_core.default.getLanguage(name)!==void 0}var SYSTEM_THEME_NAME="system",FAMILIES={neutral:{hue:231.49,saturation:{min:.02,max:.08},slot:8},blue:{hue:231.49,saturation:{min:.1,max:.68},slot:4},green:{hue:158.68,saturation:{min:.1,max:.76},slot:2},red:{hue:20,saturation:{min:.1,max:.92},slot:1},yellow:{hue:82.36,saturation:{min:.5,max:1},slot:3},orange:{hue:52,saturation:{min:.12,max:.85},slot:3},violet:{hue:295,saturation:{min:.2,max:.6},slot:5},calamine:{hue:202.43,saturation:{min:.1,max:.74},slot:6},thinkingSlate:{hue:231.49,saturation:{min:.08,max:.2},slot:4},thinkingBlue:{hue:231.49,saturation:{min:.2,max:.45},slot:4},thinkingPeriwinkle:{hue:263.25,saturation:{min:.3,max:.6},slot:6},thinkingViolet:{hue:295,saturation:{min:.4,max:.75},slot:5},thinkingMagenta:{hue:337.5,saturation:{min:.5,max:.85},slot:13},thinkingRed:{hue:20,saturation:{min:.95,max:1},slot:1}},TOKEN_FAMILIES={selectedBg:"blue",searchMatchBg:"orange",userMessageBg:"blue",customMessageBg:"violet",toolPendingBg:"neutral",toolSuccessBg:"green",toolErrorBg:"red",text:"neutral",userMessageText:"neutral",customMessageText:"neutral",toolTitle:"neutral",syntaxOperator:"neutral",syntaxPunctuation:"neutral",muted:"neutral",dim:"neutral",thinkingText:"neutral",toolOutput:"neutral",mdLinkUrl:"neutral",mdQuote:"neutral",mdQuoteBorder:"neutral",mdHr:"neutral",mdCodeBlockBorder:"neutral",toolDiffContext:"neutral",syntaxComment:"neutral",scrollbarTrack:"neutral",scrollbarThumb:"neutral",searchMatchText:"neutral",borderMuted:"neutral",accent:"violet",borderAccent:"violet",customMessageLabel:"violet",mdCode:"violet",mdListBullet:"violet",syntaxType:"violet",border:"blue",mdLink:"blue",syntaxKeyword:"blue",syntaxVariable:"calamine",success:"green",mdCodeBlock:"green",toolDiffAdded:"green",bashMode:"green",syntaxNumber:"green",error:"red",toolDiffRemoved:"red",warning:"yellow",mdHeading:"yellow",syntaxFunction:"yellow",syntaxString:"orange",thinkingOff:"neutral",thinkingMinimal:"thinkingSlate",thinkingLow:"thinkingBlue",thinkingMedium:"thinkingPeriwinkle",thinkingHigh:"thinkingViolet",thinkingXhigh:"thinkingMagenta",thinkingMax:"thinkingRed"},TOKEN_SLOTS={syntaxString:2,syntaxNumber:5,searchMatchBg:3},LEVELS={panel:{dark:{coefficients:[.29131,-.39746,2.33185,-.85524,-1.2076,.86276],reachable:[0,.979]},light:{coefficients:[-3.74073,27.94549,-78.44258,112.6798,-79.60015,22.11277],reachable:[.348,1]}},track:{dark:{coefficients:[.39028,-.23015,.83573,2.43829,-4.38292,2.01582],reachable:[0,.946]},light:{coefficients:[-5.24921,38.37322,-107.28833,152.10005,-106.17127,29.18061],reachable:[.368,1]}},thinking0:{dark:{coefficients:[.52988,-.05809,-.30924,4.63567,-6.52933,2.89108],reachable:[0,.873]},light:{coefficients:[-28.27749,182.85284,-469.62416,603.15916,-384.59976,97.35147],reachable:[.51,1]}},thinking1:{dark:{coefficients:[.55278,-.03667,-.45659,4.95347,-6.90265,3.0706],reachable:[0,.858]},light:{coefficients:[-37.10484,235.86282,-596.62344,754.3633,-474.00763,118.3551],reachable:[.535,1]}},thinking2:{dark:{coefficients:[.57486,-.01765,-.58987,5.25227,-7.27175,3.25532],reachable:[0,.842]},light:{coefficients:[-59.89653,377.05024,-945.07843,1182.03145,-734.96375,181.68658],reachable:[.556,1]}},thinking3:{dark:{coefficients:[.59621,-62e-5,-.71148,5.53588,-7.6392,3.44606],reachable:[0,.827]},light:{coefficients:[-72.07122,445.84082,-1099.57352,1353.88793,-829.53392,202.26164],reachable:[.58,1]}},thinking4:{dark:{coefficients:[.61691,.01462,-.82288,5.80651,-8.00641,3.64333],reachable:[0,.811]},light:{coefficients:[-110.14338,674.21488,-1645.75941,2004.32367,-1215.15899,293.3183],reachable:[.6,1]}},thinking5:{dark:{coefficients:[.63702,.02826,-.92498,6.06465,-8.37246,3.84651],reachable:[0,.795]},light:{coefficients:[-175.47701,1063.54495,-2570.70594,3098.80776,-1860.15527,444.76392],reachable:[.62,1]}},thinking6:{dark:{coefficients:[.65658,.04044,-1.01835,6.30989,-8.73529,4.05439],reachable:[0,.779]},light:{coefficients:[-183.81712,1094.70055,-2602.68539,3088.71276,-1826.91131,430.75931],reachable:[.643,1]}},subtle:{dark:{coefficients:[.56762,-.02475,-.5383,5.12628,-7.10931,3.17324],reachable:[0,.848]},light:{coefficients:[-232.85459,1376.54473,-3249.11801,3827.91186,-2248.29472,526.55751],reachable:[.657,1]}},thumb:{dark:{coefficients:[.60323,.00278,-.73328,5.57157,-7.68067,3.46933],reachable:[0,.823]},light:{coefficients:[-82.89897,511.01355,-1255.98095,1540.76821,-940.68087,228.58523],reachable:[.586,1]}},readable:{dark:{coefficients:[.66937,.04704,-1.06871,6.43941,-8.9332,4.17229],reachable:[0,.77]},light:{coefficients:[-1554.52576,8733.56817,-19604.93507,21977.72696,-12300.99599,2749.81288],reachable:[.751,1]}},emphasis:{dark:{coefficients:[.7303,.07695,-1.31626,7.1681,-10.14436,4.92846],reachable:[0,.712]},light:{coefficients:[-4948.31942,26870.91986,-58334.48399,63280.17197,-34298.01053,7430.30146],reachable:[.811,1]}},textOnPanel:{dark:{coefficients:[.86713,.05232,-.89428,4.79014,-5.5432,1.75023],reachable:[0,.542]},light:{coefficients:[-8570.89457,43954.60805,-90084.00702,92220.6791,-47152.15802,9632.27113],reachable:[.867,1]}},text:{dark:{coefficients:[.89242,.02311,-.44862,2.34417,-.06084,-2.63844],reachable:[0,.5]},light:{coefficients:[-2004.67048,6664.47299,-6060.70202,-1792.61209,5133.82359,-1939.85583],reachable:[.894,1]}}},TOOL_PANELS=["toolPendingBg","toolSuccessBg","toolErrorBg"],MESSAGE_PANELS=["userMessageBg","customMessageBg"],PANELS=["userMessageBg","toolPendingBg","toolSuccessBg","toolErrorBg","selectedBg","searchMatchBg","customMessageBg"],THINKING=["thinkingOff","thinkingMinimal","thinkingLow","thinkingMedium","thinkingHigh","thinkingXhigh","thinkingMax"],THINKING_LEVELS=["thinking0","thinking1","thinking2","thinking3","thinking4","thinking5","thinking6"],each=(tokens,on2,level)=>tokens.map(token=>({token,on:on2,level})),RULES=[...each(PANELS,["background"],"panel"),{token:"text",on:["background"],level:"text"},{token:"text",on:["selectedBg"],level:"textOnPanel"},{token:"userMessageText",on:["userMessageBg"],level:"textOnPanel"},{token:"toolTitle",on:TOOL_PANELS,level:"textOnPanel"},...each(["accent","success","error","warning"],["background","selectedBg",...TOOL_PANELS],"readable"),{token:"muted",on:["background","selectedBg","customMessageBg",...TOOL_PANELS],level:"readable"},{token:"dim",on:["background","selectedBg","customMessageBg",...TOOL_PANELS],level:"subtle"},{token:"thinkingText",on:["background"],level:"readable"},{token:"customMessageText",on:["customMessageBg",...TOOL_PANELS],level:"readable"},{token:"customMessageLabel",on:["background","customMessageBg","selectedBg",...TOOL_PANELS],level:"readable"},{token:"toolOutput",on:["background",...TOOL_PANELS],level:"readable"},...each(["mdHeading","mdLink","mdLinkUrl","mdCode","mdQuote","mdCodeBlockBorder","mdListBullet"],["background",...MESSAGE_PANELS],"readable"),{token:"mdCodeBlock",on:["background",...MESSAGE_PANELS,...TOOL_PANELS],level:"readable"},...each(["toolDiffAdded","toolDiffRemoved","toolDiffContext"],["background",...TOOL_PANELS],"readable"),...each(["syntaxComment","syntaxKeyword","syntaxFunction","syntaxVariable","syntaxString","syntaxNumber","syntaxType","syntaxOperator","syntaxPunctuation"],["background",...MESSAGE_PANELS,...TOOL_PANELS],"readable"),{token:"searchMatchText",on:["searchMatchBg"],level:"readable"},...each(["bashMode","border","borderAccent"],["background"],"readable"),{token:"borderMuted",on:["background"],level:"subtle"},...each(["mdQuoteBorder","mdHr"],["background",...MESSAGE_PANELS,...TOOL_PANELS],"readable"),{token:"scrollbarTrack",on:["background"],level:"track"},{token:"scrollbarThumb",on:["scrollbarTrack"],level:"thumb"},...THINKING.map((token,index)=>({token,on:["background"],level:THINKING_LEVELS[index]}))],READABLE_FLOOR={dark:"readable",light:"subtle"},FOREGROUND_LEVEL="emphasis",FOREGROUND_TOKENS=["text","userMessageText","toolTitle"],TEXT_MINIMUM_WCAG_CONTRAST=4.5,SOLVE_ORDER=(()=>{let order=[],visit=token=>{if(!order.includes(token)){for(let rule of RULES)if(rule.token===token)for(let surface of rule.on)surface!=="background"&&visit(surface);order.push(token)}};for(let rule of RULES)visit(rule.token);return order})();function oklabLightness(color){return colorToOklch(rgbColor(color.r,color.g,color.b)).l}function relativeLuminance({r,g,b:b2}){let linear=channel=>{let value=channel/255;return value<=.04045?value/12.92:((value+.055)/1.055)**2.4};return .2126*linear(r)+.7152*linear(g)+.0722*linear(b2)}function wcagContrast(first,second){let a=relativeLuminance(first),b2=relativeLuminance(second);return(Math.max(a,b2)+.05)/(Math.min(a,b2)+.05)}function terminalAppearance(background,foreground){let white={r:255,g:255,b:255},black={r:0,g:0,b:0},whiteContrast=wcagContrast(white,background),blackContrast=wcagContrast(black,background);if(foreground){let foregroundL=oklabLightness(foreground),backgroundL=oklabLightness(background);if(Math.abs(foregroundL-backgroundL)>.05){let appearance=foregroundL>backgroundL?"dark":"light";if((appearance==="dark"?whiteContrast:blackContrast)>=TEXT_MINIMUM_WCAG_CONTRAST)return appearance}}return whiteContrast>=blackContrast?"dark":"light"}var clamp2=(value,min,max)=>Math.min(max,Math.max(min,value));function hexOf({r,g,b:b2}){return`#${[r,g,b2].map(channel=>Math.round(channel).toString(16).padStart(2,"0")).join("")}`}function bellWeight(lightness){let gaussian=x2=>Math.exp(-((x2-.5)**2)/.125);return(gaussian(lightness)-gaussian(0))/(1-gaussian(0))}function saturationCurve({saturation:{min,max}},lightness){let floor=max>0?min/max:1;return floor+(1-floor)*bellWeight(lightness)}function levelTarget(level,appearance,surfaceL){let curve=LEVELS[level][appearance];if(!(surfaceL<curve.reachable[0]||surfaceL>curve.reachable[1]))return curve.coefficients.reduce((sum,coefficient,power)=>sum+coefficient*surfaceL**power,0)}function generateSystemThemeColors(input){let saturation=clamp2(input.saturation??1,0,1),{background,foreground}=input;if(!background)return indexedColors(saturation,input.appearanceHint);let palette=input.palette?.length===16?input.palette.map(sourceOf):void 0,appearance=terminalAppearance(background,foreground),lighter=appearance==="dark",extreme=lighter?1:0,backgroundL=oklabLightness(background),paint=(token,oklabL)=>{let lightness=oklabToOkhslLightness(oklabL),family=FAMILIES[TOKEN_FAMILIES[token]];if(!palette){let{min,max}=family.saturation;return okhslColor(family.hue,(min+(max-min)*bellWeight(lightness))*saturation,lightness)}return anchored(palette[TOKEN_SLOTS[token]??family.slot],family,lightness,saturation)},target=(level,surfaceL,t)=>{let reached=levelTarget(level,appearance,surfaceL);if(reached===void 0&&t===0)return;let distance=(reached??extreme)-surfaceL,floor=(levelTarget(READABLE_FLOOR[appearance],appearance,surfaceL)??extreme)-surfaceL,compressed=Math.abs(distance)>Math.abs(floor)?distance-(distance-floor)*Math.min(t,1):distance;return surfaceL+compressed*(1-Math.max(0,t-1))},extremeText=lighter?{r:255,g:255,b:255}:{r:0,g:0,b:0},readable=color=>wcagContrast(extremeText,color)>=TEXT_MINIMUM_WCAG_CONTRAST,limitPanel=(token,l3)=>{let color=paint(token,l3);if(readable(color))return color;let[low,high]=[backgroundL,l3];for(let index=0;index<20;index++){let middle=(low+high)/2;readable(paint(token,middle))?low=middle:high=middle}return paint(token,low)},solve=t=>{let colors2=new Map([["background",background]]);for(let token of SOLVE_ORDER){let targets=[];for(let rule of RULES)if(rule.token===token)for(let surface of rule.on){let value=target(rule.level,oklabLightness(colors2.get(surface)??background),t);if(value===void 0||value<0||value>1)return;targets.push(value)}let l3=lighter?Math.max(...targets):Math.min(...targets);colors2.set(token,PANELS.includes(token)?limitPanel(token,l3):paint(token,l3))}return colors2},relaxation=0,colors=solve(0);if(!colors){let[low,high]=[0,2];colors=solve(high);for(let index=0;index<20;index++){let middle=(low+high)/2,attempt=solve(middle);attempt?[high,colors]=[middle,attempt]:low=middle}relaxation=high}let solved=colors??new Map,surfacesOf=token=>RULES.filter(rule=>rule.token===token).flatMap(rule=>rule.on.map(surface=>solved.get(surface)??background)),result={};for(let token of Object.keys(TOKEN_FAMILIES)){let color=solved.get(token);result[token]=color?hexOf(color):""}for(let token of FOREGROUND_TOKENS){let surfaces=surfacesOf(token),text=solved.get(token);if(foreground){let targets=surfaces.map(surface=>target(FOREGROUND_LEVEL,oklabLightness(surface),relaxation));if(targets.every(value=>value!==void 0&&value>=0&&value<=1)){let needed=lighter?Math.max(...targets):Math.min(...targets),foregroundL=oklabLightness(foreground);if(lighter?foregroundL>=needed:foregroundL<=needed){result[token]="";continue}text=anchored(sourceOf(foreground),FAMILIES.neutral,oklabToOkhslLightness(needed),saturation)}}text&&(result[token]=hexOf(withTextContrast(text,surfaces,lighter)))}return{colors:result,dim:[],appearance}}function okhslOf({r,g,b:b2}){return colorToOkhsl(rgbColor(r,g,b2))}function sourceOf(color){return{...okhslOf(color),chroma:colorToOklch(rgbColor(color.r,color.g,color.b)).c}}function anchored(source,family,lightness,saturation){let anchor=saturationCurve(family,source.l),falloff=anchor>0?Math.min(1,saturationCurve(family,lightness)/anchor):1,color=okhslColor(source.h,source.s*falloff*saturation,lightness),cap=source.chroma*falloff*saturation,{l:l3,c:c2}=colorToOklch(color);return c2<=cap?color:colorToRgb(oklchColor(l3,cap,source.h))}function withTextContrast(color,surfaces,lighter){let meets=candidate=>surfaces.every(surface=>wcagContrast(candidate,surface)>=TEXT_MINIMUM_WCAG_CONTRAST);if(meets(color))return color;let{h,s,l:l3}=okhslOf(color),at2=lightness=>okhslColor(h,s,lightness),extreme=lighter?1:0;if(!meets(at2(extreme)))return at2(extreme);let[low,high]=[l3,extreme];for(let index=0;index<20;index++){let middle=(low+high)/2;meets(at2(middle))?high=middle:low=middle}return at2(high)}function indexedColors(saturation,appearance){let colors={},dim=[];for(let[token,familyName]of Object.entries(TOKEN_FAMILIES)){if(PANELS.includes(token)){colors[token]="";continue}let neutral=familyName==="neutral";colors[token]=!neutral&&saturation>0?TOKEN_SLOTS[token]??FAMILIES[familyName].slot:"",neutral&&!FOREGROUND_TOKENS.includes(token)&&dim.push(token)}return{colors,dim,appearance}}var themeJsonValidator;function setThemeJsonValidator(validator){themeJsonValidator=validator}function resolveVarRefs(value,vars,visited=new Set){if(typeof value=="number"||value===""||value.startsWith("#")||/^ok(lch|hsl)\(/i.test(value))return value;if(visited.has(value))throw new Error(`Circular variable reference detected: ${value}`);if(!(value in vars))throw new Error(`Variable reference not found: ${value}`);return visited.add(value),resolveVarRefs(vars[value],vars,visited)}function resolveThemeColors(colors,vars={}){let resolved={};for(let[key,value]of Object.entries(colors))resolved[key]=resolveVarRefs(value,vars);return resolved}function withThemeColorFallbacks(colors){return{...colors,scrollbarTrack:colors.scrollbarTrack??colors.muted,scrollbarThumb:colors.scrollbarThumb??colors.text,thinkingMax:colors.thinkingMax??colors.thinkingXhigh,searchMatchBg:colors.searchMatchBg??colors.selectedBg,searchMatchText:colors.searchMatchText??colors.text}}var terminalColors={},terminalColorsPending=!1,terminalColorScheme;function setTerminalColors(colors){terminalColors={...colors},terminalColorsPending=!1}function setTerminalColorScheme(scheme){terminalColorScheme=scheme}function markTerminalColorsPending(){terminalColorsPending=!0}var GUESSED_DEFAULT_COLORS={dark:{foreground:parseColor("#e5e5e7"),background:parseColor("#000000")},light:{foreground:parseColor("#000000"),background:parseColor("#ffffff")}};function averageLightness(colors){let fixed=colors.filter(color=>color.kind!=="indexed"||color.index>=16);if(fixed.length!==0)return fixed.reduce((sum,color)=>sum+colorToOklch(color).l,0)/fixed.length}function detectAppearance(foregrounds,backgrounds){let fg=averageLightness(foregrounds),bg=averageLightness(backgrounds);if(fg!==void 0&&bg!==void 0)return bg<fg?"dark":"light";if(bg!==void 0)return bg<.5?"dark":"light";if(fg!==void 0)return fg>.5?"dark":"light"}var Theme=class{name;sourcePath;sourceInfo;mode;fgAnsi=new Map;bgAnsi=new Map;concreteColors={};defaultForegroundTokens=[];defaultBackgroundTokens=[];dimTokens;ownAppearance;resolvedColors;constructor(fgColors,bgColors,mode,options={}){this.name=options.name,this.sourcePath=options.sourcePath,this.sourceInfo=options.sourceInfo,this.mode=mode,this.dimTokens=new Set(options.dim);let foregrounds={...fgColors,scrollbarTrack:fgColors.scrollbarTrack??fgColors.muted,scrollbarThumb:fgColors.scrollbarThumb??fgColors.text,thinkingMax:fgColors.thinkingMax??fgColors.thinkingXhigh,searchMatchText:fgColors.searchMatchText??fgColors.text},backgrounds={...bgColors,searchMatchBg:bgColors.searchMatchBg??bgColors.selectedBg},concreteForegrounds=[],concreteBackgrounds=[],addToken=(token,value,isBackground)=>{if(value==="")return(isBackground?this.defaultBackgroundTokens:this.defaultForegroundTokens).push(token),isBackground?"\x1B[49m":"\x1B[39m";let color=parseColor(value);return this.concreteColors[token]=color,(isBackground?concreteBackgrounds:concreteForegrounds).push(color),isBackground?backgroundAnsi(color,mode):foregroundAnsi(color,mode)};for(let[token,value]of Object.entries(foregrounds))this.fgAnsi.set(token,addToken(token,value,!1));for(let[token,value]of Object.entries(backgrounds))this.bgAnsi.set(token,addToken(token,value,!0));this.ownAppearance=options.appearance??detectAppearance(concreteForegrounds,concreteBackgrounds)}get appearance(){return this.ownAppearance??getTerminalTheme()}get colors(){let terminal=terminalColors;if(this.resolvedColors?.terminal!==terminal){let guess=GUESSED_DEFAULT_COLORS[this.appearance],toColor=(rgb,fallback)=>rgb?rgbColor(rgb.r,rgb.g,rgb.b):fallback,foreground=toColor(terminal.foreground,guess.foreground),background=toColor(terminal.background,guess.background),colors={...this.concreteColors};for(let token of this.defaultForegroundTokens)colors[token]=foreground;for(let token of this.defaultBackgroundTokens)colors[token]=background;for(let token of this.dimTokens){let color=colors[token];color&&(colors[token]=mixColors(color,background,.4))}this.resolvedColors={terminal,colors:Object.freeze(colors)}}return this.resolvedColors.colors}style(text,options){let{fg,bg}=options;return typeof fg=="string"&&this.dimTokens.has(fg)&&(options={...options,dim:!0}),styleTextWithAnsi(text,fg===void 0?void 0:typeof fg=="string"?this.tokenAnsi(this.fgAnsi,fg):foregroundAnsi(fg,this.mode),bg===void 0?void 0:typeof bg=="string"?this.tokenAnsi(this.bgAnsi,bg):backgroundAnsi(bg,this.mode),options)}fg(color,text){let ansi=this.tokenAnsi(this.fgAnsi,color);return this.dimTokens.has(color)?`${ansi}\x1B[2m${text}\x1B[22;39m`:`${ansi}${text}\x1B[39m`}bg(color,text){return`${this.tokenAnsi(this.bgAnsi,color)}${text}\x1B[49m`}tokenAnsi(ansi,token){let value=ansi.get(token);if(value===void 0)throw new Error(`Unknown theme color: ${token}`);return value}bold(text){return source_default.bold(text)}italic(text){return source_default.italic(text)}underline(text){return source_default.underline(text)}inverse(text){return source_default.inverse(text)}strikethrough(text){return source_default.strikethrough(text)}getFgAnsi(color){let ansi=this.tokenAnsi(this.fgAnsi,color);return this.dimTokens.has(color)?`${ansi}\x1B[2m`:ansi}getBgAnsi(color){return this.tokenAnsi(this.bgAnsi,color)}getColorMode(){return this.mode}getThinkingBorderColor(level){switch(level){case"off":return str=>this.fg("thinkingOff",str);case"minimal":return str=>this.fg("thinkingMinimal",str);case"low":return str=>this.fg("thinkingLow",str);case"medium":return str=>this.fg("thinkingMedium",str);case"high":return str=>this.fg("thinkingHigh",str);case"xhigh":return str=>this.fg("thinkingXhigh",str);case"max":return str=>this.fg("thinkingMax",str);default:return str=>this.fg("thinkingOff",str)}}getBashModeBorderColor(){return str=>this.fg("bashMode",str)}},BUILTIN_THEMES;function getBuiltinThemes(){if(!BUILTIN_THEMES){let themesDir=getThemesDir(),darkPath=path4.join(themesDir,"dark.json"),lightPath=path4.join(themesDir,"light.json");BUILTIN_THEMES={dark:JSON.parse(stripBom(fs3.readFileSync(darkPath,"utf-8"))),light:JSON.parse(stripBom(fs3.readFileSync(lightPath,"utf-8")))}}return BUILTIN_THEMES}function getAvailableThemes(){return getAvailableThemesWithPaths().map(({name})=>name)}function getAvailableThemesWithPaths(){let themesDir=getThemesDir(),result=[],seen=new Set,addTheme=themeInfo=>{seen.has(themeInfo.name)||(seen.add(themeInfo.name),result.push(themeInfo))};addTheme({name:SYSTEM_THEME_NAME,path:void 0});for(let name of Object.keys(getBuiltinThemes()))addTheme({name,path:path4.join(themesDir,`${name}.json`)});for(let themeInfo of getCustomThemeInfos())addTheme(themeInfo);for(let[name,theme2]of registeredThemes.entries())addTheme({name,path:theme2.sourcePath});return result.sort((a,b2)=>a.name===SYSTEM_THEME_NAME?-1:b2.name===SYSTEM_THEME_NAME?1:a.name.localeCompare(b2.name))}function getCustomThemeInfos(){let customThemesDir=getCustomThemesDir(),result=[];if(!fs3.existsSync(customThemesDir))return result;for(let file of fs3.readdirSync(customThemesDir)){if(!file.endsWith(".json"))continue;let themePath=path4.join(customThemesDir,file);try{let customTheme=loadThemeFromPath(themePath);customTheme.name&&result.push({name:customTheme.name,path:themePath})}catch{}}return result}function assertThemeNameIsValid(name){if(name.includes("/"))throw new Error(`Invalid theme name "${name}": theme names cannot contain "/" because it is reserved for automatic light/dark theme settings.`)}function parseThemeJson(label,json2){if(themeJsonValidator)return themeJsonValidator(label,json2);if(typeof json2!="object"||json2===null||!("colors"in json2))throw new Error(`Invalid theme "${label}": expected an object with a "colors" map.`);return json2}function parseThemeJsonContent(label,content){let json2;try{json2=JSON.parse(stripBom(content))}catch(error){throw new Error(`Failed to parse theme ${label}: ${error}`)}return parseThemeJson(label,json2)}function loadThemeJson(name){let builtinThemes=getBuiltinThemes();if(name in builtinThemes)return builtinThemes[name];let registeredTheme=registeredThemes.get(name);if(registeredTheme?.sourcePath){let content2=fs3.readFileSync(registeredTheme.sourcePath,"utf-8");return parseThemeJsonContent(registeredTheme.sourcePath,content2)}if(registeredTheme)throw new Error(`Theme "${name}" does not have a source path for export`);let customThemesDir=getCustomThemesDir(),themePath=path4.join(customThemesDir,`${name}.json`);if(!fs3.existsSync(themePath))throw new Error(`Theme not found: ${name}`);let content=fs3.readFileSync(themePath,"utf-8");return parseThemeJsonContent(name,content)}var BACKGROUND_TOKENS=new Set(["selectedBg","searchMatchBg","userMessageBg","customMessageBg","toolPendingBg","toolSuccessBg","toolErrorBg"]);function splitThemeColors(colors){let fgColors={},bgColors={};for(let[key,value]of Object.entries(colors))BACKGROUND_TOKENS.has(key)?bgColors[key]=value:fgColors[key]=value;return{fgColors,bgColors}}function createTheme(themeJson,mode,sourcePath){let colorMode=mode??getTerminalColorMode(),resolvedColors=resolveThemeColors(withThemeColorFallbacks(themeJson.colors),themeJson.vars),{fgColors,bgColors}=splitThemeColors(resolvedColors);return new Theme(fgColors,bgColors,colorMode,{name:themeJson.name,sourcePath,appearance:themeJson.appearance})}function createSystemTheme(mode){let generated=generateSystemThemeColors({...terminalColors,saturation:terminalColorsPending?0:1,appearanceHint:getTerminalTheme()}),{fgColors,bgColors}=splitThemeColors(generated.colors);return new Theme(fgColors,bgColors,mode??getTerminalColorMode(),{name:SYSTEM_THEME_NAME,appearance:generated.appearance,dim:generated.dim})}function loadThemeFromPath(themePath,mode){let content=fs3.readFileSync(themePath,"utf-8"),themeJson=parseThemeJsonContent(themePath,content);return createTheme(themeJson,mode,themePath)}function loadTheme(name,mode){if(name===SYSTEM_THEME_NAME)return createSystemTheme(mode);let registeredTheme=registeredThemes.get(name);if(registeredTheme)return registeredTheme;let themeJson=loadThemeJson(name);return createTheme(themeJson,mode)}function getThemeByName(name){try{return loadTheme(name)}catch{return}}function parseAutoThemeSetting(themeSetting){if(!themeSetting)return;let slashIndex=themeSetting.indexOf("/");if(slashIndex===-1||themeSetting.indexOf("/",slashIndex+1)!==-1)return;let lightTheme=themeSetting.slice(0,slashIndex).trim(),darkTheme=themeSetting.slice(slashIndex+1).trim();if(!(!lightTheme||!darkTheme))return{lightTheme,darkTheme}}function resolveThemeSetting(themeSetting,terminalTheme){let autoTheme=parseAutoThemeSetting(themeSetting);if(autoTheme)return terminalTheme==="light"?autoTheme.lightTheme:autoTheme.darkTheme;if(!themeSetting?.includes("/")&&typeof themeSetting=="string")return themeSetting}function detectColorFgBgTheme(env2=process.env){let bg=env2.COLORFGBG?.split(";").at(-1)?.trim();if(!bg||!/^\d{1,2}$/.test(bg))return;let index=Number(bg);if(!(index>15))return index<=6||index===8?"dark":"light"}function detectTerminalTheme(colors={},reportedScheme,env2=process.env){let{background,foreground}=colors;return background?terminalAppearance(background,foreground):reportedScheme??detectColorFgBgTheme(env2)??"dark"}function getTerminalTheme(){return detectTerminalTheme(terminalColors,terminalColorScheme)}var THEME_KEY=Symbol.for("@earendil-works/pi-coding-agent:theme"),THEME_KEY_OLD=Symbol.for("@mariozechner/pi-coding-agent:theme"),theme=new Proxy({},{get(_target,prop){let t=globalThis[THEME_KEY];if(!t)throw new Error("Theme not initialized. Call initTheme() first.");return t[prop]}});function setGlobalTheme(t){globalThis[THEME_KEY]=t,globalThis[THEME_KEY_OLD]=t}var currentThemeName,themeWatcher,themeReloadTimer,onThemeChangeCallback,registeredThemes=new Map;function setRegisteredThemes(themes){registeredThemes.clear();for(let theme2 of themes)theme2.name&&(assertThemeNameIsValid(theme2.name),registeredThemes.set(theme2.name,theme2))}function initTheme(themeName,enableWatcher=!1){let name=themeName??SYSTEM_THEME_NAME;currentThemeName=name;try{setGlobalTheme(loadTheme(name)),enableWatcher&&startThemeWatcher()}catch{currentThemeName=SYSTEM_THEME_NAME,setGlobalTheme(loadTheme(SYSTEM_THEME_NAME))}}function setTheme(name,enableWatcher=!1){currentThemeName=name;try{return setGlobalTheme(loadTheme(name)),enableWatcher&&startThemeWatcher(),onThemeChangeCallback&&onThemeChangeCallback(),{success:!0}}catch(error){return currentThemeName=SYSTEM_THEME_NAME,setGlobalTheme(loadTheme(SYSTEM_THEME_NAME)),{success:!1,error:error instanceof Error?error.message:String(error)}}}function setThemeInstance(themeInstance){setGlobalTheme(themeInstance),currentThemeName="<in-memory>",stopThemeWatcher(),onThemeChangeCallback&&onThemeChangeCallback()}function onThemeChange(callback){onThemeChangeCallback=callback}function startThemeWatcher(){if(stopThemeWatcher(),!currentThemeName||currentThemeName==="dark"||currentThemeName==="light"||currentThemeName===SYSTEM_THEME_NAME)return;let customThemesDir=getCustomThemesDir(),watchedThemeName=currentThemeName,watchedFileName=`${watchedThemeName}.json`,themeFile=path4.join(customThemesDir,watchedFileName);if(!fs3.existsSync(themeFile))return;let scheduleReload=()=>{themeReloadTimer&&clearTimeout(themeReloadTimer),themeReloadTimer=setTimeout(()=>{if(themeReloadTimer=void 0,currentThemeName===watchedThemeName&&fs3.existsSync(themeFile))try{let reloadedTheme=loadThemeFromPath(themeFile);registeredThemes.set(watchedThemeName,reloadedTheme),setGlobalTheme(reloadedTheme),onThemeChangeCallback&&onThemeChangeCallback()}catch{}},100)};themeWatcher=watchWithErrorHandler(customThemesDir,(_eventType,filename)=>{if(currentThemeName===watchedThemeName){if(!filename){scheduleReload();return}filename===watchedFileName&&scheduleReload()}},()=>{closeWatcher(themeWatcher),themeWatcher=void 0})??void 0}function stopThemeWatcher(){themeReloadTimer&&(clearTimeout(themeReloadTimer),themeReloadTimer=void 0),closeWatcher(themeWatcher),themeWatcher=void 0}function getResolvedThemeColors(themeName){let colors=loadTheme(themeName??currentThemeName??SYSTEM_THEME_NAME).colors;return Object.fromEntries(Object.entries(colors).map(([token,color])=>[token,colorToHex(color)]))}function getThemeExportColors(themeName){let name=themeName??currentThemeName??SYSTEM_THEME_NAME;if(name===SYSTEM_THEME_NAME)return{};try{let themeJson=loadThemeJson(name),exportSection=themeJson.export;if(!exportSection)return{};let vars=themeJson.vars??{},resolve2=value=>{if(value===void 0)return;let resolved=resolveVarRefs(value,vars);if(typeof resolved=="number")return colorToHex(indexedColor(resolved));if(resolved!=="")return/^okhsl\(/i.test(resolved)?colorToHex(parseColor(resolved)):resolved};return{pageBg:resolve2(exportSection.pageBg),cardBg:resolve2(exportSection.cardBg),infoBg:resolve2(exportSection.infoBg)}}catch{return{}}}var cachedHighlightThemeFor,cachedCliHighlightTheme;function buildCliHighlightTheme(t){return{keyword:s=>t.fg("syntaxKeyword",s),built_in:s=>t.fg("syntaxType",s),literal:s=>t.fg("syntaxNumber",s),number:s=>t.fg("syntaxNumber",s),regexp:s=>t.fg("syntaxString",s),string:s=>t.fg("syntaxString",s),subst:s=>t.fg("text",s),comment:s=>t.fg("syntaxComment",s),doctag:s=>t.fg("syntaxComment",s),meta:s=>t.fg("muted",s),function:s=>t.fg("syntaxFunction",s),title:s=>t.fg("syntaxFunction",s),class:s=>t.fg("syntaxType",s),type:s=>t.fg("syntaxType",s),tag:s=>t.fg("syntaxPunctuation",s),name:s=>t.fg("syntaxKeyword",s),attr:s=>t.fg("syntaxVariable",s),variable:s=>t.fg("syntaxVariable",s),params:s=>t.fg("syntaxVariable",s),operator:s=>t.fg("syntaxOperator",s),punctuation:s=>t.fg("syntaxPunctuation",s),emphasis:s=>t.italic(s),strong:s=>t.bold(s),link:s=>t.underline(s),addition:s=>t.fg("toolDiffAdded",s),deletion:s=>t.fg("toolDiffRemoved",s)}}function getCliHighlightTheme(t){return(cachedHighlightThemeFor!==t||!cachedCliHighlightTheme)&&(cachedHighlightThemeFor=t,cachedCliHighlightTheme=buildCliHighlightTheme(t)),cachedCliHighlightTheme}function highlightCode(code,lang){let validLang=lang&&supportsLanguage(lang)?lang:void 0;if(!validLang)return code.split(`
127
129
  `).map(line=>theme.fg("mdCodeBlock",line));let opts={language:validLang,ignoreIllegals:!0,theme:getCliHighlightTheme(theme)};try{return highlight(code,opts).split(`
128
130
  `)}catch{return code.split(`
129
131
  `)}}function getLanguageFromPath(filePath){let ext=filePath.split(".").pop()?.toLowerCase();return ext?{ts:"typescript",tsx:"typescript",js:"javascript",jsx:"javascript",mjs:"javascript",cjs:"javascript",py:"python",rb:"ruby",rs:"rust",go:"go",java:"java",kt:"kotlin",swift:"swift",c:"c",h:"c",cpp:"cpp",cc:"cpp",cxx:"cpp",hpp:"cpp",cs:"csharp",php:"php",sh:"bash",bash:"bash",zsh:"bash",fish:"fish",ps1:"powershell",sql:"sql",html:"html",htm:"html",css:"css",scss:"scss",sass:"sass",less:"less",json:"json",yaml:"yaml",yml:"yaml",toml:"toml",xml:"xml",md:"markdown",markdown:"markdown",dockerfile:"dockerfile",makefile:"makefile",cmake:"cmake",lua:"lua",perl:"perl",r:"r",scala:"scala",clj:"clojure",ex:"elixir",exs:"elixir",erl:"erlang",hs:"haskell",ml:"ocaml",vim:"vim",graphql:"graphql",proto:"protobuf",tf:"hcl",hcl:"hcl"}[ext]:void 0}function getMarkdownTheme(){return{heading:text=>theme.fg("mdHeading",text),link:text=>theme.fg("mdLink",text),linkUrl:text=>theme.fg("mdLinkUrl",text),code:text=>theme.fg("mdCode",text),codeBlock:text=>theme.fg("mdCodeBlock",text),codeBlockBorder:text=>theme.fg("mdCodeBlockBorder",text),quote:text=>theme.fg("mdQuote",text),quoteBorder:text=>theme.fg("mdQuoteBorder",text),hr:text=>theme.fg("mdHr",text),listBullet:text=>theme.fg("mdListBullet",text),bold:text=>theme.bold(text),italic:text=>theme.italic(text),underline:text=>theme.underline(text),strikethrough:text=>theme.strikethrough(text),highlightCode:(code,lang)=>{let validLang=lang&&supportsLanguage(lang)?lang:void 0;if(!validLang)return code.split(`