@code-yeongyu/senpi 2026.10.1-2 → 2026.10.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.
- package/CHANGELOG.md +1 -17
- package/dist/bundle/chunks/{app-server-command-P5OFBB4F.js → app-server-command-CZT5WSC4.js} +1 -1
- package/dist/bundle/chunks/chunk-45PHWY2H.js +9 -0
- package/dist/bundle/chunks/{chunk-U67UZN7N.js → chunk-JWHA752H.js} +137 -137
- package/dist/bundle/chunks/{chunk-LFPTNJFL.js → chunk-P4MKROXN.js} +1 -1
- package/dist/bundle/chunks/{chunk-GFJGG447.js → chunk-ZUQ36DFK.js} +1 -1
- package/dist/bundle/chunks/{cli-main-NG6YCUOL.js → cli-main-RCIUWYKL.js} +1 -1
- package/dist/bundle/chunks/{interactive-mode-MPZJRI3K.js → interactive-mode-M64RXEHC.js} +1 -1
- package/dist/bundle/chunks/{multi-session-host-EP53H7TX.js → multi-session-host-BPDPIBNN.js} +1 -1
- package/dist/bundle/chunks/{package-manager-cli-ZEWHBRS5.js → package-manager-cli-Y3GREN75.js} +1 -1
- package/dist/bundle/chunks/{rotation-stream-3JC676HE.js → rotation-stream-PH5JIQBD.js} +1 -1
- package/dist/bundle/chunks/{rpc-mode-EE3ZMJSB.js → rpc-mode-TB4O62O7.js} +1 -1
- package/dist/bundle/chunks/{schedule-command-GSAMNT2Y.js → schedule-command-IN6IJG2Y.js} +1 -1
- package/dist/bundle/chunks/session-worker.js +338 -346
- package/dist/bundle/cli.js +1 -1
- package/dist/bundle/index.js +1 -1
- package/dist/bundle/rpc-entry.js +1 -1
- package/dist/bundle/runtime-manifest.json +1 -1
- package/dist/core/extensions/builtin/anthropic-subscription/content-blocks.d.ts +0 -1
- package/dist/core/extensions/builtin/anthropic-subscription/content-blocks.js +0 -3
- package/dist/core/extensions/builtin/anthropic-subscription/prompt-bridge.js +3 -5
- package/dist/index.d.ts +0 -1
- package/dist/index.js +1 -2
- package/dist/utils/shell.js +2 -3
- package/package.json +6 -6
- package/dist/bundle/chunks/chunk-2SC5XIAI.js +0 -17
- package/dist/core/extensions/builtin/anthropic-subscription/cold-seed-images.d.ts +0 -30
- package/dist/core/extensions/builtin/anthropic-subscription/cold-seed-images.js +0 -133
- package/dist/utils/bundled-bun.d.ts +0 -16
- package/dist/utils/bundled-bun.js +0 -101
package/CHANGELOG.md
CHANGED
|
@@ -12,18 +12,6 @@
|
|
|
12
12
|
|
|
13
13
|
### Removed
|
|
14
14
|
|
|
15
|
-
## [2026.10.1-2] - 2026-10-01
|
|
16
|
-
|
|
17
|
-
### Breaking Changes
|
|
18
|
-
|
|
19
|
-
### Added
|
|
20
|
-
|
|
21
|
-
### Changed
|
|
22
|
-
|
|
23
|
-
### Fixed
|
|
24
|
-
|
|
25
|
-
### Removed
|
|
26
|
-
|
|
27
15
|
## [2026.10.1] - 2026-10-01
|
|
28
16
|
|
|
29
17
|
### Breaking Changes
|
|
@@ -116,10 +104,6 @@
|
|
|
116
104
|
|
|
117
105
|
### Fixed
|
|
118
106
|
|
|
119
|
-
- On the `anthropic-subscription` lane, re-sending the whole conversation (a cold seed or flatten) no longer presents images the agent read with a tool as new user attachments. Such an image stays attached to its tool result with a note that it is tool output, identical image bytes are sent once and later copies refer back to the first, at most 8 earlier images are replayed (your own uploads first, then the most recent), and missing or unreadable image data is dropped with a one-line note. Before, one uploaded screenshot read five times was re-sent as six images, the agent took them for new uploads and read them again, and the count kept growing with each cold seed. Thanks @willowite for the precise report and reproduction, and the community report that confirmed it. ([#2490](https://github.com/code-yeongyu/senpi/issues/2490))
|
|
120
|
-
|
|
121
|
-
- In a compiled build with no Bun on `PATH` (for example a desktop app started from Finder, or a standalone binary on a machine without Bun), `bun` and `bunx` from an eval cell, the bash tool and the terminal now run Bun itself. Before this fix, an eval cell's `bun test` started a second agent and returned its reply as a passing result with exit code 0, and the bash tool reported `bun: command not found`. A Bun you installed and put on `PATH` is still used first. ([omo#9362](https://github.com/code-yeongyu/oh-my-openagent/issues/9362))
|
|
122
|
-
|
|
123
107
|
- Manual `/compact` on the `anthropic-subscription` lane now replaces the resident Claude transcript with the compacted summary and retained suffix instead of forking the old uncompressed transcript, so the next request actually uses the smaller context. Thanks to @ayalcoh for the fix and @Tinycute00 for the report. ([#2331](https://github.com/code-yeongyu/senpi/issues/2331))
|
|
124
108
|
|
|
125
109
|
- An updated client can retire a shared host left running by an older release. While such a host was alive, every `host ensure` in the agent directory (including each desktop thread's own endpoint) was refused with `legacy_host`, and `host stop --drain` answered `unknown_owner`, so nothing short of killing the process by hand freed the machine. Now `host stop --drain` drains it when its old record still proves the process, and an ensure drains and replaces it on its own once it holds no session. With a session open the refusal says which process it is, which socket it serves, and the `host stop --drain --socket <socket>` that retires it. ([#2423](https://github.com/code-yeongyu/senpi/issues/2423))
|
|
@@ -142,7 +126,7 @@
|
|
|
142
126
|
- A fallback-chain entry whose provider answered one 429 with a very long `Retry-After` (a weekly window, or an API gateway replaying a stale wait of almost a day) is checked again after `fallback.circuitMaxCooldownMs` (30 minutes by default) instead of being skipped by every session until the whole hint elapsed. The circuit breaker now bounds the provider's wait by that ceiling like its own cooldown: once it passes, one half-open probe goes to the entry, a response closes the circuit, and another rate limit re-opens it with the fresh hint. Hints up to the ceiling are honored as before. ([#2446](https://github.com/code-yeongyu/senpi/issues/2446))
|
|
143
127
|
|
|
144
128
|
- Fixed inherited new sessions being lost when the process exits before the first assistant response. The session file is now created when the first user message is sent ([#10000](https://github.com/earendil-works/pi/issues/10000)).
|
|
145
|
-
- When an extension command starts a deferred turn, `--print` now waits before choosing the final answer and exit status, rather than finishing with empty or stale output.
|
|
129
|
+
- When an extension command starts a deferred turn, `--print` now waits before choosing the final answer and exit status, rather than finishing with empty or stale output. ([#2436](https://github.com/code-yeongyu/senpi/pull/2436))
|
|
146
130
|
|
|
147
131
|
- Fixed inherited split-turn compaction summaries being refused by Claude Fable 5.1, mid-run threshold compaction silently skipping oversized trailing tool results ([#9740](https://github.com/earendil-works/pi/issues/9740)), and cancellation races that could start automatic compaction, leave stale retry state or miss cancellation during summarization auth ([#9340](https://github.com/earendil-works/pi/issues/9340), [#9777](https://github.com/earendil-works/pi/issues/9777)) ([#9908](https://github.com/earendil-works/pi/pull/9908) by [@davidbrai](https://github.com/davidbrai)).
|
|
148
132
|
|
package/dist/bundle/chunks/{app-server-command-P5OFBB4F.js → app-server-command-CZT5WSC4.js}
RENAMED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createRequire as __piCreateRequire } from "node:module"; const require = __piCreateRequire(import.meta.url); { const __piWorkerThreads = require("node:worker_threads"); if (typeof __piWorkerThreads.markAsUncloneable !== "function") { __piWorkerThreads.markAsUncloneable = () => {}; } }
|
|
2
|
-
import{import_websocket_server,wrapper_default}from"./chunk-YBZDAABT.js";import{AuthStorage,DefaultResourceLoader,GOAL_STORE_CHANGED_EVENT,ModelRegistry,SessionManager,clearGoal,createAgentSession,createGoal,createPendingQuestion,defaultModelPerProvider,formatProviderNativeBody,formatProviderNativeSummary,getMcpService,goalStoreRef,loadEntriesFromFile,loadMcpConfig,loadSkills,readGoal,resolveAuthMode,updateGoal}from"./chunk-
|
|
2
|
+
import{import_websocket_server,wrapper_default}from"./chunk-YBZDAABT.js";import{AuthStorage,DefaultResourceLoader,GOAL_STORE_CHANGED_EVENT,ModelRegistry,SessionManager,clearGoal,createAgentSession,createGoal,createPendingQuestion,defaultModelPerProvider,formatProviderNativeBody,formatProviderNativeSummary,getMcpService,goalStoreRef,loadEntriesFromFile,loadMcpConfig,loadSkills,readGoal,resolveAuthMode,updateGoal}from"./chunk-JWHA752H.js";import{RPC_ERROR_UNKNOWN_COMMAND,UNKNOWN_COMMAND_CONFIRM_HINT,UnknownCommandError,getCredentialAccounts,getModels,getProviders,getSupportedThinkingLevels,pinCredentialAccount,removeCredentialAccount,subscribeProviderAccountEvents}from"./chunk-ZUQ36DFK.js";import"./chunk-DP63ZKKF.js";import{require_ignore}from"./chunk-FTBU746H.js";import{SettingsManager,getAvailableThemesWithPaths,getThemeByName,takeOverStdout,theme,waitForRawStdoutBackpressure,writeRawStdout}from"./chunk-KNB5PWS6.js";import"./chunk-YZJ53A7A.js";import"./chunk-G6YNJ3G7.js";import{x}from"./chunk-GCEEMWGS.js";import"./chunk-WIAXG52U.js";import"./chunk-U5KVIAHJ.js";import"./chunk-6Q3PLTKP.js";import"./chunk-JABBHOD5.js";import"./chunk-BP7SYEAO.js";import"./chunk-DN6WCOIS.js";import{acquireOwnershipSafeLock}from"./chunk-5GSU6FQI.js";import"./chunk-UJQHD3KS.js";import"./chunk-H4QOEVS5.js";import"./chunk-P4MKROXN.js";import"./chunk-JMS6KHT7.js";import"./chunk-45PHWY2H.js";import"./chunk-HP2P2623.js";import"./chunk-KUPQO7MC.js";import"./chunk-7X72IACK.js";import"./chunk-YU2P3CAR.js";import"./chunk-BMX2U22F.js";import"./chunk-MHEC3URX.js";import"./chunk-CIRZTP7W.js";import{parseDaemonPidFile,processMatchesPidFile,readProcessStartTime,stopValidatedPid,waitForGone,waitForStartTime}from"./chunk-DLCG63OQ.js";import{attachJsonlLineReader}from"./chunk-GXACYECD.js";import"./chunk-HB35RBP4.js";import"./chunk-XOLCOWF6.js";import"./chunk-QUHRFKGY.js";import"./chunk-3SROZFB6.js";import"./chunk-26UBFF6N.js";import"./chunk-H6XRTLAJ.js";import"./chunk-GZVCRV7I.js";import"./chunk-U3VOXCGP.js";import"./chunk-RFB5CBW7.js";import"./chunk-2VZJTDUX.js";import"./chunk-RUYXD3CX.js";import"./chunk-LX75SBFN.js";import"./chunk-ZOFZRJSL.js";import"./chunk-2SOVDETB.js";import{APP_NAME,CONFIG_DIR_NAME,ENV_SESSION_DIR,VERSION,getAgentDir,getSessionsDir,isLocalPath,resolvePath}from"./chunk-JCTWDSQT.js";import"./chunk-ATQFN5HI.js";import"./chunk-RBCQOIAD.js";import"./chunk-JRGNL6WM.js";import"./chunk-X4Q5YSTE.js";import"./chunk-CWLCGRUS.js";import"./chunk-6WCOSBI7.js";import"./chunk-LHYG7TK7.js";import"./chunk-KRNXUTZJ.js";import"./chunk-YOPVJDSU.js";import"./chunk-WHPDEDCC.js";import"./chunk-HK46JMSC.js";import"./chunk-4VVYXOOM.js";import"./chunk-WDTJ6JKE.js";import"./chunk-5ROMKDLK.js";import"./chunk-3W47LTXQ.js";import"./chunk-45SZOLCU.js";import"./chunk-BBK6SSYT.js";import"./chunk-BPX6QWPD.js";import{normalizeProviderId}from"./chunk-GR32NG6W.js";import"./chunk-DMI55M2N.js";import"./chunk-PJ34QVL5.js";import{__toESM}from"./chunk-IKOFCODM.js";import{isIP}from"node:net";var APP_SERVER_LISTEN_USAGE="Invalid --listen value. Use stdio://, unix://, unix:///abs/path, or ws://IP:PORT.";function formatAppServerUsage(){let listenForms="stdio://|unix://|unix:///abs/path|ws://IP:PORT";return[`Usage: ${APP_NAME} app-server [--listen <${listenForms}>] [--ws-auth <token-file|off>] [--json-logs] [--extension <path>]...`,` ${APP_NAME} app-server daemon <start|stop|status|restart> [--listen <${listenForms}>] [--extension <path>]...`].join(`
|
|
3
3
|
`)}function parseListen(value){if(value==="stdio://")return{kind:"stdio",url:"stdio://"};if(value==="unix://")return{kind:"unix",url:"unix://"};if(value.startsWith("unix:///")){let path=value.slice(7);return path.startsWith("/")?{kind:"unix",url:value,path}:void 0}if(!value.startsWith("ws://"))return;let parsed;try{parsed=new URL(value)}catch(error){if(error instanceof TypeError)return;throw error}let port=Number(parsed.port);if(!(parsed.protocol!=="ws:"||parsed.username!==""||parsed.password!==""||parsed.pathname!=="/"||parsed.search!==""||parsed.hash!==""||parsed.port===""||!Number.isInteger(port)||port<1||port>65535||isIP(parsed.hostname)===0))return{kind:"ws",url:value,host:parsed.hostname,port}}function parseDaemonVerb(value){switch(value){case"start":case"stop":case"status":case"restart":return value;default:return}}function parseWsAuth(value){return value==="off"?{kind:"off"}:{kind:"token-file",path:value}}var EXTENSION_USAGE="--extension requires <path>.";function parseServerArgs(args){let listen3={kind:"stdio",url:"stdio://"},wsAuth,jsonLogs=!1,extensions=[];for(let index=0;index<args.length;index++){let arg=args[index];if(arg==="--extension"){let value=args[index+1];if(value===void 0)return{kind:"usage-error",message:EXTENSION_USAGE};extensions.push(value),index++;continue}if(arg==="--listen"){let value=args[index+1];if(value===void 0)return{kind:"usage-error",message:APP_SERVER_LISTEN_USAGE};let parsed=parseListen(value);if(parsed===void 0)return{kind:"usage-error",message:APP_SERVER_LISTEN_USAGE};listen3=parsed,index++;continue}if(arg==="--ws-auth"){let value=args[index+1];if(value===void 0)return{kind:"usage-error",message:"--ws-auth requires <token-file|off>."};wsAuth=parseWsAuth(value),index++;continue}if(arg==="--json-logs"){jsonLogs=!0;continue}return{kind:"usage-error",message:`Unexpected app-server argument: ${arg}`}}return{kind:"server",listen:listen3,wsAuth,jsonLogs,extensions}}function parseDaemonArgs(args){let verb=parseDaemonVerb(args[0]);if(verb===void 0)return{kind:"usage-error",message:"Usage: app-server daemon <start|stop|status|restart>."};let listen3={kind:"ws",url:"ws://127.0.0.1:18800",host:"127.0.0.1",port:18800},extensions=[];for(let index=1;index<args.length;index++){let arg=args[index];if(arg==="--extension"){let value=args[index+1];if(value===void 0)return{kind:"usage-error",message:EXTENSION_USAGE};extensions.push(value),index++;continue}if(arg==="--listen"){let value=args[index+1];if(value===void 0)return{kind:"usage-error",message:APP_SERVER_LISTEN_USAGE};let parsed=parseListen(value);if(parsed===void 0)return{kind:"usage-error",message:APP_SERVER_LISTEN_USAGE};listen3=parsed,index++;continue}return{kind:"usage-error",message:`Unexpected app-server daemon argument: ${arg}`}}return{kind:"daemon",verb,listen:listen3,extensions}}function parseAppServerCliArgs(args){return args[0]==="daemon"?parseDaemonArgs(args.slice(1)):parseServerArgs(args)}function resolveAppServerExtensionPaths(extensions,cwd=process.cwd()){return extensions.map(value=>isLocalPath(value)?resolvePath(value,cwd):value)}var RpcHandlerError=class extends Error{constructor(error){super(error.message),this.name="RpcHandlerError",this.rpcError=error}};function invalidRequestError(){return{code:-32600,message:"Invalid request"}}function methodNotFoundError(method){return{code:-32601,message:`Method not found: ${method}`}}function invalidParamsError(){return{code:-32602,message:"Invalid params"}}function internalError(message="Internal error"){return{code:-32603,message}}function notInitializedError(){return{code:-32600,message:"Not initialized"}}function alreadyInitializedError(){return{code:-32600,message:"Already initialized"}}function experimentalCapabilityError(method){return{code:-32600,message:`${method} requires experimentalApi capability`}}function registerExtensionRequestMethod(registry,getThread){registry.register("extension_request",{scope:"thread",handler:async({request})=>{let params=request.params;if(typeof params!="object"||params===null||Array.isArray(params))throw new RpcHandlerError({code:-32602,message:"Invalid params"});let threadId=Reflect.get(params,"threadId"),name=Reflect.get(params,"name");if(typeof threadId!="string"||threadId.length===0||typeof name!="string"||name.length===0)throw new RpcHandlerError({code:-32602,message:"Invalid params"});try{return await getThread(threadId).extensionRunner.requestRpc(name,Reflect.get(params,"data"))}catch(error){throw new RpcHandlerError(internalError(error instanceof Error?error.message:String(error)))}}})}function createRegistry(){return new InMemoryMethodRegistry}var InMemoryMethodRegistry=class{constructor(){this.methods=new Map}register(method,registration){this.methods.set(method,registration)}async dispatch(connection,request){if(!connection.initialized){let registration2=this.methods.get(request.method);if(request.method!=="initialize"||registration2?.requiresInit!==!1)return{id:request.id,error:notInitializedError()}}if(connection.initialized&&request.method==="initialize")return{id:request.id,error:alreadyInitializedError()};let registration=this.methods.get(request.method);if(!registration)return{id:request.id,error:methodNotFoundError(request.method)};if(registration.experimental===!0&&connection.capabilities?.experimentalApi!==!0)return{id:request.id,error:experimentalCapabilityError(request.method)};try{let result=await registration.handler({connection,request});return{id:request.id,result}}catch(error){return error instanceof RpcHandlerError?{id:request.id,error:error.rpcError}:{id:request.id,error:internalError(error instanceof Error?error.message:String(error))}}}};function registerFuzzyFileSearchMethods(registry,service){registry.register("fuzzyFileSearch",{scope:"global",handler:({request})=>service.search(parseOneShotParams(request.params))}),registry.register("fuzzyFileSearch/sessionStart",{experimental:!0,scope:"global",handler:({request})=>service.startSession(parseSessionStartParams(request.params))}),registry.register("fuzzyFileSearch/sessionUpdate",{experimental:!0,scope:"global",handler:({request})=>service.updateSession(parseSessionUpdateParams(request.params))}),registry.register("fuzzyFileSearch/sessionStop",{experimental:!0,scope:"global",handler:({request})=>service.stopSession(parseSessionStopParams(request.params))})}function parseOneShotParams(value){let params=objectParams(value,"fuzzyFileSearch");return{query:requiredString(params.query,"fuzzyFileSearch query"),roots:requiredStringArray(params.roots,"fuzzyFileSearch roots"),cancellationToken:optionalString(params.cancellationToken,"fuzzyFileSearch cancellationToken")}}function parseSessionStartParams(value){let params=objectParams(value,"fuzzyFileSearch/sessionStart");return{sessionId:requiredString(params.sessionId,"fuzzyFileSearch/sessionStart sessionId"),roots:requiredStringArray(params.roots,"fuzzyFileSearch/sessionStart roots")}}function parseSessionUpdateParams(value){let params=objectParams(value,"fuzzyFileSearch/sessionUpdate");return{sessionId:requiredString(params.sessionId,"fuzzyFileSearch/sessionUpdate sessionId"),query:requiredString(params.query,"fuzzyFileSearch/sessionUpdate query")}}function parseSessionStopParams(value){let params=objectParams(value,"fuzzyFileSearch/sessionStop");return{sessionId:requiredString(params.sessionId,"fuzzyFileSearch/sessionStop sessionId")}}function objectParams(value,method){if(!isRecord(value))throw invalidRequest(`${method} params must be an object`);return value}function requiredString(value,field){if(typeof value!="string")throw invalidRequest(`${field} must be a string`);return value}function requiredStringArray(value,field){if(!Array.isArray(value)||value.some(entry=>typeof entry!="string"))throw invalidRequest(`${field} must be an array of strings`);return value}function optionalString(value,field){if(value==null)return null;if(typeof value!="string")throw invalidRequest(`${field} must be a string or null`);return value}function invalidRequest(message){return new RpcHandlerError({code:-32600,message})}function isRecord(value){return typeof value=="object"&&value!==null&&!Array.isArray(value)}import{lstat,readdir}from"node:fs/promises";import{basename,join as join2,relative as relative2,resolve,sep as sep2}from"node:path";var import_ignore=__toESM(require_ignore(),1);import{readFile}from"node:fs/promises";import{join,relative,sep}from"node:path";async function addGitignoreScope(matchers,directory){let gitignore=await readableText(join(directory,".gitignore"));return gitignore===void 0?matchers:[...matchers,{directory,matcher:(0,import_ignore.default)().add(gitignore)}]}function isIgnored(matchers,path,isDirectory){let ignored=!1;for(let scope of matchers){let relativePath=relative(scope.directory,path).split(sep).join("/"),result=scope.matcher.test(isDirectory?`${relativePath}/`:relativePath);result.ignored&&(ignored=!0),result.unignored&&(ignored=!1)}return ignored}async function readableText(path){try{return await readFile(path,"utf8")}catch(error){if(error instanceof Error)return;throw error}}var FUZZY_SEARCH_MAX_DEPTH=12,FUZZY_SEARCH_MAX_VISITED_ENTRIES=5e4,FUZZY_SEARCH_RESULT_LIMIT=50,FILENAME_MATCH_BONUS=1e6,CHARACTER_MATCH_SCORE=10,CONTIGUOUS_MATCH_BONUS=20,BOUNDARY_MATCH_BONUS=5,CANCELLATION_YIELD_INTERVAL=256;async function collectFuzzyFileEntries(roots,options={}){let entries=[],state={visitedEntries:0,stopped:!1},maxDepth=options.maxDepth??FUZZY_SEARCH_MAX_DEPTH,maxVisitedEntries=options.maxVisitedEntries??FUZZY_SEARCH_MAX_VISITED_ENTRIES;for(let root of roots){if(options.signal?.aborted||state.stopped)break;let absoluteRoot=resolve(root),rootStat=await readableStat(absoluteRoot);!rootStat?.isDirectory()||rootStat.isSymbolicLink()||await walkDirectory({wireRoot:root,absoluteRoot,absoluteDirectory:absoluteRoot,depth:0,matchers:[],entries,state,signal:options.signal,maxDepth,maxVisitedEntries})}return entries}function rankFuzzyFileEntries(query,entries){if(query.length===0)return[];let results=[];for(let entry of entries){let filenameMatch=scoreSubsequence(entry.fileName,query),pathMatch=filenameMatch??scoreSubsequence(entry.path,query);if(!pathMatch)continue;let filenameOffset=Array.from(entry.path).length-Array.from(entry.fileName).length,indices=filenameMatch?filenameMatch.indices.map(index=>index+filenameOffset):pathMatch.indices;results.push({root:entry.root,path:entry.path,match_type:entry.matchType,file_name:entry.fileName,score:pathMatch.score+(filenameMatch?FILENAME_MATCH_BONUS:0),indices})}return results.sort(compareResults),results.slice(0,FUZZY_SEARCH_RESULT_LIMIT)}async function walkDirectory(input){let matchers=await addGitignoreScope(input.matchers,input.absoluteDirectory),directoryEntries=await readableDirectory(input.absoluteDirectory);directoryEntries.sort((left,right)=>compareText(left.name,right.name));for(let directoryEntry of directoryEntries){if(input.signal?.aborted||input.state.stopped)return;if(input.state.visitedEntries>=input.maxVisitedEntries){input.state.stopped=!0;return}if(input.state.visitedEntries+=1,directoryEntry.name===".git"||directoryEntry.name==="node_modules"||directoryEntry.isSymbolicLink())continue;let isDirectory=directoryEntry.isDirectory();if(!isDirectory&&!directoryEntry.isFile())continue;let absolutePath=join2(input.absoluteDirectory,directoryEntry.name),relativePath=toPosixPath(relative2(input.absoluteRoot,absolutePath));if(isIgnored(matchers,absolutePath,isDirectory))continue;input.entries.push({root:input.wireRoot,path:relativePath,matchType:isDirectory?"directory":"file",fileName:basename(relativePath)});let entryDepth=input.depth+1;isDirectory&&entryDepth<input.maxDepth&&await walkDirectory({...input,absoluteDirectory:absolutePath,depth:entryDepth,matchers}),input.state.visitedEntries%CANCELLATION_YIELD_INTERVAL===0&&await yieldToEventLoop()}}function scoreSubsequence(candidate,query){let normalizedCandidate=normalizeText(candidate),normalizedQuery=query.toLowerCase(),contiguousStart=normalizedCandidate.value.indexOf(normalizedQuery),normalizedIndices=[];if(contiguousStart>=0){let cursor=contiguousStart;for(let character of normalizedQuery)normalizedIndices.push(cursor),cursor+=character.length}else{let cursor=0;for(let character of normalizedQuery){let matchIndex=normalizedCandidate.value.indexOf(character,cursor);if(matchIndex<0)return;normalizedIndices.push(matchIndex),cursor=matchIndex+character.length}}let indices=[];for(let normalizedIndex of normalizedIndices){let sourceIndex=normalizedCandidate.sourceIndices[normalizedIndex];if(sourceIndex===void 0)return;indices.at(-1)!==sourceIndex&&indices.push(sourceIndex)}let candidateCharacters=Array.from(candidate),score=indices.length*CHARACTER_MATCH_SCORE;for(let index=0;index<indices.length;index++){let current=indices[index];if(current===void 0)continue;let previous=indices[index-1];previous!==void 0&¤t===previous+1&&(score+=CONTIGUOUS_MATCH_BONUS),(current===0||isBoundary(candidateCharacters[current-1]))&&(score+=BOUNDARY_MATCH_BONUS)}return{score,indices}}function normalizeText(value){let sourceIndices=[];for(let[sourceIndex,character]of Array.from(value).entries())for(let index=0;index<character.toLowerCase().length;index++)sourceIndices.push(sourceIndex);return{value:value.toLowerCase(),sourceIndices}}function compareResults(left,right){return left.score!==right.score?right.score-left.score:compareText(left.path,right.path)}function compareText(left,right){return left<right?-1:left>right?1:0}function isBoundary(character){return character==="/"||character==="-"||character==="_"||character==="."||character===" "}async function readableDirectory(path){try{return await readdir(path,{withFileTypes:!0})}catch(error){if(error instanceof Error)return[];throw error}}async function readableStat(path){try{return await lstat(path)}catch(error){if(error instanceof Error)return;throw error}}function toPosixPath(path){return path.split(sep2).join("/")}function yieldToEventLoop(){return new Promise(resolve4=>setImmediate(resolve4))}var FuzzyFileSearchService=class{constructor(options){this.activeSearches=new Set,this.pendingSearches=new Map,this.sessions=new Map,this.disposed=!1,this.broadcast=options.broadcast,this.collectEntries=options.collectEntries??((roots,signal)=>collectFuzzyFileEntries(roots,{signal})),this.rankEntries=options.rankEntries??rankFuzzyFileEntries}async search(params){if(this.disposed)return{files:[]};let controller=new AbortController;this.activeSearches.add(controller);let token=params.cancellationToken;token!==null&&(this.pendingSearches.get(token)?.abort(),this.pendingSearches.set(token,controller));try{if(params.query.length===0)return{files:[]};let entries=await this.collectEntries(params.roots,controller.signal);return controller.signal.aborted||this.disposed?{files:[]}:{files:this.rankEntries(params.query,entries)}}finally{this.activeSearches.delete(controller),token!==null&&this.pendingSearches.get(token)===controller&&this.pendingSearches.delete(token)}}startSession(params){if(params.sessionId.length===0)throw invalidRequest2("sessionId must not be empty");this.cancelSession(params.sessionId);let session={id:params.sessionId,roots:params.roots,controller:new AbortController,query:"",version:0,entries:void 0,active:!this.disposed,completedVersion:void 0};return this.sessions.set(session.id,session),this.runTraversal(session),{}}updateSession(params){let session=this.sessions.get(params.sessionId);if(!session?.active)throw invalidRequest2(`fuzzy file search session not found: ${params.sessionId}`);return session.query=params.query,session.version+=1,session.entries!==void 0&&this.emitVersion(session,session.version),{}}stopSession(params){return this.cancelSession(params.sessionId),{}}dispose(){if(!this.disposed){this.disposed=!0;for(let controller of this.activeSearches)controller.abort();this.activeSearches.clear(),this.pendingSearches.clear();for(let session of this.sessions.values())this.deactivate(session);this.sessions.clear()}}async runTraversal(session){let entries;try{entries=await this.collectEntries(session.roots,session.controller.signal)}catch(error){if(!(error instanceof Error))throw error;entries=[]}if(this.isLive(session))for(session.entries=entries;this.isLive(session);){let version=session.version;if(await this.emitVersion(session,version))break}}async emitVersion(session,version){if(await Promise.resolve(),!this.isLive(session)||session.version!==version||session.entries===void 0)return!1;if(session.completedVersion===version)return!0;let query=session.query,files=query.length===0?[]:this.rankEntries(query,session.entries);return!this.isLive(session)||session.version!==version||(this.broadcast({method:"fuzzyFileSearch/sessionUpdated",params:{sessionId:session.id,query,files}}),!this.isLive(session)||session.version!==version)?!1:(session.completedVersion=version,this.broadcast({method:"fuzzyFileSearch/sessionCompleted",params:{sessionId:session.id}}),!0)}cancelSession(sessionId){let session=this.sessions.get(sessionId);session&&(this.deactivate(session),this.sessions.get(sessionId)===session&&this.sessions.delete(sessionId))}deactivate(session){session.active=!1,session.controller.abort()}isLive(session){return!this.disposed&&session.active&&this.sessions.get(session.id)===session}};function invalidRequest2(message){return new RpcHandlerError({code:-32600,message})}var APPROVAL_DECISIONS=["accept","acceptForSession","decline","cancel"],PERMISSION_OPTIONS=["Allow once","Allow always","Deny","Deny with feedback"],CANCEL_REASON="approval request was cancelled because the turn ended",NO_SUBSCRIBER_REASON="no client connected to approve";var ApprovalBridge=class{constructor(sendToThreadSubscribers){this.nextServerRequestId=0,this.pending=new Map,this.sessionAllows=new Set,this.sendToThreadSubscribers=sendToThreadSubscribers}get pendingCount(){return this.pending.size}requestApproval(threadId,kind,payload){let allowKey=createAllowKey(threadId,kind,payload);if(allowKey&&this.sessionAllows.has(allowKey))return Promise.resolve({allow:!0,decision:"acceptForSession"});let requestId=this.nextServerRequestId;this.nextServerRequestId+=1;let request=buildApprovalRequest(threadId,requestId,kind,payload);return new Promise(resolve4=>{this.pending.set(requestId,{threadId,request,allowKey,resolve:resolve4}),!(this.sendToThreadSubscribers(threadId,request)>0)&&(this.pending.delete(requestId),resolve4({allow:!1,decision:"decline",reason:NO_SUBSCRIBER_REASON}))})}resolveResponse(response){let pending=this.pending.get(response.id);if(!pending)return!1;let decision=readDecision(response);return this.pending.delete(response.id),decision==="acceptForSession"&&pending.allowKey&&this.sessionAllows.add(pending.allowKey),this.emitResolved(pending.threadId,response.id),pending.resolve(decisionToOutcome(decision,readReason(response))),!0}replayPendingForThread(threadId){let replayed=0;for(let pending of this.pending.values())pending.threadId===threadId&&(this.sendToThreadSubscribers(threadId,pending.request),replayed+=1);return replayed}cancelPendingForThread(threadId){let cancelled=0;for(let[requestId,pending]of Array.from(this.pending.entries()))pending.threadId===threadId&&(this.pending.delete(requestId),this.emitResolved(threadId,requestId),pending.resolve({allow:!1,decision:"cancel",reason:CANCEL_REASON}),cancelled+=1);return cancelled}emitResolved(threadId,requestId){this.sendToThreadSubscribers(threadId,{method:"serverRequest/resolved",params:{threadId,requestId}})}};function buildApprovalRequest(threadId,requestId,kind,payload){let base={threadId,turnId:payload.turnId??"turn-approval",itemId:payload.itemId??(kind==="commandExecution"?"approval-command":"approval-file-change"),startedAtMs:Date.now()};return kind==="fileChange"?{id:requestId,method:"item/fileChange/requestApproval",params:{...base,reason:payload.reason??null,grantRoot:payload.grantRoot??null}}:{id:requestId,method:"item/commandExecution/requestApproval",params:{...base,approvalId:payload.approvalId??null,environmentId:payload.environmentId??null,reason:payload.reason??null,command:payload.command??null,cwd:payload.cwd??null,availableDecisions:[...APPROVAL_DECISIONS]}}}function decisionToOutcome(decision,reason){return decision==="accept"||decision==="acceptForSession"?{allow:!0,decision}:reason?{allow:!1,decision,reason}:{allow:!1,decision}}function readDecision(response){let decision=isRecord2(response.result)?response.result.decision:void 0;return isApprovalDecision(decision)?decision:"cancel"}function readReason(response){let resultReason=isRecord2(response.result)?response.result.reason??response.result.message:void 0,errorReason=isRecord2(response.error)?response.error.message:void 0,reason=typeof resultReason=="string"?resultReason:errorReason;return typeof reason=="string"&&reason.length>0?reason:void 0}function createAllowKey(threadId,kind,payload){if(!(!payload.toolName||typeof payload.command!="string"))return`${threadId}\0${kind}\0${payload.toolName}\0${payload.command}`}function isApprovalDecision(value){return value==="accept"||value==="acceptForSession"||value==="decline"||value==="cancel"}function isRecord2(value){return typeof value=="object"&&value!==null&&!Array.isArray(value)}function createAppServerUIContext(bridge,threadId,userInput,getTurnId=()=>"turn-user-input"){let pendingInput,editorText="",editorFactory,toolsExpanded=!1;return{question(request,opts){return userInput?.requestUserInput(threadId,getTurnId(),request.requestId,request,opts)??Promise.resolve({status:"unavailable",answers:{},unanswered:request.questions.map(question=>question.id)})},async select(title,options){let prompt=parsePermissionPrompt(title);if(!prompt||!isPermissionOptions(options))return;let outcome=await bridge.requestApproval(threadId,prompt.kind,{turnId:"turn-approval",itemId:`approval-${prompt.toolName}`,toolName:prompt.toolName,command:prompt.command,reason:prompt.reason});return outcome.decision==="accept"?"Allow once":outcome.decision==="acceptForSession"?"Allow always":outcome.reason&&outcome.reason!==NO_SUBSCRIBER_REASON&&outcome.reason!==CANCEL_REASON?(pendingInput=outcome.reason,"Deny with feedback"):"Deny"},async confirm(title,message){return(await bridge.requestApproval(threadId,"commandExecution",{turnId:"turn-approval",itemId:"approval-confirm",toolName:"confirm",command:title,reason:message})).allow},async input(){let value=pendingInput;return pendingInput=void 0,value},notify(){},onTerminalInput(){return()=>{}},setStatus(){},setWorkingMessage(){},setWorkingVisible(){},setWorkingIndicator(){},setHiddenThinkingLabel(){},setWidget(){},setFooter(){},setHeader(){},setTitle(){},custom(){return Promise.reject(new Error("Custom UI is not available in app-server mode."))},pasteToEditor(text){editorText=text},setEditorText(text){editorText=text},getEditorText(){return editorText},async editor(_title,prefill){return prefill},addAutocompleteProvider(){},setEditorComponent(factory){editorFactory=factory},getEditorComponent(){return editorFactory},theme,getAllThemes:getAvailableThemesWithPaths,getTheme(name){return getThemeByName(name)},setTheme(_nextTheme){return{success:!1,error:"Theme switching is not available in app-server mode."}},getToolsExpanded(){return toolsExpanded},setToolsExpanded(expanded){toolsExpanded=expanded}}}function parsePermissionPrompt(title){let[firstLine="",...rest]=title.split(`
|
|
4
4
|
`),prefix="Permission required: ";if(!firstLine.startsWith(prefix))return;let toolName=firstLine.slice(prefix.length).trim(),reason=rest.join(`
|
|
5
5
|
`).trim();return{kind:permissionKind(toolName),toolName,command:readLineValue(reason,"Command: $ ")??readLineValue(reason,"File: ")??readLineValue(reason,"Path: ")??null,reason}}function permissionKind(toolName){return toolName==="edit"||toolName==="write"||toolName==="apply_patch"||toolName==="multiedit"?"fileChange":"commandExecution"}function readLineValue(text,prefix){return text.split(`
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { createRequire as __piCreateRequire } from "node:module"; const require = __piCreateRequire(import.meta.url); { const __piWorkerThreads = require("node:worker_threads"); if (typeof __piWorkerThreads.markAsUncloneable !== "function") { __piWorkerThreads.markAsUncloneable = () => {}; } }
|
|
2
|
+
import{getBinDir}from"./chunk-JCTWDSQT.js";import{existsSync}from"node:fs";import{delimiter,join}from"node:path";import{spawnSync}from"child_process";var GIT_BASH_PATH_ENV="SENPI_GIT_BASH_PATH";function isLegacyWslBashPath(path){let normalized=path.replace(/\//g,"\\").toLowerCase();return/^[a-z]:\\windows\\(?:system32|sysnative)\\bash\.exe$/.test(normalized)}function resolveShellKind(shellPath){let base=shellPath.replace(/\\/g,"/").split("/").pop()?.toLowerCase().replace(/\.exe$/,"");return base==="cmd"?"cmd":base==="powershell"||base==="pwsh"?"powershell":base==="sh"?"sh":"bash"}function getBashShellConfig(shell){return isLegacyWslBashPath(shell)?{shell,args:["-s"],commandTransport:"stdin",kind:"bash"}:{shell,args:["-c"],kind:"bash"}}function getShellConfigForPath(shellPath){let kind=resolveShellKind(shellPath);switch(kind){case"cmd":return{shell:shellPath,args:["/c"],kind};case"powershell":return{shell:shellPath,args:["-NoProfile","-Command"],kind};case"sh":return{shell:shellPath,args:["-c"],kind};default:return getBashShellConfig(shellPath)}}function findExecutableOnPath(executable){if(process.platform==="win32"){try{let result=spawnSync("where",[executable],{encoding:"utf-8",timeout:5e3,windowsHide:!0});if(result.status===0&&result.stdout){let firstMatch=result.stdout.trim().split(/\r?\n/)[0];if(firstMatch&&existsSync(firstMatch))return firstMatch}}catch{}return null}try{let result=spawnSync("which",[executable],{encoding:"utf-8",timeout:5e3});if(result.status===0&&result.stdout){let firstMatch=result.stdout.trim().split(/\r?\n/)[0];if(firstMatch)return firstMatch}}catch{}return null}function getShellConfig(customShellPath){if(customShellPath){if(existsSync(customShellPath))return getShellConfigForPath(customShellPath);throw new Error(`Custom shell path not found: ${customShellPath}`)}let gitBashOverride=process.env[GIT_BASH_PATH_ENV];if(gitBashOverride){if(existsSync(gitBashOverride))return getShellConfigForPath(gitBashOverride);throw new Error(`${GIT_BASH_PATH_ENV} points to a missing shell: ${gitBashOverride}`)}if(process.platform==="win32"){let paths=[],programFiles=process.env.ProgramFiles;programFiles&&paths.push(`${programFiles}\\Git\\bin\\bash.exe`);let programFilesX86=process.env["ProgramFiles(x86)"];programFilesX86&&paths.push(`${programFilesX86}\\Git\\bin\\bash.exe`);for(let path of paths)if(existsSync(path))return getBashShellConfig(path);let bashOnPath2=findExecutableOnPath("bash.exe");if(bashOnPath2)return getBashShellConfig(bashOnPath2);throw new Error(`No bash shell found. Options:
|
|
3
|
+
1. Install Git for Windows: https://git-scm.com/download/win
|
|
4
|
+
2. Add your bash to PATH (Cygwin, MSYS2, etc.)
|
|
5
|
+
3. Set shellPath in settings.json
|
|
6
|
+
|
|
7
|
+
Searched Git Bash in:
|
|
8
|
+
${paths.map(p=>` ${p}`).join(`
|
|
9
|
+
`)}`)}if(existsSync("/bin/bash"))return getBashShellConfig("/bin/bash");let bashOnPath=findExecutableOnPath("bash");return bashOnPath?getBashShellConfig(bashOnPath):{shell:"sh",args:["-c"]}}var POWERSHELL_ARGS=["-NoProfile","-NonInteractive","-ExecutionPolicy","Bypass","-Command"];function getPowerShellConfig(){if(process.platform!=="win32")throw new Error("The powershell tool is only available on Windows.");let shell=findExecutableOnPath("pwsh.exe")??findExecutableOnPath("powershell.exe");if(!shell)throw new Error("No PowerShell executable found. Install PowerShell or add powershell.exe/pwsh.exe to PATH.");return{shell,args:[...POWERSHELL_ARGS]}}function getShellEnv(){let binDir=getBinDir(),pathKey=Object.keys(process.env).find(key=>key.toLowerCase()==="path")??"PATH",currentPath=process.env[pathKey]??"",updatedPath=currentPath.split(delimiter).filter(Boolean).includes(binDir)?currentPath:[binDir,currentPath].filter(Boolean).join(delimiter);return{...process.env,[pathKey]:updatedPath}}function sanitizeBinaryOutput(str){return hasUnsafeDisplayCharacter(str)?str.replace(/[\x00-\x08\x0B\x0C\x0E-\x1F\uFFF9-\uFFFB]/g,""):str}function hasUnsafeDisplayCharacter(str){for(let i=0;i<str.length;i++){let code=str.charCodeAt(i),isAllowedControl=code===9||code===10||code===13;if(code<=31&&!isAllowedControl||code>=65529&&code<=65531)return!0}return!1}var trackedDetachedChildren=new Map;function trackDetachedChildPid(pid){trackedDetachedChildren.set(pid,{pid,pgid:pid,leaderExited:!1})}function untrackDetachedChildPid(pid){trackedDetachedChildren.delete(pid)}function noteDetachedChildExited(pid){let entry=trackedDetachedChildren.get(pid);if(entry!==void 0){if(process.platform==="win32"||!processGroupIsAlive(entry.pgid)){trackedDetachedChildren.delete(pid);return}entry.leaderExited=!0}}function pruneTrackedDetachedChildren(){if(process.platform!=="win32")for(let[pid,entry]of trackedDetachedChildren)trackedDetachedChildIsGone(entry)&&trackedDetachedChildren.delete(pid)}function signalTargetExists(target){try{return process.kill(target,0),!0}catch(error){return error.code!=="ESRCH"}}function processGroupIsAlive(pgid){return signalTargetExists(-pgid)}function trackedDetachedChildIsGone(entry){return processGroupIsAlive(entry.pgid)?!1:entry.leaderExited||!signalTargetExists(entry.pid)}function killTrackedDetachedChildren(){pruneTrackedDetachedChildren();for(let entry of trackedDetachedChildren.values())process.platform==="win32"?killWindowsProcessTree(entry.pid):killTrackedDetachedGroup(entry);trackedDetachedChildren.clear()}function killTrackedDetachedGroup(entry){try{process.kill(-entry.pgid,"SIGKILL");return}catch{}if(!entry.leaderExited)try{process.kill(entry.pid,"SIGKILL")}catch{}}function windowsTaskkillCandidates(env=process.env){let systemDrive=env.SystemDrive?`${env.SystemDrive}\\`:void 0,roots=[env.SystemRoot,env.SYSTEMROOT,env.windir,systemDrive&&join(systemDrive,"Windows")],candidates=[];for(let root of roots)if(root)for(let systemDir of["System32","Sysnative"]){let absolute=join(root,systemDir,"taskkill.exe");!candidates.includes(absolute)&&existsSync(absolute)&&candidates.push(absolute)}return candidates.push("taskkill.exe"),candidates}function killProcessDirectly(pid){try{process.kill(pid)}catch{}}var TASKKILL_TIMEOUT_MS=5e3;function taskkillHandledTree(pid,taskkillPath){try{let result=spawnSync(taskkillPath,["/F","/T","/PID",String(pid)],{stdio:"ignore",windowsHide:!0,timeout:TASKKILL_TIMEOUT_MS});return result.error===void 0&&result.status!==null}catch{return!1}}function killWindowsProcessTree(pid,taskkillPaths=windowsTaskkillCandidates()){for(let taskkillPath of taskkillPaths)if(taskkillHandledTree(pid,taskkillPath))return;killProcessDirectly(pid)}function killProcessTree(pid){if(process.platform==="win32")killWindowsProcessTree(pid);else try{process.kill(-pid,"SIGKILL")}catch{try{process.kill(pid,"SIGKILL")}catch{}}}export{getShellConfig,getPowerShellConfig,getShellEnv,sanitizeBinaryOutput,trackDetachedChildPid,untrackDetachedChildPid,noteDetachedChildExited,pruneTrackedDetachedChildren,killTrackedDetachedChildren,killWindowsProcessTree,killProcessTree};
|