@code-yeongyu/senpi 2026.10.10-4 → 2026.10.10-6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +46 -0
- package/dist/bundle/chunks/{anthropic-messages-OE3QBX4P.js → anthropic-messages-DUULMQBF.js} +1 -1
- package/dist/bundle/chunks/{app-server-command-N3L2LNP7.js → app-server-command-GJ5NXQSY.js} +1 -1
- package/dist/bundle/chunks/{chunk-3A3C5VVO.js → chunk-3OGEJMZ7.js} +1 -1
- package/dist/bundle/chunks/{chunk-J5MUMVWB.js → chunk-64ZVBCTL.js} +8 -7
- package/dist/bundle/chunks/{chunk-MP2DMTI7.js → chunk-C7LEZMWS.js} +124 -124
- package/dist/bundle/chunks/{chunk-ZSYRWQWG.js → chunk-JMI5OCIJ.js} +1 -1
- package/dist/bundle/chunks/{chunk-ODYQK5XJ.js → chunk-TALS4X7S.js} +1 -1
- package/dist/bundle/chunks/{chunk-7GVD54RM.js → chunk-U3IL5N76.js} +1 -1
- package/dist/bundle/chunks/{chunk-H67EVDWG.js → chunk-URQSNRHZ.js} +1 -1
- package/dist/bundle/chunks/{chunk-H4UIUFU5.js → chunk-VGYIPYOK.js} +1 -1
- package/dist/bundle/chunks/{chunk-M2IHGL3M.js → chunk-VW74BGIC.js} +1 -1
- package/dist/bundle/chunks/{chunk-4TK7VCZZ.js → chunk-WKMUAG23.js} +1 -1
- package/dist/bundle/chunks/chunk-YG5UO3E4.js +7 -0
- package/dist/bundle/chunks/chunk-YV2XQFXG.js +14 -0
- package/dist/bundle/chunks/{chunk-Z7MMKKIY.js → chunk-ZYHIRFGT.js} +1 -1
- package/dist/bundle/chunks/{cli-main-CHDR33FZ.js → cli-main-SZ54SQLA.js} +1 -1
- package/dist/bundle/chunks/{help-fast-path-EHRZEBRO.js → help-fast-path-W5W3FYYM.js} +1 -1
- package/dist/bundle/chunks/{host-command-VATE7HRG.js → host-command-YG2FIDPN.js} +1 -1
- package/dist/bundle/chunks/{host-lifecycle-GC3GIR2N.js → host-lifecycle-5AV4JXDQ.js} +1 -1
- package/dist/bundle/chunks/{interactive-mode-RVEM62WX.js → interactive-mode-SCNDQ4R6.js} +1 -1
- package/dist/bundle/chunks/{list-tips-IIRFXBTO.js → list-tips-BXAA4FG5.js} +1 -1
- package/dist/bundle/chunks/{multi-session-host-CFND7CXH.js → multi-session-host-ZDZMPNP5.js} +7 -6
- package/dist/bundle/chunks/{package-manager-cli-NWNECBF7.js → package-manager-cli-4LMYHHKH.js} +1 -1
- package/dist/bundle/chunks/{rotation-stream-C5BM7TMM.js → rotation-stream-E3XKSST7.js} +1 -1
- package/dist/bundle/chunks/{rpc-mode-JQFUDLNB.js → rpc-mode-ZFNFREN5.js} +1 -1
- package/dist/bundle/chunks/{schedule-command-EQ4PQCRP.js → schedule-command-K6CTAB4T.js} +1 -1
- package/dist/bundle/chunks/{session-control-endpoint-HMB5T5VD.js → session-control-endpoint-MVSYBGM3.js} +1 -1
- package/dist/bundle/chunks/{session-picker-O7OESJWU.js → session-picker-TNXWY5QY.js} +1 -1
- package/dist/bundle/chunks/session-worker.js +224 -222
- 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/agent-session-runtime.d.ts +6 -0
- package/dist/core/agent-session-runtime.js +18 -0
- package/dist/core/agent-session.js +5 -2
- package/dist/core/extensions/builtin/anthropic-subscription/auth-lane.js +3 -2
- package/dist/core/extensions/builtin/anthropic-subscription/options.js +11 -2
- package/dist/core/extensions/builtin/anthropic-subscription/session-reattach.js +4 -1
- package/dist/core/extensions/builtin/anthropic-subscription/session-sync.js +3 -0
- package/dist/core/extensions/builtin/anthropic-subscription/settings.d.ts +5 -0
- package/dist/core/extensions/builtin/anthropic-subscription/settings.js +11 -0
- package/dist/core/extensions/builtin/anthropic-subscription/stream.d.ts +1 -0
- package/dist/core/extensions/builtin/anthropic-subscription/stream.js +17 -1
- package/dist/core/extensions/builtin/compaction/lane-policy.d.ts +20 -12
- package/dist/core/extensions/builtin/compaction/lane-policy.js +39 -34
- package/dist/core/extensions/builtin/html-render/bootstrap.d.ts +15 -0
- package/dist/core/extensions/builtin/html-render/bootstrap.js +123 -0
- package/dist/core/extensions/builtin/html-render/images.d.ts +16 -0
- package/dist/core/extensions/builtin/html-render/images.js +155 -0
- package/dist/core/extensions/builtin/html-render/index.d.ts +3 -0
- package/dist/core/extensions/builtin/html-render/index.js +5 -0
- package/dist/core/extensions/builtin/html-render/tool.d.ts +19 -0
- package/dist/core/extensions/builtin/html-render/tool.js +74 -0
- package/dist/core/extensions/builtin/index.js +4 -0
- package/dist/core/extensions/builtin/mcp/auth/catalog-identity.d.ts +4 -0
- package/dist/core/extensions/builtin/mcp/auth/catalog-identity.js +41 -0
- package/dist/core/extensions/builtin/mcp/auth/legacy-lock.d.ts +3 -0
- package/dist/core/extensions/builtin/mcp/auth/legacy-lock.js +39 -0
- package/dist/core/extensions/builtin/mcp/auth/legacy-migration.d.ts +14 -0
- package/dist/core/extensions/builtin/mcp/auth/legacy-migration.js +91 -0
- package/dist/core/extensions/builtin/mcp/auth/oauth-refresh.js +1 -1
- package/dist/core/extensions/builtin/mcp/auth/token-store.d.ts +1 -0
- package/dist/core/extensions/builtin/mcp/auth/token-store.js +19 -90
- package/dist/core/extensions/builtin/mcp/catalog-cache.d.ts +7 -3
- package/dist/core/extensions/builtin/mcp/catalog-cache.js +61 -12
- package/dist/core/extensions/builtin/mcp/catalog.d.ts +3 -1
- package/dist/core/extensions/builtin/mcp/catalog.js +2 -0
- package/dist/core/extensions/builtin/mcp/connection-types.d.ts +2 -0
- package/dist/core/extensions/builtin/mcp/expose/call.d.ts +12 -0
- package/dist/core/extensions/builtin/mcp/expose/call.js +60 -0
- package/dist/core/extensions/builtin/mcp/expose/proxy.js +16 -3
- package/dist/core/extensions/builtin/mcp/expose/register.d.ts +3 -1
- package/dist/core/extensions/builtin/mcp/expose/register.js +41 -50
- package/dist/core/extensions/builtin/mcp/expose/session.d.ts +4 -0
- package/dist/core/extensions/builtin/mcp/expose/session.js +5 -1
- package/dist/core/extensions/builtin/mcp/expose/tier-b.js +15 -4
- package/dist/core/extensions/builtin/mcp/index.js +5 -26
- package/dist/core/extensions/builtin/mcp/invocation.d.ts +42 -0
- package/dist/core/extensions/builtin/mcp/invocation.js +118 -0
- package/dist/core/extensions/builtin/mcp/service-connection.d.ts +3 -0
- package/dist/core/extensions/builtin/mcp/service-connection.js +6 -0
- package/dist/core/extensions/builtin/mcp/service-register.d.ts +4 -0
- package/dist/core/extensions/builtin/mcp/service-register.js +45 -1
- package/dist/core/extensions/builtin/mcp/service-tools-changed.js +26 -3
- package/dist/core/extensions/builtin/mcp/service-types.d.ts +6 -0
- package/dist/core/extensions/builtin/mcp/service.js +83 -49
- package/dist/core/extensions/builtin/mcp/shared-connection.js +17 -4
- package/dist/core/extensions/builtin/mcp/sharing-policy.js +1 -0
- package/dist/core/extensions/builtin/mcp/startup-race.js +47 -9
- package/dist/core/extensions/builtin/permission-system/dispatch-metadata.d.ts +8 -0
- package/dist/core/extensions/builtin/permission-system/dispatch-metadata.js +23 -0
- package/dist/core/extensions/builtin/permission-system/dispatch-policy.d.ts +14 -0
- package/dist/core/extensions/builtin/permission-system/dispatch-policy.js +53 -0
- package/dist/core/extensions/builtin/permission-system/dispatch.d.ts +33 -0
- package/dist/core/extensions/builtin/permission-system/dispatch.js +106 -0
- package/dist/core/extensions/builtin/permission-system/index.js +64 -17
- package/dist/core/extensions/builtin/permission-system/prompt.d.ts +1 -1
- package/dist/core/extensions/builtin/permission-system/prompt.js +3 -1
- package/dist/core/extensions/builtin/permission-system/service.d.ts +11 -1
- package/dist/core/extensions/builtin/permission-system/service.js +14 -4
- package/dist/core/extensions/builtin/ttsr/detectors/collapse-near-duplicates.d.ts +1 -0
- package/dist/core/extensions/builtin/ttsr/detectors/collapse-near-duplicates.js +24 -5
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/modes/interactive/interactive-mode.js +21 -4
- package/dist/modes/rpc/host-reservations.d.ts +1 -1
- package/dist/modes/rpc/host-reservations.js +9 -3
- package/dist/modes/rpc/rpc-client.js +14 -2
- package/dist/modes/rpc/rpc-request-deadline.d.ts +8 -0
- package/dist/modes/rpc/rpc-request-deadline.js +10 -0
- package/dist/modes/rpc/rpc-types.d.ts +7 -4
- package/dist/modes/rpc/session-binding.js +15 -1
- package/dist/modes/rpc/session-command-router.d.ts +1 -0
- package/dist/modes/rpc/session-command-router.js +16 -0
- package/dist/modes/rpc/session-registry-attach.js +8 -2
- package/dist/modes/rpc/session-registry.js +5 -7
- package/dist/modes/rpc/session-teardown.d.ts +6 -1
- package/dist/modes/rpc/session-teardown.js +26 -7
- package/dist/modes/rpc/session-worker-client.d.ts +2 -0
- package/dist/modes/rpc/session-worker-client.js +6 -0
- package/dist/modes/rpc/session-worker-protocol.d.ts +4 -0
- package/dist/modes/rpc/session-worker.js +6 -0
- package/dist/modes/rpc/worker-session-registry.js +6 -1
- package/docs/providers.md +3 -2
- package/docs/rpc.md +26 -10
- package/package.json +6 -6
- package/dist/bundle/chunks/chunk-RADHRQ4K.js +0 -7
- package/dist/bundle/chunks/chunk-USRAHAW4.js +0 -14
|
@@ -1,2 +1,2 @@
|
|
|
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{KeybindingsManager,TUI_KEYBINDINGS,isWarpWslSession}from"./chunk-
|
|
2
|
+
import{KeybindingsManager,TUI_KEYBINDINGS,isWarpWslSession}from"./chunk-64ZVBCTL.js";import{getAgentDir,stripBom}from"./chunk-463OK2Y4.js";import{existsSync,readFileSync}from"fs";import{join}from"path";function useWindowsKeybindings(platform=process.platform,env=process.env){return platform==="win32"||platform==="linux"&&!!(env.WSL_DISTRO_NAME||env.WSL_INTEROP)}var windowsKeybindings=useWindowsKeybindings(),QUESTION_ANSWER_PRIMARY_KEY="alt+up",QUESTION_ANSWER_FALLBACK_KEY="alt+a",KEYBINDINGS={...TUI_KEYBINDINGS,"tui.editor.undo":{...TUI_KEYBINDINGS["tui.editor.undo"],defaultKeys:process.platform==="win32"?"ctrl+z":windowsKeybindings?"alt+z":"ctrl+-"},"tui.altScreen.previousPrompt":{...TUI_KEYBINDINGS["tui.altScreen.previousPrompt"],defaultKeys:windowsKeybindings?"ctrl+up":["ctrl+shift+up","ctrl+up"]},"tui.altScreen.nextPrompt":{...TUI_KEYBINDINGS["tui.altScreen.nextPrompt"],defaultKeys:windowsKeybindings?"ctrl+down":["ctrl+shift+down","ctrl+down"]},"tui.altScreen.search":{...TUI_KEYBINDINGS["tui.altScreen.search"],defaultKeys:windowsKeybindings?"ctrl+f":"ctrl+shift+f"},"app.interrupt":{defaultKeys:"escape",description:"Cancel or abort"},"app.clear":{defaultKeys:"ctrl+c",description:"Clear editor"},"app.exit":{defaultKeys:"ctrl+d",description:"Exit when editor is empty"},"app.suspend":{defaultKeys:process.platform==="win32"?[]:"ctrl+z",description:"Suspend to background"},"app.thinking.cycle":{defaultKeys:"shift+tab",description:"Cycle thinking level"},"app.thinking.save":{defaultKeys:"ctrl+s",description:"Save thinking level"},"app.model.cycleForward":{defaultKeys:"ctrl+p",description:"Cycle to next model"},"app.model.cycleBackward":{defaultKeys:windowsKeybindings?"alt+p":"shift+ctrl+p",description:"Cycle to previous model"},"app.model.select":{defaultKeys:"ctrl+l",description:"Open model selector"},"app.history.search":{defaultKeys:"ctrl+r",description:"Search prompt history across sessions"},"app.tools.expand":{defaultKeys:"ctrl+o",description:"Toggle tool output"},"app.thinking.toggle":{defaultKeys:"ctrl+t",description:"Toggle thinking blocks"},"app.session.toggleNamedFilter":{defaultKeys:"ctrl+n",description:"Toggle named session filter"},"app.editor.external":{defaultKeys:"ctrl+g",description:"Open external editor"},"app.message.copy":{defaultKeys:"ctrl+x",description:"Copy selection or last assistant message"},"app.message.followUp":{defaultKeys:windowsKeybindings?"ctrl+q":"alt+enter",description:"Queue follow-up message"},"app.message.dequeue":{defaultKeys:windowsKeybindings?"alt+q":"alt+up",description:"Restore queued messages"},"app.question.answer":{defaultKeys:[QUESTION_ANSWER_PRIMARY_KEY,QUESTION_ANSWER_FALLBACK_KEY],description:"Open the pending question"},"app.question.next":{defaultKeys:"alt+down",description:"Show the next pending question"},"app.clipboard.pasteImage":{defaultKeys:isWarpWslSession()?["ctrl+v","alt+v"]:windowsKeybindings?"alt+v":"ctrl+v",description:"Paste files on macOS, images, or text from clipboard"},"app.session.new":{defaultKeys:[],description:"Start a new session"},"app.session.tree":{defaultKeys:[],description:"Open session tree"},"app.session.fork":{defaultKeys:[],description:"Fork current session"},"app.session.resume":{defaultKeys:[],description:"Resume a session"},"app.session.renameCurrent":{defaultKeys:[],description:"Rename the current session"},"app.tree.foldOrUp":{defaultKeys:process.platform==="darwin"?["alt+left","ctrl+left"]:["ctrl+left","alt+left"],description:"Fold tree branch or move up"},"app.tree.unfoldOrDown":{defaultKeys:process.platform==="darwin"?["alt+right","ctrl+right"]:["ctrl+right","alt+right"],description:"Unfold tree branch or move down"},"app.tree.editLabel":{defaultKeys:"shift+l",description:"Edit tree label"},"app.tree.editMessage":{defaultKeys:"ctrl+e",description:"Edit the selected assistant response, or reopen a user message in the editor"},"app.tree.toggleLabelTimestamp":{defaultKeys:"shift+t",description:"Toggle tree label timestamps"},"app.session.togglePath":{defaultKeys:"ctrl+p",description:"Toggle session path display"},"app.session.toggleSort":{defaultKeys:"ctrl+s",description:"Toggle session sort mode"},"app.session.rename":{defaultKeys:"ctrl+r",description:"Rename session"},"app.session.delete":{defaultKeys:"ctrl+d",description:"Delete session"},"app.session.deleteNoninvasive":{defaultKeys:"ctrl+backspace",description:"Delete session when query is empty"},"app.models.save":{defaultKeys:"ctrl+s",description:"Save model selection"},"app.models.toggleFavorite":{defaultKeys:"ctrl+f",description:"Toggle favorite model"},"app.models.enableAll":{defaultKeys:"ctrl+a",description:"Enable all models"},"app.models.clearAll":{defaultKeys:"ctrl+x",description:"Clear all models"},"app.models.toggleProvider":{defaultKeys:"ctrl+p",description:"Toggle all models for provider"},"app.models.reorderUp":{defaultKeys:"alt+up",description:"Move model up in order"},"app.models.reorderDown":{defaultKeys:"alt+down",description:"Move model down in order"},"app.tree.filter.default":{defaultKeys:"ctrl+d",description:"Tree filter: default view"},"app.tree.filter.noTools":{defaultKeys:"ctrl+t",description:"Tree filter: hide tool results"},"app.tree.filter.userOnly":{defaultKeys:"ctrl+u",description:"Tree filter: user messages only"},"app.tree.filter.labeledOnly":{defaultKeys:"ctrl+l",description:"Tree filter: labeled entries only"},"app.tree.filter.all":{defaultKeys:"ctrl+a",description:"Tree filter: show all entries"},"app.tree.filter.cycleForward":{defaultKeys:"ctrl+o",description:"Tree filter: cycle forward"},"app.tree.filter.cycleBackward":{defaultKeys:"shift+ctrl+o",description:"Tree filter: cycle backward"}},KEYBINDING_NAME_MIGRATIONS={cursorUp:"tui.editor.cursorUp",cursorDown:"tui.editor.cursorDown",cursorLeft:"tui.editor.cursorLeft",cursorRight:"tui.editor.cursorRight",cursorWordLeft:"tui.editor.cursorWordLeft",cursorWordRight:"tui.editor.cursorWordRight",cursorLineStart:"tui.editor.cursorLineStart",cursorLineEnd:"tui.editor.cursorLineEnd",jumpForward:"tui.editor.jumpForward",jumpBackward:"tui.editor.jumpBackward",pageUp:"tui.editor.pageUp",pageDown:"tui.editor.pageDown",deleteCharBackward:"tui.editor.deleteCharBackward",deleteCharForward:"tui.editor.deleteCharForward",deleteWordBackward:"tui.editor.deleteWordBackward",deleteWordForward:"tui.editor.deleteWordForward",deleteToLineStart:"tui.editor.deleteToLineStart",deleteToLineEnd:"tui.editor.deleteToLineEnd",yank:"tui.editor.yank",yankPop:"tui.editor.yankPop",undo:"tui.editor.undo",newLine:"tui.input.newLine",submit:"tui.input.submit",tab:"tui.input.tab",copy:"tui.input.copy",selectUp:"tui.select.up",selectDown:"tui.select.down",selectPageUp:"tui.select.pageUp",selectPageDown:"tui.select.pageDown",selectConfirm:"tui.select.confirm",selectCancel:"tui.select.cancel",interrupt:"app.interrupt",clear:"app.clear",exit:"app.exit",suspend:"app.suspend",cycleThinkingLevel:"app.thinking.cycle",cycleModelForward:"app.model.cycleForward",cycleModelBackward:"app.model.cycleBackward",selectModel:"app.model.select",expandTools:"app.tools.expand",toggleThinking:"app.thinking.toggle",toggleSessionNamedFilter:"app.session.toggleNamedFilter",externalEditor:"app.editor.external",followUp:"app.message.followUp",dequeue:"app.message.dequeue",pasteImage:"app.clipboard.pasteImage",newSession:"app.session.new",tree:"app.session.tree",fork:"app.session.fork",resume:"app.session.resume",treeFoldOrUp:"app.tree.foldOrUp",treeUnfoldOrDown:"app.tree.unfoldOrDown",treeEditLabel:"app.tree.editLabel",treeEditMessage:"app.tree.editMessage",treeToggleLabelTimestamp:"app.tree.toggleLabelTimestamp",toggleSessionPath:"app.session.togglePath",toggleSessionSort:"app.session.toggleSort",renameSession:"app.session.rename",deleteSession:"app.session.delete",deleteSessionNoninvasive:"app.session.deleteNoninvasive"};function isRecord(value){return typeof value=="object"&&value!==null&&!Array.isArray(value)}function hasOwn(value,key){return Object.hasOwn(value,key)}function isLegacyKeybindingName(key){return key in KEYBINDING_NAME_MIGRATIONS}function toKeybindingsConfig(value){let config={};for(let[key,binding]of Object.entries(value)){if(typeof binding=="string"){config[key]=binding;continue}Array.isArray(binding)&&binding.every(entry=>typeof entry=="string")&&(config[key]=binding)}return config}function migrateKeybindingsConfig(rawConfig){let config={},migrated=!1;for(let[key,value]of Object.entries(rawConfig)){let nextKey=isLegacyKeybindingName(key)?KEYBINDING_NAME_MIGRATIONS[key]:key;if(nextKey!==key&&(migrated=!0),key!==nextKey&&hasOwn(rawConfig,nextKey)){migrated=!0;continue}config[nextKey]=value}return{config:orderKeybindingsConfig(config),migrated}}function orderKeybindingsConfig(config){let ordered={};for(let keybinding of Object.keys(KEYBINDINGS))hasOwn(config,keybinding)&&(ordered[keybinding]=config[keybinding]);let extras=Object.keys(config).filter(key=>!hasOwn(ordered,key)).sort();for(let key of extras)ordered[key]=config[key];return ordered}function loadRawConfig(path){if(existsSync(path))try{let parsed=JSON.parse(stripBom(readFileSync(path,"utf-8")));return isRecord(parsed)?parsed:void 0}catch{return}}var KeybindingsManager2=class _KeybindingsManager extends KeybindingsManager{constructor(userBindings={},configPath){super(KEYBINDINGS,userBindings),this.configPath=configPath}static create(agentDir=getAgentDir()){let configPath=join(agentDir,"keybindings.json"),userBindings=_KeybindingsManager.loadFromFile(configPath);return new _KeybindingsManager(userBindings,configPath)}reload(){this.configPath&&this.setUserBindings(_KeybindingsManager.loadFromFile(this.configPath))}getEffectiveConfig(){return this.getResolvedBindings()}static loadFromFile(path){let rawConfig=loadRawConfig(path);return rawConfig?toKeybindingsConfig(migrateKeybindingsConfig(rawConfig).config):{}}};export{QUESTION_ANSWER_PRIMARY_KEY,QUESTION_ANSWER_FALLBACK_KEY,KEYBINDINGS,migrateKeybindingsConfig,KeybindingsManager2 as KeybindingsManager};
|
|
@@ -1,2 +1,2 @@
|
|
|
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{rateLimitModelFamily}from"./chunk-F6EQ7EV3.js";import{getShellConfig}from"./chunk-JEZWV7JW.js";import{getOverflowPatterns}from"./chunk-ODYQK5XJ.js";import{normalizeProviderError}from"./chunk-TAV6QZFM.js";import{extract429RetryAfterMs}from"./chunk-PELNNWGO.js";import{PROVIDER_NOT_CONFIGURED_PREFIX,USAGE_LIMIT_EXHAUSTION}from"./chunk-XL5KIYQF.js";var PRE_COMMIT_EVENT_TYPES=new Set(["start","text_start","thinking_start","toolcall_start"]);function isCommittedRotationOutput(event){return!PRE_COMMIT_EVENT_TYPES.has(event.type)}function isRotationStreamStart(event){return event.type==="start"}function rotationErrorFromEvent(event){if(event.type!=="error")return;let failure=new Error(event.error.errorMessage??"provider stream error"),status=event.error.providerDiagnostic?.httpStatus;return status===void 0?failure:Object.assign(failure,{status})}function rendezvousOrder(key,slots,hasher){return[...slots].map(slot=>({slot,score:hasher(`${key}\0${slot.name}`)})).sort((left,right)=>right.score>left.score?1:right.score<left.score?-1:0).map(({slot})=>slot)}var DEFAULT_SLOT_BLOCK_MS=6e4,MAX_SLOT_BLOCK_MS=2880*60*1e3;var MONTHS=["jan","feb","mar","apr","may","jun","jul","aug","sep","oct","nov","dec"],RESET_AT_KEYS=new Set(["resets_at"]),RESET_AFTER_SECONDS_KEYS=new Set(["reset_after_seconds"]),RELATIVE_RE=/\b(?:resets?|try again|retry)\s+in\s+~?((?:\d+(?:\.\d+)?\s*(?:days?|d|hours?|hrs?|h|minutes?|mins?|m|seconds?|secs?|s)\b(?:\s*,?\s*(?:and\s+)?)?)+)/i,RELATIVE_PART_RE=/(\d+(?:\.\d+)?)\s*(days?|d|hours?|hrs?|h|minutes?|mins?|m|seconds?|secs?|s)\b/gi,CLOCK_RE=/\b(?:resets?|try again)\s+(?:at\s+|on\s+)?(?:([a-z]{3})[a-z]*\.?\s+(\d{1,2}),?\s+(?:at\s+)?)?(\d{1,2})(?::(\d{2}))?\s*([ap])\.?\s?m\b\.?(?:\s*\(([A-Za-z_]+(?:\/[A-Za-z0-9_+-]+)*)\))?/i;function usageLimitResetMs(text,nowMs){return fromJsonFields(text,nowMs)??fromRelativeProse(text)??fromClockProse(text,nowMs)}function fromJsonFields(text,nowMs){let start=text.indexOf("{");if(start<0)return;let parsed;try{parsed=JSON.parse(text.slice(start))}catch{return}let found;return walk(parsed,(key,value)=>{let ms=RESET_AT_KEYS.has(key)?absoluteFieldMs(value,nowMs):RESET_AFTER_SECONDS_KEYS.has(key)?secondsFieldMs(value):void 0;ms!==void 0&&(found===void 0||ms>found)&&(found=ms)}),found}function walk(value,visit){if(Array.isArray(value)){for(let item of value)walk(item,visit);return}if(!(typeof value!="object"||value===null))for(let[key,entry]of Object.entries(value))visit(key,entry),walk(entry,visit)}function absoluteFieldMs(value,nowMs){if(typeof value=="number"&&Number.isFinite(value)&&value>0){let epochMs=value<1e12?value*1e3:value;return Math.max(0,Math.ceil(epochMs-nowMs))}if(typeof value=="string"&&/\d{4}-\d{2}-\d{2}T/.test(value)){let epochMs=Date.parse(value);return Number.isNaN(epochMs)?void 0:Math.max(0,epochMs-nowMs)}}function secondsFieldMs(value){return typeof value=="number"&&Number.isFinite(value)&&value>=0?Math.ceil(value*1e3):void 0}function fromRelativeProse(text){let phrase=RELATIVE_RE.exec(text)?.[1];if(phrase===void 0)return;let total=0;for(let[,amount,unit]of phrase.matchAll(RELATIVE_PART_RE))total+=Number.parseFloat(amount??"0")*unitMs(unit??"");return Math.ceil(total)}function unitMs(unit){let u=unit.toLowerCase();return u.startsWith("d")?864e5:u.startsWith("h")?36e5:u==="s"||u.startsWith("sec")?1e3:6e4}function fromClockProse(text,nowMs){let match=CLOCK_RE.exec(text);if(!match)return;let[,monthName,dayText,hourText,minuteText,meridiem,zoneText]=match,hour12=Number.parseInt(hourText??"",10),minute=minuteText===void 0?0:Number.parseInt(minuteText,10);if(hour12<1||hour12>12||minute>59)return;let hour=hour12%12+(meridiem?.toLowerCase()==="p"?12:0),zone=zoneText??Intl.DateTimeFormat().resolvedOptions().timeZone;if(!isValidTimeZone(zone))return;let today=zonedParts(zone,nowMs);if(monthName!==void 0){let month=MONTHS.indexOf(monthName.toLowerCase()),day=Number.parseInt(dayText??"",10);if(month<0||day<1||day>31)return;let target2=zonedToEpoch(zone,today.year,month,day,hour,minute);return target2<=nowMs&&(target2=zonedToEpoch(zone,today.year+1,month,day,hour,minute)),target2-nowMs}let target=zonedToEpoch(zone,today.year,today.month,today.day,hour,minute);return target<=nowMs&&(target=zonedToEpoch(zone,today.year,today.month,today.day+1,hour,minute)),target-nowMs}function isValidTimeZone(zone){try{return new Intl.DateTimeFormat("en-US",{timeZone:zone}),!0}catch{return!1}}function zonedParts(zone,epochMs){let parts=new Intl.DateTimeFormat("en-US",{timeZone:zone,hourCycle:"h23",year:"numeric",month:"numeric",day:"numeric",hour:"numeric",minute:"numeric",second:"numeric"}).formatToParts(epochMs),get=type=>Number.parseInt(parts.find(part=>part.type===type)?.value??"0",10);return{year:get("year"),month:get("month")-1,day:get("day"),hour:get("hour"),minute:get("minute"),second:get("second")}}function zoneOffsetMs(zone,epochMs){let p=zonedParts(zone,epochMs);return Date.UTC(p.year,p.month,p.day,p.hour,p.minute,p.second)-Math.floor(epochMs/1e3)*1e3}function zonedToEpoch(zone,year,month,day,hour,minute){let wall=Date.UTC(year,month,day,hour,minute),first=wall-zoneOffsetMs(zone,wall);return wall-zoneOffsetMs(zone,first)}function escapeRegExp(text){return text.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}var ACCOUNT_USAGE_LIMIT_TEXT=new RegExp([...USAGE_LIMIT_EXHAUSTION.markers.map(escapeRegExp),String.raw`\b(?:hit|reached)\s+your\b[^.]*?\blimit\b`,String.raw`\busage\s+limit\s+reached\b`,String.raw`\b(?:Go|Free)UsageLimitError\b`,String.raw`\bblocking_limit\b`,String.raw`\brapid_refill_breaker\b`,String.raw`\bquota\s+exceeded\b`].join("|"),"i");function isAccountUsageLimitText(text){return ACCOUNT_USAGE_LIMIT_TEXT.test(text)}var COOLDOWN_BASE_MS=DEFAULT_SLOT_BLOCK_MS,COOLDOWN_CAP_MS=MAX_SLOT_BLOCK_MS,RETRY_SAME_MAX_ATTEMPTS=2;function rateLimitCooldown(failureCount,serverHintMs,policy={}){let cap=policy.capMs??COOLDOWN_CAP_MS,base=policy.baseMs??COOLDOWN_BASE_MS,backoff=Math.min(cap,base*2**Math.max(0,failureCount)),floored=serverHintMs===void 0?backoff:Math.max(backoff,serverHintMs);return{cooldownMs:Math.min(cap,floored),retryAfterWasCapped:floored>cap}}var INVALID_KEY_TEXT=/invalid[ _-]?(?:api[ _-]?)?key|authentication[_ ]?error|invalid x-api-key|unauthorized/i,ACCOUNT_SCOPED_403_TEXT=/account|credential|token|api[ _-]?key|organization|subscription/i,RATE_LIMIT_TEXT=/rate[ _-]?limit|too many requests|resource_exhausted/i,BILLING_TEXT=/billing|credits?[ _-]?(?:required|exhausted|balance)|insufficient[ _-]?(?:funds|quota|credit)|payment[ _-]?required|quota[ _-]?exhausted/i,OVERLOAD_TEXT=/overloaded/i,NETWORK_TEXT=/econnreset|econnrefused|etimedout|enotfound|socket hang up|fetch failed|network error|request timed out/i,WEBSOCKET_REQUEST_FAULT_TEXT=/websocket closed 100[89]\b/i,WEBSOCKET_TRANSPORT_FAULT_TEXT=/websocket (?:closed|error|connect timeout|liveness timeout)/i,FAIL_FAST_TEXT=/context[ _-]?(?:length|window)|maximum context|invalid[ _-]?model|model[ _-]?not[ _-]?found|malformed[ _-]?stream|premature[ _-]?(?:close|stream)/i,ABORT_TEXT=/\baborted?\b/i;function isAbort(error,message){return error instanceof Error&&error.name==="AbortError"?!0:ABORT_TEXT.test(message)}function isOverflowText(text){return getOverflowPatterns().some(pattern=>pattern.test(text))}function classifyCredentialFailure(error,context={}){let normalized=normalizeProviderError(error),text=normalized.messageCarriesBody?normalized.message:`${normalized.message} ${normalized.body??""}`,status=normalized.status,failureCount=context.failureCount??0;if(isAbort(error,text))return{kind:"fail_request"};if(text.includes(PROVIDER_NOT_CONFIGURED_PREFIX))return{kind:"failover",block:{reason:"auth_error"}};if(status===401||INVALID_KEY_TEXT.test(text))return{kind:"failover",block:{reason:"auth_error"}};if(status===403)return ACCOUNT_SCOPED_403_TEXT.test(text)?{kind:"failover",block:{reason:"auth_error"}}:{kind:"fail_request"};if(status===402||BILLING_TEXT.test(text))return{kind:"failover",block:{reason:"account_disabled"}};let usageLimit=isAccountUsageLimitText(text)&&!isOverflowText(text);if(status===429||RATE_LIMIT_TEXT.test(text)||usageLimit){let nowMs=context.nowMs??Date.now(),hint=extract429RetryAfterMs({status:status??429,bodyText:text},nowMs)??(usageLimit?normalized.retryAfterMs??usageLimitResetMs(text,nowMs):void 0),modelFamily=rateLimitModelFamily(text);return{kind:"failover",block:{reason:"rate_limit",...rateLimitCooldown(failureCount,hint,{baseMs:context.cooldownBaseMs,capMs:context.cooldownCapMs}),...modelFamily===void 0?{}:{modelFamily}}}}return isOverflowText(text)||status===400||status===404||FAIL_FAST_TEXT.test(text)?{kind:"fail_request"}:WEBSOCKET_REQUEST_FAULT_TEXT.test(text)?{kind:"fail_request"}:WEBSOCKET_TRANSPORT_FAULT_TEXT.test(text)?{kind:"retry_same",maxAttempts:RETRY_SAME_MAX_ATTEMPTS}:status===529||OVERLOAD_TEXT.test(text)||status!==void 0&&status>=500&&status<600?{kind:"retry_same",maxAttempts:RETRY_SAME_MAX_ATTEMPTS}:status===408||NETWORK_TEXT.test(text)?{kind:"retry_same",maxAttempts:RETRY_SAME_MAX_ATTEMPTS}:{kind:"fail_request"}}var CredentialFailoverError=class extends Error{constructor(action,original,options={}){let detail=original instanceof Error?original.message:String(original);super(detail,{cause:original}),this.name="CredentialFailoverError",this.action=action,this.original=original,this.retryAt=options.retryAt}};function isAvailable(slot,now){return!(slot.blockReason==="auth_error"||slot.blockReason==="account_disabled"||slot.blockedUntil!==void 0&&slot.blockedUntil>now)}function soonestRetryAt(slots,now){let deadlines=slots.map(slot=>slot.blockedUntil).filter(value=>value!==void 0&&value>now);return deadlines.length===0?void 0:Math.min(...deadlines)}async function settle(stream){let iterator=stream[Symbol.asyncIterator]();try{await iterator.return?.(void 0)}catch{}}async function*runCredentialFailover(options){let now=options.now??Date.now,classify=options.classify??classifyCredentialFailure,attempted=new Set,retriesBySlot=new Map,lastError,lastOriginal,lastTerminalEvent,startAnnounced=!1;for(;;){let slots=await options.listSlots(),candidates=slots.filter(slot2=>!attempted.has(slot2.name)&&isAvailable(slot2,now()));if(candidates.length===0){if(lastTerminalEvent!==void 0){yield lastTerminalEvent;return}let retryAt=soonestRetryAt(slots,now());throw lastError!==void 0&&lastOriginal!==void 0?new CredentialFailoverError(lastError.action,lastOriginal,retryAt===void 0?{}:{retryAt}):new CredentialFailoverError({kind:"fail_request"},new Error("No credential slots available"),retryAt===void 0?{}:{retryAt})}let slot=options.select(candidates),committedOutput=!1,terminalEvent,attemptStream;try{attemptStream=await options.runAttempt(slot);for await(let event of attemptStream){let failure=options.errorFromEvent?.(event);if(failure!==void 0)throw terminalEvent=event,failure;if(options.isStreamStart?.(event)){if(startAnnounced)continue;startAnnounced=!0}committedOutput||=options.isCommittedOutput(event),yield event}await options.onSuccess?.(slot);return}catch(error){attemptStream&&await settle(attemptStream);let failureCount=(slot.failureCount??0)+(retriesBySlot.get(slot.name)??0),action=classify(error,{failureCount});if(lastOriginal=error,lastTerminalEvent=terminalEvent,action.kind==="retry_same"&&!committedOutput){let used=(retriesBySlot.get(slot.name)??0)+1;if(retriesBySlot.set(slot.name,used),used<action.maxAttempts)continue;if(terminalEvent!==void 0){yield terminalEvent;return}throw new CredentialFailoverError(action,error)}if(action.kind!=="failover"){if(terminalEvent!==void 0){yield terminalEvent;return}throw new CredentialFailoverError(action,error)}await options.persistBlock(slot,action.block),attempted.add(slot.name);let failure=new CredentialFailoverError(action,error);if(lastError=failure,await options.onRotate?.({slot,block:action.block,attempt:attempted.size,committedOutput}),committedOutput){if(terminalEvent!==void 0){yield terminalEvent;return}throw failure}}}}function sleep(ms,signal){return new Promise((resolve,reject)=>{if(signal?.aborted){reject(new Error("Aborted"));return}let timeout=setTimeout(resolve,ms);signal?.addEventListener("abort",()=>{clearTimeout(timeout),reject(new Error("Aborted"))})})}import{spawn}from"child_process";var COMMAND_EXECUTION_MAX_ATTEMPTS=3,COMMAND_EXECUTION_BACKOFF_MS=[250,1e3],COMMAND_TIMEOUT_MS=1e4,COMMAND_MAX_OUTPUT_BYTES=1024*1024;function runCommandProcess(file,args,options){return new Promise(resolveOutcome=>{let spawnOptions={shell:options.shell,windowsHide:!0,...options.env===void 0?{}:{env:{...process.env,...options.env}}},child=options.stdin===void 0?spawn(file,[...args],{...spawnOptions,stdio:["ignore","pipe","ignore"]}):spawn(file,[...args],{...spawnOptions,stdio:["pipe","pipe","ignore"]}),stdout="",settled=!1,finish=outcome=>{settled||(settled=!0,clearTimeout(timer),resolveOutcome(outcome))},timer=setTimeout(()=>{child.kill("SIGTERM"),child.unref(),finish({executed:!0,value:void 0})},COMMAND_TIMEOUT_MS);child.stdout.setEncoding("utf-8"),child.stdout.on("data",chunk=>{stdout+=chunk,!(stdout.length<=COMMAND_MAX_OUTPUT_BYTES)&&(child.kill("SIGTERM"),finish({executed:!0,value:void 0}))}),child.on("error",error=>finish({executed:error.code!=="ENOENT",value:void 0})),child.on("close",code=>{let value=stdout.trim();finish({executed:!0,value:code===0&&value?value:void 0})}),child.stdin?.end(options.stdin)})}async function executeWithConfiguredShell(command,env){try{let{shell,args,commandTransport}=getShellConfig(),commandFromStdin=commandTransport==="stdin";return await runCommandProcess(shell,commandFromStdin?args:[...args,command],{shell:!1,...commandFromStdin?{stdin:command}:{},...env===void 0?{}:{env}})}catch{return{executed:!1,value:void 0}}}async function executeCommandOnce(command,env){if(process.platform==="win32"){let configured=await executeWithConfiguredShell(command,env);if(configured.executed)return configured.value}return(await runCommandProcess(command,[],{shell:!0,...env===void 0?{}:{env}})).value}async function runConfigCommand(commandConfig,env){let command=commandConfig.slice(1);for(let attempt=0;attempt<COMMAND_EXECUTION_MAX_ATTEMPTS;attempt++){let value=await executeCommandOnce(command,env);if(value!==void 0)return value;let backoffMs=COMMAND_EXECUTION_BACKOFF_MS[attempt];backoffMs!==void 0&&await sleep(backoffMs)}}var commandResultCache=new Map,ENV_VAR_NAME_RE=/^[A-Za-z_][A-Za-z0-9_]*$/,ENV_VAR_NAME_PREFIX_RE=/^[A-Za-z_][A-Za-z0-9_]*/;function appendLiteral(parts,value){if(!value)return;let previousPart=parts[parts.length-1];if(previousPart?.type==="literal"){previousPart.value+=value;return}parts.push({type:"literal",value})}function parseConfigValueTemplate(config){let parts=[],index=0;for(;index<config.length;){let dollarIndex=config.indexOf("$",index);if(dollarIndex<0){appendLiteral(parts,config.slice(index));break}appendLiteral(parts,config.slice(index,dollarIndex));let nextChar=config[dollarIndex+1];if(nextChar==="$"||nextChar==="!"){appendLiteral(parts,nextChar),index=dollarIndex+2;continue}if(nextChar==="{"){let endIndex=config.indexOf("}",dollarIndex+2);if(endIndex<0){appendLiteral(parts,"$"),index=dollarIndex+1;continue}let name=config.slice(dollarIndex+2,endIndex);ENV_VAR_NAME_RE.test(name)?parts.push({type:"env",name}):appendLiteral(parts,config.slice(dollarIndex,endIndex+1)),index=endIndex+1;continue}let match=config.slice(dollarIndex+1).match(ENV_VAR_NAME_PREFIX_RE);if(match){parts.push({type:"env",name:match[0]}),index=dollarIndex+1+match[0].length;continue}appendLiteral(parts,"$"),index=dollarIndex+1}return parts}function parseConfigValueReference(config){return config.startsWith("!")?{type:"command",config}:{type:"template",parts:parseConfigValueTemplate(config)}}function resolveEnvConfigValue(name,env){return env?.[name]||process.env[name]||void 0}function getTemplateEnvVarNames(parts){let names=[];for(let part of parts)part.type!=="env"||names.includes(part.name)||names.push(part.name);return names}function resolveTemplate(parts,env){let resolved="";for(let part of parts){if(part.type==="literal"){resolved+=part.value;continue}let envValue=resolveEnvConfigValue(part.name,env);if(envValue===void 0)return;resolved+=envValue}return resolved}function getConfigValueEnvVarNames(config){let reference=parseConfigValueReference(config);return reference.type==="template"?getTemplateEnvVarNames(reference.parts):[]}function getMissingConfigValueEnvVarNames(config,env){return getConfigValueEnvVarNames(config).filter(name=>resolveEnvConfigValue(name,env)===void 0)}function isCommandConfigValue(config){return parseConfigValueReference(config).type==="command"}function isConfigValueConfigured(config,env){return getMissingConfigValueEnvVarNames(config,env).length===0}function resolveConfigValue(config,env){let reference=parseConfigValueReference(config);return reference.type==="command"?env===void 0?executeCommand(reference.config):runConfigCommand(reference.config,env):Promise.resolve(resolveTemplate(reference.parts,env))}function executeCommand(commandConfig){let cached=commandResultCache.get(commandConfig);if(cached)return cached;let result=runConfigCommand(commandConfig);return commandResultCache.set(commandConfig,result),result}function resolveConfigValueUncached(config,env){let reference=parseConfigValueReference(config);return reference.type==="command"?runConfigCommand(reference.config,env):Promise.resolve(resolveTemplate(reference.parts,env))}async function resolveConfigValueOrThrow(config,description,env){let resolvedValue=await resolveConfigValueUncached(config,env);if(resolvedValue!==void 0)return resolvedValue;let reference=parseConfigValueReference(config);if(reference.type==="command")throw new Error(`Failed to resolve ${description} from shell command: ${reference.config.slice(1)}`);if(reference.type==="template"){let missingEnvVars=getMissingConfigValueEnvVarNames(config,env);if(missingEnvVars.length===1)throw new Error(`Failed to resolve ${description} from environment variable: ${missingEnvVars[0]}`);if(missingEnvVars.length>1)throw new Error(`Failed to resolve ${description} from environment variables: ${missingEnvVars.join(", ")}`)}throw new Error(`Failed to resolve ${description}`)}async function resolveHeadersOrThrow(headers,description,env){if(!headers)return;let resolved={};for(let[key,value]of Object.entries(headers))resolved[key]=await resolveConfigValueOrThrow(value,`${description} header "${key}"`,env);return Object.keys(resolved).length>0?resolved:void 0}export{sleep,getConfigValueEnvVarNames,isCommandConfigValue,isConfigValueConfigured,resolveConfigValue,resolveConfigValueOrThrow,resolveHeadersOrThrow,isCommittedRotationOutput,isRotationStreamStart,rotationErrorFromEvent,rendezvousOrder,usageLimitResetMs,classifyCredentialFailure,CredentialFailoverError,runCredentialFailover};
|
|
2
|
+
import{rateLimitModelFamily}from"./chunk-F6EQ7EV3.js";import{getShellConfig}from"./chunk-JEZWV7JW.js";import{getOverflowPatterns}from"./chunk-TALS4X7S.js";import{normalizeProviderError}from"./chunk-TAV6QZFM.js";import{extract429RetryAfterMs}from"./chunk-PELNNWGO.js";import{PROVIDER_NOT_CONFIGURED_PREFIX,USAGE_LIMIT_EXHAUSTION}from"./chunk-XL5KIYQF.js";var PRE_COMMIT_EVENT_TYPES=new Set(["start","text_start","thinking_start","toolcall_start"]);function isCommittedRotationOutput(event){return!PRE_COMMIT_EVENT_TYPES.has(event.type)}function isRotationStreamStart(event){return event.type==="start"}function rotationErrorFromEvent(event){if(event.type!=="error")return;let failure=new Error(event.error.errorMessage??"provider stream error"),status=event.error.providerDiagnostic?.httpStatus;return status===void 0?failure:Object.assign(failure,{status})}function rendezvousOrder(key,slots,hasher){return[...slots].map(slot=>({slot,score:hasher(`${key}\0${slot.name}`)})).sort((left,right)=>right.score>left.score?1:right.score<left.score?-1:0).map(({slot})=>slot)}var DEFAULT_SLOT_BLOCK_MS=6e4,MAX_SLOT_BLOCK_MS=2880*60*1e3;var MONTHS=["jan","feb","mar","apr","may","jun","jul","aug","sep","oct","nov","dec"],RESET_AT_KEYS=new Set(["resets_at"]),RESET_AFTER_SECONDS_KEYS=new Set(["reset_after_seconds"]),RELATIVE_RE=/\b(?:resets?|try again|retry)\s+in\s+~?((?:\d+(?:\.\d+)?\s*(?:days?|d|hours?|hrs?|h|minutes?|mins?|m|seconds?|secs?|s)\b(?:\s*,?\s*(?:and\s+)?)?)+)/i,RELATIVE_PART_RE=/(\d+(?:\.\d+)?)\s*(days?|d|hours?|hrs?|h|minutes?|mins?|m|seconds?|secs?|s)\b/gi,CLOCK_RE=/\b(?:resets?|try again)\s+(?:at\s+|on\s+)?(?:([a-z]{3})[a-z]*\.?\s+(\d{1,2}),?\s+(?:at\s+)?)?(\d{1,2})(?::(\d{2}))?\s*([ap])\.?\s?m\b\.?(?:\s*\(([A-Za-z_]+(?:\/[A-Za-z0-9_+-]+)*)\))?/i;function usageLimitResetMs(text,nowMs){return fromJsonFields(text,nowMs)??fromRelativeProse(text)??fromClockProse(text,nowMs)}function fromJsonFields(text,nowMs){let start=text.indexOf("{");if(start<0)return;let parsed;try{parsed=JSON.parse(text.slice(start))}catch{return}let found;return walk(parsed,(key,value)=>{let ms=RESET_AT_KEYS.has(key)?absoluteFieldMs(value,nowMs):RESET_AFTER_SECONDS_KEYS.has(key)?secondsFieldMs(value):void 0;ms!==void 0&&(found===void 0||ms>found)&&(found=ms)}),found}function walk(value,visit){if(Array.isArray(value)){for(let item of value)walk(item,visit);return}if(!(typeof value!="object"||value===null))for(let[key,entry]of Object.entries(value))visit(key,entry),walk(entry,visit)}function absoluteFieldMs(value,nowMs){if(typeof value=="number"&&Number.isFinite(value)&&value>0){let epochMs=value<1e12?value*1e3:value;return Math.max(0,Math.ceil(epochMs-nowMs))}if(typeof value=="string"&&/\d{4}-\d{2}-\d{2}T/.test(value)){let epochMs=Date.parse(value);return Number.isNaN(epochMs)?void 0:Math.max(0,epochMs-nowMs)}}function secondsFieldMs(value){return typeof value=="number"&&Number.isFinite(value)&&value>=0?Math.ceil(value*1e3):void 0}function fromRelativeProse(text){let phrase=RELATIVE_RE.exec(text)?.[1];if(phrase===void 0)return;let total=0;for(let[,amount,unit]of phrase.matchAll(RELATIVE_PART_RE))total+=Number.parseFloat(amount??"0")*unitMs(unit??"");return Math.ceil(total)}function unitMs(unit){let u=unit.toLowerCase();return u.startsWith("d")?864e5:u.startsWith("h")?36e5:u==="s"||u.startsWith("sec")?1e3:6e4}function fromClockProse(text,nowMs){let match=CLOCK_RE.exec(text);if(!match)return;let[,monthName,dayText,hourText,minuteText,meridiem,zoneText]=match,hour12=Number.parseInt(hourText??"",10),minute=minuteText===void 0?0:Number.parseInt(minuteText,10);if(hour12<1||hour12>12||minute>59)return;let hour=hour12%12+(meridiem?.toLowerCase()==="p"?12:0),zone=zoneText??Intl.DateTimeFormat().resolvedOptions().timeZone;if(!isValidTimeZone(zone))return;let today=zonedParts(zone,nowMs);if(monthName!==void 0){let month=MONTHS.indexOf(monthName.toLowerCase()),day=Number.parseInt(dayText??"",10);if(month<0||day<1||day>31)return;let target2=zonedToEpoch(zone,today.year,month,day,hour,minute);return target2<=nowMs&&(target2=zonedToEpoch(zone,today.year+1,month,day,hour,minute)),target2-nowMs}let target=zonedToEpoch(zone,today.year,today.month,today.day,hour,minute);return target<=nowMs&&(target=zonedToEpoch(zone,today.year,today.month,today.day+1,hour,minute)),target-nowMs}function isValidTimeZone(zone){try{return new Intl.DateTimeFormat("en-US",{timeZone:zone}),!0}catch{return!1}}function zonedParts(zone,epochMs){let parts=new Intl.DateTimeFormat("en-US",{timeZone:zone,hourCycle:"h23",year:"numeric",month:"numeric",day:"numeric",hour:"numeric",minute:"numeric",second:"numeric"}).formatToParts(epochMs),get=type=>Number.parseInt(parts.find(part=>part.type===type)?.value??"0",10);return{year:get("year"),month:get("month")-1,day:get("day"),hour:get("hour"),minute:get("minute"),second:get("second")}}function zoneOffsetMs(zone,epochMs){let p=zonedParts(zone,epochMs);return Date.UTC(p.year,p.month,p.day,p.hour,p.minute,p.second)-Math.floor(epochMs/1e3)*1e3}function zonedToEpoch(zone,year,month,day,hour,minute){let wall=Date.UTC(year,month,day,hour,minute),first=wall-zoneOffsetMs(zone,wall);return wall-zoneOffsetMs(zone,first)}function escapeRegExp(text){return text.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}var ACCOUNT_USAGE_LIMIT_TEXT=new RegExp([...USAGE_LIMIT_EXHAUSTION.markers.map(escapeRegExp),String.raw`\b(?:hit|reached)\s+your\b[^.]*?\blimit\b`,String.raw`\busage\s+limit\s+reached\b`,String.raw`\b(?:Go|Free)UsageLimitError\b`,String.raw`\bblocking_limit\b`,String.raw`\brapid_refill_breaker\b`,String.raw`\bquota\s+exceeded\b`].join("|"),"i");function isAccountUsageLimitText(text){return ACCOUNT_USAGE_LIMIT_TEXT.test(text)}var COOLDOWN_BASE_MS=DEFAULT_SLOT_BLOCK_MS,COOLDOWN_CAP_MS=MAX_SLOT_BLOCK_MS,RETRY_SAME_MAX_ATTEMPTS=2;function rateLimitCooldown(failureCount,serverHintMs,policy={}){let cap=policy.capMs??COOLDOWN_CAP_MS,base=policy.baseMs??COOLDOWN_BASE_MS,backoff=Math.min(cap,base*2**Math.max(0,failureCount)),floored=serverHintMs===void 0?backoff:Math.max(backoff,serverHintMs);return{cooldownMs:Math.min(cap,floored),retryAfterWasCapped:floored>cap}}var INVALID_KEY_TEXT=/invalid[ _-]?(?:api[ _-]?)?key|authentication[_ ]?error|invalid x-api-key|unauthorized/i,ACCOUNT_SCOPED_403_TEXT=/account|credential|token|api[ _-]?key|organization|subscription/i,RATE_LIMIT_TEXT=/rate[ _-]?limit|too many requests|resource_exhausted/i,BILLING_TEXT=/billing|credits?[ _-]?(?:required|exhausted|balance)|insufficient[ _-]?(?:funds|quota|credit)|payment[ _-]?required|quota[ _-]?exhausted/i,OVERLOAD_TEXT=/overloaded/i,NETWORK_TEXT=/econnreset|econnrefused|etimedout|enotfound|socket hang up|fetch failed|network error|request timed out/i,WEBSOCKET_REQUEST_FAULT_TEXT=/websocket closed 100[89]\b/i,WEBSOCKET_TRANSPORT_FAULT_TEXT=/websocket (?:closed|error|connect timeout|liveness timeout)/i,FAIL_FAST_TEXT=/context[ _-]?(?:length|window)|maximum context|invalid[ _-]?model|model[ _-]?not[ _-]?found|malformed[ _-]?stream|premature[ _-]?(?:close|stream)/i,ABORT_TEXT=/\baborted?\b/i;function isAbort(error,message){return error instanceof Error&&error.name==="AbortError"?!0:ABORT_TEXT.test(message)}function isOverflowText(text){return getOverflowPatterns().some(pattern=>pattern.test(text))}function classifyCredentialFailure(error,context={}){let normalized=normalizeProviderError(error),text=normalized.messageCarriesBody?normalized.message:`${normalized.message} ${normalized.body??""}`,status=normalized.status,failureCount=context.failureCount??0;if(isAbort(error,text))return{kind:"fail_request"};if(text.includes(PROVIDER_NOT_CONFIGURED_PREFIX))return{kind:"failover",block:{reason:"auth_error"}};if(status===401||INVALID_KEY_TEXT.test(text))return{kind:"failover",block:{reason:"auth_error"}};if(status===403)return ACCOUNT_SCOPED_403_TEXT.test(text)?{kind:"failover",block:{reason:"auth_error"}}:{kind:"fail_request"};if(status===402||BILLING_TEXT.test(text))return{kind:"failover",block:{reason:"account_disabled"}};let usageLimit=isAccountUsageLimitText(text)&&!isOverflowText(text);if(status===429||RATE_LIMIT_TEXT.test(text)||usageLimit){let nowMs=context.nowMs??Date.now(),hint=extract429RetryAfterMs({status:status??429,bodyText:text},nowMs)??(usageLimit?normalized.retryAfterMs??usageLimitResetMs(text,nowMs):void 0),modelFamily=rateLimitModelFamily(text);return{kind:"failover",block:{reason:"rate_limit",...rateLimitCooldown(failureCount,hint,{baseMs:context.cooldownBaseMs,capMs:context.cooldownCapMs}),...modelFamily===void 0?{}:{modelFamily}}}}return isOverflowText(text)||status===400||status===404||FAIL_FAST_TEXT.test(text)?{kind:"fail_request"}:WEBSOCKET_REQUEST_FAULT_TEXT.test(text)?{kind:"fail_request"}:WEBSOCKET_TRANSPORT_FAULT_TEXT.test(text)?{kind:"retry_same",maxAttempts:RETRY_SAME_MAX_ATTEMPTS}:status===529||OVERLOAD_TEXT.test(text)||status!==void 0&&status>=500&&status<600?{kind:"retry_same",maxAttempts:RETRY_SAME_MAX_ATTEMPTS}:status===408||NETWORK_TEXT.test(text)?{kind:"retry_same",maxAttempts:RETRY_SAME_MAX_ATTEMPTS}:{kind:"fail_request"}}var CredentialFailoverError=class extends Error{constructor(action,original,options={}){let detail=original instanceof Error?original.message:String(original);super(detail,{cause:original}),this.name="CredentialFailoverError",this.action=action,this.original=original,this.retryAt=options.retryAt}};function isAvailable(slot,now){return!(slot.blockReason==="auth_error"||slot.blockReason==="account_disabled"||slot.blockedUntil!==void 0&&slot.blockedUntil>now)}function soonestRetryAt(slots,now){let deadlines=slots.map(slot=>slot.blockedUntil).filter(value=>value!==void 0&&value>now);return deadlines.length===0?void 0:Math.min(...deadlines)}async function settle(stream){let iterator=stream[Symbol.asyncIterator]();try{await iterator.return?.(void 0)}catch{}}async function*runCredentialFailover(options){let now=options.now??Date.now,classify=options.classify??classifyCredentialFailure,attempted=new Set,retriesBySlot=new Map,lastError,lastOriginal,lastTerminalEvent,startAnnounced=!1;for(;;){let slots=await options.listSlots(),candidates=slots.filter(slot2=>!attempted.has(slot2.name)&&isAvailable(slot2,now()));if(candidates.length===0){if(lastTerminalEvent!==void 0){yield lastTerminalEvent;return}let retryAt=soonestRetryAt(slots,now());throw lastError!==void 0&&lastOriginal!==void 0?new CredentialFailoverError(lastError.action,lastOriginal,retryAt===void 0?{}:{retryAt}):new CredentialFailoverError({kind:"fail_request"},new Error("No credential slots available"),retryAt===void 0?{}:{retryAt})}let slot=options.select(candidates),committedOutput=!1,terminalEvent,attemptStream;try{attemptStream=await options.runAttempt(slot);for await(let event of attemptStream){let failure=options.errorFromEvent?.(event);if(failure!==void 0)throw terminalEvent=event,failure;if(options.isStreamStart?.(event)){if(startAnnounced)continue;startAnnounced=!0}committedOutput||=options.isCommittedOutput(event),yield event}await options.onSuccess?.(slot);return}catch(error){attemptStream&&await settle(attemptStream);let failureCount=(slot.failureCount??0)+(retriesBySlot.get(slot.name)??0),action=classify(error,{failureCount});if(lastOriginal=error,lastTerminalEvent=terminalEvent,action.kind==="retry_same"&&!committedOutput){let used=(retriesBySlot.get(slot.name)??0)+1;if(retriesBySlot.set(slot.name,used),used<action.maxAttempts)continue;if(terminalEvent!==void 0){yield terminalEvent;return}throw new CredentialFailoverError(action,error)}if(action.kind!=="failover"){if(terminalEvent!==void 0){yield terminalEvent;return}throw new CredentialFailoverError(action,error)}await options.persistBlock(slot,action.block),attempted.add(slot.name);let failure=new CredentialFailoverError(action,error);if(lastError=failure,await options.onRotate?.({slot,block:action.block,attempt:attempted.size,committedOutput}),committedOutput){if(terminalEvent!==void 0){yield terminalEvent;return}throw failure}}}}function sleep(ms,signal){return new Promise((resolve,reject)=>{if(signal?.aborted){reject(new Error("Aborted"));return}let timeout=setTimeout(resolve,ms);signal?.addEventListener("abort",()=>{clearTimeout(timeout),reject(new Error("Aborted"))})})}import{spawn}from"child_process";var COMMAND_EXECUTION_MAX_ATTEMPTS=3,COMMAND_EXECUTION_BACKOFF_MS=[250,1e3],COMMAND_TIMEOUT_MS=1e4,COMMAND_MAX_OUTPUT_BYTES=1024*1024;function runCommandProcess(file,args,options){return new Promise(resolveOutcome=>{let spawnOptions={shell:options.shell,windowsHide:!0,...options.env===void 0?{}:{env:{...process.env,...options.env}}},child=options.stdin===void 0?spawn(file,[...args],{...spawnOptions,stdio:["ignore","pipe","ignore"]}):spawn(file,[...args],{...spawnOptions,stdio:["pipe","pipe","ignore"]}),stdout="",settled=!1,finish=outcome=>{settled||(settled=!0,clearTimeout(timer),resolveOutcome(outcome))},timer=setTimeout(()=>{child.kill("SIGTERM"),child.unref(),finish({executed:!0,value:void 0})},COMMAND_TIMEOUT_MS);child.stdout.setEncoding("utf-8"),child.stdout.on("data",chunk=>{stdout+=chunk,!(stdout.length<=COMMAND_MAX_OUTPUT_BYTES)&&(child.kill("SIGTERM"),finish({executed:!0,value:void 0}))}),child.on("error",error=>finish({executed:error.code!=="ENOENT",value:void 0})),child.on("close",code=>{let value=stdout.trim();finish({executed:!0,value:code===0&&value?value:void 0})}),child.stdin?.end(options.stdin)})}async function executeWithConfiguredShell(command,env){try{let{shell,args,commandTransport}=getShellConfig(),commandFromStdin=commandTransport==="stdin";return await runCommandProcess(shell,commandFromStdin?args:[...args,command],{shell:!1,...commandFromStdin?{stdin:command}:{},...env===void 0?{}:{env}})}catch{return{executed:!1,value:void 0}}}async function executeCommandOnce(command,env){if(process.platform==="win32"){let configured=await executeWithConfiguredShell(command,env);if(configured.executed)return configured.value}return(await runCommandProcess(command,[],{shell:!0,...env===void 0?{}:{env}})).value}async function runConfigCommand(commandConfig,env){let command=commandConfig.slice(1);for(let attempt=0;attempt<COMMAND_EXECUTION_MAX_ATTEMPTS;attempt++){let value=await executeCommandOnce(command,env);if(value!==void 0)return value;let backoffMs=COMMAND_EXECUTION_BACKOFF_MS[attempt];backoffMs!==void 0&&await sleep(backoffMs)}}var commandResultCache=new Map,ENV_VAR_NAME_RE=/^[A-Za-z_][A-Za-z0-9_]*$/,ENV_VAR_NAME_PREFIX_RE=/^[A-Za-z_][A-Za-z0-9_]*/;function appendLiteral(parts,value){if(!value)return;let previousPart=parts[parts.length-1];if(previousPart?.type==="literal"){previousPart.value+=value;return}parts.push({type:"literal",value})}function parseConfigValueTemplate(config){let parts=[],index=0;for(;index<config.length;){let dollarIndex=config.indexOf("$",index);if(dollarIndex<0){appendLiteral(parts,config.slice(index));break}appendLiteral(parts,config.slice(index,dollarIndex));let nextChar=config[dollarIndex+1];if(nextChar==="$"||nextChar==="!"){appendLiteral(parts,nextChar),index=dollarIndex+2;continue}if(nextChar==="{"){let endIndex=config.indexOf("}",dollarIndex+2);if(endIndex<0){appendLiteral(parts,"$"),index=dollarIndex+1;continue}let name=config.slice(dollarIndex+2,endIndex);ENV_VAR_NAME_RE.test(name)?parts.push({type:"env",name}):appendLiteral(parts,config.slice(dollarIndex,endIndex+1)),index=endIndex+1;continue}let match=config.slice(dollarIndex+1).match(ENV_VAR_NAME_PREFIX_RE);if(match){parts.push({type:"env",name:match[0]}),index=dollarIndex+1+match[0].length;continue}appendLiteral(parts,"$"),index=dollarIndex+1}return parts}function parseConfigValueReference(config){return config.startsWith("!")?{type:"command",config}:{type:"template",parts:parseConfigValueTemplate(config)}}function resolveEnvConfigValue(name,env){return env?.[name]||process.env[name]||void 0}function getTemplateEnvVarNames(parts){let names=[];for(let part of parts)part.type!=="env"||names.includes(part.name)||names.push(part.name);return names}function resolveTemplate(parts,env){let resolved="";for(let part of parts){if(part.type==="literal"){resolved+=part.value;continue}let envValue=resolveEnvConfigValue(part.name,env);if(envValue===void 0)return;resolved+=envValue}return resolved}function getConfigValueEnvVarNames(config){let reference=parseConfigValueReference(config);return reference.type==="template"?getTemplateEnvVarNames(reference.parts):[]}function getMissingConfigValueEnvVarNames(config,env){return getConfigValueEnvVarNames(config).filter(name=>resolveEnvConfigValue(name,env)===void 0)}function isCommandConfigValue(config){return parseConfigValueReference(config).type==="command"}function isConfigValueConfigured(config,env){return getMissingConfigValueEnvVarNames(config,env).length===0}function resolveConfigValue(config,env){let reference=parseConfigValueReference(config);return reference.type==="command"?env===void 0?executeCommand(reference.config):runConfigCommand(reference.config,env):Promise.resolve(resolveTemplate(reference.parts,env))}function executeCommand(commandConfig){let cached=commandResultCache.get(commandConfig);if(cached)return cached;let result=runConfigCommand(commandConfig);return commandResultCache.set(commandConfig,result),result}function resolveConfigValueUncached(config,env){let reference=parseConfigValueReference(config);return reference.type==="command"?runConfigCommand(reference.config,env):Promise.resolve(resolveTemplate(reference.parts,env))}async function resolveConfigValueOrThrow(config,description,env){let resolvedValue=await resolveConfigValueUncached(config,env);if(resolvedValue!==void 0)return resolvedValue;let reference=parseConfigValueReference(config);if(reference.type==="command")throw new Error(`Failed to resolve ${description} from shell command: ${reference.config.slice(1)}`);if(reference.type==="template"){let missingEnvVars=getMissingConfigValueEnvVarNames(config,env);if(missingEnvVars.length===1)throw new Error(`Failed to resolve ${description} from environment variable: ${missingEnvVars[0]}`);if(missingEnvVars.length>1)throw new Error(`Failed to resolve ${description} from environment variables: ${missingEnvVars.join(", ")}`)}throw new Error(`Failed to resolve ${description}`)}async function resolveHeadersOrThrow(headers,description,env){if(!headers)return;let resolved={};for(let[key,value]of Object.entries(headers))resolved[key]=await resolveConfigValueOrThrow(value,`${description} header "${key}"`,env);return Object.keys(resolved).length>0?resolved:void 0}export{sleep,getConfigValueEnvVarNames,isCommandConfigValue,isConfigValueConfigured,resolveConfigValue,resolveConfigValueOrThrow,resolveHeadersOrThrow,isCommittedRotationOutput,isRotationStreamStart,rotationErrorFromEvent,rendezvousOrder,usageLimitResetMs,classifyCredentialFailure,CredentialFailoverError,runCredentialFailover};
|
|
@@ -0,0 +1,7 @@
|
|
|
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{getAgentDir}from"./chunk-463OK2Y4.js";import{existsSync,realpathSync}from"node:fs";import{basename,dirname,join,resolve}from"node:path";function canonicalSessionPath(path){let absolutePath=resolve(path),missing=[],existing=absolutePath;for(;!existsSync(existing);){let parent=dirname(existing);if(parent===existing)return absolutePath;missing.unshift(basename(existing)),existing=parent}try{return join(realpathSync(existing),...missing)}catch{return absolutePath}}function sessionDirectoryRemoved(sessionFile){return!existsSync(dirname(sessionFile))}import{createHash,randomUUID}from"node:crypto";import{chmod,link,mkdir,readFile,rename,rm,writeFile}from"node:fs/promises";import{basename as basename2,dirname as dirname2,join as join2,win32}from"node:path";var HOST_DAEMON_LAYOUT=2,HOST_DAEMON_DIR_ENV="SENPI_RPC_HOST_DAEMON_DIR",ENDPOINT_REGISTRY_VERSION=1,DIRECTORY_MODE=448,HOST_STATE_FILE_MODE=384;function canonicalEndpointPath(socket,platform=process.platform){return platform==="win32"?win32.normalize(socket).toLowerCase():socket.startsWith("\0")?socket:join2(canonicalSessionPath(dirname2(socket)),basename2(socket))}function daemonDirectoryName(socket,platform=process.platform){return directoryNameOf(canonicalEndpointPath(socket,platform))}function sameEndpoint(socket,other){return socket===other||canonicalEndpointPath(socket)===canonicalEndpointPath(other)}function socketNamesDirectory(socket,name){return daemonDirectoryName(socket)===name||process.platform!=="win32"&&directoryNameOf(socket)===name}function directoryNameOf(endpoint){return createHash("sha256").update(endpoint,"utf8").digest("hex").slice(0,16)}function shardKey(kind,ownerId){return createHash("sha256").update(`${kind}:${ownerId}`,"utf8").digest("hex").slice(0,16)}function shardSocketPathForKey(root,kind,key){return join2(root,`${kind}-${key}.sock`)}function shardSocketPath(root,kind,ownerId){return shardSocketPathForKey(root,kind,shardKey(kind,ownerId))}var SHARD_SOCKET_NAME=/^(p|i)-([0-9a-f]{16})\.sock$/;function parseShardSocket(socket){let match=SHARD_SOCKET_NAME.exec(basename2(socket)),key=match?.[2];return key===void 0?null:{kind:match?.[1]==="i"?"i":"p",key}}function createHostDaemonPaths(target){let flatDir=join2(target.agentDir??getAgentDir(),"rpc-host-daemon");return{socket:target.socket,flatDir,layoutMarker:join2(flatDir,"layout.json"),legacyPidFile:join2(flatDir,"host.pid"),...hostDaemonDirectoryPaths(join2(flatDir,daemonDirectoryName(target.socket)))}}function hostDaemonDirectoryPaths(dir){return{dir,endpointFile:join2(dir,"endpoint.json"),pointerFile:join2(dir,"host.pid"),lockFile:join2(dir,"daemon.lock"),settingsFile:join2(dir,"settings.json"),stderrLog:join2(dir,"stderr.log"),generationsDir:join2(dir,"generations"),reservationsDir:join2(dir,"reservations")}}function generationPaths(paths,instanceId){let dir=join2(paths.generationsDir,instanceId);return{dir,relativeDir:`generations/${instanceId}`,pidFile:join2(dir,"host.pid"),settingsFile:join2(dir,"settings.json"),scratchDir:join2(dir,"scratch")}}var HostDaemonStateError=class extends Error{constructor(path,cause){super(`RPC daemon state directory ${path} is not usable: ${cause instanceof Error?cause.message:cause}`,{cause}),this.name="HostDaemonStateError",this.path=path}};async function createDaemonDirectories(paths,identity={}){try{await mkdir(paths.flatDir,{recursive:!0,mode:DIRECTORY_MODE}),await makePrivateDirectory(paths.dir),await Promise.all([makePrivateDirectory(paths.generationsDir),makePrivateDirectory(paths.reservationsDir),writeFile(paths.layoutMarker,`${JSON.stringify({layout:HOST_DAEMON_LAYOUT,dir:basename2(paths.dir)})}
|
|
3
|
+
`,{mode:HOST_STATE_FILE_MODE})])}catch(cause){throw new HostDaemonStateError(paths.dir,cause)}await ensureEndpointIdentity(paths,paths.socket,identity)}async function makePrivateDirectory(directory){await mkdir(directory,{recursive:!0,mode:DIRECTORY_MODE})===void 0&&await chmod(directory,DIRECTORY_MODE)}async function ensureEndpointIdentity(paths,socket,options={}){let temporary=`${paths.endpointFile}.${process.pid}-${randomUUID()}.tmp`;try{await mkdir(paths.dir,{recursive:!0,mode:DIRECTORY_MODE});let record=`${JSON.stringify({layout:HOST_DAEMON_LAYOUT,registry_version:ENDPOINT_REGISTRY_VERSION,endpoint_kind:options.kind??"rpc_host",socket,created_at:new Date().toISOString()})}
|
|
4
|
+
`;await writeFile(temporary,record,{mode:HOST_STATE_FILE_MODE,flag:"wx"}),!await link(temporary,paths.endpointFile).then(()=>!0,cause=>isErrorCode(cause,"EEXIST")?!1:createExclusively(paths.endpointFile,record))&&options.repair===!0&&!await namesThisDirectory(paths)&&await rename(temporary,paths.endpointFile)}catch(cause){throw new HostDaemonStateError(paths.endpointFile,cause)}finally{await rm(temporary,{force:!0})}}async function createExclusively(path,content){try{return await writeFile(path,content,{mode:HOST_STATE_FILE_MODE,flag:"wx"}),!0}catch(cause){if(isErrorCode(cause,"EEXIST"))return!1;throw cause}}function isErrorCode(cause,code){return cause instanceof Error&&"code"in cause&&cause.code===code}async function namesThisDirectory(paths){let record;try{record=JSON.parse(await readFile(paths.endpointFile,"utf8"))}catch{return!1}return typeof record!="object"||record===null||!("socket"in record)?!1:typeof record.socket=="string"&&record.socket!==""&&socketNamesDirectory(record.socket,basename2(paths.dir))}async function createGenerationDirectory(generation){try{await mkdir(generation.scratchDir,{recursive:!0,mode:DIRECTORY_MODE}),await chmod(generation.dir,DIRECTORY_MODE)}catch(cause){throw new HostDaemonStateError(generation.dir,cause)}}import{execFile}from"node:child_process";function parseDaemonPidFile(text){let parsed;try{parsed=JSON.parse(text)}catch(error){if(error instanceof SyntaxError)return;throw error}let unguarded=parsed!==null&&isRecord(parsed)&&parsed.processStartTime===null;if(!(!isRecord(parsed)||typeof parsed.pid!="number"||!unguarded&&typeof parsed.processStartTime!="string")&&!(!Number.isInteger(parsed.pid)||parsed.pid<=0)){if(unguarded)return{pid:parsed.pid,processStartTime:null};if(!(typeof parsed.processStartTime!="string"||parsed.processStartTime.trim()===""))return{pid:parsed.pid,processStartTime:parsed.processStartTime}}}var ProcessIdentityUnreadableError=class extends Error{constructor(pid,attempts,cause){super(`process identity for live pid ${pid} stayed unreadable after ${attempts} probe attempt(s): ${cause instanceof Error?cause.message:String(cause)}`),this.name="ProcessIdentityUnreadableError",this.pid=pid,this.attempts=attempts,this.cause=cause}};async function processMatchesPidFile(pidFile,readStartTime=readProcessStartTime,isLive=processIsLive,retry={}){if(pidFile.processStartTime===null){if(!isLive(pidFile.pid))return!1;throw new ProcessIdentityUnreadableError(pidFile.pid,0,new Error("pidfile carries no process identity guard"))}let attempts=Math.max(1,retry.attempts??5),delayMs=retry.delayMs??200,lastError;for(let attempt=1;attempt<=attempts;attempt++)try{let current=await readStartTime(pidFile.pid);if(current!==void 0)return current===pidFile.processStartTime;if(!isLive(pidFile.pid))return!1;lastError=new Error("process identity probe returned no identity for a live process"),attempt<attempts&&await new Promise(resolve2=>setTimeout(resolve2,delayMs))}catch(error){if(!isLive(pidFile.pid))return!1;lastError=error,attempt<attempts&&await new Promise(resolve2=>setTimeout(resolve2,delayMs))}throw new ProcessIdentityUnreadableError(pidFile.pid,attempts,lastError)}async function readProcessIdentity(pid,platform=process.platform,timeoutMs,isLive=processIsLive){let command=platform==="win32"?{executable:"powershell.exe",args:["-NoProfile","-NonInteractive","-Command",`$process = Get-CimInstance Win32_Process -Filter "ProcessId=${String(pid)}" -ErrorAction Stop; if ($null -eq $process) { Write-Output '__SENPI_ABSENT__'; exit 0 }; $process.CreationDate.ToFileTimeUtc().ToString("D", [Globalization.CultureInfo]::InvariantCulture)`]}:{executable:"ps",args:["-o","lstart=","-p",String(pid)]};return new Promise(resolve2=>{let effectiveTimeoutMs=timeoutMs??(platform==="win32"?1e3:void 0);execFile(command.executable,command.args,{windowsHide:!0,...effectiveTimeoutMs===void 0?{}:{timeout:effectiveTimeoutMs}},(error,stdout)=>{if(error){let code="code"in error?error.code:void 0;if(platform!=="win32"&&code===1||!isLive(pid)){resolve2({kind:"absent"});return}resolve2({kind:"error",error});return}let output=stdout.trim();if(output==="__SENPI_ABSENT__")return resolve2({kind:"absent"});if(!output||platform==="win32"&&!/^\d+$/.test(output))return resolve2({kind:"error",error:new Error("invalid process identity output")});resolve2({kind:"present",identity:output})}).once("error",error=>resolve2({kind:"error",error}))})}async function stopValidatedPid(pidFile,signal){if(await processMatchesPidFile(pidFile)){try{process.kill(pidFile.pid,signal)}catch(error){if(!isNodeErrorCode(error,"ESRCH"))throw error}signal==="SIGTERM"&&await waitForGone(pidFile,1e4),signal==="SIGKILL"&&await waitForGone(pidFile,2e3)}}async function waitForGone(pidFile,timeoutMs){let deadline=Date.now()+timeoutMs;for(;Date.now()<=deadline;){if(!await processMatchesPidFile(pidFile))return!0;await delay(100)}return!await processMatchesPidFile(pidFile)}async function readProcessStartTime(pid,platform=process.platform,timeoutMs){return readProcessIdentity(pid,platform,timeoutMs).then(result=>{if(result.kind==="error")throw result.error;return result.kind==="present"?result.identity:void 0})}function processIsLive(pid){try{return process.kill(pid,0),!0}catch(error){if(isNodeErrorCode(error,"ESRCH"))return!1;if(isNodeErrorCode(error,"EPERM"))return!0;throw error}}async function waitForStartTime(pid,timeoutMs,readStartTime=readProcessStartTime,isLive=processIsLive){let deadline=Date.now()+timeoutMs;for(;Date.now()<=deadline;){let startTime;try{startTime=await readStartTime(pid)}catch{}if(startTime)return startTime;await delay(20)}if(!isLive(pid))throw new Error(`spawned daemon pid ${pid} had no process start time`)}function delay(ms){return new Promise(resolveDelay=>setTimeout(resolveDelay,ms))}function isRecord(value){return typeof value=="object"&&value!==null&&!Array.isArray(value)}function isNodeErrorCode(error,code){return error instanceof Error&&"code"in error&&error.code===code}import{createHash as createHash2}from"node:crypto";import{mkdir as mkdir2,readdir,readFile as readFile3,rename as rename2,rm as rm2,writeFile as writeFile3}from"node:fs/promises";import{join as join3}from"node:path";import{readFile as readFile2,writeFile as writeFile2}from"node:fs/promises";async function writeHostSettings(paths,settings){let generation=generationPaths(paths,settings.instanceId);await createGenerationDirectory(generation),await writeStateFile(paths.settingsFile,settings),await writeStateFile(generation.settingsFile,settings)}async function readHostSettings(paths){let parsed=parseJson(await readFileOrUndefined(paths.settingsFile));if(parsed)return{...typeof parsed.coldStart=="string"&&{coldStart:parsed.coldStart},...typeof parsed.idleExitMs=="number"&&{idleExitMs:parsed.idleExitMs}}}async function writeStateFile(path,content){try{await writeFile2(path,`${JSON.stringify(content)}
|
|
5
|
+
`,{mode:HOST_STATE_FILE_MODE})}catch(cause){throw new HostDaemonStateError(path,cause)}}async function readFileOrUndefined(path){try{return await readFile2(path,"utf8")}catch(error){if(isNodeErrorCode2(error,"ENOENT")||isNodeErrorCode2(error,"ENOTDIR"))return;throw error}}function parseJson(text){if(text!==void 0)try{let parsed=JSON.parse(text);return isRecord2(parsed)?parsed:void 0}catch{return}}function isRecord2(value){return typeof value=="object"&&value!==null&&!Array.isArray(value)}function isNodeErrorCode2(error,code){return error instanceof Error&&"code"in error&&error.code===code}var SESSION_PATH_RETRY_AFTER_MS=2e3;function reservationFile(dir,sessionPath){return join3(dir,`${createHash2("sha256").update(sessionPath,"utf8").digest("hex").slice(0,16)}.json`)}function createEndpointReservations(host){let told=process.env[HOST_DAEMON_DIR_ENV],dir=told!==void 0&&told.trim()!==""?told:host.socket===void 0?void 0:createHostDaemonPaths({socket:host.socket,agentDir:host.agentDir}).dir;if(dir!==void 0)return createSessionPathReservations({daemonDir:dir,instanceId:host.instanceId,...host.onFailure?{onFailure:host.onFailure}:{}})}function createSessionPathReservations(options){let paths=hostDaemonDirectoryPaths(options.daemonDir),dir=paths.reservationsDir,pid=options.pid??process.pid,startTime=readProcessStartTime(pid).then(value=>value??null,()=>null),held=new Set,updates=new Map,report=message=>options.onFailure?.(message),publish=async(sessionPath,attached,stillHeld)=>{let owner={instanceId:options.instanceId,pid,processStartTime:await startTime,sessionPath,attached},file=reservationFile(dir,sessionPath);await mkdir2(dir,{recursive:!0,mode:448});let staging=`${file}.${pid}.tmp`;if(await writeFile3(staging,`${JSON.stringify(owner)}
|
|
6
|
+
`,{mode:384}),stillHeld?.()===!1){await rm2(staging,{force:!0});return}await rename2(staging,file)};return{async claim(sessionPath,attached=!0){let existing=await readOwner(reservationFile(dir,sessionPath));if(existing&&existing.pid!==pid){let standing=await standingOwner(existing,paths.pointerFile);if(standing)return standing}try{await publish(sessionPath,attached),held.add(sessionPath)}catch(cause){report(`session path reservation for ${sessionPath} could not be written (${errorMessage(cause)})`)}},async release(sessionPath){held.delete(sessionPath)&&(await updates.get(sessionPath),updates.delete(sessionPath),await rm2(reservationFile(dir,sessionPath),{force:!0}).catch(cause=>{report(`session path reservation for ${sessionPath} could not be removed (${errorMessage(cause)})`)}))},setAttached(sessionPath,attached){if(!held.has(sessionPath))return;let update=(updates.get(sessionPath)??Promise.resolve()).then(()=>publish(sessionPath,attached,()=>held.has(sessionPath))).catch(cause=>{report(`session path reservation for ${sessionPath} could not be updated (${errorMessage(cause)})`)});updates.set(sessionPath,update)}}}async function readSessionPathClaims(dir){let entries=await readdir(dir).catch(()=>[]),claims=[];for(let entry of entries){if(!entry.endsWith(".json"))continue;let file=join3(dir,entry),owner=await readOwner(file);owner&&claims.push({file,owner})}return claims}async function standingOwner(owner,pointerFile){if(!await claimOwnerIsLive(owner))return;let current=await currentInstanceId(pointerFile)===owner.instanceId;return current||owner.attached!==!1?{...owner,current}:void 0}async function currentInstanceId(pointerFile){let pointer=parseJson(await readFileOrUndefined(pointerFile).catch(()=>{}));return typeof pointer?.instance_id=="string"?pointer.instance_id:void 0}async function readOwner(file){let parsed;try{parsed=JSON.parse(await readFile3(file,"utf8"))}catch{return}if(typeof parsed!="object"||parsed===null)return;let{instanceId,pid,processStartTime,sessionPath,attached}=parsed;if(!(typeof instanceId!="string"||typeof pid!="number"||typeof sessionPath!="string"))return{instanceId,pid,processStartTime:typeof processStartTime=="string"?processStartTime:null,sessionPath,...typeof attached=="boolean"?{attached}:{}}}async function claimOwnerIsLive(owner){if(!processIsLive(owner.pid))return!1;if(owner.processStartTime===null)return!0;let current=await readProcessStartTime(owner.pid).catch(()=>{});return current===void 0||current===owner.processStartTime}function errorMessage(cause){return cause instanceof Error?cause.message:String(cause)}import{rename as rename3,rm as rm4}from"node:fs/promises";import{readdir as readdir3,rm as rm3}from"node:fs/promises";import{readdir as readdir2}from"node:fs/promises";import{readdirSync,readFileSync}from"node:fs";function supportedPlatform(platform){return platform==="darwin"||platform==="linux"?platform:void 0}async function loadProcessTableReader(platform=process.platform,options={}){let supported=supportedPlatform(platform);return supported===void 0||typeof globalThis.Bun>"u"?void 0:supported==="darwin"?await darwinReader(options):linuxReader}var KINFO_PROC_STRIDE=648,KINFO_PID_OFFSET=40,KINFO_PPID_OFFSET=560,KINFO_STAT_OFFSET=36,SZOMB=5,PROC_PIDTASKINFO=4,TASKINFO_RESIDENT_OFFSET=8,TABLE_START_BYTES=1<<20,TABLE_MAX_BYTES=32<<20;function parseKernelProcessTable(table,rowCount,residentKb){if(rowCount<=0||table.byteLength<rowCount*KINFO_PROC_STRIDE)return;let view=new DataView(table.buffer,table.byteOffset,table.byteLength),rows=[],selfSeen=!1;for(let index=0;index<rowCount;index++){let base=index*KINFO_PROC_STRIDE,pid=view.getUint32(base+KINFO_PID_OFFSET,!0);if(!Number.isInteger(pid)||pid<=0)continue;let ppid=view.getUint32(base+KINFO_PPID_OFFSET,!0),zombie=table[base+KINFO_STAT_OFFSET]===SZOMB;if(pid===process.pid){if(ppid!==process.ppid||zombie)return;selfSeen=!0}rows.push({pid,ppid,state:zombie?"Z":"U",rssKb:residentKb(pid)})}return selfSeen?rows:void 0}async function darwinReader(options){let{dlopen,FFIType,ptr}=await import("bun:ffi"),library=dlopen("libSystem.B.dylib",{sysctl:{args:[FFIType.ptr,FFIType.u32,FFIType.ptr,FFIType.ptr,FFIType.ptr,FFIType.i32],returns:FFIType.i32},proc_pidinfo:{args:[FFIType.i32,FFIType.i32,FFIType.u32,FFIType.ptr,FFIType.i32],returns:FFIType.i32}}),mib=new Int32Array([1,14,0]),none=new Uint8Array(1),requested=options.initialTableBytes,table=new Uint8Array(Number.isFinite(requested)&&requested!==void 0&&requested>0?Math.min(Math.floor(requested),TABLE_MAX_BYTES):TABLE_START_BYTES),length=new Uint32Array(1),taskInfo=new Uint8Array(256),taskView=new DataView(taskInfo.buffer),residentKb=pid=>(taskInfo.fill(0),library.symbols.proc_pidinfo(pid,PROC_PIDTASKINFO,0,ptr(taskInfo),taskInfo.byteLength)>0?Math.round(Number(taskView.getBigUint64(TASKINFO_RESIDENT_OFFSET,!0))/1024):0);return()=>{for(;;){if(length[0]=table.byteLength,library.symbols.sysctl(ptr(mib),mib.length,ptr(table),ptr(length),ptr(none),0)!==0){if(table.byteLength>=TABLE_MAX_BYTES)return;let reported=length[0]>table.byteLength?length[0]:0;table=new Uint8Array(Math.min(TABLE_MAX_BYTES,Math.max(table.byteLength*2,reported)));continue}return parseKernelProcessTable(table,Math.floor(length[0]/KINFO_PROC_STRIDE),residentKb)}}}function linuxReader(){let rows=[];for(let entry of readdirSync("/proc")){let pid=Number(entry);if(!Number.isInteger(pid)||pid<=0)continue;let stat2;try{stat2=readFileSync(`/proc/${pid}/stat`,"utf8")}catch{continue}let tail=stat2.slice(stat2.lastIndexOf(")")+2).split(" "),state=tail[0],ppid=Number(tail[1]);if(state===void 0||!Number.isInteger(ppid))continue;let rssPages=Number(tail[21]);rows.push({pid,ppid,state,rssKb:Number.isFinite(rssPages)?Math.round(rssPages*4):0})}return rows}var UNOBSERVED={rss_mb:null,host_rss_mb:null,open_fds:null,zombies:null},readers=new Map;function tableReader(platform){let cached=readers.get(platform);if(cached!==void 0)return cached;let loading=loadProcessTableReader(platform);return readers.set(platform,loading),loading}async function readHostProcessMetrics(pid,platform=process.platform){if(platform==="win32")return UNOBSERVED;let read=await tableReader(platform);if(read===void 0)return UNOBSERVED;let rows=read();if(rows===void 0)return UNOBSERVED;let tree=descendants(rows,pid);return tree.length===0?UNOBSERVED:{rss_mb:residentMegabytes(tree),host_rss_mb:residentMegabytes(tree.filter(row=>row.pid===pid||row.ppid===pid)),open_fds:platform==="linux"?await openDescriptors(tree):null,zombies:tree.filter(row=>row.state.startsWith("Z")).length}}function residentMegabytes(rows){return Math.round(rows.reduce((total,row)=>total+row.rssKb,0)/KILOBYTES_PER_MEGABYTE)}function descendants(rows,root){let tree=rows.filter(row=>row.pid===root);if(tree.length===0)return tree;for(let index=0;index<tree.length;index++){let parent=tree[index].pid;for(let row of rows)row.ppid===parent&&!tree.includes(row)&&tree.push(row)}return tree}var KILOBYTES_PER_MEGABYTE=1024;async function openDescriptors(tree){let total=0,counted=!1;for(let row of tree){let entries=await readdir2(`/proc/${row.pid}/fd`).catch(()=>{});entries!==void 0&&(counted=!0,total+=entries.length)}return counted?total:null}async function pruneDeadGenerations(paths){let pointer=parseJson(await readFileOrUndefined(paths.pointerFile).catch(()=>{})),pointedAt=typeof pointer?.instance_id=="string"?pointer.instance_id:void 0,generations=[];for(let instanceId of await readdir3(paths.generationsDir).catch(()=>[])){let record=parseJson(await readFileOrUndefined(generationPaths(paths,instanceId).pidFile));typeof record?.pid!="number"||processIsLive(record.pid)||(await rm3(generationPaths(paths,instanceId).dir,{recursive:!0,force:!0}).catch(()=>{}),generations.push(instanceId))}let pointerRemoved=pointedAt!==void 0&&generations.includes(pointedAt);pointerRemoved&&await rm3(paths.pointerFile,{force:!0}).catch(()=>{});let claims=[];for(let claim of await readSessionPathClaims(paths.reservationsDir))await claimOwnerIsLive(claim.owner)||(await rm3(claim.file,{force:!0}).catch(()=>{}),claims.push(claim.owner.sessionPath));return{generations,claims,pointer:pointerRemoved}}function memoryOf(metrics){return{rss_mb:metrics.rss_mb,host_rss_mb:metrics.host_rss_mb}}async function readGenerationRows(paths,options={}){let pointer=parseJson(await readFileOrUndefined(paths.pointerFile).catch(()=>{})),currentId=typeof pointer?.instance_id=="string"?pointer.instance_id:void 0,claims=await readSessionPathClaims(paths.reservationsDir),rows=[];for(let instanceId of await readdir3(paths.generationsDir).catch(()=>[])){let record=parseJson(await readFileOrUndefined(generationPaths(paths,instanceId).pidFile));if(typeof record?.pid!="number")continue;let alive=processIsLive(record.pid);!alive&&options.includeDead!==!0||rows.push({instanceId,generation:typeof record.generation=="number"?record.generation:0,pid:record.pid,engineVersion:typeof record.engineVersion=="string"?record.engineVersion:null,...alive?memoryOf(await readHostProcessMetrics(record.pid)):{rss_mb:null,host_rss_mb:null},sessions:claims.filter(claim=>claim.owner.instanceId===instanceId).length,current:instanceId===currentId,alive})}return rows.sort((left,right)=>left.generation-right.generation)}async function readHostRegistration(paths){let pointer=parseJson(await readFileOrUndefined(paths.pointerFile));if(!pointer||typeof pointer.instance_id!="string")return;let text=await readFileOrUndefined(generationPaths(paths,pointer.instance_id).pidFile),record=text===void 0?void 0:parseDaemonPidFile(text);if(record===void 0)return;let parsed=parseJson(text)??{},writer=parseWriter(parsed);return{record,...writer&&{writer},...typeof parsed.socket=="string"&&{socket:parsed.socket},instanceId:pointer.instance_id,generation:typeof parsed.generation=="number"?parsed.generation:0}}async function writeHostRegistration(paths,registration,options={}){options.fresh!==!0&&await pruneDeadGenerations(paths);let{generation,writer}=await writeGenerationRecord(paths,registration);await writeStateFile(`${paths.pointerFile}.${process.pid}.tmp`,{layout:HOST_DAEMON_LAYOUT,instance_id:registration.instanceId,generation_dir:generation.relativeDir,writer}),await rename3(`${paths.pointerFile}.${process.pid}.tmp`,paths.pointerFile)}async function writeGenerationRecord(paths,registration){let generation=generationPaths(paths,registration.instanceId),writer={pid:process.pid,startTime:await thisProcessStartTime()},{build}=registration;return await createGenerationDirectory(generation),await writeStateFile(generation.pidFile,{...registration.record,instance_id:registration.instanceId,generation:registration.generation,...build&&{engineVersion:build.text,engineOrdinal:build.ordinal},launchProfileId:registration.launchProfileId,socket:registration.socket,writer}),{generation,writer}}async function clearHostRegistration(paths){let pointer=parseJson(await readFileOrUndefined(paths.pointerFile));typeof pointer?.instance_id=="string"&&await rm4(generationPaths(paths,pointer.instance_id).dir,{recursive:!0,force:!0}),await rm4(paths.settingsFile,{force:!0}),await rm4(paths.pointerFile,{force:!0})}async function releaseGeneration(paths,owner){let generation=generationPaths(paths,owner.instanceId),record=parseDaemonPidFile(await readFileOrUndefined(generation.pidFile)??"");if(record!==void 0&&record.pid!==owner.pid)return;if(owner.superseded===!0){await rm4(generation.dir,{recursive:!0,force:!0});return}let ownsPointer=parseJson(await readFileOrUndefined(paths.pointerFile))?.instance_id===owner.instanceId;ownsPointer&&await rm4(paths.settingsFile,{force:!0}),await rm4(generation.dir,{recursive:!0,force:!0}),ownsPointer&&await rm4(paths.pointerFile,{force:!0})}async function provenOwner(registered,socket){let record=registered?.record;if(!record||record.processStartTime===null||registered?.socket!==void 0&&!sameEndpoint(registered.socket,socket))return;let identity={pid:record.pid,processStartTime:record.processStartTime};return await processMatchesPidFile(identity,readProcessStartTime).catch(()=>!1)?{...identity,instanceId:registered.instanceId}:void 0}async function writtenByThisProcess(writer,readStartTime){if(writer===void 0||writer.pid!==process.pid||writer.startTime===null)return!1;let startTime=readStartTime?await readStartTime(process.pid).then(value=>value??null,()=>null):await thisProcessStartTime();return writer.startTime===startTime}var selfStartTime;function thisProcessStartTime(){return selfStartTime??=readProcessStartTime(process.pid).then(value=>value??null,()=>null),selfStartTime}function parseWriter(parsed){if(!isRecord2(parsed.writer)||typeof parsed.writer.pid!="number")return;let{pid,startTime}=parsed.writer;return{pid,startTime:typeof startTime=="string"?startTime:null}}import{createHash as createHash3,randomBytes,timingSafeEqual}from"node:crypto";import{chmod as chmod2,mkdir as mkdir3,readFile as readFile4,writeFile as writeFile4}from"node:fs/promises";import{dirname as dirname3,win32 as win322}from"node:path";var WINDOWS_PIPE_PREFIX="\\\\.\\pipe\\senpi-rpc-",SOCKET_SECRET_BYTES=32,SOCKET_SECRET_SUFFIX=".secret",SOCKET_SECRET_FILE_ENV="SENPI_RPC_SOCKET_SECRET_FILE",SOCKET_HANDSHAKE_TIMEOUT_MS=2e3;function socketSecretPath(logicalPath){if(logicalPath.toLowerCase().startsWith("\\\\.\\pipe\\"))throw new Error(`Windows RPC named-pipe addresses need a logical filesystem path for their secret: ${logicalPath}`);return`${logicalPath}${SOCKET_SECRET_SUFFIX}`}async function ensureSocketSecret(path){try{let existing=await readFile4(path);if(existing.length===SOCKET_SECRET_BYTES)return existing}catch(error){if(!isNodeErrorCode3(error,"ENOENT"))throw error}return createSocketSecret(path)}async function createSocketSecret(path){await mkdir3(dirname3(path),{recursive:!0});let secret=randomBytes(SOCKET_SECRET_BYTES);return await writeFile4(path,secret,{mode:384}),await chmod2(path,384),secret}async function readSocketSecret(path){let secret=await readFile4(path);if(secret.length!==SOCKET_SECRET_BYTES)throw new Error(`invalid RPC socket secret: ${path}`);return secret}function resolveSocketTransportAddress(socketPath,platform,secret){if(platform!=="win32"||socketPath.toLowerCase().startsWith("\\\\.\\pipe\\"))return socketPath;if(!/^[a-zA-Z]:[\\/]/.test(socketPath)&&!/^\\\\[^/]/.test(socketPath))throw new Error(`Windows RPC socket path must be drive-qualified or UNC: ${socketPath}`);let canonical=win322.normalize(socketPath).toLowerCase(),identity=Buffer.concat([Buffer.from(canonical,"utf8"),Buffer.from(secret??[])]),name=createHash3("sha256").update(identity).digest("hex").slice(0,32);return`${WINDOWS_PIPE_PREFIX}${name}`}function authenticateSocket(socket,secret,onAuthenticated){let received=Buffer.alloc(0),finish=()=>{clearTimeout(timer),socket.off("data",onData),socket.off("error",onError)},onError=()=>{finish(),socket.destroy()},timer=setTimeout(()=>{finish(),socket.destroy()},SOCKET_HANDSHAKE_TIMEOUT_MS),onData=chunk=>{if(received=Buffer.concat([received,chunk]),received.length<secret.length)return;if(finish(),!timingSafeEqual(received.subarray(0,secret.length),Buffer.from(secret))){socket.destroy();return}let remainder=received.subarray(secret.length);remainder.length>0&&socket.unshift(remainder),onAuthenticated()};socket.on("data",onData),socket.once("error",onError),socket.once("close",finish)}function sendSocketHandshake(socket,secret){socket.write(Buffer.from(secret))}function isNodeErrorCode3(error,code){return error instanceof Error&&"code"in error&&error.code===code}import{mkdir as mkdir4,readFile as readFile5,rename as rename4,stat,unlink,writeFile as writeFile5}from"node:fs/promises";import{dirname as dirname4}from"node:path";var PUBLIC_SOCKET_IDENTITY_FILE="public-socket.owner",SOCKET_IDENTITY_WAIT_MS=3e4,MAX_SOCKET_PATH_BYTES=103;function generationBindPath(publicSocket,generation){return`${publicSocket}.next-${generation}`}function sameSocketIdentity(a,b){return a.dev===b.dev&&a.ino===b.ino}async function statSocketIdentity(socketPath){try{let{dev,ino}=await stat(socketPath);return{dev,ino}}catch(cause){if(isNodeErrorCode4(cause,"ENOENT"))return;throw cause}}async function classifyEndpointOwnership(socketPath,identity){if(identity===void 0||process.platform==="win32"||socketPath.startsWith("\0"))return"unknown";let current;try{current=await statSocketIdentity(socketPath)}catch{return"unknown"}return current===void 0?"absent":sameSocketIdentity(current,identity)?"held":"replaced"}async function socketEntryReplaced(socketPath,identity){return await classifyEndpointOwnership(socketPath,identity)==="replaced"}async function writeSocketIdentityFile(path,identity){await mkdir4(dirname4(path),{recursive:!0,mode:448});let tmpPath=`${path}.${process.pid}.tmp`;await writeFile5(tmpPath,`${JSON.stringify(identity)}
|
|
7
|
+
`,{mode:384}),await rename4(tmpPath,path)}async function readSocketIdentityFile(path){let raw;try{raw=await readFile5(path,"utf8")}catch(cause){if(isNodeErrorCode4(cause,"ENOENT"))return;throw cause}let parsed;try{parsed=JSON.parse(raw)}catch{return}if(!(typeof parsed!="object"||parsed===null||typeof parsed.dev!="number"||typeof parsed.ino!="number"))return{dev:parsed.dev,ino:parsed.ino}}async function waitForSocketIdentityFile(path,timeoutMs=SOCKET_IDENTITY_WAIT_MS,intervalMs=25){let deadline=Date.now()+timeoutMs;for(;;){let identity=await readSocketIdentityFile(path);if(identity!==void 0)return identity;if(Date.now()>=deadline)return;await delayUnrefed(intervalMs)}}async function unlinkOwnedSocket(socketPath,identity,log){if(process.platform==="win32"||socketPath.startsWith("\0"))return;let current;try{current=await statSocketIdentity(socketPath)}catch(cause){log(`socket ${socketPath} ownership could not be verified (${errorMessage2(cause)}); leaving it`);return}if(current!==void 0){if(identity===void 0){log(`socket path ${socketPath} ownership unknown; leaving it`);return}if(!sameSocketIdentity(current,identity)){log(`socket path ${socketPath} now owned by another host; leaving it`);return}try{await unlink(socketPath)}catch(cause){isNodeErrorCode4(cause,"ENOENT")||log(`socket ${socketPath} removal failed (${errorMessage2(cause)})`)}}}async function shieldSocketDuringClose(socketPath,close){if(process.platform==="win32"||socketPath.startsWith("\0"))return close();let shieldPath=`${socketPath}.shield-${process.pid}`,shielded=!1;try{await statSocketIdentity(socketPath)!==void 0&&(await rename4(socketPath,shieldPath),shielded=!0)}catch{}try{await close()}finally{if(shielded)try{await rename4(shieldPath,socketPath)}catch{}}}function delayUnrefed(ms){return new Promise(resolve2=>{setTimeout(resolve2,ms).unref?.()})}function errorMessage2(cause){return cause instanceof Error?cause.message:String(cause)}function isNodeErrorCode4(cause,code){return cause instanceof Error&&"code"in cause&&cause.code===code}export{canonicalSessionPath,sessionDirectoryRemoved,HOST_DAEMON_LAYOUT,HOST_DAEMON_DIR_ENV,ENDPOINT_REGISTRY_VERSION,HOST_STATE_FILE_MODE,canonicalEndpointPath,daemonDirectoryName,sameEndpoint,socketNamesDirectory,shardKey,shardSocketPathForKey,shardSocketPath,parseShardSocket,createHostDaemonPaths,hostDaemonDirectoryPaths,generationPaths,createDaemonDirectories,ensureEndpointIdentity,writeHostSettings,readHostSettings,writeStateFile,readFileOrUndefined,parseJson,parseDaemonPidFile,ProcessIdentityUnreadableError,processMatchesPidFile,stopValidatedPid,waitForGone,readProcessStartTime,processIsLive,waitForStartTime,readHostProcessMetrics,SESSION_PATH_RETRY_AFTER_MS,createEndpointReservations,readSessionPathClaims,claimOwnerIsLive,pruneDeadGenerations,readGenerationRows,readHostRegistration,writeHostRegistration,writeGenerationRecord,clearHostRegistration,releaseGeneration,provenOwner,writtenByThisProcess,thisProcessStartTime,SOCKET_SECRET_FILE_ENV,socketSecretPath,ensureSocketSecret,createSocketSecret,readSocketSecret,resolveSocketTransportAddress,authenticateSocket,sendSocketHandshake,PUBLIC_SOCKET_IDENTITY_FILE,MAX_SOCKET_PATH_BYTES,generationBindPath,statSocketIdentity,classifyEndpointOwnership,socketEntryReplaced,writeSocketIdentityFile,readSocketIdentityFile,waitForSocketIdentityFile,unlinkOwnedSocket,shieldSocketDuringClose};
|