@tonyclaw/agent-inspector 3.0.45 → 3.0.47
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 +8018 -5451
- 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-BwZEsYfS.mjs} +19794 -19444
- 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-V-8lPASC.js} +1 -1
- package/.output/{public/assets/InspectorPet-Cpn6hv4P.js → ui/assets/InspectorPet-D4CVnfdf.js} +1 -1
- package/.output/ui/assets/ProxyViewerContainer-CO3ZVHLX.js +59 -0
- package/.output/{public/assets/ReplayDialog-B3EKVdJk.js → ui/assets/ReplayDialog-CpGyTLtt.js} +1 -1
- package/.output/{public/assets/RequestAnatomy-COOQjyUC.js → ui/assets/RequestAnatomy-BLuJL9dZ.js} +1 -1
- package/.output/ui/assets/ResponseView-BuSC-CH7.js +2 -0
- package/.output/ui/assets/StreamingChunkSequence-DeA-JJKa.js +1 -0
- package/.output/{public/assets/_sessionId-zbgYl7ZJ.js → ui/assets/_sessionId-8HuHFhjo.js} +1 -1
- package/.output/{public/assets/_sessionId-BJlM3nmt.js → ui/assets/_sessionId-Chp67th6.js} +1 -1
- package/.output/ui/assets/favicon-DYEkHSNl.svg +21 -0
- package/.output/ui/assets/index-BvXp42al.css +1 -0
- package/.output/{public/assets/index-xF_NY8Yb.js → ui/assets/index-DPmKK_5d.js} +5 -5
- package/.output/{public/assets/index-BIK4bPTv.js → ui/assets/index-atoQrlb8.js} +1 -1
- package/.output/ui/assets/index-nY3E1vxV.js +73 -0
- package/.output/{public/assets/index-D2Qw6Ri2.js → ui/assets/index-nl9-dpZn.js} +1 -1
- package/.output/ui/assets/json-viewer-B9kIzqeX.js +1 -0
- package/.output/{public/assets/jszip.min-B_rfAUCe.js → ui/assets/jszip.min-B7tfyE-I.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 +182 -43
- package/docs/instance-control.openapi.yaml +59 -4
- package/package.json +40 -6
- 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/backend/routes/api/-instances.ts +7 -0
- 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 +36 -13
- package/src/cli/instanceApi.ts +213 -0
- package/src/cli/instanceArgs.ts +46 -11
- package/src/cli/instanceControl.ts +10 -2
- package/src/cli/instanceModel.ts +18 -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/rustBackendPackage.ts +450 -0
- package/src/cli/templates/codex-skill-onboard.ts +44 -14
- package/src/cli/templates/skill-onboard.ts +64 -28
- package/src/cli.ts +341 -75
- 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/backendImplementation.ts +16 -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 +30 -11
- package/src/lib/managedInstance.ts +9 -1
- 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 +2 -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 +567 -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 +70 -14
- package/src/proxy/sqliteLogIndex.ts +65 -42
- 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/src/routes/api/-instances.ts +0 -109
- /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
|
@@ -5,9 +5,9 @@ var __export = (target, all) => {
|
|
|
5
5
|
};
|
|
6
6
|
|
|
7
7
|
// src/proxy/logFinalizer.ts
|
|
8
|
-
import { Buffer as
|
|
9
|
-
import { existsSync as existsSync5, readFileSync as readFileSync2, rmSync as rmSync2, statSync
|
|
10
|
-
import { join as
|
|
8
|
+
import { Buffer as Buffer4 } from "node:buffer";
|
|
9
|
+
import { existsSync as existsSync5, readFileSync as readFileSync2, rmSync as rmSync2, statSync } from "node:fs";
|
|
10
|
+
import { join as join6 } from "node:path";
|
|
11
11
|
import { fileURLToPath as fileURLToPath2, pathToFileURL } from "node:url";
|
|
12
12
|
|
|
13
13
|
// src/proxy/chunkStorage.ts
|
|
@@ -16,29 +16,38 @@ import {
|
|
|
16
16
|
readFileSync,
|
|
17
17
|
unlinkSync,
|
|
18
18
|
existsSync as existsSync3,
|
|
19
|
-
renameSync,
|
|
19
|
+
renameSync as renameSync2,
|
|
20
20
|
copyFileSync
|
|
21
21
|
} from "node:fs";
|
|
22
|
-
import { join as
|
|
22
|
+
import { join as join4, isAbsolute as isAbsolute2 } from "node:path";
|
|
23
23
|
|
|
24
24
|
// src/proxy/logger.ts
|
|
25
|
-
import { Buffer as
|
|
26
|
-
import {
|
|
27
|
-
import { appendFile, readdir, rename, stat, unlink } from "node:fs/promises";
|
|
25
|
+
import { Buffer as Buffer3 } from "node:buffer";
|
|
26
|
+
import { closeSync as closeSync2, constants as constants3, fsyncSync, openSync as openSync2, writeSync } from "node:fs";
|
|
27
|
+
import { appendFile, readdir as readdir2, rename, stat as stat2, unlink as unlink2 } from "node:fs/promises";
|
|
28
28
|
import path from "node:path";
|
|
29
29
|
|
|
30
30
|
// src/proxy/dataDir.ts
|
|
31
|
-
import { cpSync, existsSync as
|
|
31
|
+
import { cpSync, existsSync, readdirSync as readdirSync2, renameSync, rmSync } from "node:fs";
|
|
32
32
|
import { isAbsolute, join as join2 } from "node:path";
|
|
33
33
|
|
|
34
34
|
// src/proxy/privateDataPath.ts
|
|
35
35
|
import { spawnSync } from "node:child_process";
|
|
36
|
-
import {
|
|
37
|
-
|
|
36
|
+
import {
|
|
37
|
+
closeSync,
|
|
38
|
+
constants,
|
|
39
|
+
fchmodSync,
|
|
40
|
+
fstatSync,
|
|
41
|
+
lstatSync,
|
|
42
|
+
mkdirSync,
|
|
43
|
+
openSync,
|
|
44
|
+
readdirSync,
|
|
45
|
+
realpathSync
|
|
46
|
+
} from "node:fs";
|
|
47
|
+
import { join, parse, resolve, sep } from "node:path";
|
|
38
48
|
var PRIVATE_DIRECTORY_MODE = 448;
|
|
39
49
|
var PRIVATE_FILE_MODE = 384;
|
|
40
|
-
var
|
|
41
|
-
var securedFileIdentities = /* @__PURE__ */ new Map();
|
|
50
|
+
var securedPathFingerprints = /* @__PURE__ */ new Map();
|
|
42
51
|
var cachedWindowsSid = null;
|
|
43
52
|
function windowsSystemPath(executable) {
|
|
44
53
|
const systemRoot = process.env["SystemRoot"] ?? "C:\\Windows";
|
|
@@ -68,9 +77,7 @@ function resolveWindowsUserSid(run) {
|
|
|
68
77
|
function windowsBroadGroupRemovalArgs() {
|
|
69
78
|
return ["/remove:g", "*S-1-1-0", "*S-1-5-11", "*S-1-5-32-545"];
|
|
70
79
|
}
|
|
71
|
-
function
|
|
72
|
-
const sid = resolveWindowsUserSid(run);
|
|
73
|
-
if (sid === null) return false;
|
|
80
|
+
function applyWindowsAclWithSid(path2, kind, sid, run) {
|
|
74
81
|
const access = kind === "directory" ? `(OI)(CI)F` : "F";
|
|
75
82
|
const result = run("icacls.exe", [
|
|
76
83
|
path2,
|
|
@@ -82,93 +89,226 @@ function applyWindowsUserOnlyAcl(path2, kind, run = runWindowsCommand) {
|
|
|
82
89
|
]);
|
|
83
90
|
return result.status === 0;
|
|
84
91
|
}
|
|
85
|
-
function
|
|
92
|
+
function applyWindowsUserOnlyAcl(path2, kind, run = runWindowsCommand) {
|
|
86
93
|
const sid = resolveWindowsUserSid(run);
|
|
87
|
-
|
|
88
|
-
const result = run("icacls.exe", [
|
|
89
|
-
root,
|
|
90
|
-
"/inheritance:r",
|
|
91
|
-
"/grant:r",
|
|
92
|
-
`*${sid}:(OI)(CI)F`,
|
|
93
|
-
`*${sid}:F`,
|
|
94
|
-
...windowsBroadGroupRemovalArgs(),
|
|
95
|
-
"/T",
|
|
96
|
-
"/C",
|
|
97
|
-
"/Q"
|
|
98
|
-
]);
|
|
99
|
-
return result.status === 0;
|
|
94
|
+
return sid !== null && applyWindowsAclWithSid(path2, kind, sid, run);
|
|
100
95
|
}
|
|
101
|
-
function
|
|
96
|
+
function comparablePath(path2) {
|
|
97
|
+
let normalized = path2;
|
|
102
98
|
if (process.platform === "win32") {
|
|
103
|
-
|
|
99
|
+
if (normalized.startsWith("\\\\?\\UNC\\")) {
|
|
100
|
+
normalized = `\\\\${normalized.slice(8)}`;
|
|
101
|
+
} else if (normalized.startsWith("\\\\?\\")) {
|
|
102
|
+
normalized = normalized.slice(4);
|
|
103
|
+
}
|
|
104
104
|
}
|
|
105
|
+
const absolute = resolve(normalized);
|
|
106
|
+
return process.platform === "win32" ? absolute.toLowerCase() : absolute;
|
|
107
|
+
}
|
|
108
|
+
function pathIdentity(stats) {
|
|
109
|
+
return `${String(stats.dev)}:${String(stats.ino)}:${String(stats.birthtimeMs)}`;
|
|
110
|
+
}
|
|
111
|
+
function readPathEntry(path2) {
|
|
112
|
+
let stats;
|
|
105
113
|
try {
|
|
106
|
-
|
|
107
|
-
return
|
|
114
|
+
const observed = lstatSync(path2);
|
|
115
|
+
if (observed === void 0) return { status: "missing" };
|
|
116
|
+
stats = observed;
|
|
108
117
|
} catch {
|
|
109
|
-
return
|
|
118
|
+
return { status: "missing" };
|
|
110
119
|
}
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
if (!applyPrivatePermissionsSync(path2, kind)) return false;
|
|
116
|
-
securedPaths.add(cacheKey);
|
|
117
|
-
return true;
|
|
118
|
-
}
|
|
119
|
-
function ensurePrivateDirectorySync(path2) {
|
|
120
|
+
if (stats.isSymbolicLink()) return { status: "unsafe" };
|
|
121
|
+
const kind = stats.isDirectory() ? "directory" : stats.isFile() ? "file" : null;
|
|
122
|
+
if (kind === null) return { status: "unsafe" };
|
|
123
|
+
let canonical;
|
|
120
124
|
try {
|
|
121
|
-
|
|
125
|
+
canonical = realpathSync.native(path2);
|
|
122
126
|
} catch {
|
|
123
|
-
return
|
|
127
|
+
return { status: "unsafe" };
|
|
124
128
|
}
|
|
125
|
-
|
|
129
|
+
if (comparablePath(canonical) !== comparablePath(path2)) return { status: "unsafe" };
|
|
130
|
+
return {
|
|
131
|
+
status: "ok",
|
|
132
|
+
entry: {
|
|
133
|
+
path: path2,
|
|
134
|
+
kind,
|
|
135
|
+
identity: pathIdentity(stats),
|
|
136
|
+
mode: stats.mode & 511
|
|
137
|
+
}
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
function snapshotPathChain(path2) {
|
|
141
|
+
const absolutePath = resolve(path2);
|
|
142
|
+
const root = parse(absolutePath).root;
|
|
143
|
+
const suffix = absolutePath.slice(root.length);
|
|
144
|
+
const parts = suffix === "" ? [] : suffix.split(sep).filter((part) => part !== "");
|
|
145
|
+
const entries = [];
|
|
146
|
+
let current = root;
|
|
147
|
+
const rootRead = readPathEntry(root);
|
|
148
|
+
if (rootRead.status !== "ok" || rootRead.entry.kind !== "directory") return null;
|
|
149
|
+
entries.push(rootRead.entry);
|
|
150
|
+
for (let index = 0; index < parts.length; index += 1) {
|
|
151
|
+
const part = parts[index];
|
|
152
|
+
if (part === void 0) return null;
|
|
153
|
+
current = join(current, part);
|
|
154
|
+
const read = readPathEntry(current);
|
|
155
|
+
if (read.status === "unsafe") return null;
|
|
156
|
+
if (read.status === "missing") {
|
|
157
|
+
return {
|
|
158
|
+
absolutePath,
|
|
159
|
+
complete: false,
|
|
160
|
+
entries,
|
|
161
|
+
missingParts: parts.slice(index)
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
if (index < parts.length - 1 && read.entry.kind !== "directory") return null;
|
|
165
|
+
entries.push(read.entry);
|
|
166
|
+
}
|
|
167
|
+
return { absolutePath, complete: true, entries, missingParts: [] };
|
|
126
168
|
}
|
|
127
|
-
function
|
|
128
|
-
|
|
169
|
+
function chainFingerprint(snapshot) {
|
|
170
|
+
return snapshot.entries.map((entry) => `${entry.path}:${entry.identity}`).join("|");
|
|
171
|
+
}
|
|
172
|
+
function snapshotsRetainPrefix(before, after) {
|
|
173
|
+
if (after.entries.length < before.entries.length) return false;
|
|
174
|
+
return before.entries.every((entry, index) => {
|
|
175
|
+
const next = after.entries[index];
|
|
176
|
+
return next !== void 0 && next.path === entry.path && next.identity === entry.identity;
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
function completeSnapshotForKind(path2, kind) {
|
|
180
|
+
const snapshot = snapshotPathChain(path2);
|
|
181
|
+
if (snapshot === null || !snapshot.complete) return null;
|
|
182
|
+
const leaf = snapshot.entries.at(-1);
|
|
183
|
+
return leaf !== void 0 && leaf.kind === kind ? snapshot : null;
|
|
184
|
+
}
|
|
185
|
+
function applyPosixPermissions(path2, kind, expectedIdentity) {
|
|
186
|
+
let descriptor = null;
|
|
129
187
|
try {
|
|
130
|
-
const
|
|
131
|
-
|
|
188
|
+
const directoryFlag = kind === "directory" ? constants.O_DIRECTORY : 0;
|
|
189
|
+
descriptor = openSync(path2, constants.O_RDONLY | constants.O_NOFOLLOW | directoryFlag);
|
|
190
|
+
const before = fstatSync(descriptor);
|
|
191
|
+
if (pathIdentity(before) !== expectedIdentity) return false;
|
|
192
|
+
fchmodSync(descriptor, kind === "directory" ? PRIVATE_DIRECTORY_MODE : PRIVATE_FILE_MODE);
|
|
193
|
+
const after = fstatSync(descriptor);
|
|
194
|
+
return pathIdentity(after) === expectedIdentity && (after.mode & 511) === (kind === "directory" ? PRIVATE_DIRECTORY_MODE : PRIVATE_FILE_MODE);
|
|
132
195
|
} catch {
|
|
133
196
|
return false;
|
|
197
|
+
} finally {
|
|
198
|
+
if (descriptor !== null) {
|
|
199
|
+
try {
|
|
200
|
+
closeSync(descriptor);
|
|
201
|
+
} catch {
|
|
202
|
+
}
|
|
203
|
+
}
|
|
134
204
|
}
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
205
|
+
}
|
|
206
|
+
function permissionsArePrivate(entry) {
|
|
207
|
+
if (process.platform === "win32") return true;
|
|
208
|
+
return entry.mode === (entry.kind === "directory" ? PRIVATE_DIRECTORY_MODE : PRIVATE_FILE_MODE);
|
|
209
|
+
}
|
|
210
|
+
function secureExistingPath(path2, kind, forcePermissions = false) {
|
|
211
|
+
const before = completeSnapshotForKind(path2, kind);
|
|
212
|
+
if (before === null) return false;
|
|
213
|
+
const leaf = before.entries.at(-1);
|
|
214
|
+
if (leaf === void 0) return false;
|
|
215
|
+
const cacheKey = `${kind}:${before.absolutePath}`;
|
|
216
|
+
const beforeFingerprint = chainFingerprint(before);
|
|
217
|
+
if (!forcePermissions && securedPathFingerprints.get(cacheKey) === beforeFingerprint && permissionsArePrivate(leaf)) {
|
|
218
|
+
const cachedCheck = completeSnapshotForKind(path2, kind);
|
|
219
|
+
return cachedCheck !== null && chainFingerprint(cachedCheck) === beforeFingerprint;
|
|
139
220
|
}
|
|
140
|
-
|
|
141
|
-
|
|
221
|
+
const applied = process.platform === "win32" ? applyWindowsUserOnlyAcl(path2, kind) : applyPosixPermissions(path2, kind, leaf.identity);
|
|
222
|
+
if (!applied) return false;
|
|
223
|
+
const after = completeSnapshotForKind(path2, kind);
|
|
224
|
+
if (after === null || !snapshotsRetainPrefix(before, after)) return false;
|
|
225
|
+
const afterLeaf = after.entries.at(-1);
|
|
226
|
+
if (afterLeaf === void 0 || afterLeaf.identity !== leaf.identity) return false;
|
|
227
|
+
if (!permissionsArePrivate(afterLeaf)) return false;
|
|
228
|
+
securedPathFingerprints.set(cacheKey, chainFingerprint(after));
|
|
142
229
|
return true;
|
|
143
230
|
}
|
|
144
|
-
function
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
231
|
+
function ensurePrivateDirectorySync(path2) {
|
|
232
|
+
const before = snapshotPathChain(path2);
|
|
233
|
+
if (before === null) return false;
|
|
234
|
+
let current = before.entries.at(-1)?.path;
|
|
235
|
+
if (current === void 0) return false;
|
|
236
|
+
for (const part of before.missingParts) {
|
|
237
|
+
const next = join(current, part);
|
|
238
|
+
try {
|
|
239
|
+
mkdirSync(next, { mode: PRIVATE_DIRECTORY_MODE });
|
|
240
|
+
} catch {
|
|
241
|
+
const raced = readPathEntry(next);
|
|
242
|
+
if (raced.status !== "ok" || raced.entry.kind !== "directory") return false;
|
|
243
|
+
}
|
|
244
|
+
if (!secureExistingPath(next, "directory", true)) return false;
|
|
245
|
+
current = next;
|
|
151
246
|
}
|
|
152
|
-
|
|
153
|
-
if (!
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
247
|
+
const complete = completeSnapshotForKind(path2, "directory");
|
|
248
|
+
if (complete === null || !snapshotsRetainPrefix(before, complete)) return false;
|
|
249
|
+
return secureExistingPath(path2, "directory");
|
|
250
|
+
}
|
|
251
|
+
function securePrivateFileSync(path2, forceAcl = false) {
|
|
252
|
+
return secureExistingPath(path2, "file", forceAcl);
|
|
253
|
+
}
|
|
254
|
+
function collectSafeTree(root) {
|
|
255
|
+
const collected = [];
|
|
256
|
+
const visit = (path2) => {
|
|
257
|
+
const snapshot = snapshotPathChain(path2);
|
|
258
|
+
if (snapshot === null || !snapshot.complete) return false;
|
|
259
|
+
const leaf = snapshot.entries.at(-1);
|
|
260
|
+
if (leaf === void 0) return false;
|
|
261
|
+
const fingerprint = chainFingerprint(snapshot);
|
|
262
|
+
collected.push({ path: snapshot.absolutePath, kind: leaf.kind, fingerprint });
|
|
263
|
+
if (leaf.kind === "file") return true;
|
|
264
|
+
let entries;
|
|
265
|
+
try {
|
|
266
|
+
entries = readdirSync(path2);
|
|
267
|
+
} catch {
|
|
268
|
+
return false;
|
|
269
|
+
}
|
|
270
|
+
const afterRead = completeSnapshotForKind(path2, "directory");
|
|
271
|
+
if (afterRead === null || chainFingerprint(afterRead) !== fingerprint) return false;
|
|
272
|
+
for (const entry of entries) {
|
|
273
|
+
if (!visit(join(path2, entry))) return false;
|
|
274
|
+
}
|
|
157
275
|
return true;
|
|
276
|
+
};
|
|
277
|
+
return visit(root) ? collected : null;
|
|
278
|
+
}
|
|
279
|
+
function treeFingerprintsMatch(expected, observed) {
|
|
280
|
+
if (observed === null || observed.length !== expected.length) return false;
|
|
281
|
+
return expected.every((entry, index) => {
|
|
282
|
+
const next = observed[index];
|
|
283
|
+
return next !== void 0 && next.path === entry.path && next.kind === entry.kind && next.fingerprint === entry.fingerprint;
|
|
284
|
+
});
|
|
285
|
+
}
|
|
286
|
+
function isPathTreeFreeOfIndirectionSync(root) {
|
|
287
|
+
return collectSafeTree(root) !== null;
|
|
288
|
+
}
|
|
289
|
+
function applyWindowsUserOnlyTreeAcl(root, run = runWindowsCommand) {
|
|
290
|
+
const entries = collectSafeTree(root);
|
|
291
|
+
if (entries === null) return false;
|
|
292
|
+
const sid = resolveWindowsUserSid(run);
|
|
293
|
+
if (sid === null) return false;
|
|
294
|
+
for (const entry of entries) {
|
|
295
|
+
const before = completeSnapshotForKind(entry.path, entry.kind);
|
|
296
|
+
if (before === null || chainFingerprint(before) !== entry.fingerprint) return false;
|
|
297
|
+
if (!applyWindowsAclWithSid(entry.path, entry.kind, sid, run)) return false;
|
|
298
|
+
const after = completeSnapshotForKind(entry.path, entry.kind);
|
|
299
|
+
if (after === null || chainFingerprint(after) !== entry.fingerprint) return false;
|
|
300
|
+
securedPathFingerprints.set(`${entry.kind}:${entry.path}`, entry.fingerprint);
|
|
158
301
|
}
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
}
|
|
166
|
-
let secured = true;
|
|
302
|
+
return treeFingerprintsMatch(entries, collectSafeTree(root));
|
|
303
|
+
}
|
|
304
|
+
function securePrivateTreeSync(root) {
|
|
305
|
+
const entries = collectSafeTree(root);
|
|
306
|
+
if (entries === null) return false;
|
|
307
|
+
if (process.platform === "win32") return applyWindowsUserOnlyTreeAcl(root);
|
|
167
308
|
for (const entry of entries) {
|
|
168
|
-
|
|
169
|
-
if (!securePrivateTreeSync(childPath)) secured = false;
|
|
309
|
+
if (!secureExistingPath(entry.path, entry.kind, true)) return false;
|
|
170
310
|
}
|
|
171
|
-
return
|
|
311
|
+
return treeFingerprintsMatch(entries, collectSafeTree(root));
|
|
172
312
|
}
|
|
173
313
|
|
|
174
314
|
// src/proxy/dataDir.ts
|
|
@@ -176,7 +316,7 @@ var CURRENT_DATA_DIR_NAME = ".agent-inspector";
|
|
|
176
316
|
var LEGACY_DATA_DIR_NAMES = [".llm-inspector", ".llm-agent"];
|
|
177
317
|
function getDataDir() {
|
|
178
318
|
migrateLegacyDataDirs();
|
|
179
|
-
return resolveDataDir(
|
|
319
|
+
return resolveDataDir(existsSync);
|
|
180
320
|
}
|
|
181
321
|
function hasDataDirState(pathExists, dir) {
|
|
182
322
|
return pathExists(join2(dir, "providers.json")) || pathExists(join2(dir, "config.json")) || pathExists(join2(dir, "logs")) || pathExists(join2(dir, "chunks"));
|
|
@@ -203,293 +343,52 @@ function migrateLegacyDataDirs() {
|
|
|
203
343
|
if (hasExplicitDataDir()) return;
|
|
204
344
|
const base = defaultBaseDir();
|
|
205
345
|
const currentDir = join2(base, CURRENT_DATA_DIR_NAME);
|
|
206
|
-
if (hasDataDirState(
|
|
346
|
+
if (hasDataDirState(existsSync, currentDir)) return;
|
|
207
347
|
for (const legacyName of LEGACY_DATA_DIR_NAMES) {
|
|
208
348
|
const legacyDir = join2(base, legacyName);
|
|
209
|
-
if (!
|
|
349
|
+
if (!existsSync(legacyDir)) continue;
|
|
350
|
+
const stagingDir = join2(
|
|
351
|
+
base,
|
|
352
|
+
`${CURRENT_DATA_DIR_NAME}.migration-${String(process.pid)}-${String(Date.now())}`
|
|
353
|
+
);
|
|
210
354
|
try {
|
|
211
|
-
if (!
|
|
212
|
-
|
|
213
|
-
|
|
355
|
+
if (!isPathTreeFreeOfIndirectionSync(legacyDir)) return;
|
|
356
|
+
if (existsSync(currentDir)) {
|
|
357
|
+
if (readdirSync2(currentDir).length > 0) return;
|
|
358
|
+
rmSync(currentDir, { recursive: true, force: false });
|
|
359
|
+
}
|
|
360
|
+
if (!ensurePrivateDirectorySync(stagingDir)) return;
|
|
361
|
+
for (const entry of readdirSync2(legacyDir)) {
|
|
362
|
+
cpSync(join2(legacyDir, entry), join2(stagingDir, entry), {
|
|
363
|
+
recursive: true,
|
|
364
|
+
force: false,
|
|
365
|
+
errorOnExist: true
|
|
366
|
+
});
|
|
367
|
+
}
|
|
368
|
+
if (!isPathTreeFreeOfIndirectionSync(legacyDir)) {
|
|
369
|
+
rmSync(stagingDir, { recursive: true, force: true });
|
|
370
|
+
return;
|
|
371
|
+
}
|
|
372
|
+
if (!securePrivateTreeSync(stagingDir)) {
|
|
373
|
+
rmSync(stagingDir, { recursive: true, force: true });
|
|
374
|
+
return;
|
|
375
|
+
}
|
|
376
|
+
renameSync(stagingDir, currentDir);
|
|
214
377
|
rmSync(legacyDir, { recursive: true, force: true });
|
|
378
|
+
return;
|
|
215
379
|
} catch {
|
|
380
|
+
if (existsSync(stagingDir)) rmSync(stagingDir, { recursive: true, force: true });
|
|
381
|
+
return;
|
|
216
382
|
}
|
|
217
383
|
}
|
|
218
384
|
}
|
|
219
385
|
|
|
220
|
-
// src/proxy/
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
process.stderr.write(`${message} ${String(error51)}
|
|
227
|
-
`);
|
|
228
|
-
}
|
|
229
|
-
function resolveLogDir() {
|
|
230
|
-
const logDirEnv = process.env["LOG_DIR"];
|
|
231
|
-
if (logDirEnv !== void 0 && logDirEnv !== "") {
|
|
232
|
-
return path.isAbsolute(logDirEnv) ? logDirEnv : path.join(getDataDir(), logDirEnv);
|
|
233
|
-
}
|
|
234
|
-
return path.join(getDataDir(), "logs");
|
|
235
|
-
}
|
|
236
|
-
function getLogFilePath() {
|
|
237
|
-
const date5 = /* @__PURE__ */ new Date();
|
|
238
|
-
const yyyy = date5.getUTCFullYear();
|
|
239
|
-
const mm = String(date5.getUTCMonth() + 1).padStart(2, "0");
|
|
240
|
-
const dd = String(date5.getUTCDate()).padStart(2, "0");
|
|
241
|
-
return path.join(resolveLogDir(), `${yyyy}-${mm}-${dd}.jsonl`);
|
|
242
|
-
}
|
|
243
|
-
function getInspectorLogPath() {
|
|
244
|
-
const logFileEnv = process.env["AGENT_INSPECTOR_LOG_FILE"];
|
|
245
|
-
if (logFileEnv !== void 0 && logFileEnv !== "") {
|
|
246
|
-
return logFileEnv;
|
|
247
|
-
}
|
|
248
|
-
return path.join(getDataDir(), "logs", "inspector.log");
|
|
249
|
-
}
|
|
250
|
-
function readBoundedInteger(name, fallback, minimum, maximum) {
|
|
251
|
-
const raw = process.env[name];
|
|
252
|
-
if (raw === void 0 || raw === "") return fallback;
|
|
253
|
-
const parsed = Number(raw);
|
|
254
|
-
if (!Number.isInteger(parsed) || parsed < minimum || parsed > maximum) return fallback;
|
|
255
|
-
return parsed;
|
|
256
|
-
}
|
|
257
|
-
function getApplicationLogPolicy() {
|
|
258
|
-
const retentionDays = readBoundedInteger("LOG_RETENTION_DAYS", DEFAULT_RETENTION_DAYS, 1, 3650);
|
|
259
|
-
return {
|
|
260
|
-
maxBytes: readBoundedInteger(
|
|
261
|
-
"AGENT_INSPECTOR_APP_LOG_MAX_BYTES",
|
|
262
|
-
DEFAULT_APP_LOG_MAX_BYTES,
|
|
263
|
-
1,
|
|
264
|
-
1024 * 1024 * 1024
|
|
265
|
-
),
|
|
266
|
-
maxFiles: readBoundedInteger(
|
|
267
|
-
"AGENT_INSPECTOR_APP_LOG_MAX_FILES",
|
|
268
|
-
DEFAULT_APP_LOG_MAX_FILES,
|
|
269
|
-
1,
|
|
270
|
-
100
|
|
271
|
-
),
|
|
272
|
-
retentionMs: retentionDays * DAY_MS
|
|
273
|
-
};
|
|
274
|
-
}
|
|
275
|
-
function getRotatedGeneration(entry, baseName) {
|
|
276
|
-
const prefix = `${baseName}.`;
|
|
277
|
-
if (!entry.startsWith(prefix)) return null;
|
|
278
|
-
const suffix = entry.slice(prefix.length);
|
|
279
|
-
if (!/^\d+$/.test(suffix)) return null;
|
|
280
|
-
const generation = Number(suffix);
|
|
281
|
-
if (!Number.isSafeInteger(generation) || generation < 1) return null;
|
|
282
|
-
return generation;
|
|
283
|
-
}
|
|
284
|
-
async function listApplicationLogFiles(logPath) {
|
|
285
|
-
const directory = path.dirname(logPath);
|
|
286
|
-
const baseName = path.basename(logPath);
|
|
287
|
-
const entries = await readdir(directory);
|
|
288
|
-
const files = [];
|
|
289
|
-
for (const entry of entries) {
|
|
290
|
-
const generation = entry === baseName ? 0 : getRotatedGeneration(entry, baseName);
|
|
291
|
-
if (generation === null) continue;
|
|
292
|
-
const filePath = path.join(directory, entry);
|
|
293
|
-
try {
|
|
294
|
-
const fileStat = await stat(filePath);
|
|
295
|
-
if (!fileStat.isFile()) continue;
|
|
296
|
-
files.push({ generation, modifiedAt: fileStat.mtimeMs, path: filePath });
|
|
297
|
-
} catch {
|
|
298
|
-
}
|
|
299
|
-
}
|
|
300
|
-
return files;
|
|
301
|
-
}
|
|
302
|
-
async function removeApplicationLog(filePath) {
|
|
303
|
-
try {
|
|
304
|
-
await stat(filePath);
|
|
305
|
-
} catch {
|
|
306
|
-
return true;
|
|
307
|
-
}
|
|
308
|
-
try {
|
|
309
|
-
await unlink(filePath);
|
|
310
|
-
return true;
|
|
311
|
-
} catch {
|
|
312
|
-
return false;
|
|
313
|
-
}
|
|
314
|
-
}
|
|
315
|
-
async function maintainApplicationLogs(logPath, policy) {
|
|
316
|
-
const directory = path.dirname(logPath);
|
|
317
|
-
if (!ensurePrivateDirectorySync(directory)) return false;
|
|
318
|
-
let files;
|
|
319
|
-
try {
|
|
320
|
-
files = await listApplicationLogFiles(logPath);
|
|
321
|
-
} catch {
|
|
322
|
-
return false;
|
|
323
|
-
}
|
|
324
|
-
for (const file2 of files) {
|
|
325
|
-
if (!securePrivateFileSync(file2.path)) return false;
|
|
326
|
-
}
|
|
327
|
-
const cutoff = Date.now() - policy.retentionMs;
|
|
328
|
-
const retained = files.filter((file2) => file2.modifiedAt >= cutoff);
|
|
329
|
-
let maintained = true;
|
|
330
|
-
for (const file2 of files) {
|
|
331
|
-
if (file2.modifiedAt < cutoff && !await removeApplicationLog(file2.path)) maintained = false;
|
|
332
|
-
}
|
|
333
|
-
const rotated = retained.filter((file2) => file2.generation > 0).sort((left, right) => right.modifiedAt - left.modifiedAt);
|
|
334
|
-
const retainedRotatedCount = Math.max(0, policy.maxFiles - 1);
|
|
335
|
-
for (const file2 of rotated.slice(retainedRotatedCount)) {
|
|
336
|
-
if (!await removeApplicationLog(file2.path)) maintained = false;
|
|
337
|
-
}
|
|
338
|
-
return maintained;
|
|
339
|
-
}
|
|
340
|
-
async function moveApplicationLog(source, destination) {
|
|
341
|
-
try {
|
|
342
|
-
await stat(source);
|
|
343
|
-
} catch {
|
|
344
|
-
return true;
|
|
345
|
-
}
|
|
346
|
-
try {
|
|
347
|
-
await rename(source, destination);
|
|
348
|
-
if (!securePrivateFileSync(destination)) {
|
|
349
|
-
writeStderrFallback("[logger] Failed to secure rotated application log:", destination);
|
|
350
|
-
return false;
|
|
351
|
-
}
|
|
352
|
-
return true;
|
|
353
|
-
} catch (error51) {
|
|
354
|
-
writeStderrFallback("[logger] Failed to rotate application log:", error51);
|
|
355
|
-
return false;
|
|
356
|
-
}
|
|
357
|
-
}
|
|
358
|
-
async function rotateApplicationLog(logPath, maxFiles) {
|
|
359
|
-
if (maxFiles === 1) {
|
|
360
|
-
return await removeApplicationLog(logPath);
|
|
361
|
-
}
|
|
362
|
-
if (!await removeApplicationLog(`${logPath}.${String(maxFiles - 1)}`)) return false;
|
|
363
|
-
for (let generation = maxFiles - 2; generation >= 1; generation -= 1) {
|
|
364
|
-
if (!await moveApplicationLog(
|
|
365
|
-
`${logPath}.${String(generation)}`,
|
|
366
|
-
`${logPath}.${String(generation + 1)}`
|
|
367
|
-
)) {
|
|
368
|
-
return false;
|
|
369
|
-
}
|
|
370
|
-
}
|
|
371
|
-
return await moveApplicationLog(logPath, `${logPath}.1`);
|
|
372
|
-
}
|
|
373
|
-
async function rotateApplicationLogIfNeeded(logPath, incomingBytes, policy) {
|
|
374
|
-
try {
|
|
375
|
-
const fileStat = await stat(logPath);
|
|
376
|
-
if (fileStat.size > 0 && fileStat.size + incomingBytes > policy.maxBytes) {
|
|
377
|
-
return await rotateApplicationLog(logPath, policy.maxFiles);
|
|
378
|
-
}
|
|
379
|
-
return true;
|
|
380
|
-
} catch {
|
|
381
|
-
return true;
|
|
382
|
-
}
|
|
383
|
-
}
|
|
384
|
-
async function initLogger() {
|
|
385
|
-
const dir = resolveLogDir();
|
|
386
|
-
const policy = getApplicationLogPolicy();
|
|
387
|
-
const cutoff = Date.now() - policy.retentionMs;
|
|
388
|
-
try {
|
|
389
|
-
if (!ensurePrivateDirectorySync(dir)) {
|
|
390
|
-
writeStderrFallback("[logger] Failed to secure log directory:", dir);
|
|
391
|
-
} else if (!securePrivateTreeSync(dir)) {
|
|
392
|
-
writeStderrFallback("[logger] Failed to secure existing log files:", dir);
|
|
393
|
-
} else {
|
|
394
|
-
const entries = await readdir(dir);
|
|
395
|
-
for (const entry of entries) {
|
|
396
|
-
if (!entry.endsWith(".jsonl")) continue;
|
|
397
|
-
const fullPath = path.join(dir, entry);
|
|
398
|
-
try {
|
|
399
|
-
const s = await stat(fullPath);
|
|
400
|
-
if (s.mtimeMs < cutoff) {
|
|
401
|
-
await unlink(fullPath);
|
|
402
|
-
}
|
|
403
|
-
} catch {
|
|
404
|
-
}
|
|
405
|
-
}
|
|
406
|
-
}
|
|
407
|
-
} catch (err) {
|
|
408
|
-
writeStderrFallback("[logger] Failed to initialize log directory:", err);
|
|
409
|
-
}
|
|
410
|
-
const applicationLogPath = getInspectorLogPath();
|
|
411
|
-
if (!await maintainApplicationLogs(applicationLogPath, policy)) {
|
|
412
|
-
writeStderrFallback(
|
|
413
|
-
"[logger] Failed to initialize application log lifecycle:",
|
|
414
|
-
applicationLogPath
|
|
415
|
-
);
|
|
416
|
-
}
|
|
417
|
-
}
|
|
418
|
-
var loggerInitialization = null;
|
|
419
|
-
var applicationLogWriteQueue = Promise.resolve();
|
|
420
|
-
function ensureLoggerInitialized() {
|
|
421
|
-
if (loggerInitialization === null) loggerInitialization = initLogger();
|
|
422
|
-
return loggerInitialization;
|
|
423
|
-
}
|
|
424
|
-
async function appendApplicationLogLine(logPath, line, policy) {
|
|
425
|
-
const logDirPath = path.dirname(logPath);
|
|
426
|
-
if (!ensurePrivateDirectorySync(logDirPath)) {
|
|
427
|
-
return { ok: false, reason: "application log directory is not private" };
|
|
428
|
-
}
|
|
429
|
-
try {
|
|
430
|
-
if (!await rotateApplicationLogIfNeeded(logPath, Buffer2.byteLength(line, "utf-8"), policy)) {
|
|
431
|
-
return { ok: false, reason: "application log rotation failed" };
|
|
432
|
-
}
|
|
433
|
-
await appendFile(logPath, line, { encoding: "utf-8", mode: PRIVATE_FILE_MODE });
|
|
434
|
-
if (!securePrivateFileSync(logPath)) {
|
|
435
|
-
return { ok: false, reason: "application log permissions could not be secured" };
|
|
436
|
-
}
|
|
437
|
-
return { ok: true };
|
|
438
|
-
} catch (error51) {
|
|
439
|
-
return { ok: false, reason: error51 };
|
|
440
|
-
}
|
|
441
|
-
}
|
|
442
|
-
async function writeAppLog(message) {
|
|
443
|
-
const logPath = getInspectorLogPath();
|
|
444
|
-
const line = `[${(/* @__PURE__ */ new Date()).toISOString()}] ${message}
|
|
445
|
-
`;
|
|
446
|
-
const initialization = ensureLoggerInitialized();
|
|
447
|
-
const write = async () => {
|
|
448
|
-
await initialization;
|
|
449
|
-
const result = await appendApplicationLogLine(logPath, line, getApplicationLogPolicy());
|
|
450
|
-
if (!result.ok) writeStderrFallback(`[logger] Failed to write to ${logPath}:`, result.reason);
|
|
451
|
-
};
|
|
452
|
-
applicationLogWriteQueue = applicationLogWriteQueue.then(write, write);
|
|
453
|
-
await applicationLogWriteQueue;
|
|
454
|
-
}
|
|
455
|
-
var logger = {
|
|
456
|
-
debug(message, ...args) {
|
|
457
|
-
const msg = args.length > 0 ? `${message} ${args.map(String).join(" ")}` : message;
|
|
458
|
-
void writeAppLog(`[DEBUG] ${msg}`);
|
|
459
|
-
},
|
|
460
|
-
info(message, ...args) {
|
|
461
|
-
const msg = args.length > 0 ? `${message} ${args.map(String).join(" ")}` : message;
|
|
462
|
-
void writeAppLog(`[INFO] ${msg}`);
|
|
463
|
-
},
|
|
464
|
-
warn(message, ...args) {
|
|
465
|
-
const msg = args.length > 0 ? `${message} ${args.map(String).join(" ")}` : message;
|
|
466
|
-
void writeAppLog(`[WARN] ${msg}`);
|
|
467
|
-
},
|
|
468
|
-
error(message, ...args) {
|
|
469
|
-
const msg = args.length > 0 ? `${message} ${args.map(String).join(" ")}` : message;
|
|
470
|
-
void writeAppLog(`[ERROR] ${msg}`);
|
|
471
|
-
}
|
|
472
|
-
};
|
|
473
|
-
var writeBuffer = [];
|
|
474
|
-
var writeQueue = Promise.resolve();
|
|
475
|
-
var logWriteLock = Promise.resolve();
|
|
476
|
-
function drainBuffer() {
|
|
477
|
-
const toWrite = writeBuffer.join("");
|
|
478
|
-
writeBuffer = [];
|
|
479
|
-
return toWrite;
|
|
480
|
-
}
|
|
481
|
-
process.on("exit", () => {
|
|
482
|
-
if (writeBuffer.length > 0) {
|
|
483
|
-
const toWrite = drainBuffer();
|
|
484
|
-
try {
|
|
485
|
-
const filePath = getLogFilePath();
|
|
486
|
-
if (!ensurePrivateDirectorySync(path.dirname(filePath))) return;
|
|
487
|
-
appendFileSync(filePath, toWrite, { encoding: "utf-8", mode: PRIVATE_FILE_MODE });
|
|
488
|
-
void securePrivateFileSync(filePath);
|
|
489
|
-
} catch {
|
|
490
|
-
}
|
|
491
|
-
}
|
|
492
|
-
});
|
|
386
|
+
// src/proxy/jsonlRecovery.ts
|
|
387
|
+
import { createHash, randomUUID } from "node:crypto";
|
|
388
|
+
import { Buffer as Buffer2 } from "node:buffer";
|
|
389
|
+
import { constants as constants2, existsSync as existsSync2, lstatSync as lstatSync2 } from "node:fs";
|
|
390
|
+
import { link, lstat, open, readFile, readdir, stat, unlink } from "node:fs/promises";
|
|
391
|
+
import { basename, join as join3, resolve as resolve2 } from "node:path";
|
|
493
392
|
|
|
494
393
|
// node_modules/.bun/zod@4.4.3/node_modules/zod/v4/classic/external.js
|
|
495
394
|
var external_exports = {};
|
|
@@ -674,7 +573,7 @@ __export(external_exports, {
|
|
|
674
573
|
object: () => object,
|
|
675
574
|
optional: () => optional,
|
|
676
575
|
overwrite: () => _overwrite,
|
|
677
|
-
parse: () =>
|
|
576
|
+
parse: () => parse3,
|
|
678
577
|
parseAsync: () => parseAsync2,
|
|
679
578
|
partialRecord: () => partialRecord,
|
|
680
579
|
pipe: () => pipe,
|
|
@@ -994,7 +893,7 @@ __export(core_exports2, {
|
|
|
994
893
|
isValidJWT: () => isValidJWT,
|
|
995
894
|
locales: () => locales_exports,
|
|
996
895
|
meta: () => meta,
|
|
997
|
-
parse: () =>
|
|
896
|
+
parse: () => parse2,
|
|
998
897
|
parseAsync: () => parseAsync,
|
|
999
898
|
prettifyError: () => prettifyError,
|
|
1000
899
|
process: () => process2,
|
|
@@ -1939,7 +1838,7 @@ var _parse = (_Err) => (schema, value, _ctx, _params) => {
|
|
|
1939
1838
|
}
|
|
1940
1839
|
return result.value;
|
|
1941
1840
|
};
|
|
1942
|
-
var
|
|
1841
|
+
var parse2 = /* @__PURE__ */ _parse($ZodRealError);
|
|
1943
1842
|
var _parseAsync = (_Err) => async (schema, value, _ctx, params) => {
|
|
1944
1843
|
const ctx = _ctx ? { ..._ctx, async: true } : { async: true };
|
|
1945
1844
|
let result = schema._zod.run({ value, issues: [] }, ctx);
|
|
@@ -4731,10 +4630,10 @@ var $ZodFunction = /* @__PURE__ */ $constructor("$ZodFunction", (inst, def) => {
|
|
|
4731
4630
|
throw new Error("implement() must be called with a function");
|
|
4732
4631
|
}
|
|
4733
4632
|
return function(...args) {
|
|
4734
|
-
const parsedArgs = inst._def.input ?
|
|
4633
|
+
const parsedArgs = inst._def.input ? parse2(inst._def.input, args) : args;
|
|
4735
4634
|
const result = Reflect.apply(func, this, parsedArgs);
|
|
4736
4635
|
if (inst._def.output) {
|
|
4737
|
-
return
|
|
4636
|
+
return parse2(inst._def.output, result);
|
|
4738
4637
|
}
|
|
4739
4638
|
return result;
|
|
4740
4639
|
};
|
|
@@ -13168,7 +13067,7 @@ var ZodRealError = /* @__PURE__ */ $constructor("ZodError", initializer2, {
|
|
|
13168
13067
|
});
|
|
13169
13068
|
|
|
13170
13069
|
// node_modules/.bun/zod@4.4.3/node_modules/zod/v4/classic/parse.js
|
|
13171
|
-
var
|
|
13070
|
+
var parse3 = /* @__PURE__ */ _parse(ZodRealError);
|
|
13172
13071
|
var parseAsync2 = /* @__PURE__ */ _parseAsync(ZodRealError);
|
|
13173
13072
|
var safeParse2 = /* @__PURE__ */ _safeParse(ZodRealError);
|
|
13174
13073
|
var safeParseAsync2 = /* @__PURE__ */ _safeParseAsync(ZodRealError);
|
|
@@ -13231,7 +13130,7 @@ var ZodType = /* @__PURE__ */ $constructor("ZodType", (inst, def) => {
|
|
|
13231
13130
|
inst.def = def;
|
|
13232
13131
|
inst.type = def.type;
|
|
13233
13132
|
Object.defineProperty(inst, "_def", { value: def });
|
|
13234
|
-
inst.parse = (data, params) =>
|
|
13133
|
+
inst.parse = (data, params) => parse3(inst, data, params, { callee: inst.parse });
|
|
13235
13134
|
inst.safeParse = (data, params) => safeParse2(inst, data, params);
|
|
13236
13135
|
inst.parseAsync = async (data, params) => parseAsync2(inst, data, params, { callee: inst.parseAsync });
|
|
13237
13136
|
inst.safeParseAsync = async (data, params) => safeParseAsync2(inst, data, params);
|
|
@@ -15024,6 +14923,15 @@ function trustAsJsonValue(value) {
|
|
|
15024
14923
|
}
|
|
15025
14924
|
|
|
15026
14925
|
// src/contracts/log.ts
|
|
14926
|
+
var LogIdSchema = external_exports.number().int().nonnegative().max(Number.MAX_SAFE_INTEGER);
|
|
14927
|
+
var CaptureIncompleteReasonSchema = external_exports.enum([
|
|
14928
|
+
"capacity-exceeded",
|
|
14929
|
+
"pipeline-closed",
|
|
14930
|
+
"write-failed",
|
|
14931
|
+
"finalize-failed",
|
|
14932
|
+
"upstream-stream-error",
|
|
14933
|
+
"shutdown"
|
|
14934
|
+
]);
|
|
15027
14935
|
var StreamingChunkSchema = external_exports.object({
|
|
15028
14936
|
index: external_exports.number(),
|
|
15029
14937
|
timestamp: external_exports.number(),
|
|
@@ -15036,7 +14944,7 @@ var StreamingChunksArraySchema = external_exports.object({
|
|
|
15036
14944
|
});
|
|
15037
14945
|
var LogBodyPartSchema = external_exports.enum(["request", "response"]);
|
|
15038
14946
|
var LogBodyChunkSchema = external_exports.object({
|
|
15039
|
-
logId:
|
|
14947
|
+
logId: LogIdSchema,
|
|
15040
14948
|
part: LogBodyPartSchema,
|
|
15041
14949
|
text: external_exports.string(),
|
|
15042
14950
|
offset: external_exports.number().int().nonnegative(),
|
|
@@ -15048,7 +14956,7 @@ var LogBodyChunkSchema = external_exports.object({
|
|
|
15048
14956
|
contentMode: external_exports.enum(["empty", "partial", "full"])
|
|
15049
14957
|
});
|
|
15050
14958
|
var CapturedLogSchema = external_exports.object({
|
|
15051
|
-
id:
|
|
14959
|
+
id: LogIdSchema,
|
|
15052
14960
|
timestamp: external_exports.string(),
|
|
15053
14961
|
method: external_exports.string(),
|
|
15054
14962
|
path: external_exports.string(),
|
|
@@ -15073,7 +14981,7 @@ var CapturedLogSchema = external_exports.object({
|
|
|
15073
14981
|
headers: external_exports.record(external_exports.string(), external_exports.string()).optional(),
|
|
15074
14982
|
apiFormat: external_exports.enum(["anthropic", "openai", "unknown"]).default("unknown"),
|
|
15075
14983
|
isTest: external_exports.boolean().optional().default(false),
|
|
15076
|
-
replayOfLogId:
|
|
14984
|
+
replayOfLogId: LogIdSchema.nullable().optional(),
|
|
15077
14985
|
providerName: external_exports.string().nullable().optional(),
|
|
15078
14986
|
clientPort: external_exports.number().nullable().optional(),
|
|
15079
14987
|
clientPid: external_exports.number().nullable().optional(),
|
|
@@ -15084,6 +14992,10 @@ var CapturedLogSchema = external_exports.object({
|
|
|
15084
14992
|
rawRequestBodyBytes: external_exports.number().int().nonnegative().nullable().optional(),
|
|
15085
14993
|
responseTextBytes: external_exports.number().int().nonnegative().nullable().optional(),
|
|
15086
14994
|
bodyContentMode: external_exports.enum(["full", "compact", "truncated"]).optional(),
|
|
14995
|
+
captureIncomplete: external_exports.boolean().optional(),
|
|
14996
|
+
droppedChunks: external_exports.number().int().nonnegative().optional(),
|
|
14997
|
+
droppedBytes: external_exports.number().int().nonnegative().optional(),
|
|
14998
|
+
captureIncompleteReason: CaptureIncompleteReasonSchema.nullable().optional(),
|
|
15087
14999
|
warnings: external_exports.array(external_exports.string()).optional(),
|
|
15088
15000
|
/** Error message from streaming response (e.g., SSE error event) */
|
|
15089
15001
|
error: external_exports.string().nullable().optional()
|
|
@@ -15456,32 +15368,681 @@ var OpenAIResponsesSSEventSchema = external_exports.object({
|
|
|
15456
15368
|
}).passthrough();
|
|
15457
15369
|
function parseOpenAIResponse(rawBody) {
|
|
15458
15370
|
try {
|
|
15459
|
-
const json2 = JSON.parse(rawBody);
|
|
15460
|
-
const result = OpenAIResponseSchema.safeParse(json2);
|
|
15461
|
-
if (result.success) return result.data;
|
|
15462
|
-
return null;
|
|
15371
|
+
const json2 = JSON.parse(rawBody);
|
|
15372
|
+
const result = OpenAIResponseSchema.safeParse(json2);
|
|
15373
|
+
if (result.success) return result.data;
|
|
15374
|
+
return null;
|
|
15375
|
+
} catch {
|
|
15376
|
+
return null;
|
|
15377
|
+
}
|
|
15378
|
+
}
|
|
15379
|
+
function parseOpenAIResponsesResponse(rawBody) {
|
|
15380
|
+
try {
|
|
15381
|
+
const json2 = JSON.parse(rawBody);
|
|
15382
|
+
const result = OpenAIResponsesResponseSchema.safeParse(json2);
|
|
15383
|
+
if (result.success) return result.data;
|
|
15384
|
+
return null;
|
|
15385
|
+
} catch {
|
|
15386
|
+
return null;
|
|
15387
|
+
}
|
|
15388
|
+
}
|
|
15389
|
+
|
|
15390
|
+
// src/proxy/schemas.ts
|
|
15391
|
+
var RequestModelSchema = external_exports.object({
|
|
15392
|
+
model: external_exports.string()
|
|
15393
|
+
});
|
|
15394
|
+
var LooseRequestSchema = external_exports.object({
|
|
15395
|
+
model: external_exports.string().optional(),
|
|
15396
|
+
metadata: external_exports.object({ user_id: external_exports.string().optional() }).passthrough().optional()
|
|
15397
|
+
});
|
|
15398
|
+
|
|
15399
|
+
// src/proxy/jsonlRecovery.ts
|
|
15400
|
+
var READ_CHUNK_BYTES = 64 * 1024;
|
|
15401
|
+
var QUARANTINE_DIRECTORY = "quarantine";
|
|
15402
|
+
var activeContext = null;
|
|
15403
|
+
function emptyHealth() {
|
|
15404
|
+
return {
|
|
15405
|
+
level: "ok",
|
|
15406
|
+
diagnostic: null,
|
|
15407
|
+
repairedFiles: 0,
|
|
15408
|
+
delimiterRepairs: 0,
|
|
15409
|
+
quarantinedTails: 0
|
|
15410
|
+
};
|
|
15411
|
+
}
|
|
15412
|
+
function contextFor(logDir) {
|
|
15413
|
+
const root = resolve2(logDir);
|
|
15414
|
+
if (activeContext === null || activeContext.root !== root) {
|
|
15415
|
+
activeContext = {
|
|
15416
|
+
root,
|
|
15417
|
+
health: emptyHealth(),
|
|
15418
|
+
startup: null,
|
|
15419
|
+
startupComplete: false,
|
|
15420
|
+
safeFiles: /* @__PURE__ */ new Map()
|
|
15421
|
+
};
|
|
15422
|
+
}
|
|
15423
|
+
return activeContext;
|
|
15424
|
+
}
|
|
15425
|
+
function copyHealth(health) {
|
|
15426
|
+
return { ...health };
|
|
15427
|
+
}
|
|
15428
|
+
function hashBytes(value) {
|
|
15429
|
+
return createHash("sha256").update(value).digest("hex");
|
|
15430
|
+
}
|
|
15431
|
+
function signatureFromStats(stats) {
|
|
15432
|
+
return {
|
|
15433
|
+
size: stats.size,
|
|
15434
|
+
modifiedAt: stats.mtimeMs,
|
|
15435
|
+
changedAt: stats.ctimeMs,
|
|
15436
|
+
device: stats.dev,
|
|
15437
|
+
inode: stats.ino
|
|
15438
|
+
};
|
|
15439
|
+
}
|
|
15440
|
+
function signaturesMatch(left, right) {
|
|
15441
|
+
return left.size === right.size && left.modifiedAt === right.modifiedAt && left.changedAt === right.changedAt && left.device === right.device && left.inode === right.inode;
|
|
15442
|
+
}
|
|
15443
|
+
function validateRecord(bytes) {
|
|
15444
|
+
const withoutCarriageReturn = bytes.length > 0 && bytes[bytes.length - 1] === 13 ? bytes.subarray(0, -1) : bytes;
|
|
15445
|
+
const text = withoutCarriageReturn.toString("utf-8");
|
|
15446
|
+
if (text.trim() === "") return { valid: true };
|
|
15447
|
+
let parsed;
|
|
15448
|
+
try {
|
|
15449
|
+
parsed = JSON.parse(text);
|
|
15450
|
+
} catch {
|
|
15451
|
+
return { valid: false, reason: "invalid-json" };
|
|
15452
|
+
}
|
|
15453
|
+
return CapturedLogSchema.safeParse(parsed).success ? { valid: true } : { valid: false, reason: "invalid-log-schema" };
|
|
15454
|
+
}
|
|
15455
|
+
async function scanFile(handle, size) {
|
|
15456
|
+
const readBuffer = Buffer2.alloc(READ_CHUNK_BYTES);
|
|
15457
|
+
let position = 0;
|
|
15458
|
+
let pending = Buffer2.alloc(0);
|
|
15459
|
+
let pendingOffset = 0;
|
|
15460
|
+
let line = 1;
|
|
15461
|
+
while (position < size) {
|
|
15462
|
+
const length = Math.min(READ_CHUNK_BYTES, size - position);
|
|
15463
|
+
let bytesRead;
|
|
15464
|
+
try {
|
|
15465
|
+
const result = await handle.read(readBuffer, 0, length, position);
|
|
15466
|
+
bytesRead = result.bytesRead;
|
|
15467
|
+
} catch (error51) {
|
|
15468
|
+
return { status: "failed", reason: `read failed: ${String(error51)}` };
|
|
15469
|
+
}
|
|
15470
|
+
if (bytesRead === 0) {
|
|
15471
|
+
return { status: "failed", reason: "captured-log file changed while being scanned" };
|
|
15472
|
+
}
|
|
15473
|
+
const chunk = readBuffer.subarray(0, bytesRead);
|
|
15474
|
+
const combined = pending.length === 0 ? Buffer2.from(chunk) : Buffer2.concat([pending, chunk]);
|
|
15475
|
+
let consumed = 0;
|
|
15476
|
+
let newline = combined.indexOf(10, consumed);
|
|
15477
|
+
while (newline !== -1) {
|
|
15478
|
+
const record2 = combined.subarray(consumed, newline);
|
|
15479
|
+
const validation = validateRecord(record2);
|
|
15480
|
+
if (!validation.valid) {
|
|
15481
|
+
return {
|
|
15482
|
+
status: "interior-corruption",
|
|
15483
|
+
line,
|
|
15484
|
+
byteOffset: pendingOffset + consumed,
|
|
15485
|
+
recordHash: hashBytes(record2),
|
|
15486
|
+
reason: validation.reason
|
|
15487
|
+
};
|
|
15488
|
+
}
|
|
15489
|
+
consumed = newline + 1;
|
|
15490
|
+
line += 1;
|
|
15491
|
+
newline = combined.indexOf(10, consumed);
|
|
15492
|
+
}
|
|
15493
|
+
pending = Buffer2.from(combined.subarray(consumed));
|
|
15494
|
+
pendingOffset += consumed;
|
|
15495
|
+
position += bytesRead;
|
|
15496
|
+
}
|
|
15497
|
+
return { status: "complete", pending, pendingOffset, nextLine: line };
|
|
15498
|
+
}
|
|
15499
|
+
async function syncDirectory(directory) {
|
|
15500
|
+
let handle = null;
|
|
15501
|
+
try {
|
|
15502
|
+
handle = await open(directory, "r");
|
|
15503
|
+
await handle.sync();
|
|
15504
|
+
} catch {
|
|
15505
|
+
} finally {
|
|
15506
|
+
await handle?.close().catch(() => void 0);
|
|
15507
|
+
}
|
|
15508
|
+
}
|
|
15509
|
+
async function removeTemporaryFile(filePath) {
|
|
15510
|
+
await unlink(filePath).catch(() => void 0);
|
|
15511
|
+
}
|
|
15512
|
+
function readOwnProperty(value, name) {
|
|
15513
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) return void 0;
|
|
15514
|
+
return Object.getOwnPropertyDescriptor(value, name)?.value;
|
|
15515
|
+
}
|
|
15516
|
+
async function inspectExistingQuarantine(filePath, expected) {
|
|
15517
|
+
if (!existsSync2(filePath)) return "missing";
|
|
15518
|
+
try {
|
|
15519
|
+
const parsed = JSON.parse(await readFile(filePath, "utf-8"));
|
|
15520
|
+
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";
|
|
15521
|
+
} catch {
|
|
15522
|
+
return "conflicting";
|
|
15523
|
+
}
|
|
15524
|
+
}
|
|
15525
|
+
async function quarantineTail(context, sourceFile, tail, tailOffset) {
|
|
15526
|
+
const quarantineDirectory = join3(context.root, QUARANTINE_DIRECTORY);
|
|
15527
|
+
if (!ensurePrivateDirectorySync(quarantineDirectory)) return null;
|
|
15528
|
+
const tailSha256 = hashBytes(tail);
|
|
15529
|
+
const sourceFileName = basename(sourceFile);
|
|
15530
|
+
const destination = join3(quarantineDirectory, `${sourceFileName}.tail-${tailSha256}.json`);
|
|
15531
|
+
const temporary = join3(
|
|
15532
|
+
quarantineDirectory,
|
|
15533
|
+
`.${sourceFileName}.${String(process.pid)}.${randomUUID()}.tmp`
|
|
15534
|
+
);
|
|
15535
|
+
const record2 = {
|
|
15536
|
+
schemaVersion: 1,
|
|
15537
|
+
reason: "invalid-final-jsonl-record",
|
|
15538
|
+
sourceFile: sourceFileName,
|
|
15539
|
+
sourcePathHash: hashBytes(Buffer2.from(resolve2(sourceFile), "utf-8")),
|
|
15540
|
+
recoveredAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
15541
|
+
tailOffset,
|
|
15542
|
+
tailBytes: tail.length,
|
|
15543
|
+
tailSha256,
|
|
15544
|
+
tailBase64: tail.toString("base64")
|
|
15545
|
+
};
|
|
15546
|
+
const existing = await inspectExistingQuarantine(destination, record2);
|
|
15547
|
+
if (existing === "matching") {
|
|
15548
|
+
return securePrivateFileSync(destination) ? destination : null;
|
|
15549
|
+
}
|
|
15550
|
+
if (existing === "conflicting") return null;
|
|
15551
|
+
let handle = null;
|
|
15552
|
+
try {
|
|
15553
|
+
handle = await open(temporary, "wx", PRIVATE_FILE_MODE);
|
|
15554
|
+
await handle.writeFile(`${JSON.stringify(record2)}
|
|
15555
|
+
`, "utf-8");
|
|
15556
|
+
await handle.sync();
|
|
15557
|
+
await handle.close();
|
|
15558
|
+
handle = null;
|
|
15559
|
+
if (!securePrivateFileSync(temporary)) {
|
|
15560
|
+
await removeTemporaryFile(temporary);
|
|
15561
|
+
return null;
|
|
15562
|
+
}
|
|
15563
|
+
await link(temporary, destination);
|
|
15564
|
+
await unlink(temporary);
|
|
15565
|
+
if (!securePrivateFileSync(destination)) return null;
|
|
15566
|
+
await syncDirectory(quarantineDirectory);
|
|
15567
|
+
return destination;
|
|
15568
|
+
} catch {
|
|
15569
|
+
await handle?.close().catch(() => void 0);
|
|
15570
|
+
await removeTemporaryFile(temporary);
|
|
15571
|
+
const racedExisting = await inspectExistingQuarantine(destination, record2);
|
|
15572
|
+
return racedExisting === "matching" && securePrivateFileSync(destination) ? destination : null;
|
|
15573
|
+
}
|
|
15574
|
+
}
|
|
15575
|
+
async function recoverFile(context, filePath) {
|
|
15576
|
+
if (!existsSync2(filePath)) {
|
|
15577
|
+
context.safeFiles.delete(filePath);
|
|
15578
|
+
return {
|
|
15579
|
+
status: "clean",
|
|
15580
|
+
signature: { size: 0, modifiedAt: 0, changedAt: 0, device: 0, inode: 0 }
|
|
15581
|
+
};
|
|
15582
|
+
}
|
|
15583
|
+
let fileStats;
|
|
15584
|
+
try {
|
|
15585
|
+
fileStats = await lstat(filePath);
|
|
15586
|
+
} catch (error51) {
|
|
15587
|
+
return { status: "failed", reason: `stat failed: ${String(error51)}` };
|
|
15588
|
+
}
|
|
15589
|
+
if (fileStats.isSymbolicLink() || !fileStats.isFile()) {
|
|
15590
|
+
return { status: "failed", reason: "captured-log path is not a regular private file" };
|
|
15591
|
+
}
|
|
15592
|
+
const initialSignature = signatureFromStats(fileStats);
|
|
15593
|
+
const safeSignature = context.safeFiles.get(filePath);
|
|
15594
|
+
if (safeSignature !== void 0 && signaturesMatch(safeSignature, initialSignature)) {
|
|
15595
|
+
return { status: "clean", signature: initialSignature };
|
|
15596
|
+
}
|
|
15597
|
+
let handle = null;
|
|
15598
|
+
try {
|
|
15599
|
+
handle = await open(filePath, constants2.O_RDWR | constants2.O_NOFOLLOW);
|
|
15600
|
+
const openedStats = await handle.stat();
|
|
15601
|
+
if (!openedStats.isFile()) {
|
|
15602
|
+
return { status: "failed", reason: "captured-log handle is not a regular file" };
|
|
15603
|
+
}
|
|
15604
|
+
const openedSignature = signatureFromStats(openedStats);
|
|
15605
|
+
if (!signaturesMatch(initialSignature, openedSignature)) {
|
|
15606
|
+
return {
|
|
15607
|
+
status: "failed",
|
|
15608
|
+
reason: "captured-log path changed between metadata validation and open"
|
|
15609
|
+
};
|
|
15610
|
+
}
|
|
15611
|
+
const scan = await scanFile(handle, openedStats.size);
|
|
15612
|
+
const scannedSignature = signatureFromStats(await handle.stat());
|
|
15613
|
+
if (!signaturesMatch(openedSignature, scannedSignature)) {
|
|
15614
|
+
return {
|
|
15615
|
+
status: "failed",
|
|
15616
|
+
reason: "captured-log file changed while recovery was scanning it"
|
|
15617
|
+
};
|
|
15618
|
+
}
|
|
15619
|
+
switch (scan.status) {
|
|
15620
|
+
case "failed":
|
|
15621
|
+
return scan;
|
|
15622
|
+
case "interior-corruption":
|
|
15623
|
+
return scan;
|
|
15624
|
+
case "complete": {
|
|
15625
|
+
if (scan.pending.length === 0) {
|
|
15626
|
+
return { status: "clean", signature: signatureFromStats(await handle.stat()) };
|
|
15627
|
+
}
|
|
15628
|
+
const validation = validateRecord(scan.pending);
|
|
15629
|
+
if (validation.valid) {
|
|
15630
|
+
const write = await handle.write(Buffer2.from("\n", "utf-8"), 0, 1, openedStats.size);
|
|
15631
|
+
if (write.bytesWritten !== 1) {
|
|
15632
|
+
return { status: "failed", reason: "captured-log delimiter append was incomplete" };
|
|
15633
|
+
}
|
|
15634
|
+
await handle.sync();
|
|
15635
|
+
return {
|
|
15636
|
+
status: "delimiter-appended",
|
|
15637
|
+
signature: signatureFromStats(await handle.stat())
|
|
15638
|
+
};
|
|
15639
|
+
}
|
|
15640
|
+
const quarantinePath = await quarantineTail(
|
|
15641
|
+
context,
|
|
15642
|
+
filePath,
|
|
15643
|
+
scan.pending,
|
|
15644
|
+
scan.pendingOffset
|
|
15645
|
+
);
|
|
15646
|
+
if (quarantinePath === null) {
|
|
15647
|
+
return { status: "failed", reason: "invalid tail could not be privately quarantined" };
|
|
15648
|
+
}
|
|
15649
|
+
const beforeTruncate = signatureFromStats(await handle.stat());
|
|
15650
|
+
if (!signaturesMatch(openedSignature, beforeTruncate)) {
|
|
15651
|
+
return {
|
|
15652
|
+
status: "failed",
|
|
15653
|
+
reason: "captured-log file changed before invalid-tail truncation"
|
|
15654
|
+
};
|
|
15655
|
+
}
|
|
15656
|
+
await handle.truncate(scan.pendingOffset);
|
|
15657
|
+
await handle.sync();
|
|
15658
|
+
return {
|
|
15659
|
+
status: "tail-quarantined",
|
|
15660
|
+
signature: signatureFromStats(await handle.stat())
|
|
15661
|
+
};
|
|
15662
|
+
}
|
|
15663
|
+
}
|
|
15664
|
+
return { status: "failed", reason: "unsupported captured-log scan state" };
|
|
15665
|
+
} catch (error51) {
|
|
15666
|
+
return { status: "failed", reason: String(error51) };
|
|
15667
|
+
} finally {
|
|
15668
|
+
await handle?.close().catch(() => void 0);
|
|
15669
|
+
}
|
|
15670
|
+
}
|
|
15671
|
+
function applyFileResult(context, filePath, result) {
|
|
15672
|
+
const file2 = basename(filePath);
|
|
15673
|
+
switch (result.status) {
|
|
15674
|
+
case "clean":
|
|
15675
|
+
context.safeFiles.set(filePath, result.signature);
|
|
15676
|
+
return;
|
|
15677
|
+
case "delimiter-appended":
|
|
15678
|
+
context.safeFiles.set(filePath, result.signature);
|
|
15679
|
+
context.health.delimiterRepairs += 1;
|
|
15680
|
+
context.health.repairedFiles += 1;
|
|
15681
|
+
return;
|
|
15682
|
+
case "tail-quarantined":
|
|
15683
|
+
context.safeFiles.set(filePath, result.signature);
|
|
15684
|
+
context.health.quarantinedTails += 1;
|
|
15685
|
+
context.health.repairedFiles += 1;
|
|
15686
|
+
if (context.health.level !== "unavailable") {
|
|
15687
|
+
context.health.level = "degraded";
|
|
15688
|
+
context.health.diagnostic = `Recovered and quarantined an invalid JSONL tail in ${file2}`;
|
|
15689
|
+
}
|
|
15690
|
+
return;
|
|
15691
|
+
case "interior-corruption":
|
|
15692
|
+
context.safeFiles.delete(filePath);
|
|
15693
|
+
context.health.level = "unavailable";
|
|
15694
|
+
context.health.diagnostic = `JSONL corruption in ${file2} at line ${String(result.line)} (offset ${String(result.byteOffset)}, ${result.reason}, sha256 ${result.recordHash})`;
|
|
15695
|
+
return;
|
|
15696
|
+
case "failed":
|
|
15697
|
+
context.safeFiles.delete(filePath);
|
|
15698
|
+
context.health.level = "unavailable";
|
|
15699
|
+
context.health.diagnostic = `JSONL recovery failed for ${file2}: ${result.reason}`;
|
|
15700
|
+
}
|
|
15701
|
+
}
|
|
15702
|
+
async function runStartupRecovery(context) {
|
|
15703
|
+
if (!ensurePrivateDirectorySync(context.root)) {
|
|
15704
|
+
context.health.level = "unavailable";
|
|
15705
|
+
context.health.diagnostic = "Captured-log directory could not be made private";
|
|
15706
|
+
return copyHealth(context.health);
|
|
15707
|
+
}
|
|
15708
|
+
let entries;
|
|
15709
|
+
try {
|
|
15710
|
+
entries = await readdir(context.root);
|
|
15711
|
+
} catch (error51) {
|
|
15712
|
+
context.health.level = "unavailable";
|
|
15713
|
+
context.health.diagnostic = `Captured-log directory could not be listed: ${String(error51)}`;
|
|
15714
|
+
return copyHealth(context.health);
|
|
15715
|
+
}
|
|
15716
|
+
const files = entries.filter((entry) => entry.endsWith(".jsonl")).sort();
|
|
15717
|
+
for (const file2 of files) {
|
|
15718
|
+
const filePath = join3(context.root, file2);
|
|
15719
|
+
const result = await recoverFile(context, filePath);
|
|
15720
|
+
applyFileResult(context, filePath, result);
|
|
15721
|
+
if (context.health.level === "unavailable") break;
|
|
15722
|
+
}
|
|
15723
|
+
return copyHealth(context.health);
|
|
15724
|
+
}
|
|
15725
|
+
async function recoverCapturedLogStorage(logDir) {
|
|
15726
|
+
const context = contextFor(logDir);
|
|
15727
|
+
if (context.startup === null) {
|
|
15728
|
+
context.startup = runStartupRecovery(context).then((health) => {
|
|
15729
|
+
context.startupComplete = true;
|
|
15730
|
+
return health;
|
|
15731
|
+
});
|
|
15732
|
+
}
|
|
15733
|
+
return await context.startup;
|
|
15734
|
+
}
|
|
15735
|
+
function canAppendCapturedLogFileOnExit(logDir, filePath) {
|
|
15736
|
+
const context = contextFor(logDir);
|
|
15737
|
+
if (!context.startupComplete || context.health.level === "unavailable") return false;
|
|
15738
|
+
const trusted = context.safeFiles.get(filePath);
|
|
15739
|
+
if (trusted === void 0) return false;
|
|
15740
|
+
try {
|
|
15741
|
+
const observed = lstatSync2(filePath);
|
|
15742
|
+
if (observed === void 0 || observed.isSymbolicLink() || !observed.isFile()) return false;
|
|
15743
|
+
return signaturesMatch(trusted, signatureFromStats(observed));
|
|
15744
|
+
} catch {
|
|
15745
|
+
return false;
|
|
15746
|
+
}
|
|
15747
|
+
}
|
|
15748
|
+
|
|
15749
|
+
// src/proxy/logger.ts
|
|
15750
|
+
var DAY_MS = 24 * 60 * 60 * 1e3;
|
|
15751
|
+
var DEFAULT_RETENTION_DAYS = 7;
|
|
15752
|
+
var DEFAULT_APP_LOG_MAX_BYTES = 10 * 1024 * 1024;
|
|
15753
|
+
var DEFAULT_APP_LOG_MAX_FILES = 5;
|
|
15754
|
+
function writeStderrFallback(message, error51) {
|
|
15755
|
+
process.stderr.write(`${message} ${String(error51)}
|
|
15756
|
+
`);
|
|
15757
|
+
}
|
|
15758
|
+
function resolveLogDir() {
|
|
15759
|
+
const logDirEnv = process.env["LOG_DIR"];
|
|
15760
|
+
if (logDirEnv !== void 0 && logDirEnv !== "") {
|
|
15761
|
+
return path.isAbsolute(logDirEnv) ? logDirEnv : path.join(getDataDir(), logDirEnv);
|
|
15762
|
+
}
|
|
15763
|
+
return path.join(getDataDir(), "logs");
|
|
15764
|
+
}
|
|
15765
|
+
function getLogFilePath() {
|
|
15766
|
+
const date5 = /* @__PURE__ */ new Date();
|
|
15767
|
+
const yyyy = date5.getUTCFullYear();
|
|
15768
|
+
const mm = String(date5.getUTCMonth() + 1).padStart(2, "0");
|
|
15769
|
+
const dd = String(date5.getUTCDate()).padStart(2, "0");
|
|
15770
|
+
return path.join(resolveLogDir(), `${yyyy}-${mm}-${dd}.jsonl`);
|
|
15771
|
+
}
|
|
15772
|
+
function getInspectorLogPath() {
|
|
15773
|
+
const logFileEnv = process.env["AGENT_INSPECTOR_LOG_FILE"];
|
|
15774
|
+
if (logFileEnv !== void 0 && logFileEnv !== "") {
|
|
15775
|
+
return logFileEnv;
|
|
15776
|
+
}
|
|
15777
|
+
return path.join(getDataDir(), "logs", "inspector.log");
|
|
15778
|
+
}
|
|
15779
|
+
function readBoundedInteger(name, fallback, minimum, maximum) {
|
|
15780
|
+
const raw = process.env[name];
|
|
15781
|
+
if (raw === void 0 || raw === "") return fallback;
|
|
15782
|
+
const parsed = Number(raw);
|
|
15783
|
+
if (!Number.isInteger(parsed) || parsed < minimum || parsed > maximum) return fallback;
|
|
15784
|
+
return parsed;
|
|
15785
|
+
}
|
|
15786
|
+
function getApplicationLogPolicy() {
|
|
15787
|
+
const retentionDays = readBoundedInteger("LOG_RETENTION_DAYS", DEFAULT_RETENTION_DAYS, 1, 3650);
|
|
15788
|
+
return {
|
|
15789
|
+
maxBytes: readBoundedInteger(
|
|
15790
|
+
"AGENT_INSPECTOR_APP_LOG_MAX_BYTES",
|
|
15791
|
+
DEFAULT_APP_LOG_MAX_BYTES,
|
|
15792
|
+
1,
|
|
15793
|
+
1024 * 1024 * 1024
|
|
15794
|
+
),
|
|
15795
|
+
maxFiles: readBoundedInteger(
|
|
15796
|
+
"AGENT_INSPECTOR_APP_LOG_MAX_FILES",
|
|
15797
|
+
DEFAULT_APP_LOG_MAX_FILES,
|
|
15798
|
+
1,
|
|
15799
|
+
100
|
|
15800
|
+
),
|
|
15801
|
+
retentionMs: retentionDays * DAY_MS
|
|
15802
|
+
};
|
|
15803
|
+
}
|
|
15804
|
+
function getRotatedGeneration(entry, baseName) {
|
|
15805
|
+
const prefix = `${baseName}.`;
|
|
15806
|
+
if (!entry.startsWith(prefix)) return null;
|
|
15807
|
+
const suffix = entry.slice(prefix.length);
|
|
15808
|
+
if (!/^\d+$/.test(suffix)) return null;
|
|
15809
|
+
const generation = Number(suffix);
|
|
15810
|
+
if (!Number.isSafeInteger(generation) || generation < 1) return null;
|
|
15811
|
+
return generation;
|
|
15812
|
+
}
|
|
15813
|
+
async function listApplicationLogFiles(logPath) {
|
|
15814
|
+
const directory = path.dirname(logPath);
|
|
15815
|
+
const baseName = path.basename(logPath);
|
|
15816
|
+
const entries = await readdir2(directory);
|
|
15817
|
+
const files = [];
|
|
15818
|
+
for (const entry of entries) {
|
|
15819
|
+
const generation = entry === baseName ? 0 : getRotatedGeneration(entry, baseName);
|
|
15820
|
+
if (generation === null) continue;
|
|
15821
|
+
const filePath = path.join(directory, entry);
|
|
15822
|
+
try {
|
|
15823
|
+
const fileStat = await stat2(filePath);
|
|
15824
|
+
if (!fileStat.isFile()) continue;
|
|
15825
|
+
files.push({ generation, modifiedAt: fileStat.mtimeMs, path: filePath });
|
|
15826
|
+
} catch {
|
|
15827
|
+
}
|
|
15828
|
+
}
|
|
15829
|
+
return files;
|
|
15830
|
+
}
|
|
15831
|
+
async function removeApplicationLog(filePath) {
|
|
15832
|
+
try {
|
|
15833
|
+
await stat2(filePath);
|
|
15463
15834
|
} catch {
|
|
15464
|
-
return
|
|
15835
|
+
return true;
|
|
15836
|
+
}
|
|
15837
|
+
try {
|
|
15838
|
+
await unlink2(filePath);
|
|
15839
|
+
return true;
|
|
15840
|
+
} catch {
|
|
15841
|
+
return false;
|
|
15465
15842
|
}
|
|
15466
15843
|
}
|
|
15467
|
-
function
|
|
15844
|
+
async function maintainApplicationLogs(logPath, policy) {
|
|
15845
|
+
const directory = path.dirname(logPath);
|
|
15846
|
+
if (!ensurePrivateDirectorySync(directory)) return false;
|
|
15847
|
+
let files;
|
|
15468
15848
|
try {
|
|
15469
|
-
|
|
15470
|
-
const result = OpenAIResponsesResponseSchema.safeParse(json2);
|
|
15471
|
-
if (result.success) return result.data;
|
|
15472
|
-
return null;
|
|
15849
|
+
files = await listApplicationLogFiles(logPath);
|
|
15473
15850
|
} catch {
|
|
15474
|
-
return
|
|
15851
|
+
return false;
|
|
15852
|
+
}
|
|
15853
|
+
for (const file2 of files) {
|
|
15854
|
+
if (!securePrivateFileSync(file2.path)) return false;
|
|
15855
|
+
}
|
|
15856
|
+
const cutoff = Date.now() - policy.retentionMs;
|
|
15857
|
+
const retained = files.filter((file2) => file2.modifiedAt >= cutoff);
|
|
15858
|
+
let maintained = true;
|
|
15859
|
+
for (const file2 of files) {
|
|
15860
|
+
if (file2.modifiedAt < cutoff && !await removeApplicationLog(file2.path)) maintained = false;
|
|
15861
|
+
}
|
|
15862
|
+
const rotated = retained.filter((file2) => file2.generation > 0).sort((left, right) => right.modifiedAt - left.modifiedAt);
|
|
15863
|
+
const retainedRotatedCount = Math.max(0, policy.maxFiles - 1);
|
|
15864
|
+
for (const file2 of rotated.slice(retainedRotatedCount)) {
|
|
15865
|
+
if (!await removeApplicationLog(file2.path)) maintained = false;
|
|
15475
15866
|
}
|
|
15867
|
+
return maintained;
|
|
15476
15868
|
}
|
|
15477
|
-
|
|
15478
|
-
|
|
15479
|
-
|
|
15480
|
-
|
|
15481
|
-
|
|
15482
|
-
|
|
15483
|
-
|
|
15484
|
-
|
|
15869
|
+
async function moveApplicationLog(source, destination) {
|
|
15870
|
+
try {
|
|
15871
|
+
await stat2(source);
|
|
15872
|
+
} catch {
|
|
15873
|
+
return true;
|
|
15874
|
+
}
|
|
15875
|
+
try {
|
|
15876
|
+
await rename(source, destination);
|
|
15877
|
+
if (!securePrivateFileSync(destination)) {
|
|
15878
|
+
writeStderrFallback("[logger] Failed to secure rotated application log:", destination);
|
|
15879
|
+
return false;
|
|
15880
|
+
}
|
|
15881
|
+
return true;
|
|
15882
|
+
} catch (error51) {
|
|
15883
|
+
writeStderrFallback("[logger] Failed to rotate application log:", error51);
|
|
15884
|
+
return false;
|
|
15885
|
+
}
|
|
15886
|
+
}
|
|
15887
|
+
async function rotateApplicationLog(logPath, maxFiles) {
|
|
15888
|
+
if (maxFiles === 1) {
|
|
15889
|
+
return await removeApplicationLog(logPath);
|
|
15890
|
+
}
|
|
15891
|
+
if (!await removeApplicationLog(`${logPath}.${String(maxFiles - 1)}`)) return false;
|
|
15892
|
+
for (let generation = maxFiles - 2; generation >= 1; generation -= 1) {
|
|
15893
|
+
if (!await moveApplicationLog(
|
|
15894
|
+
`${logPath}.${String(generation)}`,
|
|
15895
|
+
`${logPath}.${String(generation + 1)}`
|
|
15896
|
+
)) {
|
|
15897
|
+
return false;
|
|
15898
|
+
}
|
|
15899
|
+
}
|
|
15900
|
+
return await moveApplicationLog(logPath, `${logPath}.1`);
|
|
15901
|
+
}
|
|
15902
|
+
async function rotateApplicationLogIfNeeded(logPath, incomingBytes, policy) {
|
|
15903
|
+
try {
|
|
15904
|
+
const fileStat = await stat2(logPath);
|
|
15905
|
+
if (fileStat.size > 0 && fileStat.size + incomingBytes > policy.maxBytes) {
|
|
15906
|
+
return await rotateApplicationLog(logPath, policy.maxFiles);
|
|
15907
|
+
}
|
|
15908
|
+
return true;
|
|
15909
|
+
} catch {
|
|
15910
|
+
return true;
|
|
15911
|
+
}
|
|
15912
|
+
}
|
|
15913
|
+
async function initLogger() {
|
|
15914
|
+
const dir = resolveLogDir();
|
|
15915
|
+
const policy = getApplicationLogPolicy();
|
|
15916
|
+
const cutoff = Date.now() - policy.retentionMs;
|
|
15917
|
+
try {
|
|
15918
|
+
if (!ensurePrivateDirectorySync(dir)) {
|
|
15919
|
+
writeStderrFallback("[logger] Failed to secure log directory:", dir);
|
|
15920
|
+
} else if (!securePrivateTreeSync(dir)) {
|
|
15921
|
+
writeStderrFallback("[logger] Failed to secure existing log files:", dir);
|
|
15922
|
+
} else {
|
|
15923
|
+
const recovery = await recoverCapturedLogStorage(dir);
|
|
15924
|
+
if (recovery.level === "unavailable") {
|
|
15925
|
+
writeStderrFallback(
|
|
15926
|
+
"[logger] Captured-log recovery blocked readiness:",
|
|
15927
|
+
recovery.diagnostic ?? "unknown recovery failure"
|
|
15928
|
+
);
|
|
15929
|
+
} else {
|
|
15930
|
+
const entries = await readdir2(dir);
|
|
15931
|
+
for (const entry of entries) {
|
|
15932
|
+
if (!entry.endsWith(".jsonl")) continue;
|
|
15933
|
+
const fullPath = path.join(dir, entry);
|
|
15934
|
+
try {
|
|
15935
|
+
const s = await stat2(fullPath);
|
|
15936
|
+
if (s.mtimeMs < cutoff) {
|
|
15937
|
+
await unlink2(fullPath);
|
|
15938
|
+
}
|
|
15939
|
+
} catch {
|
|
15940
|
+
}
|
|
15941
|
+
}
|
|
15942
|
+
}
|
|
15943
|
+
}
|
|
15944
|
+
} catch (err) {
|
|
15945
|
+
writeStderrFallback("[logger] Failed to initialize log directory:", err);
|
|
15946
|
+
}
|
|
15947
|
+
const applicationLogPath = getInspectorLogPath();
|
|
15948
|
+
if (!await maintainApplicationLogs(applicationLogPath, policy)) {
|
|
15949
|
+
writeStderrFallback(
|
|
15950
|
+
"[logger] Failed to initialize application log lifecycle:",
|
|
15951
|
+
applicationLogPath
|
|
15952
|
+
);
|
|
15953
|
+
}
|
|
15954
|
+
}
|
|
15955
|
+
var loggerInitialization = null;
|
|
15956
|
+
var applicationLogWriteQueue = Promise.resolve();
|
|
15957
|
+
function ensureLoggerInitialized() {
|
|
15958
|
+
if (loggerInitialization === null) loggerInitialization = initLogger();
|
|
15959
|
+
return loggerInitialization;
|
|
15960
|
+
}
|
|
15961
|
+
async function appendApplicationLogLine(logPath, line, policy) {
|
|
15962
|
+
const logDirPath = path.dirname(logPath);
|
|
15963
|
+
if (!ensurePrivateDirectorySync(logDirPath)) {
|
|
15964
|
+
return { ok: false, reason: "application log directory is not private" };
|
|
15965
|
+
}
|
|
15966
|
+
try {
|
|
15967
|
+
if (!await rotateApplicationLogIfNeeded(logPath, Buffer3.byteLength(line, "utf-8"), policy)) {
|
|
15968
|
+
return { ok: false, reason: "application log rotation failed" };
|
|
15969
|
+
}
|
|
15970
|
+
await appendFile(logPath, line, { encoding: "utf-8", mode: PRIVATE_FILE_MODE });
|
|
15971
|
+
if (!securePrivateFileSync(logPath)) {
|
|
15972
|
+
return { ok: false, reason: "application log permissions could not be secured" };
|
|
15973
|
+
}
|
|
15974
|
+
return { ok: true };
|
|
15975
|
+
} catch (error51) {
|
|
15976
|
+
return { ok: false, reason: error51 };
|
|
15977
|
+
}
|
|
15978
|
+
}
|
|
15979
|
+
async function writeAppLog(message) {
|
|
15980
|
+
const logPath = getInspectorLogPath();
|
|
15981
|
+
const line = `[${(/* @__PURE__ */ new Date()).toISOString()}] ${message}
|
|
15982
|
+
`;
|
|
15983
|
+
const initialization = ensureLoggerInitialized();
|
|
15984
|
+
const write = async () => {
|
|
15985
|
+
await initialization;
|
|
15986
|
+
const result = await appendApplicationLogLine(logPath, line, getApplicationLogPolicy());
|
|
15987
|
+
if (!result.ok) writeStderrFallback(`[logger] Failed to write to ${logPath}:`, result.reason);
|
|
15988
|
+
};
|
|
15989
|
+
applicationLogWriteQueue = applicationLogWriteQueue.then(write, write);
|
|
15990
|
+
await applicationLogWriteQueue;
|
|
15991
|
+
}
|
|
15992
|
+
var logger = {
|
|
15993
|
+
debug(message, ...args) {
|
|
15994
|
+
const msg = args.length > 0 ? `${message} ${args.map(String).join(" ")}` : message;
|
|
15995
|
+
void writeAppLog(`[DEBUG] ${msg}`);
|
|
15996
|
+
},
|
|
15997
|
+
info(message, ...args) {
|
|
15998
|
+
const msg = args.length > 0 ? `${message} ${args.map(String).join(" ")}` : message;
|
|
15999
|
+
void writeAppLog(`[INFO] ${msg}`);
|
|
16000
|
+
},
|
|
16001
|
+
warn(message, ...args) {
|
|
16002
|
+
const msg = args.length > 0 ? `${message} ${args.map(String).join(" ")}` : message;
|
|
16003
|
+
void writeAppLog(`[WARN] ${msg}`);
|
|
16004
|
+
},
|
|
16005
|
+
error(message, ...args) {
|
|
16006
|
+
const msg = args.length > 0 ? `${message} ${args.map(String).join(" ")}` : message;
|
|
16007
|
+
void writeAppLog(`[ERROR] ${msg}`);
|
|
16008
|
+
}
|
|
16009
|
+
};
|
|
16010
|
+
var writeBuffer = [];
|
|
16011
|
+
var writeQueue = Promise.resolve();
|
|
16012
|
+
var logWriteLock = Promise.resolve();
|
|
16013
|
+
function drainBuffer() {
|
|
16014
|
+
const toWrite = writeBuffer.join("");
|
|
16015
|
+
writeBuffer = [];
|
|
16016
|
+
return toWrite;
|
|
16017
|
+
}
|
|
16018
|
+
process.on("exit", () => {
|
|
16019
|
+
if (writeBuffer.length > 0) {
|
|
16020
|
+
const toWrite = drainBuffer();
|
|
16021
|
+
try {
|
|
16022
|
+
const filePath = getLogFilePath();
|
|
16023
|
+
if (!ensurePrivateDirectorySync(path.dirname(filePath))) return;
|
|
16024
|
+
if (!canAppendCapturedLogFileOnExit(resolveLogDir(), filePath)) return;
|
|
16025
|
+
const descriptor = openSync2(
|
|
16026
|
+
filePath,
|
|
16027
|
+
constants3.O_WRONLY | constants3.O_APPEND | constants3.O_NOFOLLOW,
|
|
16028
|
+
PRIVATE_FILE_MODE
|
|
16029
|
+
);
|
|
16030
|
+
try {
|
|
16031
|
+
const payload = Buffer3.from(toWrite, "utf-8");
|
|
16032
|
+
let written = 0;
|
|
16033
|
+
while (written < payload.length) {
|
|
16034
|
+
const writeCount = writeSync(descriptor, payload, written, payload.length - written);
|
|
16035
|
+
if (writeCount === 0) return;
|
|
16036
|
+
written += writeCount;
|
|
16037
|
+
}
|
|
16038
|
+
fsyncSync(descriptor);
|
|
16039
|
+
} finally {
|
|
16040
|
+
closeSync2(descriptor);
|
|
16041
|
+
}
|
|
16042
|
+
void securePrivateFileSync(filePath);
|
|
16043
|
+
} catch {
|
|
16044
|
+
}
|
|
16045
|
+
}
|
|
15485
16046
|
});
|
|
15486
16047
|
|
|
15487
16048
|
// src/proxy/chunkStorage.ts
|
|
@@ -15498,15 +16059,15 @@ var StreamingChunksDataSchema = external_exports.object({
|
|
|
15498
16059
|
function getChunksDir() {
|
|
15499
16060
|
const chunksDirEnv = process.env["CHUNKS_DIR"];
|
|
15500
16061
|
if (chunksDirEnv !== void 0 && chunksDirEnv !== "") {
|
|
15501
|
-
return isAbsolute2(chunksDirEnv) ? chunksDirEnv :
|
|
16062
|
+
return isAbsolute2(chunksDirEnv) ? chunksDirEnv : join4(getDataDir(), chunksDirEnv);
|
|
15502
16063
|
}
|
|
15503
|
-
return
|
|
16064
|
+
return join4(getDataDir(), "chunks");
|
|
15504
16065
|
}
|
|
15505
16066
|
function getChunkFilePath(logId) {
|
|
15506
|
-
return
|
|
16067
|
+
return join4(getChunksDir(), `${logId}.json`);
|
|
15507
16068
|
}
|
|
15508
16069
|
function getTempFilePath(logId) {
|
|
15509
|
-
return
|
|
16070
|
+
return join4(getChunksDir(), `.${logId}.tmp`);
|
|
15510
16071
|
}
|
|
15511
16072
|
function writeChunks(logId, chunks, truncated) {
|
|
15512
16073
|
const dir = getChunksDir();
|
|
@@ -15532,7 +16093,7 @@ function writeChunks(logId, chunks, truncated) {
|
|
|
15532
16093
|
return targetPath;
|
|
15533
16094
|
}
|
|
15534
16095
|
try {
|
|
15535
|
-
|
|
16096
|
+
renameSync2(tempPath, targetPath);
|
|
15536
16097
|
} catch (err) {
|
|
15537
16098
|
logger.warn("[chunkStorage] Rename failed, falling back to copy+delete:", String(err));
|
|
15538
16099
|
try {
|
|
@@ -15548,14 +16109,14 @@ function writeChunks(logId, chunks, truncated) {
|
|
|
15548
16109
|
return targetPath;
|
|
15549
16110
|
}
|
|
15550
16111
|
|
|
15551
|
-
// src/
|
|
15552
|
-
var
|
|
15553
|
-
|
|
15554
|
-
|
|
15555
|
-
|
|
15556
|
-
|
|
15557
|
-
|
|
15558
|
-
|
|
16112
|
+
// src/lib/apiFormat.ts
|
|
16113
|
+
var API_FORMAT_PATH_ENTRIES = [
|
|
16114
|
+
["/v1/messages", "anthropic"],
|
|
16115
|
+
["/v1/chat/completions", "openai"],
|
|
16116
|
+
["/chat/completions", "openai"],
|
|
16117
|
+
["/v1/responses", "openai"],
|
|
16118
|
+
["/responses", "openai"]
|
|
16119
|
+
];
|
|
15559
16120
|
|
|
15560
16121
|
// src/proxy/formats/registry.ts
|
|
15561
16122
|
var FormatRegistryImpl = class {
|
|
@@ -15595,11 +16156,9 @@ var formatRegistry = new FormatRegistryImpl();
|
|
|
15595
16156
|
function formatForPath(path2) {
|
|
15596
16157
|
return formatRegistry.getByPath(path2) ?? null;
|
|
15597
16158
|
}
|
|
15598
|
-
|
|
15599
|
-
formatRegistry.registerPath(
|
|
15600
|
-
|
|
15601
|
-
formatRegistry.registerPath(PATH_V1_RESPONSES, "openai");
|
|
15602
|
-
formatRegistry.registerPath(PATH_RESPONSES, "openai");
|
|
16159
|
+
for (const [path2, format] of API_FORMAT_PATH_ENTRIES) {
|
|
16160
|
+
formatRegistry.registerPath(path2, format);
|
|
16161
|
+
}
|
|
15603
16162
|
|
|
15604
16163
|
// src/proxy/formats/anthropic/stream.ts
|
|
15605
16164
|
function parseInputJson(json2) {
|
|
@@ -16555,12 +17114,12 @@ registry2.register(alibabaProvider);
|
|
|
16555
17114
|
// src/proxy/sessionProcess.ts
|
|
16556
17115
|
import { existsSync as existsSync4 } from "node:fs";
|
|
16557
17116
|
import { fileURLToPath } from "node:url";
|
|
16558
|
-
import { join as
|
|
17117
|
+
import { join as join5 } from "node:path";
|
|
16559
17118
|
var IDLE_TIMEOUT_MS = Number(process.env["SESSION_PROCESS_IDLE_MS"]) || 5 * 60 * 1e3;
|
|
16560
17119
|
function resolveSessionWorkerPath() {
|
|
16561
17120
|
const workerDir = process.env["AGENT_INSPECTOR_WORKER_DIR"];
|
|
16562
17121
|
if (workerDir !== void 0 && workerDir.trim().length > 0) {
|
|
16563
|
-
const builtWorkerPath =
|
|
17122
|
+
const builtWorkerPath = join5(workerDir, "sessionWorkerEntry.js");
|
|
16564
17123
|
if (existsSync4(builtWorkerPath)) return builtWorkerPath;
|
|
16565
17124
|
}
|
|
16566
17125
|
return fileURLToPath(new URL("./sessionWorkerEntry.ts", import.meta.url));
|
|
@@ -16570,6 +17129,7 @@ function isSessionProcessAvailable() {
|
|
|
16570
17129
|
}
|
|
16571
17130
|
|
|
16572
17131
|
// src/proxy/logIndex.ts
|
|
17132
|
+
var INDEX_READ_CHUNK_BYTES = 64 * 1024;
|
|
16573
17133
|
var idGenerationChain = Promise.resolve();
|
|
16574
17134
|
|
|
16575
17135
|
// src/lib/publicBasePathContext.ts
|
|
@@ -16690,14 +17250,14 @@ function cleanupPathForRawStream(rawStream) {
|
|
|
16690
17250
|
}
|
|
16691
17251
|
function rawStreamByteLength(rawStream) {
|
|
16692
17252
|
if (typeof rawStream === "string") {
|
|
16693
|
-
return
|
|
17253
|
+
return Buffer4.byteLength(rawStream, "utf8");
|
|
16694
17254
|
}
|
|
16695
17255
|
switch (rawStream.type) {
|
|
16696
17256
|
case "memory":
|
|
16697
|
-
return
|
|
17257
|
+
return Buffer4.byteLength(rawStream.rawStream, "utf8");
|
|
16698
17258
|
case "file":
|
|
16699
17259
|
try {
|
|
16700
|
-
return
|
|
17260
|
+
return statSync(rawStream.path).size;
|
|
16701
17261
|
} catch {
|
|
16702
17262
|
return null;
|
|
16703
17263
|
}
|
|
@@ -16856,8 +17416,13 @@ function buildFinalizeLogResult(job) {
|
|
|
16856
17416
|
switch (job.type) {
|
|
16857
17417
|
case "non-streaming":
|
|
16858
17418
|
return finalizeNonStreaming(job, log);
|
|
16859
|
-
case "streaming":
|
|
16860
|
-
|
|
17419
|
+
case "streaming": {
|
|
17420
|
+
const result = finalizeStreaming(job, log);
|
|
17421
|
+
if (job.terminalError !== void 0 && job.terminalError !== null) {
|
|
17422
|
+
result.log.error = job.terminalError;
|
|
17423
|
+
}
|
|
17424
|
+
return result;
|
|
17425
|
+
}
|
|
16861
17426
|
case "stream-abort":
|
|
16862
17427
|
return finalizeStreamAbort(job, log);
|
|
16863
17428
|
default: {
|
|
@@ -16885,7 +17450,7 @@ var WORKER_COUNT = Math.max(1, Number(process.env["FINALIZER_WORKER_COUNT"]) ||
|
|
|
16885
17450
|
function resolveLogFinalizerWorkerUrl() {
|
|
16886
17451
|
const workerDir = process.env["AGENT_INSPECTOR_WORKER_DIR"];
|
|
16887
17452
|
if (workerDir !== void 0 && workerDir.trim().length > 0) {
|
|
16888
|
-
const builtWorkerPath =
|
|
17453
|
+
const builtWorkerPath = join6(workerDir, "logFinalizer.worker.js");
|
|
16889
17454
|
if (existsSync5(builtWorkerPath)) return pathToFileURL(builtWorkerPath);
|
|
16890
17455
|
}
|
|
16891
17456
|
return new URL("./logFinalizer.worker.ts", import.meta.url);
|