- होम
- Documentation
- सत्र
- सत्र संग्रहण और प्रविष्टि मॉडल
सत्र संग्रहण और प्रविष्टि मॉडल
यह दस्तावेज़ इस बात का प्रामाणिक स्रोत है कि coding-agent सत्रों को रनटाइम पर कैसे प्रस्तुत, स्थायी, माइग्रेट और पुनर्निर्मित किया जाता है।
इसमें शामिल है:
- सत्र JSONL प्रारूप और संस्करण
- प्रविष्टि वर्गीकरण और ट्री सिमैंटिक्स (
id/parentId+ लीफ पॉइंटर) - पुरानी या विकृत फ़ाइलें लोड करते समय माइग्रेशन/संगतता व्यवहार
- संदर्भ पुनर्निर्माण (
buildSessionContext) - स्थायित्व गारंटी, विफलता व्यवहार, ट्रंकेशन/ब्लॉब बाह्यकरण
- संग्रहण अमूर्तन (
FileSessionStorage,MemorySessionStorage) और संबंधित उपयोगिताएँ
इसमें शामिल नहीं है: /tree UI रेंडरिंग व्यवहार, सत्र डेटा को प्रभावित करने वाले सिमैंटिक्स से परे।
कार्यान्वयन फ़ाइलें
Section titled “कार्यान्वयन फ़ाइलें”src/session/session-manager.tssrc/session/messages.tssrc/session/session-storage.tssrc/session/history-storage.tssrc/session/blob-store.ts
डिस्क पर लेआउट
Section titled “डिस्क पर लेआउट”डिफ़ॉल्ट सत्र फ़ाइल स्थान:
~/.xcsh/agent/sessions/--<cwd-encoded>--/<timestamp>_<sessionId>.jsonl<cwd-encoded> कार्यशील निर्देशिका से अग्रणी स्लैश हटाकर और /, \\, तथा : को - से बदलकर प्राप्त किया जाता है।
ब्लॉब स्टोर स्थान:
~/.xcsh/agent/blobs/<sha256>टर्मिनल ब्रेडक्रम्ब फ़ाइलें यहाँ लिखी जाती हैं:
~/.xcsh/agent/terminal-sessions/<terminal-id>ब्रेडक्रम्ब सामग्री दो पंक्तियाँ हैं: मूल cwd, फिर सत्र फ़ाइल पथ। continueRecent() सबसे हाल के mtime को स्कैन करने से पहले इस टर्मिनल-स्कोप्ड पॉइंटर को प्राथमिकता देता है।
फ़ाइल प्रारूप
Section titled “फ़ाइल प्रारूप”सत्र फ़ाइलें JSONL हैं: प्रति पंक्ति एक JSON ऑब्जेक्ट।
- पंक्ति 1 हमेशा सत्र हेडर (
type: "session") होती है। - शेष पंक्तियाँ
SessionEntryमान हैं। - रनटाइम पर प्रविष्टियाँ केवल-जोड़ने योग्य हैं; शाखा नेविगेशन मौजूदा प्रविष्टियों को बदलने के बजाय एक पॉइंटर (
leafId) को स्थानांतरित करता है।
हेडर (SessionHeader)
Section titled “हेडर (SessionHeader)”{ "type": "session", "version": 3, "id": "1f9d2a6b9c0d1234", "timestamp": "2026-02-16T10:20:30.000Z", "cwd": "/work/pi", "title": "optional session title", "parentSession": "optional lineage marker"}नोट:
- v1 फ़ाइलों में
versionवैकल्पिक है; अनुपस्थिति का अर्थ v1 है। parentSessionएक अपारदर्शी वंशावली स्ट्रिंग है। वर्तमान कोड प्रवाह (fork,forkFrom,createBranchedSession, या स्पष्टnewSession({ parentSession })) के आधार पर या तो सत्र id या सत्र पथ लिखता है। इसे मेटाडेटा मानें, टाइप्ड विदेशी कुंजी नहीं।
प्रविष्टि आधार (SessionEntryBase)
Section titled “प्रविष्टि आधार (SessionEntryBase)”सभी गैर-हेडर प्रविष्टियों में शामिल है:
{ "type": "...", "id": "8-char-id", "parentId": "previous-or-branch-parent", "timestamp": "2026-02-16T10:20:30.000Z"}parentId मूल प्रविष्टि (पहला जोड़, या resetLeaf() के बाद) के लिए null हो सकता है।
प्रविष्टि वर्गीकरण
Section titled “प्रविष्टि वर्गीकरण”SessionEntry इनका संघ है:
messagethinking_level_changemodel_changecompactionbranch_summarycustomcustom_messagelabelttsr_injectionsession_initmode_change
message
Section titled “message”सीधे एक AgentMessage संग्रहीत करता है।
{ "type": "message", "id": "a1b2c3d4", "parentId": null, "timestamp": "2026-02-16T10:21:00.000Z", "message": { "role": "assistant", "provider": "anthropic", "model": "claude-sonnet-4-5", "content": [{ "type": "text", "text": "Done." }], "usage": { "input": 100, "output": 20, "cacheRead": 0, "cacheWrite": 0, "cost": { "input": 0, "output": 0, "cacheRead": 0, "cacheWrite": 0, "total": 0 } }, "timestamp": 1760000000000 }}model_change
Section titled “model_change”{ "type": "model_change", "id": "b1c2d3e4", "parentId": "a1b2c3d4", "timestamp": "2026-02-16T10:21:30.000Z", "model": "openai/gpt-4o", "role": "default"}role वैकल्पिक है; संदर्भ पुनर्निर्माण में अनुपस्थित को default माना जाता है।
thinking_level_change
Section titled “thinking_level_change”{ "type": "thinking_level_change", "id": "c1d2e3f4", "parentId": "b1c2d3e4", "timestamp": "2026-02-16T10:22:00.000Z", "thinkingLevel": "high"}compaction
Section titled “compaction”{ "type": "compaction", "id": "d1e2f3a4", "parentId": "c1d2e3f4", "timestamp": "2026-02-16T10:23:00.000Z", "summary": "Conversation summary", "shortSummary": "Short recap", "firstKeptEntryId": "a1b2c3d4", "tokensBefore": 42000, "details": { "readFiles": ["src/a.ts"] }, "preserveData": { "hookState": true }, "fromExtension": false}branch_summary
Section titled “branch_summary”{ "type": "branch_summary", "id": "e1f2a3b4", "parentId": "a1b2c3d4", "timestamp": "2026-02-16T10:24:00.000Z", "fromId": "a1b2c3d4", "summary": "Summary of abandoned path", "details": { "note": "optional" }, "fromExtension": true}यदि मूल से शाखा बना रहे हैं (branchFromId === null), तो fromId शाब्दिक स्ट्रिंग "root" होता है।
custom
Section titled “custom”एक्सटेंशन स्थिति स्थायित्व; buildSessionContext द्वारा अनदेखा किया जाता है।
{ "type": "custom", "id": "f1a2b3c4", "parentId": "e1f2a3b4", "timestamp": "2026-02-16T10:25:00.000Z", "customType": "my-extension", "data": { "state": 1 }}custom_message
Section titled “custom_message”एक्सटेंशन-प्रदत्त संदेश जो LLM संदर्भ में भाग लेता है।
{ "type": "custom_message", "id": "a2b3c4d5", "parentId": "f1a2b3c4", "timestamp": "2026-02-16T10:26:00.000Z", "customType": "my-extension", "content": "Injected context", "display": true, "details": { "debug": false }}{ "type": "label", "id": "b2c3d4e5", "parentId": "a2b3c4d5", "timestamp": "2026-02-16T10:27:00.000Z", "targetId": "a1b2c3d4", "label": "checkpoint"}label: undefined targetId के लिए एक लेबल साफ़ करता है।
ttsr_injection
Section titled “ttsr_injection”{ "type": "ttsr_injection", "id": "c2d3e4f5", "parentId": "b2c3d4e5", "timestamp": "2026-02-16T10:28:00.000Z", "injectedRules": ["ruleA", "ruleB"]}session_init
Section titled “session_init”{ "type": "session_init", "id": "d2e3f4a5", "parentId": "c2d3e4f5", "timestamp": "2026-02-16T10:29:00.000Z", "systemPrompt": "...", "task": "...", "tools": ["read", "edit"], "outputSchema": { "type": "object" }}mode_change
Section titled “mode_change”{ "type": "mode_change", "id": "e2f3a4b5", "parentId": "d2e3f4a5", "timestamp": "2026-02-16T10:30:00.000Z", "mode": "plan", "data": { "planFile": "/tmp/plan.md" }}संस्करण और माइग्रेशन
Section titled “संस्करण और माइग्रेशन”वर्तमान सत्र संस्करण: 3।
v1 -> v2
Section titled “v1 -> v2”तब लागू होता है जब हेडर version अनुपस्थित हो या < 2:
- प्रत्येक गैर-हेडर प्रविष्टि में
idऔरparentIdजोड़ता है। - फ़ाइल क्रम का उपयोग करके एक रैखिक पैरेंट श्रृंखला पुनर्निर्मित करता है।
- जब मौजूद हो तो संघनन फ़ील्ड
firstKeptEntryIndex->firstKeptEntryIdमाइग्रेट करता है। - हेडर
version = 2सेट करता है।
v2 -> v3
Section titled “v2 -> v3”तब लागू होता है जब हेडर version < 3:
messageप्रविष्टियों के लिए: विरासतmessage.role === "hookMessage"को"custom"में पुनर्लिखित करता है।- हेडर
version = 3सेट करता है।
माइग्रेशन ट्रिगर और स्थायित्व
Section titled “माइग्रेशन ट्रिगर और स्थायित्व”- माइग्रेशन सत्र लोड (
setSessionFile) के दौरान चलते हैं। - यदि कोई माइग्रेशन चला, तो पूरी फ़ाइल तुरंत डिस्क पर पुनर्लिखित की जाती है।
- माइग्रेशन पहले इन-मेमोरी प्रविष्टियों को बदलता है, फिर पुनर्लिखित JSONL को स्थायी करता है।
लोड और संगतता व्यवहार
Section titled “लोड और संगतता व्यवहार”loadEntriesFromFile(path) व्यवहार:
- अनुपस्थित फ़ाइल (
ENOENT) ->[]लौटाता है। - गैर-पार्स करने योग्य पंक्तियों को उदार JSONL पार्सर (
parseJsonlLenient) द्वारा संभाला जाता है। - यदि पहली पार्स की गई प्रविष्टि एक मान्य सत्र हेडर नहीं है (
type !== "session"या स्ट्रिंगidअनुपस्थित) ->[]लौटाता है।
SessionManager.setSessionFile() व्यवहार:
- लोडर से
[]को खाली/अस्तित्वहीन सत्र माना जाता है और उस पथ पर एक नई आरंभीकृत सत्र फ़ाइल से बदल दिया जाता है। - मान्य फ़ाइलें लोड की जाती हैं, आवश्यकता होने पर माइग्रेट की जाती हैं, ब्लॉब रेफ़ हल किए जाते हैं, फिर अनुक्रमित किए जाते हैं।
ट्री और लीफ सिमैंटिक्स
Section titled “ट्री और लीफ सिमैंटिक्स”अंतर्निहित मॉडल केवल-जोड़ने योग्य ट्री + परिवर्तनशील लीफ पॉइंटर है:
- प्रत्येक जोड़ने की विधि ठीक एक नई प्रविष्टि बनाती है जिसका
parentIdवर्तमानleafIdहोता है। - नई प्रविष्टि नया
leafIdबन जाती है। branch(entryId)केवलleafIdको स्थानांतरित करता है; मौजूदा प्रविष्टियाँ अपरिवर्तित रहती हैं।resetLeaf()leafId = nullसेट करता है; अगला जोड़ एक नई मूल प्रविष्टि (parentId: null) बनाता है।branchWithSummary()लीफ को शाखा लक्ष्य पर सेट करता है और एकbranch_summaryप्रविष्टि जोड़ता है।
getEntries() सभी गैर-हेडर प्रविष्टियों को सम्मिलन क्रम में लौटाता है। सामान्य संचालन में मौजूदा प्रविष्टियाँ हटाई नहीं जातीं; पुनर्लेखन प्रतिनिधित्व को अपडेट करते हुए तार्किक इतिहास को संरक्षित करते हैं (माइग्रेशन, स्थानांतरण, लक्षित पुनर्लेखन सहायक)।
संदर्भ पुनर्निर्माण (buildSessionContext)
Section titled “संदर्भ पुनर्निर्माण (buildSessionContext)”buildSessionContext(entries, leafId, byId?) यह निर्धारित करता है कि मॉडल को क्या भेजा जाता है।
एल्गोरिदम:
- लीफ निर्धारित करें:
leafId === null-> खाली संदर्भ लौटाएँ।- स्पष्ट
leafId-> यदि मिले तो उस प्रविष्टि का उपयोग करें। - अन्यथा अंतिम प्रविष्टि पर फ़ॉलबैक।
- लीफ से मूल तक
parentIdश्रृंखला पर चलें और मूल->लीफ पथ के लिए उलटें। - पथ पर रनटाइम स्थिति प्राप्त करें:
- नवीनतम
thinking_level_changeसेthinkingLevel(डिफ़ॉल्ट"off") model_changeप्रविष्टियों से मॉडल मैप (role ?? "default")- यदि कोई स्पष्ट मॉडल परिवर्तन नहीं है तो सहायक संदेश provider/model से फ़ॉलबैक
models.default - सभी
ttsr_injectionप्रविष्टियों से डिडुप्लिकेटेडinjectedTtsrRules - नवीनतम
mode_changeसे mode/modeData (डिफ़ॉल्ट मोड"none")
- नवीनतम
- संदेश सूची बनाएँ:
messageप्रविष्टियाँ सीधे पास होती हैंcustom_messageप्रविष्टियाँcreateCustomMessageके माध्यम सेcustomAgentMessages बनती हैंbranch_summaryप्रविष्टियाँcreateBranchSummaryMessageके माध्यम सेbranchSummaryAgentMessages बनती हैं- यदि पथ पर
compactionमौजूद है:- पहले संघनन सारांश प्रकाशित करें (
createCompactionSummaryMessage) - संघनन सीमा तक
firstKeptEntryIdसे शुरू होने वाली पथ प्रविष्टियाँ प्रकाशित करें - संघनन सीमा के बाद की प्रविष्टियाँ प्रकाशित करें
- पहले संघनन सारांश प्रकाशित करें (
custom और session_init प्रविष्टियाँ सीधे मॉडल संदर्भ में इंजेक्ट नहीं करतीं।
स्थायित्व गारंटी और विफलता मॉडल
Section titled “स्थायित्व गारंटी और विफलता मॉडल”स्थायी बनाम इन-मेमोरी
Section titled “स्थायी बनाम इन-मेमोरी”SessionManager.create/open/continueRecent/forkFrom-> स्थायी मोड (persist = true)।SessionManager.inMemory-> गैर-स्थायी मोड (persist = false)MemorySessionStorageके साथ।
लेखन पाइपलाइन
Section titled “लेखन पाइपलाइन”लेखन एक आंतरिक प्रॉमिस श्रृंखला (#persistChain) और NdjsonFileWriter के माध्यम से क्रमबद्ध होते हैं।
append*इन-मेमोरी स्थिति को तुरंत अपडेट करता है।- कम से कम एक सहायक संदेश मौजूद होने तक स्थायित्व स्थगित रहता है।
- पहले सहायक से पहले: प्रविष्टियाँ मेमोरी में रखी जाती हैं; कोई फ़ाइल जोड़ नहीं होता।
- जब पहला सहायक मौजूद हो: पूर्ण इन-मेमोरी सत्र फ़ाइल में फ़्लश किया जाता है।
- उसके बाद: नई प्रविष्टियाँ क्रमिक रूप से जोड़ी जाती हैं।
कोड में तर्काधार: ऐसे सत्रों को स्थायी करने से बचें जिन्होंने कभी सहायक प्रतिक्रिया उत्पन्न नहीं की।
स्थायित्व संचालन
Section titled “स्थायित्व संचालन”flush()राइटर को फ़्लश करता है औरfsync()कॉल करता है।- परमाणु पूर्ण पुनर्लेखन (
#rewriteFile) अस्थायी फ़ाइल में लिखते हैं, flush+fsync करते हैं, बंद करते हैं, फिर लक्ष्य पर नाम बदलते हैं। - माइग्रेशन,
setSessionName,rewriteEntries, स्थानांतरण संचालन, और टूल-कॉल आर्ग पुनर्लेखन के लिए उपयोग किया जाता है।
त्रुटि व्यवहार
Section titled “त्रुटि व्यवहार”- स्थायित्व त्रुटियाँ लैच की जाती हैं (
#persistError) और बाद के संचालनों पर पुनः फेंकी जाती हैं। - पहली त्रुटि सत्र फ़ाइल संदर्भ के साथ एक बार लॉग की जाती है।
- राइटर बंद करना सर्वोत्तम-प्रयास है लेकिन पहली सार्थक त्रुटि को प्रसारित करता है।
डेटा आकार नियंत्रण और ब्लॉब बाह्यकरण
Section titled “डेटा आकार नियंत्रण और ब्लॉब बाह्यकरण”प्रविष्टियों को स्थायी करने से पहले:
- बड़ी स्ट्रिंग्स को
MAX_PERSIST_CHARS(500,000 वर्ण) तक सूचना के साथ ट्रंकेट किया जाता है:"[Session persistence truncated large content]"
- क्षणिक फ़ील्ड
partialJsonऔरjsonlEventsहटा दिए जाते हैं। - यदि ऑब्जेक्ट में
contentऔरlineCountदोनों हैं, तो ट्रंकेशन के बाद लाइन काउंट पुनर्गणना किया जाता है। contentसरणियों में base64 लंबाई >= 1024 वाले इमेज ब्लॉक ब्लॉब रेफ़ में बाह्यकृत किए जाते हैं:blob:sha256:<hash>के रूप में संग्रहीत- कच्चे बाइट ब्लॉब स्टोर (
BlobStore.put) में लिखे जाते हैं
लोड पर, message/custom_message इमेज ब्लॉक के लिए ब्लॉब रेफ़ वापस base64 में हल किए जाते हैं।
संग्रहण अमूर्तन
Section titled “संग्रहण अमूर्तन”SessionStorage इंटरफ़ेस SessionManager द्वारा उपयोग किए जाने वाले सभी फ़ाइलसिस्टम संचालन प्रदान करता है:
- तुल्यकालिक:
ensureDirSync,existsSync,writeTextSync,statSync,listFilesSync - अतुल्यकालिक:
exists,readText,readTextPrefix,writeText,rename,unlink,openWriter
कार्यान्वयन:
FileSessionStorage: वास्तविक फ़ाइलसिस्टम (Bun + node fs)MemorySessionStorage: परीक्षणों/गैर-स्थायी सत्रों के लिए मैप-समर्थित इन-मेमोरी कार्यान्वयन
SessionStorageWriter writeLine, flush, fsync, close, getError प्रकट करता है।
सत्र खोज उपयोगिताएँ
Section titled “सत्र खोज उपयोगिताएँ”session-manager.ts में परिभाषित:
getRecentSessions(sessionDir, limit)-> UI/सत्र चयनकर्ता के लिए हल्का मेटाडेटाfindMostRecentSession(sessionDir)-> mtime द्वारा नवीनतमlist(cwd, sessionDir?)-> एक प्रोजेक्ट दायरे में सत्रlistAll()->~/.xcsh/agent/sessionsके अंतर्गत सभी प्रोजेक्ट दायरों में सत्र
मेटाडेटा निष्कर्षण जहाँ संभव हो केवल एक उपसर्ग (readTextPrefix(..., 4096)) पढ़ता है।
संबंधित लेकिन भिन्न: प्रॉम्प्ट इतिहास संग्रहण
Section titled “संबंधित लेकिन भिन्न: प्रॉम्प्ट इतिहास संग्रहण”HistoryStorage (history-storage.ts) प्रॉम्प्ट स्मरण/खोज के लिए एक अलग SQLite उपप्रणाली है, सत्र पुनर्चालन के लिए नहीं।
- DB:
~/.xcsh/agent/history.db - तालिका:
history(id, prompt, created_at, cwd) - FTS5 अनुक्रमणिका: ट्रिगर-अनुरक्षित सिंक के साथ
history_fts - इन-मेमोरी अंतिम-प्रॉम्प्ट कैश का उपयोग करके लगातार समान प्रॉम्प्ट्स को डिडुप्लिकेट करता है
- अतुल्यकालिक सम्मिलन (
setImmediate) ताकि प्रॉम्प्ट कैप्चर टर्न निष्पादन को अवरुद्ध न करे
वार्तालाप ग्राफ/स्थिति पुनर्चालन के लिए सत्र फ़ाइलों का उपयोग करें; प्रॉम्प्ट इतिहास UX के लिए HistoryStorage का उपयोग करें।