farming-code 2.2.29 → 2.2.32
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/README.md +25 -66
- package/README.zh_cn.md +15 -66
- package/THIRD_PARTY_NOTICES.md +7 -0
- package/backend/acp/{client-services.js → client-services.cjs} +132 -134
- package/backend/acp/packaged-claude-acp.cjs +37 -0
- package/backend/acp/packaged-codex-acp.cjs +37 -0
- package/backend/acp/patch-decisions.cjs +182 -0
- package/backend/acp/permission-security.cjs +131 -0
- package/backend/{acp-checkpoint-store.js → acp-checkpoint-store.cjs} +90 -59
- package/backend/{acp-runtime.js → acp-runtime.cjs} +1219 -1125
- package/backend/acp-session-state.cjs +622 -0
- package/backend/acp-transcript.cjs +525 -0
- package/backend/agent-env.cjs +257 -0
- package/backend/agent-extension-discovery.cjs +452 -0
- package/backend/agent-extension-inventory.cjs +116 -0
- package/backend/agent-json-stream.cjs +283 -0
- package/backend/agent-lifecycle-journal.cjs +185 -0
- package/backend/{agent-manager.js → agent-manager.cjs} +3116 -4275
- package/backend/agent-order-transaction.cjs +85 -0
- package/backend/agent-order.cjs +159 -0
- package/backend/agent-provider-session.cjs +98 -0
- package/backend/agent-runtime-binding.cjs +179 -0
- package/backend/agent-session-history.cjs +1022 -0
- package/backend/agent-session-inventory.cjs +291 -0
- package/backend/async-cache.cjs +104 -0
- package/backend/atomic-json-store.cjs +67 -0
- package/backend/auth.cjs +261 -0
- package/backend/authoritative-inventory-cache.cjs +383 -0
- package/backend/business-health.cjs +68 -0
- package/backend/chat-runtime.cjs +50 -0
- package/backend/claude-settings.cjs +132 -0
- package/backend/cli-agents.cjs +435 -0
- package/backend/codex-context-window.cjs +196 -0
- package/backend/codex-models.cjs +228 -0
- package/backend/codex-session-archive.cjs +82 -0
- package/backend/codex-session-history.cjs +590 -0
- package/backend/{codex-terminal-profile.js → codex-terminal-profile.cjs} +149 -155
- package/backend/codex-transcript-sanitizer.cjs +130 -0
- package/backend/codex-transcript.cjs +2107 -0
- package/backend/command-runner-child.cjs +105 -0
- package/backend/config-manager.cjs +1263 -0
- package/backend/control-api.cjs +439 -0
- package/backend/data/LICENSE.cua +21 -0
- package/backend/executable-discovery.cjs +204 -0
- package/backend/farming-agent-bootstrap.cjs +81 -0
- package/backend/farming-agent-bootstrap.zh_cn.md +6 -2
- package/backend/{farming-app-cli.js → farming-app-cli.cjs} +441 -493
- package/backend/farming-cli.cjs +414 -0
- package/backend/farming-net-pass.cjs +319 -0
- package/backend/farming-net-registry.cjs +123 -0
- package/backend/farming-net-server.cjs +309 -0
- package/backend/farming-session-store.cjs +651 -0
- package/backend/git-worktree-info.cjs +181 -0
- package/backend/haiku-token.cjs +828 -0
- package/backend/index-html.cjs +96 -0
- package/backend/input-parts.cjs +68 -0
- package/backend/input-routing.cjs +40 -0
- package/backend/{local-session-engine.js → local-session-engine.cjs} +276 -282
- package/backend/main-agent-skills.cjs +309 -0
- package/backend/main-page-session.cjs +132 -0
- package/backend/native-pty-controller-generation.cjs +139 -0
- package/backend/{native-pty-host-client.js → native-pty-host-client.cjs} +338 -346
- package/backend/native-pty-host-identity.cjs +125 -0
- package/backend/native-pty-host-path.cjs +68 -0
- package/backend/{native-pty-host.js → native-pty-host.cjs} +480 -569
- package/backend/native-session-engine.cjs +296 -0
- package/backend/network.cjs +57 -0
- package/backend/npm-update-helper.cjs +399 -0
- package/backend/packaged-node-pty.cjs +120 -0
- package/backend/preview-session-manager.cjs +89 -0
- package/backend/provider-adapters.cjs +492 -0
- package/backend/provider-home-configuration.cjs +211 -0
- package/backend/provider-session-id.cjs +79 -0
- package/backend/provider-session-service.cjs +333 -0
- package/backend/qr-share-tickets.cjs +119 -0
- package/backend/resource-broadcast-protocol.cjs +50 -0
- package/backend/review-diff-router.cjs +202 -0
- package/backend/review-diff-service.cjs +1267 -0
- package/backend/review-session-router.cjs +93 -0
- package/backend/review-session-service.cjs +470 -0
- package/backend/review-session-store.cjs +161 -0
- package/backend/review-state-router.cjs +132 -0
- package/backend/review-state-store.cjs +299 -0
- package/backend/run-history-store.cjs +97 -0
- package/backend/runtime-dependency-manager.cjs +893 -0
- package/backend/runtime-executable-invocation.cjs +37 -0
- package/backend/runtime-observation.cjs +96 -0
- package/backend/server-process-identity.cjs +70 -0
- package/backend/server.cjs +3356 -0
- package/backend/session-engine-bridge.cjs +144 -0
- package/backend/session-engine-router.cjs +105 -0
- package/backend/session-engine.cjs +64 -0
- package/backend/session-stream-protocol.cjs +181 -0
- package/backend/shell-busy-integration.cjs +442 -0
- package/backend/slash-command-discovery.cjs +423 -0
- package/backend/storage-layout.cjs +263 -0
- package/backend/system-monitor.cjs +96 -0
- package/backend/terminal-attach-checkpoint.cjs +73 -0
- package/backend/terminal-exit-quiescence.cjs +57 -0
- package/backend/{terminal-reducer-flow-control.js → terminal-reducer-flow-control.cjs} +45 -22
- package/backend/terminal-runtime-cleanup.cjs +99 -0
- package/backend/{terminal-screen-state.js → terminal-screen-state.cjs} +100 -108
- package/backend/{terminal-screen-worker-pool.js → terminal-screen-worker-pool.cjs} +89 -79
- package/backend/{terminal-screen-worker-thread.js → terminal-screen-worker-thread.cjs} +64 -65
- package/backend/terminal-screen-worker.cjs +352 -0
- package/backend/terminal-state-serialization.cjs +147 -0
- package/backend/{terminal-status.js → terminal-status.cjs} +137 -187
- package/backend/theme-manager.cjs +185 -0
- package/backend/update-service.cjs +675 -0
- package/backend/usage-forecast.cjs +95 -0
- package/backend/{usage-history-client.js → usage-history-client.cjs} +144 -94
- package/backend/usage-history-smoke.cjs +85 -0
- package/backend/usage-history-worker.cjs +60 -0
- package/backend/{usage-monitor.js → usage-monitor.cjs} +363 -390
- package/backend/workspace-directory.cjs +239 -0
- package/backend/workspace-discovery.cjs +271 -0
- package/backend/{workspace-file-router.js → workspace-file-router.cjs} +213 -282
- package/backend/{workspace-file-service.js → workspace-file-service.cjs} +1139 -1318
- package/backend/workspace-root-registry.cjs +192 -0
- package/bin/farming +1 -1
- package/config/farming.deploy.env.example +1 -1
- package/config/farming.install.env.example +1 -1
- package/dist/acp/codex-acp-1.1.4.mjs +405 -8
- package/dist/assets/App-BCkdpWB6.css +1 -0
- package/dist/assets/App-CRjKpaGp.js +697 -0
- package/dist/assets/CodeSelect-Ci8sKZPU.js +1 -0
- package/dist/assets/CodeSelect-T2eNzrOc.css +1 -0
- package/dist/assets/{FileEditorMarkdownPreview-Cs9cLv8a.js → FileEditorMarkdownPreview-V06QHlAg.js} +55 -55
- package/dist/assets/FileEditorPane-BX-Wjg9U.js +2 -0
- package/dist/assets/IconGlyphs-YhV7tqd4.js +1 -0
- package/dist/assets/ProjectFilesSection-BDT2_r0o.js +12 -0
- package/dist/assets/ReviewPage-BqAs5sG1.js +3 -0
- package/dist/assets/code-dark-B7eM_9G9.css +1 -0
- package/dist/assets/{cssMode-Bdg5RpcJ.js → cssMode-ADdAlxTO.js} +1 -1
- package/dist/assets/{editor.api2-D74ufkbr.js → editor.api2-BFLAr0YF.js} +162 -162
- package/dist/assets/file-icons-BpeqWkIB.js +1 -0
- package/dist/assets/{freemarker2-DfMDJfnE.js → freemarker2-C90q5jrp.js} +1 -1
- package/dist/assets/{handlebars-BEdPtzMT.js → handlebars-BwUQcEDq.js} +1 -1
- package/dist/assets/{html-B1fPb1QD.js → html-1s3uPKfh.js} +1 -1
- package/dist/assets/{htmlMode-CY2ZjHxH.js → htmlMode-xtKD99de.js} +1 -1
- package/dist/assets/{index-CQNaZc3l.js → index-C8MchCem.js} +3 -3
- package/dist/assets/{javascript-BV2OsWA0.js → javascript-Ph7ijyny.js} +1 -1
- package/dist/assets/{jsonMode-zd07aeuX.js → jsonMode-D-jGAnFH.js} +1 -1
- package/dist/assets/linkComputer-CbGyI_qx.js +1 -0
- package/dist/assets/{liquid-BParI24X.js → liquid-0IamE_cI.js} +1 -1
- package/dist/assets/{lspLanguageFeatures-BzredkoV.js → lspLanguageFeatures-BxnQunWF.js} +1 -1
- package/dist/assets/main-CLKXa6hf.css +1 -0
- package/dist/assets/{mdx-vGzUJN98.js → mdx-DdNmfivn.js} +1 -1
- package/dist/assets/{monaco.contribution-BmaeBQEc.js → monaco.contribution-B43jsUs1.js} +2 -2
- package/dist/assets/{python-CUwdLgsI.js → python-IAt4X5TS.js} +1 -1
- package/dist/assets/{razor-BScebUxU.js → razor-DRkFYW0S.js} +1 -1
- package/dist/assets/review-C8-oPKXk.css +1 -0
- package/dist/assets/{tsMode-DzUAibXK.js → tsMode-_d_4U2gf.js} +1 -1
- package/dist/assets/{typescript-D9EOeM7N.js → typescript-C7zcMq9l.js} +1 -1
- package/dist/assets/{workers-DAiomYZM.js → workers-D0nOyJzf.js} +1 -1
- package/dist/assets/workspace-editor-model-DND_Y-Bj.js +1 -0
- package/dist/assets/workspace-editor-monaco-BPWhgcIB.js +4 -0
- package/dist/assets/workspace-editor-monaco-N641qPjX.js +1 -0
- package/dist/assets/workspace-view-state-k1bTlJ_Z.js +13 -0
- package/dist/assets/{xml-wWl1dhkQ.js → xml-BR-HvxT8.js} +1 -1
- package/dist/assets/{yaml-Dc2WDaOZ.js → yaml-YtFQwh4q.js} +1 -1
- package/dist/index.html +2 -1
- package/extensions/browser/backend/agent-browser-runtime.cjs +1040 -0
- package/extensions/browser/backend/agent-capability.cjs +85 -0
- package/extensions/browser/backend/browser-mcp-server.cjs +655 -0
- package/extensions/browser/backend/browser-resource-manager.cjs +1486 -0
- package/extensions/browser/backend/browser-resource-store.cjs +228 -0
- package/extensions/browser/backend/browser-router.cjs +203 -0
- package/extensions/browser/backend/executable-discovery.cjs +248 -0
- package/extensions/browser/backend/farming-browser-client.cjs +116 -0
- package/extensions/browser/backend/index.cjs +32 -0
- package/extensions/browser/backend/managed-chromium-installer.cjs +833 -0
- package/extensions/browser/bin/farming-browser +16 -7
- package/extensions/computer/backend/agent-capability.cjs +72 -0
- package/extensions/computer/backend/computer-constants.cjs +59 -0
- package/extensions/computer/backend/computer-mcp-server.cjs +182 -0
- package/extensions/computer/backend/computer-resource-manager.cjs +1219 -0
- package/extensions/computer/backend/computer-resource-store.cjs +190 -0
- package/extensions/computer/backend/computer-router.cjs +257 -0
- package/extensions/computer/backend/cua-tools.json +3067 -0
- package/extensions/computer/backend/farming-computer-client.cjs +84 -0
- package/extensions/computer/backend/index.cjs +35 -0
- package/extensions/computer/backend/isolated-browser-provider.cjs +157 -0
- package/extensions/computer/bin/farming-computer +131 -0
- package/frontend/farming-net/app.js +255 -262
- package/frontend/ghostty-loader.js +24 -20
- package/frontend/reading-anchor.js +210 -193
- package/frontend/runtime-paths.js +24 -26
- package/frontend/session-bridge.js +90 -111
- package/frontend/session-modal-bridge.js +184 -302
- package/frontend/skin-bridge.js +20 -23
- package/frontend/skins/crt/app.js +7686 -7901
- package/frontend/skins/crt/effects.js +7 -6
- package/frontend/skins/crt/index.html +6 -6
- package/frontend/skins/crt/styles/markdown.css +4 -4
- package/frontend/terminal-bridge.js +174 -181
- package/frontend/terminal-replay.js +320 -345
- package/frontend/theme-loader.js +55 -71
- package/index.html +1 -0
- package/package.json +64 -37
- package/shared/backend-connection-status.js +38 -69
- package/shared/browser-protocol.js +235 -110
- package/shared/websocket-liveness.js +40 -0
- package/backend/acp/packaged-claude-acp.js +0 -13
- package/backend/acp/packaged-codex-acp.js +0 -13
- package/backend/acp/patch-decisions.js +0 -153
- package/backend/acp/permission-security.js +0 -108
- package/backend/acp-session-state.js +0 -644
- package/backend/acp-transcript.js +0 -512
- package/backend/agent-env.js +0 -250
- package/backend/agent-json-stream.js +0 -268
- package/backend/agent-lifecycle-journal.js +0 -133
- package/backend/agent-memory-report.js +0 -583
- package/backend/agent-order.js +0 -166
- package/backend/agent-provider-session.js +0 -76
- package/backend/agent-runtime-binding.js +0 -174
- package/backend/agent-session-history.js +0 -953
- package/backend/async-cache.js +0 -94
- package/backend/atomic-json-store.js +0 -37
- package/backend/auth.js +0 -251
- package/backend/bundle-update-helper.js +0 -113
- package/backend/chat-runtime.js +0 -28
- package/backend/claude-settings.js +0 -121
- package/backend/cli-agents.js +0 -486
- package/backend/codex-context-window.js +0 -189
- package/backend/codex-models.js +0 -226
- package/backend/codex-rollout-follower.js +0 -326
- package/backend/codex-session-archive.js +0 -65
- package/backend/codex-session-history.js +0 -647
- package/backend/codex-transcript-sanitizer.js +0 -115
- package/backend/codex-transcript.js +0 -2564
- package/backend/command-runner-child.js +0 -67
- package/backend/config-manager.js +0 -1133
- package/backend/control-api.js +0 -455
- package/backend/executable-discovery.js +0 -216
- package/backend/farming-agent-bootstrap.js +0 -49
- package/backend/farming-cli.js +0 -457
- package/backend/farming-net-pass.js +0 -285
- package/backend/farming-net-registry.js +0 -112
- package/backend/farming-net-server.js +0 -298
- package/backend/farming-session-store.js +0 -677
- package/backend/git-worktree-info.js +0 -181
- package/backend/haiku-token.js +0 -772
- package/backend/index-html.js +0 -62
- package/backend/input-parts.js +0 -54
- package/backend/input-routing.js +0 -24
- package/backend/json-cli-runtime.js +0 -275
- package/backend/main-agent-skills.js +0 -305
- package/backend/main-page-session.js +0 -122
- package/backend/native-pty-controller-generation.js +0 -106
- package/backend/native-pty-host-identity.js +0 -86
- package/backend/native-pty-host-path.js +0 -42
- package/backend/native-session-engine.js +0 -268
- package/backend/network.js +0 -23
- package/backend/npm-update-helper.js +0 -374
- package/backend/packaged-node-pty.js +0 -99
- package/backend/preview-session-manager.js +0 -68
- package/backend/provider-adapters.js +0 -399
- package/backend/provider-session-id.js +0 -47
- package/backend/provider-session-service.js +0 -345
- package/backend/qr-share-tickets.js +0 -100
- package/backend/review-diff-router.js +0 -180
- package/backend/review-diff-service.js +0 -1270
- package/backend/review-session-router.js +0 -74
- package/backend/review-session-service.js +0 -446
- package/backend/review-session-store.js +0 -151
- package/backend/review-state-router.js +0 -116
- package/backend/review-state-store.js +0 -286
- package/backend/run-history-store.js +0 -67
- package/backend/runtime-dependency-manager.js +0 -759
- package/backend/runtime-executable-invocation.js +0 -20
- package/backend/runtime-observation.js +0 -81
- package/backend/server-process-identity.js +0 -47
- package/backend/server.js +0 -3267
- package/backend/session-engine-bridge.js +0 -129
- package/backend/session-engine-router.js +0 -66
- package/backend/session-engine.js +0 -39
- package/backend/session-stream-protocol.js +0 -185
- package/backend/shell-busy-integration.js +0 -472
- package/backend/slash-command-discovery.js +0 -433
- package/backend/storage-layout.js +0 -190
- package/backend/system-monitor.js +0 -77
- package/backend/terminal-attach-checkpoint.js +0 -74
- package/backend/terminal-exit-quiescence.js +0 -39
- package/backend/terminal-runtime-cleanup.js +0 -80
- package/backend/terminal-screen-worker.js +0 -337
- package/backend/terminal-state-serialization.js +0 -127
- package/backend/theme-manager.js +0 -163
- package/backend/update-service.js +0 -1545
- package/backend/usage-forecast.js +0 -86
- package/backend/usage-history-scanner.ts +0 -2718
- package/backend/usage-history-smoke.js +0 -64
- package/backend/usage-history-worker.js +0 -34
- package/backend/workspace-directory.js +0 -232
- package/backend/workspace-discovery.js +0 -311
- package/backend/workspace-root-registry.js +0 -166
- package/dist/assets/App-BKNUILuL.css +0 -1
- package/dist/assets/App-Ex2oVVXO.js +0 -693
- package/dist/assets/FileEditorPane-CNtuGjQ3.js +0 -2
- package/dist/assets/IconGlyphs-BClgag6E.js +0 -1
- package/dist/assets/ProjectFilesSection-Cf2BEcAN.js +0 -12
- package/dist/assets/ReviewPage-BRuxFaH5.js +0 -3
- package/dist/assets/code-dark-BEZTQwYZ.css +0 -1
- package/dist/assets/file-icons-BOlcJ0ZF.js +0 -1
- package/dist/assets/main-DK9Sy7-c.css +0 -1
- package/dist/assets/review-BcnwQtJv.css +0 -1
- package/dist/assets/workspace-editor-model-CSGCl21x.js +0 -1
- package/dist/assets/workspace-editor-monaco-CJNwbpCy.js +0 -4
- package/dist/assets/workspace-editor-monaco-CO9w8YV0.js +0 -1
- package/dist/assets/workspace-view-state-BjKPYp0E.js +0 -7
- package/extensions/browser/backend/agent-browser-runtime.js +0 -1041
- package/extensions/browser/backend/agent-capability.js +0 -55
- package/extensions/browser/backend/browser-mcp-server.js +0 -621
- package/extensions/browser/backend/browser-resource-manager.js +0 -1309
- package/extensions/browser/backend/browser-resource-store.js +0 -190
- package/extensions/browser/backend/browser-router.js +0 -133
- package/extensions/browser/backend/executable-discovery.js +0 -224
- package/extensions/browser/backend/farming-browser-client.js +0 -83
- package/extensions/browser/backend/index.js +0 -7
- package/extensions/browser/frontend/BrowserSidebarPortals.tsx +0 -360
- package/extensions/browser/frontend/BrowserViewer.tsx +0 -500
- package/extensions/browser/frontend/browser-resource-state.ts +0 -60
- package/extensions/browser/frontend/browser.css +0 -567
- package/extensions/browser/frontend/types.ts +0 -31
- package/extensions/browser/frontend/useBrowserResources.ts +0 -158
- package/frontend/vendor/ghostty-web/index.d.ts +0 -1842
- package/shared/backend-connection-status.d.ts +0 -37
- package/shared/browser-protocol.d.ts +0 -5
- /package/dist/assets/{api-w2x5QfxB.js → api-ByCV9MEr.js} +0 -0
- /package/dist/assets/{core-vPkV8P_m.js → core-Czwdx12k.js} +0 -0
- /package/dist/assets/{fsharp-DNZNZyEE.js → fsharp-BjPpkoJe.js} +0 -0
- /package/dist/assets/{go-_kPJjNc_.js → go-BkIDmSUP.js} +0 -0
- /package/dist/assets/{graphql-4HCNVt5g.js → graphql-CCJTpqi1.js} +0 -0
- /package/dist/assets/{hcl-C87ymY0o.js → hcl-s4z8lUFg.js} +0 -0
- /package/dist/assets/{ini-BYrrGNTc.js → ini-CyUW1I7Z.js} +0 -0
- /package/dist/assets/{java-B211rJbk.js → java-CFCcGRiM.js} +0 -0
- /package/dist/assets/{julia-DVPsRtBm.js → julia-DQyH_EYb.js} +0 -0
- /package/dist/assets/{kotlin-BYyNerjp.js → kotlin-B8hA5O51.js} +0 -0
- /package/dist/assets/{less-EC9UblGE.js → less-DaVdaas0.js} +0 -0
- /package/dist/assets/{lexon-B1yuUdqW.js → lexon-DLBhPd3y.js} +0 -0
- /package/dist/assets/{lua-Bo6GFzxT.js → lua-gB1c_cif.js} +0 -0
- /package/dist/assets/{m3-C-Y9cBVI.js → m3-C2T3z3gB.js} +0 -0
- /package/dist/assets/{markdown-BHu-wLbe.js → markdown-CKq-Euj1.js} +0 -0
- /package/dist/assets/{mips-Dkds26rX.js → mips-Bcs5qIDX.js} +0 -0
- /package/dist/assets/{msdax-PU4g-8_g.js → msdax-CBP48FHF.js} +0 -0
- /package/dist/assets/{mysql-fPpuGpS7.js → mysql-c7tiPcFj.js} +0 -0
- /package/dist/assets/{objective-c-Wy1e5JUf.js → objective-c-D4BZkeEV.js} +0 -0
- /package/dist/assets/{pascal-BIXwvrqU.js → pascal-CJDZg0MN.js} +0 -0
- /package/dist/assets/{pascaligo-DwR0AtL_.js → pascaligo-Bygi8Ynl.js} +0 -0
- /package/dist/assets/{perl-CGHAl8my.js → perl-aS8bkf7E.js} +0 -0
- /package/dist/assets/{pgsql-B91M73E2.js → pgsql-CzNAYFYl.js} +0 -0
- /package/dist/assets/{php-C70ttrCx.js → php-DOtoEFTT.js} +0 -0
- /package/dist/assets/{pla-BNrXaRh0.js → pla-DugRnao1.js} +0 -0
- /package/dist/assets/{postiats-Dv2IAZR9.js → postiats-DsXwusKh.js} +0 -0
- /package/dist/assets/{powerquery-CkY5Wq7J.js → powerquery-DL3o72oD.js} +0 -0
- /package/dist/assets/{powershell-uGIYLU3C.js → powershell-C1qHekys.js} +0 -0
- /package/dist/assets/{protobuf-CavfmJu-.js → protobuf-DHgsc-cH.js} +0 -0
- /package/dist/assets/{pug-Drqnyitx.js → pug-FZXlE_Iu.js} +0 -0
- /package/dist/assets/{qrcode-7uGsTEmi.js → qrcode-DJDTdjL7.js} +0 -0
- /package/dist/assets/{qsharp-C7yF-Dti.js → qsharp-bLyhI3DT.js} +0 -0
- /package/dist/assets/{r-HXLGP0_-.js → r-DjFGXbAa.js} +0 -0
- /package/dist/assets/{redis-C4y6mf2p.js → redis-DSoZ_V6u.js} +0 -0
- /package/dist/assets/{redshift-DdQrFPrv.js → redshift-CzkdCsrg.js} +0 -0
- /package/dist/assets/{restructuredtext-CBrf2PNj.js → restructuredtext-B_XPrGCQ.js} +0 -0
- /package/dist/assets/{ruby-CVtMoX2B.js → ruby-Cry2RneJ.js} +0 -0
- /package/dist/assets/{rust-Ckq4sbMP.js → rust-CWzdbFq1.js} +0 -0
- /package/dist/assets/{sb-er66OpE3.js → sb-DmofU59h.js} +0 -0
- /package/dist/assets/{scala-BdWZz-hH.js → scala-BUC2l-vN.js} +0 -0
- /package/dist/assets/{scheme-kTV_s2kP.js → scheme-CNIB_72f.js} +0 -0
- /package/dist/assets/{scss-Bymy2VJQ.js → scss-DcL4-NbX.js} +0 -0
- /package/dist/assets/{shell-bwEP1LQ1.js → shell-CgAGvSSA.js} +0 -0
- /package/dist/assets/{solidity-DCddeBgL.js → solidity-DSkt6O_P.js} +0 -0
- /package/dist/assets/{sophia-BMN3AQig.js → sophia--5ytcjDN.js} +0 -0
- /package/dist/assets/{sparql-CSXOLjzi.js → sparql-C1Srr7cD.js} +0 -0
- /package/dist/assets/{sql-COg8ewmK.js → sql-2k_O5fj7.js} +0 -0
- /package/dist/assets/{st-CIaZtBS_.js → st-DCCCPqfz.js} +0 -0
- /package/dist/assets/{swift-DXiOhUHu.js → swift-Dd8mAfOt.js} +0 -0
- /package/dist/assets/{systemverilog-BTDE6Dr2.js → systemverilog-B0-aZYXu.js} +0 -0
- /package/dist/assets/{tcl-B0zy9NvV.js → tcl-CZAZwPVX.js} +0 -0
- /package/dist/assets/{twig-D594l4Z1.js → twig-D-Ag0tdS.js} +0 -0
- /package/dist/assets/{typespec-XKVjaPqo.js → typespec-B7kTFp0Z.js} +0 -0
- /package/dist/assets/{useWorkspaceMenuKeyboard-Bpy_s69Z.js → useWorkspaceMenuKeyboard-uYZpDxhU.js} +0 -0
- /package/dist/assets/{vb-B2wYoKRV.js → vb-20w1JPum.js} +0 -0
- /package/dist/assets/{wgsl-D0Yf2LbK.js → wgsl-CLJfqFt0.js} +0 -0
- /package/dist/assets/{workspace-working-copy-C3FSR3N6.js → workspace-working-copy-Cfz07cOd.js} +0 -0
|
@@ -0,0 +1,1022 @@
|
|
|
1
|
+
// Generated by scripts/build-backend-runtime.ts. Do not edit.
|
|
2
|
+
"use strict";
|
|
3
|
+
var __create = Object.create;
|
|
4
|
+
var __defProp = Object.defineProperty;
|
|
5
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
6
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
7
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
8
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
9
|
+
var __export = (target, all) => {
|
|
10
|
+
for (var name in all)
|
|
11
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
12
|
+
};
|
|
13
|
+
var __copyProps = (to, from, except, desc) => {
|
|
14
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
15
|
+
for (let key of __getOwnPropNames(from))
|
|
16
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
17
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
18
|
+
}
|
|
19
|
+
return to;
|
|
20
|
+
};
|
|
21
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
22
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
23
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
24
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
25
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
26
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
27
|
+
mod
|
|
28
|
+
));
|
|
29
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
30
|
+
var agent_session_history_exports = {};
|
|
31
|
+
__export(agent_session_history_exports, {
|
|
32
|
+
buildAgentSessionResumeCommand: () => buildAgentSessionResumeCommand,
|
|
33
|
+
compareAgentSessions: () => compareAgentSessions,
|
|
34
|
+
findAgentSession: () => findAgentSession,
|
|
35
|
+
hasTemporaryWorkspaceReference: () => import_codex_session_history.hasTemporaryWorkspaceReference,
|
|
36
|
+
isAgentManagedWorktree: () => isAgentManagedWorktree,
|
|
37
|
+
isDefaultClaudeSessionTitle: () => isDefaultClaudeSessionTitle,
|
|
38
|
+
isSafeSessionId: () => isSafeSessionId,
|
|
39
|
+
isTemporaryWorkspace: () => import_codex_session_history.isTemporaryWorkspace,
|
|
40
|
+
isVisibleAgentSession: () => isVisibleAgentSession,
|
|
41
|
+
listAgentSessions: () => listAgentSessions,
|
|
42
|
+
listClaudeSessions: () => listClaudeSessions,
|
|
43
|
+
listOpenCodeSessions: () => listOpenCodeSessions,
|
|
44
|
+
listQoderSessions: () => listQoderSessions,
|
|
45
|
+
listQwenSessions: () => listQwenSessions,
|
|
46
|
+
normalizeProvider: () => normalizeProvider,
|
|
47
|
+
paginateAgentSessions: () => paginateAgentSessions,
|
|
48
|
+
resolveCodexResumeModelProvider: () => resolveCodexResumeModelProvider,
|
|
49
|
+
searchAgentSessions: () => searchAgentSessions
|
|
50
|
+
});
|
|
51
|
+
module.exports = __toCommonJS(agent_session_history_exports);
|
|
52
|
+
var import_child_process = require("child_process");
|
|
53
|
+
var fs = __toESM(require("fs"));
|
|
54
|
+
var fsp = __toESM(require("fs/promises"));
|
|
55
|
+
var os = __toESM(require("os"));
|
|
56
|
+
var path = __toESM(require("path"));
|
|
57
|
+
var readline = __toESM(require("readline"));
|
|
58
|
+
var import_codex_session_history = require("./codex-session-history.cjs");
|
|
59
|
+
var import_provider_session_id = require("./provider-session-id.cjs");
|
|
60
|
+
const DEFAULT_LIMIT = 60;
|
|
61
|
+
const DEFAULT_SCAN_LIMIT = 500;
|
|
62
|
+
const MAX_AGENT_SESSION_HISTORY_LIMIT = 5e3;
|
|
63
|
+
const MAX_AGENT_SESSION_SCAN_LIMIT = 5e3;
|
|
64
|
+
const CLAUDE_HISTORY_TAIL_BYTES = 2 * 1024 * 1024;
|
|
65
|
+
const QODER_HISTORY_TAIL_BYTES = 2 * 1024 * 1024;
|
|
66
|
+
const QWEN_HISTORY_TAIL_BYTES = 2 * 1024 * 1024;
|
|
67
|
+
const MAX_RECENT_FILE_SCAN_DIRECTORIES = 2e3;
|
|
68
|
+
const PROVIDERS = /* @__PURE__ */ new Set(["codex", "claude", "opencode", "qoder", "qwen"]);
|
|
69
|
+
function isHistoryRecord(value) {
|
|
70
|
+
return typeof value === "object" && value !== null;
|
|
71
|
+
}
|
|
72
|
+
function isAgentProvider(value) {
|
|
73
|
+
return PROVIDERS.has(value);
|
|
74
|
+
}
|
|
75
|
+
function quoteCommandArg(value) {
|
|
76
|
+
return `'${String(value).replace(/'/g, `'\\''`)}'`;
|
|
77
|
+
}
|
|
78
|
+
function tomlStringAssignment(line, key) {
|
|
79
|
+
const match = String(line || "").match(new RegExp(`^\\s*${key}\\s*=\\s*("(?:[^"\\\\]|\\\\.)*"|'[^']*')\\s*(?:#.*)?$`));
|
|
80
|
+
if (!match) return "";
|
|
81
|
+
const literal = match[1];
|
|
82
|
+
if (literal.startsWith('"')) {
|
|
83
|
+
try {
|
|
84
|
+
return JSON.parse(literal).trim();
|
|
85
|
+
} catch {
|
|
86
|
+
return "";
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
return literal.slice(1, -1).trim();
|
|
90
|
+
}
|
|
91
|
+
function codexProfileNameForSection(section) {
|
|
92
|
+
const match = String(section || "").trim().match(/^profiles\.(?:"([^"]+)"|'([^']+)'|([A-Za-z0-9_-]+))$/);
|
|
93
|
+
return match ? match[1] || match[2] || match[3] || "" : "";
|
|
94
|
+
}
|
|
95
|
+
function resolveCodexResumeModelProvider(codexHome) {
|
|
96
|
+
const home = normalizePathValue(codexHome) || normalizePathValue(process.env.CODEX_HOME) || path.join(os.homedir(), ".codex");
|
|
97
|
+
let config = "";
|
|
98
|
+
try {
|
|
99
|
+
config = fs.readFileSync(path.join(home, "config.toml"), "utf8");
|
|
100
|
+
} catch {
|
|
101
|
+
return "openai";
|
|
102
|
+
}
|
|
103
|
+
let section = "";
|
|
104
|
+
let activeProfile = "";
|
|
105
|
+
let topLevelProvider = "";
|
|
106
|
+
const profileProviders = /* @__PURE__ */ new Map();
|
|
107
|
+
for (const line of config.split(/\r?\n/)) {
|
|
108
|
+
const sectionMatch = line.match(/^\s*\[([^\]]+)]\s*(?:#.*)?$/);
|
|
109
|
+
if (sectionMatch) {
|
|
110
|
+
section = sectionMatch[1].trim();
|
|
111
|
+
continue;
|
|
112
|
+
}
|
|
113
|
+
if (!section) {
|
|
114
|
+
activeProfile = tomlStringAssignment(line, "profile") || activeProfile;
|
|
115
|
+
topLevelProvider = tomlStringAssignment(line, "model_provider") || topLevelProvider;
|
|
116
|
+
continue;
|
|
117
|
+
}
|
|
118
|
+
const profileName = codexProfileNameForSection(section);
|
|
119
|
+
if (profileName) {
|
|
120
|
+
const provider = tomlStringAssignment(line, "model_provider");
|
|
121
|
+
if (provider) profileProviders.set(profileName, provider);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
return activeProfile && profileProviders.get(activeProfile) || topLevelProvider || "openai";
|
|
125
|
+
}
|
|
126
|
+
function normalizePathValue(value) {
|
|
127
|
+
if (typeof value !== "string") return "";
|
|
128
|
+
const trimmed = value.trim();
|
|
129
|
+
if (!trimmed || trimmed === path.sep) return trimmed;
|
|
130
|
+
return trimmed.replace(/[\\/]+$/, "");
|
|
131
|
+
}
|
|
132
|
+
function timestampMs(value) {
|
|
133
|
+
const parsed = Date.parse(String(value || ""));
|
|
134
|
+
return Number.isFinite(parsed) ? parsed : 0;
|
|
135
|
+
}
|
|
136
|
+
function agentSessionIdentity(session) {
|
|
137
|
+
return [
|
|
138
|
+
String(session?.provider || ""),
|
|
139
|
+
String(session?.providerHomeId || "default"),
|
|
140
|
+
String(session?.id || "")
|
|
141
|
+
].join("\0");
|
|
142
|
+
}
|
|
143
|
+
function compareAgentSessions(a, b) {
|
|
144
|
+
const timeDelta = timestampMs(b?.updatedAt || b?.createdAt) - timestampMs(a?.updatedAt || a?.createdAt);
|
|
145
|
+
return timeDelta || agentSessionIdentity(a).localeCompare(agentSessionIdentity(b));
|
|
146
|
+
}
|
|
147
|
+
function dedupeAgentSessions(sessions) {
|
|
148
|
+
const sessionsByIdentity = /* @__PURE__ */ new Map();
|
|
149
|
+
for (const session of sessions) {
|
|
150
|
+
const identity = agentSessionIdentity(session);
|
|
151
|
+
const current = sessionsByIdentity.get(identity);
|
|
152
|
+
if (!current || timestampMs(session?.updatedAt || session?.createdAt) > timestampMs(current?.updatedAt || current?.createdAt)) {
|
|
153
|
+
sessionsByIdentity.set(identity, session);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
return Array.from(sessionsByIdentity.values());
|
|
157
|
+
}
|
|
158
|
+
function encodeAgentSessionCursor(session) {
|
|
159
|
+
if (!session?.provider || !session?.id) return "";
|
|
160
|
+
return Buffer.from(JSON.stringify({
|
|
161
|
+
version: 1,
|
|
162
|
+
provider: String(session.provider),
|
|
163
|
+
providerHomeId: String(session.providerHomeId || "default"),
|
|
164
|
+
id: String(session.id),
|
|
165
|
+
updatedAt: String(session.updatedAt || session.createdAt || "")
|
|
166
|
+
})).toString("base64url");
|
|
167
|
+
}
|
|
168
|
+
function decodeAgentSessionCursor(value) {
|
|
169
|
+
try {
|
|
170
|
+
const parsed = JSON.parse(Buffer.from(String(value || ""), "base64url").toString("utf8"));
|
|
171
|
+
if (parsed?.version !== 1 || !parsed.provider || !parsed.id) return null;
|
|
172
|
+
return {
|
|
173
|
+
provider: String(parsed.provider),
|
|
174
|
+
providerHomeId: String(parsed.providerHomeId || "default"),
|
|
175
|
+
id: String(parsed.id),
|
|
176
|
+
updatedAt: String(parsed.updatedAt || "")
|
|
177
|
+
};
|
|
178
|
+
} catch {
|
|
179
|
+
return null;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
function paginateAgentSessions(sessions, options = {}) {
|
|
183
|
+
const limit = typeof options.limit === "number" && Number.isFinite(options.limit) ? Math.max(1, Math.min(MAX_AGENT_SESSION_HISTORY_LIMIT, Math.floor(options.limit))) : DEFAULT_LIMIT;
|
|
184
|
+
const cursorValue = String(options.cursor || "").trim();
|
|
185
|
+
let start = 0;
|
|
186
|
+
if (cursorValue) {
|
|
187
|
+
const cursor = decodeAgentSessionCursor(cursorValue);
|
|
188
|
+
if (!cursor) return { sessions: [], nextCursor: "", hasMore: false, invalidCursor: true };
|
|
189
|
+
const exactIndex = sessions.findIndex((session) => agentSessionIdentity(session) === agentSessionIdentity(cursor) && String(session.updatedAt || session.createdAt || "") === cursor.updatedAt);
|
|
190
|
+
if (exactIndex >= 0) {
|
|
191
|
+
start = exactIndex + 1;
|
|
192
|
+
} else {
|
|
193
|
+
const nextIndex = sessions.findIndex((session) => compareAgentSessions(session, cursor) > 0);
|
|
194
|
+
start = nextIndex >= 0 ? nextIndex : sessions.length;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
const page = sessions.slice(start, start + limit);
|
|
198
|
+
const hasMore = start + page.length < sessions.length;
|
|
199
|
+
return {
|
|
200
|
+
sessions: page,
|
|
201
|
+
nextCursor: hasMore && page.length > 0 ? encodeAgentSessionCursor(page[page.length - 1]) : "",
|
|
202
|
+
hasMore,
|
|
203
|
+
invalidCursor: false
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
function searchAgentSessions(sessions, query, options = {}) {
|
|
207
|
+
const normalizedQuery = String(query || "").trim().toLowerCase();
|
|
208
|
+
const limit = typeof options.limit === "number" && Number.isFinite(options.limit) ? Math.max(1, Math.min(MAX_AGENT_SESSION_HISTORY_LIMIT, Math.floor(options.limit))) : DEFAULT_LIMIT;
|
|
209
|
+
if (!normalizedQuery) {
|
|
210
|
+
return { sessions: [], total: 0, query: "", scope: "id-title-project" };
|
|
211
|
+
}
|
|
212
|
+
const projectNames = options.projectNames && typeof options.projectNames === "object" ? options.projectNames : {};
|
|
213
|
+
const matches = sessions.filter((session) => {
|
|
214
|
+
const projectPaths = [session?.workspace, session?.cwd];
|
|
215
|
+
return [
|
|
216
|
+
session?.id,
|
|
217
|
+
session?.title,
|
|
218
|
+
...projectPaths,
|
|
219
|
+
...projectPaths.map((workspace) => projectNames[String(workspace || "")])
|
|
220
|
+
].some((value) => String(value || "").toLowerCase().includes(normalizedQuery));
|
|
221
|
+
});
|
|
222
|
+
return {
|
|
223
|
+
sessions: matches.slice(0, limit),
|
|
224
|
+
total: matches.length,
|
|
225
|
+
query: normalizedQuery,
|
|
226
|
+
scope: "id-title-project"
|
|
227
|
+
};
|
|
228
|
+
}
|
|
229
|
+
function isAgentManagedWorktree(workspace) {
|
|
230
|
+
const value = normalizePathValue(workspace);
|
|
231
|
+
return value.includes(`${path.sep}.codex${path.sep}worktrees${path.sep}`) || value.includes(`${path.sep}.claude${path.sep}worktrees${path.sep}`);
|
|
232
|
+
}
|
|
233
|
+
function isDefaultClaudeSessionTitle(title) {
|
|
234
|
+
return String(title || "").trim().toLowerCase() === "claude session";
|
|
235
|
+
}
|
|
236
|
+
function firstTrimmedString(...values) {
|
|
237
|
+
for (const value of values) {
|
|
238
|
+
if (typeof value !== "string") continue;
|
|
239
|
+
const trimmed = value.trim();
|
|
240
|
+
if (trimmed) return trimmed;
|
|
241
|
+
}
|
|
242
|
+
return "";
|
|
243
|
+
}
|
|
244
|
+
function extractClaudeModel(event) {
|
|
245
|
+
return firstTrimmedString(
|
|
246
|
+
event?.model,
|
|
247
|
+
event?.message?.model,
|
|
248
|
+
event?.metadata?.model,
|
|
249
|
+
event?.message?.metadata?.model,
|
|
250
|
+
event?.request?.model,
|
|
251
|
+
event?.options?.model
|
|
252
|
+
);
|
|
253
|
+
}
|
|
254
|
+
function extractClaudeEffort(event) {
|
|
255
|
+
return firstTrimmedString(
|
|
256
|
+
event?.effort,
|
|
257
|
+
event?.message?.effort,
|
|
258
|
+
event?.metadata?.effort,
|
|
259
|
+
event?.message?.metadata?.effort,
|
|
260
|
+
event?.request?.effort,
|
|
261
|
+
event?.options?.effort
|
|
262
|
+
);
|
|
263
|
+
}
|
|
264
|
+
function extractQoderModel(event) {
|
|
265
|
+
return firstTrimmedString(
|
|
266
|
+
event?.model,
|
|
267
|
+
event?.message?.model,
|
|
268
|
+
event?.metadata?.model,
|
|
269
|
+
event?.message?.metadata?.model
|
|
270
|
+
);
|
|
271
|
+
}
|
|
272
|
+
function extractQoderEffort(event) {
|
|
273
|
+
return firstTrimmedString(
|
|
274
|
+
event?.reasoningEffort,
|
|
275
|
+
event?.reasoning_effort,
|
|
276
|
+
event?.effort,
|
|
277
|
+
event?.metadata?.reasoningEffort,
|
|
278
|
+
event?.metadata?.reasoning_effort,
|
|
279
|
+
event?.message?.metadata?.reasoningEffort,
|
|
280
|
+
event?.message?.metadata?.reasoning_effort
|
|
281
|
+
);
|
|
282
|
+
}
|
|
283
|
+
function isoTimestamp(value) {
|
|
284
|
+
if (typeof value === "string") {
|
|
285
|
+
const parsed = Date.parse(value);
|
|
286
|
+
return Number.isFinite(parsed) ? new Date(parsed).toISOString() : "";
|
|
287
|
+
}
|
|
288
|
+
if (typeof value === "number" && Number.isFinite(value) && value > 0) {
|
|
289
|
+
try {
|
|
290
|
+
const date = new Date(value);
|
|
291
|
+
return Number.isFinite(date.getTime()) ? date.toISOString() : "";
|
|
292
|
+
} catch {
|
|
293
|
+
return "";
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
return "";
|
|
297
|
+
}
|
|
298
|
+
function qoderTextFromMessage(message) {
|
|
299
|
+
if (typeof message === "string") return message.trim();
|
|
300
|
+
if (!isHistoryRecord(message)) return "";
|
|
301
|
+
const content = message.content;
|
|
302
|
+
if (typeof content === "string") return content.trim();
|
|
303
|
+
if (!Array.isArray(content)) return "";
|
|
304
|
+
return content.map((part) => {
|
|
305
|
+
if (typeof part === "string") return part;
|
|
306
|
+
if (!isHistoryRecord(part)) return "";
|
|
307
|
+
if (typeof part.text === "string") return part.text;
|
|
308
|
+
if (typeof part.content === "string") return part.content;
|
|
309
|
+
return "";
|
|
310
|
+
}).join("\n").trim();
|
|
311
|
+
}
|
|
312
|
+
function qwenTextFromMessage(message) {
|
|
313
|
+
if (typeof message === "string") return message.trim();
|
|
314
|
+
if (!isHistoryRecord(message)) return "";
|
|
315
|
+
const parts = Array.isArray(message.parts) ? message.parts : Array.isArray(message.content) ? message.content : [];
|
|
316
|
+
return parts.map((part) => {
|
|
317
|
+
if (typeof part === "string") return part;
|
|
318
|
+
if (!isHistoryRecord(part)) return "";
|
|
319
|
+
return typeof part.text === "string" ? part.text : "";
|
|
320
|
+
}).join("\n").trim();
|
|
321
|
+
}
|
|
322
|
+
function isVisibleAgentSession(session) {
|
|
323
|
+
const provider = String(session?.provider || "").trim().toLowerCase();
|
|
324
|
+
if (provider === "claude") {
|
|
325
|
+
if (isDefaultClaudeSessionTitle(session?.title)) return false;
|
|
326
|
+
if (isAgentManagedWorktree(session?.cwd) || isAgentManagedWorktree(session?.workspace)) return false;
|
|
327
|
+
}
|
|
328
|
+
return !(0, import_codex_session_history.isTemporaryWorkspace)(session?.cwd) && !(0, import_codex_session_history.isTemporaryWorkspace)(session?.workspace) && !(0, import_codex_session_history.hasTemporaryWorkspaceReference)(session?.title);
|
|
329
|
+
}
|
|
330
|
+
function activeScheduleFromMetadata(value, sessionId = "") {
|
|
331
|
+
if (!value || typeof value !== "object") return null;
|
|
332
|
+
const rrule = typeof value.rrule === "string" ? value.rrule.trim() : "";
|
|
333
|
+
if (!rrule) return null;
|
|
334
|
+
const targetThreadId = typeof value.target_thread_id === "string" ? value.target_thread_id.trim() : typeof value.targetThreadId === "string" ? value.targetThreadId.trim() : "";
|
|
335
|
+
if (targetThreadId && sessionId && targetThreadId !== sessionId) return null;
|
|
336
|
+
const rawStatus = typeof value.status === "string" ? value.status.trim().toUpperCase() : "";
|
|
337
|
+
const enabled = value.enabled !== false && value.active !== false;
|
|
338
|
+
if (rawStatus && !["ACTIVE", "ENABLED"].includes(rawStatus)) return null;
|
|
339
|
+
if (!enabled) return null;
|
|
340
|
+
return {
|
|
341
|
+
id: typeof value.id === "string" ? value.id.trim() : "",
|
|
342
|
+
kind: typeof value.kind === "string" ? value.kind.trim() : "",
|
|
343
|
+
name: typeof value.name === "string" ? value.name.trim() : "",
|
|
344
|
+
status: rawStatus || "ACTIVE",
|
|
345
|
+
rrule,
|
|
346
|
+
label: (0, import_codex_session_history.formatAutomationRRuleLabel)(rrule)
|
|
347
|
+
};
|
|
348
|
+
}
|
|
349
|
+
function scheduleFromClaudeEvent(event, sessionId) {
|
|
350
|
+
const candidates = [
|
|
351
|
+
event?.automation,
|
|
352
|
+
event?.schedule,
|
|
353
|
+
event?.metadata?.automation,
|
|
354
|
+
event?.metadata?.schedule,
|
|
355
|
+
event?.message?.metadata?.automation,
|
|
356
|
+
event?.message?.metadata?.schedule
|
|
357
|
+
];
|
|
358
|
+
for (const candidate of candidates) {
|
|
359
|
+
const schedule = activeScheduleFromMetadata(candidate, sessionId);
|
|
360
|
+
if (schedule) return schedule;
|
|
361
|
+
}
|
|
362
|
+
return null;
|
|
363
|
+
}
|
|
364
|
+
async function collectRecentFiles(root, extension, limit, acceptFile = () => true, descendDirectory = () => true) {
|
|
365
|
+
const directories = [root];
|
|
366
|
+
let files = [];
|
|
367
|
+
let visitedDirectories = 0;
|
|
368
|
+
while (directories.length > 0 && visitedDirectories < MAX_RECENT_FILE_SCAN_DIRECTORIES) {
|
|
369
|
+
const directory = directories.pop();
|
|
370
|
+
if (!directory) continue;
|
|
371
|
+
let entries = [];
|
|
372
|
+
try {
|
|
373
|
+
entries = await fsp.readdir(directory, { withFileTypes: true });
|
|
374
|
+
} catch {
|
|
375
|
+
continue;
|
|
376
|
+
}
|
|
377
|
+
visitedDirectories += 1;
|
|
378
|
+
entries.sort((a, b) => {
|
|
379
|
+
if (a.isDirectory() !== b.isDirectory()) return a.isDirectory() ? -1 : 1;
|
|
380
|
+
return a.name.localeCompare(b.name);
|
|
381
|
+
});
|
|
382
|
+
for (const entry of entries) {
|
|
383
|
+
const fullPath = path.join(directory, entry.name);
|
|
384
|
+
if (entry.isDirectory()) {
|
|
385
|
+
if (descendDirectory(fullPath)) directories.push(fullPath);
|
|
386
|
+
} else if (entry.isFile() && entry.name.endsWith(extension) && acceptFile(fullPath)) {
|
|
387
|
+
let mtimeMs = 0;
|
|
388
|
+
try {
|
|
389
|
+
mtimeMs = (await fsp.stat(fullPath)).mtimeMs;
|
|
390
|
+
} catch {
|
|
391
|
+
mtimeMs = 0;
|
|
392
|
+
}
|
|
393
|
+
files.push({ filePath: fullPath, mtimeMs });
|
|
394
|
+
if (files.length > limit * 2) {
|
|
395
|
+
files = files.sort((a, b) => b.mtimeMs - a.mtimeMs).slice(0, limit);
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
return files.sort((a, b) => b.mtimeMs - a.mtimeMs).slice(0, limit);
|
|
401
|
+
}
|
|
402
|
+
async function readTextTail(filePath, maxBytes) {
|
|
403
|
+
let handle = null;
|
|
404
|
+
try {
|
|
405
|
+
const stat = await fsp.stat(filePath);
|
|
406
|
+
const start = Math.max(0, stat.size - maxBytes);
|
|
407
|
+
const length = stat.size - start;
|
|
408
|
+
const buffer = Buffer.alloc(length);
|
|
409
|
+
handle = await fsp.open(filePath, "r");
|
|
410
|
+
await handle.read(buffer, 0, length, start);
|
|
411
|
+
const text = buffer.toString("utf8");
|
|
412
|
+
return start > 0 ? text.replace(/^[^\n]*(\n|$)/, "") : text;
|
|
413
|
+
} catch {
|
|
414
|
+
return "";
|
|
415
|
+
} finally {
|
|
416
|
+
if (handle) {
|
|
417
|
+
await handle.close().catch(() => {
|
|
418
|
+
});
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
async function readClaudePromptHistory(claudeHome) {
|
|
423
|
+
const historyPath = path.join(claudeHome, "history.jsonl");
|
|
424
|
+
const entries = /* @__PURE__ */ new Map();
|
|
425
|
+
const lines = (await readTextTail(historyPath, CLAUDE_HISTORY_TAIL_BYTES)).split("\n").filter(Boolean);
|
|
426
|
+
for (const line of lines) {
|
|
427
|
+
try {
|
|
428
|
+
const entry = JSON.parse(line);
|
|
429
|
+
if (!entry || typeof entry.sessionId !== "string") continue;
|
|
430
|
+
entries.set(entry.sessionId, {
|
|
431
|
+
title: typeof entry.display === "string" ? entry.display.trim() : "",
|
|
432
|
+
workspace: typeof entry.project === "string" ? normalizePathValue(entry.project) : "",
|
|
433
|
+
updatedAt: typeof entry.timestamp === "string" ? entry.timestamp : ""
|
|
434
|
+
});
|
|
435
|
+
} catch {
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
return entries;
|
|
439
|
+
}
|
|
440
|
+
function claudeSessionIdFromFilePath(filePath) {
|
|
441
|
+
const match = path.basename(filePath).match(/^([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})\.jsonl$/i);
|
|
442
|
+
return match ? match[1] : "";
|
|
443
|
+
}
|
|
444
|
+
async function readClaudeSessionMetadata(filePath, promptHistory, maxLines = 160) {
|
|
445
|
+
const stream = fs.createReadStream(filePath, { encoding: "utf8" });
|
|
446
|
+
const reader = readline.createInterface({ input: stream, crlfDelay: Infinity });
|
|
447
|
+
const fileSessionId = claudeSessionIdFromFilePath(filePath);
|
|
448
|
+
const metadata = {
|
|
449
|
+
filePath,
|
|
450
|
+
id: fileSessionId,
|
|
451
|
+
title: "",
|
|
452
|
+
cwd: "",
|
|
453
|
+
workspace: "",
|
|
454
|
+
createdAt: "",
|
|
455
|
+
updatedAt: "",
|
|
456
|
+
model: "",
|
|
457
|
+
effort: "",
|
|
458
|
+
source: "",
|
|
459
|
+
schedule: null
|
|
460
|
+
};
|
|
461
|
+
let lineCount = 0;
|
|
462
|
+
try {
|
|
463
|
+
for await (const line of reader) {
|
|
464
|
+
if (!line) continue;
|
|
465
|
+
lineCount += 1;
|
|
466
|
+
try {
|
|
467
|
+
const event = JSON.parse(line);
|
|
468
|
+
if (typeof event.sessionId === "string") {
|
|
469
|
+
metadata.id = event.sessionId;
|
|
470
|
+
}
|
|
471
|
+
if (typeof event.timestamp === "string") {
|
|
472
|
+
metadata.updatedAt = event.timestamp;
|
|
473
|
+
metadata.createdAt = metadata.createdAt || event.timestamp;
|
|
474
|
+
}
|
|
475
|
+
if (typeof event.cwd === "string" && event.cwd.trim()) {
|
|
476
|
+
metadata.cwd = normalizePathValue(event.cwd);
|
|
477
|
+
}
|
|
478
|
+
if (typeof event.entrypoint === "string" && event.entrypoint.trim()) {
|
|
479
|
+
metadata.source = event.entrypoint.trim();
|
|
480
|
+
}
|
|
481
|
+
if (event.type === "ai-title" && typeof event.aiTitle === "string" && event.aiTitle.trim()) {
|
|
482
|
+
metadata.title = event.aiTitle.trim();
|
|
483
|
+
}
|
|
484
|
+
metadata.model = extractClaudeModel(event) || metadata.model;
|
|
485
|
+
metadata.effort = extractClaudeEffort(event) || metadata.effort;
|
|
486
|
+
if (!metadata.schedule) {
|
|
487
|
+
metadata.schedule = scheduleFromClaudeEvent(event, metadata.id || fileSessionId);
|
|
488
|
+
}
|
|
489
|
+
} catch {
|
|
490
|
+
}
|
|
491
|
+
if (lineCount >= maxLines || metadata.id && metadata.title && metadata.cwd && metadata.model) {
|
|
492
|
+
break;
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
} finally {
|
|
496
|
+
reader.close();
|
|
497
|
+
stream.destroy();
|
|
498
|
+
}
|
|
499
|
+
if (!metadata.id) return null;
|
|
500
|
+
const indexed = promptHistory.get(metadata.id);
|
|
501
|
+
metadata.title = metadata.title || indexed?.title || "Claude session";
|
|
502
|
+
metadata.workspace = normalizePathValue(indexed?.workspace || metadata.cwd || "");
|
|
503
|
+
metadata.updatedAt = metadata.updatedAt || indexed?.updatedAt || "";
|
|
504
|
+
metadata.source = metadata.source || "claude";
|
|
505
|
+
return metadata;
|
|
506
|
+
}
|
|
507
|
+
async function listClaudeSessions(options = {}) {
|
|
508
|
+
const claudeHome = options.claudeHome || path.join(os.homedir(), ".claude");
|
|
509
|
+
const limit = typeof options.limit === "number" && Number.isFinite(options.limit) ? Math.max(0, Math.min(MAX_AGENT_SESSION_HISTORY_LIMIT, Math.floor(options.limit))) : DEFAULT_LIMIT;
|
|
510
|
+
const scanLimit = typeof options.scanLimit === "number" && Number.isFinite(options.scanLimit) ? Math.max(limit, Math.min(MAX_AGENT_SESSION_SCAN_LIMIT, Math.floor(options.scanLimit))) : DEFAULT_SCAN_LIMIT;
|
|
511
|
+
const promptHistory = await readClaudePromptHistory(claudeHome);
|
|
512
|
+
const projectsRoot = path.join(claudeHome, "projects");
|
|
513
|
+
const sessionFiles = await collectRecentFiles(
|
|
514
|
+
projectsRoot,
|
|
515
|
+
".jsonl",
|
|
516
|
+
scanLimit,
|
|
517
|
+
(filePath) => path.relative(projectsRoot, filePath).split(path.sep).length === 2,
|
|
518
|
+
(directoryPath) => path.relative(projectsRoot, directoryPath).split(path.sep).length === 1
|
|
519
|
+
);
|
|
520
|
+
const sessions = [];
|
|
521
|
+
for (const { filePath, mtimeMs } of sessionFiles) {
|
|
522
|
+
const metadata = await readClaudeSessionMetadata(filePath, promptHistory);
|
|
523
|
+
if (!metadata) continue;
|
|
524
|
+
const mtimeIso = mtimeMs > 0 ? new Date(mtimeMs).toISOString() : "";
|
|
525
|
+
const updatedAt = timestampMs(mtimeIso) > timestampMs(metadata.updatedAt) ? mtimeIso : metadata.updatedAt || mtimeIso;
|
|
526
|
+
const session = {
|
|
527
|
+
provider: "claude",
|
|
528
|
+
providerName: "Claude",
|
|
529
|
+
id: metadata.id,
|
|
530
|
+
title: metadata.title,
|
|
531
|
+
cwd: metadata.cwd,
|
|
532
|
+
workspace: metadata.workspace,
|
|
533
|
+
updatedAt,
|
|
534
|
+
createdAt: metadata.createdAt,
|
|
535
|
+
archived: false,
|
|
536
|
+
pinned: false,
|
|
537
|
+
unread: false,
|
|
538
|
+
projectless: !metadata.workspace,
|
|
539
|
+
model: metadata.model,
|
|
540
|
+
effort: metadata.effort,
|
|
541
|
+
source: metadata.source,
|
|
542
|
+
schedule: metadata.schedule || void 0,
|
|
543
|
+
capabilities: ["resume", "fork"]
|
|
544
|
+
};
|
|
545
|
+
if (isVisibleAgentSession(session)) {
|
|
546
|
+
sessions.push(session);
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
return dedupeAgentSessions(sessions).sort((a, b) => timestampMs(b.updatedAt) - timestampMs(a.updatedAt)).slice(0, limit);
|
|
550
|
+
}
|
|
551
|
+
function qoderSessionIdFromFilePath(filePath) {
|
|
552
|
+
const match = path.basename(filePath).match(/^([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})\.jsonl$/i);
|
|
553
|
+
return match ? match[1] : "";
|
|
554
|
+
}
|
|
555
|
+
function applyQoderSessionEvent(metadata, event, fileSessionId) {
|
|
556
|
+
if (!event || typeof event !== "object") return;
|
|
557
|
+
const eventSessionId = typeof event.sessionId === "string" ? event.sessionId : typeof event.session_id === "string" ? event.session_id : "";
|
|
558
|
+
if (eventSessionId && (0, import_provider_session_id.isSafeProviderSessionId)(eventSessionId)) {
|
|
559
|
+
metadata.id = eventSessionId;
|
|
560
|
+
}
|
|
561
|
+
const timestamp = isoTimestamp(event.timestamp);
|
|
562
|
+
if (timestamp) {
|
|
563
|
+
metadata.updatedAt = timestamp;
|
|
564
|
+
metadata.createdAt = metadata.createdAt || timestamp;
|
|
565
|
+
}
|
|
566
|
+
if (typeof event.cwd === "string" && event.cwd.trim()) {
|
|
567
|
+
metadata.cwd = normalizePathValue(event.cwd);
|
|
568
|
+
}
|
|
569
|
+
if (typeof event.entrypoint === "string" && event.entrypoint.trim()) {
|
|
570
|
+
metadata.source = event.entrypoint.trim();
|
|
571
|
+
}
|
|
572
|
+
if (event.type === "system" && typeof event.qodercli_version === "string") {
|
|
573
|
+
metadata.cliVersion = event.qodercli_version.trim();
|
|
574
|
+
}
|
|
575
|
+
if (typeof event.version === "string" && event.version.trim()) {
|
|
576
|
+
metadata.cliVersion = event.version.trim();
|
|
577
|
+
}
|
|
578
|
+
if (event.type === "runtime-config" && typeof event.version === "string") {
|
|
579
|
+
metadata.cliVersion = event.version.trim();
|
|
580
|
+
}
|
|
581
|
+
if (event.type === "ai-title" && typeof event.aiTitle === "string" && event.aiTitle.trim()) {
|
|
582
|
+
metadata.title = event.aiTitle.trim();
|
|
583
|
+
}
|
|
584
|
+
if (event.type === "last-prompt" && typeof event.lastPrompt === "string" && event.lastPrompt.trim()) {
|
|
585
|
+
metadata.lastPrompt = event.lastPrompt.trim();
|
|
586
|
+
}
|
|
587
|
+
if (!metadata.firstPrompt && event.type === "user") {
|
|
588
|
+
metadata.firstPrompt = qoderTextFromMessage(event.message);
|
|
589
|
+
}
|
|
590
|
+
metadata.model = extractQoderModel(event) || metadata.model;
|
|
591
|
+
metadata.effort = extractQoderEffort(event) || metadata.effort;
|
|
592
|
+
if (!metadata.id && fileSessionId) {
|
|
593
|
+
metadata.id = fileSessionId;
|
|
594
|
+
}
|
|
595
|
+
}
|
|
596
|
+
async function readQoderSessionMetadata(filePath, maxLines = 160) {
|
|
597
|
+
const fileSessionId = qoderSessionIdFromFilePath(filePath);
|
|
598
|
+
const metadata = {
|
|
599
|
+
filePath,
|
|
600
|
+
id: fileSessionId,
|
|
601
|
+
title: "",
|
|
602
|
+
lastPrompt: "",
|
|
603
|
+
firstPrompt: "",
|
|
604
|
+
cwd: "",
|
|
605
|
+
workspace: "",
|
|
606
|
+
createdAt: "",
|
|
607
|
+
updatedAt: "",
|
|
608
|
+
model: "",
|
|
609
|
+
effort: "",
|
|
610
|
+
source: "",
|
|
611
|
+
cliVersion: ""
|
|
612
|
+
};
|
|
613
|
+
const stream = fs.createReadStream(filePath, { encoding: "utf8" });
|
|
614
|
+
const reader = readline.createInterface({ input: stream, crlfDelay: Infinity });
|
|
615
|
+
let lineCount = 0;
|
|
616
|
+
try {
|
|
617
|
+
for await (const line of reader) {
|
|
618
|
+
if (!line) continue;
|
|
619
|
+
lineCount += 1;
|
|
620
|
+
try {
|
|
621
|
+
applyQoderSessionEvent(metadata, JSON.parse(line), fileSessionId);
|
|
622
|
+
} catch {
|
|
623
|
+
}
|
|
624
|
+
if (lineCount >= maxLines || metadata.id && metadata.cwd && metadata.model && metadata.title) {
|
|
625
|
+
break;
|
|
626
|
+
}
|
|
627
|
+
}
|
|
628
|
+
} finally {
|
|
629
|
+
reader.close();
|
|
630
|
+
stream.destroy();
|
|
631
|
+
}
|
|
632
|
+
const tail = await readTextTail(filePath, QODER_HISTORY_TAIL_BYTES);
|
|
633
|
+
for (const line of tail.split("\n").filter(Boolean)) {
|
|
634
|
+
try {
|
|
635
|
+
applyQoderSessionEvent(metadata, JSON.parse(line), fileSessionId);
|
|
636
|
+
} catch {
|
|
637
|
+
}
|
|
638
|
+
}
|
|
639
|
+
if (!metadata.id || !(0, import_provider_session_id.isSafeProviderSessionId)(metadata.id)) return null;
|
|
640
|
+
metadata.title = firstTrimmedString(metadata.title, metadata.lastPrompt, metadata.firstPrompt, "Qoder session");
|
|
641
|
+
metadata.workspace = normalizePathValue(metadata.cwd || "");
|
|
642
|
+
metadata.source = metadata.source || "qodercli";
|
|
643
|
+
return metadata;
|
|
644
|
+
}
|
|
645
|
+
async function listQoderSessions(options = {}) {
|
|
646
|
+
const qoderHome = options.qoderHome || path.join(os.homedir(), ".qoder");
|
|
647
|
+
const limit = typeof options.limit === "number" && Number.isFinite(options.limit) ? Math.max(0, Math.min(MAX_AGENT_SESSION_HISTORY_LIMIT, Math.floor(options.limit))) : DEFAULT_LIMIT;
|
|
648
|
+
const scanLimit = typeof options.scanLimit === "number" && Number.isFinite(options.scanLimit) ? Math.max(limit, Math.min(MAX_AGENT_SESSION_SCAN_LIMIT, Math.floor(options.scanLimit))) : DEFAULT_SCAN_LIMIT;
|
|
649
|
+
const projectsRoot = path.join(qoderHome, "projects");
|
|
650
|
+
const sessionFiles = await collectRecentFiles(
|
|
651
|
+
projectsRoot,
|
|
652
|
+
".jsonl",
|
|
653
|
+
scanLimit,
|
|
654
|
+
(filePath) => path.relative(projectsRoot, filePath).split(path.sep).length === 2,
|
|
655
|
+
(directoryPath) => path.relative(projectsRoot, directoryPath).split(path.sep).length === 1
|
|
656
|
+
);
|
|
657
|
+
const sessions = [];
|
|
658
|
+
for (const { filePath, mtimeMs } of sessionFiles) {
|
|
659
|
+
const metadata = await readQoderSessionMetadata(filePath);
|
|
660
|
+
if (!metadata) continue;
|
|
661
|
+
const mtimeIso = mtimeMs > 0 ? new Date(mtimeMs).toISOString() : "";
|
|
662
|
+
const updatedAt = timestampMs(mtimeIso) > timestampMs(metadata.updatedAt) ? mtimeIso : metadata.updatedAt || mtimeIso;
|
|
663
|
+
const session = {
|
|
664
|
+
provider: "qoder",
|
|
665
|
+
providerName: "Qoder",
|
|
666
|
+
id: metadata.id,
|
|
667
|
+
title: metadata.title,
|
|
668
|
+
cwd: metadata.cwd,
|
|
669
|
+
workspace: metadata.workspace,
|
|
670
|
+
updatedAt,
|
|
671
|
+
createdAt: metadata.createdAt,
|
|
672
|
+
archived: false,
|
|
673
|
+
pinned: false,
|
|
674
|
+
unread: false,
|
|
675
|
+
projectless: !metadata.workspace,
|
|
676
|
+
model: metadata.model,
|
|
677
|
+
effort: metadata.effort,
|
|
678
|
+
source: metadata.source,
|
|
679
|
+
cliVersion: metadata.cliVersion,
|
|
680
|
+
capabilities: ["resume", "fork"]
|
|
681
|
+
};
|
|
682
|
+
if (isVisibleAgentSession(session)) {
|
|
683
|
+
sessions.push(session);
|
|
684
|
+
}
|
|
685
|
+
}
|
|
686
|
+
return dedupeAgentSessions(sessions).sort((a, b) => timestampMs(b.updatedAt) - timestampMs(a.updatedAt)).slice(0, limit);
|
|
687
|
+
}
|
|
688
|
+
function qwenSessionIdFromFilePath(filePath) {
|
|
689
|
+
const match = path.basename(filePath).match(/^([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})\.jsonl$/i);
|
|
690
|
+
return match ? match[1] : "";
|
|
691
|
+
}
|
|
692
|
+
function applyQwenSessionEvent(metadata, event, fileSessionId) {
|
|
693
|
+
if (!event || typeof event !== "object") return;
|
|
694
|
+
const eventSessionId = typeof event.sessionId === "string" ? event.sessionId : "";
|
|
695
|
+
if (eventSessionId && (0, import_provider_session_id.isSafeProviderSessionId)(eventSessionId)) {
|
|
696
|
+
metadata.id = eventSessionId;
|
|
697
|
+
}
|
|
698
|
+
const timestamp = isoTimestamp(event.timestamp);
|
|
699
|
+
if (timestamp) {
|
|
700
|
+
metadata.updatedAt = timestamp;
|
|
701
|
+
metadata.createdAt = metadata.createdAt || timestamp;
|
|
702
|
+
}
|
|
703
|
+
if (typeof event.cwd === "string" && event.cwd.trim()) {
|
|
704
|
+
metadata.cwd = normalizePathValue(event.cwd);
|
|
705
|
+
}
|
|
706
|
+
if (typeof event.version === "string" && event.version.trim()) {
|
|
707
|
+
metadata.cliVersion = event.version.trim();
|
|
708
|
+
}
|
|
709
|
+
if (typeof event.model === "string" && event.model.trim()) {
|
|
710
|
+
metadata.model = event.model.trim();
|
|
711
|
+
}
|
|
712
|
+
if (event.type === "system" && event.subtype === "custom_title" && typeof event.systemPayload?.customTitle === "string" && event.systemPayload.customTitle.trim()) {
|
|
713
|
+
metadata.title = event.systemPayload.customTitle.trim();
|
|
714
|
+
}
|
|
715
|
+
if (!metadata.firstPrompt && event.type === "user") {
|
|
716
|
+
metadata.firstPrompt = qwenTextFromMessage(event.message);
|
|
717
|
+
}
|
|
718
|
+
if (!metadata.id && fileSessionId) metadata.id = fileSessionId;
|
|
719
|
+
}
|
|
720
|
+
async function readQwenSessionMetadata(filePath, maxLines = 160) {
|
|
721
|
+
const fileSessionId = qwenSessionIdFromFilePath(filePath);
|
|
722
|
+
const metadata = {
|
|
723
|
+
filePath,
|
|
724
|
+
id: fileSessionId,
|
|
725
|
+
title: "",
|
|
726
|
+
firstPrompt: "",
|
|
727
|
+
cwd: "",
|
|
728
|
+
workspace: "",
|
|
729
|
+
createdAt: "",
|
|
730
|
+
updatedAt: "",
|
|
731
|
+
model: "",
|
|
732
|
+
source: "qwen",
|
|
733
|
+
cliVersion: ""
|
|
734
|
+
};
|
|
735
|
+
const stream = fs.createReadStream(filePath, { encoding: "utf8" });
|
|
736
|
+
const reader = readline.createInterface({ input: stream, crlfDelay: Infinity });
|
|
737
|
+
let lineCount = 0;
|
|
738
|
+
try {
|
|
739
|
+
for await (const line of reader) {
|
|
740
|
+
if (!line) continue;
|
|
741
|
+
lineCount += 1;
|
|
742
|
+
try {
|
|
743
|
+
applyQwenSessionEvent(metadata, JSON.parse(line), fileSessionId);
|
|
744
|
+
} catch {
|
|
745
|
+
}
|
|
746
|
+
if (lineCount >= maxLines || metadata.id && metadata.cwd && metadata.firstPrompt && metadata.model) {
|
|
747
|
+
break;
|
|
748
|
+
}
|
|
749
|
+
}
|
|
750
|
+
} finally {
|
|
751
|
+
reader.close();
|
|
752
|
+
stream.destroy();
|
|
753
|
+
}
|
|
754
|
+
const tail = await readTextTail(filePath, QWEN_HISTORY_TAIL_BYTES);
|
|
755
|
+
for (const line of tail.split("\n").filter(Boolean)) {
|
|
756
|
+
try {
|
|
757
|
+
applyQwenSessionEvent(metadata, JSON.parse(line), fileSessionId);
|
|
758
|
+
} catch {
|
|
759
|
+
}
|
|
760
|
+
}
|
|
761
|
+
if (!metadata.id || !(0, import_provider_session_id.isSafeProviderSessionId)(metadata.id)) return null;
|
|
762
|
+
metadata.title = firstTrimmedString(metadata.title, metadata.firstPrompt, "Qwen Code session");
|
|
763
|
+
metadata.workspace = normalizePathValue(metadata.cwd || "");
|
|
764
|
+
return metadata;
|
|
765
|
+
}
|
|
766
|
+
async function listQwenSessions(options = {}) {
|
|
767
|
+
const qwenHome = options.qwenHome || path.join(os.homedir(), ".qwen");
|
|
768
|
+
const limit = typeof options.limit === "number" && Number.isFinite(options.limit) ? Math.max(0, Math.min(MAX_AGENT_SESSION_HISTORY_LIMIT, Math.floor(options.limit))) : DEFAULT_LIMIT;
|
|
769
|
+
const scanLimit = typeof options.scanLimit === "number" && Number.isFinite(options.scanLimit) ? Math.max(limit, Math.min(MAX_AGENT_SESSION_SCAN_LIMIT, Math.floor(options.scanLimit))) : DEFAULT_SCAN_LIMIT;
|
|
770
|
+
const projectsRoot = path.join(qwenHome, "projects");
|
|
771
|
+
const sessionFiles = await collectRecentFiles(
|
|
772
|
+
projectsRoot,
|
|
773
|
+
".jsonl",
|
|
774
|
+
scanLimit,
|
|
775
|
+
(filePath) => {
|
|
776
|
+
const relativeParts = path.relative(projectsRoot, filePath).split(path.sep);
|
|
777
|
+
return relativeParts.length === 3 && relativeParts[1] === "chats";
|
|
778
|
+
},
|
|
779
|
+
(directoryPath) => {
|
|
780
|
+
const relativeParts = path.relative(projectsRoot, directoryPath).split(path.sep);
|
|
781
|
+
return relativeParts.length === 1 || relativeParts.length === 2 && relativeParts[1] === "chats";
|
|
782
|
+
}
|
|
783
|
+
);
|
|
784
|
+
const sessions = [];
|
|
785
|
+
for (const { filePath, mtimeMs } of sessionFiles) {
|
|
786
|
+
const metadata = await readQwenSessionMetadata(filePath);
|
|
787
|
+
if (!metadata) continue;
|
|
788
|
+
const mtimeIso = mtimeMs > 0 ? new Date(mtimeMs).toISOString() : "";
|
|
789
|
+
const updatedAt = timestampMs(mtimeIso) > timestampMs(metadata.updatedAt) ? mtimeIso : metadata.updatedAt || mtimeIso;
|
|
790
|
+
const session = {
|
|
791
|
+
provider: "qwen",
|
|
792
|
+
providerName: "Qwen Code",
|
|
793
|
+
id: metadata.id,
|
|
794
|
+
title: metadata.title,
|
|
795
|
+
cwd: metadata.cwd,
|
|
796
|
+
workspace: metadata.workspace,
|
|
797
|
+
updatedAt,
|
|
798
|
+
createdAt: metadata.createdAt,
|
|
799
|
+
archived: false,
|
|
800
|
+
pinned: false,
|
|
801
|
+
unread: false,
|
|
802
|
+
projectless: !metadata.workspace,
|
|
803
|
+
model: metadata.model,
|
|
804
|
+
effort: "",
|
|
805
|
+
source: metadata.source,
|
|
806
|
+
cliVersion: metadata.cliVersion,
|
|
807
|
+
capabilities: ["resume"]
|
|
808
|
+
};
|
|
809
|
+
if (isVisibleAgentSession(session)) sessions.push(session);
|
|
810
|
+
}
|
|
811
|
+
return dedupeAgentSessions(sessions).sort((a, b) => timestampMs(b.updatedAt) - timestampMs(a.updatedAt)).slice(0, limit);
|
|
812
|
+
}
|
|
813
|
+
function runOpenCodeSessionList(options = {}) {
|
|
814
|
+
const executable = options.opencodeBin || process.env.FARMING_OPENCODE_BIN || "opencode";
|
|
815
|
+
const maxCount = typeof options.maxCount === "number" && Number.isFinite(options.maxCount) ? Math.max(1, Math.floor(options.maxCount)) : DEFAULT_SCAN_LIMIT;
|
|
816
|
+
const env = { ...process.env };
|
|
817
|
+
if (options.opencodeHome) env.OPENCODE_CONFIG_DIR = options.opencodeHome;
|
|
818
|
+
return new Promise((resolve, reject) => {
|
|
819
|
+
(0, import_child_process.execFile)(executable, ["session", "list", "--format", "json", "--max-count", String(maxCount)], {
|
|
820
|
+
env,
|
|
821
|
+
maxBuffer: 4 * 1024 * 1024,
|
|
822
|
+
timeout: 15e3
|
|
823
|
+
}, (error, stdout) => {
|
|
824
|
+
if (error) {
|
|
825
|
+
reject(error);
|
|
826
|
+
return;
|
|
827
|
+
}
|
|
828
|
+
resolve(stdout);
|
|
829
|
+
});
|
|
830
|
+
});
|
|
831
|
+
}
|
|
832
|
+
async function listOpenCodeSessions(options = {}) {
|
|
833
|
+
const limit = typeof options.limit === "number" && Number.isFinite(options.limit) ? Math.max(0, Math.min(MAX_AGENT_SESSION_HISTORY_LIMIT, Math.floor(options.limit))) : DEFAULT_LIMIT;
|
|
834
|
+
const scanLimit = typeof options.scanLimit === "number" && Number.isFinite(options.scanLimit) ? Math.max(limit, Math.min(MAX_AGENT_SESSION_SCAN_LIMIT, Math.floor(options.scanLimit))) : DEFAULT_SCAN_LIMIT;
|
|
835
|
+
const listCommand = options.runOpenCodeSessionList || runOpenCodeSessionList;
|
|
836
|
+
let rawSessions = [];
|
|
837
|
+
try {
|
|
838
|
+
const output = await listCommand({
|
|
839
|
+
maxCount: scanLimit,
|
|
840
|
+
opencodeBin: options.opencodeBin,
|
|
841
|
+
opencodeHome: options.opencodeHome
|
|
842
|
+
});
|
|
843
|
+
rawSessions = JSON.parse(String(output || "[]"));
|
|
844
|
+
} catch {
|
|
845
|
+
return [];
|
|
846
|
+
}
|
|
847
|
+
if (!Array.isArray(rawSessions)) return [];
|
|
848
|
+
return dedupeAgentSessions(rawSessions.map((raw) => {
|
|
849
|
+
if (!isHistoryRecord(raw)) return null;
|
|
850
|
+
const id = firstTrimmedString(raw.id);
|
|
851
|
+
const cwd = normalizePathValue(raw.directory || "");
|
|
852
|
+
if (!id || !(0, import_provider_session_id.isSafeProviderSessionId)(id)) return null;
|
|
853
|
+
return {
|
|
854
|
+
provider: "opencode",
|
|
855
|
+
providerName: "OpenCode",
|
|
856
|
+
id,
|
|
857
|
+
title: firstTrimmedString(raw.title, "OpenCode session"),
|
|
858
|
+
cwd,
|
|
859
|
+
workspace: cwd,
|
|
860
|
+
updatedAt: isoTimestamp(raw.updated),
|
|
861
|
+
createdAt: isoTimestamp(raw.created),
|
|
862
|
+
archived: false,
|
|
863
|
+
pinned: false,
|
|
864
|
+
unread: false,
|
|
865
|
+
projectless: !cwd,
|
|
866
|
+
source: "opencode",
|
|
867
|
+
capabilities: ["resume", "fork"]
|
|
868
|
+
};
|
|
869
|
+
}).filter((session) => session !== null && isVisibleAgentSession(session))).sort((a, b) => timestampMs(b.updatedAt) - timestampMs(a.updatedAt)).slice(0, limit);
|
|
870
|
+
}
|
|
871
|
+
function normalizeCodexSession(session) {
|
|
872
|
+
return {
|
|
873
|
+
provider: "codex",
|
|
874
|
+
providerName: "Codex",
|
|
875
|
+
...session,
|
|
876
|
+
capabilities: ["resume", "fork"]
|
|
877
|
+
};
|
|
878
|
+
}
|
|
879
|
+
function normalizeProvider(provider) {
|
|
880
|
+
const normalized = String(provider || "").trim().toLowerCase();
|
|
881
|
+
return isAgentProvider(normalized) ? normalized : "";
|
|
882
|
+
}
|
|
883
|
+
function isSafeSessionId(sessionId) {
|
|
884
|
+
return (0, import_provider_session_id.isSafeProviderSessionId)(sessionId);
|
|
885
|
+
}
|
|
886
|
+
function buildAgentSessionResumeCommand(provider, sessionId, options = {}) {
|
|
887
|
+
const normalizedProvider = normalizeProvider(provider);
|
|
888
|
+
const normalizedSessionId = String(sessionId || "").trim();
|
|
889
|
+
if (!normalizedProvider || !isSafeSessionId(normalizedSessionId)) return "";
|
|
890
|
+
if (normalizedProvider === "codex") {
|
|
891
|
+
const cwd = normalizePathValue(options.cwd);
|
|
892
|
+
const modelProvider = String(
|
|
893
|
+
options.modelProvider || (Object.prototype.hasOwnProperty.call(options, "providerHomePath") ? resolveCodexResumeModelProvider(options.providerHomePath) : "")
|
|
894
|
+
).trim();
|
|
895
|
+
const providerArgs = modelProvider ? ` -c ${quoteCommandArg(`model_provider=${JSON.stringify(modelProvider)}`)}` : "";
|
|
896
|
+
const cwdArgs = cwd ? ` -C ${quoteCommandArg(cwd)}` : "";
|
|
897
|
+
return `codex ${options.fork === true ? "fork" : "resume"}${providerArgs}${cwdArgs} ${normalizedSessionId}`;
|
|
898
|
+
}
|
|
899
|
+
if (normalizedProvider === "claude") {
|
|
900
|
+
return options.fork === true ? `claude --resume ${normalizedSessionId} --fork-session` : `claude --resume ${normalizedSessionId}`;
|
|
901
|
+
}
|
|
902
|
+
if (normalizedProvider === "qoder") {
|
|
903
|
+
return options.fork === true ? `qodercli --resume ${normalizedSessionId} --fork-session` : `qodercli --resume ${normalizedSessionId}`;
|
|
904
|
+
}
|
|
905
|
+
if (normalizedProvider === "qwen") {
|
|
906
|
+
return options.fork === true ? "" : `qwen --resume ${normalizedSessionId}`;
|
|
907
|
+
}
|
|
908
|
+
if (normalizedProvider === "opencode") {
|
|
909
|
+
return `opencode --session ${normalizedSessionId}${options.fork === true ? " --fork" : ""}`;
|
|
910
|
+
}
|
|
911
|
+
return "";
|
|
912
|
+
}
|
|
913
|
+
async function listAgentSessions(options = {}) {
|
|
914
|
+
const limit = typeof options.limit === "number" && Number.isFinite(options.limit) ? Math.max(0, Math.min(MAX_AGENT_SESSION_HISTORY_LIMIT, Math.floor(options.limit))) : DEFAULT_LIMIT;
|
|
915
|
+
const requestedProviders = Array.isArray(options.providers) ? options.providers.map(normalizeProvider).filter((provider) => Boolean(provider)) : ["codex", "claude", "opencode", "qoder", "qwen"];
|
|
916
|
+
const providers = Array.from(new Set(requestedProviders));
|
|
917
|
+
const sessions = [];
|
|
918
|
+
const providerHomes = options.providerHomes && typeof options.providerHomes === "object" ? options.providerHomes : {};
|
|
919
|
+
async function listForHomes(homes, fallbackHomeKey, listFn, homeOptionKey, normalize = (session) => session) {
|
|
920
|
+
const configuredHomes = Array.isArray(homes) && homes.length > 0 ? homes : [{ id: "default", path: options[fallbackHomeKey] }];
|
|
921
|
+
const perHomeLimit = typeof options.providerLimit === "number" && Number.isFinite(options.providerLimit) ? Math.max(0, Math.min(MAX_AGENT_SESSION_HISTORY_LIMIT, Math.floor(options.providerLimit))) : limit;
|
|
922
|
+
for (const home of configuredHomes) {
|
|
923
|
+
const providerHomeId = String(home && home.id || "default").trim() || "default";
|
|
924
|
+
const providerHomePath = String(home && home.path || "").trim();
|
|
925
|
+
const listOptions = {
|
|
926
|
+
limit: perHomeLimit,
|
|
927
|
+
scanLimit: options.scanLimit,
|
|
928
|
+
opencodeBin: options.opencodeBin,
|
|
929
|
+
runOpenCodeSessionList: options.runOpenCodeSessionList
|
|
930
|
+
};
|
|
931
|
+
if (providerHomePath) listOptions[homeOptionKey] = providerHomePath;
|
|
932
|
+
const homeSessions = await listFn(listOptions);
|
|
933
|
+
sessions.push(...homeSessions.map((session) => normalize({
|
|
934
|
+
...session,
|
|
935
|
+
providerHomeId,
|
|
936
|
+
providerHomePath
|
|
937
|
+
})).filter(isVisibleAgentSession));
|
|
938
|
+
}
|
|
939
|
+
}
|
|
940
|
+
if (providers.includes("codex")) {
|
|
941
|
+
await listForHomes(providerHomes.codex, "codexHome", import_codex_session_history.listCodexSessions, "codexHome", normalizeCodexSession);
|
|
942
|
+
}
|
|
943
|
+
if (providers.includes("claude")) {
|
|
944
|
+
await listForHomes(providerHomes.claude, "claudeHome", listClaudeSessions, "claudeHome");
|
|
945
|
+
}
|
|
946
|
+
if (providers.includes("qoder")) {
|
|
947
|
+
await listForHomes(providerHomes.qoder, "qoderHome", listQoderSessions, "qoderHome");
|
|
948
|
+
}
|
|
949
|
+
if (providers.includes("qwen")) {
|
|
950
|
+
await listForHomes(providerHomes.qwen, "qwenHome", listQwenSessions, "qwenHome");
|
|
951
|
+
}
|
|
952
|
+
if (providers.includes("opencode")) {
|
|
953
|
+
const configuredHomes = Array.isArray(providerHomes.opencode) && providerHomes.opencode.length > 0 ? providerHomes.opencode : [{ id: "default", path: options.opencodeHome }];
|
|
954
|
+
const home = configuredHomes.find((candidate) => String(candidate?.id || "") === "default") || configuredHomes[0];
|
|
955
|
+
const providerHomeId = String(home?.id || "default").trim() || "default";
|
|
956
|
+
const providerHomePath = String(home?.path || "").trim();
|
|
957
|
+
const homeSessions = await listOpenCodeSessions({
|
|
958
|
+
limit: typeof options.providerLimit === "number" && Number.isFinite(options.providerLimit) ? options.providerLimit : limit,
|
|
959
|
+
scanLimit: options.scanLimit,
|
|
960
|
+
opencodeBin: options.opencodeBin,
|
|
961
|
+
opencodeHome: providerHomePath,
|
|
962
|
+
runOpenCodeSessionList: options.runOpenCodeSessionList
|
|
963
|
+
});
|
|
964
|
+
const bindingsBySession = /* @__PURE__ */ new Map();
|
|
965
|
+
for (const binding of options.providerSessionBindings || []) {
|
|
966
|
+
if (normalizeProvider(binding?.provider) !== "opencode") continue;
|
|
967
|
+
const sessionId = String(binding?.providerSessionId || "").trim();
|
|
968
|
+
if (!sessionId) continue;
|
|
969
|
+
const bindings = bindingsBySession.get(sessionId) || [];
|
|
970
|
+
bindings.push(binding);
|
|
971
|
+
bindingsBySession.set(sessionId, bindings);
|
|
972
|
+
}
|
|
973
|
+
sessions.push(...homeSessions.map((session) => {
|
|
974
|
+
const bindings = bindingsBySession.get(String(session.id || "")) || [];
|
|
975
|
+
const exactBindings = new Map(bindings.map((binding2) => [
|
|
976
|
+
`${binding2.providerHomeId}\0${binding2.providerHomePath}`,
|
|
977
|
+
binding2
|
|
978
|
+
]));
|
|
979
|
+
const binding = exactBindings.size === 1 ? [...exactBindings.values()][0] : null;
|
|
980
|
+
return {
|
|
981
|
+
...session,
|
|
982
|
+
providerHomeId: binding?.providerHomeId || providerHomeId,
|
|
983
|
+
providerHomePath: binding?.providerHomePath || providerHomePath
|
|
984
|
+
};
|
|
985
|
+
}));
|
|
986
|
+
}
|
|
987
|
+
return dedupeAgentSessions(sessions).sort(compareAgentSessions).slice(0, limit);
|
|
988
|
+
}
|
|
989
|
+
async function findAgentSession(provider, sessionId, options = {}) {
|
|
990
|
+
const normalizedProvider = normalizeProvider(provider);
|
|
991
|
+
const normalizedSessionId = String(sessionId || "").trim();
|
|
992
|
+
if (!normalizedProvider || !isSafeSessionId(normalizedSessionId)) return null;
|
|
993
|
+
const sessions = await listAgentSessions({
|
|
994
|
+
...options,
|
|
995
|
+
providers: [normalizedProvider],
|
|
996
|
+
limit: options.limit || 200,
|
|
997
|
+
providerLimit: options.providerLimit || 200
|
|
998
|
+
});
|
|
999
|
+
const requestedHomeId = typeof options.providerHomeId === "string" ? options.providerHomeId.trim() : "";
|
|
1000
|
+
return sessions.find((session) => session.id === normalizedSessionId && (!requestedHomeId || (session.providerHomeId || "default") === requestedHomeId)) || null;
|
|
1001
|
+
}
|
|
1002
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
1003
|
+
0 && (module.exports = {
|
|
1004
|
+
buildAgentSessionResumeCommand,
|
|
1005
|
+
compareAgentSessions,
|
|
1006
|
+
findAgentSession,
|
|
1007
|
+
hasTemporaryWorkspaceReference,
|
|
1008
|
+
isAgentManagedWorktree,
|
|
1009
|
+
isDefaultClaudeSessionTitle,
|
|
1010
|
+
isSafeSessionId,
|
|
1011
|
+
isTemporaryWorkspace,
|
|
1012
|
+
isVisibleAgentSession,
|
|
1013
|
+
listAgentSessions,
|
|
1014
|
+
listClaudeSessions,
|
|
1015
|
+
listOpenCodeSessions,
|
|
1016
|
+
listQoderSessions,
|
|
1017
|
+
listQwenSessions,
|
|
1018
|
+
normalizeProvider,
|
|
1019
|
+
paginateAgentSessions,
|
|
1020
|
+
resolveCodexResumeModelProvider,
|
|
1021
|
+
searchAgentSessions
|
|
1022
|
+
});
|