@myagentroam/node 0.9.62 → 0.9.65
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/LICENSE +202 -0
- package/NOTICE +4 -0
- package/dist/capabilities.js +110 -2
- package/dist/claude-agent-sdk.js +330 -2
- package/dist/claude-channel.js +44 -2
- package/dist/codex-app-server.js +510 -2
- package/dist/config.js +106 -2
- package/dist/connector/node-connector-options.js +1 -2
- package/dist/connector/node-operation-router.js +22 -2
- package/dist/connector.js +1736 -2
- package/dist/control-outbound-scheduler.js +153 -2
- package/dist/database.js +639 -2
- package/dist/fake-runner.js +129 -2
- package/dist/git-askpass.js +12 -0
- package/dist/git-execution-helper.js +266 -0
- package/dist/health.js +3 -2
- package/dist/main.js +57 -2
- package/dist/mcp-installation-model.js +1 -2
- package/dist/migrations/v004.js +55 -3
- package/dist/migrations/v005.js +13 -3
- package/dist/migrations/v006.js +90 -3
- package/dist/migrations/v007.js +22 -3
- package/dist/migrations/v008.js +18 -3
- package/dist/migrations/v009.js +70 -4
- package/dist/migrations/v010.js +43 -3
- package/dist/migrations/v011.js +20 -3
- package/dist/migrations/v012.js +8 -0
- package/dist/native-jsonl-reader.js +186 -2
- package/dist/native-session-history.js +1143 -2
- package/dist/opencode-runtime.js +80 -2
- package/dist/opencode-server.js +259 -2
- package/dist/operational.js +122 -2
- package/dist/process-tree.js +18 -2
- package/dist/ripgrep-binary.js +31 -2
- package/dist/rotating-log.js +67 -2
- package/dist/runner/abstract-runner.js +260 -2
- package/dist/runner/claude/managed-run-controller.js +355 -2
- package/dist/runner/claude/tool-normalizer.js +120 -2
- package/dist/runner/claude-code-runner.js +303 -2
- package/dist/runner/codex/composer-image-markers.js +8 -2
- package/dist/runner/codex/conversation-parser.js +913 -2
- package/dist/runner/codex/managed-run-controller.js +494 -2
- package/dist/runner/codex/tool-normalizer.js +214 -2
- package/dist/runner/codex-runner.js +585 -2
- package/dist/runner/fake-test-runner.js +47 -2
- package/dist/runner/mar-agent/conversation-normalizer.js +644 -2
- package/dist/runner/mar-agent/executor-stdio-client-transport.js +139 -2
- package/dist/runner/mar-agent/generated-images.js +41 -2
- package/dist/runner/mar-agent/history-projection.js +106 -2
- package/dist/runner/mar-agent/hosted-conversation-runtime.js +446 -2
- package/dist/runner/mar-agent/managed-run-controller.js +785 -2
- package/dist/runner/mar-agent/mcp-client-pool.js +233 -2
- package/dist/runner/mar-agent/runtime-model-factory.js +326 -2
- package/dist/runner/mar-agent-runner.js +458 -2
- package/dist/runner/opencode/conversation-parser.js +221 -2
- package/dist/runner/opencode/managed-run-controller.js +588 -2
- package/dist/runner/opencode/tool-normalizer.js +80 -2
- package/dist/runner/opencode-runner.js +426 -2
- package/dist/runner/runner-registry.js +87 -2
- package/dist/runner-command-engine.js +71 -2
- package/dist/runner-profiles.js +323 -2
- package/dist/runner-usage.js +190 -2
- package/dist/runtime-command-detector.js +73 -2
- package/dist/runtime-model.js +1 -2
- package/dist/runtime-state.js +1509 -2
- package/dist/service/attachment-domain-state.js +7 -2
- package/dist/service/bubblewrap-sandbox-executor.js +543 -2
- package/dist/service/continuous-run-coordinator.js +425 -2
- package/dist/service/conversation-history-service.js +552 -2
- package/dist/service/conversation-hosting-capability-service.js +61 -2
- package/dist/service/conversation-hosting-enablement-service.js +91 -2
- package/dist/service/conversation-hosting-maintenance-service.js +174 -2
- package/dist/service/conversation-segment-service.js +162 -2
- package/dist/service/conversation-template-node-service.js +992 -2
- package/dist/service/external-session-resume-service.js +152 -2
- package/dist/service/fake-managed-run-service.js +60 -2
- package/dist/service/git-execution-service.js +418 -0
- package/dist/service/git-operation-service.js +57 -0
- package/dist/service/hosted-conversation-node-service.js +1982 -2
- package/dist/service/hosted-conversation-store.js +1405 -2
- package/dist/service/managed-runner-session-service.js +35 -2
- package/dist/service/mar-agent-model-transport-test-service.js +88 -2
- package/dist/service/mcp-installation-verifier.js +87 -2
- package/dist/service/mcp-node-operation-service.js +90 -2
- package/dist/service/mission-mcp-server.js +124 -2
- package/dist/service/mission-mcp-stdio.js +40 -2
- package/dist/service/mission-runtime.js +142 -2
- package/dist/service/native-session-projection-service.js +274 -2
- package/dist/service/native-session-watch-service.js +683 -2
- package/dist/service/node-connection-lifecycle-service.js +88 -2
- package/dist/service/node-control-channel.js +85 -2
- package/dist/service/node-control-message-service.js +109 -2
- package/dist/service/node-request-service.js +62 -2
- package/dist/service/node-run-event-bridge.js +88 -2
- package/dist/service/node-terminal-channel.js +202 -2
- package/dist/service/node-upgrade-coordinator.js +137 -2
- package/dist/service/node-workspace-coordinator.js +97 -2
- package/dist/service/recent-run-projection-service.js +99 -2
- package/dist/service/run-attachment-service.js +321 -2
- package/dist/service/run-domain-state.js +4 -2
- package/dist/service/run-event-service.js +246 -2
- package/dist/service/run-ownership-policy.js +22 -2
- package/dist/service/run-workbench-service.js +120 -2
- package/dist/service/runner-channel-message-service.js +20 -2
- package/dist/service/runner-interaction-service.js +243 -2
- package/dist/service/runner-service.js +69 -2
- package/dist/service/runtime-credential-control-service.js +95 -2
- package/dist/service/session-catalog-service.js +404 -2
- package/dist/service/session-command-service.js +125 -2
- package/dist/service/session-context-service.js +128 -2
- package/dist/service/session-domain-state.js +9 -2
- package/dist/service/session-identity-service.js +86 -2
- package/dist/service/session-lifecycle-service.js +248 -2
- package/dist/service/session-message-service.js +270 -2
- package/dist/service/session-presentation-service.js +43 -2
- package/dist/service/session-query-service.js +82 -2
- package/dist/service/session-watch-slot-coordinator.js +21 -2
- package/dist/service/skill-directory-service.js +238 -2
- package/dist/service/skill-install-service.js +434 -2
- package/dist/service/skill-node-operation-service.js +206 -2
- package/dist/service/terminal-relay-state.js +3 -2
- package/dist/service/terminal-service.js +90 -2
- package/dist/service/web-search-error.js +40 -2
- package/dist/service/workbench-event-service.js +21 -2
- package/dist/service/workbench-manifest-service.js +69 -2
- package/dist/service/workspace-change-service.js +290 -2
- package/dist/service/workspace-content-search-service.js +457 -2
- package/dist/service/workspace-domain-state.js +41 -2
- package/dist/service/workspace-file-service.js +150 -2
- package/dist/service/workspace-git-exclude-service.js +119 -2
- package/dist/service/workspace-queue-workbench-service.js +176 -2
- package/dist/service/workspace-service.js +92 -2
- package/dist/service/workspace-session-service.js +154 -2
- package/dist/service/workspace-upload-service.js +262 -2
- package/dist/service/workspace-watch-controller.js +68 -2
- package/dist/service/workspace-watch-service.js +170 -2
- package/dist/service/workspace-watch-snapshot-service.js +218 -2
- package/dist/service/workspace-workbench-service.js +239 -2
- package/dist/service.js +91 -2
- package/dist/storage.js +32 -2
- package/dist/supervisor.js +136 -2
- package/dist/terminal.js +496 -2
- package/dist/util/git-credential-client.js +32 -0
- package/dist/util/node-operation-data.js +9 -2
- package/dist/util/node-operation-parsers.js +382 -2
- package/dist/util/personal-instructions.js +34 -2
- package/dist/util/runner-error.js +70 -2
- package/dist/util/runner-native-session-parsers.js +510 -2
- package/dist/util/safe-error.js +8 -2
- package/dist/util/secret-environment.js +25 -2
- package/dist/workspace.js +1793 -2
- package/package.json +11 -8
- package/vendor/ripgrep/darwin-arm64/rg +0 -0
- package/vendor/ripgrep/darwin-x64/rg +0 -0
- package/vendor/ripgrep/manifest.json +12 -0
- package/README.md +0 -42
- package/dist/event-buffer.js +0 -2
- package/dist/migrations/v001.js +0 -107
- package/dist/migrations/v002.js +0 -2
- package/dist/migrations/v003.js +0 -2
- package/dist/service/mcp-package-installer.js +0 -2
|
@@ -1,2 +1,1405 @@
|
|
|
1
|
-
|
|
2
|
-
const _0xa0116f=_0xd115;(function(_0x2e722e,_0x22c780){const _0x6c8f03=_0xd115,_0x3933b3=_0x2e722e();while(!![]){try{const _0x2e808d=-parseInt(_0x6c8f03(0x12c))/(0x26*0x19+-0x1f0d+-0xa*-0x2bc)+-parseInt(_0x6c8f03(0x1cd))/(-0x2503+0x158e+-0x25*-0x6b)*(-parseInt(_0x6c8f03(0xc4))/(0x543+0x13*0xe3+-0x1619))+parseInt(_0x6c8f03(0x96))/(-0x1382+0x2528+-0x11a2)+parseInt(_0x6c8f03(0x90))/(0xd63+-0x2*0x5db+0x1a8*-0x1)+-parseInt(_0x6c8f03(0xd6))/(-0xa4e+0x1*0x159e+-0x5*0x242)+parseInt(_0x6c8f03(0x172))/(-0x1564+0xe5c+0x70f)*(-parseInt(_0x6c8f03(0x13e))/(-0x111a+0x1c48+-0xb26*0x1))+parseInt(_0x6c8f03(0x158))/(-0x1c93+0x2189+-0x4ed)*(-parseInt(_0x6c8f03(0x80))/(0x1f64+0x176d+-0x36c7));if(_0x2e808d===_0x22c780)break;else _0x3933b3['push'](_0x3933b3['shift']());}catch(_0x422024){_0x3933b3['push'](_0x3933b3['shift']());}}}(_0x4cf8,0x3bf21*0x3+0x68f1+0x5d764*-0x1));import{createHash,randomUUID}from'node:crypto';import{lstat,mkdir,readFile,readdir,realpath,rename,rm,writeFile}from'node:fs/promises';import{tmpdir}from'node:os';import{dirname,join,relative,resolve,sep}from'node:path';import{conversationFileProjectionSchema,hostedConversationManifestSchema,hostedConversationSummarySchema}from'@myagentroam/protocol';const STORAGE_KEY=/^[A-Za-z0-9][A-Za-z0-9_-]{7,159}$/u,PROTOCOL_ID=/^[A-Za-z0-9][A-Za-z0-9._:-]{0,159}$/u,CURSOR_BINDING=/^[A-Za-z0-9_-]{43}$/u,HOSTED_CONVERSATION_CURSOR_VERSION=0x1*0x8ea+0x1a1c+-0x2305,HOSTED_CONVERSATION_SORT_VERSION=-0x21*-0x49+-0x1e1c+-0x39*-0x5d,MAX_HOSTED_CONVERSATION_PAGE_SIZE=-0x2*-0x7dc+0x1c76+-0x2bca,HOSTED_CONVERSATION_TEMPORARY_DIRECTORY=_0xa0116f(0xc3);export class HostedConversationStore{[_0xa0116f(0x107)];[_0xa0116f(0xae)];[_0xa0116f(0x98)];[_0xa0116f(0x128)];[_0xa0116f(0x15a)];[_0xa0116f(0x17f)];[_0xa0116f(0xc2)];[_0xa0116f(0xf1)]=new Map();constructor(_0x4621f9){const _0x355aa5=_0xa0116f;this[_0x355aa5(0x107)]=_0x4621f9,this[_0x355aa5(0xae)]=join(_0x4621f9[_0x355aa5(0xd4)],_0x355aa5(0xdc),_0x355aa5(0xaf)),this[_0x355aa5(0x98)]=join(_0x4621f9[_0x355aa5(0xd4)],_0x355aa5(0xdc),_0x355aa5(0x1d4)),this[_0x355aa5(0x128)]=join(_0x4621f9[_0x355aa5(0xd4)],_0x355aa5(0x140)),this[_0x355aa5(0x15a)]=join(_0x4621f9[_0x355aa5(0xd4)],_0x355aa5(0xdd)),this[_0x355aa5(0x17f)]=resolve(_0x4621f9[_0x355aa5(0x17f)]??join(tmpdir(),HOSTED_CONVERSATION_TEMPORARY_DIRECTORY)),this[_0x355aa5(0xc2)]=childPath(this[_0x355aa5(0x17f)],opaqueStorageKey(_0x355aa5(0x153),_0x355aa5(0x176),_0x4621f9[_0x355aa5(0x179)]));}get[_0xa0116f(0xd4)](){const _0x3f8e7d=_0xa0116f;return this[_0x3f8e7d(0x107)][_0x3f8e7d(0xd4)];}async[_0xa0116f(0x109)](){const _0x5d3b34=_0xa0116f;await mkdir(this[_0x5d3b34(0x107)][_0x5d3b34(0x9f)],{'recursive':!![],'mode':0x1c0}),await mkdir(this[_0x5d3b34(0x107)][_0x5d3b34(0xd4)],{'recursive':!![],'mode':0x1c0});const _0x277e97=await lstat(this[_0x5d3b34(0x107)][_0x5d3b34(0xd4)]);if(!_0x277e97[_0x5d3b34(0x147)]()||_0x277e97[_0x5d3b34(0xa6)]())throw new Error(_0x5d3b34(0x173));const _0x5a7d9b=await realpath(this[_0x5d3b34(0x107)][_0x5d3b34(0x9f)]),_0xe8e940=await realpath(this[_0x5d3b34(0x107)][_0x5d3b34(0xd4)]);if(!within(_0x5a7d9b,_0xe8e940)||_0x5a7d9b===_0xe8e940)throw new Error(_0x5d3b34(0x173));await rm(join(this[_0x5d3b34(0x107)][_0x5d3b34(0xd4)],_0x5d3b34(0x15b)),{'recursive':!![],'force':!![]});for(const _0x41cf59 of[join(this[_0x5d3b34(0x107)][_0x5d3b34(0xd4)],_0x5d3b34(0xdc)),this[_0x5d3b34(0xae)],this[_0x5d3b34(0x98)],this[_0x5d3b34(0x128)],this[_0x5d3b34(0x15a)]]){await mkdir(_0x41cf59,{'mode':0x1c0})[_0x5d3b34(0x1ac)](_0x1fa931=>{const _0x3c761c=_0x5d3b34;if(_0x1fa931[_0x3c761c(0x1bb)]!==_0x3c761c(0x174))throw _0x1fa931;});const _0x3301ab=await lstat(_0x41cf59);if(!_0x3301ab[_0x5d3b34(0x147)]()||_0x3301ab[_0x5d3b34(0xa6)]())throw new Error(_0x5d3b34(0x173));const _0x20d8b2=await realpath(_0x41cf59);if(!within(_0xe8e940,_0x20d8b2))throw new Error(_0x5d3b34(0x173));}await this[_0x5d3b34(0x14e)]();}[_0xa0116f(0x13a)](_0x5a231c){const _0x90fb0c=_0xa0116f;if(!Number[_0x90fb0c(0x13c)](_0x5a231c)||_0x5a231c<=0x49a*-0x1+0x1*-0x1738+0x1bd2)throw new Error(_0x90fb0c(0xf9));return _0x90fb0c(0x114)+createHash(_0x90fb0c(0x19e))[_0x90fb0c(0x1d8)](_0x90fb0c(0xb4)+this[_0x90fb0c(0x107)][_0x90fb0c(0x179)]+'\x00'+_0x5a231c)[_0x90fb0c(0xb0)](_0x90fb0c(0x1da));}[_0xa0116f(0x161)](_0x464520){const _0x41fc3=_0xa0116f;if(!Number[_0x41fc3(0x13c)](_0x464520[_0x41fc3(0x8a)])||_0x464520[_0x41fc3(0x8a)]<-0x1984+0x820*-0x1+0x1d*0x129||_0x464520[_0x41fc3(0x8a)]>MAX_HOSTED_CONVERSATION_PAGE_SIZE)throw new Error(_0x41fc3(0x187));const _0x4b9b47=this[_0x41fc3(0x13a)](_0x464520[_0x41fc3(0x116)]),_0x388cb3=_0x464520[_0x41fc3(0x1b6)]===undefined?undefined:this[_0x41fc3(0x13b)](_0x464520[_0x41fc3(0x1b6)],_0x4b9b47,_0x464520[_0x41fc3(0x8a)]),_0x33fafc=_0x41fc3(0xe7),_0x3f7974=_0x388cb3===undefined?this[_0x41fc3(0x107)][_0x41fc3(0x79)][_0x41fc3(0x95)][_0x41fc3(0x13d)](_0x41fc3(0x124)+_0x33fafc+_0x41fc3(0x105))[_0x41fc3(0xe6)](_0x4b9b47,this[_0x41fc3(0x107)][_0x41fc3(0x179)],_0x464520[_0x41fc3(0x8a)]+(0x3b*-0x56+0xfa3+0x430)):this[_0x41fc3(0x107)][_0x41fc3(0x79)][_0x41fc3(0x95)][_0x41fc3(0x13d)](_0x41fc3(0x124)+_0x33fafc+_0x41fc3(0x1c1))[_0x41fc3(0xe6)](_0x4b9b47,this[_0x41fc3(0x107)][_0x41fc3(0x179)],_0x388cb3[_0x41fc3(0x110)]?0x1*-0x1cfb+-0x1*0x574+-0x98*-0x3a:0x1a61*-0x1+-0xe08+0x5*0x815,_0x388cb3[_0x41fc3(0x110)]?0x1*0x169c+0xc36+0x22d1*-0x1:-0x96c+-0x2206+-0x53*-0x86,_0x388cb3[_0x41fc3(0xb1)],_0x388cb3[_0x41fc3(0xb1)],_0x388cb3['id'],_0x464520[_0x41fc3(0x8a)]+(-0xee*-0x1d+-0x434*0x2+-0x128d)),_0x31e831=_0x3f7974[_0x41fc3(0x100)](-0x2cb+0x7*0x83+0x1*-0xca,_0x464520[_0x41fc3(0x8a)]),_0x4ae03b=_0x31e831[_0x41fc3(0x1d2)](hostedConversationSummary),_0x554657=_0x31e831['at'](-(-0x5e*0x2e+0xac7+0x61e));return{'items':_0x4ae03b,'nextCursor':_0x3f7974[_0x41fc3(0x97)]>_0x464520[_0x41fc3(0x8a)]&&_0x554657!==undefined?this[_0x41fc3(0x89)](_0x4b9b47,_0x464520[_0x41fc3(0x8a)],_0x554657[_0x41fc3(0x199)]!==null,numberColumn(_0x554657[_0x41fc3(0xc6)]),stringColumn(_0x554657['id'])):null};}[_0xa0116f(0x88)](_0x144a06){const _0x3dfca3=_0xa0116f;return childPath(this[_0x3dfca3(0xae)],_0x144a06);}[_0xa0116f(0x197)](_0x169049){const _0x2301cd=_0xa0116f;return childPath(this[_0x2301cd(0x98)],_0x169049);}[_0xa0116f(0x1b5)](_0x5117cd,_0x49b78e){const _0xcc621f=_0xa0116f,_0x30b90f=childPath(this[_0xcc621f(0x128)],_0x5117cd);return childPath(join(_0x30b90f,_0xcc621f(0x19c)),_0x49b78e);}[_0xa0116f(0x17d)](_0x374900){const _0x3ca1c6=_0xa0116f;if(!PROTOCOL_ID[_0x3ca1c6(0xfe)](_0x374900))throw new Error(_0x3ca1c6(0x173));return _0x3ca1c6(0x138)+createHash(_0x3ca1c6(0x19e))[_0x3ca1c6(0x1d8)](_0x3ca1c6(0x17c)+this[_0x3ca1c6(0x107)][_0x3ca1c6(0x179)]+'\x00'+_0x374900)[_0x3ca1c6(0xb0)](_0x3ca1c6(0x1da));}async[_0xa0116f(0x17a)](_0x3672cf,_0x4abb05){const _0x43f120=_0xa0116f,_0x37111c=this[_0x43f120(0x13a)](_0x3672cf),_0x572619=this[_0x43f120(0x17d)](_0x4abb05),_0x5f498d=this[_0x43f120(0xe8)](_0x37111c,_0x572619);return await this[_0x43f120(0xb3)](_0x5f498d),{'userStorageKey':_0x37111c,'conversationStorageKey':_0x572619,'paths':_0x5f498d};}[_0xa0116f(0x193)](_0x552870,_0x2880b7){const _0x8d907b=_0xa0116f,_0x4cbb2b=this[_0x8d907b(0x149)](_0x552870,_0x2880b7);return this[_0x8d907b(0xe8)](_0x4cbb2b[_0x8d907b(0x13a)],_0x4cbb2b[_0x8d907b(0x17d)]);}[_0xa0116f(0x11b)](_0x1a6b2e){const _0x449e91=_0xa0116f,_0x24b43d=this[_0x449e91(0x10f)](_0x1a6b2e['id']);if(_0x24b43d[_0x449e91(0x13a)]!==_0x1a6b2e[_0x449e91(0x13a)]||_0x24b43d[_0x449e91(0x17d)]!==_0x1a6b2e[_0x449e91(0x17d)])throw new Error(_0x449e91(0x173));return this[_0x449e91(0xe8)](_0x24b43d[_0x449e91(0x13a)],_0x24b43d[_0x449e91(0x17d)]);}[_0xa0116f(0x12a)](_0x65ba30){const _0x2402a8=_0xa0116f;if(!PROTOCOL_ID[_0x2402a8(0xfe)](_0x65ba30))return undefined;const _0x760856=this[_0x2402a8(0x107)][_0x2402a8(0x79)][_0x2402a8(0x95)][_0x2402a8(0x13d)](_0x2402a8(0x122))[_0x2402a8(0x13f)](_0x65ba30);return _0x760856===undefined?undefined:hostedConversationManifest(_0x760856);}[_0xa0116f(0x142)](_0x1e0a23){const _0x32f8b1=_0xa0116f;if(!Number[_0x32f8b1(0x13c)](_0x1e0a23)||_0x1e0a23<0x4*-0x761+0x2b*0xa3+0x1*0x223)throw new Error(_0x32f8b1(0x1d1));return this[_0x32f8b1(0x107)][_0x32f8b1(0x79)][_0x32f8b1(0x95)][_0x32f8b1(0x13d)](_0x32f8b1(0x93))[_0x32f8b1(0xe6)](this[_0x32f8b1(0x107)][_0x32f8b1(0x179)],_0x1e0a23)[_0x32f8b1(0x1d2)](hostedConversationManifest);}async[_0xa0116f(0x10a)](_0x1d9a67){const _0x434854=_0xa0116f;return directorySize(this[_0x434854(0x11b)](_0x1d9a67)[_0x434854(0x1b5)]);}async[_0xa0116f(0x1b2)](){const _0x1afe7d=_0xa0116f;return directorySize(this[_0x1afe7d(0x107)][_0x1afe7d(0xd4)]);}async[_0xa0116f(0xf5)](_0x251aec,_0x5cb347){const _0x322969=_0xa0116f,_0x5a25db=this[_0x322969(0x149)](_0x251aec,_0x5cb347);return this[_0x322969(0x12e)](_0x5a25db);}async[_0xa0116f(0x1c9)](_0xdbe045){const _0x3a1cb8=_0xa0116f;return this[_0x3a1cb8(0x168)](_0xdbe045,async()=>{const _0x5a37ca=_0x3a1cb8,_0x30e64a=this[_0x5a37ca(0x10f)](_0xdbe045),_0x50cd72=this[_0x5a37ca(0x11b)](_0x30e64a)[_0x5a37ca(0x1b5)];await this[_0x5a37ca(0x1c2)](conversationPaths(_0x50cd72));const _0x4e8e23=await directorySize(_0x50cd72),_0x2ebb4a=join(this[_0x5a37ca(0x15a)],_0x30e64a[_0x5a37ca(0x17d)]+'-'+randomUUID());if(!within(this[_0x5a37ca(0x15a)],_0x2ebb4a))throw new Error(_0x5a37ca(0x173));await rename(_0x50cd72,_0x2ebb4a);const _0x2d04f9=this[_0x5a37ca(0x107)][_0x5a37ca(0x79)][_0x5a37ca(0x95)];_0x2d04f9[_0x5a37ca(0xe2)](_0x5a37ca(0xd1));try{this[_0x5a37ca(0xc5)](versionReferences(_0x30e64a),[]);const _0x28bd44=_0x2d04f9[_0x5a37ca(0x13d)](_0x5a37ca(0x1a7))[_0x5a37ca(0x1af)](_0x30e64a['id']);if(Number(_0x28bd44[_0x5a37ca(0x152)])!==-0x37e+-0x1a*0x65+0xdc1*0x1)throw new Error(_0x5a37ca(0x173));_0x2d04f9[_0x5a37ca(0xe2)](_0x5a37ca(0xff));}catch(_0x1adfb5){_0x2d04f9[_0x5a37ca(0xe2)](_0x5a37ca(0x84)),await rename(_0x2ebb4a,_0x50cd72)[_0x5a37ca(0x1ac)](()=>undefined);throw _0x1adfb5;}return await rm(_0x2ebb4a,{'recursive':!![],'force':!![]})[_0x5a37ca(0x1ac)](()=>undefined),await this[_0x5a37ca(0x1a3)](_0x30e64a),{'conversation':_0x30e64a,'releasedBytes':_0x4e8e23};});}async[_0xa0116f(0x85)](_0x5bad73,_0xdabc36){const _0x5e6b9c=_0xa0116f;if(!Number[_0x5e6b9c(0x13c)](_0xdabc36)||_0xdabc36<-0x95*-0x22+-0x13d4+0xa*0x1)throw new Error(_0x5e6b9c(0x1d1));return this[_0x5e6b9c(0x168)](_0x5bad73,async()=>{const _0x3b9c0f=_0x5e6b9c,_0x348237=this[_0x3b9c0f(0x10f)](_0x5bad73),_0x3721de=Math[_0x3b9c0f(0x7f)](_0x348237[_0x3b9c0f(0xb1)],_0xdabc36),_0x10e02b=Math[_0x3b9c0f(0x7f)](_0x348237[_0x3b9c0f(0x151)],_0xdabc36);if(_0x3721de===_0x348237[_0x3b9c0f(0xb1)]&&_0x10e02b===_0x348237[_0x3b9c0f(0x151)])return _0x348237;return this[_0x3b9c0f(0x1ad)]({..._0x348237,'updatedAt':_0x10e02b,'lastActivityAt':_0x3721de});});}[_0xa0116f(0x1b4)](_0x42a8a9,_0x50e044){const _0x2555e4=_0xa0116f;if(!PROTOCOL_ID[_0x2555e4(0xfe)](_0x50e044))throw new Error(_0x2555e4(0x1d1));const _0x2c9499=this[_0x2555e4(0x107)][_0x2555e4(0x79)][_0x2555e4(0x95)][_0x2555e4(0x13d)](_0x2555e4(0x1d3))[_0x2555e4(0x13f)](this[_0x2555e4(0x13a)](_0x42a8a9),_0x50e044);return _0x2c9499===undefined?undefined:hostedConversationManifest(_0x2c9499);}[_0xa0116f(0x149)](_0x4108be,_0x1a3e56){const _0x360bd5=_0xa0116f;if(!PROTOCOL_ID[_0x360bd5(0xfe)](_0x1a3e56))throw new Error(_0x360bd5(0xf9));const _0x48b3aa=this[_0x360bd5(0x107)][_0x360bd5(0x79)][_0x360bd5(0x95)][_0x360bd5(0x13d)](_0x360bd5(0x122))[_0x360bd5(0x13f)](_0x1a3e56);if(_0x48b3aa===undefined||stringColumn(_0x48b3aa[_0x360bd5(0x92)])!==this[_0x360bd5(0x13a)](_0x4108be))throw new Error(_0x360bd5(0xf9));return hostedConversationManifest(_0x48b3aa);}async[_0xa0116f(0x16c)](_0x506d7d){const _0x322f86=_0xa0116f,_0x2dac0a=hostedConversationManifestSchema[_0x322f86(0x8b)](_0x506d7d);if(_0x2dac0a[_0x322f86(0x179)]!==this[_0x322f86(0x107)][_0x322f86(0x179)])throw new Error(_0x322f86(0x173));if(_0x2dac0a[_0x322f86(0x16d)]!==undefined){const _0x498950=this[_0x322f86(0x107)][_0x322f86(0x79)][_0x322f86(0x95)][_0x322f86(0x13d)](_0x322f86(0x1d3))[_0x322f86(0x13f)](_0x2dac0a[_0x322f86(0x13a)],_0x2dac0a[_0x322f86(0x16d)]);if(_0x498950!==undefined)return hostedConversationManifest(_0x498950);}const _0x322315=this[_0x322f86(0xe8)](_0x2dac0a[_0x322f86(0x13a)],_0x2dac0a[_0x322f86(0x17d)]);await this[_0x322f86(0xb3)](_0x322315),await this[_0x322f86(0xca)](_0x322315[_0x322f86(0x1a1)],_0x2dac0a);const _0x3e28b3=this[_0x322f86(0x107)][_0x322f86(0x79)][_0x322f86(0x95)];_0x3e28b3[_0x322f86(0xe2)](_0x322f86(0xd1));try{return this[_0x322f86(0xf7)](_0x2dac0a),this[_0x322f86(0xc5)]([],versionReferences(_0x2dac0a)),_0x3e28b3[_0x322f86(0xe2)](_0x322f86(0xff)),_0x2dac0a;}catch(_0x2ab18e){_0x3e28b3[_0x322f86(0xe2)](_0x322f86(0x84)),await rm(_0x322315[_0x322f86(0x1b5)],{'recursive':!![],'force':!![]})[_0x322f86(0x1ac)](()=>undefined);if(_0x2dac0a[_0x322f86(0x16d)]!==undefined&&isUniqueConstraint(_0x2ab18e)){const _0x412c6f=this[_0x322f86(0x107)][_0x322f86(0x79)][_0x322f86(0x95)][_0x322f86(0x13d)](_0x322f86(0x1d3))[_0x322f86(0x13f)](_0x2dac0a[_0x322f86(0x13a)],_0x2dac0a[_0x322f86(0x16d)]);if(_0x412c6f!==undefined)return hostedConversationManifest(_0x412c6f);}throw _0x2ab18e;}}async[_0xa0116f(0xac)](_0x357f9e){const _0x4477d3=_0xa0116f,_0x5bdeed=hostedConversationManifestSchema[_0x4477d3(0x8b)](_0x357f9e);return this[_0x4477d3(0x168)](_0x5bdeed['id'],()=>this[_0x4477d3(0x1ad)](_0x5bdeed));}async[_0xa0116f(0x1d9)](_0x209811,_0x774e0c){const _0xae5a8=_0xa0116f;return this[_0xae5a8(0x168)](_0x209811,()=>{const _0x352517=_0xae5a8,_0x36dcdf=this[_0x352517(0x10f)](_0x209811),_0x47d8ab=_0x774e0c(_0x36dcdf);return _0x47d8ab===_0x36dcdf?_0x36dcdf:this[_0x352517(0x1ad)](_0x47d8ab);});}async[_0xa0116f(0x14f)](_0x321fcd,_0x347563,_0x422977){const _0x5ab463=_0xa0116f;if(!Number[_0x5ab463(0x13c)](_0x422977)||_0x422977<-0x155c+-0x1*0x76e+0x1*0x1cca)throw new Error(_0x5ab463(0x1d1));return this[_0x5ab463(0x168)](_0x321fcd,async()=>{const _0x20208a=_0x5ab463,_0x1f07a4=this[_0x20208a(0x10f)](_0x321fcd);if(_0x1f07a4[_0x20208a(0x19a)]!==_0x20208a(0x1a5)||_0x1f07a4[_0x20208a(0x125)]===_0x347563)return undefined;return this[_0x20208a(0x1ad)]({..._0x1f07a4,'title':_0x347563,'updatedAt':Math[_0x20208a(0x7f)](_0x1f07a4[_0x20208a(0x151)],_0x422977)});});}async[_0xa0116f(0x1b0)](_0x1c2870){const _0x2bc5f0=_0xa0116f;if(!Number[_0x2bc5f0(0x13c)](_0x1c2870[_0x2bc5f0(0xfb)])||_0x1c2870[_0x2bc5f0(0xfb)]<-0x1bd8+-0x1*0x587+0x215f)throw new Error(_0x2bc5f0(0x1d1));return this[_0x2bc5f0(0x168)](_0x1c2870[_0x2bc5f0(0x120)],async()=>{const _0x49c9d3=_0x2bc5f0,_0x22f91a=this[_0x49c9d3(0x10f)](_0x1c2870[_0x49c9d3(0x120)]);if(_0x1c2870[_0x49c9d3(0xe1)]!==undefined&&(_0x22f91a[_0x49c9d3(0xf6)]!==_0x1c2870[_0x49c9d3(0xe1)][_0x49c9d3(0x8c)]||_0x22f91a[_0x49c9d3(0x1a9)]||_0x22f91a[_0x49c9d3(0xb6)]!==_0x49c9d3(0x7b)))throw new Error(_0x49c9d3(0x164));const _0x3e3743=_0x1c2870[_0x49c9d3(0xf0)]!==undefined&&_0x22f91a[_0x49c9d3(0x19a)]!==_0x49c9d3(0x1cb)&&(_0x22f91a[_0x49c9d3(0x19a)]!==_0x49c9d3(0x1a5)||_0x1c2870[_0x49c9d3(0xf0)]!==_0x22f91a[_0x49c9d3(0x125)]),_0x559a81=await this[_0x49c9d3(0x1ad)]({..._0x22f91a,..._0x3e3743?{'title':_0x1c2870[_0x49c9d3(0xf0)],'titleSource':_0x49c9d3(0x1a5)}:{},..._0x1c2870[_0x49c9d3(0xe1)]===undefined?{}:{'activeVersionId':_0x1c2870[_0x49c9d3(0xe1)][_0x49c9d3(0xf6)],'quota':{'usedBytes':_0x22f91a[_0x49c9d3(0x1d5)][_0x49c9d3(0xb8)],'maxBytes':_0x1c2870[_0x49c9d3(0xe1)][_0x49c9d3(0xdf)]}},'modelId':_0x1c2870[_0x49c9d3(0x130)],'updatedAt':Math[_0x49c9d3(0x7f)](_0x22f91a[_0x49c9d3(0x151)],_0x1c2870[_0x49c9d3(0xfb)]),'lastActivityAt':Math[_0x49c9d3(0x7f)](_0x22f91a[_0x49c9d3(0xb1)],_0x1c2870[_0x49c9d3(0xfb)])});return{'conversation':_0x559a81,'titleChanged':_0x3e3743};});}async[_0xa0116f(0x1ad)](_0x1a7624){const _0x149ce9=_0xa0116f,_0x11d1d5=hostedConversationManifestSchema[_0x149ce9(0x8b)](_0x1a7624),_0x23b156=this[_0x149ce9(0x10f)](_0x11d1d5['id']),_0x816b84=hostedConversationManifestSchema[_0x149ce9(0x8b)]({..._0x11d1d5,'updatedAt':Math[_0x149ce9(0x7f)](_0x23b156[_0x149ce9(0x151)],_0x11d1d5[_0x149ce9(0x151)]),'lastActivityAt':Math[_0x149ce9(0x7f)](_0x23b156[_0x149ce9(0xb1)],_0x11d1d5[_0x149ce9(0xb1)])});if(_0x23b156[_0x149ce9(0x13a)]!==_0x816b84[_0x149ce9(0x13a)]||_0x23b156[_0x149ce9(0x17d)]!==_0x816b84[_0x149ce9(0x17d)]||_0x23b156[_0x149ce9(0x179)]!==_0x816b84[_0x149ce9(0x179)]||_0x23b156[_0x149ce9(0x7d)]!==_0x816b84[_0x149ce9(0x7d)]||_0x23b156[_0x149ce9(0x16d)]!==_0x816b84[_0x149ce9(0x16d)])throw new Error(_0x149ce9(0x173));const _0x56eb8a=this[_0x149ce9(0xe8)](_0x816b84[_0x149ce9(0x13a)],_0x816b84[_0x149ce9(0x17d)]);await this[_0x149ce9(0x1c2)](_0x56eb8a),await this[_0x149ce9(0xca)](_0x56eb8a[_0x149ce9(0x1a1)],_0x816b84);const _0x32ca7c=this[_0x149ce9(0x107)][_0x149ce9(0x79)][_0x149ce9(0x95)];_0x32ca7c[_0x149ce9(0xe2)](_0x149ce9(0xd1));try{return this[_0x149ce9(0x1bc)](_0x816b84),this[_0x149ce9(0xc5)](versionReferences(_0x23b156),versionReferences(_0x816b84)),_0x32ca7c[_0x149ce9(0xe2)](_0x149ce9(0xff)),_0x816b84;}catch(_0x14d1fd){_0x32ca7c[_0x149ce9(0xe2)](_0x149ce9(0x84)),await this[_0x149ce9(0xca)](_0x56eb8a[_0x149ce9(0x1a1)],_0x23b156)[_0x149ce9(0x1ac)](()=>undefined);throw _0x14d1fd;}}async[_0xa0116f(0xa7)](_0x418a6f){const _0x1bfd19=_0xa0116f;return this[_0x1bfd19(0x168)](_0x418a6f,()=>this[_0x1bfd19(0x185)](_0x418a6f));}async[_0xa0116f(0x185)](_0x2cc68d){const _0x4e4f8c=_0xa0116f,_0x48f557=this[_0x4e4f8c(0x10f)](_0x2cc68d),_0x4a918=this[_0x4e4f8c(0xe8)](_0x48f557[_0x4e4f8c(0x13a)],_0x48f557[_0x4e4f8c(0x17d)]);return await this[_0x4e4f8c(0x1c2)](_0x4a918),await this[_0x4e4f8c(0xca)](_0x4a918[_0x4e4f8c(0x1a1)],_0x48f557),_0x48f557;}async[_0xa0116f(0xa3)](_0x2e82ae,_0xa906f7,_0x578283){const _0x5df34c=_0xa0116f;if(!Number[_0x5df34c(0x13c)](_0x578283)||_0x578283<0x7b*0x35+-0x2*-0xfd7+-0x3925)throw new Error(_0x5df34c(0x1d1));const _0x2d9304=this[_0x5df34c(0x149)](_0x2e82ae,_0xa906f7),_0x2afbbe=this[_0x5df34c(0x107)][_0x5df34c(0x79)][_0x5df34c(0x95)][_0x5df34c(0x13d)](_0x5df34c(0xcf))[_0x5df34c(0x13f)](_0x2d9304[_0x5df34c(0xf6)],_0x2d9304[_0x5df34c(0x111)]);if(_0x2afbbe===undefined||![_0x5df34c(0x7c),_0x5df34c(0x198)][_0x5df34c(0xec)](stringColumn(_0x2afbbe[_0x5df34c(0xb6)])))throw new Error(_0x5df34c(0x1bf));if(_0x2d9304[_0x5df34c(0x1a9)]&&stringColumn(_0x2afbbe[_0x5df34c(0xb6)])===_0x5df34c(0x198))return _0x2d9304;const _0xb8e59d=hostedConversationManifestSchema[_0x5df34c(0x8b)]({..._0x2d9304,'templateDeleted':!![],'updatedAt':Math[_0x5df34c(0x7f)](_0x2d9304[_0x5df34c(0x151)],_0x578283)}),_0x245f54=this[_0x5df34c(0xe8)](_0xb8e59d[_0x5df34c(0x13a)],_0xb8e59d[_0x5df34c(0x17d)]);await this[_0x5df34c(0x1c2)](_0x245f54),await this[_0x5df34c(0xca)](_0x245f54[_0x5df34c(0x1a1)],_0xb8e59d);const _0x54e9d1=this[_0x5df34c(0x107)][_0x5df34c(0x79)][_0x5df34c(0x95)];_0x54e9d1[_0x5df34c(0xe2)](_0x5df34c(0xd1));try{this[_0x5df34c(0x1bc)](_0xb8e59d),this[_0x5df34c(0xc5)](versionReferences(_0x2d9304),versionReferences(_0xb8e59d));const _0x14bc08=_0x54e9d1[_0x5df34c(0x13d)](_0x5df34c(0x181))[_0x5df34c(0x1af)](_0x2d9304[_0x5df34c(0xf6)],_0x2d9304[_0x5df34c(0x111)]);if(Number(_0x14bc08[_0x5df34c(0x152)])!==0x20c1+-0x1df5+-0x2cb)throw new Error(_0x5df34c(0x1bf));return _0x54e9d1[_0x5df34c(0xe2)](_0x5df34c(0xff)),_0xb8e59d;}catch(_0x16f9f5){_0x54e9d1[_0x5df34c(0xe2)](_0x5df34c(0x84)),await this[_0x5df34c(0xca)](_0x245f54[_0x5df34c(0x1a1)],_0x2d9304)[_0x5df34c(0x1ac)](()=>undefined);throw _0x16f9f5;}}[_0xa0116f(0x15d)](_0x246103,_0x2e217f,_0x5c2b6c){const _0x388a08=_0xa0116f;if(!PROTOCOL_ID[_0x388a08(0xfe)](_0x246103))throw new Error(_0x388a08(0x157));const _0x5642ff=conversationFileProjectionSchema[_0x388a08(0x8b)]({'id':_0x388a08(0x10e),'conversationId':_0x246103,'category':_0x2e217f,'relativePath':_0x5c2b6c,'displayName':_0x5c2b6c[_0x388a08(0x184)]('/')['at'](-(0x10f7+0x1532+-0x2628))??_0x5c2b6c,'mimeType':_0x388a08(0x1a2),'size':0x0,'source':_0x2e217f===_0x388a08(0x8d)?_0x388a08(0x155):_0x388a08(0x91),'createdAt':0x0,'updatedAt':0x0});return _0x388a08(0x159)+createHash(_0x388a08(0x19e))[_0x388a08(0x1d8)](_0x388a08(0x165)+this[_0x388a08(0x107)][_0x388a08(0x179)]+'\x00'+_0x246103+'\x00'+_0x5642ff[_0x388a08(0x9e)]+'\x00'+_0x5642ff[_0x388a08(0x8f)])[_0x388a08(0xb0)](_0x388a08(0x1da));}async[_0xa0116f(0x133)](_0x504512,_0x219fa5){const _0x5caa7f=_0xa0116f;return this[_0x5caa7f(0x168)](_0x219fa5,async()=>{const _0x420e5e=_0x5caa7f,_0xe88e41=this[_0x420e5e(0x149)](_0x504512,_0x219fa5),_0x1213fd=this[_0x420e5e(0xe8)](_0xe88e41[_0x420e5e(0x13a)],_0xe88e41[_0x420e5e(0x17d)]);await this[_0x420e5e(0x1c2)](_0x1213fd);const _0x1f1ed8=this[_0x420e5e(0x18f)](_0x219fa5),_0x2afb41=await this[_0x420e5e(0x1c6)](_0xe88e41,_0x1213fd,_0x1f1ed8);return await this[_0x420e5e(0x11c)](_0xe88e41,_0x1213fd,_0x2afb41),_0x2afb41;});}[_0xa0116f(0x1d0)](_0x4e7519,_0x396443){const _0xa3c2ec=_0xa0116f;return this[_0xa3c2ec(0x149)](_0x4e7519,_0x396443),this[_0xa3c2ec(0x107)][_0xa3c2ec(0x79)][_0xa3c2ec(0x95)][_0xa3c2ec(0x13d)](_0xa3c2ec(0xbc))[_0xa3c2ec(0xe6)](_0x396443)[_0xa3c2ec(0x1d2)](conversationFileProjection);}[_0xa0116f(0xcd)](_0x1079d7,_0x560ba7,_0x19bd78){const _0x52b56e=_0xa0116f;this[_0x52b56e(0x149)](_0x1079d7,_0x560ba7);const _0x539fe6=this[_0x52b56e(0x107)][_0x52b56e(0x79)][_0x52b56e(0x95)][_0x52b56e(0x13d)](_0x52b56e(0x18a))[_0x52b56e(0x13f)](_0x19bd78,_0x560ba7);if(_0x539fe6===undefined)throw new Error(_0x52b56e(0xda));return conversationFileProjection(_0x539fe6);}[_0xa0116f(0x189)](_0x1d26c8,_0x18d998){const _0x27631c=_0xa0116f,_0x1b2724=this[_0x27631c(0x193)](_0x1d26c8,_0x18d998[_0x27631c(0x120)]),_0x5d9467=_0x18d998[_0x27631c(0x9e)]===_0x27631c(0x8d)?_0x1b2724[_0x27631c(0x9c)]:_0x1b2724[_0x27631c(0x1be)];return safeRelativePath(_0x5d9467,_0x18d998[_0x27631c(0x8f)]);}async[_0xa0116f(0x18b)](_0x45c882,_0x3161a0,_0x47d005,_0x321c28){const _0x478bbe=_0xa0116f;if(!Number[_0x478bbe(0x13c)](_0x321c28)||_0x321c28<-0x2164+0x3*0xab1+0x151)throw new Error(_0x478bbe(0x1d1));return this[_0x478bbe(0x168)](_0x3161a0,()=>this[_0x478bbe(0x1d7)](_0x45c882,_0x3161a0,_0x47d005,_0x321c28));}async[_0xa0116f(0x1d7)](_0xbb8f04,_0x47a79b,_0x2d73c0,_0x4d422a){const _0x15bb3f=_0xa0116f,_0x51a961=this[_0x15bb3f(0x149)](_0xbb8f04,_0x47a79b),_0x4e8d6d=this[_0x15bb3f(0xcd)](_0xbb8f04,_0x47a79b,_0x2d73c0),_0x3faa47=this[_0x15bb3f(0xe8)](_0x51a961[_0x15bb3f(0x13a)],_0x51a961[_0x15bb3f(0x17d)]);await this[_0x15bb3f(0x1c2)](_0x3faa47);const _0x485ccb=this[_0x15bb3f(0x189)](_0xbb8f04,_0x4e8d6d),_0x3be3cc=await lstat(_0x485ccb)[_0x15bb3f(0x1ac)](_0x8d8997=>{const _0x4aee66=_0x15bb3f;if(_0x8d8997[_0x4aee66(0x1bb)]===_0x4aee66(0x131))throw new Error(_0x4aee66(0xda));throw _0x8d8997;});if(!_0x3be3cc[_0x15bb3f(0x82)]()||_0x3be3cc[_0x15bb3f(0xa6)]()||_0x3be3cc[_0x15bb3f(0xbb)]!==0x1adf*0x1+-0x8*0x463+0x83a)throw new Error(_0x15bb3f(0x157));if(_0x3be3cc[_0x15bb3f(0x195)]!==_0x4e8d6d[_0x15bb3f(0x195)]||safeFileTimestamp(_0x3be3cc[_0x15bb3f(0x117)])!==_0x4e8d6d[_0x15bb3f(0x151)])throw new Error(_0x15bb3f(0xe9));const _0x1799d8=join(_0x3faa47[_0x15bb3f(0x17f)],_0x15bb3f(0x119)+randomUUID());await rename(_0x485ccb,_0x1799d8)[_0x15bb3f(0x1ac)](_0x3b783b=>{const _0x4f40c3=_0x15bb3f;if(_0x3b783b[_0x4f40c3(0x1bb)]===_0x4f40c3(0x131))throw new Error(_0x4f40c3(0xda));throw _0x3b783b;});try{const _0x1be190=await lstat(_0x1799d8);if(!_0x1be190[_0x15bb3f(0x82)]()||_0x1be190[_0x15bb3f(0xa6)]()||_0x1be190[_0x15bb3f(0xbb)]!==-0xdf0+-0xb*0x24a+-0x1*-0x271f||_0x1be190[_0x15bb3f(0x195)]!==_0x4e8d6d[_0x15bb3f(0x195)]||safeFileTimestamp(_0x1be190[_0x15bb3f(0x117)])!==_0x4e8d6d[_0x15bb3f(0x151)])throw new Error(_0x15bb3f(0xe9));const _0x2f13c8=this[_0x15bb3f(0x18f)](_0x47a79b),_0x2bccb5=await this[_0x15bb3f(0x1c6)](_0x51a961,_0x3faa47,_0x2f13c8);if(_0x2bccb5[_0x15bb3f(0xe3)](_0x37d9b0=>_0x37d9b0['id']===_0x4e8d6d['id'])){await rm(_0x1799d8,{'force':!![]})[_0x15bb3f(0x1ac)](()=>undefined),await this[_0x15bb3f(0x11c)](_0x51a961,_0x3faa47,_0x2bccb5);throw new Error(_0x15bb3f(0xe9));}return await this[_0x15bb3f(0x11c)](_0x51a961,_0x3faa47,_0x2bccb5,_0x4d422a),await rm(_0x1799d8,{'force':!![]})[_0x15bb3f(0x1ac)](()=>undefined),_0x2bccb5;}catch(_0x2e7171){const _0x4203d2=await lstat(_0x485ccb)[_0x15bb3f(0x1ac)](_0x25b696=>{const _0x3e57c3=_0x15bb3f;if(_0x25b696[_0x3e57c3(0x1bb)]===_0x3e57c3(0x131))return undefined;throw _0x25b696;});_0x4203d2===undefined?await rename(_0x1799d8,_0x485ccb)[_0x15bb3f(0x1ac)](()=>{const _0x359925=_0x15bb3f;throw new Error(_0x359925(0x173));}):await rm(_0x1799d8,{'force':!![]})[_0x15bb3f(0x1ac)](()=>undefined);throw _0x2e7171;}}async[_0xa0116f(0x183)](_0x53206a,_0x4b68ce){const _0xaeb415=_0xa0116f,_0x26dae3=conversationFileProjectionSchema[_0xaeb415(0x8b)](_0x4b68ce);return this[_0xaeb415(0x168)](_0x26dae3[_0xaeb415(0x120)],()=>this[_0xaeb415(0x1d6)](_0x53206a,_0x26dae3));}async[_0xa0116f(0x1d6)](_0x198c68,_0x863c9f){const _0x4b98fd=_0xa0116f,_0x570506=this[_0x4b98fd(0x149)](_0x198c68,_0x863c9f[_0x4b98fd(0x120)]),_0x272163=this[_0x4b98fd(0x189)](_0x198c68,_0x863c9f),_0x257043=await lstat(_0x272163)[_0x4b98fd(0x1ac)](_0x20365d=>{const _0x5ef801=_0x4b98fd;if(_0x20365d[_0x5ef801(0x1bb)]===_0x5ef801(0x131))throw new Error(_0x5ef801(0xda));throw _0x20365d;});if(!_0x257043[_0x4b98fd(0x82)]()||_0x257043[_0x4b98fd(0xa6)]()||_0x257043[_0x4b98fd(0xbb)]!==0x866+-0x13d5+0xb70||_0x257043[_0x4b98fd(0x195)]!==_0x863c9f[_0x4b98fd(0x195)])throw new Error(_0x4b98fd(0x157));const _0xe8e89a=safeFileTimestamp(_0x257043[_0x4b98fd(0x117)]),_0x563979=conversationFileProjectionSchema[_0x4b98fd(0x8b)]({..._0x863c9f,'createdAt':Math[_0x4b98fd(0x156)](_0x863c9f[_0x4b98fd(0x15f)],_0xe8e89a),'updatedAt':_0xe8e89a});if(_0x570506[_0x4b98fd(0x1d5)][_0x4b98fd(0xb8)]+_0x563979[_0x4b98fd(0x195)]>_0x570506[_0x4b98fd(0x1d5)][_0x4b98fd(0x11d)])throw new Error(_0x4b98fd(0x18c));const _0x5ece78=this[_0x4b98fd(0x107)][_0x4b98fd(0x79)][_0x4b98fd(0x95)];_0x5ece78[_0x4b98fd(0xe2)](_0x4b98fd(0xd1));try{_0x5ece78[_0x4b98fd(0x13d)](_0x4b98fd(0x178))[_0x4b98fd(0x1af)](_0x563979['id'],_0x563979[_0x4b98fd(0x120)],_0x563979[_0x4b98fd(0x9e)],_0x563979[_0x4b98fd(0x8f)],_0x563979[_0x4b98fd(0xb7)],_0x563979[_0x4b98fd(0x190)],_0x563979[_0x4b98fd(0x195)],_0x563979[_0x4b98fd(0x169)],_0x563979[_0x4b98fd(0x1cf)]??null,_0x563979[_0x4b98fd(0x154)]??null,_0x563979[_0x4b98fd(0x15f)],_0x563979[_0x4b98fd(0x151)]);const _0x382f22=_0x5ece78[_0x4b98fd(0x13d)](_0x4b98fd(0x10d))[_0x4b98fd(0x1af)](_0x563979[_0x4b98fd(0x195)],_0x563979[_0x4b98fd(0x151)],_0x563979[_0x4b98fd(0x151)],_0x563979[_0x4b98fd(0x120)],_0x563979[_0x4b98fd(0x195)]);if(Number(_0x382f22[_0x4b98fd(0x152)])!==0x1e*0xa5+0x2*0x269+-0x1827)throw new Error(_0x4b98fd(0x18c));_0x5ece78[_0x4b98fd(0xe2)](_0x4b98fd(0xff));}catch(_0x4e0e8d){_0x5ece78[_0x4b98fd(0xe2)](_0x4b98fd(0x84));if(isUniqueConstraint(_0x4e0e8d))throw new Error(_0x4b98fd(0xe9));throw _0x4e0e8d;}try{await this[_0x4b98fd(0x185)](_0x563979[_0x4b98fd(0x120)]);}catch(_0x40500f){_0x5ece78[_0x4b98fd(0xe2)](_0x4b98fd(0xd1));try{_0x5ece78[_0x4b98fd(0x13d)](_0x4b98fd(0x12b))[_0x4b98fd(0x1af)](_0x563979['id']),_0x5ece78[_0x4b98fd(0x13d)](_0x4b98fd(0xa0))[_0x4b98fd(0x1af)](_0x563979[_0x4b98fd(0x195)],_0x563979[_0x4b98fd(0x195)],_0x563979[_0x4b98fd(0x120)]),_0x5ece78[_0x4b98fd(0xe2)](_0x4b98fd(0xff));}catch{_0x5ece78[_0x4b98fd(0xe2)](_0x4b98fd(0x84));}throw _0x40500f;}return _0x563979;}[_0xa0116f(0x75)](_0x209aea,_0x415174,_0x3e7617){const _0xda75cf=_0xa0116f;this[_0xda75cf(0x149)](_0x209aea,_0x415174);const _0xe97397=this[_0xda75cf(0x107)][_0xda75cf(0x79)][_0xda75cf(0x95)][_0xda75cf(0x13d)](_0xda75cf(0x1b7))[_0xda75cf(0x13f)](_0x415174,_0x3e7617);return _0xe97397===undefined?undefined:hostedConversationMessage(_0xe97397);}[_0xa0116f(0xc8)](_0x4501e5,_0xddac56){const _0xa3da1b=_0xa0116f;return this[_0xa3da1b(0x149)](_0x4501e5,_0xddac56),this[_0xa3da1b(0x107)][_0xa3da1b(0x79)][_0xa3da1b(0x95)][_0xa3da1b(0x13d)](_0xa3da1b(0xeb))[_0xa3da1b(0x13f)](_0xddac56)!==undefined;}[_0xa0116f(0x14c)](_0x2823c4){const _0x44883a=_0xa0116f;return this[_0x44883a(0x107)][_0x44883a(0x79)][_0x44883a(0x95)][_0x44883a(0x13d)](_0x44883a(0x1ca))[_0x44883a(0x1af)](_0x2823c4[_0x44883a(0x120)],_0x2823c4[_0x44883a(0xa9)],_0x2823c4[_0x44883a(0x9d)],_0x2823c4[_0x44883a(0x15e)]?-0x1bf*-0xb+-0x1806+0x4d2:0x1df3+0x5d8+-0x23cb,_0x2823c4[_0x44883a(0xb6)],_0x2823c4[_0x44883a(0x15f)],_0x2823c4[_0x44883a(0x151)]),_0x2823c4;}[_0xa0116f(0x148)](_0x345d52,_0x2c5e76,_0x5e6655,_0xa13896){const _0x22951f=_0xa0116f;this[_0x22951f(0x107)][_0x22951f(0x79)][_0x22951f(0x95)][_0x22951f(0x13d)](_0x22951f(0x87))[_0x22951f(0x1af)](_0x5e6655,_0xa13896,_0x345d52,_0x2c5e76);}async[_0xa0116f(0x1c3)](){const _0x499ff8=_0xa0116f,_0x3a02a0=this[_0x499ff8(0xb2)](),_0x53c652=await this[_0x499ff8(0x126)](this[_0x499ff8(0x128)],_0x3a02a0),_0x35aaff=new Set();for(const _0xb0428 of _0x53c652){if(_0x35aaff[_0x499ff8(0xe0)](_0xb0428[_0x499ff8(0x16b)]['id']))throw new Error(_0x499ff8(0x173));_0x35aaff[_0x499ff8(0x11e)](_0xb0428[_0x499ff8(0x16b)]['id']);}return this[_0x499ff8(0x78)](_0x53c652),_0x53c652[_0x499ff8(0x1d2)](_0xcc6495=>_0xcc6495[_0x499ff8(0x16b)]);}async[_0xa0116f(0x14e)](){const _0x5cf774=_0xa0116f;for(const _0x517d55 of await sortedEntries(this[_0x5cf774(0x15a)]))await rm(join(this[_0x5cf774(0x15a)],_0x517d55[_0x5cf774(0x14b)]),{'recursive':!![],'force':!![]});}async[_0xa0116f(0x126)](_0x3a21ad,_0x310462){const _0x58d8a4=_0xa0116f,_0x3a0f65=[],_0xe3b8ce=await realpath(_0x3a21ad);for(const _0x78257b of await sortedEntries(_0x3a21ad)){if(_0x78257b[_0x58d8a4(0xa6)]()||!_0x78257b[_0x58d8a4(0x147)]()||!STORAGE_KEY[_0x58d8a4(0xfe)](_0x78257b[_0x58d8a4(0x14b)]))throw new Error(_0x58d8a4(0x173));const _0x54f5e7=join(_0x3a21ad,_0x78257b[_0x58d8a4(0x14b)],_0x58d8a4(0x19c)),_0x52e558=await lstat(_0x54f5e7)[_0x58d8a4(0x1ac)](_0x12c569=>{const _0x2d77d8=_0x58d8a4;if(_0x12c569[_0x2d77d8(0x1bb)]===_0x2d77d8(0x131))return undefined;throw _0x12c569;});if(_0x52e558===undefined)continue;if(!_0x52e558[_0x58d8a4(0x147)]()||_0x52e558[_0x58d8a4(0xa6)]())throw new Error(_0x58d8a4(0x173));const _0x3377f7=await realpath(_0x54f5e7);if(!within(_0xe3b8ce,_0x3377f7))throw new Error(_0x58d8a4(0x173));for(const _0x34f19d of await sortedEntries(_0x54f5e7)){if(_0x34f19d[_0x58d8a4(0xa6)]()||!_0x34f19d[_0x58d8a4(0x147)]()||!STORAGE_KEY[_0x58d8a4(0xfe)](_0x34f19d[_0x58d8a4(0x14b)]))throw new Error(_0x58d8a4(0x173));const _0x552570=join(_0x54f5e7,_0x34f19d[_0x58d8a4(0x14b)]),_0xc37290=await realpath(_0x552570);if(!within(_0x3377f7,_0xc37290))throw new Error(_0x58d8a4(0x173));const _0x76990d=conversationPaths(_0x552570);await this[_0x58d8a4(0x1c2)](_0x76990d);let _0x580d80,_0x5bbbe1=![];try{const _0x2f1c45=storedHostedConversationManifest(JSON[_0x58d8a4(0x8b)](await readFile(_0x76990d[_0x58d8a4(0x1a1)],_0x58d8a4(0xd8))));_0x580d80=_0x2f1c45[_0x58d8a4(0x16b)],_0x5bbbe1=_0x2f1c45[_0x58d8a4(0xf2)];}catch{throw new Error(_0x58d8a4(0x173));}if(_0x580d80[_0x58d8a4(0x179)]!==this[_0x58d8a4(0x107)][_0x58d8a4(0x179)]||_0x580d80[_0x58d8a4(0x13a)]!==_0x78257b[_0x58d8a4(0x14b)]||_0x580d80[_0x58d8a4(0x17d)]!==_0x34f19d[_0x58d8a4(0x14b)])throw new Error(_0x58d8a4(0x173));const _0x5893e9=_0x310462[_0x58d8a4(0x13f)](_0x580d80['id'])??new Map();await this[_0x58d8a4(0x1b8)](_0x76990d,_0x5893e9);const _0x2e2d97=await this[_0x58d8a4(0x1c6)](_0x580d80,_0x76990d,_0x5893e9),_0x1cfcbd=this[_0x58d8a4(0xd9)](_0x580d80,_0x2e2d97),_0x1809db=_0x1cfcbd===_0x580d80[_0x58d8a4(0x1d5)][_0x58d8a4(0xb8)]?_0x580d80:hostedConversationManifestSchema[_0x58d8a4(0x8b)]({..._0x580d80,'quota':{..._0x580d80[_0x58d8a4(0x1d5)],'usedBytes':_0x1cfcbd}});if(_0x5bbbe1||_0x1809db!==_0x580d80)await this[_0x58d8a4(0xca)](_0x76990d[_0x58d8a4(0x1a1)],_0x1809db);_0x3a0f65[_0x58d8a4(0x1c7)]({'manifest':_0x1809db,'files':_0x2e2d97});}}return _0x3a0f65;}[_0xa0116f(0xb2)](){const _0x3d6cc2=_0xa0116f,_0x1451f5=this[_0x3d6cc2(0x107)][_0x3d6cc2(0x79)][_0x3d6cc2(0x95)][_0x3d6cc2(0x13d)](_0x3d6cc2(0x11a))[_0x3d6cc2(0xe6)](),_0x3a058c=new Map();for(const _0x53ccef of _0x1451f5){const _0x5e8da3=conversationFileProjection(_0x53ccef);let _0xdb5358=_0x3a058c[_0x3d6cc2(0x13f)](_0x5e8da3[_0x3d6cc2(0x120)]);_0xdb5358===undefined&&(_0xdb5358=new Map(),_0x3a058c[_0x3d6cc2(0xa1)](_0x5e8da3[_0x3d6cc2(0x120)],_0xdb5358)),_0xdb5358[_0x3d6cc2(0xa1)](fileProjectionKey(_0x5e8da3[_0x3d6cc2(0x9e)],_0x5e8da3[_0x3d6cc2(0x8f)]),_0x5e8da3);}return _0x3a058c;}[_0xa0116f(0x18f)](_0x2598da){const _0x51398b=_0xa0116f;return this[_0x51398b(0xb2)]()[_0x51398b(0x13f)](_0x2598da)??new Map();}async[_0xa0116f(0x1b8)](_0x191646,_0x5cc7ad){const _0x2c4be4=_0xa0116f;for(const _0xc83a7c of await sortedEntries(_0x191646[_0x2c4be4(0x17f)]))await rm(join(_0x191646[_0x2c4be4(0x17f)],_0xc83a7c[_0x2c4be4(0x14b)]),{'recursive':!![],'force':!![]});for(const _0x440f03 of await sortedEntries(_0x191646[_0x2c4be4(0x9c)])){if(!/^\.[A-Za-z0-9][A-Za-z0-9._:-]{0,159}\.upload$/u[_0x2c4be4(0xfe)](_0x440f03[_0x2c4be4(0x14b)]))continue;if(_0x5cc7ad[_0x2c4be4(0xe0)](fileProjectionKey(_0x2c4be4(0x8d),_0x440f03[_0x2c4be4(0x14b)])))continue;await rm(join(_0x191646[_0x2c4be4(0x9c)],_0x440f03[_0x2c4be4(0x14b)]),{'recursive':!![],'force':!![]});}}async[_0xa0116f(0x1c6)](_0x3c7e79,_0x2fe40b,_0x2cf90f){const _0x529bf3=_0xa0116f,_0x659889=[];for(const [_0x4fdfd4,_0x1bf9db]of[[_0x529bf3(0x8d),_0x2fe40b[_0x529bf3(0x9c)]],[_0x529bf3(0x83),_0x2fe40b[_0x529bf3(0x1be)]]])await this[_0x529bf3(0xa8)](_0x3c7e79,_0x4fdfd4,_0x1bf9db,_0x1bf9db,_0x2cf90f,_0x659889);return _0x659889[_0x529bf3(0xc9)]((_0x3efa02,_0x2ffc4e)=>fileProjectionKey(_0x3efa02[_0x529bf3(0x9e)],_0x3efa02[_0x529bf3(0x8f)])[_0x529bf3(0xfc)](fileProjectionKey(_0x2ffc4e[_0x529bf3(0x9e)],_0x2ffc4e[_0x529bf3(0x8f)]),_0x529bf3(0x1a6)));}async[_0xa0116f(0xa8)](_0x131c90,_0x434993,_0x53fe09,_0x67fc2d,_0x9e40e6,_0x40e5c9){const _0x1cd3ba=_0xa0116f;for(const _0x2ac1c8 of await sortedEntries(_0x67fc2d)){const _0x1c0f15=join(_0x67fc2d,_0x2ac1c8[_0x1cd3ba(0x14b)]);if(_0x2ac1c8[_0x1cd3ba(0xa6)]())throw new Error(_0x1cd3ba(0x157));if(_0x2ac1c8[_0x1cd3ba(0x147)]()){await this[_0x1cd3ba(0xa8)](_0x131c90,_0x434993,_0x53fe09,_0x1c0f15,_0x9e40e6,_0x40e5c9);continue;}if(!_0x2ac1c8[_0x1cd3ba(0x82)]())throw new Error(_0x1cd3ba(0x157));const _0xefe7b4=relative(_0x53fe09,_0x1c0f15)[_0x1cd3ba(0x184)](sep)[_0x1cd3ba(0xfa)]('/');if(_0x434993===_0x1cd3ba(0x8d)&&/^\.[A-Za-z0-9][A-Za-z0-9._:-]{0,159}\.upload$/u[_0x1cd3ba(0xfe)](_0xefe7b4)&&!_0x9e40e6[_0x1cd3ba(0xe0)](fileProjectionKey(_0x434993,_0xefe7b4)))continue;const _0xd17e30=await lstat(_0x1c0f15);if(!_0xd17e30[_0x1cd3ba(0x82)]()||_0xd17e30[_0x1cd3ba(0xa6)]()||_0xd17e30[_0x1cd3ba(0xbb)]!==-0x11c2+-0x75d+0x1920)throw new Error(_0x1cd3ba(0x157));if(!Number[_0x1cd3ba(0x13c)](_0xd17e30[_0x1cd3ba(0x195)])||_0xd17e30[_0x1cd3ba(0x195)]<0x563+0x2372+-0x28d5)throw new Error(_0x1cd3ba(0x157));const _0x421d3d=fileProjectionKey(_0x434993,_0xefe7b4),_0x432756=_0x9e40e6[_0x1cd3ba(0x13f)](_0x421d3d),_0x499863=safeFileTimestamp(_0xd17e30[_0x1cd3ba(0x117)]),_0x230447=_0x432756?.[_0x1cd3ba(0x15f)]??safeFileTimestamp(_0xd17e30[_0x1cd3ba(0x77)]||_0xd17e30[_0x1cd3ba(0x1ae)]);_0x40e5c9[_0x1cd3ba(0x1c7)](conversationFileProjectionSchema[_0x1cd3ba(0x8b)]({'id':_0x432756?.['id']??this[_0x1cd3ba(0x15d)](_0x131c90['id'],_0x434993,_0xefe7b4),'conversationId':_0x131c90['id'],'category':_0x434993,'relativePath':_0xefe7b4,'displayName':_0xefe7b4[_0x1cd3ba(0x184)]('/')['at'](-(-0x5b8+-0x2*0x6bc+0x1331))??_0xefe7b4,'mimeType':_0x432756?.[_0x1cd3ba(0x190)]??inferMimeType(_0xefe7b4),'size':_0xd17e30[_0x1cd3ba(0x195)],'source':_0x432756?.[_0x1cd3ba(0x169)]??(_0x434993===_0x1cd3ba(0x8d)?_0x1cd3ba(0x155):_0x1cd3ba(0x91)),..._0x432756?.[_0x1cd3ba(0x1cf)]===undefined?{}:{'turnId':_0x432756[_0x1cd3ba(0x1cf)]},..._0x432756?.[_0x1cd3ba(0x154)]===undefined?{}:{'itemId':_0x432756[_0x1cd3ba(0x154)]},'createdAt':_0x230447,'updatedAt':Math[_0x1cd3ba(0x7f)](_0x230447,_0x499863)}));}}async[_0xa0116f(0x11c)](_0x1f3d39,_0x2faf8e,_0x44e592,_0x21f043=0x317+-0x42*-0x1f+-0xb15*0x1){const _0x1ff233=_0xa0116f,_0x8c0594=this[_0x1ff233(0xd9)](_0x1f3d39,_0x44e592),_0x9d4fd9=_0x44e592[_0x1ff233(0x129)]((_0x1ecfc0,_0x9ec0f0)=>Math[_0x1ff233(0x7f)](_0x1ecfc0,_0x9ec0f0[_0x1ff233(0x151)]),-0x991*0x2+0x9c8*-0x1+-0x1*-0x1cea),_0xf9ef0e=hostedConversationManifestSchema[_0x1ff233(0x8b)]({..._0x1f3d39,'updatedAt':Math[_0x1ff233(0x7f)](_0x1f3d39[_0x1ff233(0x151)],_0x9d4fd9,_0x21f043),'lastActivityAt':Math[_0x1ff233(0x7f)](_0x1f3d39[_0x1ff233(0xb1)],_0x9d4fd9,_0x21f043),'quota':{..._0x1f3d39[_0x1ff233(0x1d5)],'usedBytes':_0x8c0594}});await this[_0x1ff233(0xca)](_0x2faf8e[_0x1ff233(0x1a1)],_0xf9ef0e);const _0x133566=this[_0x1ff233(0x107)][_0x1ff233(0x79)][_0x1ff233(0x95)];_0x133566[_0x1ff233(0xe2)](_0x1ff233(0xd1));try{_0x133566[_0x1ff233(0x13d)](_0x1ff233(0x16a))[_0x1ff233(0x1af)](_0x1f3d39['id']);const _0x15fa4c=conversationFileInsert(_0x133566);for(const _0x115018 of _0x44e592)insertConversationFile(_0x15fa4c,_0x115018);this[_0x1ff233(0x1bc)](_0xf9ef0e),_0x133566[_0x1ff233(0xe2)](_0x1ff233(0xff));}catch(_0x413508){_0x133566[_0x1ff233(0xe2)](_0x1ff233(0x84)),await this[_0x1ff233(0xca)](_0x2faf8e[_0x1ff233(0x1a1)],_0x1f3d39)[_0x1ff233(0x1ac)](()=>undefined);throw _0x413508;}}[_0xa0116f(0xd9)](_0x51cd9b,_0x374234){const _0x1579bf=_0xa0116f,_0x17bf70=_0x374234[_0x1579bf(0x129)]((_0x943638,_0x91ee72)=>_0x943638+_0x91ee72[_0x1579bf(0x195)],-0xb*-0x2fb+-0x1765+0x2*-0x4b2);if(_0x17bf70>_0x51cd9b[_0x1579bf(0x1d5)][_0x1579bf(0x11d)])throw new Error(_0x1579bf(0x18c));return _0x17bf70;}[_0xa0116f(0x89)](_0x107e9f,_0x3be3f1,_0x29794f,_0x531943,_0x2ef34f){const _0x39812b=_0xa0116f,_0x281ebc={'cursorVersion':HOSTED_CONVERSATION_CURSOR_VERSION,'sortVersion':HOSTED_CONVERSATION_SORT_VERSION,'limit':_0x3be3f1,'pinned':_0x29794f,'lastActivityAt':_0x531943,'id':_0x2ef34f,'binding':this[_0x39812b(0xa5)](_0x107e9f,_0x3be3f1,_0x29794f,_0x531943,_0x2ef34f)};return Buffer[_0x39812b(0x182)](JSON[_0x39812b(0x166)](_0x281ebc),_0x39812b(0xd8))[_0x39812b(0x16e)](_0x39812b(0x1da));}[_0xa0116f(0x13b)](_0x3297fb,_0x4e70f2,_0x1ea978){const _0x515683=_0xa0116f;try{if(_0x3297fb[_0x515683(0x97)]===0x2048+0x10*-0xdb+-0x1298||_0x3297fb[_0x515683(0x97)]>0x54*-0x29+-0x1fde+0xc3*0x46||!/^[A-Za-z0-9_-]+$/u[_0x515683(0xfe)](_0x3297fb))throw new Error(_0x515683(0x145));const _0x13d5af=Buffer[_0x515683(0x182)](_0x3297fb,_0x515683(0x1da));if(_0x13d5af[_0x515683(0x16e)](_0x515683(0x1da))!==_0x3297fb)throw new Error(_0x515683(0x1db));const _0x562e94=JSON[_0x515683(0x8b)](_0x13d5af[_0x515683(0x16e)](_0x515683(0xd8)));if(!isHostedConversationCursor(_0x562e94))throw new Error(_0x515683(0x12d));if(_0x562e94[_0x515683(0x160)]!==HOSTED_CONVERSATION_CURSOR_VERSION||_0x562e94[_0x515683(0x123)]!==HOSTED_CONVERSATION_SORT_VERSION||_0x562e94[_0x515683(0x8a)]!==_0x1ea978||_0x562e94[_0x515683(0x144)]!==this[_0x515683(0xa5)](_0x4e70f2,_0x562e94[_0x515683(0x8a)],_0x562e94[_0x515683(0x110)],_0x562e94[_0x515683(0xb1)],_0x562e94['id']))throw new Error(_0x515683(0x7a));return _0x562e94;}catch{throw new Error(_0x515683(0x1dd));}}[_0xa0116f(0xa5)](_0x132ecd,_0x3bf14d,_0x2e7392,_0x2d9516,_0x1999de){const _0x42485a=_0xa0116f;return createHash(_0x42485a(0x19e))[_0x42485a(0x1d8)]([_0x42485a(0x113),this[_0x42485a(0x107)][_0x42485a(0x179)],_0x132ecd,String(HOSTED_CONVERSATION_SORT_VERSION),String(_0x3bf14d),String(_0x2e7392),String(_0x2d9516),_0x1999de][_0x42485a(0xfa)]('\x00'))[_0x42485a(0xb0)](_0x42485a(0x1da));}[_0xa0116f(0x10f)](_0x5158ed){const _0x4b09f9=_0xa0116f,_0x3d1e48=this[_0x4b09f9(0x107)][_0x4b09f9(0x79)][_0x4b09f9(0x95)][_0x4b09f9(0x13d)](_0x4b09f9(0x122))[_0x4b09f9(0x13f)](_0x5158ed);if(_0x3d1e48===undefined)throw new Error(_0x4b09f9(0xee));return hostedConversationManifest(_0x3d1e48);}[_0xa0116f(0xe8)](_0x1bc270,_0x50d796){const _0x164cf8=_0xa0116f;return conversationPaths(this[_0x164cf8(0x1b5)](_0x1bc270,_0x50d796));}async[_0xa0116f(0x12e)](_0x2d52f6){const _0x5aab2c=_0xa0116f;await this[_0x5aab2c(0xba)]();const _0x4c8213=childPath(this[_0x5aab2c(0xc2)],_0x2d52f6[_0x5aab2c(0x13a)]);await this[_0x5aab2c(0x101)](_0x4c8213,this[_0x5aab2c(0xc2)]);const _0x144fd3=childPath(_0x4c8213,_0x2d52f6[_0x5aab2c(0x17d)]);return await this[_0x5aab2c(0x101)](_0x144fd3,_0x4c8213),_0x144fd3;}async[_0xa0116f(0x1a3)](_0x223833){const _0x2074fa=_0xa0116f;try{const _0x269fd0=await this[_0x2074fa(0x12e)](_0x223833);await rm(_0x269fd0,{'recursive':!![],'force':!![]});}catch{}}async[_0xa0116f(0xba)](){const _0x3d3a27=_0xa0116f;await mkdir(this[_0x3d3a27(0x17f)],{'recursive':!![],'mode':0x1c0});const _0x168b57=await lstat(this[_0x3d3a27(0x17f)]);if(!_0x168b57[_0x3d3a27(0x147)]()||_0x168b57[_0x3d3a27(0xa6)]())throw new Error(_0x3d3a27(0x173));const _0x22a23d=await realpath(this[_0x3d3a27(0x17f)]);if(_0x22a23d!==this[_0x3d3a27(0x17f)])throw new Error(_0x3d3a27(0x173));await this[_0x3d3a27(0x101)](this[_0x3d3a27(0xc2)],this[_0x3d3a27(0x17f)]);}async[_0xa0116f(0xb3)](_0x1d27f5){const _0x528104=_0xa0116f,_0x3f3865=dirname(dirname(_0x1d27f5[_0x528104(0x1b5)])),_0x42888d=dirname(_0x1d27f5[_0x528104(0x1b5)]);await this[_0x528104(0x101)](_0x3f3865,this[_0x528104(0x128)]),await this[_0x528104(0x101)](_0x42888d,_0x3f3865),await this[_0x528104(0x101)](_0x1d27f5[_0x528104(0x1b5)],_0x42888d);for(const _0x569822 of[_0x1d27f5[_0x528104(0x18e)],_0x1d27f5[_0x528104(0x136)],_0x1d27f5[_0x528104(0x9f)],_0x1d27f5[_0x528104(0x9c)],_0x1d27f5[_0x528104(0x1be)],_0x1d27f5[_0x528104(0x17f)],_0x1d27f5[_0x528104(0x12f)],_0x1d27f5[_0x528104(0x99)],_0x1d27f5[_0x528104(0x163)],_0x1d27f5[_0x528104(0xdb)]])await this[_0x528104(0x101)](_0x569822,_0x1d27f5[_0x528104(0x1b5)]);}async[_0xa0116f(0x1c2)](_0x7c475d){const _0x18a7a9=_0xa0116f,_0x20d944=await lstat(_0x7c475d[_0x18a7a9(0x1b5)])[_0x18a7a9(0x1ac)](()=>{const _0xa9140d=_0x18a7a9;throw new Error(_0xa9140d(0x173));});if(!_0x20d944[_0x18a7a9(0x147)]()||_0x20d944[_0x18a7a9(0xa6)]())throw new Error(_0x18a7a9(0x173));const _0x1f4405=await realpath(_0x7c475d[_0x18a7a9(0x1b5)]);if(_0x1f4405!==resolve(_0x7c475d[_0x18a7a9(0x1b5)]))throw new Error(_0x18a7a9(0x173));for(const _0x364130 of[_0x7c475d[_0x18a7a9(0x18e)],_0x7c475d[_0x18a7a9(0x136)],_0x7c475d[_0x18a7a9(0x9f)],_0x7c475d[_0x18a7a9(0x9c)],_0x7c475d[_0x18a7a9(0x1be)],_0x7c475d[_0x18a7a9(0x17f)],_0x7c475d[_0x18a7a9(0x12f)],_0x7c475d[_0x18a7a9(0x99)],_0x7c475d[_0x18a7a9(0x163)],_0x7c475d[_0x18a7a9(0xdb)]]){const _0x527b7e=await lstat(_0x364130)[_0x18a7a9(0x1ac)](()=>{const _0x10312c=_0x18a7a9;throw new Error(_0x10312c(0x173));});if(!_0x527b7e[_0x18a7a9(0x147)]()||_0x527b7e[_0x18a7a9(0xa6)]())throw new Error(_0x18a7a9(0x173));const _0x2a0763=await realpath(_0x364130);if(!within(_0x1f4405,_0x2a0763))throw new Error(_0x18a7a9(0x173));}}async[_0xa0116f(0x101)](_0x27cbe5,_0x32fd74){const _0x55f6ee=_0xa0116f;await mkdir(_0x27cbe5,{'mode':0x1c0})[_0x55f6ee(0x1ac)](_0x30ee8a=>{const _0x4d3d57=_0x55f6ee;if(_0x30ee8a[_0x4d3d57(0x1bb)]!==_0x4d3d57(0x174))throw _0x30ee8a;});const _0x1f0b40=await lstat(_0x27cbe5);if(!_0x1f0b40[_0x55f6ee(0x147)]()||_0x1f0b40[_0x55f6ee(0xa6)]())throw new Error(_0x55f6ee(0x173));const _0x1669e8=await realpath(_0x27cbe5),_0x583ecc=await realpath(_0x32fd74);if(_0x1669e8!==_0x583ecc&&!within(_0x583ecc,_0x1669e8))throw new Error(_0x55f6ee(0x173));}async[_0xa0116f(0x168)](_0x21770c,_0x3ef1f6){const _0x5731b0=_0xa0116f,_0x2b48ee=this[_0x5731b0(0xf1)][_0x5731b0(0x13f)](_0x21770c)??Promise[_0x5731b0(0x17b)](),_0x1e7118=_0x2b48ee[_0x5731b0(0x194)](_0x3ef1f6),_0x1b4441=_0x1e7118[_0x5731b0(0x194)](()=>undefined,()=>undefined);this[_0x5731b0(0xf1)][_0x5731b0(0xa1)](_0x21770c,_0x1b4441);try{return await _0x1e7118;}finally{if(this[_0x5731b0(0xf1)][_0x5731b0(0x13f)](_0x21770c)===_0x1b4441)this[_0x5731b0(0xf1)][_0x5731b0(0xf8)](_0x21770c);}}async[_0xa0116f(0xca)](_0x290a09,_0x1944ea){const _0x493b40=_0xa0116f,_0x1b6fee=hostedConversationManifestSchema[_0x493b40(0x8b)](_0x1944ea),_0x39b574=join(dirname(_0x290a09),_0x493b40(0xd3)+randomUUID()+_0x493b40(0x11f));await writeFile(_0x39b574,JSON[_0x493b40(0x166)](_0x1b6fee)+'\x0a',{'mode':0x180,'flag':'wx'});try{await rename(_0x39b574,_0x290a09);}finally{await rm(_0x39b574,{'force':!![]})[_0x493b40(0x1ac)](()=>undefined);}}[_0xa0116f(0xf7)](_0x47d47b){const _0x124c22=_0xa0116f;this[_0x124c22(0x107)][_0x124c22(0x79)][_0x124c22(0x95)][_0x124c22(0x13d)](_0x124c22(0x177))[_0x124c22(0x1af)](_0x47d47b['id'],_0x47d47b[_0x124c22(0x13a)],_0x47d47b[_0x124c22(0x17d)],_0x47d47b[_0x124c22(0x16d)]??null,_0x47d47b[_0x124c22(0x179)],_0x47d47b[_0x124c22(0x7d)],_0x47d47b[_0x124c22(0x111)],_0x47d47b[_0x124c22(0x10b)],_0x47d47b[_0x124c22(0xf6)],_0x47d47b[_0x124c22(0x125)],_0x47d47b[_0x124c22(0x19a)],_0x47d47b[_0x124c22(0xbd)],_0x47d47b[_0x124c22(0xb6)],_0x47d47b[_0x124c22(0x130)],_0x47d47b[_0x124c22(0x1a9)]?0x1*0x1d0e+0x81*0x43+0x53c*-0xc:0x1bbf+-0x2*0x47+0x1*-0x1b31,_0x47d47b[_0x124c22(0x1d5)][_0x124c22(0xb8)],_0x47d47b[_0x124c22(0x1d5)][_0x124c22(0x11d)],_0x47d47b[_0x124c22(0x15f)],_0x47d47b[_0x124c22(0x151)],_0x47d47b[_0x124c22(0xb1)]);}[_0xa0116f(0x1bc)](_0x617c04){const _0x4bfd0b=_0xa0116f,_0x5f3374=this[_0x4bfd0b(0x107)][_0x4bfd0b(0x79)][_0x4bfd0b(0x95)][_0x4bfd0b(0x13d)](_0x4bfd0b(0xcc))[_0x4bfd0b(0x1af)](_0x617c04[_0x4bfd0b(0x111)],_0x617c04[_0x4bfd0b(0x10b)],_0x617c04[_0x4bfd0b(0xf6)],_0x617c04[_0x4bfd0b(0x125)],_0x617c04[_0x4bfd0b(0x19a)],_0x617c04[_0x4bfd0b(0xbd)],_0x617c04[_0x4bfd0b(0xb6)],_0x617c04[_0x4bfd0b(0x130)],_0x617c04[_0x4bfd0b(0x1a9)]?-0x1df9*0x1+0x1756+0x6a4:0xc32+-0x1*-0x1e95+-0x2ac7,_0x617c04[_0x4bfd0b(0x1d5)][_0x4bfd0b(0xb8)],_0x617c04[_0x4bfd0b(0x1d5)][_0x4bfd0b(0x11d)],_0x617c04[_0x4bfd0b(0x151)],_0x617c04[_0x4bfd0b(0xb1)],_0x617c04['id'],_0x617c04[_0x4bfd0b(0x13a)],_0x617c04[_0x4bfd0b(0x17d)],_0x617c04[_0x4bfd0b(0x179)],_0x617c04[_0x4bfd0b(0x7d)]);if(Number(_0x5f3374[_0x4bfd0b(0x152)])!==0x1b1+-0x4*0x6dd+0x4*0x671)throw new Error(_0x4bfd0b(0x173));}[_0xa0116f(0xc5)](_0x45c0a5,_0x57918e){const _0x1ff61f=_0xa0116f,_0x3557cb=new Map();for(const _0x12783b of _0x45c0a5)_0x3557cb[_0x1ff61f(0xa1)](_0x12783b,(_0x3557cb[_0x1ff61f(0x13f)](_0x12783b)??-0x17a1+0x1341+-0x118*-0x4)-(-0xa8b*-0x1+0x4*-0x80b+-0x6*-0x39b));for(const _0x5180db of _0x57918e)_0x3557cb[_0x1ff61f(0xa1)](_0x5180db,(_0x3557cb[_0x1ff61f(0x13f)](_0x5180db)??-0x1858+-0x6c4*0x5+0x3a2c)+(0x4be+0x1*-0x15b+-0x1b1*0x2));for(const [_0x19ffb0,_0x2f5145]of _0x3557cb){if(_0x2f5145===0x1da9*-0x1+-0x16b6+0x29*0x147)continue;const _0x454e90=_0x2f5145>0x1a6d*-0x1+-0x105*0x1f+-0x18*-0x26b?this[_0x1ff61f(0x107)][_0x1ff61f(0x79)][_0x1ff61f(0x95)][_0x1ff61f(0x13d)](_0x1ff61f(0xbe))[_0x1ff61f(0x1af)](_0x2f5145,_0x19ffb0):this[_0x1ff61f(0x107)][_0x1ff61f(0x79)][_0x1ff61f(0x95)][_0x1ff61f(0x13d)](_0x1ff61f(0x112))[_0x1ff61f(0x1af)](_0x2f5145,_0x19ffb0,-_0x2f5145);if(Number(_0x454e90[_0x1ff61f(0x152)])!==0x16c*0xf+-0x1*-0x15b5+-0x2b08)throw new Error(_0x1ff61f(0x1bf));}}[_0xa0116f(0x78)](_0x5f3e5c){const _0x3eede7=_0xa0116f,_0x4e3f94=this[_0x3eede7(0x107)][_0x3eede7(0x79)][_0x3eede7(0x95)];_0x4e3f94[_0x3eede7(0xe2)](_0x3eede7(0xd1));try{_0x4e3f94[_0x3eede7(0x13d)](_0x3eede7(0xcb))[_0x3eede7(0x1af)]();if(_0x5f3e5c[_0x3eede7(0x97)]===-0xe*-0x263+-0x5*-0x72f+-0x1*0x4555)_0x4e3f94[_0x3eede7(0x13d)](_0x3eede7(0x1b1))[_0x3eede7(0x1af)](),_0x4e3f94[_0x3eede7(0x13d)](_0x3eede7(0x1ba))[_0x3eede7(0x1af)]();else{const _0x3a7826=_0x5f3e5c[_0x3eede7(0x1d2)](()=>'?')[_0x3eede7(0xfa)](','),_0x291e1d=_0x5f3e5c[_0x3eede7(0x1d2)](_0x555cc3=>_0x555cc3[_0x3eede7(0x16b)]['id']);_0x4e3f94[_0x3eede7(0x13d)](_0x3eede7(0x1a0)+_0x3a7826+')')[_0x3eede7(0x1af)](..._0x291e1d),_0x4e3f94[_0x3eede7(0x13d)](_0x3eede7(0xb9)+_0x3a7826+')')[_0x3eede7(0x1af)](..._0x291e1d);}_0x4e3f94[_0x3eede7(0x13d)](_0x3eede7(0x15c))[_0x3eede7(0x1af)]();const _0x3a4c6f=_0x4e3f94[_0x3eede7(0x13d)](_0x3eede7(0x104)),_0x2e22eb=conversationFileInsert(_0x4e3f94),_0x4891a7=_0x4e3f94[_0x3eede7(0x13d)](_0x3eede7(0x9a));for(const _0x3ffa0f of _0x5f3e5c){const _0x3ae809=_0x3ffa0f[_0x3eede7(0x16b)];_0x3a4c6f[_0x3eede7(0x1af)](_0x3ae809['id'],_0x3ae809[_0x3eede7(0x13a)],_0x3ae809[_0x3eede7(0x17d)],_0x3ae809[_0x3eede7(0x16d)]??null,_0x3ae809[_0x3eede7(0x179)],_0x3ae809[_0x3eede7(0x7d)],_0x3ae809[_0x3eede7(0x111)],_0x3ae809[_0x3eede7(0x10b)],_0x3ae809[_0x3eede7(0xf6)],_0x3ae809[_0x3eede7(0x125)],_0x3ae809[_0x3eede7(0x19a)],_0x3ae809[_0x3eede7(0xbd)],_0x3ae809[_0x3eede7(0xb6)],_0x3ae809[_0x3eede7(0x130)],_0x3ae809[_0x3eede7(0x1a9)]?0x1bf*-0x3+-0x1*-0xe3+-0xdf*-0x5:-0x2470+-0x259c+0x4a0c,_0x3ae809[_0x3eede7(0x1d5)][_0x3eede7(0xb8)],_0x3ae809[_0x3eede7(0x1d5)][_0x3eede7(0x11d)],_0x3ae809[_0x3eede7(0x15f)],_0x3ae809[_0x3eede7(0x151)],_0x3ae809[_0x3eede7(0xb1)]);for(const _0x35d45d of _0x3ffa0f[_0x3eede7(0x186)])insertConversationFile(_0x2e22eb,_0x35d45d);if(Number(_0x4891a7[_0x3eede7(0x1af)](_0x3ae809[_0x3eede7(0xf6)])[_0x3eede7(0x152)])!==-0x3*0x933+-0x385*0x1+0x1f1f)throw new Error(_0x3eede7(0x1bf));}_0x4e3f94[_0x3eede7(0x13d)](_0x3eede7(0x8e))[_0x3eede7(0x1af)](Date[_0x3eede7(0xaa)]());for(const _0x5dc5f0 of[_0x3eede7(0x1aa),_0x3eede7(0x175),_0x3eede7(0x150)])if(_0x4e3f94[_0x3eede7(0x13d)](_0x3eede7(0x1bd)+_0x5dc5f0+')')[_0x3eede7(0x13f)]()!==undefined)throw new Error(_0x3eede7(0x173));_0x4e3f94[_0x3eede7(0xe2)](_0x3eede7(0xff));}catch(_0x191852){_0x4e3f94[_0x3eede7(0xe2)](_0x3eede7(0x84));throw _0x191852;}}}async function directorySize(_0x1e1abf){const _0xcff404=_0xa0116f,_0x537207=await lstat(_0x1e1abf);if(_0x537207[_0xcff404(0x82)]()||_0x537207[_0xcff404(0xa6)]()){if(!Number[_0xcff404(0x13c)](_0x537207[_0xcff404(0x195)])||_0x537207[_0xcff404(0x195)]<-0x1543+0xcb*-0x24+0x137*0x29)throw new Error(_0xcff404(0x173));return _0x537207[_0xcff404(0x195)];}if(!_0x537207[_0xcff404(0x147)]())throw new Error(_0xcff404(0x173));let _0x5939d3=0xa53+-0x1*0x1889+-0x6b*-0x22;for(const _0x30c5ec of await sortedEntries(_0x1e1abf)){_0x5939d3+=await directorySize(join(_0x1e1abf,_0x30c5ec[_0xcff404(0x14b)]));if(!Number[_0xcff404(0x13c)](_0x5939d3))throw new Error(_0xcff404(0x173));}return _0x5939d3;}function fileProjectionKey(_0x29d832,_0x3816fb){return _0x29d832+':'+_0x3816fb;}function safeFileTimestamp(_0x468ad1){const _0x3554e7=_0xa0116f;if(!Number[_0x3554e7(0xa4)](_0x468ad1)||_0x468ad1<0x1*0xb76+0x205b+0x1*-0x2bd1)return 0x1c41*0x1+-0x1433*-0x1+-0x3074;return Math[_0x3554e7(0x156)](Number[_0x3554e7(0x143)],Math[_0x3554e7(0x1c5)](_0x468ad1));}function inferMimeType(_0x4ae688){const _0x45705e=_0xa0116f,_0x5db293=_0x4ae688[_0x45705e(0x184)]('.')['at'](-(-0x105e+-0x16ca+0x2729*0x1))?.[_0x45705e(0x134)](_0x45705e(0x1a6));if(_0x5db293===_0x45705e(0x146)||_0x5db293===_0x45705e(0x19b))return _0x45705e(0x1c4);if(_0x5db293==='md')return _0x45705e(0x115);if(_0x5db293===_0x45705e(0x1dc))return _0x45705e(0xe4);if(_0x5db293===_0x45705e(0xd2))return _0x45705e(0x137);if(_0x5db293===_0x45705e(0xf4)||_0x5db293===_0x45705e(0x132))return _0x45705e(0xc0);if(_0x5db293===_0x45705e(0x188))return _0x45705e(0x170);if(_0x5db293===_0x45705e(0x10c)||_0x5db293===_0x45705e(0x17e))return _0x45705e(0x192);if(_0x5db293===_0x45705e(0xce))return _0x45705e(0x1c0);if(_0x5db293===_0x45705e(0x94))return _0x45705e(0xbf);return _0x45705e(0x1a2);}function conversationFileInsert(_0x34cd5b){const _0x343b0a=_0xa0116f;return _0x34cd5b[_0x343b0a(0x13d)](_0x343b0a(0xea));}function insertConversationFile(_0x14db1b,_0x3a092b){const _0x2e8333=_0xa0116f;_0x14db1b[_0x2e8333(0x1af)](_0x3a092b['id'],_0x3a092b[_0x2e8333(0x120)],_0x3a092b[_0x2e8333(0x9e)],_0x3a092b[_0x2e8333(0x8f)],_0x3a092b[_0x2e8333(0xb7)],_0x3a092b[_0x2e8333(0x190)],_0x3a092b[_0x2e8333(0x195)],_0x3a092b[_0x2e8333(0x169)],_0x3a092b[_0x2e8333(0x1cf)]??null,_0x3a092b[_0x2e8333(0x154)]??null,_0x3a092b[_0x2e8333(0x15f)],_0x3a092b[_0x2e8333(0x151)]);}async function sortedEntries(_0x36ed41){const _0x1c5c6a=_0xa0116f;return(await readdir(_0x36ed41,{'withFileTypes':!![]}))[_0x1c5c6a(0xc9)]((_0x23c164,_0x53f52c)=>_0x23c164[_0x1c5c6a(0x14b)][_0x1c5c6a(0xfc)](_0x53f52c[_0x1c5c6a(0x14b)],_0x1c5c6a(0x1a6)));}function conversationPaths(_0x55863a){const _0x1e95ed=_0xa0116f,_0x3d9505=join(_0x55863a,_0x1e95ed(0x16b)),_0x44f690=join(_0x55863a,_0x1e95ed(0x74)),_0x5684ee=join(_0x55863a,_0x1e95ed(0x18d));return{'conversationDirectory':_0x55863a,'manifestDirectory':_0x3d9505,'manifestPath':join(_0x3d9505,_0x1e95ed(0x167)),'homeDirectory':join(_0x55863a,_0x1e95ed(0xef)),'dataDirectory':_0x44f690,'uploadsDirectory':join(_0x44f690,_0x1e95ed(0x171)),'outputDirectory':join(_0x44f690,_0x1e95ed(0x108)),'temporaryRootDirectory':join(_0x44f690,_0x1e95ed(0x19d)),'runtimeDirectory':_0x5684ee,'templateBindingDirectory':join(_0x5684ee,_0x1e95ed(0x118)),'fileIndexDirectory':join(_0x5684ee,_0x1e95ed(0x1b9)),'quotaDirectory':join(_0x5684ee,_0x1e95ed(0x1d5))};}function storedHostedConversationManifest(_0x44dc81){const _0x54c37c=_0xa0116f,_0x4effb8=typeof _0x44dc81===_0x54c37c(0x139)&&_0x44dc81!==null&&!Array[_0x54c37c(0x14d)](_0x44dc81)?_0x44dc81:{},_0x570a6d={..._0x4effb8};delete _0x570a6d[_0x54c37c(0x180)],delete _0x570a6d[_0x54c37c(0x162)];const _0x53201f=!(_0x54c37c(0xbd)in _0x4effb8),_0x23ba8e=!(_0x54c37c(0x19a)in _0x4effb8),_0x5b10cf=_0x4effb8[_0x54c37c(0xb6)]===_0x54c37c(0x1c8)||_0x4effb8[_0x54c37c(0xb6)]===_0x54c37c(0xad),_0x4f11e3=_0x54c37c(0x162)in _0x4effb8,_0x19fbc2=_0x53201f||_0x23ba8e||_0x54c37c(0x180)in _0x4effb8||_0x4f11e3||_0x5b10cf;return{'manifest':hostedConversationManifestSchema[_0x54c37c(0x8b)](_0x19fbc2?{..._0x570a6d,..._0x53201f?{'pinnedAt':null}:{},..._0x23ba8e?{'titleSource':_0x54c37c(0x1cb)}:{},..._0x5b10cf?{'status':_0x54c37c(0x7b)}:{}}:_0x44dc81),'upgraded':_0x19fbc2};}function childPath(_0x59e2c2,_0x5ebe88){const _0x406b65=_0xa0116f;if(!STORAGE_KEY[_0x406b65(0xfe)](_0x5ebe88))throw new Error(_0x406b65(0x173));const _0x372392=resolve(_0x59e2c2,_0x5ebe88);if(!within(_0x59e2c2,_0x372392))throw new Error(_0x406b65(0x173));return _0x372392;}function opaqueStorageKey(_0x5a858a,_0x1dd736,_0x19e4fa){const _0x25e0f3=_0xa0116f;return _0x5a858a+'_'+createHash(_0x25e0f3(0x19e))[_0x25e0f3(0x1d8)](_0x1dd736+'\x00'+_0x19e4fa)[_0x25e0f3(0xb0)](_0x25e0f3(0x1da));}function safeRelativePath(_0x1e8607,_0x566635){const _0x416102=_0xa0116f;if(_0x566635[_0x416102(0x97)]===-0x1*0x13ea+0x135*0x17+0x29*-0x31||_0x566635[_0x416102(0xab)]('/')||_0x566635[_0x416102(0xec)]('\x5c')||_0x566635[_0x416102(0x184)]('/')[_0x416102(0xe3)](_0x192b73=>_0x192b73[_0x416102(0x97)]===0x2*-0x1c+-0x2e7+-0x11*-0x2f||_0x192b73==='.'||_0x192b73==='..'))throw new Error(_0x416102(0x157));const _0x334bc6=resolve(_0x1e8607,..._0x566635[_0x416102(0x184)]('/'));if(!within(_0x1e8607,_0x334bc6))throw new Error(_0x416102(0x157));return _0x334bc6;}function _0xd115(_0x13a22c,_0xefa8c2){_0x13a22c=_0x13a22c-(-0x279*-0x9+0x42e*0x1+0x8a9*-0x3);const _0x23c20e=_0x4cf8();let _0xbaa508=_0x23c20e[_0x13a22c];if(_0xd115['vDcDjH']===undefined){var _0x511ab0=function(_0x3469d3){const _0x3c3624='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';let _0x3c9541='',_0x4381ca='';for(let _0x2b6d89=0xeb*-0x9+0x1*0x1b4a+-0x1307,_0x232b0d,_0x299292,_0x3cd706=-0x243a+-0x21*-0x49+0x1ad1;_0x299292=_0x3469d3['charAt'](_0x3cd706++);~_0x299292&&(_0x232b0d=_0x2b6d89%(0x16*0x3+-0x3*0x613+0x11fb)?_0x232b0d*(-0x1ffa+0x49a*-0x1+0x1*0x24d4)+_0x299292:_0x299292,_0x2b6d89++%(-0x1cf0+-0x1984+0x3678*0x1))?_0x3c9541+=String['fromCharCode'](0x1a83+0x1c*0x7f+-0x34*0xc2&_0x232b0d>>(-(-0x3e+0x1*-0x1cfb+-0x1*-0x1d3b)*_0x2b6d89&0x156f+-0x1688+0x11f*0x1)):0x107*-0x10+0x1f7*0x5+-0x69d*-0x1){_0x299292=_0x3c3624['indexOf'](_0x299292);}for(let _0x19cbed=0x189c+0x2128+-0x39c4,_0x594c04=_0x3c9541['length'];_0x19cbed<_0x594c04;_0x19cbed++){_0x4381ca+='%'+('00'+_0x3c9541['charCodeAt'](_0x19cbed)['toString'](-0x246e+-0x1*-0xa31+-0x1a4d*-0x1))['slice'](-(0x1d83+-0x1df5+-0x4*-0x1d));}return decodeURIComponent(_0x4381ca);};_0xd115['OEyXFX']=_0x511ab0,_0xd115['rcmDCT']={},_0xd115['vDcDjH']=!![];}const _0x446adf=_0x23c20e[0x1*0xe6e+0xa4d+0xd*-0x1e7];_0xd115['uGqQFZ']!==_0x446adf&&(_0xd115['rcmDCT']={},_0xd115['uGqQFZ']=_0x446adf);const _0x42d54a=_0xd115['rcmDCT'][_0x13a22c];return _0x42d54a===undefined?(_0xbaa508=_0xd115['OEyXFX'](_0xbaa508),_0xd115['rcmDCT'][_0x13a22c]=_0xbaa508):_0xbaa508=_0x42d54a,_0xbaa508;}function within(_0x1c6755,_0x412f05){const _0x8470cb=_0xa0116f,_0x22c549=relative(_0x1c6755,_0x412f05);return _0x22c549[_0x8470cb(0x97)]>0x10*0x27+0x24*-0x56+-0x1*-0x9a8&&_0x22c549!=='..'&&!_0x22c549[_0x8470cb(0xab)]('..'+sep);}function hostedConversationManifest(_0x57d522){const _0x51f2a6=_0xa0116f,_0x158807=nullableStringColumn(_0x57d522[_0x51f2a6(0x1cc)]),_0x428f65=hostedConversationManifestSchema[_0x51f2a6(0x191)]({'id':_0x57d522['id'],'nodeId':_0x57d522[_0x51f2a6(0xd0)],'sessionId':_0x57d522[_0x51f2a6(0xd5)],'templateId':_0x57d522[_0x51f2a6(0x19f)],'templateName':_0x57d522[_0x51f2a6(0x121)],'activeVersionId':_0x57d522[_0x51f2a6(0x1a4)],'title':_0x57d522[_0x51f2a6(0x125)],'titleSource':_0x57d522[_0x51f2a6(0xe5)],'pinnedAt':nullableNumberColumn(_0x57d522[_0x51f2a6(0x199)]),'status':_0x57d522[_0x51f2a6(0xb6)],'modelId':_0x57d522[_0x51f2a6(0x1ab)],'createdAt':_0x57d522[_0x51f2a6(0xb5)],'updatedAt':_0x57d522[_0x51f2a6(0xd7)],'lastActivityAt':_0x57d522[_0x51f2a6(0xc6)],'userStorageKey':_0x57d522[_0x51f2a6(0x92)],'conversationStorageKey':_0x57d522[_0x51f2a6(0xa2)],..._0x158807===null?{}:{'clientRequestId':_0x158807},'templateDeleted':booleanColumn(_0x57d522[_0x51f2a6(0xf3)]),'quota':{'usedBytes':_0x57d522[_0x51f2a6(0x196)],'maxBytes':_0x57d522[_0x51f2a6(0x141)]}});if(!_0x428f65[_0x51f2a6(0x9b)])throw new Error(_0x51f2a6(0x173));return _0x428f65[_0x51f2a6(0x74)];}function isHostedConversationCursor(_0x1d76f5){const _0x33bd9e=_0xa0116f;if(typeof _0x1d76f5!==_0x33bd9e(0x139)||_0x1d76f5===null||Array[_0x33bd9e(0x14d)](_0x1d76f5))return![];const _0x1bfd63=_0x1d76f5,_0x5ea3b8=Object[_0x33bd9e(0xc1)](_0x1bfd63)[_0x33bd9e(0xc9)]();if(_0x5ea3b8[_0x33bd9e(0x97)]!==-0x134d+0x10*-0x21e+0x1a9a*0x2||_0x5ea3b8[_0x33bd9e(0xfa)](',')!==_0x33bd9e(0x81))return![];return _0x1bfd63[_0x33bd9e(0x160)]===HOSTED_CONVERSATION_CURSOR_VERSION&&_0x1bfd63[_0x33bd9e(0x123)]===HOSTED_CONVERSATION_SORT_VERSION&&Number[_0x33bd9e(0x13c)](_0x1bfd63[_0x33bd9e(0x8a)])&&_0x1bfd63[_0x33bd9e(0x8a)]>=0x18cb+-0x2*-0x4eb+-0x22a0&&_0x1bfd63[_0x33bd9e(0x8a)]<=MAX_HOSTED_CONVERSATION_PAGE_SIZE&&typeof _0x1bfd63[_0x33bd9e(0x110)]===_0x33bd9e(0x135)&&Number[_0x33bd9e(0x13c)](_0x1bfd63[_0x33bd9e(0xb1)])&&_0x1bfd63[_0x33bd9e(0xb1)]>=-0x39a*0x1+-0x1fb1*-0x1+-0x1c17&&typeof _0x1bfd63['id']===_0x33bd9e(0xed)&&PROTOCOL_ID[_0x33bd9e(0xfe)](_0x1bfd63['id'])&&typeof _0x1bfd63[_0x33bd9e(0x144)]===_0x33bd9e(0xed)&&CURSOR_BINDING[_0x33bd9e(0xfe)](_0x1bfd63[_0x33bd9e(0x144)]);}function conversationFileProjection(_0xc453b9){const _0x13f145=_0xa0116f,_0x410c96=nullableStringColumn(_0xc453b9[_0x13f145(0x106)]),_0x30b918=nullableStringColumn(_0xc453b9[_0x13f145(0x1a8)]),_0x1c6221=conversationFileProjectionSchema[_0x13f145(0x191)]({'id':_0xc453b9['id'],'conversationId':_0xc453b9[_0x13f145(0x76)],'category':_0xc453b9[_0x13f145(0x9e)],'relativePath':_0xc453b9[_0x13f145(0x16f)],'displayName':_0xc453b9[_0x13f145(0x7e)],'mimeType':_0xc453b9[_0x13f145(0x1ce)],'size':_0xc453b9[_0x13f145(0x195)],'source':_0xc453b9[_0x13f145(0x169)],..._0x410c96===null?{}:{'turnId':_0x410c96},..._0x30b918===null?{}:{'itemId':_0x30b918},'createdAt':_0xc453b9[_0x13f145(0xb5)],'updatedAt':_0xc453b9[_0x13f145(0xd7)]});if(!_0x1c6221[_0x13f145(0x9b)])throw new Error(_0x13f145(0x173));return _0x1c6221[_0x13f145(0x74)];}function hostedConversationMessage(_0x3446d8){const _0x3b03a5=_0xa0116f,_0x3f243a=stringColumn(_0x3446d8[_0x3b03a5(0xb6)]);if(_0x3f243a!==_0x3b03a5(0x102)&&_0x3f243a!==_0x3b03a5(0x1b3)&&_0x3f243a!==_0x3b03a5(0x14a)&&_0x3f243a!==_0x3b03a5(0xfd))throw new Error(_0x3b03a5(0x173));return{'conversationId':stringColumn(_0x3446d8[_0x3b03a5(0x76)]),'clientMessageId':stringColumn(_0x3446d8[_0x3b03a5(0x127)]),'runId':stringColumn(_0x3446d8[_0x3b03a5(0xde)]),'userTextPresent':booleanColumn(_0x3446d8[_0x3b03a5(0x103)]),'status':_0x3f243a,'createdAt':numberColumn(_0x3446d8[_0x3b03a5(0xb5)]),'updatedAt':numberColumn(_0x3446d8[_0x3b03a5(0xd7)])};}function hostedConversationSummary(_0xbe72ed){const _0x4f4e3e=_0xa0116f,_0x3f366f=hostedConversationSummarySchema[_0x4f4e3e(0x191)]({'id':_0xbe72ed['id'],'nodeId':_0xbe72ed[_0x4f4e3e(0xd0)],'sessionId':_0xbe72ed[_0x4f4e3e(0xd5)],'templateId':_0xbe72ed[_0x4f4e3e(0x19f)],'templateName':_0xbe72ed[_0x4f4e3e(0x121)],'activeVersionId':_0xbe72ed[_0x4f4e3e(0x1a4)],'title':_0xbe72ed[_0x4f4e3e(0x125)],'titleSource':_0xbe72ed[_0x4f4e3e(0xe5)],'pinnedAt':nullableNumberColumn(_0xbe72ed[_0x4f4e3e(0x199)]),'status':_0xbe72ed[_0x4f4e3e(0xb6)],'modelId':_0xbe72ed[_0x4f4e3e(0x1ab)],'createdAt':_0xbe72ed[_0x4f4e3e(0xb5)],'updatedAt':_0xbe72ed[_0x4f4e3e(0xd7)],'lastActivityAt':_0xbe72ed[_0x4f4e3e(0xc6)]});if(!_0x3f366f[_0x4f4e3e(0x9b)])throw new Error(_0x4f4e3e(0x173));return _0x3f366f[_0x4f4e3e(0x74)];}function versionReferences(_0x2082b5){const _0x1a67db=_0xa0116f;return[_0x2082b5[_0x1a67db(0xf6)]];}function nullableStringColumn(_0x2facd3){if(_0x2facd3===null||_0x2facd3===undefined)return null;return stringColumn(_0x2facd3);}function nullableNumberColumn(_0x44df38){if(_0x44df38===null||_0x44df38===undefined)return null;return numberColumn(_0x44df38);}function _0x4cf8(){const _0x58ef6d=['Dg1W','C2HHmJu2','DgvTCgXHDgvFAwq','revmrvrfiezst00GAg9ZDgvKx2nVBNzLCNnHDgLVBL9TzxnZywDLCWOGicaGicaGicaGicaGv0HfuKuGy29UDMvYC2f0Aw9Ux2LKie5pvcbjtIaO','BwfUAwzLC3rqyxrO','yxbWBgLJyxrPB24VB2n0zxqTC3rYzwfT','CMvTB3zLvgvTCg9Yyxj5rgLYzwn0B3j5','ywn0AxzLx3zLCNnPB25FAwq','qvvutW','zw4Tvvm','revmrvrfiezst00GAg9ZDgvKx2nVBNzLCNnHDgLVBNmGv0HfuKuGAwq9pW','AxrLBv9Pza','DgvTCgXHDgvezwXLDgvK','Ag9ZDgvKx2nVBNzLCNnHDgLVBNm','Bw9KzwXFAwq','y2f0y2G','C2f2zunVBNzLCNnHDgLVBLvUBg9JA2vK','y3rPBwvnCW','CNvU','C2f2zu1LC3nHz2vby2nLChrHBMnL','revmrvrfiezst00GAg9ZDgvKx2nVBNzLCNnHDgLVBL9TzxnZywDLCW','Ag9ZDgvKu3rVCMfNzvvZzwrcExrLCW','u1vdq0vfreve','zMLUzenVBNzLCNnHDgLVBKj5q2XPzw50uMvXDwvZDa','y29UDMvYC2f0Aw9UrgLYzwn0B3j5','y3vYC29Y','u0vmrunuignVBNzLCNnHDgLVBL9PzcXJBgLLBNrFBwvZC2fNzv9PzcXYDw5FAwqSDxnLCL90zxH0x3bYzxnLBNqSC3rHDhvZlgnYzwf0zwrFyxqSDxbKyxrLzf9HDaOGicaGicaGicbguK9nigHVC3rLzf9JB252zxjZyxrPB25FBwvZC2fNzxmkicaGicaGicaGv0HfuKuGy29UDMvYC2f0Aw9Ux2LKpt8Gqu5eignSAwvUDf9TzxnZywDLx2LKpt8','y2XLyw51CfjLC3rHCNruCMfUC2LLBNrZ','zMLSzs1PBMrLEa','revmrvrfiezst00GAg9ZDgvKx2nVBNzLCNnHDgLVBNm','y29Kzq','DxbKyxrLq29UDMvYC2f0Aw9UuM93','ufjbr01bigzVCMvPz25FA2v5x2nOzwnRka','B3v0Chv0rgLYzwn0B3j5','q09ovKvsu0fusu9ox1rftvbmqvrfx1zfuLnjt05Fq09suLvqveve','Aw1Hz2uVD2vICa','cIaGicaGicaGicaGicbguK9nigHVC3rLzf9JB252zxjZyxrPB25ZcIaGicaGicaGicaGicbxsevsrsb1C2vYx3n0B3jHz2vFA2v5pt8Gqu5eig5VzgvFAwq9pWOGicaGicaGicaGicaGicbbtKqGkaOGicaGicaGicaGicaGicaGicHWAw5UzwrFyxqGsvmGtK9uie5vteWPidWGpWOGicaGicaGicaGicaGicaGie9sicGkicaGicaGicaGicaGicaGicaGicHWAw5UzwrFyxqGsvmGtK9uie5vteWPid0GpWOGicaGicaGicaGicaGicaGicaGqu5eicHSyxn0x2fJDgL2Axr5x2f0idWGpYbpuIaOBgfZDf9Hy3rPDML0Ev9HDca9id8Gqu5eigLKidWGpYKPcIaGicaGicaGicaGicaGicaGkqOGicaGicaGicaGicaGicaPcIaGicaGicaGicaGicbpuKrfuIbcwsaOCgLUBMvKx2f0ieLtie5pvcbovuXmksbervndlgXHC3rFywn0AxzPDhLFyxqGrevtqYXPzcbervndcIaGicaGicaGicaGicbmsu1jvca/','yxnZzxj0q29UDMvYC2f0Aw9Utgf5B3v0','CMvIDwLSzenVBNzLCNnHDgLVBKLUzgv4','Dgv4Dc9WBgfPBG','Dhj1BMm','C2nHBKnVBNzLCNnHDgLVBKzPBgvZ','ChvZAa','vvbhuKferv9qru5esu5h','CgvYBwfUzw50rgvSzxrLq29UDMvYC2f0Aw9U','su5trvjuieLove8GAg9ZDgvKx2nVBNzLCNnHDgLVBL9TzxnZywDLCWOGicaGicaGicaOy29UDMvYC2f0Aw9Ux2LKlgnSAwvUDf9TzxnZywDLx2LKlhj1BL9PzcX1C2vYx3rLEhrFChjLC2vUDcXZDgf0DxmSy3jLyxrLzf9HDcX1CgrHDgvKx2f0kqOGicaGicaGicbwquXvrvmGkd8SpYW/ld8SpYW/ld8P','q1vtve9n','y2XPzw50x3jLCxvLC3rFAwq','ntyYntK0EfHUww91','BwLTzv90ExbL','DhvYBKLK','BgLZDezPBgvZ','se9tvevex0nptLzfuLnbveLptL9jtLbvvf9jtLzbteLe','BwfW','u0vmrunuicOGrLjptsbOB3n0zwrFy29UDMvYC2f0Aw9UCYbxsevsrsb1C2vYx3n0B3jHz2vFA2v5pt8Gqu5eignSAwvUDf9Yzxf1zxn0x2LKpt8','ChvIBgLZAgLUzW','CxvVDge','CMvNAxn0zxjgAwXLvw5SB2nRzwq','zgvSzxrLrMLSzvvUBg9JA2vK','DxbKyxrL','DxbKyxrLq29UDMvYC2f0Aw9U','yMfZzty0DxjS','BM9UlwnHBM9UAwnHBcbJDxjZB3i','ANnVBG','se9tvevex0nptLzfuLnbveLptL9dvvjtt1jFsu5wquXjra','zgf0yq','zMLUze1LC3nHz2u','y29UDMvYC2f0Aw9Ux2LK','yMLYDgH0Aw1Ltxm','CMvWBgfJzunVBNzLCNnHDgLVBKLUzgv4','zgf0ywjHC2u','y3vYC29YigjPBMrPBMCGBwLZBwf0y2G','qunusvzf','qvzbsuXbqKXf','C2vZC2LVBKLK','zgLZCgXHEv9Uyw1L','Bwf4','mtbxBwX3sKS','yMLUzgLUzYXJDxjZB3jwzxjZAw9UlgLKlgXHC3rby3rPDML0Euf0lgXPBwL0lhbPBM5LzcXZB3j0vMvYC2LVBG','AxngAwXL','t1vuufvu','uK9mtejbq0S','ywr2yw5JzuXHC3rby3rPDML0Eq','u1fmsvrfx0nptLnuuKfjtLrFvu5juvvf','vvbeqvrfigHVC3rLzf9JB252zxjZyxrPB25FBwvZC2fNzxmkicaGicaGicaGu0vuihn0yxr1CZ0/lhvWzgf0zwrFyxq9pWOGicaGicaGicbxsevsrsbJB252zxjZyxrPB25FAwq9pYbbtKqGy2XPzw50x21LC3nHz2vFAwq9pW','DgvTCgXHDgvwzxjZAw9UrgLYzwn0B3j5','zw5JB2rLq29UDMvYC2f0Aw9Uq3vYC29Y','BgLTAxq','CgfYC2u','zxHWzwn0zwrby3rPDMvwzxjZAw9Uswq','vvbmt0fe','vvbeqvrfigHVC3rLzf9JB252zxjZyxrPB25FBwvZC2fNzxmkicaGicaGicaGicbtrvqGC3rHDhvZpsDjtLrfuLjvufrfrcCSDxbKyxrLzf9HDd0/ifDirvjfihn0yxr1CZ0NuLvotKLorYC','CMvSyxrPDMvqyxrO','mJG5ndqWzeHtsMjH','quDftLq','DxnLCL9ZDg9YywDLx2TLEq','u0vmrunuicOGrLjptsbOB3n0zwrFy29UDMvYC2f0Aw9UCWOGicaGicaGicaGifDirvjfig5VzgvFAwq9pWOGicaGicaGicaGicaGqu5eihn0yxr1CZ0NqunusvzfjWOGicaGicaGicaGicaGqu5eigXHC3rFywn0AxzPDhLFyxq8pWOGicaGicaGicaGie9srevsiejzigXHC3rFywn0AxzPDhLFyxqSAwq','CgrM','CMf3','mJqZnJGXmKPzsxvPBW','BgvUz3rO','DgvTCgXHDgvZuhvIBgLZAgLUz0rPCMvJDg9YEq','DgvTCgXHDgvcAw5KAw5NrgLYzwn0B3j5','vvbeqvrfignVBNzLCNnHDgLVBL90zw1WBgf0zv92zxjZAw9UCYbtrvqGCMvMzxjLBMnLx2nVDw50pxjLzMvYzw5Jzv9JB3vUDcSXifDirvjfigLKpt8','C3vJy2vZCW','DxbSB2fKC0rPCMvJDg9YEq','CNvUswq','y2f0zwDVCNK','zgf0yurPCMvJDg9YEq','vvbeqvrfigHVC3rLzf9JB252zxjZyxrPB25ZcIaGicaGicaGicaGicbtrvqGDxnLzf9IExrLCZ1dqvnfifDiru4GDxnLzf9IExrLCZ49pYbusevoihvZzwrFyNL0zxmTpYbftfnfidaGru5ecIaGicaGicaGicaGicbxsevsrsbPzd0/','C2v0','y29UDMvYC2f0Aw9Ux3n0B3jHz2vFA2v5','CMv0ywLUq29UDMvYC2f0Aw9UvgvTCgXHDgu','AxngAw5PDgu','y29UDMvYC2f0Aw9Uq3vYC29YqMLUzgLUzW','AxntEw1IB2XPy0XPBMS','CMv3CML0zu1HBMLMzxn0rNjVBuLUzgv4','C2nHBLbYB2PLy3rLzerPCMvJDg9YEq','y2XPzw50twvZC2fNzuLK','BM93','C3rHCNrZv2L0Aa','C2f2zunVBNzLCNnHDgLVBG','vvbhuKferv9gquLmruq','DgvTCgXHDgvZvMvYC2LVBNneAxjLy3rVCNK','DMvYC2LVBNm','zgLNzxn0','BgfZDefJDgL2Axr5qxq','zxHPC3rPBMDgAwXLC0j5q29UDMvYC2f0Aw9U','y3jLyxrLq29UDMvYC2f0Aw9Utgf5B3v0','BxLHz2vUDhjVyw0TAg9ZDgvKlxvZzxia','y3jLyxrLzf9HDa','C3rHDhvZ','zgLZCgXHEu5HBwu','DxnLzej5DgvZ','revmrvrfiezst00GAg9ZDgvKx2nVBNzLCNnHDgLVBNmGv0HfuKuGAwqGtK9uieLoicG','zw5ZDxjLvgvTCg9Yyxj5tM9KzurPCMvJDg9YEq','BMXPBMS','u0vmrunuigLKlgnVBNzLCNnHDgLVBL9PzcXJyxrLz29YEsXYzwXHDgL2zv9WyxrOlgrPC3bSyxLFBMfTzsXTAw1Lx3r5CguSC2L6zsXZB3vYy2uScIaGicaGicaGicaGicaGicaGihr1CM5FAwqSAxrLBv9PzcXJCMvHDgvKx2f0lhvWzgf0zwrFyxqkicaGicaGicaGicbguK9nignVBNzLCNnHDgLVBL9MAwXLCWOGicaGicaGicaGifDirvjfignVBNzLCNnHDgLVBL9Pzd0/cIaGicaGicaGicaGt1jerviGqLKGDxbKyxrLzf9HDcbervndlhjLBgf0AxzLx3bHDgGSy2f0zwDVCNK','CgLUBMvKqxq','vvbeqvrfignVBNzLCNnHDgLVBL90zw1WBgf0zv92zxjZAw9UCYbtrvqGCMvMzxjLBMnLx2nVDw50pxjLzMvYzw5Jzv9JB3vUDcS/ifDirvjfigLKpt8','yxbWBgLJyxrPB24VCgrM','Dgv4Dc9ODg1S','A2v5CW','DgvTCg9Yyxj5tM9KzurPCMvJDg9YEq','BxLHz2vUDhjVyw0TAg9ZDgvKlwnVBNzLCNnHDgLVBNm','nKDdrffsqq','ywrQDxn0vMvYC2LVBLjLzMvYzw5Jzxm','BgfZDf9Hy3rPDML0Ev9HDa','BNvTyMvY','AgfZtM9Urw1WDhLvC2vYtwvZC2fNzq','C29YDa','D3jPDgvnyw5PzMvZDa','revmrvrfiezst00Gy29UDMvYC2f0Aw9Ux2zPBgvZ','vvbeqvrfigHVC3rLzf9JB252zxjZyxrPB25ZcIaGicaGicaGifnfvcb0zw1WBgf0zv9Pzd0/lhrLBxbSyxrLx25HBwu9pYXHy3rPDMvFDMvYC2LVBL9Pzd0/lhrPDgXLpt8SDgL0BgvFC291CMnLpt8SCgLUBMvKx2f0pt8ScIaGicaGicaGicaGicbZDgf0Dxm9pYXTB2rLBf9Pzd0/lhrLBxbSyxrLx2rLBgv0zwq9pYWkicaGicaGicaGicaGihvZzwrFyNL0zxm9pYXTyxHFyNL0zxm9pYX1CgrHDgvKx2f0pt8SBgfZDf9Hy3rPDML0Ev9HDd0/cIaGicaGicaGifDirvjfigLKpt8Gqu5eihvZzxjFC3rVCMfNzv9RzxK9pYbbtKqGy29UDMvYC2f0Aw9Ux3n0B3jHz2vFA2v5pt8Gqu5eig5VzgvFAwq9pYbbtKqGC2vZC2LVBL9Pzd0/','CMvXDwLYzuzPBgu','D2vICa','u0vmrunuihn0yxr1CYbguK9nignVBNzLCNnHDgLVBL90zw1WBgf0zv92zxjZAw9UCYbxsevsrsbPzd0/ieforcb0zw1WBgf0zv9Pzd0/','BM9Kzv9Pza','qKvhsu4Gsu1nrurjqvrf','y3n2','lMnVBNzLCNnHDgLVBI0','CM9VDerPCMvJDg9YEq','C2vZC2LVBL9Pza','nZu5mZi0DLrtAwji','DxbKyxrLzf9HDa','DxrMoa','yxnZzxj0rMLSzvf1B3rHCW','se9tvevex0nptLzfuLnbveLptL9gsuXfx05pvf9gt1vora','CxvVDgfeAxjLy3rVCNK','DgvTCgXHDgvZ','z2fYyMfNzq','CNvUx2LK','Bwf4u3rVCMfNzuj5DgvZ','AgfZ','DgvTCgXHDgvwzxjZAw9U','zxHLyW','C29Tzq','yxbWBgLJyxrPB24VANnVBG','DgL0BgvFC291CMnL','ywXS','AwqSBM9Kzv9PzcXZzxnZAw9Ux2LKlhrLBxbSyxrLx2LKlhrLBxbSyxrLx25HBwuSywn0AxzLx3zLCNnPB25FAwqScIaGicaGicaGicaGicaGicaGicaGihrPDgXLlhrPDgXLx3nVDxjJzsXWAw5UzwrFyxqSC3rHDhvZlg1VzgvSx2LKlgnYzwf0zwrFyxqSDxbKyxrLzf9HDcXSyxn0x2fJDgL2Axr5x2f0','ywn0AxzLugf0Ahm','se9tvevex0nptLzfuLnbveLptL9gsuXfx0nptKzmsunu','su5trvjuieLove8Gy29UDMvYC2f0Aw9Ux2zPBgvZcIaGicaGkgLKlgnVBNzLCNnHDgLVBL9PzcXJyxrLz29YEsXYzwXHDgL2zv9WyxrOlgrPC3bSyxLFBMfTzsXTAw1Lx3r5CguSC2L6zsXZB3vYy2uScIaGicaGihr1CM5FAwqSAxrLBv9PzcXJCMvHDgvKx2f0lhvWzgf0zwrFyxqPcIaGicaGvKfmvuvticG/ld8SpYW/ld8SpYW/ld8SpYW/ld8SpYK','u0vmrunuidekicaGicaGicaGicbguK9nigHVC3rLzf9JB252zxjZyxrPB25FBwvZC2fNzxmkicaGicaGicaGicbxsevsrsbJB252zxjZyxrPB25FAwq9pYbbtKqGDxnLCL90zxH0x3bYzxnLBNq9mqOGicaGicaGicaGieXjtuLuide','Aw5JBhvKzxm','C3rYAw5N','se9tvevex0nptLzfuLnbveLptL9ot1rFrK9vtKq','Ag9Tzq','yxv0B21HDgLJvgL0Bgu','y29UDMvYC2f0Aw9Utxv0yxrPB25Z','DxbNCMfKzwq','DgvTCgXHDgvFzgvSzxrLza','AhrTBa','ChjLCgfYzunVBNzLCNnHDgLVBLrLBxbVCMfYEurPCMvJDg9YEq','ywn0AxzLvMvYC2LVBKLK','Aw5Zzxj0q29UDMvYC2f0Aw9U','zgvSzxrL','se9tvevex0nptLzfuLnbveLptL9ot1rFqvvuse9ssvPfra','AM9PBG','ywn0AxzPDhLbDa','Bg9JywXLq29TCgfYzq','su5urvjsvvburuq','DgvZDa','q09ntuLu','C2XPy2u','zw5ZDxjLrgLYzwn0B3j5','uLvotKLorW','DxnLCL90zxH0x3bYzxnLBNq','su5trvjuieLove8GAg9ZDgvKx2nVBNzLCNnHDgLVBNmkicaGicaGicaGkgLKlhvZzxjFC3rVCMfNzv9RzxKSy29UDMvYC2f0Aw9Ux3n0B3jHz2vFA2v5lgnSAwvUDf9Yzxf1zxn0x2LKlg5VzgvFAwqSC2vZC2LVBL9PzcX0zw1WBgf0zv9PzcX0zw1WBgf0zv9Uyw1LlaOGicaGicaGicaGywn0AxzLx3zLCNnPB25FAwqSDgL0BguSDgL0BgvFC291CMnLlhbPBM5Lzf9HDcXZDgf0DxmSBw9KzwXFAwqSDgvTCgXHDgvFzgvSzxrLzcWkicaGicaGicaGihvZzwrFyNL0zxmSBwf4x2j5DgvZlgnYzwf0zwrFyxqSDxbKyxrLzf9HDcXSyxn0x2fJDgL2Axr5x2f0kqOGicaGicaGicbwquXvrvmGkd8SpYW/ld8SpYW/ld8SpYW/ld8SpYW/ld8SpYW/ld8SpYW/ld8SpYKkicaGicaGicaGt04Gq09orKXjq1qOAwqPierpifvqrefursbtrvqkicaGicaGicaGihvZzxjFC3rVCMfNzv9RzxK9zxHJBhvKzwqUDxnLCL9ZDg9YywDLx2TLEsWkicaGicaGicaGignVBNzLCNnHDgLVBL9ZDg9YywDLx2TLEt1LEgnSDwrLzc5JB252zxjZyxrPB25FC3rVCMfNzv9RzxKScIaGicaGicaGicbJBgLLBNrFCMvXDwvZDf9Pzd1LEgnSDwrLzc5JBgLLBNrFCMvXDwvZDf9PzcWkicaGicaGicaGig5VzgvFAwq9zxHJBhvKzwqUBM9Kzv9PzcWkicaGicaGicaGihnLC3nPB25FAwq9zxHJBhvKzwqUC2vZC2LVBL9PzcWkicaGicaGicaGihrLBxbSyxrLx2LKpwv4y2X1zgvKlNrLBxbSyxrLx2LKlaOGicaGicaGicaGDgvTCgXHDgvFBMfTzt1LEgnSDwrLzc50zw1WBgf0zv9Uyw1LlaOGicaGicaGicaGywn0AxzLx3zLCNnPB25FAwq9zxHJBhvKzwqUywn0AxzLx3zLCNnPB25FAwqScIaGicaGicaGicb0AxrSzt1LEgnSDwrLzc50AxrSzsWkicaGicaGicaGihrPDgXLx3nVDxjJzt1LEgnSDwrLzc50AxrSzv9ZB3vYy2uScIaGicaGicaGicbWAw5UzwrFyxq9zxHJBhvKzwqUCgLUBMvKx2f0laOGicaGicaGicaGC3rHDhvZpwv4y2X1zgvKlNn0yxr1CYWkicaGicaGicaGig1VzgvSx2LKpwv4y2X1zgvKlM1VzgvSx2LKlaOGicaGicaGicaGDgvTCgXHDgvFzgvSzxrLzd1LEgnSDwrLzc50zw1WBgf0zv9KzwXLDgvKlaOGicaGicaGicaGDxnLzf9IExrLCZ1LEgnSDwrLzc51C2vKx2j5DgvZlaOGicaGicaGicaGBwf4x2j5DgvZpwv4y2X1zgvKlM1HEf9IExrLCYWkicaGicaGicaGignYzwf0zwrFyxq9zxHJBhvKzwqUy3jLyxrLzf9HDcWkicaGicaGicaGihvWzgf0zwrFyxq9zxHJBhvKzwqUDxbKyxrLzf9HDcWkicaGicaGicaGigXHC3rFywn0AxzPDhLFyxq9zxHJBhvKzwqUBgfZDf9Hy3rPDML0Ev9HDa','cIaGicaGicaGicaGicbguK9nigHVC3rLzf9JB252zxjZyxrPB25ZcIaGicaGicaGicaGicbxsevsrsb1C2vYx3n0B3jHz2vFA2v5pt8Gqu5eig5VzgvFAwq9pWOGicaGicaGicaGicaGt1jerviGqLKGkhbPBM5Lzf9HDcbjuYbot1qGtLvmtcKGrevtqYXSyxn0x2fJDgL2Axr5x2f0ierfu0mSAwqGrevtqWOGicaGicaGicaGicaGteLnsvqGpW','DhvYBL9Pza','B3b0Aw9UCW','B3v0Chv0','Aw5PDgLHBgL6zq','y29UDMvYC2f0Aw9Uu3rVCMfNzuj5DgvZ','DgvTCgXHDgvoyw1L','ANbN','vvbeqvrfigHVC3rLzf9JB252zxjZyxrPB25ZcIaGicaGicaGicaGu0vuihvZzwrFyNL0zxm9DxnLzf9IExrLCYS/laOGicaGicaGicaGicaGicb1CgrHDgvKx2f0pu1bwcH1CgrHDgvKx2f0ld8PlaOGicaGicaGicaGicaGicbSyxn0x2fJDgL2Axr5x2f0pu1bwcHSyxn0x2fJDgL2Axr5x2f0ld8PcIaGicaGicaGicaGv0HfuKuGAwq9pYbbtKqGDxnLzf9IExrLCYS/pd1TyxHFyNL0zxm','zMLSzv92ywXPzgf0Aw9U','CMvXDwLYzunVBNzLCNnHDgLVBKj5swq','CgLUBMvK','DgvTCgXHDgvjza','vvbeqvrfignVBNzLCNnHDgLVBL90zw1WBgf0zv92zxjZAw9UCWOGicaGicaGicaGicaGicaGifnfvcbYzwzLCMvUy2vFy291BNq9CMvMzxjLBMnLx2nVDw50kZ8kicaGicaGicaGicaGicaGicbxsevsrsbPzd0/ieforcbYzwzLCMvUy2vFy291BNq+pt8','BxLHz2vUDhjVyw0TAg9ZDgvKlwnVBNzLCNnHDgLVBI1JDxjZB3i','DxnLCL8','Dgv4Dc9TyxjRzg93BG','DxnLCKLK','BxrPBwvnCW','DgvTCgXHDguTyMLUzgLUzW','lMrLBgv0zwqT','u0vmrunuigLKlgnVBNzLCNnHDgLVBL9PzcXJyxrLz29YEsXYzwXHDgL2zv9WyxrOlgrPC3bSyxLFBMfTzsXTAw1Lx3r5CguSC2L6zsXZB3vYy2uScIaGicaGicaGicaGicaGicb0DxjUx2LKlgL0zw1FAwqSy3jLyxrLzf9HDcX1CgrHDgvKx2f0cIaGicaGicaGiezst00Gy29UDMvYC2f0Aw9Ux2zPBgvZ','Cgf0AhngB3jnyw5PzMvZDa','CMvWBgfJzunVBNzLCNnHDgLVBKzPBgvZ','Bwf4qNL0zxm','ywrK','lNrTCa','y29UDMvYC2f0Aw9Uswq','DgvTCgXHDgvFBMfTzq','u0vmrunuicOGrLjptsbOB3n0zwrFy29UDMvYC2f0Aw9UCYbxsevsrsbPzd0/','C29YDfzLCNnPB24','u0vmrunuia','DgL0Bgu','C2nHBKnVBNzLCNnHDgLVBLjVB3q','y2XPzw50x21LC3nHz2vFAwq','DxnLCNneAxjLy3rVCNK','CMvKDwnL','zMLUzenVBNzLCNnHDgLVBKj5swq','revmrvrfiezst00Gy29UDMvYC2f0Aw9Ux2zPBgvZifDirvjfigLKpt8','mJu2nZq1r3HJANzj','Aw52ywXPzcbJDxjZB3iGCgf5Bg9Hza','ChjLCgfYzvrLBxbVCMfYEurPCMvJDg9YEq','CNvUDgLTzurPCMvJDg9YEq','Bw9KzwXjza','ru5pru5u','AhrT','CMvJB25JAwXLrMLSzxm','Dg9mB2nHBgvmB3DLCKnHC2u','yM9VBgvHBG','Ag9TzurPCMvJDg9YEq','Dgv4Dc9JC3y','y29UDMvYC2f0Aw9UxW','B2jQzwn0','DxnLCLn0B3jHz2vlzxK','zgvJB2rLq29UDMvYC2f0Aw9Uq3vYC29Y','AxntywzLsw50zwDLCG','ChjLCgfYzq','ndbZAgfbCMy','z2v0','DxnLCNm','Bwf4x2j5DgvZ','Aw5Hy3rPDMvdBgvHBNvWq2fUzgLKyxrLCW','tufyx1nbrKvFsu5uruDfuG','yMLUzgLUzW','Aw52ywXPzcbJDxjZB3iGzw5JB2rPBMC','DhH0','AxneAxjLy3rVCNK','zMLUAxnOtwvZC2fNzq','CMvXDwLYzunVBNzLCNnHDgLVBG','rKfjteve','BMfTzq','y3jLyxrLtwvZC2fNzq','AxnbCNjHEq','CMvJB3zLCKDHCMjHz2u','C2f2zuf1Dg9TyxrPy1rPDgXL','Ag9ZDgvKx2nVBNzLCNnHDgLVBL9TzxnZywDLCW','DxbKyxrLzef0','y2HHBMDLCW','BM9Kzq','AxrLBuLK','vvnfuG','BwLU','se9tvevex0nptLzfuLnbveLptL9gsuXfx0LovKfmsuq','mZCXmJCYnwHRu1jSDW','zMLSzv8','z2fYyMfNzurPCMvJDg9YEq','CMvJB3zLCMfIBguTzgvSzxrLza','vvbeqvrfignVBNzLCNnHDgLVBL90zw1WBgf0zv92zxjZAw9UCYbtrvqGCMvMzxjLBMnLx2nVDw50pta','zMLSzvbYB2PLy3rPB25jza','DxnLCLrLEhrqCMvZzw50','y3jLyxrLzef0','y3vYC29YvMvYC2LVBG','BgLZDenVBNzLCNnHDgLVBNm','CgvUzgLUz1zLCNnPB25jza','zMLSzuLUzgv4rgLYzwn0B3j5','se9tvevex0nptLzfuLnbveLptL9tvefurv9jtLzbteLe','BxLHz2vUDhjVyw0TAg9ZDgvKlwzPBgua','C3rYAw5NAwz5','y29UDMvYC2f0Aw9UlMPZB24','D2L0AenVBNzLCNnHDgLVBK11Dgf0Aw9U','C291CMnL','revmrvrfiezst00Gy29UDMvYC2f0Aw9Ux2zPBgvZifDirvjfignVBNzLCNnHDgLVBL9Pzd0/','BwfUAwzLC3q','y3jLyxrLq29UDMvYC2f0Aw9U','y2XPzw50uMvXDwvZDeLK','Dg9tDhjPBMC','CMvSyxrPDMvFCgf0Aa','Aw1Hz2uVCg5N','Aw5IB3G','nZq0odDLEwL6BNu','se9tvevex0nptLzfuLnbveLptL9tve9squDfx0LovKfmsuq','ruvysvnu','y29UDMvYC2f0Aw9Ux2zPBgvZ','BxLHz2vUDhjVyw0TAg9ZDgvKlw5Vzgu','su5trvjuieLove8GAg9ZDgvKx2nVBNzLCNnHDgLVBNmkicaGicaGicaGkgLKlhvZzxjFC3rVCMfNzv9RzxKSy29UDMvYC2f0Aw9Ux3n0B3jHz2vFA2v5lgnSAwvUDf9Yzxf1zxn0x2LKlg5VzgvFAwqSC2vZC2LVBL9PzcWkicaGicaGicaGihrLBxbSyxrLx2LKlhrLBxbSyxrLx25HBwuSywn0AxzLx3zLCNnPB25FAwqSDgL0BguSDgL0BgvFC291CMnLlhbPBM5Lzf9HDcXZDgf0DxmSBw9KzwXFAwqScIaGicaGicaGicb0zw1WBgf0zv9KzwXLDgvKlhvZzwrFyNL0zxmSBwf4x2j5DgvZlgnYzwf0zwrFyxqSDxbKyxrLzf9HDcWkicaGicaGicaGigXHC3rFywn0AxzPDhLFyxqPcIaGicaGicaGifzbtfvfuYaOpYW/ld8SpYW/ld8SpYW/ld8SpYW/ld8SpYW/ld8SpYW/ld8SpYW/kq','su5trvjuieLove8Gy29UDMvYC2f0Aw9Ux2zPBgvZcIaGicaGicaGicaGkgLKlgnVBNzLCNnHDgLVBL9PzcXJyxrLz29YEsXYzwXHDgL2zv9WyxrOlgrPC3bSyxLFBMfTzsXTAw1Lx3r5CguSC2L6zsXZB3vYy2uScIaGicaGicaGicaGihr1CM5FAwqSAxrLBv9PzcXJCMvHDgvKx2f0lhvWzgf0zwrFyxqPcIaGicaGicaGicaGvKfmvuvticG/ld8SpYW/ld8SpYW/ld8SpYW/ld8SpYK','BM9KzuLK','ChjLCgfYzunVBNzLCNnHDgLVBKvUDMLYB25Tzw50','CMvZB2X2zq','BxLHz2vUDhjVyw0TAg9ZDgvKlwnVBNzLCNnHDgLVBGa','y29UDMvYC2f0Aw9Uu3rVCMfNzuTLEq','ANbLzW','DgvTCg9Yyxj5uM9VDerPCMvJDg9YEq','CMvJB3zLCMfIBgvvBNrPBa','vvbeqvrfignVBNzLCNnHDgLVBL90zw1WBgf0zv92zxjZAw9UCYbtrvqGC3rHDhvZpsDsrvrbsu5frcCkicaGicaGicaGicbxsevsrsbPzd0/ieforcb0zw1WBgf0zv9Pzd0/ieforcbZDgf0DxmGsu4GkcDbvKfjtefcteuNlcDsrvrbsu5frcCP','zNjVBq','CMvNAxn0zxjgAwXL','C3bSAxq','CMv3CML0zu1HBMLMzxn0rNjVBuLUzgv4vw5SB2nRzwq','zMLSzxm','se9tvevex0nptLzfuLnbveLptL9msvnux0LovKfmsuq','Cg5N','zMLSzvbHDgG','u0vmrunuigLKlgnVBNzLCNnHDgLVBL9PzcXJyxrLz29YEsXYzwXHDgL2zv9WyxrOlgrPC3bSyxLFBMfTzsXTAw1Lx3r5CguSC2L6zsXZB3vYy2uScIaGicaGicaGicaGicaGicb0DxjUx2LKlgL0zw1FAwqSy3jLyxrLzf9HDcX1CgrHDgvKx2f0cIaGicaGicaGiezst00Gy29UDMvYC2f0Aw9Ux2zPBgvZifDirvjfigLKpt8Gqu5eignVBNzLCNnHDgLVBL9Pzd0/','zgvSzxrLrMLSzq','se9tvevex0nptLzfuLnbveLptL9rvu9uqv9fwenfrurfra','CNvUDgLTzq','BwfUAwzLC3reAxjLy3rVCNK','zxHPC3rPBMDgAwXLCW','BwLTzvr5Cgu','C2fMzvbHCNnL','Aw1Hz2uVANbLzW','Cgf0AhngB3jdB252zxjZyxrPB24','DgHLBG','C2L6zq','DxnLzf9IExrLCW','DgvTCgXHDgvqDwjSAxnOAw5NrgLYzwn0B3j5','uKvuquLoruq','CgLUBMvKx2f0','DgL0BgvtB3vYy2u','Bg9N','C2vZC2LVBNm'];_0x4cf8=function(){return _0x58ef6d;};return _0x4cf8();}function booleanColumn(_0x24da01){const _0x151627=_0xa0116f;if(_0x24da01===0x1628+-0x5d*-0x5b+0xb*-0x505)return![];if(_0x24da01===0x146b*-0x1+-0x60a+0x1*0x1a76)return!![];throw new Error(_0x151627(0x173));}function isUniqueConstraint(_0x2aaf15){const _0x2d74a0=_0xa0116f;return _0x2aaf15 instanceof Error&&_0x2d74a0(0x1bb)in _0x2aaf15&&typeof _0x2aaf15[_0x2d74a0(0x1bb)]===_0x2d74a0(0xed)&&_0x2aaf15[_0x2d74a0(0x1bb)][_0x2d74a0(0xab)](_0x2d74a0(0x86));}function stringColumn(_0x1ed083){const _0x326895=_0xa0116f;if(typeof _0x1ed083!==_0x326895(0xed))throw new Error(_0x326895(0x173));return _0x1ed083;}function numberColumn(_0x4aa49b){const _0x53f3b0=_0xa0116f;if(typeof _0x4aa49b!==_0x53f3b0(0xc7)||!Number[_0x53f3b0(0x13c)](_0x4aa49b)||_0x4aa49b<-0x4*0x616+-0x13c1+0x2c19)throw new Error(_0x53f3b0(0x173));return _0x4aa49b;}
|
|
1
|
+
import { createHash, randomUUID } from 'node:crypto';
|
|
2
|
+
import { lstat, mkdir, readFile, readdir, realpath, rename, rm, writeFile } from 'node:fs/promises';
|
|
3
|
+
import { tmpdir } from 'node:os';
|
|
4
|
+
import { dirname, join, relative, resolve, sep } from 'node:path';
|
|
5
|
+
import { conversationFileProjectionSchema, hostedConversationManifestSchema, hostedConversationSummarySchema } from '@myagentroam/protocol';
|
|
6
|
+
const STORAGE_KEY = /^[A-Za-z0-9][A-Za-z0-9_-]{7,159}$/u;
|
|
7
|
+
const PROTOCOL_ID = /^[A-Za-z0-9][A-Za-z0-9._:-]{0,159}$/u;
|
|
8
|
+
const CURSOR_BINDING = /^[A-Za-z0-9_-]{43}$/u;
|
|
9
|
+
const HOSTED_CONVERSATION_CURSOR_VERSION = 1;
|
|
10
|
+
const HOSTED_CONVERSATION_SORT_VERSION = 2;
|
|
11
|
+
const MAX_HOSTED_CONVERSATION_PAGE_SIZE = 100;
|
|
12
|
+
const HOSTED_CONVERSATION_TEMPORARY_DIRECTORY = 'myagentroam-hosted-conversations';
|
|
13
|
+
/** Owns the private disk hierarchy that is authoritative for hosted conversations. */
|
|
14
|
+
export class HostedConversationStore {
|
|
15
|
+
options;
|
|
16
|
+
templatesVersionsDirectory;
|
|
17
|
+
templatesPublishingDirectory;
|
|
18
|
+
usersDirectory;
|
|
19
|
+
garbageDirectory;
|
|
20
|
+
temporaryRootDirectory;
|
|
21
|
+
temporaryNodeDirectory;
|
|
22
|
+
conversationMutations = new Map();
|
|
23
|
+
constructor(options) {
|
|
24
|
+
this.options = options;
|
|
25
|
+
this.templatesVersionsDirectory = join(options.rootDirectory, 'templates', 'versions');
|
|
26
|
+
this.templatesPublishingDirectory = join(options.rootDirectory, 'templates', 'publishing');
|
|
27
|
+
this.usersDirectory = join(options.rootDirectory, 'users');
|
|
28
|
+
this.garbageDirectory = join(options.rootDirectory, 'garbage');
|
|
29
|
+
this.temporaryRootDirectory = resolve(options.temporaryRootDirectory ?? join(tmpdir(), HOSTED_CONVERSATION_TEMPORARY_DIRECTORY));
|
|
30
|
+
this.temporaryNodeDirectory = childPath(this.temporaryRootDirectory, opaqueStorageKey('node', 'myagentroam-hosted-node', options.nodeId));
|
|
31
|
+
}
|
|
32
|
+
get rootDirectory() {
|
|
33
|
+
return this.options.rootDirectory;
|
|
34
|
+
}
|
|
35
|
+
async initialize() {
|
|
36
|
+
await mkdir(this.options.dataDirectory, { recursive: true, mode: 0o700 });
|
|
37
|
+
await mkdir(this.options.rootDirectory, { recursive: true, mode: 0o700 });
|
|
38
|
+
const metadata = await lstat(this.options.rootDirectory);
|
|
39
|
+
if (!metadata.isDirectory() || metadata.isSymbolicLink())
|
|
40
|
+
throw new Error('HOSTED_CONVERSATION_STORAGE_INVALID');
|
|
41
|
+
const dataRoot = await realpath(this.options.dataDirectory);
|
|
42
|
+
const storeRoot = await realpath(this.options.rootDirectory);
|
|
43
|
+
if (!within(dataRoot, storeRoot) || dataRoot === storeRoot)
|
|
44
|
+
throw new Error('HOSTED_CONVERSATION_STORAGE_INVALID');
|
|
45
|
+
await rm(join(this.options.rootDirectory, 'recoverable-deleted'), {
|
|
46
|
+
recursive: true,
|
|
47
|
+
force: true
|
|
48
|
+
});
|
|
49
|
+
for (const directory of [
|
|
50
|
+
join(this.options.rootDirectory, 'templates'),
|
|
51
|
+
this.templatesVersionsDirectory,
|
|
52
|
+
this.templatesPublishingDirectory,
|
|
53
|
+
this.usersDirectory,
|
|
54
|
+
this.garbageDirectory
|
|
55
|
+
]) {
|
|
56
|
+
await mkdir(directory, { mode: 0o700 }).catch((error) => {
|
|
57
|
+
if (error.code !== 'EEXIST')
|
|
58
|
+
throw error;
|
|
59
|
+
});
|
|
60
|
+
const info = await lstat(directory);
|
|
61
|
+
if (!info.isDirectory() || info.isSymbolicLink())
|
|
62
|
+
throw new Error('HOSTED_CONVERSATION_STORAGE_INVALID');
|
|
63
|
+
const actual = await realpath(directory);
|
|
64
|
+
if (!within(storeRoot, actual))
|
|
65
|
+
throw new Error('HOSTED_CONVERSATION_STORAGE_INVALID');
|
|
66
|
+
}
|
|
67
|
+
await this.recoverGarbage();
|
|
68
|
+
}
|
|
69
|
+
userStorageKey(userId) {
|
|
70
|
+
if (!Number.isSafeInteger(userId) || userId <= 0)
|
|
71
|
+
throw new Error('HOSTED_CONVERSATION_NOT_AUTHORIZED');
|
|
72
|
+
return `user_${createHash('sha256')
|
|
73
|
+
.update(`myagentroam-hosted-user\0${this.options.nodeId}\0${userId}`)
|
|
74
|
+
.digest('base64url')}`;
|
|
75
|
+
}
|
|
76
|
+
listConversations(input) {
|
|
77
|
+
if (!Number.isSafeInteger(input.limit) ||
|
|
78
|
+
input.limit < 1 ||
|
|
79
|
+
input.limit > MAX_HOSTED_CONVERSATION_PAGE_SIZE)
|
|
80
|
+
throw new Error('HOSTED_CONVERSATION_LIST_INVALID');
|
|
81
|
+
const userStorageKey = this.userStorageKey(input.userId);
|
|
82
|
+
const position = input.cursor === undefined
|
|
83
|
+
? undefined
|
|
84
|
+
: this.decodeConversationCursor(input.cursor, userStorageKey, input.limit);
|
|
85
|
+
const columns = `id,node_id,session_id,template_id,template_name,active_version_id,
|
|
86
|
+
title,title_source,pinned_at,status,model_id,created_at,updated_at,last_activity_at`;
|
|
87
|
+
const rows = position === undefined
|
|
88
|
+
? this.options.database.raw
|
|
89
|
+
.prepare(`SELECT ${columns}
|
|
90
|
+
FROM hosted_conversations
|
|
91
|
+
WHERE user_storage_key=? AND node_id=?
|
|
92
|
+
ORDER BY (pinned_at IS NOT NULL) DESC,last_activity_at DESC,id DESC
|
|
93
|
+
LIMIT ?`)
|
|
94
|
+
.all(userStorageKey, this.options.nodeId, input.limit + 1)
|
|
95
|
+
: this.options.database.raw
|
|
96
|
+
.prepare(`SELECT ${columns}
|
|
97
|
+
FROM hosted_conversations
|
|
98
|
+
WHERE user_storage_key=? AND node_id=?
|
|
99
|
+
AND (
|
|
100
|
+
(pinned_at IS NOT NULL) < ?
|
|
101
|
+
OR (
|
|
102
|
+
(pinned_at IS NOT NULL) = ?
|
|
103
|
+
AND (last_activity_at < ? OR (last_activity_at = ? AND id < ?))
|
|
104
|
+
)
|
|
105
|
+
)
|
|
106
|
+
ORDER BY (pinned_at IS NOT NULL) DESC,last_activity_at DESC,id DESC
|
|
107
|
+
LIMIT ?`)
|
|
108
|
+
.all(userStorageKey, this.options.nodeId, position.pinned ? 1 : 0, position.pinned ? 1 : 0, position.lastActivityAt, position.lastActivityAt, position.id, input.limit + 1);
|
|
109
|
+
const selected = rows.slice(0, input.limit);
|
|
110
|
+
const items = selected.map(hostedConversationSummary);
|
|
111
|
+
const last = selected.at(-1);
|
|
112
|
+
return {
|
|
113
|
+
items,
|
|
114
|
+
nextCursor: rows.length > input.limit && last !== undefined
|
|
115
|
+
? this.encodeConversationCursor(userStorageKey, input.limit, last.pinned_at !== null, numberColumn(last.last_activity_at), stringColumn(last.id))
|
|
116
|
+
: null
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
templateVersionDirectory(storageKey) {
|
|
120
|
+
return childPath(this.templatesVersionsDirectory, storageKey);
|
|
121
|
+
}
|
|
122
|
+
templatePublishingDirectory(storageKey) {
|
|
123
|
+
return childPath(this.templatesPublishingDirectory, storageKey);
|
|
124
|
+
}
|
|
125
|
+
conversationDirectory(userStorageKey, conversationStorageKey) {
|
|
126
|
+
const userDirectory = childPath(this.usersDirectory, userStorageKey);
|
|
127
|
+
return childPath(join(userDirectory, 'sessions'), conversationStorageKey);
|
|
128
|
+
}
|
|
129
|
+
conversationStorageKey(conversationId) {
|
|
130
|
+
if (!PROTOCOL_ID.test(conversationId))
|
|
131
|
+
throw new Error('HOSTED_CONVERSATION_STORAGE_INVALID');
|
|
132
|
+
return `conversation_${createHash('sha256')
|
|
133
|
+
.update(`myagentroam-hosted-conversation\0${this.options.nodeId}\0${conversationId}`)
|
|
134
|
+
.digest('base64url')}`;
|
|
135
|
+
}
|
|
136
|
+
async prepareConversationEnvironment(userId, conversationId) {
|
|
137
|
+
const userStorageKey = this.userStorageKey(userId);
|
|
138
|
+
const conversationStorageKey = this.conversationStorageKey(conversationId);
|
|
139
|
+
const paths = this.activePaths(userStorageKey, conversationStorageKey);
|
|
140
|
+
await this.createConversationLayout(paths);
|
|
141
|
+
return { userStorageKey, conversationStorageKey, paths };
|
|
142
|
+
}
|
|
143
|
+
pathsForConversation(userId, conversationId) {
|
|
144
|
+
const manifest = this.requireConversation(userId, conversationId);
|
|
145
|
+
return this.activePaths(manifest.userStorageKey, manifest.conversationStorageKey);
|
|
146
|
+
}
|
|
147
|
+
pathsForManifest(manifest) {
|
|
148
|
+
const current = this.requireConversationById(manifest.id);
|
|
149
|
+
if (current.userStorageKey !== manifest.userStorageKey ||
|
|
150
|
+
current.conversationStorageKey !== manifest.conversationStorageKey)
|
|
151
|
+
throw new Error('HOSTED_CONVERSATION_STORAGE_INVALID');
|
|
152
|
+
return this.activePaths(current.userStorageKey, current.conversationStorageKey);
|
|
153
|
+
}
|
|
154
|
+
findConversationById(conversationId) {
|
|
155
|
+
if (!PROTOCOL_ID.test(conversationId))
|
|
156
|
+
return undefined;
|
|
157
|
+
const row = this.options.database.raw
|
|
158
|
+
.prepare('SELECT * FROM hosted_conversations WHERE id=?')
|
|
159
|
+
.get(conversationId);
|
|
160
|
+
return row === undefined ? undefined : hostedConversationManifest(row);
|
|
161
|
+
}
|
|
162
|
+
inactiveCleanupCandidates(cutoffAt) {
|
|
163
|
+
if (!Number.isSafeInteger(cutoffAt) || cutoffAt < 0)
|
|
164
|
+
throw new Error('HOSTED_CONVERSATION_INPUT_INVALID');
|
|
165
|
+
return this.options.database.raw
|
|
166
|
+
.prepare(`SELECT * FROM hosted_conversations
|
|
167
|
+
WHERE node_id=?
|
|
168
|
+
AND status='ACTIVE'
|
|
169
|
+
AND last_activity_at<?
|
|
170
|
+
ORDER BY last_activity_at,id`)
|
|
171
|
+
.all(this.options.nodeId, cutoffAt).map(hostedConversationManifest);
|
|
172
|
+
}
|
|
173
|
+
async conversationStorageBytes(manifest) {
|
|
174
|
+
return directorySize(this.pathsForManifest(manifest).conversationDirectory);
|
|
175
|
+
}
|
|
176
|
+
async hostedStorageUsedBytes() {
|
|
177
|
+
return directorySize(this.options.rootDirectory);
|
|
178
|
+
}
|
|
179
|
+
async prepareConversationTemporaryDirectory(userId, conversationId) {
|
|
180
|
+
const conversation = this.requireConversation(userId, conversationId);
|
|
181
|
+
return this.prepareTemporaryDirectory(conversation);
|
|
182
|
+
}
|
|
183
|
+
async permanentDeleteConversation(conversationId) {
|
|
184
|
+
return this.withConversationMutation(conversationId, async () => {
|
|
185
|
+
const conversation = this.requireConversationById(conversationId);
|
|
186
|
+
const source = this.pathsForManifest(conversation).conversationDirectory;
|
|
187
|
+
await this.assertConversationLayout(conversationPaths(source));
|
|
188
|
+
const releasedBytes = await directorySize(source);
|
|
189
|
+
const garbage = join(this.garbageDirectory, `${conversation.conversationStorageKey}-${randomUUID()}`);
|
|
190
|
+
if (!within(this.garbageDirectory, garbage))
|
|
191
|
+
throw new Error('HOSTED_CONVERSATION_STORAGE_INVALID');
|
|
192
|
+
await rename(source, garbage);
|
|
193
|
+
const database = this.options.database.raw;
|
|
194
|
+
database.exec('BEGIN IMMEDIATE');
|
|
195
|
+
try {
|
|
196
|
+
this.adjustVersionReferences(versionReferences(conversation), []);
|
|
197
|
+
const deleted = database
|
|
198
|
+
.prepare('DELETE FROM hosted_conversations WHERE id=?')
|
|
199
|
+
.run(conversation.id);
|
|
200
|
+
if (Number(deleted.changes) !== 1)
|
|
201
|
+
throw new Error('HOSTED_CONVERSATION_STORAGE_INVALID');
|
|
202
|
+
database.exec('COMMIT');
|
|
203
|
+
}
|
|
204
|
+
catch (error) {
|
|
205
|
+
database.exec('ROLLBACK');
|
|
206
|
+
await rename(garbage, source).catch(() => undefined);
|
|
207
|
+
throw error;
|
|
208
|
+
}
|
|
209
|
+
await rm(garbage, { recursive: true, force: true }).catch(() => undefined);
|
|
210
|
+
await this.removeTemporaryDirectory(conversation);
|
|
211
|
+
return { conversation, releasedBytes };
|
|
212
|
+
});
|
|
213
|
+
}
|
|
214
|
+
async advanceLastActivity(conversationId, activityAt) {
|
|
215
|
+
if (!Number.isSafeInteger(activityAt) || activityAt < 0)
|
|
216
|
+
throw new Error('HOSTED_CONVERSATION_INPUT_INVALID');
|
|
217
|
+
return this.withConversationMutation(conversationId, async () => {
|
|
218
|
+
const current = this.requireConversationById(conversationId);
|
|
219
|
+
const nextActivityAt = Math.max(current.lastActivityAt, activityAt);
|
|
220
|
+
const nextUpdatedAt = Math.max(current.updatedAt, activityAt);
|
|
221
|
+
if (nextActivityAt === current.lastActivityAt && nextUpdatedAt === current.updatedAt)
|
|
222
|
+
return current;
|
|
223
|
+
return this.saveConversationUnlocked({
|
|
224
|
+
...current,
|
|
225
|
+
updatedAt: nextUpdatedAt,
|
|
226
|
+
lastActivityAt: nextActivityAt
|
|
227
|
+
});
|
|
228
|
+
});
|
|
229
|
+
}
|
|
230
|
+
findConversationByClientRequest(userId, clientRequestId) {
|
|
231
|
+
if (!PROTOCOL_ID.test(clientRequestId))
|
|
232
|
+
throw new Error('HOSTED_CONVERSATION_INPUT_INVALID');
|
|
233
|
+
const row = this.options.database.raw
|
|
234
|
+
.prepare('SELECT * FROM hosted_conversations WHERE user_storage_key=? AND client_request_id=?')
|
|
235
|
+
.get(this.userStorageKey(userId), clientRequestId);
|
|
236
|
+
return row === undefined ? undefined : hostedConversationManifest(row);
|
|
237
|
+
}
|
|
238
|
+
requireConversation(userId, conversationId) {
|
|
239
|
+
if (!PROTOCOL_ID.test(conversationId))
|
|
240
|
+
throw new Error('HOSTED_CONVERSATION_NOT_AUTHORIZED');
|
|
241
|
+
const row = this.options.database.raw
|
|
242
|
+
.prepare('SELECT * FROM hosted_conversations WHERE id=?')
|
|
243
|
+
.get(conversationId);
|
|
244
|
+
if (row === undefined || stringColumn(row.user_storage_key) !== this.userStorageKey(userId))
|
|
245
|
+
throw new Error('HOSTED_CONVERSATION_NOT_AUTHORIZED');
|
|
246
|
+
return hostedConversationManifest(row);
|
|
247
|
+
}
|
|
248
|
+
async createConversation(manifest) {
|
|
249
|
+
const parsed = hostedConversationManifestSchema.parse(manifest);
|
|
250
|
+
if (parsed.nodeId !== this.options.nodeId)
|
|
251
|
+
throw new Error('HOSTED_CONVERSATION_STORAGE_INVALID');
|
|
252
|
+
if (parsed.clientRequestId !== undefined) {
|
|
253
|
+
const existing = this.options.database.raw
|
|
254
|
+
.prepare('SELECT * FROM hosted_conversations WHERE user_storage_key=? AND client_request_id=?')
|
|
255
|
+
.get(parsed.userStorageKey, parsed.clientRequestId);
|
|
256
|
+
if (existing !== undefined)
|
|
257
|
+
return hostedConversationManifest(existing);
|
|
258
|
+
}
|
|
259
|
+
const paths = this.activePaths(parsed.userStorageKey, parsed.conversationStorageKey);
|
|
260
|
+
await this.createConversationLayout(paths);
|
|
261
|
+
await this.writeManifest(paths.manifestPath, parsed);
|
|
262
|
+
const database = this.options.database.raw;
|
|
263
|
+
database.exec('BEGIN IMMEDIATE');
|
|
264
|
+
try {
|
|
265
|
+
this.insertConversation(parsed);
|
|
266
|
+
this.adjustVersionReferences([], versionReferences(parsed));
|
|
267
|
+
database.exec('COMMIT');
|
|
268
|
+
return parsed;
|
|
269
|
+
}
|
|
270
|
+
catch (error) {
|
|
271
|
+
database.exec('ROLLBACK');
|
|
272
|
+
await rm(paths.conversationDirectory, { recursive: true, force: true }).catch(() => undefined);
|
|
273
|
+
if (parsed.clientRequestId !== undefined && isUniqueConstraint(error)) {
|
|
274
|
+
const repeated = this.options.database.raw
|
|
275
|
+
.prepare('SELECT * FROM hosted_conversations WHERE user_storage_key=? AND client_request_id=?')
|
|
276
|
+
.get(parsed.userStorageKey, parsed.clientRequestId);
|
|
277
|
+
if (repeated !== undefined)
|
|
278
|
+
return hostedConversationManifest(repeated);
|
|
279
|
+
}
|
|
280
|
+
throw error;
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
async saveConversation(manifest) {
|
|
284
|
+
const parsed = hostedConversationManifestSchema.parse(manifest);
|
|
285
|
+
return this.withConversationMutation(parsed.id, () => this.saveConversationUnlocked(parsed));
|
|
286
|
+
}
|
|
287
|
+
async updateConversation(conversationId, update) {
|
|
288
|
+
return this.withConversationMutation(conversationId, () => {
|
|
289
|
+
const current = this.requireConversationById(conversationId);
|
|
290
|
+
const next = update(current);
|
|
291
|
+
return next === current ? current : this.saveConversationUnlocked(next);
|
|
292
|
+
});
|
|
293
|
+
}
|
|
294
|
+
async saveAutomaticTitle(conversationId, title, updatedAt) {
|
|
295
|
+
if (!Number.isSafeInteger(updatedAt) || updatedAt < 0)
|
|
296
|
+
throw new Error('HOSTED_CONVERSATION_INPUT_INVALID');
|
|
297
|
+
return this.withConversationMutation(conversationId, async () => {
|
|
298
|
+
const current = this.requireConversationById(conversationId);
|
|
299
|
+
if (current.titleSource !== 'AUTO' || current.title === title)
|
|
300
|
+
return undefined;
|
|
301
|
+
return this.saveConversationUnlocked({
|
|
302
|
+
...current,
|
|
303
|
+
title,
|
|
304
|
+
updatedAt: Math.max(current.updatedAt, updatedAt)
|
|
305
|
+
});
|
|
306
|
+
});
|
|
307
|
+
}
|
|
308
|
+
async saveMessageAcceptance(input) {
|
|
309
|
+
if (!Number.isSafeInteger(input.activityAt) || input.activityAt < 0)
|
|
310
|
+
throw new Error('HOSTED_CONVERSATION_INPUT_INVALID');
|
|
311
|
+
return this.withConversationMutation(input.conversationId, async () => {
|
|
312
|
+
const current = this.requireConversationById(input.conversationId);
|
|
313
|
+
if (input.templateVersion !== undefined &&
|
|
314
|
+
(current.activeVersionId !== input.templateVersion.expectedActiveVersionId ||
|
|
315
|
+
current.templateDeleted ||
|
|
316
|
+
current.status !== 'ACTIVE'))
|
|
317
|
+
throw new Error('HOSTED_CONVERSATION_STATE_INVALID');
|
|
318
|
+
const titleChanged = input.automaticTitle !== undefined &&
|
|
319
|
+
current.titleSource !== 'CUSTOM' &&
|
|
320
|
+
(current.titleSource !== 'AUTO' || input.automaticTitle !== current.title);
|
|
321
|
+
const conversation = await this.saveConversationUnlocked({
|
|
322
|
+
...current,
|
|
323
|
+
...(titleChanged ? { title: input.automaticTitle, titleSource: 'AUTO' } : {}),
|
|
324
|
+
...(input.templateVersion === undefined
|
|
325
|
+
? {}
|
|
326
|
+
: {
|
|
327
|
+
activeVersionId: input.templateVersion.activeVersionId,
|
|
328
|
+
quota: {
|
|
329
|
+
usedBytes: current.quota.usedBytes,
|
|
330
|
+
maxBytes: input.templateVersion.maxStorageBytes
|
|
331
|
+
}
|
|
332
|
+
}),
|
|
333
|
+
modelId: input.modelId,
|
|
334
|
+
updatedAt: Math.max(current.updatedAt, input.activityAt),
|
|
335
|
+
lastActivityAt: Math.max(current.lastActivityAt, input.activityAt)
|
|
336
|
+
});
|
|
337
|
+
return { conversation, titleChanged };
|
|
338
|
+
});
|
|
339
|
+
}
|
|
340
|
+
async saveConversationUnlocked(manifest) {
|
|
341
|
+
const parsed = hostedConversationManifestSchema.parse(manifest);
|
|
342
|
+
const current = this.requireConversationById(parsed.id);
|
|
343
|
+
const next = hostedConversationManifestSchema.parse({
|
|
344
|
+
...parsed,
|
|
345
|
+
updatedAt: Math.max(current.updatedAt, parsed.updatedAt),
|
|
346
|
+
lastActivityAt: Math.max(current.lastActivityAt, parsed.lastActivityAt)
|
|
347
|
+
});
|
|
348
|
+
if (current.userStorageKey !== next.userStorageKey ||
|
|
349
|
+
current.conversationStorageKey !== next.conversationStorageKey ||
|
|
350
|
+
current.nodeId !== next.nodeId ||
|
|
351
|
+
current.sessionId !== next.sessionId ||
|
|
352
|
+
current.clientRequestId !== next.clientRequestId)
|
|
353
|
+
throw new Error('HOSTED_CONVERSATION_STORAGE_INVALID');
|
|
354
|
+
const paths = this.activePaths(next.userStorageKey, next.conversationStorageKey);
|
|
355
|
+
await this.assertConversationLayout(paths);
|
|
356
|
+
await this.writeManifest(paths.manifestPath, next);
|
|
357
|
+
const database = this.options.database.raw;
|
|
358
|
+
database.exec('BEGIN IMMEDIATE');
|
|
359
|
+
try {
|
|
360
|
+
this.updateConversationRow(next);
|
|
361
|
+
this.adjustVersionReferences(versionReferences(current), versionReferences(next));
|
|
362
|
+
database.exec('COMMIT');
|
|
363
|
+
return next;
|
|
364
|
+
}
|
|
365
|
+
catch (error) {
|
|
366
|
+
database.exec('ROLLBACK');
|
|
367
|
+
await this.writeManifest(paths.manifestPath, current).catch(() => undefined);
|
|
368
|
+
throw error;
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
async rewriteManifestFromIndex(conversationId) {
|
|
372
|
+
return this.withConversationMutation(conversationId, () => this.rewriteManifestFromIndexUnlocked(conversationId));
|
|
373
|
+
}
|
|
374
|
+
async rewriteManifestFromIndexUnlocked(conversationId) {
|
|
375
|
+
const manifest = this.requireConversationById(conversationId);
|
|
376
|
+
const paths = this.activePaths(manifest.userStorageKey, manifest.conversationStorageKey);
|
|
377
|
+
await this.assertConversationLayout(paths);
|
|
378
|
+
await this.writeManifest(paths.manifestPath, manifest);
|
|
379
|
+
return manifest;
|
|
380
|
+
}
|
|
381
|
+
async retainConversationTemplate(userId, conversationId, updatedAt) {
|
|
382
|
+
if (!Number.isSafeInteger(updatedAt) || updatedAt < 0)
|
|
383
|
+
throw new Error('HOSTED_CONVERSATION_INPUT_INVALID');
|
|
384
|
+
const current = this.requireConversation(userId, conversationId);
|
|
385
|
+
const version = this.options.database.raw
|
|
386
|
+
.prepare('SELECT status FROM conversation_template_versions WHERE id=? AND template_id=?')
|
|
387
|
+
.get(current.activeVersionId, current.templateId);
|
|
388
|
+
if (version === undefined || !['AVAILABLE', 'RETAINED'].includes(stringColumn(version.status)))
|
|
389
|
+
throw new Error('CONVERSATION_TEMPLATE_VERSION_CORRUPTED');
|
|
390
|
+
if (current.templateDeleted && stringColumn(version.status) === 'RETAINED')
|
|
391
|
+
return current;
|
|
392
|
+
const next = hostedConversationManifestSchema.parse({
|
|
393
|
+
...current,
|
|
394
|
+
templateDeleted: true,
|
|
395
|
+
updatedAt: Math.max(current.updatedAt, updatedAt)
|
|
396
|
+
});
|
|
397
|
+
const paths = this.activePaths(next.userStorageKey, next.conversationStorageKey);
|
|
398
|
+
await this.assertConversationLayout(paths);
|
|
399
|
+
await this.writeManifest(paths.manifestPath, next);
|
|
400
|
+
const database = this.options.database.raw;
|
|
401
|
+
database.exec('BEGIN IMMEDIATE');
|
|
402
|
+
try {
|
|
403
|
+
this.updateConversationRow(next);
|
|
404
|
+
this.adjustVersionReferences(versionReferences(current), versionReferences(next));
|
|
405
|
+
const retained = database
|
|
406
|
+
.prepare(`UPDATE conversation_template_versions SET status='RETAINED'
|
|
407
|
+
WHERE id=? AND template_id=? AND status IN ('AVAILABLE','RETAINED')`)
|
|
408
|
+
.run(current.activeVersionId, current.templateId);
|
|
409
|
+
if (Number(retained.changes) !== 1)
|
|
410
|
+
throw new Error('CONVERSATION_TEMPLATE_VERSION_CORRUPTED');
|
|
411
|
+
database.exec('COMMIT');
|
|
412
|
+
return next;
|
|
413
|
+
}
|
|
414
|
+
catch (error) {
|
|
415
|
+
database.exec('ROLLBACK');
|
|
416
|
+
await this.writeManifest(paths.manifestPath, current).catch(() => undefined);
|
|
417
|
+
throw error;
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
fileProjectionId(conversationId, category, relativePath) {
|
|
421
|
+
if (!PROTOCOL_ID.test(conversationId))
|
|
422
|
+
throw new Error('HOSTED_CONVERSATION_FILE_INVALID');
|
|
423
|
+
const validated = conversationFileProjectionSchema.parse({
|
|
424
|
+
id: 'file_validation',
|
|
425
|
+
conversationId,
|
|
426
|
+
category,
|
|
427
|
+
relativePath,
|
|
428
|
+
displayName: relativePath.split('/').at(-1) ?? relativePath,
|
|
429
|
+
mimeType: 'application/octet-stream',
|
|
430
|
+
size: 0,
|
|
431
|
+
source: category === 'UPLOAD' ? 'USER' : 'AGENT',
|
|
432
|
+
createdAt: 0,
|
|
433
|
+
updatedAt: 0
|
|
434
|
+
});
|
|
435
|
+
return `file_${createHash('sha256')
|
|
436
|
+
.update(`myagentroam-hosted-file\0${this.options.nodeId}\0${conversationId}\0${validated.category}\0${validated.relativePath}`)
|
|
437
|
+
.digest('base64url')}`;
|
|
438
|
+
}
|
|
439
|
+
async reconcileFiles(userId, conversationId) {
|
|
440
|
+
return this.withConversationMutation(conversationId, async () => {
|
|
441
|
+
const manifest = this.requireConversation(userId, conversationId);
|
|
442
|
+
const paths = this.activePaths(manifest.userStorageKey, manifest.conversationStorageKey);
|
|
443
|
+
await this.assertConversationLayout(paths);
|
|
444
|
+
const existing = this.existingFiles(conversationId);
|
|
445
|
+
const files = await this.scanConversationFiles(manifest, paths, existing);
|
|
446
|
+
await this.replaceConversationFiles(manifest, paths, files);
|
|
447
|
+
return files;
|
|
448
|
+
});
|
|
449
|
+
}
|
|
450
|
+
listFiles(userId, conversationId) {
|
|
451
|
+
this.requireConversation(userId, conversationId);
|
|
452
|
+
return this.options.database.raw
|
|
453
|
+
.prepare(`SELECT id,conversation_id,category,relative_path,display_name,mime_type,size,source,
|
|
454
|
+
turn_id,item_id,created_at,updated_at
|
|
455
|
+
FROM conversation_files
|
|
456
|
+
WHERE conversation_id=?
|
|
457
|
+
ORDER BY updated_at DESC,relative_path,category`)
|
|
458
|
+
.all(conversationId).map(conversationFileProjection);
|
|
459
|
+
}
|
|
460
|
+
requireFile(userId, conversationId, fileId) {
|
|
461
|
+
this.requireConversation(userId, conversationId);
|
|
462
|
+
const row = this.options.database.raw
|
|
463
|
+
.prepare(`SELECT id,conversation_id,category,relative_path,display_name,mime_type,size,source,
|
|
464
|
+
turn_id,item_id,created_at,updated_at
|
|
465
|
+
FROM conversation_files WHERE id=? AND conversation_id=?`)
|
|
466
|
+
.get(fileId, conversationId);
|
|
467
|
+
if (row === undefined)
|
|
468
|
+
throw new Error('HOSTED_CONVERSATION_FILE_NOT_FOUND');
|
|
469
|
+
return conversationFileProjection(row);
|
|
470
|
+
}
|
|
471
|
+
filePath(userId, file) {
|
|
472
|
+
const paths = this.pathsForConversation(userId, file.conversationId);
|
|
473
|
+
const root = file.category === 'UPLOAD' ? paths.uploadsDirectory : paths.outputDirectory;
|
|
474
|
+
return safeRelativePath(root, file.relativePath);
|
|
475
|
+
}
|
|
476
|
+
async deleteFile(userId, conversationId, fileId, deletedAt) {
|
|
477
|
+
if (!Number.isSafeInteger(deletedAt) || deletedAt < 0)
|
|
478
|
+
throw new Error('HOSTED_CONVERSATION_INPUT_INVALID');
|
|
479
|
+
return this.withConversationMutation(conversationId, () => this.deleteFileUnlocked(userId, conversationId, fileId, deletedAt));
|
|
480
|
+
}
|
|
481
|
+
async deleteFileUnlocked(userId, conversationId, fileId, deletedAt) {
|
|
482
|
+
const manifest = this.requireConversation(userId, conversationId);
|
|
483
|
+
const file = this.requireFile(userId, conversationId, fileId);
|
|
484
|
+
const paths = this.activePaths(manifest.userStorageKey, manifest.conversationStorageKey);
|
|
485
|
+
await this.assertConversationLayout(paths);
|
|
486
|
+
const source = this.filePath(userId, file);
|
|
487
|
+
const metadata = await lstat(source).catch((error) => {
|
|
488
|
+
if (error.code === 'ENOENT')
|
|
489
|
+
throw new Error('HOSTED_CONVERSATION_FILE_NOT_FOUND');
|
|
490
|
+
throw error;
|
|
491
|
+
});
|
|
492
|
+
if (!metadata.isFile() || metadata.isSymbolicLink() || metadata.nlink !== 1)
|
|
493
|
+
throw new Error('HOSTED_CONVERSATION_FILE_INVALID');
|
|
494
|
+
if (metadata.size !== file.size || safeFileTimestamp(metadata.mtimeMs) !== file.updatedAt)
|
|
495
|
+
throw new Error('HOSTED_CONVERSATION_FILE_CONFLICT');
|
|
496
|
+
const tombstone = join(paths.temporaryRootDirectory, `.deleted-${randomUUID()}`);
|
|
497
|
+
await rename(source, tombstone).catch((error) => {
|
|
498
|
+
if (error.code === 'ENOENT')
|
|
499
|
+
throw new Error('HOSTED_CONVERSATION_FILE_NOT_FOUND');
|
|
500
|
+
throw error;
|
|
501
|
+
});
|
|
502
|
+
try {
|
|
503
|
+
const moved = await lstat(tombstone);
|
|
504
|
+
if (!moved.isFile() ||
|
|
505
|
+
moved.isSymbolicLink() ||
|
|
506
|
+
moved.nlink !== 1 ||
|
|
507
|
+
moved.size !== file.size ||
|
|
508
|
+
safeFileTimestamp(moved.mtimeMs) !== file.updatedAt)
|
|
509
|
+
throw new Error('HOSTED_CONVERSATION_FILE_CONFLICT');
|
|
510
|
+
const existing = this.existingFiles(conversationId);
|
|
511
|
+
const files = await this.scanConversationFiles(manifest, paths, existing);
|
|
512
|
+
if (files.some((candidate) => candidate.id === file.id)) {
|
|
513
|
+
await rm(tombstone, { force: true }).catch(() => undefined);
|
|
514
|
+
await this.replaceConversationFiles(manifest, paths, files);
|
|
515
|
+
throw new Error('HOSTED_CONVERSATION_FILE_CONFLICT');
|
|
516
|
+
}
|
|
517
|
+
await this.replaceConversationFiles(manifest, paths, files, deletedAt);
|
|
518
|
+
await rm(tombstone, { force: true }).catch(() => undefined);
|
|
519
|
+
return files;
|
|
520
|
+
}
|
|
521
|
+
catch (error) {
|
|
522
|
+
const sourceState = await lstat(source).catch((sourceError) => {
|
|
523
|
+
if (sourceError.code === 'ENOENT')
|
|
524
|
+
return undefined;
|
|
525
|
+
throw sourceError;
|
|
526
|
+
});
|
|
527
|
+
if (sourceState === undefined) {
|
|
528
|
+
await rename(tombstone, source).catch(() => {
|
|
529
|
+
throw new Error('HOSTED_CONVERSATION_STORAGE_INVALID');
|
|
530
|
+
});
|
|
531
|
+
}
|
|
532
|
+
else {
|
|
533
|
+
await rm(tombstone, { force: true }).catch(() => undefined);
|
|
534
|
+
}
|
|
535
|
+
throw error;
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
async registerFile(userId, file) {
|
|
539
|
+
const input = conversationFileProjectionSchema.parse(file);
|
|
540
|
+
return this.withConversationMutation(input.conversationId, () => this.registerFileUnlocked(userId, input));
|
|
541
|
+
}
|
|
542
|
+
async registerFileUnlocked(userId, input) {
|
|
543
|
+
const manifest = this.requireConversation(userId, input.conversationId);
|
|
544
|
+
const path = this.filePath(userId, input);
|
|
545
|
+
const metadata = await lstat(path).catch((error) => {
|
|
546
|
+
if (error.code === 'ENOENT')
|
|
547
|
+
throw new Error('HOSTED_CONVERSATION_FILE_NOT_FOUND');
|
|
548
|
+
throw error;
|
|
549
|
+
});
|
|
550
|
+
if (!metadata.isFile() ||
|
|
551
|
+
metadata.isSymbolicLink() ||
|
|
552
|
+
metadata.nlink !== 1 ||
|
|
553
|
+
metadata.size !== input.size)
|
|
554
|
+
throw new Error('HOSTED_CONVERSATION_FILE_INVALID');
|
|
555
|
+
const modifiedAt = safeFileTimestamp(metadata.mtimeMs);
|
|
556
|
+
const parsed = conversationFileProjectionSchema.parse({
|
|
557
|
+
...input,
|
|
558
|
+
createdAt: Math.min(input.createdAt, modifiedAt),
|
|
559
|
+
updatedAt: modifiedAt
|
|
560
|
+
});
|
|
561
|
+
if (manifest.quota.usedBytes + parsed.size > manifest.quota.maxBytes)
|
|
562
|
+
throw new Error('HOSTED_CONVERSATION_QUOTA_EXCEEDED');
|
|
563
|
+
const database = this.options.database.raw;
|
|
564
|
+
database.exec('BEGIN IMMEDIATE');
|
|
565
|
+
try {
|
|
566
|
+
database
|
|
567
|
+
.prepare(`INSERT INTO conversation_files
|
|
568
|
+
(id,conversation_id,category,relative_path,display_name,mime_type,size,source,
|
|
569
|
+
turn_id,item_id,created_at,updated_at)
|
|
570
|
+
VALUES (?,?,?,?,?,?,?,?,?,?,?,?)`)
|
|
571
|
+
.run(parsed.id, parsed.conversationId, parsed.category, parsed.relativePath, parsed.displayName, parsed.mimeType, parsed.size, parsed.source, parsed.turnId ?? null, parsed.itemId ?? null, parsed.createdAt, parsed.updatedAt);
|
|
572
|
+
const update = database
|
|
573
|
+
.prepare(`UPDATE hosted_conversations
|
|
574
|
+
SET used_bytes=used_bytes+?,
|
|
575
|
+
updated_at=MAX(updated_at,?),
|
|
576
|
+
last_activity_at=MAX(last_activity_at,?)
|
|
577
|
+
WHERE id=? AND used_bytes+?<=max_bytes`)
|
|
578
|
+
.run(parsed.size, parsed.updatedAt, parsed.updatedAt, parsed.conversationId, parsed.size);
|
|
579
|
+
if (Number(update.changes) !== 1)
|
|
580
|
+
throw new Error('HOSTED_CONVERSATION_QUOTA_EXCEEDED');
|
|
581
|
+
database.exec('COMMIT');
|
|
582
|
+
}
|
|
583
|
+
catch (error) {
|
|
584
|
+
database.exec('ROLLBACK');
|
|
585
|
+
if (isUniqueConstraint(error))
|
|
586
|
+
throw new Error('HOSTED_CONVERSATION_FILE_CONFLICT');
|
|
587
|
+
throw error;
|
|
588
|
+
}
|
|
589
|
+
try {
|
|
590
|
+
await this.rewriteManifestFromIndexUnlocked(parsed.conversationId);
|
|
591
|
+
}
|
|
592
|
+
catch (error) {
|
|
593
|
+
database.exec('BEGIN IMMEDIATE');
|
|
594
|
+
try {
|
|
595
|
+
database.prepare('DELETE FROM conversation_files WHERE id=?').run(parsed.id);
|
|
596
|
+
database
|
|
597
|
+
.prepare(`UPDATE hosted_conversations
|
|
598
|
+
SET used_bytes=CASE WHEN used_bytes>=? THEN used_bytes-? ELSE 0 END
|
|
599
|
+
WHERE id=?`)
|
|
600
|
+
.run(parsed.size, parsed.size, parsed.conversationId);
|
|
601
|
+
database.exec('COMMIT');
|
|
602
|
+
}
|
|
603
|
+
catch {
|
|
604
|
+
database.exec('ROLLBACK');
|
|
605
|
+
}
|
|
606
|
+
throw error;
|
|
607
|
+
}
|
|
608
|
+
return parsed;
|
|
609
|
+
}
|
|
610
|
+
findMessage(userId, conversationId, clientMessageId) {
|
|
611
|
+
this.requireConversation(userId, conversationId);
|
|
612
|
+
const row = this.options.database.raw
|
|
613
|
+
.prepare(`SELECT conversation_id,client_message_id,run_id,user_text_present,status,created_at,updated_at
|
|
614
|
+
FROM hosted_conversation_messages
|
|
615
|
+
WHERE conversation_id=? AND client_message_id=?`)
|
|
616
|
+
.get(conversationId, clientMessageId);
|
|
617
|
+
return row === undefined ? undefined : hostedConversationMessage(row);
|
|
618
|
+
}
|
|
619
|
+
hasNonEmptyUserMessage(userId, conversationId) {
|
|
620
|
+
this.requireConversation(userId, conversationId);
|
|
621
|
+
return (this.options.database.raw
|
|
622
|
+
.prepare(`SELECT 1
|
|
623
|
+
FROM hosted_conversation_messages
|
|
624
|
+
WHERE conversation_id=? AND user_text_present=1
|
|
625
|
+
LIMIT 1`)
|
|
626
|
+
.get(conversationId) !== undefined);
|
|
627
|
+
}
|
|
628
|
+
createMessage(record) {
|
|
629
|
+
this.options.database.raw
|
|
630
|
+
.prepare(`INSERT INTO hosted_conversation_messages
|
|
631
|
+
(conversation_id,client_message_id,run_id,user_text_present,status,created_at,updated_at)
|
|
632
|
+
VALUES (?,?,?,?,?,?,?)`)
|
|
633
|
+
.run(record.conversationId, record.clientMessageId, record.runId, record.userTextPresent ? 1 : 0, record.status, record.createdAt, record.updatedAt);
|
|
634
|
+
return record;
|
|
635
|
+
}
|
|
636
|
+
finishMessage(conversationId, clientMessageId, status, updatedAt) {
|
|
637
|
+
this.options.database.raw
|
|
638
|
+
.prepare(`UPDATE hosted_conversation_messages
|
|
639
|
+
SET status=?,updated_at=?
|
|
640
|
+
WHERE conversation_id=? AND client_message_id=?`)
|
|
641
|
+
.run(status, updatedAt, conversationId, clientMessageId);
|
|
642
|
+
}
|
|
643
|
+
async rebuildConversationIndex() {
|
|
644
|
+
const existing = this.existingFilesByConversation();
|
|
645
|
+
const rebuilt = await this.scanConversationRoot(this.usersDirectory, existing);
|
|
646
|
+
const ids = new Set();
|
|
647
|
+
for (const item of rebuilt) {
|
|
648
|
+
if (ids.has(item.manifest.id))
|
|
649
|
+
throw new Error('HOSTED_CONVERSATION_STORAGE_INVALID');
|
|
650
|
+
ids.add(item.manifest.id);
|
|
651
|
+
}
|
|
652
|
+
this.replaceConversationIndex(rebuilt);
|
|
653
|
+
return rebuilt.map((item) => item.manifest);
|
|
654
|
+
}
|
|
655
|
+
async recoverGarbage() {
|
|
656
|
+
for (const entry of await sortedEntries(this.garbageDirectory))
|
|
657
|
+
await rm(join(this.garbageDirectory, entry.name), { recursive: true, force: true });
|
|
658
|
+
}
|
|
659
|
+
async scanConversationRoot(rootDirectory, existing) {
|
|
660
|
+
const rebuilt = [];
|
|
661
|
+
const root = await realpath(rootDirectory);
|
|
662
|
+
for (const user of await sortedEntries(rootDirectory)) {
|
|
663
|
+
if (user.isSymbolicLink() || !user.isDirectory() || !STORAGE_KEY.test(user.name))
|
|
664
|
+
throw new Error('HOSTED_CONVERSATION_STORAGE_INVALID');
|
|
665
|
+
const sessionsDirectory = join(rootDirectory, user.name, 'sessions');
|
|
666
|
+
const sessionsInfo = await lstat(sessionsDirectory).catch((error) => {
|
|
667
|
+
if (error.code === 'ENOENT')
|
|
668
|
+
return undefined;
|
|
669
|
+
throw error;
|
|
670
|
+
});
|
|
671
|
+
if (sessionsInfo === undefined)
|
|
672
|
+
continue;
|
|
673
|
+
if (!sessionsInfo.isDirectory() || sessionsInfo.isSymbolicLink())
|
|
674
|
+
throw new Error('HOSTED_CONVERSATION_STORAGE_INVALID');
|
|
675
|
+
const actualSessions = await realpath(sessionsDirectory);
|
|
676
|
+
if (!within(root, actualSessions))
|
|
677
|
+
throw new Error('HOSTED_CONVERSATION_STORAGE_INVALID');
|
|
678
|
+
for (const conversation of await sortedEntries(sessionsDirectory)) {
|
|
679
|
+
if (conversation.isSymbolicLink() ||
|
|
680
|
+
!conversation.isDirectory() ||
|
|
681
|
+
!STORAGE_KEY.test(conversation.name))
|
|
682
|
+
throw new Error('HOSTED_CONVERSATION_STORAGE_INVALID');
|
|
683
|
+
const directory = join(sessionsDirectory, conversation.name);
|
|
684
|
+
const actual = await realpath(directory);
|
|
685
|
+
if (!within(actualSessions, actual))
|
|
686
|
+
throw new Error('HOSTED_CONVERSATION_STORAGE_INVALID');
|
|
687
|
+
const paths = conversationPaths(directory);
|
|
688
|
+
await this.assertConversationLayout(paths);
|
|
689
|
+
let manifest;
|
|
690
|
+
let manifestNeedsUpgrade = false;
|
|
691
|
+
try {
|
|
692
|
+
const stored = storedHostedConversationManifest(JSON.parse(await readFile(paths.manifestPath, 'utf8')));
|
|
693
|
+
manifest = stored.manifest;
|
|
694
|
+
manifestNeedsUpgrade = stored.upgraded;
|
|
695
|
+
}
|
|
696
|
+
catch {
|
|
697
|
+
throw new Error('HOSTED_CONVERSATION_STORAGE_INVALID');
|
|
698
|
+
}
|
|
699
|
+
if (manifest.nodeId !== this.options.nodeId ||
|
|
700
|
+
manifest.userStorageKey !== user.name ||
|
|
701
|
+
manifest.conversationStorageKey !== conversation.name)
|
|
702
|
+
throw new Error('HOSTED_CONVERSATION_STORAGE_INVALID');
|
|
703
|
+
const indexed = existing.get(manifest.id) ?? new Map();
|
|
704
|
+
await this.cleanupRestartTransients(paths, indexed);
|
|
705
|
+
const files = await this.scanConversationFiles(manifest, paths, indexed);
|
|
706
|
+
const usedBytes = this.assertFileQuotas(manifest, files);
|
|
707
|
+
const next = usedBytes === manifest.quota.usedBytes
|
|
708
|
+
? manifest
|
|
709
|
+
: hostedConversationManifestSchema.parse({
|
|
710
|
+
...manifest,
|
|
711
|
+
quota: { ...manifest.quota, usedBytes }
|
|
712
|
+
});
|
|
713
|
+
if (manifestNeedsUpgrade || next !== manifest)
|
|
714
|
+
await this.writeManifest(paths.manifestPath, next);
|
|
715
|
+
rebuilt.push({ manifest: next, files });
|
|
716
|
+
}
|
|
717
|
+
}
|
|
718
|
+
return rebuilt;
|
|
719
|
+
}
|
|
720
|
+
existingFilesByConversation() {
|
|
721
|
+
const files = this.options.database.raw
|
|
722
|
+
.prepare(`SELECT id,conversation_id,category,relative_path,display_name,mime_type,size,source,
|
|
723
|
+
turn_id,item_id,created_at,updated_at
|
|
724
|
+
FROM conversation_files`)
|
|
725
|
+
.all();
|
|
726
|
+
const byConversation = new Map();
|
|
727
|
+
for (const row of files) {
|
|
728
|
+
const file = conversationFileProjection(row);
|
|
729
|
+
let indexed = byConversation.get(file.conversationId);
|
|
730
|
+
if (indexed === undefined) {
|
|
731
|
+
indexed = new Map();
|
|
732
|
+
byConversation.set(file.conversationId, indexed);
|
|
733
|
+
}
|
|
734
|
+
indexed.set(fileProjectionKey(file.category, file.relativePath), file);
|
|
735
|
+
}
|
|
736
|
+
return byConversation;
|
|
737
|
+
}
|
|
738
|
+
existingFiles(conversationId) {
|
|
739
|
+
return this.existingFilesByConversation().get(conversationId) ?? new Map();
|
|
740
|
+
}
|
|
741
|
+
async cleanupRestartTransients(paths, existing) {
|
|
742
|
+
for (const entry of await sortedEntries(paths.temporaryRootDirectory))
|
|
743
|
+
await rm(join(paths.temporaryRootDirectory, entry.name), { recursive: true, force: true });
|
|
744
|
+
for (const entry of await sortedEntries(paths.uploadsDirectory)) {
|
|
745
|
+
if (!/^\.[A-Za-z0-9][A-Za-z0-9._:-]{0,159}\.upload$/u.test(entry.name))
|
|
746
|
+
continue;
|
|
747
|
+
if (existing.has(fileProjectionKey('UPLOAD', entry.name)))
|
|
748
|
+
continue;
|
|
749
|
+
await rm(join(paths.uploadsDirectory, entry.name), { recursive: true, force: true });
|
|
750
|
+
}
|
|
751
|
+
}
|
|
752
|
+
async scanConversationFiles(manifest, paths, existing) {
|
|
753
|
+
const files = [];
|
|
754
|
+
for (const [category, root] of [
|
|
755
|
+
['UPLOAD', paths.uploadsDirectory],
|
|
756
|
+
['OUTPUT', paths.outputDirectory]
|
|
757
|
+
])
|
|
758
|
+
await this.scanProjectedDirectory(manifest, category, root, root, existing, files);
|
|
759
|
+
return files.sort((left, right) => fileProjectionKey(left.category, left.relativePath).localeCompare(fileProjectionKey(right.category, right.relativePath), 'en-US'));
|
|
760
|
+
}
|
|
761
|
+
async scanProjectedDirectory(manifest, category, root, directory, existing, output) {
|
|
762
|
+
for (const entry of await sortedEntries(directory)) {
|
|
763
|
+
const path = join(directory, entry.name);
|
|
764
|
+
if (entry.isSymbolicLink())
|
|
765
|
+
throw new Error('HOSTED_CONVERSATION_FILE_INVALID');
|
|
766
|
+
if (entry.isDirectory()) {
|
|
767
|
+
await this.scanProjectedDirectory(manifest, category, root, path, existing, output);
|
|
768
|
+
continue;
|
|
769
|
+
}
|
|
770
|
+
if (!entry.isFile())
|
|
771
|
+
throw new Error('HOSTED_CONVERSATION_FILE_INVALID');
|
|
772
|
+
const relativePath = relative(root, path).split(sep).join('/');
|
|
773
|
+
if (category === 'UPLOAD' &&
|
|
774
|
+
/^\.[A-Za-z0-9][A-Za-z0-9._:-]{0,159}\.upload$/u.test(relativePath) &&
|
|
775
|
+
!existing.has(fileProjectionKey(category, relativePath)))
|
|
776
|
+
continue;
|
|
777
|
+
const metadata = await lstat(path);
|
|
778
|
+
if (!metadata.isFile() || metadata.isSymbolicLink() || metadata.nlink !== 1)
|
|
779
|
+
throw new Error('HOSTED_CONVERSATION_FILE_INVALID');
|
|
780
|
+
if (!Number.isSafeInteger(metadata.size) || metadata.size < 0)
|
|
781
|
+
throw new Error('HOSTED_CONVERSATION_FILE_INVALID');
|
|
782
|
+
const key = fileProjectionKey(category, relativePath);
|
|
783
|
+
const previous = existing.get(key);
|
|
784
|
+
const modifiedAt = safeFileTimestamp(metadata.mtimeMs);
|
|
785
|
+
const createdAt = previous?.createdAt ?? safeFileTimestamp(metadata.birthtimeMs || metadata.ctimeMs);
|
|
786
|
+
output.push(conversationFileProjectionSchema.parse({
|
|
787
|
+
id: previous?.id ?? this.fileProjectionId(manifest.id, category, relativePath),
|
|
788
|
+
conversationId: manifest.id,
|
|
789
|
+
category,
|
|
790
|
+
relativePath,
|
|
791
|
+
displayName: relativePath.split('/').at(-1) ?? relativePath,
|
|
792
|
+
mimeType: previous?.mimeType ?? inferMimeType(relativePath),
|
|
793
|
+
size: metadata.size,
|
|
794
|
+
source: previous?.source ?? (category === 'UPLOAD' ? 'USER' : 'AGENT'),
|
|
795
|
+
...(previous?.turnId === undefined ? {} : { turnId: previous.turnId }),
|
|
796
|
+
...(previous?.itemId === undefined ? {} : { itemId: previous.itemId }),
|
|
797
|
+
createdAt,
|
|
798
|
+
updatedAt: Math.max(createdAt, modifiedAt)
|
|
799
|
+
}));
|
|
800
|
+
}
|
|
801
|
+
}
|
|
802
|
+
async replaceConversationFiles(manifest, paths, files, activityAt = 0) {
|
|
803
|
+
const usedBytes = this.assertFileQuotas(manifest, files);
|
|
804
|
+
const latestFileAt = files.reduce((latest, file) => Math.max(latest, file.updatedAt), 0);
|
|
805
|
+
const next = hostedConversationManifestSchema.parse({
|
|
806
|
+
...manifest,
|
|
807
|
+
updatedAt: Math.max(manifest.updatedAt, latestFileAt, activityAt),
|
|
808
|
+
lastActivityAt: Math.max(manifest.lastActivityAt, latestFileAt, activityAt),
|
|
809
|
+
quota: { ...manifest.quota, usedBytes }
|
|
810
|
+
});
|
|
811
|
+
await this.writeManifest(paths.manifestPath, next);
|
|
812
|
+
const database = this.options.database.raw;
|
|
813
|
+
database.exec('BEGIN IMMEDIATE');
|
|
814
|
+
try {
|
|
815
|
+
database.prepare('DELETE FROM conversation_files WHERE conversation_id=?').run(manifest.id);
|
|
816
|
+
const insert = conversationFileInsert(database);
|
|
817
|
+
for (const file of files)
|
|
818
|
+
insertConversationFile(insert, file);
|
|
819
|
+
this.updateConversationRow(next);
|
|
820
|
+
database.exec('COMMIT');
|
|
821
|
+
}
|
|
822
|
+
catch (error) {
|
|
823
|
+
database.exec('ROLLBACK');
|
|
824
|
+
await this.writeManifest(paths.manifestPath, manifest).catch(() => undefined);
|
|
825
|
+
throw error;
|
|
826
|
+
}
|
|
827
|
+
}
|
|
828
|
+
assertFileQuotas(manifest, files) {
|
|
829
|
+
const usedBytes = files.reduce((sum, file) => sum + file.size, 0);
|
|
830
|
+
if (usedBytes > manifest.quota.maxBytes)
|
|
831
|
+
throw new Error('HOSTED_CONVERSATION_QUOTA_EXCEEDED');
|
|
832
|
+
return usedBytes;
|
|
833
|
+
}
|
|
834
|
+
encodeConversationCursor(userStorageKey, limit, pinned, lastActivityAt, id) {
|
|
835
|
+
const cursor = {
|
|
836
|
+
cursorVersion: HOSTED_CONVERSATION_CURSOR_VERSION,
|
|
837
|
+
sortVersion: HOSTED_CONVERSATION_SORT_VERSION,
|
|
838
|
+
limit,
|
|
839
|
+
pinned,
|
|
840
|
+
lastActivityAt,
|
|
841
|
+
id,
|
|
842
|
+
binding: this.conversationCursorBinding(userStorageKey, limit, pinned, lastActivityAt, id)
|
|
843
|
+
};
|
|
844
|
+
return Buffer.from(JSON.stringify(cursor), 'utf8').toString('base64url');
|
|
845
|
+
}
|
|
846
|
+
decodeConversationCursor(cursor, userStorageKey, limit) {
|
|
847
|
+
try {
|
|
848
|
+
if (cursor.length === 0 || cursor.length > 2_048 || !/^[A-Za-z0-9_-]+$/u.test(cursor))
|
|
849
|
+
throw new Error('invalid cursor encoding');
|
|
850
|
+
const decoded = Buffer.from(cursor, 'base64url');
|
|
851
|
+
if (decoded.toString('base64url') !== cursor)
|
|
852
|
+
throw new Error('non-canonical cursor');
|
|
853
|
+
const value = JSON.parse(decoded.toString('utf8'));
|
|
854
|
+
if (!isHostedConversationCursor(value))
|
|
855
|
+
throw new Error('invalid cursor payload');
|
|
856
|
+
if (value.cursorVersion !== HOSTED_CONVERSATION_CURSOR_VERSION ||
|
|
857
|
+
value.sortVersion !== HOSTED_CONVERSATION_SORT_VERSION ||
|
|
858
|
+
value.limit !== limit ||
|
|
859
|
+
value.binding !==
|
|
860
|
+
this.conversationCursorBinding(userStorageKey, value.limit, value.pinned, value.lastActivityAt, value.id))
|
|
861
|
+
throw new Error('cursor binding mismatch');
|
|
862
|
+
return value;
|
|
863
|
+
}
|
|
864
|
+
catch {
|
|
865
|
+
throw new Error('HOSTED_CONVERSATION_CURSOR_INVALID');
|
|
866
|
+
}
|
|
867
|
+
}
|
|
868
|
+
conversationCursorBinding(userStorageKey, limit, pinned, lastActivityAt, id) {
|
|
869
|
+
return createHash('sha256')
|
|
870
|
+
.update([
|
|
871
|
+
'myagentroam-hosted-conversation-cursor',
|
|
872
|
+
this.options.nodeId,
|
|
873
|
+
userStorageKey,
|
|
874
|
+
String(HOSTED_CONVERSATION_SORT_VERSION),
|
|
875
|
+
String(limit),
|
|
876
|
+
String(pinned),
|
|
877
|
+
String(lastActivityAt),
|
|
878
|
+
id
|
|
879
|
+
].join('\0'))
|
|
880
|
+
.digest('base64url');
|
|
881
|
+
}
|
|
882
|
+
requireConversationById(conversationId) {
|
|
883
|
+
const row = this.options.database.raw
|
|
884
|
+
.prepare('SELECT * FROM hosted_conversations WHERE id=?')
|
|
885
|
+
.get(conversationId);
|
|
886
|
+
if (row === undefined)
|
|
887
|
+
throw new Error('HOSTED_CONVERSATION_NOT_FOUND');
|
|
888
|
+
return hostedConversationManifest(row);
|
|
889
|
+
}
|
|
890
|
+
activePaths(userStorageKey, conversationStorageKey) {
|
|
891
|
+
return conversationPaths(this.conversationDirectory(userStorageKey, conversationStorageKey));
|
|
892
|
+
}
|
|
893
|
+
async prepareTemporaryDirectory(conversation) {
|
|
894
|
+
await this.ensureTemporaryNodeDirectory();
|
|
895
|
+
const userDirectory = childPath(this.temporaryNodeDirectory, conversation.userStorageKey);
|
|
896
|
+
await this.ensureDirectory(userDirectory, this.temporaryNodeDirectory);
|
|
897
|
+
const conversationDirectory = childPath(userDirectory, conversation.conversationStorageKey);
|
|
898
|
+
await this.ensureDirectory(conversationDirectory, userDirectory);
|
|
899
|
+
return conversationDirectory;
|
|
900
|
+
}
|
|
901
|
+
async removeTemporaryDirectory(conversation) {
|
|
902
|
+
try {
|
|
903
|
+
const directory = await this.prepareTemporaryDirectory(conversation);
|
|
904
|
+
await rm(directory, { recursive: true, force: true });
|
|
905
|
+
}
|
|
906
|
+
catch {
|
|
907
|
+
// Host temporary storage is best-effort and may already be unavailable.
|
|
908
|
+
}
|
|
909
|
+
}
|
|
910
|
+
async ensureTemporaryNodeDirectory() {
|
|
911
|
+
await mkdir(this.temporaryRootDirectory, { recursive: true, mode: 0o700 });
|
|
912
|
+
const metadata = await lstat(this.temporaryRootDirectory);
|
|
913
|
+
if (!metadata.isDirectory() || metadata.isSymbolicLink())
|
|
914
|
+
throw new Error('HOSTED_CONVERSATION_STORAGE_INVALID');
|
|
915
|
+
const actualRoot = await realpath(this.temporaryRootDirectory);
|
|
916
|
+
if (actualRoot !== this.temporaryRootDirectory)
|
|
917
|
+
throw new Error('HOSTED_CONVERSATION_STORAGE_INVALID');
|
|
918
|
+
await this.ensureDirectory(this.temporaryNodeDirectory, this.temporaryRootDirectory);
|
|
919
|
+
}
|
|
920
|
+
async createConversationLayout(paths) {
|
|
921
|
+
const userDirectory = dirname(dirname(paths.conversationDirectory));
|
|
922
|
+
const sessionsDirectory = dirname(paths.conversationDirectory);
|
|
923
|
+
await this.ensureDirectory(userDirectory, this.usersDirectory);
|
|
924
|
+
await this.ensureDirectory(sessionsDirectory, userDirectory);
|
|
925
|
+
await this.ensureDirectory(paths.conversationDirectory, sessionsDirectory);
|
|
926
|
+
for (const directory of [
|
|
927
|
+
paths.manifestDirectory,
|
|
928
|
+
paths.homeDirectory,
|
|
929
|
+
paths.dataDirectory,
|
|
930
|
+
paths.uploadsDirectory,
|
|
931
|
+
paths.outputDirectory,
|
|
932
|
+
paths.temporaryRootDirectory,
|
|
933
|
+
paths.runtimeDirectory,
|
|
934
|
+
paths.templateBindingDirectory,
|
|
935
|
+
paths.fileIndexDirectory,
|
|
936
|
+
paths.quotaDirectory
|
|
937
|
+
])
|
|
938
|
+
await this.ensureDirectory(directory, paths.conversationDirectory);
|
|
939
|
+
}
|
|
940
|
+
async assertConversationLayout(paths) {
|
|
941
|
+
const metadata = await lstat(paths.conversationDirectory).catch(() => {
|
|
942
|
+
throw new Error('HOSTED_CONVERSATION_STORAGE_INVALID');
|
|
943
|
+
});
|
|
944
|
+
if (!metadata.isDirectory() || metadata.isSymbolicLink())
|
|
945
|
+
throw new Error('HOSTED_CONVERSATION_STORAGE_INVALID');
|
|
946
|
+
const root = await realpath(paths.conversationDirectory);
|
|
947
|
+
if (root !== resolve(paths.conversationDirectory))
|
|
948
|
+
throw new Error('HOSTED_CONVERSATION_STORAGE_INVALID');
|
|
949
|
+
for (const directory of [
|
|
950
|
+
paths.manifestDirectory,
|
|
951
|
+
paths.homeDirectory,
|
|
952
|
+
paths.dataDirectory,
|
|
953
|
+
paths.uploadsDirectory,
|
|
954
|
+
paths.outputDirectory,
|
|
955
|
+
paths.temporaryRootDirectory,
|
|
956
|
+
paths.runtimeDirectory,
|
|
957
|
+
paths.templateBindingDirectory,
|
|
958
|
+
paths.fileIndexDirectory,
|
|
959
|
+
paths.quotaDirectory
|
|
960
|
+
]) {
|
|
961
|
+
const directoryMetadata = await lstat(directory).catch(() => {
|
|
962
|
+
throw new Error('HOSTED_CONVERSATION_STORAGE_INVALID');
|
|
963
|
+
});
|
|
964
|
+
if (!directoryMetadata.isDirectory() || directoryMetadata.isSymbolicLink())
|
|
965
|
+
throw new Error('HOSTED_CONVERSATION_STORAGE_INVALID');
|
|
966
|
+
const actual = await realpath(directory);
|
|
967
|
+
if (!within(root, actual))
|
|
968
|
+
throw new Error('HOSTED_CONVERSATION_STORAGE_INVALID');
|
|
969
|
+
}
|
|
970
|
+
}
|
|
971
|
+
async ensureDirectory(path, root) {
|
|
972
|
+
await mkdir(path, { mode: 0o700 }).catch((error) => {
|
|
973
|
+
if (error.code !== 'EEXIST')
|
|
974
|
+
throw error;
|
|
975
|
+
});
|
|
976
|
+
const metadata = await lstat(path);
|
|
977
|
+
if (!metadata.isDirectory() || metadata.isSymbolicLink())
|
|
978
|
+
throw new Error('HOSTED_CONVERSATION_STORAGE_INVALID');
|
|
979
|
+
const actual = await realpath(path);
|
|
980
|
+
const actualRoot = await realpath(root);
|
|
981
|
+
if (actual !== actualRoot && !within(actualRoot, actual))
|
|
982
|
+
throw new Error('HOSTED_CONVERSATION_STORAGE_INVALID');
|
|
983
|
+
}
|
|
984
|
+
async withConversationMutation(conversationId, operation) {
|
|
985
|
+
const previous = this.conversationMutations.get(conversationId) ?? Promise.resolve();
|
|
986
|
+
const result = previous.then(operation);
|
|
987
|
+
const settled = result.then(() => undefined, () => undefined);
|
|
988
|
+
this.conversationMutations.set(conversationId, settled);
|
|
989
|
+
try {
|
|
990
|
+
return await result;
|
|
991
|
+
}
|
|
992
|
+
finally {
|
|
993
|
+
if (this.conversationMutations.get(conversationId) === settled)
|
|
994
|
+
this.conversationMutations.delete(conversationId);
|
|
995
|
+
}
|
|
996
|
+
}
|
|
997
|
+
async writeManifest(manifestPath, manifest) {
|
|
998
|
+
const parsed = hostedConversationManifestSchema.parse(manifest);
|
|
999
|
+
const temporaryPath = join(dirname(manifestPath), `.conversation-${randomUUID()}.tmp`);
|
|
1000
|
+
await writeFile(temporaryPath, `${JSON.stringify(parsed)}\n`, { mode: 0o600, flag: 'wx' });
|
|
1001
|
+
try {
|
|
1002
|
+
await rename(temporaryPath, manifestPath);
|
|
1003
|
+
}
|
|
1004
|
+
finally {
|
|
1005
|
+
await rm(temporaryPath, { force: true }).catch(() => undefined);
|
|
1006
|
+
}
|
|
1007
|
+
}
|
|
1008
|
+
insertConversation(manifest) {
|
|
1009
|
+
this.options.database.raw
|
|
1010
|
+
.prepare(`INSERT INTO hosted_conversations
|
|
1011
|
+
(id,user_storage_key,conversation_storage_key,client_request_id,node_id,session_id,
|
|
1012
|
+
template_id,template_name,active_version_id,title,title_source,pinned_at,status,model_id,
|
|
1013
|
+
template_deleted,used_bytes,max_bytes,created_at,updated_at,
|
|
1014
|
+
last_activity_at)
|
|
1015
|
+
VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)`)
|
|
1016
|
+
.run(manifest.id, manifest.userStorageKey, manifest.conversationStorageKey, manifest.clientRequestId ?? null, manifest.nodeId, manifest.sessionId, manifest.templateId, manifest.templateName, manifest.activeVersionId, manifest.title, manifest.titleSource, manifest.pinnedAt, manifest.status, manifest.modelId, manifest.templateDeleted ? 1 : 0, manifest.quota.usedBytes, manifest.quota.maxBytes, manifest.createdAt, manifest.updatedAt, manifest.lastActivityAt);
|
|
1017
|
+
}
|
|
1018
|
+
updateConversationRow(manifest) {
|
|
1019
|
+
const result = this.options.database.raw
|
|
1020
|
+
.prepare(`UPDATE hosted_conversations
|
|
1021
|
+
SET template_id=?,template_name=?,active_version_id=?,title=?,title_source=?,pinned_at=?,
|
|
1022
|
+
status=?,model_id=?,template_deleted=?,
|
|
1023
|
+
used_bytes=?,max_bytes=?,updated_at=?,last_activity_at=?
|
|
1024
|
+
WHERE id=? AND user_storage_key=? AND conversation_storage_key=? AND node_id=? AND session_id=?`)
|
|
1025
|
+
.run(manifest.templateId, manifest.templateName, manifest.activeVersionId, manifest.title, manifest.titleSource, manifest.pinnedAt, manifest.status, manifest.modelId, manifest.templateDeleted ? 1 : 0, manifest.quota.usedBytes, manifest.quota.maxBytes, manifest.updatedAt, manifest.lastActivityAt, manifest.id, manifest.userStorageKey, manifest.conversationStorageKey, manifest.nodeId, manifest.sessionId);
|
|
1026
|
+
if (Number(result.changes) !== 1)
|
|
1027
|
+
throw new Error('HOSTED_CONVERSATION_STORAGE_INVALID');
|
|
1028
|
+
}
|
|
1029
|
+
adjustVersionReferences(previous, next) {
|
|
1030
|
+
const counts = new Map();
|
|
1031
|
+
for (const id of previous)
|
|
1032
|
+
counts.set(id, (counts.get(id) ?? 0) - 1);
|
|
1033
|
+
for (const id of next)
|
|
1034
|
+
counts.set(id, (counts.get(id) ?? 0) + 1);
|
|
1035
|
+
for (const [id, delta] of counts) {
|
|
1036
|
+
if (delta === 0)
|
|
1037
|
+
continue;
|
|
1038
|
+
const result = delta > 0
|
|
1039
|
+
? this.options.database.raw
|
|
1040
|
+
.prepare('UPDATE conversation_template_versions SET reference_count=reference_count+? WHERE id=?')
|
|
1041
|
+
.run(delta, id)
|
|
1042
|
+
: this.options.database.raw
|
|
1043
|
+
.prepare(`UPDATE conversation_template_versions
|
|
1044
|
+
SET reference_count=reference_count+?
|
|
1045
|
+
WHERE id=? AND reference_count>=?`)
|
|
1046
|
+
.run(delta, id, -delta);
|
|
1047
|
+
if (Number(result.changes) !== 1)
|
|
1048
|
+
throw new Error('CONVERSATION_TEMPLATE_VERSION_CORRUPTED');
|
|
1049
|
+
}
|
|
1050
|
+
}
|
|
1051
|
+
replaceConversationIndex(rebuilt) {
|
|
1052
|
+
const database = this.options.database.raw;
|
|
1053
|
+
database.exec('BEGIN IMMEDIATE');
|
|
1054
|
+
try {
|
|
1055
|
+
database.prepare('DELETE FROM conversation_files').run();
|
|
1056
|
+
if (rebuilt.length === 0) {
|
|
1057
|
+
database.prepare('DELETE FROM hosted_conversation_messages').run();
|
|
1058
|
+
database.prepare('DELETE FROM hosted_conversations').run();
|
|
1059
|
+
}
|
|
1060
|
+
else {
|
|
1061
|
+
const placeholders = rebuilt.map(() => '?').join(',');
|
|
1062
|
+
const ids = rebuilt.map((item) => item.manifest.id);
|
|
1063
|
+
database
|
|
1064
|
+
.prepare(`DELETE FROM hosted_conversation_messages
|
|
1065
|
+
WHERE conversation_id NOT IN (${placeholders})`)
|
|
1066
|
+
.run(...ids);
|
|
1067
|
+
database
|
|
1068
|
+
.prepare(`DELETE FROM hosted_conversations WHERE id NOT IN (${placeholders})`)
|
|
1069
|
+
.run(...ids);
|
|
1070
|
+
}
|
|
1071
|
+
database.prepare('UPDATE conversation_template_versions SET reference_count=0').run();
|
|
1072
|
+
const upsert = database.prepare(`INSERT INTO hosted_conversations
|
|
1073
|
+
(id,user_storage_key,conversation_storage_key,client_request_id,node_id,session_id,template_id,template_name,
|
|
1074
|
+
active_version_id,title,title_source,pinned_at,status,model_id,template_deleted,
|
|
1075
|
+
used_bytes,max_bytes,created_at,updated_at,last_activity_at)
|
|
1076
|
+
VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)
|
|
1077
|
+
ON CONFLICT(id) DO UPDATE SET
|
|
1078
|
+
user_storage_key=excluded.user_storage_key,
|
|
1079
|
+
conversation_storage_key=excluded.conversation_storage_key,
|
|
1080
|
+
client_request_id=excluded.client_request_id,
|
|
1081
|
+
node_id=excluded.node_id,
|
|
1082
|
+
session_id=excluded.session_id,
|
|
1083
|
+
template_id=excluded.template_id,
|
|
1084
|
+
template_name=excluded.template_name,
|
|
1085
|
+
active_version_id=excluded.active_version_id,
|
|
1086
|
+
title=excluded.title,
|
|
1087
|
+
title_source=excluded.title_source,
|
|
1088
|
+
pinned_at=excluded.pinned_at,
|
|
1089
|
+
status=excluded.status,
|
|
1090
|
+
model_id=excluded.model_id,
|
|
1091
|
+
template_deleted=excluded.template_deleted,
|
|
1092
|
+
used_bytes=excluded.used_bytes,
|
|
1093
|
+
max_bytes=excluded.max_bytes,
|
|
1094
|
+
created_at=excluded.created_at,
|
|
1095
|
+
updated_at=excluded.updated_at,
|
|
1096
|
+
last_activity_at=excluded.last_activity_at`);
|
|
1097
|
+
const insertFile = conversationFileInsert(database);
|
|
1098
|
+
const addReference = database.prepare('UPDATE conversation_template_versions SET reference_count=reference_count+1 WHERE id=?');
|
|
1099
|
+
for (const item of rebuilt) {
|
|
1100
|
+
const manifest = item.manifest;
|
|
1101
|
+
upsert.run(manifest.id, manifest.userStorageKey, manifest.conversationStorageKey, manifest.clientRequestId ?? null, manifest.nodeId, manifest.sessionId, manifest.templateId, manifest.templateName, manifest.activeVersionId, manifest.title, manifest.titleSource, manifest.pinnedAt, manifest.status, manifest.modelId, manifest.templateDeleted ? 1 : 0, manifest.quota.usedBytes, manifest.quota.maxBytes, manifest.createdAt, manifest.updatedAt, manifest.lastActivityAt);
|
|
1102
|
+
for (const file of item.files)
|
|
1103
|
+
insertConversationFile(insertFile, file);
|
|
1104
|
+
if (Number(addReference.run(manifest.activeVersionId).changes) !== 1)
|
|
1105
|
+
throw new Error('CONVERSATION_TEMPLATE_VERSION_CORRUPTED');
|
|
1106
|
+
}
|
|
1107
|
+
database
|
|
1108
|
+
.prepare(`UPDATE hosted_conversation_messages
|
|
1109
|
+
SET status='INTERRUPTED',updated_at=? WHERE status='RUNNING'`)
|
|
1110
|
+
.run(Date.now());
|
|
1111
|
+
for (const table of [
|
|
1112
|
+
'hosted_conversations',
|
|
1113
|
+
'conversation_files',
|
|
1114
|
+
'hosted_conversation_messages'
|
|
1115
|
+
])
|
|
1116
|
+
if (database.prepare(`PRAGMA foreign_key_check(${table})`).get() !== undefined)
|
|
1117
|
+
throw new Error('HOSTED_CONVERSATION_STORAGE_INVALID');
|
|
1118
|
+
database.exec('COMMIT');
|
|
1119
|
+
}
|
|
1120
|
+
catch (error) {
|
|
1121
|
+
database.exec('ROLLBACK');
|
|
1122
|
+
throw error;
|
|
1123
|
+
}
|
|
1124
|
+
}
|
|
1125
|
+
}
|
|
1126
|
+
async function directorySize(path) {
|
|
1127
|
+
const metadata = await lstat(path);
|
|
1128
|
+
if (metadata.isFile() || metadata.isSymbolicLink()) {
|
|
1129
|
+
if (!Number.isSafeInteger(metadata.size) || metadata.size < 0)
|
|
1130
|
+
throw new Error('HOSTED_CONVERSATION_STORAGE_INVALID');
|
|
1131
|
+
return metadata.size;
|
|
1132
|
+
}
|
|
1133
|
+
if (!metadata.isDirectory())
|
|
1134
|
+
throw new Error('HOSTED_CONVERSATION_STORAGE_INVALID');
|
|
1135
|
+
let total = 0;
|
|
1136
|
+
for (const entry of await sortedEntries(path)) {
|
|
1137
|
+
total += await directorySize(join(path, entry.name));
|
|
1138
|
+
if (!Number.isSafeInteger(total))
|
|
1139
|
+
throw new Error('HOSTED_CONVERSATION_STORAGE_INVALID');
|
|
1140
|
+
}
|
|
1141
|
+
return total;
|
|
1142
|
+
}
|
|
1143
|
+
function fileProjectionKey(category, relativePath) {
|
|
1144
|
+
return `${category}:${relativePath}`;
|
|
1145
|
+
}
|
|
1146
|
+
function safeFileTimestamp(value) {
|
|
1147
|
+
if (!Number.isFinite(value) || value < 0)
|
|
1148
|
+
return 0;
|
|
1149
|
+
return Math.min(Number.MAX_SAFE_INTEGER, Math.trunc(value));
|
|
1150
|
+
}
|
|
1151
|
+
function inferMimeType(relativePath) {
|
|
1152
|
+
const extension = relativePath.split('.').at(-1)?.toLocaleLowerCase('en-US');
|
|
1153
|
+
if (extension === 'txt' || extension === 'log')
|
|
1154
|
+
return 'text/plain';
|
|
1155
|
+
if (extension === 'md')
|
|
1156
|
+
return 'text/markdown';
|
|
1157
|
+
if (extension === 'json')
|
|
1158
|
+
return 'application/json';
|
|
1159
|
+
if (extension === 'csv')
|
|
1160
|
+
return 'text/csv';
|
|
1161
|
+
if (extension === 'html' || extension === 'htm')
|
|
1162
|
+
return 'text/html';
|
|
1163
|
+
if (extension === 'png')
|
|
1164
|
+
return 'image/png';
|
|
1165
|
+
if (extension === 'jpg' || extension === 'jpeg')
|
|
1166
|
+
return 'image/jpeg';
|
|
1167
|
+
if (extension === 'webp')
|
|
1168
|
+
return 'image/webp';
|
|
1169
|
+
if (extension === 'pdf')
|
|
1170
|
+
return 'application/pdf';
|
|
1171
|
+
return 'application/octet-stream';
|
|
1172
|
+
}
|
|
1173
|
+
function conversationFileInsert(database) {
|
|
1174
|
+
return database.prepare(`INSERT INTO conversation_files
|
|
1175
|
+
(id,conversation_id,category,relative_path,display_name,mime_type,size,source,
|
|
1176
|
+
turn_id,item_id,created_at,updated_at)
|
|
1177
|
+
VALUES (?,?,?,?,?,?,?,?,?,?,?,?)`);
|
|
1178
|
+
}
|
|
1179
|
+
function insertConversationFile(insert, file) {
|
|
1180
|
+
insert.run(file.id, file.conversationId, file.category, file.relativePath, file.displayName, file.mimeType, file.size, file.source, file.turnId ?? null, file.itemId ?? null, file.createdAt, file.updatedAt);
|
|
1181
|
+
}
|
|
1182
|
+
async function sortedEntries(directory) {
|
|
1183
|
+
return (await readdir(directory, { withFileTypes: true })).sort((left, right) => left.name.localeCompare(right.name, 'en-US'));
|
|
1184
|
+
}
|
|
1185
|
+
function conversationPaths(conversationDirectory) {
|
|
1186
|
+
const manifestDirectory = join(conversationDirectory, 'manifest');
|
|
1187
|
+
const dataDirectory = join(conversationDirectory, 'data');
|
|
1188
|
+
const runtimeDirectory = join(conversationDirectory, 'runtime');
|
|
1189
|
+
return {
|
|
1190
|
+
conversationDirectory,
|
|
1191
|
+
manifestDirectory,
|
|
1192
|
+
manifestPath: join(manifestDirectory, 'conversation.json'),
|
|
1193
|
+
homeDirectory: join(conversationDirectory, 'home'),
|
|
1194
|
+
dataDirectory,
|
|
1195
|
+
uploadsDirectory: join(dataDirectory, 'inbox'),
|
|
1196
|
+
outputDirectory: join(dataDirectory, 'output'),
|
|
1197
|
+
temporaryRootDirectory: join(dataDirectory, 'tmp'),
|
|
1198
|
+
runtimeDirectory,
|
|
1199
|
+
templateBindingDirectory: join(runtimeDirectory, 'template-binding'),
|
|
1200
|
+
fileIndexDirectory: join(runtimeDirectory, 'file-index'),
|
|
1201
|
+
quotaDirectory: join(runtimeDirectory, 'quota')
|
|
1202
|
+
};
|
|
1203
|
+
}
|
|
1204
|
+
function storedHostedConversationManifest(input) {
|
|
1205
|
+
const stored = typeof input === 'object' && input !== null && !Array.isArray(input)
|
|
1206
|
+
? input
|
|
1207
|
+
: {};
|
|
1208
|
+
const withoutLegacyMetadata = { ...stored };
|
|
1209
|
+
delete withoutLegacyMetadata['recoverableUntil'];
|
|
1210
|
+
delete withoutLegacyMetadata['pendingVersionId'];
|
|
1211
|
+
const missingPinnedAt = !('pinnedAt' in stored);
|
|
1212
|
+
const missingTitleSource = !('titleSource' in stored);
|
|
1213
|
+
const legacyUpgradeStatus = stored.status === 'UPGRADE_PENDING' || stored.status === 'UPGRADE_FAILED';
|
|
1214
|
+
const hasPendingVersion = 'pendingVersionId' in stored;
|
|
1215
|
+
const upgraded = missingPinnedAt ||
|
|
1216
|
+
missingTitleSource ||
|
|
1217
|
+
'recoverableUntil' in stored ||
|
|
1218
|
+
hasPendingVersion ||
|
|
1219
|
+
legacyUpgradeStatus;
|
|
1220
|
+
return {
|
|
1221
|
+
manifest: hostedConversationManifestSchema.parse(upgraded
|
|
1222
|
+
? {
|
|
1223
|
+
...withoutLegacyMetadata,
|
|
1224
|
+
...(missingPinnedAt ? { pinnedAt: null } : {}),
|
|
1225
|
+
...(missingTitleSource ? { titleSource: 'CUSTOM' } : {}),
|
|
1226
|
+
...(legacyUpgradeStatus ? { status: 'ACTIVE' } : {})
|
|
1227
|
+
}
|
|
1228
|
+
: input),
|
|
1229
|
+
upgraded
|
|
1230
|
+
};
|
|
1231
|
+
}
|
|
1232
|
+
function childPath(parent, key) {
|
|
1233
|
+
if (!STORAGE_KEY.test(key))
|
|
1234
|
+
throw new Error('HOSTED_CONVERSATION_STORAGE_INVALID');
|
|
1235
|
+
const candidate = resolve(parent, key);
|
|
1236
|
+
if (!within(parent, candidate))
|
|
1237
|
+
throw new Error('HOSTED_CONVERSATION_STORAGE_INVALID');
|
|
1238
|
+
return candidate;
|
|
1239
|
+
}
|
|
1240
|
+
function opaqueStorageKey(prefix, domain, value) {
|
|
1241
|
+
return `${prefix}_${createHash('sha256').update(`${domain}\0${value}`).digest('base64url')}`;
|
|
1242
|
+
}
|
|
1243
|
+
function safeRelativePath(root, relativePath) {
|
|
1244
|
+
if (relativePath.length === 0 ||
|
|
1245
|
+
relativePath.startsWith('/') ||
|
|
1246
|
+
relativePath.includes('\\') ||
|
|
1247
|
+
relativePath
|
|
1248
|
+
.split('/')
|
|
1249
|
+
.some((segment) => segment.length === 0 || segment === '.' || segment === '..'))
|
|
1250
|
+
throw new Error('HOSTED_CONVERSATION_FILE_INVALID');
|
|
1251
|
+
const candidate = resolve(root, ...relativePath.split('/'));
|
|
1252
|
+
if (!within(root, candidate))
|
|
1253
|
+
throw new Error('HOSTED_CONVERSATION_FILE_INVALID');
|
|
1254
|
+
return candidate;
|
|
1255
|
+
}
|
|
1256
|
+
function within(parent, candidate) {
|
|
1257
|
+
const relation = relative(parent, candidate);
|
|
1258
|
+
return relation.length > 0 && relation !== '..' && !relation.startsWith(`..${sep}`);
|
|
1259
|
+
}
|
|
1260
|
+
function hostedConversationManifest(row) {
|
|
1261
|
+
const clientRequestId = nullableStringColumn(row.client_request_id);
|
|
1262
|
+
const parsed = hostedConversationManifestSchema.safeParse({
|
|
1263
|
+
id: row.id,
|
|
1264
|
+
nodeId: row.node_id,
|
|
1265
|
+
sessionId: row.session_id,
|
|
1266
|
+
templateId: row.template_id,
|
|
1267
|
+
templateName: row.template_name,
|
|
1268
|
+
activeVersionId: row.active_version_id,
|
|
1269
|
+
title: row.title,
|
|
1270
|
+
titleSource: row.title_source,
|
|
1271
|
+
pinnedAt: nullableNumberColumn(row.pinned_at),
|
|
1272
|
+
status: row.status,
|
|
1273
|
+
modelId: row.model_id,
|
|
1274
|
+
createdAt: row.created_at,
|
|
1275
|
+
updatedAt: row.updated_at,
|
|
1276
|
+
lastActivityAt: row.last_activity_at,
|
|
1277
|
+
userStorageKey: row.user_storage_key,
|
|
1278
|
+
conversationStorageKey: row.conversation_storage_key,
|
|
1279
|
+
...(clientRequestId === null ? {} : { clientRequestId }),
|
|
1280
|
+
templateDeleted: booleanColumn(row.template_deleted),
|
|
1281
|
+
quota: {
|
|
1282
|
+
usedBytes: row.used_bytes,
|
|
1283
|
+
maxBytes: row.max_bytes
|
|
1284
|
+
}
|
|
1285
|
+
});
|
|
1286
|
+
if (!parsed.success)
|
|
1287
|
+
throw new Error('HOSTED_CONVERSATION_STORAGE_INVALID');
|
|
1288
|
+
return parsed.data;
|
|
1289
|
+
}
|
|
1290
|
+
function isHostedConversationCursor(value) {
|
|
1291
|
+
if (typeof value !== 'object' || value === null || Array.isArray(value))
|
|
1292
|
+
return false;
|
|
1293
|
+
const cursor = value;
|
|
1294
|
+
const keys = Object.keys(cursor).sort();
|
|
1295
|
+
if (keys.length !== 7 ||
|
|
1296
|
+
keys.join(',') !== 'binding,cursorVersion,id,lastActivityAt,limit,pinned,sortVersion')
|
|
1297
|
+
return false;
|
|
1298
|
+
return (cursor.cursorVersion === HOSTED_CONVERSATION_CURSOR_VERSION &&
|
|
1299
|
+
cursor.sortVersion === HOSTED_CONVERSATION_SORT_VERSION &&
|
|
1300
|
+
Number.isSafeInteger(cursor.limit) &&
|
|
1301
|
+
cursor.limit >= 1 &&
|
|
1302
|
+
cursor.limit <= MAX_HOSTED_CONVERSATION_PAGE_SIZE &&
|
|
1303
|
+
typeof cursor.pinned === 'boolean' &&
|
|
1304
|
+
Number.isSafeInteger(cursor.lastActivityAt) &&
|
|
1305
|
+
cursor.lastActivityAt >= 0 &&
|
|
1306
|
+
typeof cursor.id === 'string' &&
|
|
1307
|
+
PROTOCOL_ID.test(cursor.id) &&
|
|
1308
|
+
typeof cursor.binding === 'string' &&
|
|
1309
|
+
CURSOR_BINDING.test(cursor.binding));
|
|
1310
|
+
}
|
|
1311
|
+
function conversationFileProjection(row) {
|
|
1312
|
+
const turnId = nullableStringColumn(row.turn_id);
|
|
1313
|
+
const itemId = nullableStringColumn(row.item_id);
|
|
1314
|
+
const parsed = conversationFileProjectionSchema.safeParse({
|
|
1315
|
+
id: row.id,
|
|
1316
|
+
conversationId: row.conversation_id,
|
|
1317
|
+
category: row.category,
|
|
1318
|
+
relativePath: row.relative_path,
|
|
1319
|
+
displayName: row.display_name,
|
|
1320
|
+
mimeType: row.mime_type,
|
|
1321
|
+
size: row.size,
|
|
1322
|
+
source: row.source,
|
|
1323
|
+
...(turnId === null ? {} : { turnId }),
|
|
1324
|
+
...(itemId === null ? {} : { itemId }),
|
|
1325
|
+
createdAt: row.created_at,
|
|
1326
|
+
updatedAt: row.updated_at
|
|
1327
|
+
});
|
|
1328
|
+
if (!parsed.success)
|
|
1329
|
+
throw new Error('HOSTED_CONVERSATION_STORAGE_INVALID');
|
|
1330
|
+
return parsed.data;
|
|
1331
|
+
}
|
|
1332
|
+
function hostedConversationMessage(row) {
|
|
1333
|
+
const status = stringColumn(row.status);
|
|
1334
|
+
if (status !== 'RUNNING' &&
|
|
1335
|
+
status !== 'SUCCEEDED' &&
|
|
1336
|
+
status !== 'FAILED' &&
|
|
1337
|
+
status !== 'INTERRUPTED')
|
|
1338
|
+
throw new Error('HOSTED_CONVERSATION_STORAGE_INVALID');
|
|
1339
|
+
return {
|
|
1340
|
+
conversationId: stringColumn(row.conversation_id),
|
|
1341
|
+
clientMessageId: stringColumn(row.client_message_id),
|
|
1342
|
+
runId: stringColumn(row.run_id),
|
|
1343
|
+
userTextPresent: booleanColumn(row.user_text_present),
|
|
1344
|
+
status,
|
|
1345
|
+
createdAt: numberColumn(row.created_at),
|
|
1346
|
+
updatedAt: numberColumn(row.updated_at)
|
|
1347
|
+
};
|
|
1348
|
+
}
|
|
1349
|
+
function hostedConversationSummary(row) {
|
|
1350
|
+
const parsed = hostedConversationSummarySchema.safeParse({
|
|
1351
|
+
id: row.id,
|
|
1352
|
+
nodeId: row.node_id,
|
|
1353
|
+
sessionId: row.session_id,
|
|
1354
|
+
templateId: row.template_id,
|
|
1355
|
+
templateName: row.template_name,
|
|
1356
|
+
activeVersionId: row.active_version_id,
|
|
1357
|
+
title: row.title,
|
|
1358
|
+
titleSource: row.title_source,
|
|
1359
|
+
pinnedAt: nullableNumberColumn(row.pinned_at),
|
|
1360
|
+
status: row.status,
|
|
1361
|
+
modelId: row.model_id,
|
|
1362
|
+
createdAt: row.created_at,
|
|
1363
|
+
updatedAt: row.updated_at,
|
|
1364
|
+
lastActivityAt: row.last_activity_at
|
|
1365
|
+
});
|
|
1366
|
+
if (!parsed.success)
|
|
1367
|
+
throw new Error('HOSTED_CONVERSATION_STORAGE_INVALID');
|
|
1368
|
+
return parsed.data;
|
|
1369
|
+
}
|
|
1370
|
+
function versionReferences(manifest) {
|
|
1371
|
+
return [manifest.activeVersionId];
|
|
1372
|
+
}
|
|
1373
|
+
function nullableStringColumn(value) {
|
|
1374
|
+
if (value === null || value === undefined)
|
|
1375
|
+
return null;
|
|
1376
|
+
return stringColumn(value);
|
|
1377
|
+
}
|
|
1378
|
+
function nullableNumberColumn(value) {
|
|
1379
|
+
if (value === null || value === undefined)
|
|
1380
|
+
return null;
|
|
1381
|
+
return numberColumn(value);
|
|
1382
|
+
}
|
|
1383
|
+
function booleanColumn(value) {
|
|
1384
|
+
if (value === 0)
|
|
1385
|
+
return false;
|
|
1386
|
+
if (value === 1)
|
|
1387
|
+
return true;
|
|
1388
|
+
throw new Error('HOSTED_CONVERSATION_STORAGE_INVALID');
|
|
1389
|
+
}
|
|
1390
|
+
function isUniqueConstraint(error) {
|
|
1391
|
+
return (error instanceof Error &&
|
|
1392
|
+
'code' in error &&
|
|
1393
|
+
typeof error.code === 'string' &&
|
|
1394
|
+
error.code.startsWith('SQLITE_CONSTRAINT_UNIQUE'));
|
|
1395
|
+
}
|
|
1396
|
+
function stringColumn(value) {
|
|
1397
|
+
if (typeof value !== 'string')
|
|
1398
|
+
throw new Error('HOSTED_CONVERSATION_STORAGE_INVALID');
|
|
1399
|
+
return value;
|
|
1400
|
+
}
|
|
1401
|
+
function numberColumn(value) {
|
|
1402
|
+
if (typeof value !== 'number' || !Number.isSafeInteger(value) || value < 0)
|
|
1403
|
+
throw new Error('HOSTED_CONVERSATION_STORAGE_INVALID');
|
|
1404
|
+
return value;
|
|
1405
|
+
}
|