@tonyclaw/agent-inspector 3.0.45 → 3.0.46
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/.output/{nitro.json → backend/nitro.json} +3 -3
- package/.output/backend-public/assets/index-D4LX-sw-.js +11 -0
- package/.output/cli.js +2326 -516
- package/.output/server/_libs/extend.mjs +4 -8
- package/.output/server/_libs/jszip.mjs +9 -35
- package/.output/server/_libs/react-dom.mjs +2 -3
- package/.output/server/_libs/react.mjs +1 -27
- package/.output/server/_libs/tanstack__react-router.mjs +1 -329
- package/.output/server/_libs/tanstack__router-core.mjs +42 -100
- package/.output/server/_libs/use-sync-external-store.mjs +1 -64
- package/.output/server/_libs/ws.mjs +1 -1
- package/.output/server/_ssr/index.mjs +4 -4
- package/.output/server/_ssr/{publicBasePathContext-5264L3rX.mjs → publicBasePathContext-IH2ilOfu.mjs} +52 -24
- package/.output/server/_ssr/{router-BJ_ltLim.mjs → router-D18yUq36.mjs} +19770 -19447
- package/.output/server/_ssr/{start-C6MjPjxp.mjs → start-COQu_AgD.mjs} +1 -1
- package/.output/server/_tanstack-start-manifest_v-DnbdNeun.mjs +4 -0
- package/.output/server/index.mjs +5 -145
- package/.output/{public/assets/CompareDrawer-B3_TLTJh.js → ui/assets/CompareDrawer-DAUuIJ6G.js} +1 -1
- package/.output/{public/assets/InspectorPet-Cpn6hv4P.js → ui/assets/InspectorPet-BRBVjOWI.js} +1 -1
- package/.output/ui/assets/ProxyViewerContainer-D7Sq0ctc.js +59 -0
- package/.output/{public/assets/ReplayDialog-B3EKVdJk.js → ui/assets/ReplayDialog-nDLsjOhs.js} +1 -1
- package/.output/{public/assets/RequestAnatomy-COOQjyUC.js → ui/assets/RequestAnatomy-zd4BDgL0.js} +1 -1
- package/.output/ui/assets/ResponseView-AdIXGcSn.js +2 -0
- package/.output/ui/assets/StreamingChunkSequence-CesTz8He.js +1 -0
- package/.output/{public/assets/_sessionId-zbgYl7ZJ.js → ui/assets/_sessionId-BAfzrhSU.js} +1 -1
- package/.output/{public/assets/_sessionId-BJlM3nmt.js → ui/assets/_sessionId-QnBomgPD.js} +1 -1
- package/.output/ui/assets/favicon-DYEkHSNl.svg +21 -0
- package/.output/{public/assets/index-BIK4bPTv.js → ui/assets/index-BcsdxBAd.js} +1 -1
- package/.output/ui/assets/index-BvXp42al.css +1 -0
- package/.output/{public/assets/index-D2Qw6Ri2.js → ui/assets/index-D0rtCN9V.js} +1 -1
- package/.output/ui/assets/index-DHpwr08Z.js +73 -0
- package/.output/{public/assets/index-xF_NY8Yb.js → ui/assets/index-dNuk2dsU.js} +5 -5
- package/.output/ui/assets/json-viewer-BvFHglMb.js +1 -0
- package/.output/{public/assets/jszip.min-B_rfAUCe.js → ui/assets/jszip.min-B5Z7gNZB.js} +1 -1
- package/.output/ui/index.html +229 -0
- package/.output/ui/runtime-config.js +2 -0
- package/.output/workers/logFinalizer.worker.js +979 -414
- package/.output/workers/sessionWorkerEntry.js +979 -414
- package/README.md +175 -43
- package/docs/instance-control.openapi.yaml +59 -4
- package/package.json +25 -5
- package/scripts/generate-theme-scales.mjs +3 -3
- package/src/{router.tsx → backend/router.tsx} +3 -15
- package/src/backend/routes/$.ts +26 -0
- package/src/backend/routes/__root.ts +4 -0
- package/src/{routes → backend/routes}/api/-instances.ts +3 -3
- package/src/{routes → backend/routes}/api/alerts.summary.ts +3 -3
- package/src/{routes → backend/routes}/api/alerts.ts +4 -4
- package/src/{routes → backend/routes}/api/config.paths.ts +1 -1
- package/src/{routes → backend/routes}/api/config.ts +11 -2
- package/src/{routes → backend/routes}/api/ecosystem.packages.$packageId.help.ts +1 -1
- package/src/{routes → backend/routes}/api/ecosystem.packages.$packageId.install.ts +1 -1
- package/src/{routes → backend/routes}/api/ecosystem.packages.$packageId.runner-presets.ts +1 -1
- package/src/{routes → backend/routes}/api/ecosystem.packages.$packageId.upgrade.ts +1 -1
- package/src/{routes → backend/routes}/api/ecosystem.packages.ts +5 -1
- package/src/{routes → backend/routes}/api/ecosystem.recipes.$recipeId.run.ts +1 -1
- package/src/{routes → backend/routes}/api/ecosystem.tasks.$taskId.ts +1 -1
- package/src/{routes → backend/routes}/api/ecosystem.tasks.ts +1 -1
- package/src/{routes → backend/routes}/api/groups.$groupId.evidence.ts +2 -2
- package/src/{routes → backend/routes}/api/groups.$groupId.sessions.ts +2 -2
- package/src/{routes → backend/routes}/api/groups.$groupId.ts +2 -2
- package/src/{routes → backend/routes}/api/groups.ts +2 -2
- package/src/{routes → backend/routes}/api/health.ts +3 -3
- package/src/{routes → backend/routes}/api/instances.$name.connection.ts +1 -1
- package/src/{routes → backend/routes}/api/instances.$name.restart.ts +2 -2
- package/src/{routes → backend/routes}/api/instances.$name.start.ts +2 -2
- package/src/{routes → backend/routes}/api/instances.$name.stop.ts +2 -2
- package/src/{routes → backend/routes}/api/instances.$name.ts +1 -1
- package/src/{routes → backend/routes}/api/instances.ts +1 -1
- package/src/{routes → backend/routes}/api/knowledge.candidates.$candidateId.promote.ts +2 -2
- package/src/{routes → backend/routes}/api/knowledge.candidates.$candidateId.ts +2 -2
- package/src/{routes → backend/routes}/api/knowledge.candidates.ts +1 -1
- package/src/{routes → backend/routes}/api/knowledge.project-context.ts +2 -2
- package/src/{routes → backend/routes}/api/knowledge.search.ts +2 -2
- package/src/{routes → backend/routes}/api/knowledge.sessions.$sessionId.candidates.ts +3 -3
- package/src/{routes → backend/routes}/api/logs.$id.body.ts +6 -6
- package/src/{routes → backend/routes}/api/logs.$id.chunks.ts +5 -4
- package/src/{routes → backend/routes}/api/logs.$id.replay.ts +12 -11
- package/src/{routes → backend/routes}/api/logs.$id.ts +4 -3
- package/src/{routes → backend/routes}/api/logs.import.ts +3 -3
- package/src/{routes → backend/routes}/api/logs.stream.ts +11 -7
- package/src/{routes → backend/routes}/api/logs.ts +17 -9
- package/src/{routes → backend/routes}/api/mcp.ts +1 -1
- package/src/{routes → backend/routes}/api/models.ts +1 -1
- package/src/{routes → backend/routes}/api/pi-agent.ts +2 -2
- package/src/{routes → backend/routes}/api/providers.$providerId.model-metadata.ts +5 -5
- package/src/{routes → backend/routes}/api/providers.$providerId.test.log.ts +7 -7
- package/src/{routes → backend/routes}/api/providers.$providerId.ts +4 -4
- package/src/{routes → backend/routes}/api/providers.export.ts +1 -1
- package/src/{routes → backend/routes}/api/providers.import.ts +3 -3
- package/src/{routes → backend/routes}/api/providers.scan.ts +2 -2
- package/src/{routes → backend/routes}/api/providers.ts +9 -4
- package/src/{routes → backend/routes}/api/runs.$runId.evidence.ts +2 -2
- package/src/{routes → backend/routes}/api/runs.$runId.ts +2 -2
- package/src/{routes → backend/routes}/api/runs.ts +4 -4
- package/src/backend/routes/api/runtime.ts +46 -0
- package/src/{routes → backend/routes}/api/sessions.ts +3 -3
- package/src/{routes → backend/routes}/proxy/$.ts +1 -1
- package/src/{routes → backend/routes}/readyz.ts +1 -1
- package/src/{start.ts → backend/start.ts} +1 -1
- package/src/cli/alias.ts +2 -11
- package/src/cli/doctor.ts +32 -9
- package/src/cli/instance.ts +26 -13
- package/src/cli/instanceArgs.ts +30 -11
- package/src/cli/instanceControl.ts +0 -2
- package/src/cli/instanceModel.ts +9 -17
- package/src/cli/instanceRegistry.ts +0 -9
- package/src/cli/networkHints.ts +27 -14
- package/src/cli/onboard.ts +69 -2
- package/src/cli/onboardTarget.ts +89 -40
- package/src/cli/templates/codex-skill-onboard.ts +44 -14
- package/src/cli/templates/skill-onboard.ts +64 -28
- package/src/cli.ts +184 -61
- package/src/components/ProxyViewer.tsx +11 -9
- package/src/components/ProxyViewerContainer.tsx +12 -11
- package/src/components/pi-agent/PiAgentPanel.tsx +2 -2
- package/src/components/providers/ProviderCard.tsx +1 -1
- package/src/components/providers/ProviderTestResultsView.tsx +1 -1
- package/src/components/providers/SettingsDialog.tsx +159 -144
- package/src/components/proxy-viewer/ApplicationBar.tsx +2 -1
- package/src/components/proxy-viewer/LogEntry.tsx +1 -1
- package/src/components/proxy-viewer/log-formats/index.ts +1 -1
- package/src/contracts/index.ts +5 -0
- package/src/contracts/log.ts +33 -3
- package/src/knowledge/types.ts +3 -2
- package/src/lib/alertContract.ts +2 -2
- package/src/lib/apiClient.ts +30 -7
- package/src/lib/apiFormat.ts +29 -0
- package/src/lib/basePath.ts +29 -11
- package/src/lib/browserRuntimeContract.ts +124 -0
- package/src/lib/browserRuntimeResolver.ts +244 -0
- package/src/{proxy → lib}/claudeCodeStrip.ts +6 -7
- package/src/lib/codingAgentEndpoints.ts +38 -0
- package/src/lib/instanceContract.ts +27 -11
- package/src/lib/piAgentContract.ts +3 -2
- package/src/lib/publicBasePathContext.ts +40 -10
- package/src/lib/resourceLimits.ts +2 -0
- package/src/lib/runContract.ts +3 -3
- package/src/lib/sessionInfoContract.ts +3 -2
- package/src/mcp/instanceHandlers.ts +1 -0
- package/src/mcp/server.ts +19 -24
- package/src/proxy/config.ts +25 -30
- package/src/proxy/dataDir.ts +43 -7
- package/src/proxy/ecosystemTasks.ts +161 -70
- package/src/proxy/formats/registry.ts +6 -21
- package/src/proxy/handler.ts +129 -29
- package/src/proxy/identityProxy.ts +419 -39
- package/src/proxy/jsonlRecovery.ts +554 -0
- package/src/proxy/logFinalizer.ts +25 -10
- package/src/proxy/logImporter.ts +2 -1
- package/src/proxy/logIndex.ts +191 -95
- package/src/proxy/logger.ts +77 -14
- package/src/proxy/platformCommands.ts +41 -0
- package/src/proxy/privateDataPath.ts +310 -88
- package/src/proxy/rawStreamCapture.ts +194 -13
- package/src/proxy/runtimeAdmission.ts +5 -2
- package/src/proxy/runtimeHealth.ts +14 -1
- package/src/proxy/runtimeShutdown.ts +11 -1
- package/src/proxy/schemas.ts +7 -1
- package/src/proxy/sessionArchive.ts +78 -14
- package/src/proxy/sqliteLogIndex.ts +65 -2
- package/src/proxy/store.ts +141 -34
- package/src/proxy/uiAssetServer.ts +106 -0
- package/src/proxy/upstream.ts +29 -2
- package/src/ui/bootstrap.ts +167 -0
- package/src/ui/index.html +38 -0
- package/src/ui/logsStreamClient.ts +20 -0
- package/src/ui/main.tsx +13 -0
- package/src/ui/public/runtime-config.js +2 -0
- package/src/ui/router.tsx +13 -0
- package/src/ui/routes/__root.tsx +69 -0
- package/src/{routes → ui/routes}/index.tsx +2 -3
- package/src/{routes → ui/routes}/session/$sessionId.tsx +5 -11
- package/src/ui/runtimeDiscovery.ts +50 -0
- package/styles/globals.css +1 -0
- package/.output/public/assets/ProxyViewerContainer-BEAhuGOJ.js +0 -126
- package/.output/public/assets/ResponseView-DBCjkwye.js +0 -2
- package/.output/public/assets/StreamingChunkSequence-CuXhDgMo.js +0 -1
- package/.output/public/assets/index-BZo_8koU.js +0 -70
- package/.output/public/assets/index-ZWschkCh.css +0 -1
- package/.output/public/assets/json-viewer-B-Ao6pwW.js +0 -1
- package/.output/server/_libs/@radix-ui/react-accessible-icon+[...].mjs +0 -1
- package/.output/server/_libs/@radix-ui/react-dismissable-layer+[...].mjs +0 -344
- package/.output/server/_libs/@radix-ui/react-navigation-menu+[...].mjs +0 -2
- package/.output/server/_libs/@radix-ui/react-one-time-password-field+[...].mjs +0 -2
- package/.output/server/_libs/@radix-ui/react-password-toggle-field+[...].mjs +0 -2
- package/.output/server/_libs/@radix-ui/react-use-callback-ref+[...].mjs +0 -11
- package/.output/server/_libs/@radix-ui/react-use-controllable-state+[...].mjs +0 -69
- package/.output/server/_libs/@radix-ui/react-use-effect-event+[...].mjs +0 -1
- package/.output/server/_libs/@radix-ui/react-use-is-hydrated+[...].mjs +0 -28
- package/.output/server/_libs/@radix-ui/react-use-layout-effect+[...].mjs +0 -6
- package/.output/server/_libs/@radix-ui/react-visually-hidden+[...].mjs +0 -34
- package/.output/server/_libs/aria-hidden.mjs +0 -122
- package/.output/server/_libs/bail.mjs +0 -8
- package/.output/server/_libs/character-entities.mjs +0 -2130
- package/.output/server/_libs/class-variance-authority.mjs +0 -44
- package/.output/server/_libs/clsx.mjs +0 -16
- package/.output/server/_libs/comma-separated-tokens.mjs +0 -10
- package/.output/server/_libs/decode-named-character-reference+[...].mjs +0 -8
- package/.output/server/_libs/dequal.mjs +0 -27
- package/.output/server/_libs/detect-node-es.mjs +0 -1
- package/.output/server/_libs/devlop.mjs +0 -8
- package/.output/server/_libs/diff.mjs +0 -320
- package/.output/server/_libs/estree-util-is-identifier-name.mjs +0 -11
- package/.output/server/_libs/floating-ui__core.mjs +0 -725
- package/.output/server/_libs/floating-ui__dom.mjs +0 -622
- package/.output/server/_libs/floating-ui__react-dom.mjs +0 -292
- package/.output/server/_libs/floating-ui__utils.mjs +0 -320
- package/.output/server/_libs/get-nonce.mjs +0 -9
- package/.output/server/_libs/hast-util-to-jsx-runtime.mjs +0 -388
- package/.output/server/_libs/hast-util-whitespace.mjs +0 -10
- package/.output/server/_libs/html-url-attributes.mjs +0 -26
- package/.output/server/_libs/inline-style-parser.mjs +0 -142
- package/.output/server/_libs/is-plain-obj.mjs +0 -10
- package/.output/server/_libs/lucide-react.mjs +0 -1027
- package/.output/server/_libs/mdast-util-from-markdown.mjs +0 -717
- package/.output/server/_libs/mdast-util-to-hast.mjs +0 -710
- package/.output/server/_libs/mdast-util-to-string.mjs +0 -38
- package/.output/server/_libs/micromark-core-commonmark.mjs +0 -2259
- package/.output/server/_libs/micromark-factory-destination.mjs +0 -94
- package/.output/server/_libs/micromark-factory-label.mjs +0 -63
- package/.output/server/_libs/micromark-factory-space.mjs +0 -24
- package/.output/server/_libs/micromark-factory-title.mjs +0 -65
- package/.output/server/_libs/micromark-factory-whitespace.mjs +0 -22
- package/.output/server/_libs/micromark-util-character.mjs +0 -44
- package/.output/server/_libs/micromark-util-chunked.mjs +0 -36
- package/.output/server/_libs/micromark-util-classify-character+[...].mjs +0 -12
- package/.output/server/_libs/micromark-util-combine-extensions+[...].mjs +0 -41
- package/.output/server/_libs/micromark-util-decode-numeric-character-reference+[...].mjs +0 -19
- package/.output/server/_libs/micromark-util-decode-string.mjs +0 -21
- package/.output/server/_libs/micromark-util-encode.mjs +0 -1
- package/.output/server/_libs/micromark-util-html-tag-name.mjs +0 -69
- package/.output/server/_libs/micromark-util-normalize-identifier+[...].mjs +0 -6
- package/.output/server/_libs/micromark-util-resolve-all.mjs +0 -15
- package/.output/server/_libs/micromark-util-sanitize-uri.mjs +0 -41
- package/.output/server/_libs/micromark-util-subtokenize.mjs +0 -346
- package/.output/server/_libs/micromark.mjs +0 -906
- package/.output/server/_libs/property-information.mjs +0 -1209
- package/.output/server/_libs/radix-ui.mjs +0 -1
- package/.output/server/_libs/radix-ui__number.mjs +0 -6
- package/.output/server/_libs/radix-ui__primitive.mjs +0 -11
- package/.output/server/_libs/radix-ui__react-accordion.mjs +0 -1
- package/.output/server/_libs/radix-ui__react-alert-dialog.mjs +0 -1
- package/.output/server/_libs/radix-ui__react-arrow.mjs +0 -23
- package/.output/server/_libs/radix-ui__react-aspect-ratio.mjs +0 -1
- package/.output/server/_libs/radix-ui__react-avatar.mjs +0 -1
- package/.output/server/_libs/radix-ui__react-checkbox.mjs +0 -1
- package/.output/server/_libs/radix-ui__react-collapsible.mjs +0 -144
- package/.output/server/_libs/radix-ui__react-collection.mjs +0 -69
- package/.output/server/_libs/radix-ui__react-compose-refs.mjs +0 -38
- package/.output/server/_libs/radix-ui__react-context-menu.mjs +0 -1
- package/.output/server/_libs/radix-ui__react-context.mjs +0 -64
- package/.output/server/_libs/radix-ui__react-dialog.mjs +0 -280
- package/.output/server/_libs/radix-ui__react-direction.mjs +0 -9
- package/.output/server/_libs/radix-ui__react-dropdown-menu.mjs +0 -1
- package/.output/server/_libs/radix-ui__react-focus-guards.mjs +0 -39
- package/.output/server/_libs/radix-ui__react-focus-scope.mjs +0 -210
- package/.output/server/_libs/radix-ui__react-form.mjs +0 -1
- package/.output/server/_libs/radix-ui__react-hover-card.mjs +0 -1
- package/.output/server/_libs/radix-ui__react-id.mjs +0 -14
- package/.output/server/_libs/radix-ui__react-label.mjs +0 -1
- package/.output/server/_libs/radix-ui__react-menu.mjs +0 -1
- package/.output/server/_libs/radix-ui__react-menubar.mjs +0 -1
- package/.output/server/_libs/radix-ui__react-popover.mjs +0 -1
- package/.output/server/_libs/radix-ui__react-popper.mjs +0 -340
- package/.output/server/_libs/radix-ui__react-portal.mjs +0 -16
- package/.output/server/_libs/radix-ui__react-presence.mjs +0 -173
- package/.output/server/_libs/radix-ui__react-primitive.mjs +0 -42
- package/.output/server/_libs/radix-ui__react-progress.mjs +0 -1
- package/.output/server/_libs/radix-ui__react-radio-group.mjs +0 -1
- package/.output/server/_libs/radix-ui__react-roving-focus.mjs +0 -235
- package/.output/server/_libs/radix-ui__react-scroll-area.mjs +0 -731
- package/.output/server/_libs/radix-ui__react-select.mjs +0 -1207
- package/.output/server/_libs/radix-ui__react-separator.mjs +0 -28
- package/.output/server/_libs/radix-ui__react-slider.mjs +0 -1
- package/.output/server/_libs/radix-ui__react-slot.mjs +0 -132
- package/.output/server/_libs/radix-ui__react-switch.mjs +0 -1
- package/.output/server/_libs/radix-ui__react-tabs.mjs +0 -194
- package/.output/server/_libs/radix-ui__react-toast.mjs +0 -2
- package/.output/server/_libs/radix-ui__react-toggle-group.mjs +0 -1
- package/.output/server/_libs/radix-ui__react-toggle.mjs +0 -1
- package/.output/server/_libs/radix-ui__react-toolbar.mjs +0 -1
- package/.output/server/_libs/radix-ui__react-tooltip.mjs +0 -498
- package/.output/server/_libs/radix-ui__react-use-previous.mjs +0 -14
- package/.output/server/_libs/radix-ui__react-use-size.mjs +0 -39
- package/.output/server/_libs/react-markdown.mjs +0 -235
- package/.output/server/_libs/react-remove-scroll-bar.mjs +0 -82
- package/.output/server/_libs/react-remove-scroll.mjs +0 -328
- package/.output/server/_libs/react-style-singleton.mjs +0 -69
- package/.output/server/_libs/remark-parse.mjs +0 -19
- package/.output/server/_libs/remark-rehype.mjs +0 -21
- package/.output/server/_libs/space-separated-tokens.mjs +0 -6
- package/.output/server/_libs/style-to-js.mjs +0 -72
- package/.output/server/_libs/style-to-object.mjs +0 -38
- package/.output/server/_libs/swr.mjs +0 -947
- package/.output/server/_libs/tailwind-merge.mjs +0 -3255
- package/.output/server/_libs/tanstack__react-virtual.mjs +0 -130
- package/.output/server/_libs/tanstack__virtual-core.mjs +0 -1319
- package/.output/server/_libs/three.mjs +0 -26016
- package/.output/server/_libs/trim-lines.mjs +0 -41
- package/.output/server/_libs/trough.mjs +0 -85
- package/.output/server/_libs/tslib.mjs +0 -1
- package/.output/server/_libs/ungap__structured-clone.mjs +0 -212
- package/.output/server/_libs/unified.mjs +0 -661
- package/.output/server/_libs/unist-util-is.mjs +0 -100
- package/.output/server/_libs/unist-util-position.mjs +0 -27
- package/.output/server/_libs/unist-util-stringify-position.mjs +0 -27
- package/.output/server/_libs/unist-util-visit-parents.mjs +0 -82
- package/.output/server/_libs/unist-util-visit.mjs +0 -24
- package/.output/server/_libs/use-callback-ref.mjs +0 -66
- package/.output/server/_libs/use-sidecar.mjs +0 -106
- package/.output/server/_libs/vfile-message.mjs +0 -138
- package/.output/server/_libs/vfile.mjs +0 -467
- package/.output/server/_sessionId-CJ99gZFV.mjs +0 -84
- package/.output/server/_sessionId-DEjScBpK.mjs +0 -146
- package/.output/server/_ssr/CompareDrawer-DtOIMeQB.mjs +0 -1060
- package/.output/server/_ssr/InspectorPet-CXc4oCBQ.mjs +0 -938
- package/.output/server/_ssr/ProxyViewerContainer-DVPlwfkt.mjs +0 -17632
- package/.output/server/_ssr/ReplayDialog-BQEA95qC.mjs +0 -725
- package/.output/server/_ssr/RequestAnatomy-BMyd8B7Q.mjs +0 -837
- package/.output/server/_ssr/ResponseView-qrTaEIM8.mjs +0 -757
- package/.output/server/_ssr/StreamingChunkSequence-BFTL8mIy.mjs +0 -274
- package/.output/server/_ssr/index-Bcj1Hcy4.mjs +0 -135
- package/.output/server/_ssr/index-DW-M7XUG.mjs +0 -84
- package/.output/server/_ssr/json-viewer-DiI0Yjsn.mjs +0 -483
- package/.output/server/_tanstack-start-manifest_v-C6pXXX9R.mjs +0 -4
- package/.output/server/node_modules/tslib/modules/index.js +0 -70
- package/.output/server/node_modules/tslib/modules/package.json +0 -3
- package/.output/server/node_modules/tslib/package.json +0 -47
- package/.output/server/node_modules/tslib/tslib.js +0 -484
- package/.output/server/package.json +0 -9
- package/src/routes/__root.tsx +0 -170
- /package/.output/{public → ui}/assets/agent-inspector-58K1_MsC.ico +0 -0
- /package/.output/{public → ui}/assets/alibaba-TTwafVwX.svg +0 -0
- /package/.output/{public → ui}/assets/minimax-BPMzvuL-.jpeg +0 -0
- /package/.output/{public → ui}/assets/qwen-mMn3f5ul.webp +0 -0
- /package/.output/{public → ui}/assets/zhipuai-BPNAnxo-.svg +0 -0
- /package/src/{routes → backend/routes}/livez.ts +0 -0
|
@@ -8,9 +8,9 @@ var __export = (target, all) => {
|
|
|
8
8
|
import { isMainThread, parentPort } from "node:worker_threads";
|
|
9
9
|
|
|
10
10
|
// src/proxy/logFinalizer.ts
|
|
11
|
-
import { Buffer as
|
|
12
|
-
import { existsSync as existsSync5, readFileSync as readFileSync2, rmSync as rmSync2, statSync
|
|
13
|
-
import { join as
|
|
11
|
+
import { Buffer as Buffer4 } from "node:buffer";
|
|
12
|
+
import { existsSync as existsSync5, readFileSync as readFileSync2, rmSync as rmSync2, statSync } from "node:fs";
|
|
13
|
+
import { join as join6 } from "node:path";
|
|
14
14
|
import { fileURLToPath as fileURLToPath2, pathToFileURL } from "node:url";
|
|
15
15
|
|
|
16
16
|
// src/proxy/chunkStorage.ts
|
|
@@ -19,29 +19,38 @@ import {
|
|
|
19
19
|
readFileSync,
|
|
20
20
|
unlinkSync,
|
|
21
21
|
existsSync as existsSync3,
|
|
22
|
-
renameSync,
|
|
22
|
+
renameSync as renameSync2,
|
|
23
23
|
copyFileSync
|
|
24
24
|
} from "node:fs";
|
|
25
|
-
import { join as
|
|
25
|
+
import { join as join4, isAbsolute as isAbsolute2 } from "node:path";
|
|
26
26
|
|
|
27
27
|
// src/proxy/logger.ts
|
|
28
|
-
import { Buffer as
|
|
29
|
-
import {
|
|
30
|
-
import { appendFile, readdir, rename, stat, unlink } from "node:fs/promises";
|
|
28
|
+
import { Buffer as Buffer3 } from "node:buffer";
|
|
29
|
+
import { closeSync as closeSync2, constants as constants3, fsyncSync, openSync as openSync2, writeSync } from "node:fs";
|
|
30
|
+
import { appendFile, readdir as readdir2, rename, stat as stat2, unlink as unlink2 } from "node:fs/promises";
|
|
31
31
|
import path from "node:path";
|
|
32
32
|
|
|
33
33
|
// src/proxy/dataDir.ts
|
|
34
|
-
import { cpSync, existsSync as
|
|
34
|
+
import { cpSync, existsSync, readdirSync as readdirSync2, renameSync, rmSync } from "node:fs";
|
|
35
35
|
import { isAbsolute, join as join2 } from "node:path";
|
|
36
36
|
|
|
37
37
|
// src/proxy/privateDataPath.ts
|
|
38
38
|
import { spawnSync } from "node:child_process";
|
|
39
|
-
import {
|
|
40
|
-
|
|
39
|
+
import {
|
|
40
|
+
closeSync,
|
|
41
|
+
constants,
|
|
42
|
+
fchmodSync,
|
|
43
|
+
fstatSync,
|
|
44
|
+
lstatSync,
|
|
45
|
+
mkdirSync,
|
|
46
|
+
openSync,
|
|
47
|
+
readdirSync,
|
|
48
|
+
realpathSync
|
|
49
|
+
} from "node:fs";
|
|
50
|
+
import { join, parse, resolve, sep } from "node:path";
|
|
41
51
|
var PRIVATE_DIRECTORY_MODE = 448;
|
|
42
52
|
var PRIVATE_FILE_MODE = 384;
|
|
43
|
-
var
|
|
44
|
-
var securedFileIdentities = /* @__PURE__ */ new Map();
|
|
53
|
+
var securedPathFingerprints = /* @__PURE__ */ new Map();
|
|
45
54
|
var cachedWindowsSid = null;
|
|
46
55
|
function windowsSystemPath(executable) {
|
|
47
56
|
const systemRoot = process.env["SystemRoot"] ?? "C:\\Windows";
|
|
@@ -71,9 +80,7 @@ function resolveWindowsUserSid(run) {
|
|
|
71
80
|
function windowsBroadGroupRemovalArgs() {
|
|
72
81
|
return ["/remove:g", "*S-1-1-0", "*S-1-5-11", "*S-1-5-32-545"];
|
|
73
82
|
}
|
|
74
|
-
function
|
|
75
|
-
const sid = resolveWindowsUserSid(run);
|
|
76
|
-
if (sid === null) return false;
|
|
83
|
+
function applyWindowsAclWithSid(path2, kind, sid, run) {
|
|
77
84
|
const access = kind === "directory" ? `(OI)(CI)F` : "F";
|
|
78
85
|
const result = run("icacls.exe", [
|
|
79
86
|
path2,
|
|
@@ -85,93 +92,226 @@ function applyWindowsUserOnlyAcl(path2, kind, run = runWindowsCommand) {
|
|
|
85
92
|
]);
|
|
86
93
|
return result.status === 0;
|
|
87
94
|
}
|
|
88
|
-
function
|
|
95
|
+
function applyWindowsUserOnlyAcl(path2, kind, run = runWindowsCommand) {
|
|
89
96
|
const sid = resolveWindowsUserSid(run);
|
|
90
|
-
|
|
91
|
-
const result = run("icacls.exe", [
|
|
92
|
-
root,
|
|
93
|
-
"/inheritance:r",
|
|
94
|
-
"/grant:r",
|
|
95
|
-
`*${sid}:(OI)(CI)F`,
|
|
96
|
-
`*${sid}:F`,
|
|
97
|
-
...windowsBroadGroupRemovalArgs(),
|
|
98
|
-
"/T",
|
|
99
|
-
"/C",
|
|
100
|
-
"/Q"
|
|
101
|
-
]);
|
|
102
|
-
return result.status === 0;
|
|
97
|
+
return sid !== null && applyWindowsAclWithSid(path2, kind, sid, run);
|
|
103
98
|
}
|
|
104
|
-
function
|
|
99
|
+
function comparablePath(path2) {
|
|
100
|
+
let normalized = path2;
|
|
105
101
|
if (process.platform === "win32") {
|
|
106
|
-
|
|
102
|
+
if (normalized.startsWith("\\\\?\\UNC\\")) {
|
|
103
|
+
normalized = `\\\\${normalized.slice(8)}`;
|
|
104
|
+
} else if (normalized.startsWith("\\\\?\\")) {
|
|
105
|
+
normalized = normalized.slice(4);
|
|
106
|
+
}
|
|
107
107
|
}
|
|
108
|
+
const absolute = resolve(normalized);
|
|
109
|
+
return process.platform === "win32" ? absolute.toLowerCase() : absolute;
|
|
110
|
+
}
|
|
111
|
+
function pathIdentity(stats) {
|
|
112
|
+
return `${String(stats.dev)}:${String(stats.ino)}:${String(stats.birthtimeMs)}`;
|
|
113
|
+
}
|
|
114
|
+
function readPathEntry(path2) {
|
|
115
|
+
let stats;
|
|
108
116
|
try {
|
|
109
|
-
|
|
110
|
-
return
|
|
117
|
+
const observed = lstatSync(path2);
|
|
118
|
+
if (observed === void 0) return { status: "missing" };
|
|
119
|
+
stats = observed;
|
|
111
120
|
} catch {
|
|
112
|
-
return
|
|
121
|
+
return { status: "missing" };
|
|
113
122
|
}
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
if (!applyPrivatePermissionsSync(path2, kind)) return false;
|
|
119
|
-
securedPaths.add(cacheKey);
|
|
120
|
-
return true;
|
|
121
|
-
}
|
|
122
|
-
function ensurePrivateDirectorySync(path2) {
|
|
123
|
+
if (stats.isSymbolicLink()) return { status: "unsafe" };
|
|
124
|
+
const kind = stats.isDirectory() ? "directory" : stats.isFile() ? "file" : null;
|
|
125
|
+
if (kind === null) return { status: "unsafe" };
|
|
126
|
+
let canonical;
|
|
123
127
|
try {
|
|
124
|
-
|
|
128
|
+
canonical = realpathSync.native(path2);
|
|
125
129
|
} catch {
|
|
126
|
-
return
|
|
130
|
+
return { status: "unsafe" };
|
|
127
131
|
}
|
|
128
|
-
|
|
132
|
+
if (comparablePath(canonical) !== comparablePath(path2)) return { status: "unsafe" };
|
|
133
|
+
return {
|
|
134
|
+
status: "ok",
|
|
135
|
+
entry: {
|
|
136
|
+
path: path2,
|
|
137
|
+
kind,
|
|
138
|
+
identity: pathIdentity(stats),
|
|
139
|
+
mode: stats.mode & 511
|
|
140
|
+
}
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
function snapshotPathChain(path2) {
|
|
144
|
+
const absolutePath = resolve(path2);
|
|
145
|
+
const root = parse(absolutePath).root;
|
|
146
|
+
const suffix = absolutePath.slice(root.length);
|
|
147
|
+
const parts = suffix === "" ? [] : suffix.split(sep).filter((part) => part !== "");
|
|
148
|
+
const entries = [];
|
|
149
|
+
let current = root;
|
|
150
|
+
const rootRead = readPathEntry(root);
|
|
151
|
+
if (rootRead.status !== "ok" || rootRead.entry.kind !== "directory") return null;
|
|
152
|
+
entries.push(rootRead.entry);
|
|
153
|
+
for (let index = 0; index < parts.length; index += 1) {
|
|
154
|
+
const part = parts[index];
|
|
155
|
+
if (part === void 0) return null;
|
|
156
|
+
current = join(current, part);
|
|
157
|
+
const read = readPathEntry(current);
|
|
158
|
+
if (read.status === "unsafe") return null;
|
|
159
|
+
if (read.status === "missing") {
|
|
160
|
+
return {
|
|
161
|
+
absolutePath,
|
|
162
|
+
complete: false,
|
|
163
|
+
entries,
|
|
164
|
+
missingParts: parts.slice(index)
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
if (index < parts.length - 1 && read.entry.kind !== "directory") return null;
|
|
168
|
+
entries.push(read.entry);
|
|
169
|
+
}
|
|
170
|
+
return { absolutePath, complete: true, entries, missingParts: [] };
|
|
129
171
|
}
|
|
130
|
-
function
|
|
131
|
-
|
|
172
|
+
function chainFingerprint(snapshot) {
|
|
173
|
+
return snapshot.entries.map((entry) => `${entry.path}:${entry.identity}`).join("|");
|
|
174
|
+
}
|
|
175
|
+
function snapshotsRetainPrefix(before, after) {
|
|
176
|
+
if (after.entries.length < before.entries.length) return false;
|
|
177
|
+
return before.entries.every((entry, index) => {
|
|
178
|
+
const next = after.entries[index];
|
|
179
|
+
return next !== void 0 && next.path === entry.path && next.identity === entry.identity;
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
function completeSnapshotForKind(path2, kind) {
|
|
183
|
+
const snapshot = snapshotPathChain(path2);
|
|
184
|
+
if (snapshot === null || !snapshot.complete) return null;
|
|
185
|
+
const leaf = snapshot.entries.at(-1);
|
|
186
|
+
return leaf !== void 0 && leaf.kind === kind ? snapshot : null;
|
|
187
|
+
}
|
|
188
|
+
function applyPosixPermissions(path2, kind, expectedIdentity) {
|
|
189
|
+
let descriptor = null;
|
|
132
190
|
try {
|
|
133
|
-
const
|
|
134
|
-
|
|
191
|
+
const directoryFlag = kind === "directory" ? constants.O_DIRECTORY : 0;
|
|
192
|
+
descriptor = openSync(path2, constants.O_RDONLY | constants.O_NOFOLLOW | directoryFlag);
|
|
193
|
+
const before = fstatSync(descriptor);
|
|
194
|
+
if (pathIdentity(before) !== expectedIdentity) return false;
|
|
195
|
+
fchmodSync(descriptor, kind === "directory" ? PRIVATE_DIRECTORY_MODE : PRIVATE_FILE_MODE);
|
|
196
|
+
const after = fstatSync(descriptor);
|
|
197
|
+
return pathIdentity(after) === expectedIdentity && (after.mode & 511) === (kind === "directory" ? PRIVATE_DIRECTORY_MODE : PRIVATE_FILE_MODE);
|
|
135
198
|
} catch {
|
|
136
199
|
return false;
|
|
200
|
+
} finally {
|
|
201
|
+
if (descriptor !== null) {
|
|
202
|
+
try {
|
|
203
|
+
closeSync(descriptor);
|
|
204
|
+
} catch {
|
|
205
|
+
}
|
|
206
|
+
}
|
|
137
207
|
}
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
208
|
+
}
|
|
209
|
+
function permissionsArePrivate(entry) {
|
|
210
|
+
if (process.platform === "win32") return true;
|
|
211
|
+
return entry.mode === (entry.kind === "directory" ? PRIVATE_DIRECTORY_MODE : PRIVATE_FILE_MODE);
|
|
212
|
+
}
|
|
213
|
+
function secureExistingPath(path2, kind, forcePermissions = false) {
|
|
214
|
+
const before = completeSnapshotForKind(path2, kind);
|
|
215
|
+
if (before === null) return false;
|
|
216
|
+
const leaf = before.entries.at(-1);
|
|
217
|
+
if (leaf === void 0) return false;
|
|
218
|
+
const cacheKey = `${kind}:${before.absolutePath}`;
|
|
219
|
+
const beforeFingerprint = chainFingerprint(before);
|
|
220
|
+
if (!forcePermissions && securedPathFingerprints.get(cacheKey) === beforeFingerprint && permissionsArePrivate(leaf)) {
|
|
221
|
+
const cachedCheck = completeSnapshotForKind(path2, kind);
|
|
222
|
+
return cachedCheck !== null && chainFingerprint(cachedCheck) === beforeFingerprint;
|
|
142
223
|
}
|
|
143
|
-
|
|
144
|
-
|
|
224
|
+
const applied = process.platform === "win32" ? applyWindowsUserOnlyAcl(path2, kind) : applyPosixPermissions(path2, kind, leaf.identity);
|
|
225
|
+
if (!applied) return false;
|
|
226
|
+
const after = completeSnapshotForKind(path2, kind);
|
|
227
|
+
if (after === null || !snapshotsRetainPrefix(before, after)) return false;
|
|
228
|
+
const afterLeaf = after.entries.at(-1);
|
|
229
|
+
if (afterLeaf === void 0 || afterLeaf.identity !== leaf.identity) return false;
|
|
230
|
+
if (!permissionsArePrivate(afterLeaf)) return false;
|
|
231
|
+
securedPathFingerprints.set(cacheKey, chainFingerprint(after));
|
|
145
232
|
return true;
|
|
146
233
|
}
|
|
147
|
-
function
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
234
|
+
function ensurePrivateDirectorySync(path2) {
|
|
235
|
+
const before = snapshotPathChain(path2);
|
|
236
|
+
if (before === null) return false;
|
|
237
|
+
let current = before.entries.at(-1)?.path;
|
|
238
|
+
if (current === void 0) return false;
|
|
239
|
+
for (const part of before.missingParts) {
|
|
240
|
+
const next = join(current, part);
|
|
241
|
+
try {
|
|
242
|
+
mkdirSync(next, { mode: PRIVATE_DIRECTORY_MODE });
|
|
243
|
+
} catch {
|
|
244
|
+
const raced = readPathEntry(next);
|
|
245
|
+
if (raced.status !== "ok" || raced.entry.kind !== "directory") return false;
|
|
246
|
+
}
|
|
247
|
+
if (!secureExistingPath(next, "directory", true)) return false;
|
|
248
|
+
current = next;
|
|
154
249
|
}
|
|
155
|
-
|
|
156
|
-
if (!
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
250
|
+
const complete = completeSnapshotForKind(path2, "directory");
|
|
251
|
+
if (complete === null || !snapshotsRetainPrefix(before, complete)) return false;
|
|
252
|
+
return secureExistingPath(path2, "directory");
|
|
253
|
+
}
|
|
254
|
+
function securePrivateFileSync(path2, forceAcl = false) {
|
|
255
|
+
return secureExistingPath(path2, "file", forceAcl);
|
|
256
|
+
}
|
|
257
|
+
function collectSafeTree(root) {
|
|
258
|
+
const collected = [];
|
|
259
|
+
const visit = (path2) => {
|
|
260
|
+
const snapshot = snapshotPathChain(path2);
|
|
261
|
+
if (snapshot === null || !snapshot.complete) return false;
|
|
262
|
+
const leaf = snapshot.entries.at(-1);
|
|
263
|
+
if (leaf === void 0) return false;
|
|
264
|
+
const fingerprint = chainFingerprint(snapshot);
|
|
265
|
+
collected.push({ path: snapshot.absolutePath, kind: leaf.kind, fingerprint });
|
|
266
|
+
if (leaf.kind === "file") return true;
|
|
267
|
+
let entries;
|
|
268
|
+
try {
|
|
269
|
+
entries = readdirSync(path2);
|
|
270
|
+
} catch {
|
|
271
|
+
return false;
|
|
272
|
+
}
|
|
273
|
+
const afterRead = completeSnapshotForKind(path2, "directory");
|
|
274
|
+
if (afterRead === null || chainFingerprint(afterRead) !== fingerprint) return false;
|
|
275
|
+
for (const entry of entries) {
|
|
276
|
+
if (!visit(join(path2, entry))) return false;
|
|
277
|
+
}
|
|
160
278
|
return true;
|
|
279
|
+
};
|
|
280
|
+
return visit(root) ? collected : null;
|
|
281
|
+
}
|
|
282
|
+
function treeFingerprintsMatch(expected, observed) {
|
|
283
|
+
if (observed === null || observed.length !== expected.length) return false;
|
|
284
|
+
return expected.every((entry, index) => {
|
|
285
|
+
const next = observed[index];
|
|
286
|
+
return next !== void 0 && next.path === entry.path && next.kind === entry.kind && next.fingerprint === entry.fingerprint;
|
|
287
|
+
});
|
|
288
|
+
}
|
|
289
|
+
function isPathTreeFreeOfIndirectionSync(root) {
|
|
290
|
+
return collectSafeTree(root) !== null;
|
|
291
|
+
}
|
|
292
|
+
function applyWindowsUserOnlyTreeAcl(root, run = runWindowsCommand) {
|
|
293
|
+
const entries = collectSafeTree(root);
|
|
294
|
+
if (entries === null) return false;
|
|
295
|
+
const sid = resolveWindowsUserSid(run);
|
|
296
|
+
if (sid === null) return false;
|
|
297
|
+
for (const entry of entries) {
|
|
298
|
+
const before = completeSnapshotForKind(entry.path, entry.kind);
|
|
299
|
+
if (before === null || chainFingerprint(before) !== entry.fingerprint) return false;
|
|
300
|
+
if (!applyWindowsAclWithSid(entry.path, entry.kind, sid, run)) return false;
|
|
301
|
+
const after = completeSnapshotForKind(entry.path, entry.kind);
|
|
302
|
+
if (after === null || chainFingerprint(after) !== entry.fingerprint) return false;
|
|
303
|
+
securedPathFingerprints.set(`${entry.kind}:${entry.path}`, entry.fingerprint);
|
|
161
304
|
}
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
}
|
|
169
|
-
let secured = true;
|
|
305
|
+
return treeFingerprintsMatch(entries, collectSafeTree(root));
|
|
306
|
+
}
|
|
307
|
+
function securePrivateTreeSync(root) {
|
|
308
|
+
const entries = collectSafeTree(root);
|
|
309
|
+
if (entries === null) return false;
|
|
310
|
+
if (process.platform === "win32") return applyWindowsUserOnlyTreeAcl(root);
|
|
170
311
|
for (const entry of entries) {
|
|
171
|
-
|
|
172
|
-
if (!securePrivateTreeSync(childPath)) secured = false;
|
|
312
|
+
if (!secureExistingPath(entry.path, entry.kind, true)) return false;
|
|
173
313
|
}
|
|
174
|
-
return
|
|
314
|
+
return treeFingerprintsMatch(entries, collectSafeTree(root));
|
|
175
315
|
}
|
|
176
316
|
|
|
177
317
|
// src/proxy/dataDir.ts
|
|
@@ -179,7 +319,7 @@ var CURRENT_DATA_DIR_NAME = ".agent-inspector";
|
|
|
179
319
|
var LEGACY_DATA_DIR_NAMES = [".llm-inspector", ".llm-agent"];
|
|
180
320
|
function getDataDir() {
|
|
181
321
|
migrateLegacyDataDirs();
|
|
182
|
-
return resolveDataDir(
|
|
322
|
+
return resolveDataDir(existsSync);
|
|
183
323
|
}
|
|
184
324
|
function hasDataDirState(pathExists, dir) {
|
|
185
325
|
return pathExists(join2(dir, "providers.json")) || pathExists(join2(dir, "config.json")) || pathExists(join2(dir, "logs")) || pathExists(join2(dir, "chunks"));
|
|
@@ -206,293 +346,52 @@ function migrateLegacyDataDirs() {
|
|
|
206
346
|
if (hasExplicitDataDir()) return;
|
|
207
347
|
const base = defaultBaseDir();
|
|
208
348
|
const currentDir = join2(base, CURRENT_DATA_DIR_NAME);
|
|
209
|
-
if (hasDataDirState(
|
|
349
|
+
if (hasDataDirState(existsSync, currentDir)) return;
|
|
210
350
|
for (const legacyName of LEGACY_DATA_DIR_NAMES) {
|
|
211
351
|
const legacyDir = join2(base, legacyName);
|
|
212
|
-
if (!
|
|
352
|
+
if (!existsSync(legacyDir)) continue;
|
|
353
|
+
const stagingDir = join2(
|
|
354
|
+
base,
|
|
355
|
+
`${CURRENT_DATA_DIR_NAME}.migration-${String(process.pid)}-${String(Date.now())}`
|
|
356
|
+
);
|
|
213
357
|
try {
|
|
214
|
-
if (!
|
|
215
|
-
|
|
216
|
-
|
|
358
|
+
if (!isPathTreeFreeOfIndirectionSync(legacyDir)) return;
|
|
359
|
+
if (existsSync(currentDir)) {
|
|
360
|
+
if (readdirSync2(currentDir).length > 0) return;
|
|
361
|
+
rmSync(currentDir, { recursive: true, force: false });
|
|
362
|
+
}
|
|
363
|
+
if (!ensurePrivateDirectorySync(stagingDir)) return;
|
|
364
|
+
for (const entry of readdirSync2(legacyDir)) {
|
|
365
|
+
cpSync(join2(legacyDir, entry), join2(stagingDir, entry), {
|
|
366
|
+
recursive: true,
|
|
367
|
+
force: false,
|
|
368
|
+
errorOnExist: true
|
|
369
|
+
});
|
|
370
|
+
}
|
|
371
|
+
if (!isPathTreeFreeOfIndirectionSync(legacyDir)) {
|
|
372
|
+
rmSync(stagingDir, { recursive: true, force: true });
|
|
373
|
+
return;
|
|
374
|
+
}
|
|
375
|
+
if (!securePrivateTreeSync(stagingDir)) {
|
|
376
|
+
rmSync(stagingDir, { recursive: true, force: true });
|
|
377
|
+
return;
|
|
378
|
+
}
|
|
379
|
+
renameSync(stagingDir, currentDir);
|
|
217
380
|
rmSync(legacyDir, { recursive: true, force: true });
|
|
381
|
+
return;
|
|
218
382
|
} catch {
|
|
383
|
+
if (existsSync(stagingDir)) rmSync(stagingDir, { recursive: true, force: true });
|
|
384
|
+
return;
|
|
219
385
|
}
|
|
220
386
|
}
|
|
221
387
|
}
|
|
222
388
|
|
|
223
|
-
// src/proxy/
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
process.stderr.write(`${message} ${String(error51)}
|
|
230
|
-
`);
|
|
231
|
-
}
|
|
232
|
-
function resolveLogDir() {
|
|
233
|
-
const logDirEnv = process.env["LOG_DIR"];
|
|
234
|
-
if (logDirEnv !== void 0 && logDirEnv !== "") {
|
|
235
|
-
return path.isAbsolute(logDirEnv) ? logDirEnv : path.join(getDataDir(), logDirEnv);
|
|
236
|
-
}
|
|
237
|
-
return path.join(getDataDir(), "logs");
|
|
238
|
-
}
|
|
239
|
-
function getLogFilePath() {
|
|
240
|
-
const date5 = /* @__PURE__ */ new Date();
|
|
241
|
-
const yyyy = date5.getUTCFullYear();
|
|
242
|
-
const mm = String(date5.getUTCMonth() + 1).padStart(2, "0");
|
|
243
|
-
const dd = String(date5.getUTCDate()).padStart(2, "0");
|
|
244
|
-
return path.join(resolveLogDir(), `${yyyy}-${mm}-${dd}.jsonl`);
|
|
245
|
-
}
|
|
246
|
-
function getInspectorLogPath() {
|
|
247
|
-
const logFileEnv = process.env["AGENT_INSPECTOR_LOG_FILE"];
|
|
248
|
-
if (logFileEnv !== void 0 && logFileEnv !== "") {
|
|
249
|
-
return logFileEnv;
|
|
250
|
-
}
|
|
251
|
-
return path.join(getDataDir(), "logs", "inspector.log");
|
|
252
|
-
}
|
|
253
|
-
function readBoundedInteger(name, fallback, minimum, maximum) {
|
|
254
|
-
const raw = process.env[name];
|
|
255
|
-
if (raw === void 0 || raw === "") return fallback;
|
|
256
|
-
const parsed = Number(raw);
|
|
257
|
-
if (!Number.isInteger(parsed) || parsed < minimum || parsed > maximum) return fallback;
|
|
258
|
-
return parsed;
|
|
259
|
-
}
|
|
260
|
-
function getApplicationLogPolicy() {
|
|
261
|
-
const retentionDays = readBoundedInteger("LOG_RETENTION_DAYS", DEFAULT_RETENTION_DAYS, 1, 3650);
|
|
262
|
-
return {
|
|
263
|
-
maxBytes: readBoundedInteger(
|
|
264
|
-
"AGENT_INSPECTOR_APP_LOG_MAX_BYTES",
|
|
265
|
-
DEFAULT_APP_LOG_MAX_BYTES,
|
|
266
|
-
1,
|
|
267
|
-
1024 * 1024 * 1024
|
|
268
|
-
),
|
|
269
|
-
maxFiles: readBoundedInteger(
|
|
270
|
-
"AGENT_INSPECTOR_APP_LOG_MAX_FILES",
|
|
271
|
-
DEFAULT_APP_LOG_MAX_FILES,
|
|
272
|
-
1,
|
|
273
|
-
100
|
|
274
|
-
),
|
|
275
|
-
retentionMs: retentionDays * DAY_MS
|
|
276
|
-
};
|
|
277
|
-
}
|
|
278
|
-
function getRotatedGeneration(entry, baseName) {
|
|
279
|
-
const prefix = `${baseName}.`;
|
|
280
|
-
if (!entry.startsWith(prefix)) return null;
|
|
281
|
-
const suffix = entry.slice(prefix.length);
|
|
282
|
-
if (!/^\d+$/.test(suffix)) return null;
|
|
283
|
-
const generation = Number(suffix);
|
|
284
|
-
if (!Number.isSafeInteger(generation) || generation < 1) return null;
|
|
285
|
-
return generation;
|
|
286
|
-
}
|
|
287
|
-
async function listApplicationLogFiles(logPath) {
|
|
288
|
-
const directory = path.dirname(logPath);
|
|
289
|
-
const baseName = path.basename(logPath);
|
|
290
|
-
const entries = await readdir(directory);
|
|
291
|
-
const files = [];
|
|
292
|
-
for (const entry of entries) {
|
|
293
|
-
const generation = entry === baseName ? 0 : getRotatedGeneration(entry, baseName);
|
|
294
|
-
if (generation === null) continue;
|
|
295
|
-
const filePath = path.join(directory, entry);
|
|
296
|
-
try {
|
|
297
|
-
const fileStat = await stat(filePath);
|
|
298
|
-
if (!fileStat.isFile()) continue;
|
|
299
|
-
files.push({ generation, modifiedAt: fileStat.mtimeMs, path: filePath });
|
|
300
|
-
} catch {
|
|
301
|
-
}
|
|
302
|
-
}
|
|
303
|
-
return files;
|
|
304
|
-
}
|
|
305
|
-
async function removeApplicationLog(filePath) {
|
|
306
|
-
try {
|
|
307
|
-
await stat(filePath);
|
|
308
|
-
} catch {
|
|
309
|
-
return true;
|
|
310
|
-
}
|
|
311
|
-
try {
|
|
312
|
-
await unlink(filePath);
|
|
313
|
-
return true;
|
|
314
|
-
} catch {
|
|
315
|
-
return false;
|
|
316
|
-
}
|
|
317
|
-
}
|
|
318
|
-
async function maintainApplicationLogs(logPath, policy) {
|
|
319
|
-
const directory = path.dirname(logPath);
|
|
320
|
-
if (!ensurePrivateDirectorySync(directory)) return false;
|
|
321
|
-
let files;
|
|
322
|
-
try {
|
|
323
|
-
files = await listApplicationLogFiles(logPath);
|
|
324
|
-
} catch {
|
|
325
|
-
return false;
|
|
326
|
-
}
|
|
327
|
-
for (const file2 of files) {
|
|
328
|
-
if (!securePrivateFileSync(file2.path)) return false;
|
|
329
|
-
}
|
|
330
|
-
const cutoff = Date.now() - policy.retentionMs;
|
|
331
|
-
const retained = files.filter((file2) => file2.modifiedAt >= cutoff);
|
|
332
|
-
let maintained = true;
|
|
333
|
-
for (const file2 of files) {
|
|
334
|
-
if (file2.modifiedAt < cutoff && !await removeApplicationLog(file2.path)) maintained = false;
|
|
335
|
-
}
|
|
336
|
-
const rotated = retained.filter((file2) => file2.generation > 0).sort((left, right) => right.modifiedAt - left.modifiedAt);
|
|
337
|
-
const retainedRotatedCount = Math.max(0, policy.maxFiles - 1);
|
|
338
|
-
for (const file2 of rotated.slice(retainedRotatedCount)) {
|
|
339
|
-
if (!await removeApplicationLog(file2.path)) maintained = false;
|
|
340
|
-
}
|
|
341
|
-
return maintained;
|
|
342
|
-
}
|
|
343
|
-
async function moveApplicationLog(source, destination) {
|
|
344
|
-
try {
|
|
345
|
-
await stat(source);
|
|
346
|
-
} catch {
|
|
347
|
-
return true;
|
|
348
|
-
}
|
|
349
|
-
try {
|
|
350
|
-
await rename(source, destination);
|
|
351
|
-
if (!securePrivateFileSync(destination)) {
|
|
352
|
-
writeStderrFallback("[logger] Failed to secure rotated application log:", destination);
|
|
353
|
-
return false;
|
|
354
|
-
}
|
|
355
|
-
return true;
|
|
356
|
-
} catch (error51) {
|
|
357
|
-
writeStderrFallback("[logger] Failed to rotate application log:", error51);
|
|
358
|
-
return false;
|
|
359
|
-
}
|
|
360
|
-
}
|
|
361
|
-
async function rotateApplicationLog(logPath, maxFiles) {
|
|
362
|
-
if (maxFiles === 1) {
|
|
363
|
-
return await removeApplicationLog(logPath);
|
|
364
|
-
}
|
|
365
|
-
if (!await removeApplicationLog(`${logPath}.${String(maxFiles - 1)}`)) return false;
|
|
366
|
-
for (let generation = maxFiles - 2; generation >= 1; generation -= 1) {
|
|
367
|
-
if (!await moveApplicationLog(
|
|
368
|
-
`${logPath}.${String(generation)}`,
|
|
369
|
-
`${logPath}.${String(generation + 1)}`
|
|
370
|
-
)) {
|
|
371
|
-
return false;
|
|
372
|
-
}
|
|
373
|
-
}
|
|
374
|
-
return await moveApplicationLog(logPath, `${logPath}.1`);
|
|
375
|
-
}
|
|
376
|
-
async function rotateApplicationLogIfNeeded(logPath, incomingBytes, policy) {
|
|
377
|
-
try {
|
|
378
|
-
const fileStat = await stat(logPath);
|
|
379
|
-
if (fileStat.size > 0 && fileStat.size + incomingBytes > policy.maxBytes) {
|
|
380
|
-
return await rotateApplicationLog(logPath, policy.maxFiles);
|
|
381
|
-
}
|
|
382
|
-
return true;
|
|
383
|
-
} catch {
|
|
384
|
-
return true;
|
|
385
|
-
}
|
|
386
|
-
}
|
|
387
|
-
async function initLogger() {
|
|
388
|
-
const dir = resolveLogDir();
|
|
389
|
-
const policy = getApplicationLogPolicy();
|
|
390
|
-
const cutoff = Date.now() - policy.retentionMs;
|
|
391
|
-
try {
|
|
392
|
-
if (!ensurePrivateDirectorySync(dir)) {
|
|
393
|
-
writeStderrFallback("[logger] Failed to secure log directory:", dir);
|
|
394
|
-
} else if (!securePrivateTreeSync(dir)) {
|
|
395
|
-
writeStderrFallback("[logger] Failed to secure existing log files:", dir);
|
|
396
|
-
} else {
|
|
397
|
-
const entries = await readdir(dir);
|
|
398
|
-
for (const entry of entries) {
|
|
399
|
-
if (!entry.endsWith(".jsonl")) continue;
|
|
400
|
-
const fullPath = path.join(dir, entry);
|
|
401
|
-
try {
|
|
402
|
-
const s = await stat(fullPath);
|
|
403
|
-
if (s.mtimeMs < cutoff) {
|
|
404
|
-
await unlink(fullPath);
|
|
405
|
-
}
|
|
406
|
-
} catch {
|
|
407
|
-
}
|
|
408
|
-
}
|
|
409
|
-
}
|
|
410
|
-
} catch (err) {
|
|
411
|
-
writeStderrFallback("[logger] Failed to initialize log directory:", err);
|
|
412
|
-
}
|
|
413
|
-
const applicationLogPath = getInspectorLogPath();
|
|
414
|
-
if (!await maintainApplicationLogs(applicationLogPath, policy)) {
|
|
415
|
-
writeStderrFallback(
|
|
416
|
-
"[logger] Failed to initialize application log lifecycle:",
|
|
417
|
-
applicationLogPath
|
|
418
|
-
);
|
|
419
|
-
}
|
|
420
|
-
}
|
|
421
|
-
var loggerInitialization = null;
|
|
422
|
-
var applicationLogWriteQueue = Promise.resolve();
|
|
423
|
-
function ensureLoggerInitialized() {
|
|
424
|
-
if (loggerInitialization === null) loggerInitialization = initLogger();
|
|
425
|
-
return loggerInitialization;
|
|
426
|
-
}
|
|
427
|
-
async function appendApplicationLogLine(logPath, line, policy) {
|
|
428
|
-
const logDirPath = path.dirname(logPath);
|
|
429
|
-
if (!ensurePrivateDirectorySync(logDirPath)) {
|
|
430
|
-
return { ok: false, reason: "application log directory is not private" };
|
|
431
|
-
}
|
|
432
|
-
try {
|
|
433
|
-
if (!await rotateApplicationLogIfNeeded(logPath, Buffer2.byteLength(line, "utf-8"), policy)) {
|
|
434
|
-
return { ok: false, reason: "application log rotation failed" };
|
|
435
|
-
}
|
|
436
|
-
await appendFile(logPath, line, { encoding: "utf-8", mode: PRIVATE_FILE_MODE });
|
|
437
|
-
if (!securePrivateFileSync(logPath)) {
|
|
438
|
-
return { ok: false, reason: "application log permissions could not be secured" };
|
|
439
|
-
}
|
|
440
|
-
return { ok: true };
|
|
441
|
-
} catch (error51) {
|
|
442
|
-
return { ok: false, reason: error51 };
|
|
443
|
-
}
|
|
444
|
-
}
|
|
445
|
-
async function writeAppLog(message) {
|
|
446
|
-
const logPath = getInspectorLogPath();
|
|
447
|
-
const line = `[${(/* @__PURE__ */ new Date()).toISOString()}] ${message}
|
|
448
|
-
`;
|
|
449
|
-
const initialization = ensureLoggerInitialized();
|
|
450
|
-
const write = async () => {
|
|
451
|
-
await initialization;
|
|
452
|
-
const result = await appendApplicationLogLine(logPath, line, getApplicationLogPolicy());
|
|
453
|
-
if (!result.ok) writeStderrFallback(`[logger] Failed to write to ${logPath}:`, result.reason);
|
|
454
|
-
};
|
|
455
|
-
applicationLogWriteQueue = applicationLogWriteQueue.then(write, write);
|
|
456
|
-
await applicationLogWriteQueue;
|
|
457
|
-
}
|
|
458
|
-
var logger = {
|
|
459
|
-
debug(message, ...args) {
|
|
460
|
-
const msg = args.length > 0 ? `${message} ${args.map(String).join(" ")}` : message;
|
|
461
|
-
void writeAppLog(`[DEBUG] ${msg}`);
|
|
462
|
-
},
|
|
463
|
-
info(message, ...args) {
|
|
464
|
-
const msg = args.length > 0 ? `${message} ${args.map(String).join(" ")}` : message;
|
|
465
|
-
void writeAppLog(`[INFO] ${msg}`);
|
|
466
|
-
},
|
|
467
|
-
warn(message, ...args) {
|
|
468
|
-
const msg = args.length > 0 ? `${message} ${args.map(String).join(" ")}` : message;
|
|
469
|
-
void writeAppLog(`[WARN] ${msg}`);
|
|
470
|
-
},
|
|
471
|
-
error(message, ...args) {
|
|
472
|
-
const msg = args.length > 0 ? `${message} ${args.map(String).join(" ")}` : message;
|
|
473
|
-
void writeAppLog(`[ERROR] ${msg}`);
|
|
474
|
-
}
|
|
475
|
-
};
|
|
476
|
-
var writeBuffer = [];
|
|
477
|
-
var writeQueue = Promise.resolve();
|
|
478
|
-
var logWriteLock = Promise.resolve();
|
|
479
|
-
function drainBuffer() {
|
|
480
|
-
const toWrite = writeBuffer.join("");
|
|
481
|
-
writeBuffer = [];
|
|
482
|
-
return toWrite;
|
|
483
|
-
}
|
|
484
|
-
process.on("exit", () => {
|
|
485
|
-
if (writeBuffer.length > 0) {
|
|
486
|
-
const toWrite = drainBuffer();
|
|
487
|
-
try {
|
|
488
|
-
const filePath = getLogFilePath();
|
|
489
|
-
if (!ensurePrivateDirectorySync(path.dirname(filePath))) return;
|
|
490
|
-
appendFileSync(filePath, toWrite, { encoding: "utf-8", mode: PRIVATE_FILE_MODE });
|
|
491
|
-
void securePrivateFileSync(filePath);
|
|
492
|
-
} catch {
|
|
493
|
-
}
|
|
494
|
-
}
|
|
495
|
-
});
|
|
389
|
+
// src/proxy/jsonlRecovery.ts
|
|
390
|
+
import { createHash, randomUUID } from "node:crypto";
|
|
391
|
+
import { Buffer as Buffer2 } from "node:buffer";
|
|
392
|
+
import { constants as constants2, existsSync as existsSync2, lstatSync as lstatSync2 } from "node:fs";
|
|
393
|
+
import { link, lstat, open, readFile, readdir, stat, unlink } from "node:fs/promises";
|
|
394
|
+
import { basename, join as join3, resolve as resolve2 } from "node:path";
|
|
496
395
|
|
|
497
396
|
// node_modules/.bun/zod@4.4.3/node_modules/zod/v4/classic/external.js
|
|
498
397
|
var external_exports = {};
|
|
@@ -677,7 +576,7 @@ __export(external_exports, {
|
|
|
677
576
|
object: () => object,
|
|
678
577
|
optional: () => optional,
|
|
679
578
|
overwrite: () => _overwrite,
|
|
680
|
-
parse: () =>
|
|
579
|
+
parse: () => parse3,
|
|
681
580
|
parseAsync: () => parseAsync2,
|
|
682
581
|
partialRecord: () => partialRecord,
|
|
683
582
|
pipe: () => pipe,
|
|
@@ -997,7 +896,7 @@ __export(core_exports2, {
|
|
|
997
896
|
isValidJWT: () => isValidJWT,
|
|
998
897
|
locales: () => locales_exports,
|
|
999
898
|
meta: () => meta,
|
|
1000
|
-
parse: () =>
|
|
899
|
+
parse: () => parse2,
|
|
1001
900
|
parseAsync: () => parseAsync,
|
|
1002
901
|
prettifyError: () => prettifyError,
|
|
1003
902
|
process: () => process2,
|
|
@@ -1942,7 +1841,7 @@ var _parse = (_Err) => (schema, value, _ctx, _params) => {
|
|
|
1942
1841
|
}
|
|
1943
1842
|
return result.value;
|
|
1944
1843
|
};
|
|
1945
|
-
var
|
|
1844
|
+
var parse2 = /* @__PURE__ */ _parse($ZodRealError);
|
|
1946
1845
|
var _parseAsync = (_Err) => async (schema, value, _ctx, params) => {
|
|
1947
1846
|
const ctx = _ctx ? { ..._ctx, async: true } : { async: true };
|
|
1948
1847
|
let result = schema._zod.run({ value, issues: [] }, ctx);
|
|
@@ -4734,10 +4633,10 @@ var $ZodFunction = /* @__PURE__ */ $constructor("$ZodFunction", (inst, def) => {
|
|
|
4734
4633
|
throw new Error("implement() must be called with a function");
|
|
4735
4634
|
}
|
|
4736
4635
|
return function(...args) {
|
|
4737
|
-
const parsedArgs = inst._def.input ?
|
|
4636
|
+
const parsedArgs = inst._def.input ? parse2(inst._def.input, args) : args;
|
|
4738
4637
|
const result = Reflect.apply(func, this, parsedArgs);
|
|
4739
4638
|
if (inst._def.output) {
|
|
4740
|
-
return
|
|
4639
|
+
return parse2(inst._def.output, result);
|
|
4741
4640
|
}
|
|
4742
4641
|
return result;
|
|
4743
4642
|
};
|
|
@@ -13171,7 +13070,7 @@ var ZodRealError = /* @__PURE__ */ $constructor("ZodError", initializer2, {
|
|
|
13171
13070
|
});
|
|
13172
13071
|
|
|
13173
13072
|
// node_modules/.bun/zod@4.4.3/node_modules/zod/v4/classic/parse.js
|
|
13174
|
-
var
|
|
13073
|
+
var parse3 = /* @__PURE__ */ _parse(ZodRealError);
|
|
13175
13074
|
var parseAsync2 = /* @__PURE__ */ _parseAsync(ZodRealError);
|
|
13176
13075
|
var safeParse2 = /* @__PURE__ */ _safeParse(ZodRealError);
|
|
13177
13076
|
var safeParseAsync2 = /* @__PURE__ */ _safeParseAsync(ZodRealError);
|
|
@@ -13234,7 +13133,7 @@ var ZodType = /* @__PURE__ */ $constructor("ZodType", (inst, def) => {
|
|
|
13234
13133
|
inst.def = def;
|
|
13235
13134
|
inst.type = def.type;
|
|
13236
13135
|
Object.defineProperty(inst, "_def", { value: def });
|
|
13237
|
-
inst.parse = (data, params) =>
|
|
13136
|
+
inst.parse = (data, params) => parse3(inst, data, params, { callee: inst.parse });
|
|
13238
13137
|
inst.safeParse = (data, params) => safeParse2(inst, data, params);
|
|
13239
13138
|
inst.parseAsync = async (data, params) => parseAsync2(inst, data, params, { callee: inst.parseAsync });
|
|
13240
13139
|
inst.safeParseAsync = async (data, params) => safeParseAsync2(inst, data, params);
|
|
@@ -15027,6 +14926,15 @@ function trustAsJsonValue(value) {
|
|
|
15027
14926
|
}
|
|
15028
14927
|
|
|
15029
14928
|
// src/contracts/log.ts
|
|
14929
|
+
var LogIdSchema = external_exports.number().int().nonnegative().max(Number.MAX_SAFE_INTEGER);
|
|
14930
|
+
var CaptureIncompleteReasonSchema = external_exports.enum([
|
|
14931
|
+
"capacity-exceeded",
|
|
14932
|
+
"pipeline-closed",
|
|
14933
|
+
"write-failed",
|
|
14934
|
+
"finalize-failed",
|
|
14935
|
+
"upstream-stream-error",
|
|
14936
|
+
"shutdown"
|
|
14937
|
+
]);
|
|
15030
14938
|
var StreamingChunkSchema = external_exports.object({
|
|
15031
14939
|
index: external_exports.number(),
|
|
15032
14940
|
timestamp: external_exports.number(),
|
|
@@ -15039,7 +14947,7 @@ var StreamingChunksArraySchema = external_exports.object({
|
|
|
15039
14947
|
});
|
|
15040
14948
|
var LogBodyPartSchema = external_exports.enum(["request", "response"]);
|
|
15041
14949
|
var LogBodyChunkSchema = external_exports.object({
|
|
15042
|
-
logId:
|
|
14950
|
+
logId: LogIdSchema,
|
|
15043
14951
|
part: LogBodyPartSchema,
|
|
15044
14952
|
text: external_exports.string(),
|
|
15045
14953
|
offset: external_exports.number().int().nonnegative(),
|
|
@@ -15051,7 +14959,7 @@ var LogBodyChunkSchema = external_exports.object({
|
|
|
15051
14959
|
contentMode: external_exports.enum(["empty", "partial", "full"])
|
|
15052
14960
|
});
|
|
15053
14961
|
var CapturedLogSchema = external_exports.object({
|
|
15054
|
-
id:
|
|
14962
|
+
id: LogIdSchema,
|
|
15055
14963
|
timestamp: external_exports.string(),
|
|
15056
14964
|
method: external_exports.string(),
|
|
15057
14965
|
path: external_exports.string(),
|
|
@@ -15076,7 +14984,7 @@ var CapturedLogSchema = external_exports.object({
|
|
|
15076
14984
|
headers: external_exports.record(external_exports.string(), external_exports.string()).optional(),
|
|
15077
14985
|
apiFormat: external_exports.enum(["anthropic", "openai", "unknown"]).default("unknown"),
|
|
15078
14986
|
isTest: external_exports.boolean().optional().default(false),
|
|
15079
|
-
replayOfLogId:
|
|
14987
|
+
replayOfLogId: LogIdSchema.nullable().optional(),
|
|
15080
14988
|
providerName: external_exports.string().nullable().optional(),
|
|
15081
14989
|
clientPort: external_exports.number().nullable().optional(),
|
|
15082
14990
|
clientPid: external_exports.number().nullable().optional(),
|
|
@@ -15087,6 +14995,10 @@ var CapturedLogSchema = external_exports.object({
|
|
|
15087
14995
|
rawRequestBodyBytes: external_exports.number().int().nonnegative().nullable().optional(),
|
|
15088
14996
|
responseTextBytes: external_exports.number().int().nonnegative().nullable().optional(),
|
|
15089
14997
|
bodyContentMode: external_exports.enum(["full", "compact", "truncated"]).optional(),
|
|
14998
|
+
captureIncomplete: external_exports.boolean().optional(),
|
|
14999
|
+
droppedChunks: external_exports.number().int().nonnegative().optional(),
|
|
15000
|
+
droppedBytes: external_exports.number().int().nonnegative().optional(),
|
|
15001
|
+
captureIncompleteReason: CaptureIncompleteReasonSchema.nullable().optional(),
|
|
15090
15002
|
warnings: external_exports.array(external_exports.string()).optional(),
|
|
15091
15003
|
/** Error message from streaming response (e.g., SSE error event) */
|
|
15092
15004
|
error: external_exports.string().nullable().optional()
|
|
@@ -15459,32 +15371,681 @@ var OpenAIResponsesSSEventSchema = external_exports.object({
|
|
|
15459
15371
|
}).passthrough();
|
|
15460
15372
|
function parseOpenAIResponse(rawBody) {
|
|
15461
15373
|
try {
|
|
15462
|
-
const json2 = JSON.parse(rawBody);
|
|
15463
|
-
const result = OpenAIResponseSchema.safeParse(json2);
|
|
15464
|
-
if (result.success) return result.data;
|
|
15465
|
-
return null;
|
|
15374
|
+
const json2 = JSON.parse(rawBody);
|
|
15375
|
+
const result = OpenAIResponseSchema.safeParse(json2);
|
|
15376
|
+
if (result.success) return result.data;
|
|
15377
|
+
return null;
|
|
15378
|
+
} catch {
|
|
15379
|
+
return null;
|
|
15380
|
+
}
|
|
15381
|
+
}
|
|
15382
|
+
function parseOpenAIResponsesResponse(rawBody) {
|
|
15383
|
+
try {
|
|
15384
|
+
const json2 = JSON.parse(rawBody);
|
|
15385
|
+
const result = OpenAIResponsesResponseSchema.safeParse(json2);
|
|
15386
|
+
if (result.success) return result.data;
|
|
15387
|
+
return null;
|
|
15388
|
+
} catch {
|
|
15389
|
+
return null;
|
|
15390
|
+
}
|
|
15391
|
+
}
|
|
15392
|
+
|
|
15393
|
+
// src/proxy/schemas.ts
|
|
15394
|
+
var RequestModelSchema = external_exports.object({
|
|
15395
|
+
model: external_exports.string()
|
|
15396
|
+
});
|
|
15397
|
+
var LooseRequestSchema = external_exports.object({
|
|
15398
|
+
model: external_exports.string().optional(),
|
|
15399
|
+
metadata: external_exports.object({ user_id: external_exports.string().optional() }).passthrough().optional()
|
|
15400
|
+
});
|
|
15401
|
+
|
|
15402
|
+
// src/proxy/jsonlRecovery.ts
|
|
15403
|
+
var READ_CHUNK_BYTES = 64 * 1024;
|
|
15404
|
+
var QUARANTINE_DIRECTORY = "quarantine";
|
|
15405
|
+
var activeContext = null;
|
|
15406
|
+
function emptyHealth() {
|
|
15407
|
+
return {
|
|
15408
|
+
level: "ok",
|
|
15409
|
+
diagnostic: null,
|
|
15410
|
+
repairedFiles: 0,
|
|
15411
|
+
delimiterRepairs: 0,
|
|
15412
|
+
quarantinedTails: 0
|
|
15413
|
+
};
|
|
15414
|
+
}
|
|
15415
|
+
function contextFor(logDir) {
|
|
15416
|
+
const root = resolve2(logDir);
|
|
15417
|
+
if (activeContext === null || activeContext.root !== root) {
|
|
15418
|
+
activeContext = {
|
|
15419
|
+
root,
|
|
15420
|
+
health: emptyHealth(),
|
|
15421
|
+
startup: null,
|
|
15422
|
+
startupComplete: false,
|
|
15423
|
+
safeFiles: /* @__PURE__ */ new Map()
|
|
15424
|
+
};
|
|
15425
|
+
}
|
|
15426
|
+
return activeContext;
|
|
15427
|
+
}
|
|
15428
|
+
function copyHealth(health) {
|
|
15429
|
+
return { ...health };
|
|
15430
|
+
}
|
|
15431
|
+
function hashBytes(value) {
|
|
15432
|
+
return createHash("sha256").update(value).digest("hex");
|
|
15433
|
+
}
|
|
15434
|
+
function signatureFromStats(stats) {
|
|
15435
|
+
return {
|
|
15436
|
+
size: stats.size,
|
|
15437
|
+
modifiedAt: stats.mtimeMs,
|
|
15438
|
+
changedAt: stats.ctimeMs,
|
|
15439
|
+
device: stats.dev,
|
|
15440
|
+
inode: stats.ino
|
|
15441
|
+
};
|
|
15442
|
+
}
|
|
15443
|
+
function signaturesMatch(left, right) {
|
|
15444
|
+
return left.size === right.size && left.modifiedAt === right.modifiedAt && left.changedAt === right.changedAt && left.device === right.device && left.inode === right.inode;
|
|
15445
|
+
}
|
|
15446
|
+
function validateRecord(bytes) {
|
|
15447
|
+
const withoutCarriageReturn = bytes.length > 0 && bytes[bytes.length - 1] === 13 ? bytes.subarray(0, -1) : bytes;
|
|
15448
|
+
const text = withoutCarriageReturn.toString("utf-8");
|
|
15449
|
+
if (text.trim() === "") return { valid: true };
|
|
15450
|
+
let parsed;
|
|
15451
|
+
try {
|
|
15452
|
+
parsed = JSON.parse(text);
|
|
15453
|
+
} catch {
|
|
15454
|
+
return { valid: false, reason: "invalid-json" };
|
|
15455
|
+
}
|
|
15456
|
+
return CapturedLogSchema.safeParse(parsed).success ? { valid: true } : { valid: false, reason: "invalid-log-schema" };
|
|
15457
|
+
}
|
|
15458
|
+
async function scanFile(handle, size) {
|
|
15459
|
+
const readBuffer = Buffer2.alloc(READ_CHUNK_BYTES);
|
|
15460
|
+
let position = 0;
|
|
15461
|
+
let pending = Buffer2.alloc(0);
|
|
15462
|
+
let pendingOffset = 0;
|
|
15463
|
+
let line = 1;
|
|
15464
|
+
while (position < size) {
|
|
15465
|
+
const length = Math.min(READ_CHUNK_BYTES, size - position);
|
|
15466
|
+
let bytesRead;
|
|
15467
|
+
try {
|
|
15468
|
+
const result = await handle.read(readBuffer, 0, length, position);
|
|
15469
|
+
bytesRead = result.bytesRead;
|
|
15470
|
+
} catch (error51) {
|
|
15471
|
+
return { status: "failed", reason: `read failed: ${String(error51)}` };
|
|
15472
|
+
}
|
|
15473
|
+
if (bytesRead === 0) {
|
|
15474
|
+
return { status: "failed", reason: "captured-log file changed while being scanned" };
|
|
15475
|
+
}
|
|
15476
|
+
const chunk = readBuffer.subarray(0, bytesRead);
|
|
15477
|
+
const combined = pending.length === 0 ? Buffer2.from(chunk) : Buffer2.concat([pending, chunk]);
|
|
15478
|
+
let consumed = 0;
|
|
15479
|
+
let newline = combined.indexOf(10, consumed);
|
|
15480
|
+
while (newline !== -1) {
|
|
15481
|
+
const record2 = combined.subarray(consumed, newline);
|
|
15482
|
+
const validation = validateRecord(record2);
|
|
15483
|
+
if (!validation.valid) {
|
|
15484
|
+
return {
|
|
15485
|
+
status: "interior-corruption",
|
|
15486
|
+
line,
|
|
15487
|
+
byteOffset: pendingOffset + consumed,
|
|
15488
|
+
recordHash: hashBytes(record2),
|
|
15489
|
+
reason: validation.reason
|
|
15490
|
+
};
|
|
15491
|
+
}
|
|
15492
|
+
consumed = newline + 1;
|
|
15493
|
+
line += 1;
|
|
15494
|
+
newline = combined.indexOf(10, consumed);
|
|
15495
|
+
}
|
|
15496
|
+
pending = Buffer2.from(combined.subarray(consumed));
|
|
15497
|
+
pendingOffset += consumed;
|
|
15498
|
+
position += bytesRead;
|
|
15499
|
+
}
|
|
15500
|
+
return { status: "complete", pending, pendingOffset, nextLine: line };
|
|
15501
|
+
}
|
|
15502
|
+
async function syncDirectory(directory) {
|
|
15503
|
+
let handle = null;
|
|
15504
|
+
try {
|
|
15505
|
+
handle = await open(directory, "r");
|
|
15506
|
+
await handle.sync();
|
|
15507
|
+
} catch {
|
|
15508
|
+
} finally {
|
|
15509
|
+
await handle?.close().catch(() => void 0);
|
|
15510
|
+
}
|
|
15511
|
+
}
|
|
15512
|
+
async function removeTemporaryFile(filePath) {
|
|
15513
|
+
await unlink(filePath).catch(() => void 0);
|
|
15514
|
+
}
|
|
15515
|
+
function readOwnProperty(value, name) {
|
|
15516
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) return void 0;
|
|
15517
|
+
return Object.getOwnPropertyDescriptor(value, name)?.value;
|
|
15518
|
+
}
|
|
15519
|
+
async function inspectExistingQuarantine(filePath, expected) {
|
|
15520
|
+
if (!existsSync2(filePath)) return "missing";
|
|
15521
|
+
try {
|
|
15522
|
+
const parsed = JSON.parse(await readFile(filePath, "utf-8"));
|
|
15523
|
+
return readOwnProperty(parsed, "schemaVersion") === expected.schemaVersion && readOwnProperty(parsed, "reason") === expected.reason && readOwnProperty(parsed, "sourceFile") === expected.sourceFile && readOwnProperty(parsed, "sourcePathHash") === expected.sourcePathHash && readOwnProperty(parsed, "tailOffset") === expected.tailOffset && readOwnProperty(parsed, "tailBytes") === expected.tailBytes && readOwnProperty(parsed, "tailSha256") === expected.tailSha256 && readOwnProperty(parsed, "tailBase64") === expected.tailBase64 ? "matching" : "conflicting";
|
|
15524
|
+
} catch {
|
|
15525
|
+
return "conflicting";
|
|
15526
|
+
}
|
|
15527
|
+
}
|
|
15528
|
+
async function quarantineTail(context, sourceFile, tail, tailOffset) {
|
|
15529
|
+
const quarantineDirectory = join3(context.root, QUARANTINE_DIRECTORY);
|
|
15530
|
+
if (!ensurePrivateDirectorySync(quarantineDirectory)) return null;
|
|
15531
|
+
const tailSha256 = hashBytes(tail);
|
|
15532
|
+
const sourceFileName = basename(sourceFile);
|
|
15533
|
+
const destination = join3(quarantineDirectory, `${sourceFileName}.tail-${tailSha256}.json`);
|
|
15534
|
+
const temporary = join3(
|
|
15535
|
+
quarantineDirectory,
|
|
15536
|
+
`.${sourceFileName}.${String(process.pid)}.${randomUUID()}.tmp`
|
|
15537
|
+
);
|
|
15538
|
+
const record2 = {
|
|
15539
|
+
schemaVersion: 1,
|
|
15540
|
+
reason: "invalid-final-jsonl-record",
|
|
15541
|
+
sourceFile: sourceFileName,
|
|
15542
|
+
sourcePathHash: hashBytes(Buffer2.from(resolve2(sourceFile), "utf-8")),
|
|
15543
|
+
recoveredAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
15544
|
+
tailOffset,
|
|
15545
|
+
tailBytes: tail.length,
|
|
15546
|
+
tailSha256,
|
|
15547
|
+
tailBase64: tail.toString("base64")
|
|
15548
|
+
};
|
|
15549
|
+
const existing = await inspectExistingQuarantine(destination, record2);
|
|
15550
|
+
if (existing === "matching") {
|
|
15551
|
+
return securePrivateFileSync(destination) ? destination : null;
|
|
15552
|
+
}
|
|
15553
|
+
if (existing === "conflicting") return null;
|
|
15554
|
+
let handle = null;
|
|
15555
|
+
try {
|
|
15556
|
+
handle = await open(temporary, "wx", PRIVATE_FILE_MODE);
|
|
15557
|
+
await handle.writeFile(`${JSON.stringify(record2)}
|
|
15558
|
+
`, "utf-8");
|
|
15559
|
+
await handle.sync();
|
|
15560
|
+
await handle.close();
|
|
15561
|
+
handle = null;
|
|
15562
|
+
if (!securePrivateFileSync(temporary)) {
|
|
15563
|
+
await removeTemporaryFile(temporary);
|
|
15564
|
+
return null;
|
|
15565
|
+
}
|
|
15566
|
+
await link(temporary, destination);
|
|
15567
|
+
await unlink(temporary);
|
|
15568
|
+
if (!securePrivateFileSync(destination)) return null;
|
|
15569
|
+
await syncDirectory(quarantineDirectory);
|
|
15570
|
+
return destination;
|
|
15571
|
+
} catch {
|
|
15572
|
+
await handle?.close().catch(() => void 0);
|
|
15573
|
+
await removeTemporaryFile(temporary);
|
|
15574
|
+
const racedExisting = await inspectExistingQuarantine(destination, record2);
|
|
15575
|
+
return racedExisting === "matching" && securePrivateFileSync(destination) ? destination : null;
|
|
15576
|
+
}
|
|
15577
|
+
}
|
|
15578
|
+
async function recoverFile(context, filePath) {
|
|
15579
|
+
if (!existsSync2(filePath)) {
|
|
15580
|
+
context.safeFiles.delete(filePath);
|
|
15581
|
+
return {
|
|
15582
|
+
status: "clean",
|
|
15583
|
+
signature: { size: 0, modifiedAt: 0, changedAt: 0, device: 0, inode: 0 }
|
|
15584
|
+
};
|
|
15585
|
+
}
|
|
15586
|
+
let fileStats;
|
|
15587
|
+
try {
|
|
15588
|
+
fileStats = await lstat(filePath);
|
|
15589
|
+
} catch (error51) {
|
|
15590
|
+
return { status: "failed", reason: `stat failed: ${String(error51)}` };
|
|
15591
|
+
}
|
|
15592
|
+
if (fileStats.isSymbolicLink() || !fileStats.isFile()) {
|
|
15593
|
+
return { status: "failed", reason: "captured-log path is not a regular private file" };
|
|
15594
|
+
}
|
|
15595
|
+
const initialSignature = signatureFromStats(fileStats);
|
|
15596
|
+
const safeSignature = context.safeFiles.get(filePath);
|
|
15597
|
+
if (safeSignature !== void 0 && signaturesMatch(safeSignature, initialSignature)) {
|
|
15598
|
+
return { status: "clean", signature: initialSignature };
|
|
15599
|
+
}
|
|
15600
|
+
let handle = null;
|
|
15601
|
+
try {
|
|
15602
|
+
handle = await open(filePath, constants2.O_RDWR | constants2.O_NOFOLLOW);
|
|
15603
|
+
const openedStats = await handle.stat();
|
|
15604
|
+
if (!openedStats.isFile()) {
|
|
15605
|
+
return { status: "failed", reason: "captured-log handle is not a regular file" };
|
|
15606
|
+
}
|
|
15607
|
+
const openedSignature = signatureFromStats(openedStats);
|
|
15608
|
+
if (!signaturesMatch(initialSignature, openedSignature)) {
|
|
15609
|
+
return {
|
|
15610
|
+
status: "failed",
|
|
15611
|
+
reason: "captured-log path changed between metadata validation and open"
|
|
15612
|
+
};
|
|
15613
|
+
}
|
|
15614
|
+
const scan = await scanFile(handle, openedStats.size);
|
|
15615
|
+
const scannedSignature = signatureFromStats(await handle.stat());
|
|
15616
|
+
if (!signaturesMatch(openedSignature, scannedSignature)) {
|
|
15617
|
+
return {
|
|
15618
|
+
status: "failed",
|
|
15619
|
+
reason: "captured-log file changed while recovery was scanning it"
|
|
15620
|
+
};
|
|
15621
|
+
}
|
|
15622
|
+
switch (scan.status) {
|
|
15623
|
+
case "failed":
|
|
15624
|
+
return scan;
|
|
15625
|
+
case "interior-corruption":
|
|
15626
|
+
return scan;
|
|
15627
|
+
case "complete": {
|
|
15628
|
+
if (scan.pending.length === 0) {
|
|
15629
|
+
return { status: "clean", signature: signatureFromStats(await handle.stat()) };
|
|
15630
|
+
}
|
|
15631
|
+
const validation = validateRecord(scan.pending);
|
|
15632
|
+
if (validation.valid) {
|
|
15633
|
+
const write = await handle.write(Buffer2.from("\n", "utf-8"), 0, 1, openedStats.size);
|
|
15634
|
+
if (write.bytesWritten !== 1) {
|
|
15635
|
+
return { status: "failed", reason: "captured-log delimiter append was incomplete" };
|
|
15636
|
+
}
|
|
15637
|
+
await handle.sync();
|
|
15638
|
+
return {
|
|
15639
|
+
status: "delimiter-appended",
|
|
15640
|
+
signature: signatureFromStats(await handle.stat())
|
|
15641
|
+
};
|
|
15642
|
+
}
|
|
15643
|
+
const quarantinePath = await quarantineTail(
|
|
15644
|
+
context,
|
|
15645
|
+
filePath,
|
|
15646
|
+
scan.pending,
|
|
15647
|
+
scan.pendingOffset
|
|
15648
|
+
);
|
|
15649
|
+
if (quarantinePath === null) {
|
|
15650
|
+
return { status: "failed", reason: "invalid tail could not be privately quarantined" };
|
|
15651
|
+
}
|
|
15652
|
+
const beforeTruncate = signatureFromStats(await handle.stat());
|
|
15653
|
+
if (!signaturesMatch(openedSignature, beforeTruncate)) {
|
|
15654
|
+
return {
|
|
15655
|
+
status: "failed",
|
|
15656
|
+
reason: "captured-log file changed before invalid-tail truncation"
|
|
15657
|
+
};
|
|
15658
|
+
}
|
|
15659
|
+
await handle.truncate(scan.pendingOffset);
|
|
15660
|
+
await handle.sync();
|
|
15661
|
+
return {
|
|
15662
|
+
status: "tail-quarantined",
|
|
15663
|
+
signature: signatureFromStats(await handle.stat())
|
|
15664
|
+
};
|
|
15665
|
+
}
|
|
15666
|
+
}
|
|
15667
|
+
return { status: "failed", reason: "unsupported captured-log scan state" };
|
|
15668
|
+
} catch (error51) {
|
|
15669
|
+
return { status: "failed", reason: String(error51) };
|
|
15670
|
+
} finally {
|
|
15671
|
+
await handle?.close().catch(() => void 0);
|
|
15672
|
+
}
|
|
15673
|
+
}
|
|
15674
|
+
function applyFileResult(context, filePath, result) {
|
|
15675
|
+
const file2 = basename(filePath);
|
|
15676
|
+
switch (result.status) {
|
|
15677
|
+
case "clean":
|
|
15678
|
+
context.safeFiles.set(filePath, result.signature);
|
|
15679
|
+
return;
|
|
15680
|
+
case "delimiter-appended":
|
|
15681
|
+
context.safeFiles.set(filePath, result.signature);
|
|
15682
|
+
context.health.delimiterRepairs += 1;
|
|
15683
|
+
context.health.repairedFiles += 1;
|
|
15684
|
+
return;
|
|
15685
|
+
case "tail-quarantined":
|
|
15686
|
+
context.safeFiles.set(filePath, result.signature);
|
|
15687
|
+
context.health.quarantinedTails += 1;
|
|
15688
|
+
context.health.repairedFiles += 1;
|
|
15689
|
+
if (context.health.level !== "unavailable") {
|
|
15690
|
+
context.health.level = "degraded";
|
|
15691
|
+
context.health.diagnostic = `Recovered and quarantined an invalid JSONL tail in ${file2}`;
|
|
15692
|
+
}
|
|
15693
|
+
return;
|
|
15694
|
+
case "interior-corruption":
|
|
15695
|
+
context.safeFiles.delete(filePath);
|
|
15696
|
+
context.health.level = "unavailable";
|
|
15697
|
+
context.health.diagnostic = `JSONL corruption in ${file2} at line ${String(result.line)} (offset ${String(result.byteOffset)}, ${result.reason}, sha256 ${result.recordHash})`;
|
|
15698
|
+
return;
|
|
15699
|
+
case "failed":
|
|
15700
|
+
context.safeFiles.delete(filePath);
|
|
15701
|
+
context.health.level = "unavailable";
|
|
15702
|
+
context.health.diagnostic = `JSONL recovery failed for ${file2}: ${result.reason}`;
|
|
15703
|
+
}
|
|
15704
|
+
}
|
|
15705
|
+
async function runStartupRecovery(context) {
|
|
15706
|
+
if (!ensurePrivateDirectorySync(context.root)) {
|
|
15707
|
+
context.health.level = "unavailable";
|
|
15708
|
+
context.health.diagnostic = "Captured-log directory could not be made private";
|
|
15709
|
+
return copyHealth(context.health);
|
|
15710
|
+
}
|
|
15711
|
+
let entries;
|
|
15712
|
+
try {
|
|
15713
|
+
entries = await readdir(context.root);
|
|
15714
|
+
} catch (error51) {
|
|
15715
|
+
context.health.level = "unavailable";
|
|
15716
|
+
context.health.diagnostic = `Captured-log directory could not be listed: ${String(error51)}`;
|
|
15717
|
+
return copyHealth(context.health);
|
|
15718
|
+
}
|
|
15719
|
+
const files = entries.filter((entry) => entry.endsWith(".jsonl")).sort();
|
|
15720
|
+
for (const file2 of files) {
|
|
15721
|
+
const filePath = join3(context.root, file2);
|
|
15722
|
+
const result = await recoverFile(context, filePath);
|
|
15723
|
+
applyFileResult(context, filePath, result);
|
|
15724
|
+
if (context.health.level === "unavailable") break;
|
|
15725
|
+
}
|
|
15726
|
+
return copyHealth(context.health);
|
|
15727
|
+
}
|
|
15728
|
+
async function recoverCapturedLogStorage(logDir) {
|
|
15729
|
+
const context = contextFor(logDir);
|
|
15730
|
+
if (context.startup === null) {
|
|
15731
|
+
context.startup = runStartupRecovery(context).then((health) => {
|
|
15732
|
+
context.startupComplete = true;
|
|
15733
|
+
return health;
|
|
15734
|
+
});
|
|
15735
|
+
}
|
|
15736
|
+
return await context.startup;
|
|
15737
|
+
}
|
|
15738
|
+
function canAppendCapturedLogFileOnExit(logDir, filePath) {
|
|
15739
|
+
const context = contextFor(logDir);
|
|
15740
|
+
if (!context.startupComplete || context.health.level === "unavailable") return false;
|
|
15741
|
+
const trusted = context.safeFiles.get(filePath);
|
|
15742
|
+
if (trusted === void 0) return false;
|
|
15743
|
+
try {
|
|
15744
|
+
const observed = lstatSync2(filePath);
|
|
15745
|
+
if (observed === void 0 || observed.isSymbolicLink() || !observed.isFile()) return false;
|
|
15746
|
+
return signaturesMatch(trusted, signatureFromStats(observed));
|
|
15747
|
+
} catch {
|
|
15748
|
+
return false;
|
|
15749
|
+
}
|
|
15750
|
+
}
|
|
15751
|
+
|
|
15752
|
+
// src/proxy/logger.ts
|
|
15753
|
+
var DAY_MS = 24 * 60 * 60 * 1e3;
|
|
15754
|
+
var DEFAULT_RETENTION_DAYS = 7;
|
|
15755
|
+
var DEFAULT_APP_LOG_MAX_BYTES = 10 * 1024 * 1024;
|
|
15756
|
+
var DEFAULT_APP_LOG_MAX_FILES = 5;
|
|
15757
|
+
function writeStderrFallback(message, error51) {
|
|
15758
|
+
process.stderr.write(`${message} ${String(error51)}
|
|
15759
|
+
`);
|
|
15760
|
+
}
|
|
15761
|
+
function resolveLogDir() {
|
|
15762
|
+
const logDirEnv = process.env["LOG_DIR"];
|
|
15763
|
+
if (logDirEnv !== void 0 && logDirEnv !== "") {
|
|
15764
|
+
return path.isAbsolute(logDirEnv) ? logDirEnv : path.join(getDataDir(), logDirEnv);
|
|
15765
|
+
}
|
|
15766
|
+
return path.join(getDataDir(), "logs");
|
|
15767
|
+
}
|
|
15768
|
+
function getLogFilePath() {
|
|
15769
|
+
const date5 = /* @__PURE__ */ new Date();
|
|
15770
|
+
const yyyy = date5.getUTCFullYear();
|
|
15771
|
+
const mm = String(date5.getUTCMonth() + 1).padStart(2, "0");
|
|
15772
|
+
const dd = String(date5.getUTCDate()).padStart(2, "0");
|
|
15773
|
+
return path.join(resolveLogDir(), `${yyyy}-${mm}-${dd}.jsonl`);
|
|
15774
|
+
}
|
|
15775
|
+
function getInspectorLogPath() {
|
|
15776
|
+
const logFileEnv = process.env["AGENT_INSPECTOR_LOG_FILE"];
|
|
15777
|
+
if (logFileEnv !== void 0 && logFileEnv !== "") {
|
|
15778
|
+
return logFileEnv;
|
|
15779
|
+
}
|
|
15780
|
+
return path.join(getDataDir(), "logs", "inspector.log");
|
|
15781
|
+
}
|
|
15782
|
+
function readBoundedInteger(name, fallback, minimum, maximum) {
|
|
15783
|
+
const raw = process.env[name];
|
|
15784
|
+
if (raw === void 0 || raw === "") return fallback;
|
|
15785
|
+
const parsed = Number(raw);
|
|
15786
|
+
if (!Number.isInteger(parsed) || parsed < minimum || parsed > maximum) return fallback;
|
|
15787
|
+
return parsed;
|
|
15788
|
+
}
|
|
15789
|
+
function getApplicationLogPolicy() {
|
|
15790
|
+
const retentionDays = readBoundedInteger("LOG_RETENTION_DAYS", DEFAULT_RETENTION_DAYS, 1, 3650);
|
|
15791
|
+
return {
|
|
15792
|
+
maxBytes: readBoundedInteger(
|
|
15793
|
+
"AGENT_INSPECTOR_APP_LOG_MAX_BYTES",
|
|
15794
|
+
DEFAULT_APP_LOG_MAX_BYTES,
|
|
15795
|
+
1,
|
|
15796
|
+
1024 * 1024 * 1024
|
|
15797
|
+
),
|
|
15798
|
+
maxFiles: readBoundedInteger(
|
|
15799
|
+
"AGENT_INSPECTOR_APP_LOG_MAX_FILES",
|
|
15800
|
+
DEFAULT_APP_LOG_MAX_FILES,
|
|
15801
|
+
1,
|
|
15802
|
+
100
|
|
15803
|
+
),
|
|
15804
|
+
retentionMs: retentionDays * DAY_MS
|
|
15805
|
+
};
|
|
15806
|
+
}
|
|
15807
|
+
function getRotatedGeneration(entry, baseName) {
|
|
15808
|
+
const prefix = `${baseName}.`;
|
|
15809
|
+
if (!entry.startsWith(prefix)) return null;
|
|
15810
|
+
const suffix = entry.slice(prefix.length);
|
|
15811
|
+
if (!/^\d+$/.test(suffix)) return null;
|
|
15812
|
+
const generation = Number(suffix);
|
|
15813
|
+
if (!Number.isSafeInteger(generation) || generation < 1) return null;
|
|
15814
|
+
return generation;
|
|
15815
|
+
}
|
|
15816
|
+
async function listApplicationLogFiles(logPath) {
|
|
15817
|
+
const directory = path.dirname(logPath);
|
|
15818
|
+
const baseName = path.basename(logPath);
|
|
15819
|
+
const entries = await readdir2(directory);
|
|
15820
|
+
const files = [];
|
|
15821
|
+
for (const entry of entries) {
|
|
15822
|
+
const generation = entry === baseName ? 0 : getRotatedGeneration(entry, baseName);
|
|
15823
|
+
if (generation === null) continue;
|
|
15824
|
+
const filePath = path.join(directory, entry);
|
|
15825
|
+
try {
|
|
15826
|
+
const fileStat = await stat2(filePath);
|
|
15827
|
+
if (!fileStat.isFile()) continue;
|
|
15828
|
+
files.push({ generation, modifiedAt: fileStat.mtimeMs, path: filePath });
|
|
15829
|
+
} catch {
|
|
15830
|
+
}
|
|
15831
|
+
}
|
|
15832
|
+
return files;
|
|
15833
|
+
}
|
|
15834
|
+
async function removeApplicationLog(filePath) {
|
|
15835
|
+
try {
|
|
15836
|
+
await stat2(filePath);
|
|
15466
15837
|
} catch {
|
|
15467
|
-
return
|
|
15838
|
+
return true;
|
|
15839
|
+
}
|
|
15840
|
+
try {
|
|
15841
|
+
await unlink2(filePath);
|
|
15842
|
+
return true;
|
|
15843
|
+
} catch {
|
|
15844
|
+
return false;
|
|
15468
15845
|
}
|
|
15469
15846
|
}
|
|
15470
|
-
function
|
|
15847
|
+
async function maintainApplicationLogs(logPath, policy) {
|
|
15848
|
+
const directory = path.dirname(logPath);
|
|
15849
|
+
if (!ensurePrivateDirectorySync(directory)) return false;
|
|
15850
|
+
let files;
|
|
15471
15851
|
try {
|
|
15472
|
-
|
|
15473
|
-
const result = OpenAIResponsesResponseSchema.safeParse(json2);
|
|
15474
|
-
if (result.success) return result.data;
|
|
15475
|
-
return null;
|
|
15852
|
+
files = await listApplicationLogFiles(logPath);
|
|
15476
15853
|
} catch {
|
|
15477
|
-
return
|
|
15854
|
+
return false;
|
|
15855
|
+
}
|
|
15856
|
+
for (const file2 of files) {
|
|
15857
|
+
if (!securePrivateFileSync(file2.path)) return false;
|
|
15858
|
+
}
|
|
15859
|
+
const cutoff = Date.now() - policy.retentionMs;
|
|
15860
|
+
const retained = files.filter((file2) => file2.modifiedAt >= cutoff);
|
|
15861
|
+
let maintained = true;
|
|
15862
|
+
for (const file2 of files) {
|
|
15863
|
+
if (file2.modifiedAt < cutoff && !await removeApplicationLog(file2.path)) maintained = false;
|
|
15864
|
+
}
|
|
15865
|
+
const rotated = retained.filter((file2) => file2.generation > 0).sort((left, right) => right.modifiedAt - left.modifiedAt);
|
|
15866
|
+
const retainedRotatedCount = Math.max(0, policy.maxFiles - 1);
|
|
15867
|
+
for (const file2 of rotated.slice(retainedRotatedCount)) {
|
|
15868
|
+
if (!await removeApplicationLog(file2.path)) maintained = false;
|
|
15478
15869
|
}
|
|
15870
|
+
return maintained;
|
|
15479
15871
|
}
|
|
15480
|
-
|
|
15481
|
-
|
|
15482
|
-
|
|
15483
|
-
|
|
15484
|
-
|
|
15485
|
-
|
|
15486
|
-
|
|
15487
|
-
|
|
15872
|
+
async function moveApplicationLog(source, destination) {
|
|
15873
|
+
try {
|
|
15874
|
+
await stat2(source);
|
|
15875
|
+
} catch {
|
|
15876
|
+
return true;
|
|
15877
|
+
}
|
|
15878
|
+
try {
|
|
15879
|
+
await rename(source, destination);
|
|
15880
|
+
if (!securePrivateFileSync(destination)) {
|
|
15881
|
+
writeStderrFallback("[logger] Failed to secure rotated application log:", destination);
|
|
15882
|
+
return false;
|
|
15883
|
+
}
|
|
15884
|
+
return true;
|
|
15885
|
+
} catch (error51) {
|
|
15886
|
+
writeStderrFallback("[logger] Failed to rotate application log:", error51);
|
|
15887
|
+
return false;
|
|
15888
|
+
}
|
|
15889
|
+
}
|
|
15890
|
+
async function rotateApplicationLog(logPath, maxFiles) {
|
|
15891
|
+
if (maxFiles === 1) {
|
|
15892
|
+
return await removeApplicationLog(logPath);
|
|
15893
|
+
}
|
|
15894
|
+
if (!await removeApplicationLog(`${logPath}.${String(maxFiles - 1)}`)) return false;
|
|
15895
|
+
for (let generation = maxFiles - 2; generation >= 1; generation -= 1) {
|
|
15896
|
+
if (!await moveApplicationLog(
|
|
15897
|
+
`${logPath}.${String(generation)}`,
|
|
15898
|
+
`${logPath}.${String(generation + 1)}`
|
|
15899
|
+
)) {
|
|
15900
|
+
return false;
|
|
15901
|
+
}
|
|
15902
|
+
}
|
|
15903
|
+
return await moveApplicationLog(logPath, `${logPath}.1`);
|
|
15904
|
+
}
|
|
15905
|
+
async function rotateApplicationLogIfNeeded(logPath, incomingBytes, policy) {
|
|
15906
|
+
try {
|
|
15907
|
+
const fileStat = await stat2(logPath);
|
|
15908
|
+
if (fileStat.size > 0 && fileStat.size + incomingBytes > policy.maxBytes) {
|
|
15909
|
+
return await rotateApplicationLog(logPath, policy.maxFiles);
|
|
15910
|
+
}
|
|
15911
|
+
return true;
|
|
15912
|
+
} catch {
|
|
15913
|
+
return true;
|
|
15914
|
+
}
|
|
15915
|
+
}
|
|
15916
|
+
async function initLogger() {
|
|
15917
|
+
const dir = resolveLogDir();
|
|
15918
|
+
const policy = getApplicationLogPolicy();
|
|
15919
|
+
const cutoff = Date.now() - policy.retentionMs;
|
|
15920
|
+
try {
|
|
15921
|
+
if (!ensurePrivateDirectorySync(dir)) {
|
|
15922
|
+
writeStderrFallback("[logger] Failed to secure log directory:", dir);
|
|
15923
|
+
} else if (!securePrivateTreeSync(dir)) {
|
|
15924
|
+
writeStderrFallback("[logger] Failed to secure existing log files:", dir);
|
|
15925
|
+
} else {
|
|
15926
|
+
const recovery = await recoverCapturedLogStorage(dir);
|
|
15927
|
+
if (recovery.level === "unavailable") {
|
|
15928
|
+
writeStderrFallback(
|
|
15929
|
+
"[logger] Captured-log recovery blocked readiness:",
|
|
15930
|
+
recovery.diagnostic ?? "unknown recovery failure"
|
|
15931
|
+
);
|
|
15932
|
+
} else {
|
|
15933
|
+
const entries = await readdir2(dir);
|
|
15934
|
+
for (const entry of entries) {
|
|
15935
|
+
if (!entry.endsWith(".jsonl")) continue;
|
|
15936
|
+
const fullPath = path.join(dir, entry);
|
|
15937
|
+
try {
|
|
15938
|
+
const s = await stat2(fullPath);
|
|
15939
|
+
if (s.mtimeMs < cutoff) {
|
|
15940
|
+
await unlink2(fullPath);
|
|
15941
|
+
}
|
|
15942
|
+
} catch {
|
|
15943
|
+
}
|
|
15944
|
+
}
|
|
15945
|
+
}
|
|
15946
|
+
}
|
|
15947
|
+
} catch (err) {
|
|
15948
|
+
writeStderrFallback("[logger] Failed to initialize log directory:", err);
|
|
15949
|
+
}
|
|
15950
|
+
const applicationLogPath = getInspectorLogPath();
|
|
15951
|
+
if (!await maintainApplicationLogs(applicationLogPath, policy)) {
|
|
15952
|
+
writeStderrFallback(
|
|
15953
|
+
"[logger] Failed to initialize application log lifecycle:",
|
|
15954
|
+
applicationLogPath
|
|
15955
|
+
);
|
|
15956
|
+
}
|
|
15957
|
+
}
|
|
15958
|
+
var loggerInitialization = null;
|
|
15959
|
+
var applicationLogWriteQueue = Promise.resolve();
|
|
15960
|
+
function ensureLoggerInitialized() {
|
|
15961
|
+
if (loggerInitialization === null) loggerInitialization = initLogger();
|
|
15962
|
+
return loggerInitialization;
|
|
15963
|
+
}
|
|
15964
|
+
async function appendApplicationLogLine(logPath, line, policy) {
|
|
15965
|
+
const logDirPath = path.dirname(logPath);
|
|
15966
|
+
if (!ensurePrivateDirectorySync(logDirPath)) {
|
|
15967
|
+
return { ok: false, reason: "application log directory is not private" };
|
|
15968
|
+
}
|
|
15969
|
+
try {
|
|
15970
|
+
if (!await rotateApplicationLogIfNeeded(logPath, Buffer3.byteLength(line, "utf-8"), policy)) {
|
|
15971
|
+
return { ok: false, reason: "application log rotation failed" };
|
|
15972
|
+
}
|
|
15973
|
+
await appendFile(logPath, line, { encoding: "utf-8", mode: PRIVATE_FILE_MODE });
|
|
15974
|
+
if (!securePrivateFileSync(logPath)) {
|
|
15975
|
+
return { ok: false, reason: "application log permissions could not be secured" };
|
|
15976
|
+
}
|
|
15977
|
+
return { ok: true };
|
|
15978
|
+
} catch (error51) {
|
|
15979
|
+
return { ok: false, reason: error51 };
|
|
15980
|
+
}
|
|
15981
|
+
}
|
|
15982
|
+
async function writeAppLog(message) {
|
|
15983
|
+
const logPath = getInspectorLogPath();
|
|
15984
|
+
const line = `[${(/* @__PURE__ */ new Date()).toISOString()}] ${message}
|
|
15985
|
+
`;
|
|
15986
|
+
const initialization = ensureLoggerInitialized();
|
|
15987
|
+
const write = async () => {
|
|
15988
|
+
await initialization;
|
|
15989
|
+
const result = await appendApplicationLogLine(logPath, line, getApplicationLogPolicy());
|
|
15990
|
+
if (!result.ok) writeStderrFallback(`[logger] Failed to write to ${logPath}:`, result.reason);
|
|
15991
|
+
};
|
|
15992
|
+
applicationLogWriteQueue = applicationLogWriteQueue.then(write, write);
|
|
15993
|
+
await applicationLogWriteQueue;
|
|
15994
|
+
}
|
|
15995
|
+
var logger = {
|
|
15996
|
+
debug(message, ...args) {
|
|
15997
|
+
const msg = args.length > 0 ? `${message} ${args.map(String).join(" ")}` : message;
|
|
15998
|
+
void writeAppLog(`[DEBUG] ${msg}`);
|
|
15999
|
+
},
|
|
16000
|
+
info(message, ...args) {
|
|
16001
|
+
const msg = args.length > 0 ? `${message} ${args.map(String).join(" ")}` : message;
|
|
16002
|
+
void writeAppLog(`[INFO] ${msg}`);
|
|
16003
|
+
},
|
|
16004
|
+
warn(message, ...args) {
|
|
16005
|
+
const msg = args.length > 0 ? `${message} ${args.map(String).join(" ")}` : message;
|
|
16006
|
+
void writeAppLog(`[WARN] ${msg}`);
|
|
16007
|
+
},
|
|
16008
|
+
error(message, ...args) {
|
|
16009
|
+
const msg = args.length > 0 ? `${message} ${args.map(String).join(" ")}` : message;
|
|
16010
|
+
void writeAppLog(`[ERROR] ${msg}`);
|
|
16011
|
+
}
|
|
16012
|
+
};
|
|
16013
|
+
var writeBuffer = [];
|
|
16014
|
+
var writeQueue = Promise.resolve();
|
|
16015
|
+
var logWriteLock = Promise.resolve();
|
|
16016
|
+
function drainBuffer() {
|
|
16017
|
+
const toWrite = writeBuffer.join("");
|
|
16018
|
+
writeBuffer = [];
|
|
16019
|
+
return toWrite;
|
|
16020
|
+
}
|
|
16021
|
+
process.on("exit", () => {
|
|
16022
|
+
if (writeBuffer.length > 0) {
|
|
16023
|
+
const toWrite = drainBuffer();
|
|
16024
|
+
try {
|
|
16025
|
+
const filePath = getLogFilePath();
|
|
16026
|
+
if (!ensurePrivateDirectorySync(path.dirname(filePath))) return;
|
|
16027
|
+
if (!canAppendCapturedLogFileOnExit(resolveLogDir(), filePath)) return;
|
|
16028
|
+
const descriptor = openSync2(
|
|
16029
|
+
filePath,
|
|
16030
|
+
constants3.O_WRONLY | constants3.O_APPEND | constants3.O_NOFOLLOW,
|
|
16031
|
+
PRIVATE_FILE_MODE
|
|
16032
|
+
);
|
|
16033
|
+
try {
|
|
16034
|
+
const payload = Buffer3.from(toWrite, "utf-8");
|
|
16035
|
+
let written = 0;
|
|
16036
|
+
while (written < payload.length) {
|
|
16037
|
+
const writeCount = writeSync(descriptor, payload, written, payload.length - written);
|
|
16038
|
+
if (writeCount === 0) return;
|
|
16039
|
+
written += writeCount;
|
|
16040
|
+
}
|
|
16041
|
+
fsyncSync(descriptor);
|
|
16042
|
+
} finally {
|
|
16043
|
+
closeSync2(descriptor);
|
|
16044
|
+
}
|
|
16045
|
+
void securePrivateFileSync(filePath);
|
|
16046
|
+
} catch {
|
|
16047
|
+
}
|
|
16048
|
+
}
|
|
15488
16049
|
});
|
|
15489
16050
|
|
|
15490
16051
|
// src/proxy/chunkStorage.ts
|
|
@@ -15501,15 +16062,15 @@ var StreamingChunksDataSchema = external_exports.object({
|
|
|
15501
16062
|
function getChunksDir() {
|
|
15502
16063
|
const chunksDirEnv = process.env["CHUNKS_DIR"];
|
|
15503
16064
|
if (chunksDirEnv !== void 0 && chunksDirEnv !== "") {
|
|
15504
|
-
return isAbsolute2(chunksDirEnv) ? chunksDirEnv :
|
|
16065
|
+
return isAbsolute2(chunksDirEnv) ? chunksDirEnv : join4(getDataDir(), chunksDirEnv);
|
|
15505
16066
|
}
|
|
15506
|
-
return
|
|
16067
|
+
return join4(getDataDir(), "chunks");
|
|
15507
16068
|
}
|
|
15508
16069
|
function getChunkFilePath(logId) {
|
|
15509
|
-
return
|
|
16070
|
+
return join4(getChunksDir(), `${logId}.json`);
|
|
15510
16071
|
}
|
|
15511
16072
|
function getTempFilePath(logId) {
|
|
15512
|
-
return
|
|
16073
|
+
return join4(getChunksDir(), `.${logId}.tmp`);
|
|
15513
16074
|
}
|
|
15514
16075
|
function writeChunks(logId, chunks, truncated) {
|
|
15515
16076
|
const dir = getChunksDir();
|
|
@@ -15535,7 +16096,7 @@ function writeChunks(logId, chunks, truncated) {
|
|
|
15535
16096
|
return targetPath;
|
|
15536
16097
|
}
|
|
15537
16098
|
try {
|
|
15538
|
-
|
|
16099
|
+
renameSync2(tempPath, targetPath);
|
|
15539
16100
|
} catch (err) {
|
|
15540
16101
|
logger.warn("[chunkStorage] Rename failed, falling back to copy+delete:", String(err));
|
|
15541
16102
|
try {
|
|
@@ -15551,14 +16112,14 @@ function writeChunks(logId, chunks, truncated) {
|
|
|
15551
16112
|
return targetPath;
|
|
15552
16113
|
}
|
|
15553
16114
|
|
|
15554
|
-
// src/
|
|
15555
|
-
var
|
|
15556
|
-
|
|
15557
|
-
|
|
15558
|
-
|
|
15559
|
-
|
|
15560
|
-
|
|
15561
|
-
|
|
16115
|
+
// src/lib/apiFormat.ts
|
|
16116
|
+
var API_FORMAT_PATH_ENTRIES = [
|
|
16117
|
+
["/v1/messages", "anthropic"],
|
|
16118
|
+
["/v1/chat/completions", "openai"],
|
|
16119
|
+
["/chat/completions", "openai"],
|
|
16120
|
+
["/v1/responses", "openai"],
|
|
16121
|
+
["/responses", "openai"]
|
|
16122
|
+
];
|
|
15562
16123
|
|
|
15563
16124
|
// src/proxy/formats/registry.ts
|
|
15564
16125
|
var FormatRegistryImpl = class {
|
|
@@ -15598,11 +16159,9 @@ var formatRegistry = new FormatRegistryImpl();
|
|
|
15598
16159
|
function formatForPath(path2) {
|
|
15599
16160
|
return formatRegistry.getByPath(path2) ?? null;
|
|
15600
16161
|
}
|
|
15601
|
-
|
|
15602
|
-
formatRegistry.registerPath(
|
|
15603
|
-
|
|
15604
|
-
formatRegistry.registerPath(PATH_V1_RESPONSES, "openai");
|
|
15605
|
-
formatRegistry.registerPath(PATH_RESPONSES, "openai");
|
|
16162
|
+
for (const [path2, format] of API_FORMAT_PATH_ENTRIES) {
|
|
16163
|
+
formatRegistry.registerPath(path2, format);
|
|
16164
|
+
}
|
|
15606
16165
|
|
|
15607
16166
|
// src/proxy/formats/anthropic/stream.ts
|
|
15608
16167
|
function parseInputJson(json2) {
|
|
@@ -16558,12 +17117,12 @@ registry2.register(alibabaProvider);
|
|
|
16558
17117
|
// src/proxy/sessionProcess.ts
|
|
16559
17118
|
import { existsSync as existsSync4 } from "node:fs";
|
|
16560
17119
|
import { fileURLToPath } from "node:url";
|
|
16561
|
-
import { join as
|
|
17120
|
+
import { join as join5 } from "node:path";
|
|
16562
17121
|
var IDLE_TIMEOUT_MS = Number(process.env["SESSION_PROCESS_IDLE_MS"]) || 5 * 60 * 1e3;
|
|
16563
17122
|
function resolveSessionWorkerPath() {
|
|
16564
17123
|
const workerDir = process.env["AGENT_INSPECTOR_WORKER_DIR"];
|
|
16565
17124
|
if (workerDir !== void 0 && workerDir.trim().length > 0) {
|
|
16566
|
-
const builtWorkerPath =
|
|
17125
|
+
const builtWorkerPath = join5(workerDir, "sessionWorkerEntry.js");
|
|
16567
17126
|
if (existsSync4(builtWorkerPath)) return builtWorkerPath;
|
|
16568
17127
|
}
|
|
16569
17128
|
return fileURLToPath(new URL("./sessionWorkerEntry.ts", import.meta.url));
|
|
@@ -16573,6 +17132,7 @@ function isSessionProcessAvailable() {
|
|
|
16573
17132
|
}
|
|
16574
17133
|
|
|
16575
17134
|
// src/proxy/logIndex.ts
|
|
17135
|
+
var INDEX_READ_CHUNK_BYTES = 64 * 1024;
|
|
16576
17136
|
var idGenerationChain = Promise.resolve();
|
|
16577
17137
|
|
|
16578
17138
|
// src/lib/publicBasePathContext.ts
|
|
@@ -16693,14 +17253,14 @@ function cleanupPathForRawStream(rawStream) {
|
|
|
16693
17253
|
}
|
|
16694
17254
|
function rawStreamByteLength(rawStream) {
|
|
16695
17255
|
if (typeof rawStream === "string") {
|
|
16696
|
-
return
|
|
17256
|
+
return Buffer4.byteLength(rawStream, "utf8");
|
|
16697
17257
|
}
|
|
16698
17258
|
switch (rawStream.type) {
|
|
16699
17259
|
case "memory":
|
|
16700
|
-
return
|
|
17260
|
+
return Buffer4.byteLength(rawStream.rawStream, "utf8");
|
|
16701
17261
|
case "file":
|
|
16702
17262
|
try {
|
|
16703
|
-
return
|
|
17263
|
+
return statSync(rawStream.path).size;
|
|
16704
17264
|
} catch {
|
|
16705
17265
|
return null;
|
|
16706
17266
|
}
|
|
@@ -16859,8 +17419,13 @@ function buildFinalizeLogResult(job) {
|
|
|
16859
17419
|
switch (job.type) {
|
|
16860
17420
|
case "non-streaming":
|
|
16861
17421
|
return finalizeNonStreaming(job, log);
|
|
16862
|
-
case "streaming":
|
|
16863
|
-
|
|
17422
|
+
case "streaming": {
|
|
17423
|
+
const result = finalizeStreaming(job, log);
|
|
17424
|
+
if (job.terminalError !== void 0 && job.terminalError !== null) {
|
|
17425
|
+
result.log.error = job.terminalError;
|
|
17426
|
+
}
|
|
17427
|
+
return result;
|
|
17428
|
+
}
|
|
16864
17429
|
case "stream-abort":
|
|
16865
17430
|
return finalizeStreamAbort(job, log);
|
|
16866
17431
|
default: {
|
|
@@ -16888,7 +17453,7 @@ var WORKER_COUNT = Math.max(1, Number(process.env["FINALIZER_WORKER_COUNT"]) ||
|
|
|
16888
17453
|
function resolveLogFinalizerWorkerUrl() {
|
|
16889
17454
|
const workerDir = process.env["AGENT_INSPECTOR_WORKER_DIR"];
|
|
16890
17455
|
if (workerDir !== void 0 && workerDir.trim().length > 0) {
|
|
16891
|
-
const builtWorkerPath =
|
|
17456
|
+
const builtWorkerPath = join6(workerDir, "logFinalizer.worker.js");
|
|
16892
17457
|
if (existsSync5(builtWorkerPath)) return pathToFileURL(builtWorkerPath);
|
|
16893
17458
|
}
|
|
16894
17459
|
return new URL("./logFinalizer.worker.ts", import.meta.url);
|