blade-code 0.8.3 → 0.9.0

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.
Files changed (84) hide show
  1. package/dist/blade.js +2 -2
  2. package/dist/chunk-0abtfzm6.js +1 -0
  3. package/dist/chunk-0zkhjsbv.js +1 -0
  4. package/dist/{chunk-6msfa7jh.js → chunk-119fhp5q.js} +1 -1
  5. package/dist/{chunk-fma9cbq5.js → chunk-1rpgvk3r.js} +1 -1
  6. package/dist/{chunk-7bqkkjxf.js → chunk-1v2n922p.js} +1 -1
  7. package/dist/{chunk-eyypmc9m.js → chunk-2fbwmdvg.js} +2 -2
  8. package/dist/chunk-3qgj2y5r.js +1 -0
  9. package/dist/{chunk-sva5bdgz.js → chunk-45bme7n9.js} +2 -2
  10. package/dist/{chunk-zj3q4btp.js → chunk-5jq01mg6.js} +2 -2
  11. package/dist/{chunk-5sccs44n.js → chunk-5nye3k5w.js} +1 -1
  12. package/dist/chunk-7pevqbfd.js +2 -0
  13. package/dist/chunk-8dqvnx7n.js +2 -0
  14. package/dist/chunk-8edsvxf3.js +1 -0
  15. package/dist/{chunk-hqtskyc1.js → chunk-8vemqfe4.js} +2 -2
  16. package/dist/{chunk-d7nrqg5b.js → chunk-8vtznxpq.js} +2 -2
  17. package/dist/chunk-936ft6kq.js +2 -0
  18. package/dist/{chunk-jc7k8pfn.js → chunk-9ax02vtg.js} +2 -2
  19. package/dist/chunk-9qknesxs.js +6 -0
  20. package/dist/chunk-acegy4td.js +3 -0
  21. package/dist/chunk-aewrn5xp.js +1 -0
  22. package/dist/{chunk-mqqajem9.js → chunk-aq7wf2zt.js} +2 -2
  23. package/dist/{chunk-5yt80bn2.js → chunk-ax7bx0j8.js} +1 -1
  24. package/dist/chunk-b10vr4xj.js +2 -0
  25. package/dist/{chunk-vxpdjtqc.js → chunk-bc6wbcrs.js} +1 -1
  26. package/dist/chunk-bfgm5k3e.js +1566 -0
  27. package/dist/chunk-cf3fhs7j.js +1 -0
  28. package/dist/chunk-d7y2mf7c.js +4 -0
  29. package/dist/chunk-e1586s4t.js +1 -0
  30. package/dist/chunk-enk621t7.js +98 -0
  31. package/dist/chunk-fpr6d8zc.js +2 -0
  32. package/dist/{chunk-nbpjzzrg.js → chunk-gagt42k2.js} +1 -1
  33. package/dist/chunk-gdm1xzvp.js +2 -0
  34. package/dist/chunk-gm62cfjw.js +1 -0
  35. package/dist/chunk-h3bjmkvz.js +1 -0
  36. package/dist/{chunk-qvtahmff.js → chunk-j8en7x02.js} +1 -1
  37. package/dist/{chunk-2c69g6t9.js → chunk-jyr9417h.js} +2 -2
  38. package/dist/chunk-mcnfbhpr.js +6 -0
  39. package/dist/{chunk-wcf80p9y.js → chunk-mns8e65q.js} +1 -1
  40. package/dist/chunk-mpkr3s6b.js +3 -0
  41. package/dist/chunk-n9tgxfvw.js +615 -0
  42. package/dist/{chunk-be7qz4cv.js → chunk-ppyg431d.js} +1 -1
  43. package/dist/chunk-qxhrzws6.js +1 -0
  44. package/dist/{chunk-mvww9cmc.js → chunk-r6h7eja3.js} +1 -1
  45. package/dist/chunk-r8pjwjt6.js +1 -0
  46. package/dist/{chunk-97qxd4yb.js → chunk-rmfk5f9m.js} +2 -2
  47. package/dist/chunk-rrg9bw8r.js +25 -0
  48. package/dist/chunk-w3me85va.js +2 -0
  49. package/dist/{chunk-b922cq7k.js → chunk-wtxwny0p.js} +3 -3
  50. package/dist/{chunk-crbh6x86.js → chunk-x40fkg4z.js} +2 -2
  51. package/dist/{chunk-1m63zddw.js → chunk-x548f12z.js} +1 -1
  52. package/dist/{chunk-bqhghfmt.js → chunk-xtfzjb72.js} +1 -1
  53. package/dist/{chunk-ar5564sf.js → chunk-z0qxaky4.js} +1 -1
  54. package/dist/web/assets/{FilePreview-B5g8yi8d.js → FilePreview-DpovIbME.js} +1 -1
  55. package/dist/web/assets/{MarkdownRenderer-qBCxzEb_.js → MarkdownRenderer-73wC_SGk.js} +1 -1
  56. package/dist/web/assets/{McpModal-C7y2Fsqc.js → McpModal-CIpxuyTG.js} +1 -1
  57. package/dist/web/assets/{SettingsModal-Dmc7Dw_E.js → SettingsModal-BBa1libe.js} +1 -1
  58. package/dist/web/assets/{SettingsStore-BfoB9tNV.js → SettingsStore-C8YBWQPS.js} +1 -1
  59. package/dist/web/assets/{SkillsModal-CqFAIfj5.js → SkillsModal-DArZ-nCX.js} +1 -1
  60. package/dist/web/assets/{TerminalPanel-EHh8-9b9.js → TerminalPanel-BX7C7qiD.js} +1 -1
  61. package/dist/web/assets/index-DIWzaS2_.js +16 -0
  62. package/dist/web/index.html +1 -1
  63. package/package.json +2 -1
  64. package/dist/chunk-23h9grdr.js +0 -1
  65. package/dist/chunk-6spmzx13.js +0 -6
  66. package/dist/chunk-724djh7r.js +0 -1
  67. package/dist/chunk-804j7say.js +0 -1
  68. package/dist/chunk-8yk5w2ks.js +0 -1
  69. package/dist/chunk-9cr3jexy.js +0 -2
  70. package/dist/chunk-ghf5tgjr.js +0 -1
  71. package/dist/chunk-kf43f8sy.js +0 -1577
  72. package/dist/chunk-kjc2aqww.js +0 -2
  73. package/dist/chunk-kjddt9xy.js +0 -1
  74. package/dist/chunk-m0ded6ky.js +0 -615
  75. package/dist/chunk-msr67f6q.js +0 -3
  76. package/dist/chunk-ncvr73ev.js +0 -1
  77. package/dist/chunk-qwn46cd6.js +0 -2
  78. package/dist/chunk-t9cqscfq.js +0 -2
  79. package/dist/chunk-tzr992v4.js +0 -1
  80. package/dist/chunk-x8xfx9nv.js +0 -1
  81. package/dist/chunk-yewg510f.js +0 -24
  82. package/dist/chunk-zjks0ncc.js +0 -6
  83. package/dist/chunk-zsyff0ky.js +0 -3
  84. package/dist/web/assets/index-B-BRpW1c.js +0 -16
@@ -0,0 +1 @@
1
+ import{g as a,h as b,i as c,j as d,k as e}from"./chunk-mns8e65q.js";import"./chunk-ppyg431d.js";export{b as setSkipUntilVersion,d as performUpgrade,c as getUpgradeCommand,e as checkVersionOnStartup,a as checkVersion};
@@ -0,0 +1,4 @@
1
+ import{Na as J}from"./chunk-9ax02vtg.js";import"./chunk-fpr6d8zc.js";import"./chunk-acegy4td.js";import{rc as H}from"./chunk-w3me85va.js";import"./chunk-2fbwmdvg.js";import"./chunk-gdm1xzvp.js";import{Hc as B}from"./chunk-ppyg431d.js";var O={command:"doctor",describe:"Check the health of your Blade installation",builder:(D)=>D.option("rebuild-index",{type:"boolean",default:!1,describe:"Rebuild the SQLite session index from JSONL transcripts"}),handler:async(D)=>{if(D.rebuildIndex){console.log(`Rebuilding session index from JSONL transcripts...
2
+ `);try{let{rebuildProjectionIndex:z}=await import("./chunk-aewrn5xp.js"),{SessionService:F}=await import("./chunk-gm62cfjw.js"),G=await z(F.projectionDeriverForSearch());if(G===null)console.log("[WARN] Session index unavailable (SQLite driver missing); reads fall back to JSONL scan.");else console.log(`[OK] Session index rebuilt: ${G} session(s) indexed.`)}catch(z){console.log("[FAIL] Session index rebuild failed"),console.log(` Error: ${z instanceof Error?z.message:"未知错误"}`),process.exit(1)}return}console.log(`Running Blade health check...
3
+ `);let A=0;try{await J.getInstance().initialize(),console.log("[OK] Configuration: OK")}catch(z){console.log("[FAIL] Configuration: FAILED"),console.log(` Error: ${z instanceof Error?z.message:"未知错误"}`),A++}let E=process.version;if(parseInt(E.slice(1).split(".")[0])>=18)console.log(`[OK] Node.js version: ${E}`);else console.log(`[WARN] Node.js version: ${E} (recommended: v18+)`),A++;try{let z=await import("fs/promises"),F=H();await z.access(F,(await import("fs")).constants.R_OK|(await import("fs")).constants.W_OK),console.log("[OK] File system permissions: OK")}catch(z){console.log("[FAIL] File system permissions: FAILED"),console.log(" Error: Cannot read/write in current directory"),A++}try{await import("ink"),console.log("[OK] Dependencies: OK")}catch(z){console.log("[FAIL] Dependencies: FAILED"),console.log(" Error: Missing required dependencies"),A++}if(console.log(`
4
+ Health Check Summary:`),A===0)console.log("All checks passed! Blade is ready to use.");else console.log(`Warning: Found ${A} issue(s). Please resolve them for optimal performance.`),process.exit(1)}};export{O as doctorCommands};
@@ -0,0 +1 @@
1
+ import{Ub as a,Vb as b,Wb as c,Xb as d,Yb as e,Zb as f}from"./chunk-45bme7n9.js";import"./chunk-ppyg431d.js";export{b as getVersion,c as getPackageName,a as getPackageInfo,e as getFormattedVersion,d as getDescription,f as getCopyright};
@@ -0,0 +1,98 @@
1
+ import{vc as j}from"./chunk-2fbwmdvg.js";import{Bc as N,Fc as w,Gc as L,xc as O,zc as y}from"./chunk-gdm1xzvp.js";import{Hc as U}from"./chunk-ppyg431d.js";import{stat as l}from"node:fs/promises";import B from"node:path";import*as K from"node:fs";import{createReadStream as P}from"node:fs";import*as $ from"node:fs/promises";import*as D from"node:path";import{createInterface as S}from"node:readline";var I=65536;function m(g,E,_){let R=g.trim();if(!R)return;try{return JSON.parse(R)}catch(W){throw Error(`Invalid session JSONL in ${_} at line ${E}`,{cause:W})}}function F(g,E="session transcript"){let _=g.split(`
2
+ `),R=!g.endsWith(`
3
+ `),W=[];for(let[M,T]of _.entries())try{let k=m(T,M+1,E);if(k){if(typeof k.seq!=="number")k.seq=W.length+1;W.push(k)}}catch(k){if(R&&M===_.length-1)break;throw k}return W}class H{static appendQueues=new Map;filePath;constructor(g){this.filePath=g}static maxSeq(g){let E=0;for(let _ of g)if(typeof _.seq==="number"&&_.seq>E)E=_.seq;return E}static stampSeqFrom(g,E){let _=E;return g.map((R)=>{if(typeof R.seq==="number"){if(R.seq>_)_=R.seq;return R}return _+=1,{...R,seq:_}})}static stampSeq(g,E){return H.stampSeqFrom(g,H.maxSeq(E))}async append(g){try{let[E]=await this.appendEntries([g]);return E}catch(E){throw console.error(`[JSONLStore] 追加写入失败: ${this.filePath}`,E),E}}async appendBatch(g){try{return await this.appendEntries(g)}catch(E){throw console.error(`[JSONLStore] 批量追加写入失败: ${this.filePath}`,E),E}}async appendEntries(g){if(g.length===0)return[];return this.enqueue(async()=>{await $.mkdir(D.dirname(this.filePath),{recursive:!0,mode:493});let E=await $.open(this.filePath,"a+",384);try{let _=await this.repairIncompleteTail(E),R=await this.readTailSeq(E),W=H.stampSeqFrom(g,R),M=`${W.map((T)=>JSON.stringify(T)).join(`
4
+ `)}
5
+ `;return await E.appendFile(_+M,"utf8"),await E.sync(),W}finally{await E.close()}})}async createExclusive(g){if(g.length===0)throw Error("Cannot create an empty session transcript");await $.mkdir(D.dirname(this.filePath),{recursive:!0,mode:493});let E;try{E=await $.open(this.filePath,"wx",384);let R=`${H.stampSeq(g,[]).map((W)=>JSON.stringify(W)).join(`
6
+ `)}
7
+ `;await E.writeFile(R,"utf-8"),await E.sync()}catch(_){if(E)await E.close(),E=void 0,await $.unlink(this.filePath).catch(()=>{return});throw _}finally{await E?.close()}}async readAll(){if(!K.existsSync(this.filePath))return[];let g=await $.readFile(this.filePath,"utf-8");return F(g,this.filePath)}async readStream(g){return new Promise((E,_)=>{if(!K.existsSync(this.filePath)){E();return}let R=P(this.filePath,"utf-8"),W=S({input:R,crlfDelay:Number.POSITIVE_INFINITY}),M=0;W.on("line",async(T)=>{let k=T.trim();if(k.length===0)return;try{let V=JSON.parse(k);if(M+=1,typeof V.seq!=="number")V.seq=M;await g(V)}catch(V){console.warn(`[JSONLStore] 解析 JSON 行失败: ${k}`,V)}}),W.on("close",()=>E()),W.on("error",_),R.on("error",_)})}async filter(g){let E=[];return await this.readStream((_)=>{if(g(_))E.push(_)}),E}async readLast(g){return(await this.readAll()).slice(-g)}async readFromSeq(g){return(await this.readAll()).filter((_)=>(_.seq??0)>=g)}async getStats(){try{if(!K.existsSync(this.filePath))return{exists:!1,size:0,lineCount:0};let g=await $.stat(this.filePath),_=(await $.readFile(this.filePath,"utf-8")).split(`
8
+ `).filter((R)=>R.trim().length>0).length;return{exists:!0,size:g.size,lineCount:_}}catch(g){return console.error(`[JSONLStore] 获取统计信息失败: ${this.filePath}`,g),{exists:!1,size:0,lineCount:0}}}async exists(){try{return await $.access(this.filePath),!0}catch{return!1}}async delete(){try{return await this.enqueue(async()=>{try{return await $.unlink(this.filePath),!0}catch(g){if(g.code==="ENOENT")return!1;throw g}})}catch(g){throw console.error(`[JSONLStore] 删除文件失败: ${this.filePath}`,g),g}}async deleteValidated(g){return this.enqueue(async()=>{let E;try{E=await $.open(this.filePath,"r")}catch(R){if(R.code==="ENOENT")return!1;throw R}let _;try{_=F(await E.readFile("utf8"),"session transcript")}finally{await E.close()}if(!g(_))return!1;try{return await $.unlink(this.filePath),!0}catch(R){if(R.code==="ENOENT")return!1;throw R}})}async appendValidated(g){await this.appendValidatedAsync(async(E)=>g(E))}async appendValidatedAsync(g){await this.enqueue(async()=>{let E=await $.open(this.filePath,"r+");try{let{entries:_,separator:R,size:W}=await this.readCommittedState(E,"session transcript"),M=await g(_),[T]=H.stampSeq([M],_),k=`${R}${JSON.stringify(T)}
9
+ `;await E.write(k,W,"utf8"),await E.sync()}finally{await E.close()}})}getFilePath(){return this.filePath}async enqueue(g){let _=(H.appendQueues.get(this.filePath)??Promise.resolve()).catch(()=>{return}).then(g),R=_.then(()=>{return},()=>{return});H.appendQueues.set(this.filePath,R);try{return await _}finally{if(H.appendQueues.get(this.filePath)===R)H.appendQueues.delete(this.filePath)}}async readCommittedState(g,E=this.filePath){let _=await this.repairIncompleteTail(g),R=await g.readFile("utf8"),W=F(R,E),{size:M}=await g.stat();return{entries:W,separator:_,size:M}}async readTailSeq(g){let{size:E}=await g.stat();if(E===0)return 0;let _=Math.max(0,E-I),R=Buffer.allocUnsafe(E-_);await g.read(R,0,R.length,_);let W=R.toString("utf8").split(`
10
+ `);for(let T=W.length-1;T>=0;T--){let k=W[T].trim();if(!k)continue;if(T===0&&_>0)break;try{let V=JSON.parse(k).seq;if(typeof V==="number")return V}catch{}break}let M=await g.readFile("utf8");return H.maxSeq(F(M,this.filePath))}async repairIncompleteTail(g){let{size:E}=await g.stat();if(E===0)return"";let _=Buffer.allocUnsafe(1);if(await g.read(_,0,1,E-1),_[0]===10)return"";let R=await this.findTailStart(g,E),W=Buffer.allocUnsafe(E-R);await g.read(W,0,W.length,R);try{return JSON.parse(W.toString("utf8").trim()),`
11
+ `}catch{return await g.truncate(R),""}}async findTailStart(g,E){let _=E;while(_>0){let R=Math.max(0,_-I),W=Buffer.allocUnsafe(_-R);await g.read(W,0,W.length,R);let M=W.lastIndexOf(10);if(M>=0)return R+M+1;_=R}return 0}}function h(){return typeof globalThis.Bun<"u"}function b(g){return{exec:(E)=>g.exec(E),prepare:(E)=>{let _=g.prepare(E);return{run:(...R)=>{_.run(...R)},get:(...R)=>_.get(...R),all:(...R)=>_.all(...R)}},transaction:(E)=>g.transaction(E)(),pragma:(E)=>g.pragma(E,{simple:!0}),close:()=>g.close()}}function o(g){return{exec:(E)=>g.exec(E),prepare:(E)=>{let _=g.query(E);return{run:(...R)=>{_.run(...R)},get:(...R)=>_.get(...R),all:(...R)=>_.all(...R)}},transaction:(E)=>g.transaction(E)(),pragma:(E)=>{let _=g.query(`PRAGMA ${E}`).get();if(!_)return;let R=Object.values(_);return R.length===1?R[0]:_},close:()=>g.close()}}var i=["PRAGMA journal_mode=WAL;","PRAGMA busy_timeout=5000;","PRAGMA synchronous=NORMAL;","PRAGMA foreign_keys=ON;"].join(`
12
+ `);async function p(g){try{let E;if(h()){let{Database:R}=await import("bun:sqlite");E=o(new R(g))}else{let W=(await import("better-sqlite3")).default;E=b(new W(g))}return E.exec(i),E}catch{return null}}function J(g){let E=Number(g.pragma("user_version")??0);if(E===1)return;if(E>0&&E!==1)g.exec(`
13
+ DROP TABLE IF EXISTS parts_fts;
14
+ DROP TABLE IF EXISTS parts;
15
+ DROP TABLE IF EXISTS sessions;
16
+ DROP TABLE IF EXISTS projection_state;
17
+ `);g.exec(`
18
+ CREATE TABLE IF NOT EXISTS projection_state (
19
+ project_path TEXT NOT NULL,
20
+ session_id TEXT NOT NULL,
21
+ last_seq INTEGER NOT NULL DEFAULT 0,
22
+ file_size INTEGER NOT NULL DEFAULT 0,
23
+ mtime_ms INTEGER NOT NULL DEFAULT 0,
24
+ PRIMARY KEY (project_path, session_id)
25
+ );
26
+
27
+ CREATE TABLE IF NOT EXISTS sessions (
28
+ project_path TEXT NOT NULL,
29
+ session_id TEXT NOT NULL,
30
+ root_id TEXT,
31
+ parent_id TEXT,
32
+ relation_type TEXT,
33
+ title TEXT,
34
+ agent_type TEXT,
35
+ model TEXT,
36
+ task_status TEXT,
37
+ last_message_time TEXT,
38
+ first_message_time TEXT,
39
+ message_count INTEGER NOT NULL DEFAULT 0,
40
+ has_errors INTEGER NOT NULL DEFAULT 0,
41
+ is_subagent INTEGER NOT NULL DEFAULT 0,
42
+ -- 完整 StoredSessionMetadata JSON,读回时直接反序列化,保证与 JSONL 路径一致。
43
+ metadata_json TEXT NOT NULL,
44
+ PRIMARY KEY (project_path, session_id)
45
+ );
46
+ CREATE INDEX IF NOT EXISTS idx_sessions_last ON sessions(last_message_time DESC);
47
+
48
+ CREATE TABLE IF NOT EXISTS parts (
49
+ project_path TEXT NOT NULL,
50
+ session_id TEXT NOT NULL,
51
+ part_id TEXT NOT NULL,
52
+ message_id TEXT,
53
+ part_type TEXT,
54
+ role TEXT,
55
+ seq INTEGER,
56
+ timestamp TEXT,
57
+ text TEXT,
58
+ PRIMARY KEY (project_path, session_id, part_id)
59
+ );
60
+ CREATE INDEX IF NOT EXISTS idx_parts_session ON parts(project_path, session_id);
61
+
62
+ CREATE VIRTUAL TABLE IF NOT EXISTS parts_fts USING fts5(
63
+ text,
64
+ project_path UNINDEXED,
65
+ session_id UNINDEXED,
66
+ part_id UNINDEXED,
67
+ role UNINDEXED,
68
+ timestamp UNINDEXED,
69
+ seq UNINDEXED,
70
+ tokenize = 'unicode61'
71
+ );
72
+ `),g.exec("PRAGMA user_version=1;")}function n(g){return g.type==="message_created"||g.type==="part_created"||g.type==="part_updated"}function u(g){return g.type==="message_created"&&g.data.role==="user"&&(g.data.inboxMessageId!==void 0||g.data.parentMessageId===void 0)}function x(g,E){let _=g.find((R)=>u(R)&&R.data.messageId===E);if(!_)throw Error(`Rewind checkpoint not found: ${E}`);return{messageId:E,preview:q(g,E),createdAt:_.data.createdAt}}function q(g,E){let _=g.flatMap((R)=>{if(R.type!=="part_created"||R.data.messageId!==E)return[];if(R.data.partType==="text"){let W=R.data.payload;return typeof W.text==="string"?[W.text]:[]}if(R.data.partType==="image")return["[Image]"];return[]}).join("").trim();if(_.length<=160)return _;return`${_.slice(0,160)}...`}function v(g,E){x(g,E);let _=g.findIndex((R)=>R.type==="message_created"&&R.data.messageId===E);return g.filter((R,W)=>W<_||!n(R))}function Z(g){let E=[];for(let _ of g){if(_.type!=="session_rewound"){E.push(_);continue}if(x(E,_.data.targetMessageId),_.data.mode!=="code")E=v(E,_.data.targetMessageId)}return E}function TE(g){let E=Z(g);return E.filter(u).map((_)=>({messageId:_.data.messageId,preview:q(E,_.data.messageId),createdAt:_.data.createdAt})).reverse()}function VE(g,E){let _=Z(g),R=x(_,E),W=_.findIndex((T)=>T.type==="message_created"&&T.data.messageId===E),M=_.slice(W);return{checkpoint:R,projectedEntries:v(_,E),removedTurns:M.filter(u).length,snapshotMessageIds:M.flatMap((T)=>T.type==="part_created"&&T.data.partType==="tool_call"?[T.data.partId]:[])}}var d=j("Service"),G;function c(){return B.join(w(),"index.db")}async function s(){let g=c();if(G&&G.path===g)return G.db;let E=(async()=>{let _=await p(g);if(!_)return null;try{return J(_),_}catch{return null}})();return G={path:g,db:E},E}function a(){G=void 0}function r(g){if(g&&typeof g==="object"){let E=g.text;if(typeof E==="string")return E}return null}function t(g,E,_,R){g.prepare("DELETE FROM parts WHERE project_path=? AND session_id=?").run(E,_),g.prepare("DELETE FROM parts_fts WHERE project_path=? AND session_id=?").run(E,_);let W=new Map;for(let k of R)if(k.type==="message_created")W.set(k.data.messageId,k.data.role);let M=g.prepare(`INSERT OR REPLACE INTO parts
73
+ (project_path, session_id, part_id, message_id, part_type, role, seq, timestamp, text)
74
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`),T=g.prepare(`INSERT INTO parts_fts (text, project_path, session_id, part_id, role, timestamp, seq)
75
+ VALUES (?, ?, ?, ?, ?, ?, ?)`);for(let k of R){if(k.type!=="part_created"&&k.type!=="part_updated")continue;if(k.data.partType!=="text")continue;let V=r(k.data.payload);if(V===null)continue;let Q=W.get(k.data.messageId)??"assistant",A=k.seq??0;if(M.run(E,_,k.data.partId,k.data.messageId,k.data.partType,Q,A,k.timestamp,V),Q==="user"||Q==="assistant")T.run(V,E,_,k.data.partId,Q,k.timestamp,A)}}function e(g,E){g.prepare(`INSERT INTO sessions
76
+ (project_path, session_id, root_id, parent_id, relation_type, title,
77
+ agent_type, model, task_status, last_message_time, first_message_time,
78
+ message_count, has_errors, is_subagent, metadata_json)
79
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
80
+ ON CONFLICT(project_path, session_id) DO UPDATE SET
81
+ root_id=excluded.root_id, parent_id=excluded.parent_id,
82
+ relation_type=excluded.relation_type, title=excluded.title,
83
+ agent_type=excluded.agent_type, model=excluded.model,
84
+ task_status=excluded.task_status, last_message_time=excluded.last_message_time,
85
+ first_message_time=excluded.first_message_time, message_count=excluded.message_count,
86
+ has_errors=excluded.has_errors, is_subagent=excluded.is_subagent,
87
+ metadata_json=excluded.metadata_json`).run(E.projectPath,E.sessionId,E.rootId,E.parentId??null,E.relationType??null,E.title??null,E.agentType??null,E.model??null,E.taskStatus,E.lastMessageTime,E.firstMessageTime,E.messageCount,E.hasErrors?1:0,E.relationType==="subagent"?1:0,JSON.stringify(E))}function z(g,E,_){for(let R of["sessions","parts","parts_fts","projection_state"])g.prepare(`DELETE FROM ${R} WHERE project_path=? AND session_id=?`).run(E,_)}async function EE(g,E,_,R,W=N(_,E)){let M;try{let Y=await l(W);M={size:Y.size,mtimeMs:Y.mtimeMs}}catch{return g.transaction(()=>z(g,_,E)),!0}let T=g.prepare("SELECT last_seq, file_size, mtime_ms FROM projection_state WHERE project_path=? AND session_id=?").get(_,E);if(T&&T.file_size===M.size&&T.mtime_ms===Math.floor(M.mtimeMs))return!1;let V=await new H(W).readAll();if(V.length===0)return!1;let Q=Z(V),A=R(V,E,_);if(!A)return!1;let X=V.reduce((Y,f)=>typeof f.seq==="number"&&f.seq>Y?f.seq:Y,0),C=g.prepare("SELECT last_message_time FROM sessions WHERE project_path=? AND session_id=?").get(A.projectPath,A.sessionId);if(C&&typeof C.last_message_time==="string"&&C.last_message_time>A.lastMessageTime)return g.prepare(`INSERT INTO projection_state (project_path, session_id, last_seq, file_size, mtime_ms)
88
+ VALUES (?, ?, ?, ?, ?)
89
+ ON CONFLICT(project_path, session_id) DO UPDATE SET
90
+ last_seq=excluded.last_seq, file_size=excluded.file_size, mtime_ms=excluded.mtime_ms`).run(_,E,X,M.size,Math.floor(M.mtimeMs)),!0;return g.transaction(()=>{e(g,A),t(g,A.projectPath,A.sessionId,Q),g.prepare(`INSERT INTO projection_state (project_path, session_id, last_seq, file_size, mtime_ms)
91
+ VALUES (?, ?, ?, ?, ?)
92
+ ON CONFLICT(project_path, session_id) DO UPDATE SET
93
+ last_seq=excluded.last_seq, file_size=excluded.file_size, mtime_ms=excluded.mtime_ms`).run(_,E,X,M.size,Math.floor(M.mtimeMs))}),!0}async function gE(g,E){let{readdir:_}=await import("node:fs/promises"),R=await L(),W=new Set;for(let T of R){let k=O(T),V=B.join(w(),"projects",T),Q;try{Q=await _(V)}catch{continue}for(let A of Q){if(!A.endsWith(".jsonl"))continue;let X=A.slice(0,-6);if(!y(X))continue;W.add(`${k}\x00${X}`);try{await EE(g,X,k,E,B.join(V,A))}catch(C){if(C.code!=="ENOENT")d.warn(`[SessionService] Skipping invalid session transcript: ${X}`)}}}let M=g.prepare("SELECT project_path, session_id FROM projection_state").all();for(let T of M)if(!W.has(`${T.project_path}\x00${T.session_id}`))g.transaction(()=>z(g,T.project_path,T.session_id))}function UE(g,E,_){g.transaction(()=>z(g,_,E))}async function ZE(g){let{rm:E}=await import("node:fs/promises");a();let _=c();for(let M of["","-wal","-shm"])await E(`${_}${M}`,{force:!0}).catch(()=>{return});let R=await s();if(!R)return null;return await gE(R,g),R.prepare("SELECT COUNT(*) c FROM sessions").get()?.c??0}function fE(g,E,_,R){let W=E.replace(/["*]/g," ").trim().split(/\s+/)[0];if(!W)return[];let M=`"${W}"*`,T=_?`SELECT session_id, role, timestamp, text FROM parts_fts
94
+ WHERE parts_fts MATCH ? AND project_path = ?
95
+ ORDER BY timestamp DESC LIMIT ?`:`SELECT session_id, role, timestamp, text FROM parts_fts
96
+ WHERE parts_fts MATCH ?
97
+ ORDER BY timestamp DESC LIMIT ?`,k=g.prepare(T);return _?k.all(M,_,R):k.all(M,R)}
98
+ export{F as _b,H as $b,Z as ac,TE as bc,VE as cc,c as dc,s as ec,a as fc,EE as gc,gE as hc,UE as ic,ZE as jc,fE as kc};
@@ -0,0 +1,2 @@
1
+ var r;((t)=>{t.DEFAULT="default";t.AUTO_EDIT="autoEdit";t.YOLO="yolo";t.PLAN="plan"})(r||={});var N=100;function _(n){return Number.isInteger(n)&&n>=-1&&n<=100}function u(){return"-1, 0, or an integer from 1 to 100"}
2
+ export{r as Eb,N as Fb,_ as Gb,u as Hb};
@@ -1,4 +1,4 @@
1
- import{ga as O}from"./chunk-2c69g6t9.js";import{Ea as J,Ga as L}from"./chunk-yewg510f.js";import"./chunk-jc7k8pfn.js";import"./chunk-sva5bdgz.js";import"./chunk-5sccs44n.js";import"./chunk-1m63zddw.js";import"./chunk-7bqkkjxf.js";import{Sb as H}from"./chunk-kjc2aqww.js";import"./chunk-eyypmc9m.js";import"./chunk-zsyff0ky.js";import"./chunk-be7qz4cv.js";import P from"os";import E from"path";function _(q){return typeof q==="string"?q:void 0}function T(q){if(!Array.isArray(q))return;let z=[];for(let F of q)if(typeof F==="string")z.push(F);else if(F!=null)z.push(String(F));return z}function G(){console.log(`
1
+ import{ba as O}from"./chunk-jyr9417h.js";import{Da as J,Fa as L}from"./chunk-rrg9bw8r.js";import"./chunk-9ax02vtg.js";import"./chunk-5nye3k5w.js";import"./chunk-x548f12z.js";import"./chunk-1v2n922p.js";import"./chunk-fpr6d8zc.js";import"./chunk-acegy4td.js";import"./chunk-45bme7n9.js";import{rc as H}from"./chunk-w3me85va.js";import"./chunk-2fbwmdvg.js";import"./chunk-gdm1xzvp.js";import"./chunk-ppyg431d.js";import P from"os";import E from"path";function _(q){return typeof q==="string"?q:void 0}function T(q){if(!Array.isArray(q))return;let z=[];for(let F of q)if(typeof F==="string")z.push(F);else if(F!=null)z.push(String(F));return z}function G(){console.log(`
2
2
  blade mcp
3
3
  `),console.log(`管理 MCP 服务器
4
4
  `),console.log("Commands:"),console.log(" blade mcp add <name> <commandOrUrl> [args...] 添加 MCP 服务器"),console.log(" blade mcp remove <name> 删除 MCP 服务器 [aliases: rm]"),console.log(" blade mcp list 列出所有 MCP 服务器并检查健康状态 [aliases: ls]"),console.log(" blade mcp get <name> 获取服务器详情"),console.log(` blade mcp add-json <name> <json> 从 JSON 字符串添加服务器
@@ -0,0 +1,2 @@
1
+ import{Hc as F}from"./chunk-ppyg431d.js";import{execSync as G}from"node:child_process";import*as C from"node:os";import*as v from"node:path";function H(k){return v.resolve(k).replace(/[/\\]/g,"-").replace(/:/g,"_")}function M(k){let q=k.replace(/_/g,":");if(q.startsWith("-"))q="/"+q.slice(1);return q.replace(/-/g,"/")}function z(k){let q=H(k);return v.join(E(),"projects",q)}function J(k){return typeof k==="string"&&k!=="."&&k!==".."&&/^[A-Za-z0-9_-][A-Za-z0-9._-]{0,199}$/.test(k)}function A(k){if(!J(k))throw Error(`Invalid session ID: ${k}`)}function N(k,q){return A(q),v.join(z(k),`${q}.jsonl`)}function O(k,q){return A(q),v.join(z(k),`${q}.inbox.json`)}function Q(k,q){return A(q),v.join(z(k),`${q}.goal.json`)}function T(k){try{return G("git rev-parse --abbrev-ref HEAD",{cwd:k,encoding:"utf-8",stdio:["ignore","pipe","ignore"]}).trim()||void 0}catch{return}}function E(){return process.env.BLADE_STORAGE_ROOT||v.join(C.homedir(),".blade")}async function U(){let{readdir:k}=await import("node:fs/promises");try{let q=v.join(E(),"projects");return(await k(q,{withFileTypes:!0})).filter((w)=>w.isDirectory()).map((w)=>w.name)}catch{return[]}}
2
+ export{M as xc,z as yc,J as zc,A as Ac,N as Bc,O as Cc,Q as Dc,T as Ec,E as Fc,U as Gc};
@@ -0,0 +1 @@
1
+ import{Qb as a,Rb as b,Sb as c,Tb as d}from"./chunk-mpkr3s6b.js";import"./chunk-45bme7n9.js";import"./chunk-enk621t7.js";import"./chunk-936ft6kq.js";import"./chunk-w3me85va.js";import"./chunk-2fbwmdvg.js";import"./chunk-gdm1xzvp.js";import"./chunk-ppyg431d.js";export{a as __setSessionSnapshotIOForTesting,b as __resetSessionSnapshotIOForTesting,d as SessionService,c as SessionMissingCreationError};
@@ -0,0 +1 @@
1
+ import{Lb as a}from"./chunk-8vtznxpq.js";import"./chunk-acegy4td.js";import"./chunk-2fbwmdvg.js";import"./chunk-gdm1xzvp.js";import"./chunk-ppyg431d.js";export{a as createChatServiceAsync};
@@ -1 +1 @@
1
- import{g as o}from"./chunk-wcf80p9y.js";import"./chunk-be7qz4cv.js";import{execSync as r}from"child_process";var l={command:"update",describe:"Check for updates and install if available",handler:async()=>{console.log("Checking for updates...");try{let e=await o(!0);if(console.log(`Current version: ${e.currentVersion}`),e.error){console.log(`Warning: ${e.error}`);return}if(e.latestVersion)console.log(`Latest version: ${e.latestVersion}`);if(e.hasUpdate&&e.latestVersion){console.log(""),console.log(`\x1B[33mUpdate available: ${e.currentVersion} -> ${e.latestVersion}\x1B[0m`),console.log(""),console.log("Updating...");try{r("npm install -g blade-code@latest --registry https://registry.npmjs.org",{stdio:"inherit"}),console.log(""),console.log("Update complete!")}catch(t){console.error("Error: Update failed. Please run manually:"),console.error(" npm install -g blade-code@latest"),process.exit(1)}}else console.log("You are running the latest version of Blade")}catch(e){console.error(`Error: Failed to check for updates: ${e instanceof Error?e.message:"未知错误"}`),process.exit(1)}}};export{l as updateCommands};
1
+ import{g as o}from"./chunk-mns8e65q.js";import"./chunk-ppyg431d.js";import{execSync as r}from"child_process";var l={command:"update",describe:"Check for updates and install if available",handler:async()=>{console.log("Checking for updates...");try{let e=await o(!0);if(console.log(`Current version: ${e.currentVersion}`),e.error){console.log(`Warning: ${e.error}`);return}if(e.latestVersion)console.log(`Latest version: ${e.latestVersion}`);if(e.hasUpdate&&e.latestVersion){console.log(""),console.log(`\x1B[33mUpdate available: ${e.currentVersion} -> ${e.latestVersion}\x1B[0m`),console.log(""),console.log("Updating...");try{r("npm install -g blade-code@latest --registry https://registry.npmjs.org",{stdio:"inherit"}),console.log(""),console.log("Update complete!")}catch(t){console.error("Error: Update failed. Please run manually:"),console.error(" npm install -g blade-code@latest"),process.exit(1)}}else console.log("You are running the latest version of Blade")}catch(e){console.error(`Error: Failed to check for updates: ${e instanceof Error?e.message:"未知错误"}`),process.exit(1)}}};export{l as updateCommands};
@@ -1,4 +1,4 @@
1
- import{Ua as I,Va as C}from"./chunk-sva5bdgz.js";import{Bb as R}from"./chunk-5sccs44n.js";import{Gb as E,Ib as U}from"./chunk-1m63zddw.js";import{oc as f}from"./chunk-be7qz4cv.js";import{EventEmitter as t}from"events";function p($){if($===void 0)return"undefined";if(typeof $==="string")return $;try{let L=JSON.stringify($);return L===void 0?String($):L}catch{return String($)}}function g($){let L=$;switch($.code){case"type":return`类型错误:${$.message}`;case"required":return"缺少必需参数";case"minLength":return`字符串过短:${$.message}`;case"maxLength":return`字符串过长:${$.message}`;case"minimum":case"exclusiveMinimum":return`数值太小:${$.message}`;case"maximum":case"exclusiveMaximum":return`数值太大:${$.message}`;case"minItems":return`数组元素过少:${$.message}`;case"maxItems":return`数组元素过多:${$.message}`;case"format":return`格式错误:${$.message}`;case"enum":return`必须是枚举允许的值之一:${$.message}`;case"const":return`必须是指定的字面量值:${$.message}`;case"additionalProperties":case"unevaluatedProperties":return`包含未知参数:${$.message}`;case"anyOf":case"oneOf":return"不符合任何有效的类型定义";case"~refine":return $.message||"自定义验证失败";default:return $.message||`验证失败:${p(L)}`}}class D extends Error{issues;type;constructor($,L,G="validation_error"){super($);this.issues=L;this.type=G;this.name="ToolValidationError"}}function N($,L){let G=E($,L);if(G.success)return G.data;let Q=G.error.issues.map((X)=>({field:X.path.length>0?X.path.join("."):"root",message:g(X),value:X.value})),W=Q.length===1?`参数验证失败 [${Q[0].field}]: ${Q[0].message}`:`参数验证失败 (${Q.length} 个错误):
1
+ import{sb as R}from"./chunk-5nye3k5w.js";import{xb as E,zb as U}from"./chunk-x548f12z.js";import{Vb as I,Wb as C}from"./chunk-45bme7n9.js";import{Hc as f}from"./chunk-ppyg431d.js";import{EventEmitter as t}from"events";function p($){if($===void 0)return"undefined";if(typeof $==="string")return $;try{let L=JSON.stringify($);return L===void 0?String($):L}catch{return String($)}}function g($){let L=$;switch($.code){case"type":return`类型错误:${$.message}`;case"required":return"缺少必需参数";case"minLength":return`字符串过短:${$.message}`;case"maxLength":return`字符串过长:${$.message}`;case"minimum":case"exclusiveMinimum":return`数值太小:${$.message}`;case"maximum":case"exclusiveMaximum":return`数值太大:${$.message}`;case"minItems":return`数组元素过少:${$.message}`;case"maxItems":return`数组元素过多:${$.message}`;case"format":return`格式错误:${$.message}`;case"enum":return`必须是枚举允许的值之一:${$.message}`;case"const":return`必须是指定的字面量值:${$.message}`;case"additionalProperties":case"unevaluatedProperties":return`包含未知参数:${$.message}`;case"anyOf":case"oneOf":return"不符合任何有效的类型定义";case"~refine":return $.message||"自定义验证失败";default:return $.message||`验证失败:${p(L)}`}}class D extends Error{issues;type;constructor($,L,G="validation_error"){super($);this.issues=L;this.type=G;this.name="ToolValidationError"}}function N($,L){let G=E($,L);if(G.success)return G.data;let Q=G.error.issues.map((X)=>({field:X.path.length>0?X.path.join("."):"root",message:g(X),value:X.value})),W=Q.length===1?`参数验证失败 [${Q[0].field}]: ${Q[0].message}`:`参数验证失败 (${Q.length} 个错误):
2
2
  ${Q.map((X)=>` - ${X.field}: ${X.message}`).join(`
3
3
  `)}`;throw new D(W,Q)}function K($){if(!$||typeof $!=="object")return;let L=$;if(L.type==="object"&&L.properties)L.required??=[],L.additionalProperties??=!1;for(let G of Object.values(L))if(Array.isArray(G))for(let Q of G)K(Q);else K(G)}function x($){let L=JSON.parse(JSON.stringify($,(G,Q)=>G.startsWith("~")?void 0:Q));return K(L),L}class O{toolName;params;executeFn;descriptionFn;affectedPathsFn;constructor($,L,G,Q,W){this.toolName=$;this.params=L;this.executeFn=G;this.descriptionFn=Q;this.affectedPathsFn=W}getDescription(){if(this.descriptionFn)return this.descriptionFn(this.params);return`执行工具: ${this.toolName}`}getAffectedPaths(){if(this.affectedPathsFn)return this.affectedPathsFn(this.params);return[]}async execute($,L,G){let Q={signal:$,updateOutput:L,...G};return this.executeFn(this.params,Q)}}function h($){return{name:$.name,displayName:$.displayName,kind:$.kind,isReadOnly:$.isReadOnly??R($.kind),isConcurrencySafe:$.isConcurrencySafe??!1,strict:$.strict??!1,description:$.description,version:$.version||"1.0.0",category:$.category,tags:$.tags||[],getFunctionDeclaration(){let L=x($.schema),G=$.description.short;if($.description.long)G+=`
4
4
 
@@ -31,4 +31,4 @@ ${$.description.important.map((Q)=>`[WARN] ${Q}`).join(`
31
31
  `),Q.close(),L(q)}catch(Y){Q.close(),G(Y)}});Q.on("error",G),Q.listen(V,()=>{console.log(`[OAuth] Callback server listening on port ${V}`)}),setTimeout(()=>{Q.close(),G(Error("OAuth callback timeout"))},300000)})}async exchangeCodeForToken($,L,G){let Q=$.redirectUri||`http://localhost:${V}${j}`,W=new URLSearchParams({grant_type:"authorization_code",code:L,redirect_uri:Q,code_verifier:G,client_id:$.clientId});if($.clientSecret)W.append("client_secret",$.clientSecret);let X=await fetch($.tokenUrl,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded",Accept:"application/json"},body:W.toString()});if(!X.ok){let Y=await X.text();throw Error(`Token exchange failed: ${X.status} - ${Y}`)}return await X.json()}async refreshAccessToken($,L){let G=new URLSearchParams({grant_type:"refresh_token",refresh_token:L,client_id:$.clientId});if($.clientSecret)G.append("client_secret",$.clientSecret);if($.scopes&&$.scopes.length>0)G.append("scope",$.scopes.join(" "));let Q=await fetch($.tokenUrl,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded",Accept:"application/json"},body:G.toString()});if(!Q.ok){let W=await Q.text();throw Error(`Token refresh failed: ${Q.status} - ${W}`)}return await Q.json()}async authenticate($,L){if(!L.clientId||!L.authorizationUrl||!L.tokenUrl)throw Error("Missing required OAuth configuration");let G=this.generatePKCEParams(),Q=this.buildAuthorizationUrl(L,G);console.log(`
32
32
  [OAuth] Opening browser for authentication...`),console.log(`
33
33
  If the browser does not open automatically, copy and paste this URL:`),console.log(Q),console.log("");let W=this.startCallbackServer(G.state);try{await this.openAuthorizationUrl(Q)}catch(Z){console.warn("[OAuth] Failed to open browser automatically:",Z)}let X=await W;console.log("[OAuth] Authorization code received, exchanging for tokens...");let Y=await this.exchangeCodeForToken(L,X,G.codeVerifier),q={accessToken:Y.access_token,tokenType:Y.token_type||"Bearer",refreshToken:Y.refresh_token,scope:Y.scope};if(Y.expires_in)q.expiresAt=Date.now()+Y.expires_in*1000;return await this.tokenStorage.saveToken($,q,L.clientId,L.tokenUrl),console.log("[OAuth] Authentication successful! Token saved."),q}async openAuthorizationUrl($){let{command:L,args:G}=this.getBrowserCommand($);await new Promise((Q,W)=>{let X=m(L,G,{stdio:"ignore"});X.once("error",W),X.once("close",(Y)=>{if(Y===0||Y===null)Q();else W(Error(`Failed to open browser (exit code ${Y})`))})})}getBrowserCommand($){if(process.platform==="darwin")return{command:"open",args:[$]};if(process.platform==="win32")return{command:"cmd",args:["/c","start","",$]};return{command:"xdg-open",args:[$]}}async getValidToken($,L){let G=await this.tokenStorage.getCredentials($);if(!G)return null;let{token:Q}=G;if(!this.tokenStorage.isTokenExpired(Q))return Q.accessToken;if(Q.refreshToken&&L.clientId&&G.tokenUrl)try{console.log(`[OAuth] Refreshing expired token for server: ${$}`);let W=await this.refreshAccessToken(L,Q.refreshToken),X={accessToken:W.access_token,tokenType:W.token_type,refreshToken:W.refresh_token||Q.refreshToken,scope:W.scope||Q.scope};if(W.expires_in)X.expiresAt=Date.now()+W.expires_in*1000;return await this.tokenStorage.saveToken($,X,L.clientId,G.tokenUrl),X.accessToken}catch(W){console.error("[OAuth] Failed to refresh token:",W),await this.tokenStorage.deleteCredentials($)}return null}}import{EventEmitter as l}from"events";class P extends l{client;config;checkTimer=null;isChecking=!1;consecutiveFailures=0;lastCheckTime=0;currentStatus="healthy";constructor($,L={}){super();this.client=$,this.config={interval:L.interval??30000,timeout:L.timeout??1e4,enabled:L.enabled??!1,failureThreshold:L.failureThreshold??3}}start(){if(this.checkTimer){console.warn("[HealthMonitor] 健康监控已在运行");return}if(!this.config.enabled){console.log("[HealthMonitor] 健康监控未启用");return}console.log(`[HealthMonitor] 启动健康监控(间隔: ${this.config.interval}ms)`),this.scheduleNextCheck()}stop(){if(this.checkTimer)clearTimeout(this.checkTimer),this.checkTimer=null,console.log("[HealthMonitor] 停止健康监控")}scheduleNextCheck(){this.checkTimer=setTimeout(async()=>{await this.performHealthCheck(),this.scheduleNextCheck()},this.config.interval)}async performHealthCheck(){if(this.isChecking)return console.warn("[HealthMonitor] 上一次检查仍在进行中"),this.getLastResult();this.isChecking=!0,this.lastCheckTime=Date.now(),this.setStatus("checking");try{let $=this.client.connectionStatus;if($==="connected"){await this.pingServer(),this.consecutiveFailures=0,this.setStatus("healthy");let L={status:"healthy",timestamp:Date.now(),consecutiveFailures:0};return this.emit("healthCheck",L),L}else throw Error(`连接状态异常: ${$}`)}catch($){this.consecutiveFailures++;let L=$;console.warn(`[HealthMonitor] 健康检查失败(${this.consecutiveFailures}/${this.config.failureThreshold}):`,L.message);let G;if(this.consecutiveFailures>=this.config.failureThreshold)G="unhealthy",this.emit("unhealthy",this.consecutiveFailures,L),console.log("[HealthMonitor] 达到失败阈值,触发重连..."),this.triggerReconnection().catch((W)=>{console.error("[HealthMonitor] 重连失败:",W)});else G="degraded";this.setStatus(G);let Q={status:G,timestamp:Date.now(),consecutiveFailures:this.consecutiveFailures,lastError:L};return this.emit("healthCheck",Q),Q}finally{this.isChecking=!1}}async pingServer(){let $=new Promise((G,Q)=>{setTimeout(()=>Q(Error("Health check timeout")),this.config.timeout)}),L=(async()=>{if(this.client.availableTools.length===0){if(!this.client.server)throw Error("Server info not available")}})();await Promise.race([L,$])}async triggerReconnection(){try{await this.client.disconnect(),await new Promise(($)=>setTimeout($,1000)),await this.client.connect(),console.log("[HealthMonitor] 重连成功"),this.consecutiveFailures=0,this.setStatus("healthy"),this.emit("reconnected")}catch($){throw console.error("[HealthMonitor] 重连失败:",$),$}}setStatus($){if(this.currentStatus!==$){let L=this.currentStatus;this.currentStatus=$,this.emit("statusChanged",$,L)}}getStatus(){return this.currentStatus}getLastResult(){return{status:this.currentStatus,timestamp:this.lastCheckTime,consecutiveFailures:this.consecutiveFailures}}getStatistics(){return{status:this.currentStatus,consecutiveFailures:this.consecutiveFailures,lastCheckTime:this.lastCheckTime,isChecking:this.isChecking,config:this.config}}async checkNow(){return this.performHealthCheck()}resetFailureCount(){if(this.consecutiveFailures=0,this.currentStatus!=="checking")this.setStatus("healthy")}}function T($){if(!($ instanceof Error))return{type:"unknown",isRetryable:!1,originalError:Error(String($))};let L=$.message.toLowerCase();if(["command not found","no such file","permission denied","invalid configuration","malformed","syntax error"].some((W)=>L.includes(W)))return{type:"config_error",isRetryable:!1,originalError:$};if(L.includes("unauthorized")||L.includes("401")||L.includes("authentication failed"))return{type:"auth_error",isRetryable:!1,originalError:$};if(["timeout","connection refused","network error","temporary","try again","rate limit","too many requests","service unavailable","socket hang up","econnreset","enotfound","econnrefused","etimedout","503","429"].some((W)=>L.includes(W)))return{type:"network_temporary",isRetryable:!0,originalError:$};return{type:"unknown",isRetryable:!0,originalError:$}}class y extends s{config;status="disconnected";sdkClient=null;tools=new Map;serverInfo=null;reconnectAttempts=0;MAX_RECONNECT_ATTEMPTS=5;reconnectTimer=null;isManualDisconnect=!1;oauthProvider=null;serverName;healthMonitor=null;constructor($,L,G){super();this.config=$;if(this.serverName=L||"default",$.oauth?.enabled)this.oauthProvider=new F;if(G?.enabled)this.healthMonitor=new P(this,G),this.healthMonitor.on("unhealthy",(Q,W)=>{this.emit("unhealthy",Q,W)}),this.healthMonitor.on("reconnected",()=>{this.emit("healthMonitorReconnected")})}get connectionStatus(){return this.status}get availableTools(){return Array.from(this.tools.values())}get server(){return this.serverInfo}get healthCheck(){return this.healthMonitor}async connect(){return this.connectWithRetry(3,1000)}async connectWithRetry($=3,L=1000){if(this.status!=="disconnected"&&this.status!=="error")throw Error("客户端已连接或正在连接中");if(this.status==="error"){if(this.sdkClient){try{await this.sdkClient.close()}catch{}this.sdkClient=null}this.setStatus("disconnected")}let G=null;for(let Q=1;Q<=$;Q++)try{await this.doConnect(),this.reconnectAttempts=0;return}catch(W){G=W;let X=T(W);if(!X.isRetryable)throw console.error("[McpClient] 检测到永久性错误,放弃重试:",X.type),W;if(Q<$){let Y=L*Math.pow(2,Q-1);console.warn(`[McpClient] 连接失败(${Q}/${$}),${Y}ms 后重试...`),await new Promise((q)=>setTimeout(q,Y))}}throw G||Error("连接失败")}async doConnect(){try{this.setStatus("connecting"),this.sdkClient=new i({name:C(),version:I()},{capabilities:{roots:{listChanged:!0},sampling:{}}}),this.sdkClient.onclose=()=>{this.handleUnexpectedClose()};let $=await this.createTransport();await this.sdkClient.connect($);let L=this.sdkClient.getServerVersion();if(this.serverInfo={name:L?.name||"Unknown",version:L?.version||"0.0.0"},await this.loadTools(),this.setStatus("connected"),this.emit("connected",this.serverInfo),this.healthMonitor)this.healthMonitor.start()}catch($){throw this.setStatus("error"),this.emit("error",$),$}}handleUnexpectedClose(){if(this.isManualDisconnect)return;if(this.status==="connected")console.warn("[McpClient] 检测到意外断连,准备重连..."),this.setStatus("error"),this.emit("error",Error("MCP服务器连接意外关闭")),this.scheduleReconnect()}scheduleReconnect(){if(this.reconnectTimer)clearTimeout(this.reconnectTimer),this.reconnectTimer=null;if(this.reconnectAttempts>=this.MAX_RECONNECT_ATTEMPTS){console.error("[McpClient] 达到最大重连次数,放弃重连"),this.emit("reconnectFailed");return}let $=Math.min(1000*Math.pow(2,this.reconnectAttempts),30000);this.reconnectAttempts++,console.log(`[McpClient] 将在 ${$}ms 后进行第 ${this.reconnectAttempts} 次重连...`),this.reconnectTimer=setTimeout(async()=>{try{if(this.sdkClient){try{await this.sdkClient.close()}catch{}this.sdkClient=null}this.setStatus("disconnected"),await this.doConnect(),console.log("[McpClient] 重连成功"),this.reconnectAttempts=0,this.emit("reconnected")}catch(L){if(console.error("[McpClient] 重连失败:",L),T(L).isRetryable)this.scheduleReconnect();else console.error("[McpClient] 检测到永久性错误,停止重连"),this.emit("reconnectFailed")}},$)}async disconnect(){if(this.isManualDisconnect=!0,this.healthMonitor)this.healthMonitor.stop();if(this.reconnectTimer)clearTimeout(this.reconnectTimer),this.reconnectTimer=null;if(this.sdkClient){try{await this.sdkClient.close()}catch($){console.warn("[McpClient] 断开连接时出错:",$)}this.sdkClient=null}this.tools.clear(),this.serverInfo=null,this.reconnectAttempts=0,this.setStatus("disconnected"),this.emit("disconnected"),this.isManualDisconnect=!1}async callTool($,L={}){if(!this.sdkClient)throw Error("客户端未连接到服务器");if(!this.tools.has($))throw Error(`工具 "${$}" 不存在`);try{return await this.sdkClient.callTool({name:$,arguments:L})}catch(G){throw console.error(`[McpClient] 调用工具 "${$}" 失败:`,G),G}}async createTransport(){let{type:$,command:L,args:G,env:Q,url:W,headers:X,oauth:Y}=this.config,q={...X};if(Y?.enabled&&this.oauthProvider&&($==="sse"||$==="http"))try{let Z=await this.oauthProvider.getValidToken(this.serverName,Y);if(!Z){console.log(`[McpClient] 服务器 "${this.serverName}" 需要 OAuth 认证`);let A=await this.oauthProvider.authenticate(this.serverName,Y);q.Authorization=`Bearer ${A.accessToken}`}else q.Authorization=`Bearer ${Z}`}catch(Z){throw console.error("[McpClient] OAuth 认证失败:",Z),Error(`OAuth 认证失败: ${Z instanceof Error?Z.message:String(Z)}`)}if($==="stdio"){if(!L)throw Error("stdio 传输需要 command 参数");let Z={};for(let[A,B]of Object.entries(process.env))if(B!==void 0)Z[A]=B;return new c({command:L,args:G||[],env:{...Z,...Q},stderr:"ignore"})}else if($==="sse"){if(!W)throw Error("sse 传输需要 url 参数");return new a(new URL(W),{requestInit:{headers:q}})}else if($==="http"){if(!W)throw Error("http 传输需要 url 参数");let{StreamableHTTPClientTransport:Z}=await import("@modelcontextprotocol/sdk/client/streamableHttp.js");return new Z(new URL(W),{requestInit:{headers:q}})}throw Error(`不支持的传输类型: ${$}`)}async loadTools(){if(!this.sdkClient)return;try{let $=await this.sdkClient.listTools();if(this.tools.clear(),$.tools)for(let L of $.tools)this.tools.set(L.name,L);this.emit("toolsUpdated",this.availableTools)}catch($){throw console.error("[McpClient] 加载工具失败:",$),$}}setStatus($){let L=this.status;this.status=$,this.emit("statusChanged",$,L)}async initialize(){return this.connect()}async destroy(){return this.disconnect()}async connectToServer($){return this.connect()}async disconnectFromServer($){return this.disconnect()}async listResources($){if(!this.sdkClient)return[];try{return(await this.sdkClient.listResources()).resources||[]}catch{return[]}}async listTools($){return this.availableTools}async readResource($,L){if(!this.sdkClient)throw Error("客户端未连接");return(await this.sdkClient.readResource({uri:$})).contents?.[0]||{uri:$,text:""}}}class J extends t{static instance=null;servers=new Map;isDiscovering=!1;constructor(){super()}static getInstance(){if(!J.instance)J.instance=new J;return J.instance}static createIsolated(){return new J}async registerServer($,L){if(this.servers.has($))throw Error(`MCP服务器 "${$}" 已经注册`);let G=new y(L,$,L.healthCheck),Q={config:L,client:G,status:"disconnected",tools:[]};this.setupClientEventHandlers(G,Q,$),this.servers.set($,Q),this.emit("serverRegistered",$,Q);try{await this.connectServer($)}catch(W){console.warn(`MCP服务器 "${$}" 连接失败:`,W)}}async unregisterServer($){let L=this.servers.get($);if(!L)return;try{await L.client.disconnect()}catch(G){console.warn(`断开MCP服务器 "${$}" 时出错:`,G)}this.servers.delete($),this.emit("serverUnregistered",$)}async connectServer($){let L=this.servers.get($);if(!L)throw Error(`MCP服务器 "${$}" 未注册`);if(L.status==="connected")return;try{L.status="connecting",await L.client.connect(),L.connectedAt=new Date,L.lastError=void 0,L.tools=L.client.availableTools}catch(G){throw L.lastError=G,L.status="error",G}}async disconnectServer($){let L=this.servers.get($);if(!L)return;await L.client.disconnect(),L.connectedAt=void 0}async reconnectServer($){let L=this.servers.get($);if(!L)throw Error(`MCP服务器 "${$}" 未注册`);if(L.status==="connected")await L.client.disconnect();try{L.status="connecting",await L.client.connect(),L.connectedAt=new Date,L.lastError=void 0,L.tools=L.client.availableTools}catch(G){throw L.lastError=G,L.status="error",G}}async getAvailableTools(){let $=[],L=new Map;for(let[G,Q]of this.servers)if(Q.status==="connected")for(let W of Q.tools){let X=L.get(W.name)||0;L.set(W.name,X+1)}for(let[G,Q]of this.servers)if(Q.status==="connected")for(let W of Q.tools){let Y=(L.get(W.name)||0)>1?`${G}__${W.name}`:W.name,q=z(Q.client,G,W,Y);$.push(q)}return $}async findTool($){for(let[L,G]of this.servers)if(G.status==="connected"){let Q=G.tools.find((W)=>W.name===$);if(Q)return z(G.client,L,Q)}return null}getToolsByServer($){let L=this.servers.get($);if(!L||L.status!=="connected")return[];return L.tools.map((G)=>z(L.client,$,G))}getServerStatus($){return this.servers.get($)||null}getAllServers(){return new Map(this.servers)}async refreshAllTools(){let $=[];for(let[L,G]of this.servers)if(G.status==="connected")$.push(this.refreshServerTools(L));await Promise.allSettled($)}async refreshServerTools($){let L=this.servers.get($);if(!L||L.status!=="connected")return;try{let G=L.client.availableTools,Q=L.tools.length;L.tools=G,this.emit("toolsUpdated",$,G,Q)}catch(G){console.warn(`刷新服务器 "${$}" 工具列表失败:`,G)}}setupClientEventHandlers($,L,G){$.on("connected",(Q)=>{L.status="connected",L.connectedAt=new Date,L.tools=$.availableTools,this.emit("serverConnected",G,Q)}),$.on("disconnected",()=>{L.status="disconnected",L.connectedAt=void 0,L.tools=[],this.emit("serverDisconnected",G)}),$.on("error",(Q)=>{L.status="error",L.lastError=Q,this.emit("serverError",G,Q)}),$.on("toolsUpdated",(Q)=>{let W=L.tools.length;L.tools=Q,this.emit("toolsUpdated",G,Q,W)}),$.on("statusChanged",(Q,W)=>{L.status=Q,this.emit("serverStatusChanged",G,Q,W)})}async discoverServers(){if(this.isDiscovering)return Array.from(this.servers.values());this.isDiscovering=!0,this.emit("discoveryStarted");try{return Array.from(this.servers.values())}finally{this.isDiscovering=!1,this.emit("discoveryCompleted")}}async registerServers($){let L=Object.entries($).map(([G,Q])=>this.registerServer(G,Q).catch((W)=>{return console.warn(`注册MCP服务器 "${G}" 失败:`,W),W}));await Promise.allSettled(L)}getStatistics(){let $=0,L=0,G=0;for(let Q of this.servers.values())if(Q.status==="connected")$++,L+=Q.tools.length;else if(Q.status==="error")G++;return{totalServers:this.servers.size,connectedServers:$,errorServers:G,totalTools:L,isDiscovering:this.isDiscovering}}async disconnectAll(){let $=[];for(let[L,G]of this.servers)if(G.status==="connected")$.push(G.client.disconnect().catch((Q)=>{console.warn(`断开 MCP 服务器 "${L}" 时出错:`,Q)}));await Promise.allSettled($),this.servers.clear()}}
34
- export{h as fa,J as ga};
34
+ export{h as aa,J as ba};
@@ -0,0 +1,6 @@
1
+ import{_ as A}from"./chunk-7pevqbfd.js";import{ua as C}from"./chunk-rrg9bw8r.js";import{Ga as f,Ha as T,Ia as M,Ja as w,Ka as N,Na as k,Oa as b}from"./chunk-9ax02vtg.js";import{Cb as m,xb as S,zb as n}from"./chunk-x548f12z.js";import{Eb as c,Fb as y}from"./chunk-fpr6d8zc.js";import{oc as O}from"./chunk-w3me85va.js";import{vc as h}from"./chunk-2fbwmdvg.js";import{promises as I}from"node:fs";import R from"node:path";var U=["systemPrompt","appendSystemPrompt","initialMessage","resumeSessionId","forkSession","allowedTools","disallowedTools","mcpConfigPaths","strictMcpConfig","model","addDirs","outputFormat","inputFormat","print","includePartialMessages","replayUserMessages","agentsConfig","settingSources"],x=new Set([...Object.keys(f),...U]),p=n.Number({exclusiveMinimum:0}),l=n.String({minLength:1}),r=n.Array(n.String()),B=n.Object({currentModelId:n.Optional(n.String()),models:n.Optional(n.Array(n.Object({id:l,displayName:n.Optional(l),provider:l,model:l,overrides:n.Optional(n.Object({baseUrl:n.Optional(n.String()),temperature:n.Optional(n.Number()),maxOutputTokens:n.Optional(p),timeout:n.Optional(p),apiVersion:n.Optional(n.String()),customHeaders:n.Optional(n.Record(n.String(),n.String())),maxRetries:n.Optional(n.Integer({minimum:0})),enablePromptCaching:n.Optional(n.Boolean())})),fallbackModels:n.Optional(n.Array(n.Object({provider:l,model:l})))}))),temperature:n.Optional(n.Number()),maxOutputTokens:n.Optional(p),stream:n.Optional(n.Boolean()),topP:n.Optional(n.Number()),topK:n.Optional(n.Number()),timeout:n.Optional(p),theme:n.Optional(n.String()),uiTheme:n.Optional(m(["light","dark","system"])),language:n.Optional(n.String()),fontSize:n.Optional(p),autoSaveSessions:n.Optional(n.Boolean()),notifyBuild:n.Optional(n.Boolean()),notifyErrors:n.Optional(n.Boolean()),notifySounds:n.Optional(n.Boolean()),privacyTelemetry:n.Optional(n.Boolean()),privacyCrash:n.Optional(n.Boolean()),debug:n.Optional(n.Union([n.Boolean(),n.String()])),mcpEnabled:n.Optional(n.Boolean()),mcpServers:n.Optional(n.Record(n.String(),n.Record(n.String(),n.Unknown()))),permissionMode:n.Optional(n.Enum(c)),maxTurns:n.Optional(n.Integer({minimum:-1,maximum:y})),maxConcurrentTasks:n.Optional(n.Integer({minimum:T,maximum:M})),maxQueuedTasks:n.Optional(n.Integer({minimum:w,maximum:N})),systemPrompt:n.Optional(n.String()),appendSystemPrompt:n.Optional(n.String()),initialMessage:n.Optional(n.String()),resumeSessionId:n.Optional(n.String()),forkSession:n.Optional(n.Boolean()),allowedTools:n.Optional(n.Array(l)),disallowedTools:n.Optional(n.Array(l)),mcpConfigPaths:n.Optional(n.Array(l)),strictMcpConfig:n.Optional(n.Boolean()),model:n.Optional(l),addDirs:n.Optional(n.Array(l)),outputFormat:n.Optional(m(["text","json","stream-json","jsonl"])),inputFormat:n.Optional(m(["text","stream-json"])),print:n.Optional(n.Boolean()),includePartialMessages:n.Optional(n.Boolean()),replayUserMessages:n.Optional(n.Boolean()),agentsConfig:n.Optional(n.String()),settingSources:n.Optional(n.String()),permissions:n.Optional(n.Object({allow:n.Optional(r),ask:n.Optional(r),deny:n.Optional(r)})),env:n.Optional(n.Record(n.String(),n.String())),hooks:n.Optional(n.Record(n.String(),n.Unknown())),disableAllHooks:n.Optional(n.Boolean())}),_=[["systemPrompt","systemPrompt"],["appendSystemPrompt","appendSystemPrompt"],["initialMessage","initialMessage"],["resumeSessionId","sessionId"],["forkSession","forkSession"],["allowedTools","allowedTools"],["disallowedTools","disallowedTools"],["mcpConfigPaths","mcpConfig"],["strictMcpConfig","strictMcpConfig"],["model","model"],["addDirs","addDir"],["outputFormat","outputFormat"],["inputFormat","inputFormat"],["print","print"],["includePartialMessages","includePartialMessages"],["replayUserMessages","replayUserMessages"],["agentsConfig","agents"],["settingSources","settingSources"],["permissionMode","permissionMode"],["maxTurns","maxTurns"],["maxConcurrentTasks","maxConcurrentTasks"],["maxQueuedTasks","maxQueuedTasks"]];function u(o,e){let t;try{t=JSON.parse(o)}catch(i){let a=i instanceof Error?`: ${i.message}`:"";throw Error(`Invalid JSON provided to --settings (${e})${a}`)}if(!t||typeof t!=="object"||Array.isArray(t))throw Error("--settings must contain a JSON object");for(let i of Object.keys(t))if(!x.has(i))throw Error(`Unknown --settings field: ${i}`);let s=S(B,t);if(!s.success){let i=s.error.issues.map((a)=>`${a.path.join(".")||"settings"}: ${a.message}`).join("; ");throw Error(`Invalid --settings value: ${i}`)}return s.data}async function P(o){if(o===void 0)return;let e=o.trim();if(!e)throw Error("--settings requires a JSON object or file path");if(e.startsWith("{"))return u(e,"inline JSON");let t=R.resolve(O(),e),s;try{s=await I.readFile(t,"utf8")}catch(i){let a=i instanceof Error?`: ${i.message}`:"";throw Error(`Unable to read --settings file ${t}${a}`)}return u(s,t)}function E(o,e){if(!e)return;let t=e;for(let[s,i]of _){if(s==="permissionMode"&&o.yolo===!0)continue;if(o[i]===void 0&&t[s]!==void 0)o[i]=t[s]}}var d=h("General"),Z=(o)=>{if(o.yolo){if(o.permissionMode&&o.permissionMode!=="yolo")throw Error("Cannot use both --yolo and --permission-mode with different values");o.permissionMode="yolo"}if(Array.isArray(o.allowedTools))o.allowedTools=o.allowedTools.flatMap((e)=>e.split(",").map((t)=>t.trim()).filter((t)=>t.length>0));if(Array.isArray(o.disallowedTools))o.disallowedTools=o.disallowedTools.flatMap((e)=>e.split(",").map((t)=>t.trim()).filter((t)=>t.length>0));if(Array.isArray(o.allowedTools)&&Array.isArray(o.disallowedTools)){let e=o.allowedTools.filter((t)=>o.disallowedTools.includes(t));if(e.length>0)throw Error(`Tools cannot be both allowed and disallowed: ${e.join(", ")}`)}},g=async(o)=>{let e=await P(typeof o.settings==="string"?o.settings:void 0);if(E(o,e),typeof o.agents==="string")A(o.agents);F(o);try{let s=await k.getInstance().initialize(e),i=b(s,o);if(C().config.actions.setConfig(i),o.debug)d.info("[CLI] 配置已加载到 Store")}catch(t){d.error("[CLI] [FAIL] 配置初始化失败",t instanceof Error?t.message:t),console.error(`
2
+ [FAIL] 配置初始化失败
3
+ `),console.error("原因:",t instanceof Error?t.message:"未知错误"),console.error(`
4
+ 请检查:`),console.error(" 1. 配置文件格式是否正确 (~/.blade/config.json)"),console.error(" 2. 是否需要运行 blade 进行首次配置"),console.error(` 3. 配置文件权限是否正确
5
+ `),process.exit(1)}};function F(o){if(o.continue&&o.resume)throw Error("Cannot use both --continue and --resume flags simultaneously");if(o.forkSession&&!o.continue&&!o.resume)throw Error("--fork-session requires --resume or --continue");if(o.sessionId&&(o.continue||o.resume)&&!o.forkSession)throw Error("--session-id can only be combined with --resume or --continue when --fork-session is set")}var v=(o)=>{if(o.outputFormat&&o.outputFormat!=="text"&&!o.print&&!o.headless)throw Error("--output-format can only be used with --print or --headless");if(o.headless&&o.outputFormat&&!["text","jsonl"].includes(o.outputFormat))throw Error(`--headless only supports --output-format text|jsonl, but got "${o.outputFormat}". Use --print for json|stream-json support.`);if(o.print&&o.outputFormat&&!["text","json","stream-json"].includes(o.outputFormat))throw Error(`--print only supports --output-format text|json|stream-json, but got "${o.outputFormat}". Use --headless for jsonl support.`);if(o.inputFormat==="stream-json"&&o.print)d.warn("[WARN] Warning: stream-json input format may not work as expected with --print")};
6
+ export{Z as X,g as Y,v as Z};
@@ -1,2 +1,2 @@
1
- import{oc as y}from"./chunk-be7qz4cv.js";import*as j from"fs/promises";import*as $ from"path";import b from"semver";import{fileURLToPath as N}from"url";import{ProxyAgent as G,fetch as H}from"undici";function T(){return process.env.HTTPS_PROXY||process.env.HTTP_PROXY||process.env.https_proxy||process.env.http_proxy}function R(){let q=T();if(q)try{return new G(q)}catch(z){console.warn(`[proxyFetch] Invalid proxy URL: ${q}`)}return}async function K(q,z={}){let{timeout:W=30000,signal:Q,...B}=z;if(Q?.aborted)throw new DOMException("The operation was aborted.","AbortError");let J=R(),X=new AbortController,Y=!1,F=setTimeout(()=>{Y=!0,X.abort()},W),w=()=>X.abort();Q?.addEventListener("abort",w);try{let Z={method:B.method,headers:B.headers,body:B.body,signal:X.signal,dispatcher:J};return await H(q.toString(),Z)}catch(Z){if(Z instanceof Error&&Z.name==="AbortError"){if(Y)throw Error(`Request timeout after ${W}ms`);throw Z}throw Z}finally{clearTimeout(F),Q?.removeEventListener("abort",w)}}var D="blade-code",f="https://cdn.jsdelivr.net/npm/blade-code@latest/CHANGELOG.md",M=$.join(process.env.HOME||process.env.USERPROFILE||".",".blade"),S=$.join(M,"version-cache.json"),k=3600000,L=`https://registry.npmjs.org/${D}/latest`;async function x(){try{if(process.env.BLADE_VERSION)return process.env.BLADE_VERSION;let q=N(import.meta.url),z=$.dirname(q),W=[$.join(z,"..","..","package.json"),$.join(z,"..","package.json")];for(let Q of W)try{let B=await j.readFile(Q,"utf-8"),J=JSON.parse(B);if(J.name===D&&J.version)return J.version}catch{}return"unknown"}catch{return"unknown"}}async function I(){try{let q=await j.readFile(S,"utf-8"),z=JSON.parse(q);if(Date.now()-z.checkedAt<k)return z;return{...z,checkedAt:0}}catch{return null}}async function O(q){try{await j.mkdir(M,{recursive:!0,mode:493}),await j.writeFile(S,JSON.stringify(q,null,2))}catch{}}async function P(){try{let q=await K(L,{timeout:5000,headers:{Accept:"application/json"}});if(!q.ok)return null;return(await q.json()).version||null}catch{return null}}async function v(q=!1){let z=await x(),W=f;if(z==="unknown")return{currentVersion:z,latestVersion:null,hasUpdate:!1,shouldPrompt:!1,releaseNotesUrl:W,error:"Unable to determine current version"};let Q=await I(),B=Q?.skipUntilVersion,J=null;if(!q&&Q&&Q.checkedAt>0)J=Q.latestVersion;else if(J=await P(),J)await O({latestVersion:J,checkedAt:Date.now(),skipUntilVersion:B});if(!J)return{currentVersion:z,latestVersion:null,hasUpdate:!1,shouldPrompt:!1,releaseNotesUrl:W,error:"Unable to check for updates"};let X=b.gt(J,z),Y=X;if(X&&B)Y=b.gt(J,B);return{currentVersion:z,latestVersion:J,hasUpdate:X,shouldPrompt:Y,releaseNotesUrl:W}}async function u(q){let z=await I();await O({latestVersion:z?.latestVersion||q,checkedAt:z?.checkedAt||Date.now(),skipUntilVersion:q})}function g(){return`npm install -g ${D}@latest --registry https://registry.npmjs.org`}async function C(){let{spawn:q}=await import("child_process");return new Promise((z)=>{let W=g(),Q=q(W,{stdio:"inherit",shell:!0});Q.on("close",(B)=>{if(B===0)z({success:!0,message:"Upgrade successful! Please restart blade."});else z({success:!1,message:`Upgrade failed (exit code: ${B})`})}),Q.on("error",(B)=>{z({success:!1,message:`Upgrade failed: ${B.message}`})})})}async function d(){try{let q=await v();return q.shouldPrompt?q:null}catch{return null}}
1
+ import{Hc as y}from"./chunk-ppyg431d.js";import*as j from"fs/promises";import*as $ from"path";import b from"semver";import{fileURLToPath as N}from"url";import{ProxyAgent as G,fetch as H}from"undici";function T(){return process.env.HTTPS_PROXY||process.env.HTTP_PROXY||process.env.https_proxy||process.env.http_proxy}function R(){let q=T();if(q)try{return new G(q)}catch(z){console.warn(`[proxyFetch] Invalid proxy URL: ${q}`)}return}async function K(q,z={}){let{timeout:W=30000,signal:Q,...B}=z;if(Q?.aborted)throw new DOMException("The operation was aborted.","AbortError");let J=R(),X=new AbortController,Y=!1,F=setTimeout(()=>{Y=!0,X.abort()},W),w=()=>X.abort();Q?.addEventListener("abort",w);try{let Z={method:B.method,headers:B.headers,body:B.body,signal:X.signal,dispatcher:J};return await H(q.toString(),Z)}catch(Z){if(Z instanceof Error&&Z.name==="AbortError"){if(Y)throw Error(`Request timeout after ${W}ms`);throw Z}throw Z}finally{clearTimeout(F),Q?.removeEventListener("abort",w)}}var D="blade-code",f="https://cdn.jsdelivr.net/npm/blade-code@latest/CHANGELOG.md",M=$.join(process.env.HOME||process.env.USERPROFILE||".",".blade"),S=$.join(M,"version-cache.json"),k=3600000,L=`https://registry.npmjs.org/${D}/latest`;async function x(){try{if(process.env.BLADE_VERSION)return process.env.BLADE_VERSION;let q=N(import.meta.url),z=$.dirname(q),W=[$.join(z,"..","..","package.json"),$.join(z,"..","package.json")];for(let Q of W)try{let B=await j.readFile(Q,"utf-8"),J=JSON.parse(B);if(J.name===D&&J.version)return J.version}catch{}return"unknown"}catch{return"unknown"}}async function I(){try{let q=await j.readFile(S,"utf-8"),z=JSON.parse(q);if(Date.now()-z.checkedAt<k)return z;return{...z,checkedAt:0}}catch{return null}}async function O(q){try{await j.mkdir(M,{recursive:!0,mode:493}),await j.writeFile(S,JSON.stringify(q,null,2))}catch{}}async function P(){try{let q=await K(L,{timeout:5000,headers:{Accept:"application/json"}});if(!q.ok)return null;return(await q.json()).version||null}catch{return null}}async function v(q=!1){let z=await x(),W=f;if(z==="unknown")return{currentVersion:z,latestVersion:null,hasUpdate:!1,shouldPrompt:!1,releaseNotesUrl:W,error:"Unable to determine current version"};let Q=await I(),B=Q?.skipUntilVersion,J=null;if(!q&&Q&&Q.checkedAt>0)J=Q.latestVersion;else if(J=await P(),J)await O({latestVersion:J,checkedAt:Date.now(),skipUntilVersion:B});if(!J)return{currentVersion:z,latestVersion:null,hasUpdate:!1,shouldPrompt:!1,releaseNotesUrl:W,error:"Unable to check for updates"};let X=b.gt(J,z),Y=X;if(X&&B)Y=b.gt(J,B);return{currentVersion:z,latestVersion:J,hasUpdate:X,shouldPrompt:Y,releaseNotesUrl:W}}async function u(q){let z=await I();await O({latestVersion:z?.latestVersion||q,checkedAt:z?.checkedAt||Date.now(),skipUntilVersion:q})}function g(){return`npm install -g ${D}@latest --registry https://registry.npmjs.org`}async function C(){let{spawn:q}=await import("child_process");return new Promise((z)=>{let W=g(),Q=q(W,{stdio:"inherit",shell:!0});Q.on("close",(B)=>{if(B===0)z({success:!0,message:"Upgrade successful! Please restart blade."});else z({success:!1,message:`Upgrade failed (exit code: ${B})`})}),Q.on("error",(B)=>{z({success:!1,message:`Upgrade failed: ${B.message}`})})})}async function d(){try{let q=await v();return q.shouldPrompt?q:null}catch{return null}}
2
2
  export{v as g,u as h,g as i,C as j,d as k};
@@ -0,0 +1,3 @@
1
+ import{Vb as w}from"./chunk-45bme7n9.js";import{$b as F,_b as xq,ac as j,bc as Cq,cc as e,ec as qq,hc as Eq,ic as wq}from"./chunk-enk621t7.js";import{mc as Mq}from"./chunk-936ft6kq.js";import{rc as Vq}from"./chunk-w3me85va.js";import{vc as Dq}from"./chunk-2fbwmdvg.js";import{Ac as R,Bc as x,Dc as s,Ec as E,Fc as v,xc as Fq,yc as P,zc as _q}from"./chunk-gdm1xzvp.js";import{readdir as Bq,readFile as g,rm as l,stat as aq}from"node:fs/promises";import*as O from"node:path";import{nanoid as T}from"nanoid";import{createHash as Iq,randomUUID as Pq}from"node:crypto";import*as A from"node:fs/promises";import*as u from"node:path";var Oq=1;function uq(q,J){let G=Iq("sha256").update(J).digest("hex");return u.join(P(q),".locks",`${G}.lock`)}function I(q,J){return q instanceof Error&&"code"in q&&q.code===J}async function r(q){try{let J=JSON.parse(await A.readFile(q,"utf8"));if(J.version!==Oq||typeof J.sessionId!=="string"||typeof J.ownerId!=="string"||!Number.isInteger(J.pid)||(J.pid??0)<=0||typeof J.acquiredAt!=="string")return;return J}catch{return}}async function Hq(q){let J=await r(q);if(J)return J;return await new Promise((G)=>setTimeout(G,10)),r(q)}function hq(q){try{return process.kill(q,0),!0}catch(J){return I(J,"EPERM")}}async function Qq(q,J){let G;try{return G=await A.open(q,"wx",384),await G.writeFile(`${JSON.stringify(J)}
2
+ `,"utf8"),!0}catch(X){if(I(X,"EEXIST"))return!1;if(G)await A.unlink(q).catch(()=>{return});throw X}finally{await G?.close().catch(()=>{return})}}class b extends Error{code="BLADE_SESSION_IN_USE";constructor(q){super(q?`Session is already active in another Blade process (PID ${q}). Stop that process or choose a different session.`:"Session is already active in another Blade process. Stop that process or choose a different session.");this.name="SessionInUseError"}}class y{filePath;record;released=!1;constructor(q,J){this.filePath=q;this.record=J}static async acquire(q,J=Vq()){let G=uq(J,q),X={version:Oq,sessionId:q,ownerId:Pq(),pid:process.pid,acquiredAt:new Date().toISOString()};if(await A.mkdir(u.dirname(G),{recursive:!0,mode:448}),await Qq(G,X))return new y(G,X);let $=await Hq(G);if($&&hq($.pid))throw new b($.pid);if(await A.unlink(G).catch((Y)=>{if(!I(Y,"ENOENT"))throw Y}),await Qq(G,X))return new y(G,X);throw new b((await Hq(G))?.pid)}async release(){if(this.released)return;if(this.released=!0,(await r(this.filePath))?.ownerId!==this.record.ownerId)return;await A.unlink(this.filePath).catch((J)=>{if(!I(J,"ENOENT"))throw J})}}import*as S from"node:crypto";import{promises as U}from"node:fs";import*as _ from"node:path";import a from"write-file-atomic";class h{sessionId;workspaceRoot;enableCheckpoints;maxSnapshots;snapshotDir;manifestPath;trackedFileBackups=new Map;snapshots=[];constructor(q){if(R(q.sessionId),this.sessionId=q.sessionId,q.workspaceRoot&&!_.isAbsolute(q.workspaceRoot))throw Error("Snapshot workspace root must be absolute");this.workspaceRoot=q.workspaceRoot?_.resolve(q.workspaceRoot):void 0,this.enableCheckpoints=q.enableCheckpoints??!0,this.maxSnapshots=q.maxSnapshots??10;let J=v();this.snapshotDir=_.join(J,"file-history",this.sessionId),this.manifestPath=_.join(this.snapshotDir,"manifest.json")}async initialize(){if(!this.enableCheckpoints)return;if(this.workspaceRoot)await this.selectWorkspaceSnapshotDir();await U.mkdir(this.snapshotDir,{recursive:!0,mode:493}),await this.loadManifest()}async selectWorkspaceSnapshotDir(){let q=v(),J=await U.realpath(this.workspaceRoot).catch(()=>this.workspaceRoot),G=S.createHash("sha256").update(J).digest("hex").slice(0,24),X=_.join(q,"file-history",this.sessionId),$=_.join(q,"file-history","workspaces",G,this.sessionId),Y=_.join($,"manifest.json");try{await U.access(Y)}catch{await this.migrateLegacySnapshotDir(X,$,J)}this.snapshotDir=$,this.manifestPath=Y}async migrateLegacySnapshotDir(q,J,G){let X;try{X=JSON.parse(await U.readFile(_.join(q,"manifest.json"),"utf8"))}catch{return}if(X.schemaVersion!==1||!Array.isArray(X.snapshots)||!X.snapshots.every(($)=>this.isWithinWorkspace($.filePath,G)))return;await U.mkdir(_.dirname(J),{recursive:!0,mode:493});try{await U.rename(q,J)}catch($){let Y=$.code;if(Y!=="ENOENT"&&Y!=="EEXIST"&&Y!=="ENOTEMPTY")throw $}}isWithinWorkspace(q,J){if(!_.isAbsolute(q))return!1;let G=_.relative(J,_.resolve(q));return G===""||G!==".."&&!G.startsWith(`..${_.sep}`)&&!_.isAbsolute(G)}async createSnapshot(q,J){if(!this.enableCheckpoints)return{backupFileName:"",version:0,backupTime:new Date};let G=await this.resolveFileIdentity(q),X=!0;try{await U.access(G)}catch{X=!1}let $=this.trackedFileBackups.get(G),Y=$?$.version+1:1,H=this.generateFileHash(G,Y),K=this.getSnapshotPath(H,Y),Z=new Date;if(X){let V=await U.readFile(G);await U.writeFile(K,V)}let Q={backupFileName:H,version:Y,backupTime:Z};return this.trackedFileBackups.set(G,Q),this.snapshots.push({messageId:J,backupFileName:H,timestamp:Z,filePath:G,version:Y,existedBefore:X}),await this.cleanupOldSnapshots(G),await this.persistManifest(),Q}async recordPostEditState(q,J){if(!this.enableCheckpoints||!J.backupFileName)return;let G=await this.resolveFileIdentity(q),X=this.snapshots.find(($)=>$.filePath===G&&$.backupFileName===J.backupFileName&&$.version===J.version);if(!X)throw Error(`未找到待完成的快照: ${G}`);X.postEditHash=await this.hashFile(G),await this.persistManifest()}async discardSnapshot(q,J){if(!this.enableCheckpoints||!J.backupFileName)return;let G=await this.resolveFileIdentity(q),X=this.snapshots.find(($)=>$.filePath===G&&$.backupFileName===J.backupFileName&&$.version===J.version);if(!X)return;this.removeSnapshot(X),await U.rm(this.getSnapshotPath(X.backupFileName,X.version),{force:!0}),await this.persistManifest()}async rewindLatest(q){let J=await this.resolveFileIdentity(q),G=this.snapshots.slice().reverse().find((Y)=>Y.filePath===J&&Y.postEditHash!==void 0);if(!G?.postEditHash)throw Error(`未找到可回退快照: ${J}`);if(await this.hashFile(J)!==G.postEditHash)throw Error(`文件在 Blade 编辑后已被修改,拒绝覆盖: ${J}`);let $=this.getSnapshotPath(G.backupFileName,G.version);if(G.existedBefore){let Y=await U.readFile($);await U.writeFile(J,Y)}else await U.unlink(J);return this.removeSnapshot(G),await U.rm($,{force:!0}),await this.persistManifest(),G}async restoreSnapshot(q,J){let G=await this.resolveFileIdentity(q),X=this.snapshots.slice().reverse().find((H)=>H.messageId===J&&H.filePath===G);if(!X)throw Error(`未找到快照: messageId=${J}, filePath=${G}`);let $=this.getSnapshotPath(X.backupFileName,X.version),Y=await U.readFile($);await U.writeFile(G,Y)}async listSnapshots(q){let J=await this.resolveFileIdentity(q);return this.snapshots.filter((G)=>G.filePath===J)}async listAllSnapshots(){return this.snapshots.filter((q)=>q.postEditHash!==void 0)}async previewRewind(q){let J=this.buildRewindPlan(q);return{files:J.map((G)=>G.filePath),snapshotCount:J.reduce((G,X)=>G+X.selected.length,0)}}async rewindSnapshots(q){let J=this.buildRewindPlan(q);if(J.length===0)return{files:[],snapshotCount:0};let G=new Map;for(let $ of J){let Y;try{Y=await U.readFile($.filePath)}catch(K){if(K.code!=="ENOENT")throw K;throw Error(`文件在 Blade 编辑后已被修改,拒绝覆盖: ${$.filePath}`,{cause:K})}if(S.createHash("sha256").update(Y).digest("hex")!==$.latest.postEditHash)throw Error(`文件在 Blade 编辑后已被修改,拒绝覆盖: ${$.filePath}`);if(G.set($.filePath,{existed:!0,content:Y}),$.target.existedBefore)await U.access(this.getSnapshotPath($.target.backupFileName,$.target.version))}let X=[...this.snapshots];try{for(let Y of J)if(Y.target.existedBefore){let H=await U.readFile(this.getSnapshotPath(Y.target.backupFileName,Y.target.version));await U.mkdir(_.dirname(Y.filePath),{recursive:!0}),await a(Y.filePath,H)}else await U.rm(Y.filePath,{force:!0});let $=new Set(J.flatMap((Y)=>Y.selected));this.snapshots=this.snapshots.filter((Y)=>!$.has(Y)),this.rebuildTrackedFileBackups(),await this.persistManifest(),await Promise.all([...$].map((Y)=>U.rm(this.getSnapshotPath(Y.backupFileName,Y.version),{force:!0}).catch(()=>{return})))}catch($){this.snapshots=X,this.rebuildTrackedFileBackups();let Y=[];for(let[H,K]of G)try{if(K.existed&&K.content)await a(H,K.content);else await U.rm(H,{force:!0})}catch(Z){Y.push(Z)}if(Y.length>0)throw AggregateError([$,...Y],"快照回退失败且无法完整恢复回退前状态");throw $}return{files:J.map(($)=>$.filePath),snapshotCount:J.reduce(($,Y)=>$+Y.selected.length,0)}}async commitSnapshots(q){let J=this.buildRewindPlan(q),G=new Set(J.flatMap(($)=>$.selected));if(G.size===0)return{files:[],snapshotCount:0};let X=[...this.snapshots];this.snapshots=this.snapshots.filter(($)=>!G.has($)),this.rebuildTrackedFileBackups();try{await this.persistManifest()}catch($){throw this.snapshots=X,this.rebuildTrackedFileBackups(),$}return await Promise.all([...G].map(($)=>U.rm(this.getSnapshotPath($.backupFileName,$.version),{force:!0}).catch(()=>{return}))),{files:J.map(($)=>$.filePath),snapshotCount:G.size}}buildRewindPlan(q){let J=new Set(q),G=this.snapshots.filter((Y)=>Y.postEditHash!==void 0),X=G.filter((Y)=>J.has(Y.messageId));return[...new Set(X.map((Y)=>Y.filePath))].sort().map((Y)=>{let H=G.filter((V)=>V.filePath===Y),K=H.filter((V)=>J.has(V.messageId)),Z=H.indexOf(K[0]),Q=H.slice(Z);if(Q.length!==K.length||Q.some((V)=>!J.has(V.messageId)))throw Error(`请求的快照不是文件历史的连续后缀: ${Y}`);return{filePath:Y,selected:K,target:K[0],latest:K.at(-1)}})}async loadManifest(){try{let q=await U.readFile(this.manifestPath,"utf-8"),J=JSON.parse(q);if(J.schemaVersion!==1||!Array.isArray(J.snapshots))throw Error("Unsupported snapshot manifest");this.snapshots=await Promise.all(J.snapshots.map(async(G)=>({...G,filePath:await this.resolveFileIdentity(G.filePath),timestamp:new Date(G.timestamp)}))),this.rebuildTrackedFileBackups()}catch(q){if(q.code!=="ENOENT")throw q;this.snapshots=[],this.trackedFileBackups.clear()}}async persistManifest(){if(this.snapshots.length===0){await U.rm(this.manifestPath,{force:!0});return}let q={schemaVersion:1,snapshots:this.snapshots.map((J)=>({...J,timestamp:J.timestamp.toISOString()}))};await a(this.manifestPath,JSON.stringify(q,null,2),{encoding:"utf-8",mode:384})}async cleanupOldSnapshots(q){let G=this.snapshots.filter((X)=>X.filePath===q).slice(0,-this.maxSnapshots);for(let X of G)await U.rm(this.getSnapshotPath(X.backupFileName,X.version),{force:!0}),this.removeSnapshot(X)}async cleanup(q=0){let J=this.snapshots.slice().sort((X,$)=>$.timestamp.getTime()-X.timestamp.getTime()),G=new Set(J.slice(0,q));for(let X of this.snapshots)if(!G.has(X))await U.rm(this.getSnapshotPath(X.backupFileName,X.version),{force:!0});this.snapshots=J.slice(0,q).reverse(),this.rebuildTrackedFileBackups(),await this.persistManifest()}getSnapshotPath(q,J){return _.join(this.snapshotDir,`${q}@v${J}`)}async resolveFileIdentity(q){let J=_.resolve(q),G=[],X=J;while(!0){try{let Y=await U.realpath(X);return _.join(Y,...G.reverse())}catch(Y){let H=Y.code;if(H!=="ENOENT"&&H!=="ENOTDIR")throw Y}let $=_.dirname(X);if($===X)return J;G.push(_.basename(X)),X=$}}async hashFile(q){let J=await U.readFile(q);return S.createHash("sha256").update(J).digest("hex")}removeSnapshot(q){let J=this.snapshots.indexOf(q);if(J>=0)this.snapshots.splice(J,1);this.rebuildTrackedFileBackups()}rebuildTrackedFileBackups(){this.trackedFileBackups.clear();for(let q of this.snapshots){let J=this.trackedFileBackups.get(q.filePath);if(!J||J.version<q.version)this.trackedFileBackups.set(q.filePath,{backupFileName:q.backupFileName,version:q.version,backupTime:q.timestamp})}}generateFileHash(q,J){let G=S.createHash("md5");return G.update(`${q}:${J}`),G.digest("hex").substring(0,16)}getSnapshotDir(){return this.snapshotDir}getSessionId(){return this.sessionId}getTrackedFileCount(){return this.trackedFileBackups.size}getSnapshotCount(){return this.snapshots.length}}import*as M from"node:path";var cq=50,lq=100,pq=/^[A-Za-z0-9_-]+$/,dq=/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d{1,9})?(?:Z|[+-]\d{2}:\d{2})$/;function nq(q){return typeof q==="string"&&dq.test(q)&&Number.isFinite(Date.parse(q))}function Uq(q){return typeof q==="string"&&M.isAbsolute(q)}function iq(q){return Buffer.from(JSON.stringify(q),"utf8").toString("base64url")}function rq(q){try{if(!pq.test(q))throw Error("invalid");let J=Buffer.from(q,"base64url").toString("utf8");if(Buffer.from(J,"utf8").toString("base64url")!==q)throw Error("invalid");let G=JSON.parse(J);if(G.version!==1||typeof G.includeSubagents!=="boolean"||!(G.cwd===null||Uq(G.cwd))||!nq(G.lastMessageTime)||!Uq(G.projectPath)||!_q(G.sessionId))throw Error("invalid");return{version:1,cwd:G.cwd===null?null:M.resolve(G.cwd),includeSubagents:G.includeSubagents,lastMessageTime:G.lastMessageTime,projectPath:M.resolve(G.projectPath),sessionId:G.sessionId}}catch{throw Error("Invalid session cursor")}}function o(q={}){let{cwd:J,cursor:G,limit:X,includeSubagents:$=!1}=q;if(J!==void 0&&!M.isAbsolute(J))throw Error("Session catalog cwd must be absolute");let Y=X===void 0?cq:X;if(!Number.isInteger(Y)||Y<1||Y>lq)throw Error("Session catalog limit must be an integer from 1 to 100");return{cwd:J===void 0?null:M.resolve(J),cursor:G??void 0,limit:Y,includeSubagents:$}}function c(q,J){if(q.lastMessageTime>J.lastMessageTime)return-1;if(q.lastMessageTime<J.lastMessageTime)return 1;if(q.projectPath<J.projectPath)return-1;if(q.projectPath>J.projectPath)return 1;if(q.sessionId<J.sessionId)return-1;if(q.sessionId>J.sessionId)return 1;return 0}function Wq(q,J){let G=[...q];if(J.cursor){let Y=rq(J.cursor);if(Y.cwd!==J.cwd||Y.includeSubagents!==J.includeSubagents)throw Error("Session cursor scope does not match this query");G=G.filter((H)=>c(H,{sessionId:Y.sessionId,projectPath:Y.projectPath,lastMessageTime:Y.lastMessageTime})>0)}let X=G.slice(0,J.limit);if(X.length===0||G.length<=X.length)return{sessions:X};let $=X[X.length-1];return{sessions:X,nextCursor:iq({version:1,cwd:J.cwd,includeSubagents:J.includeSubagents,lastMessageTime:$.lastMessageTime,projectPath:$.projectPath,sessionId:$.sessionId})}}var t=Dq("Service"),zq=new Set(["queued","running","completed","failed","cancelled","interrupted"]),Rq=new Set(["local","worktree"]);class Gq extends Error{}function Nq(q){try{return process.kill(q,0),!0}catch(J){return J instanceof Error&&"code"in J&&J.code==="EPERM"}}function Lq(q){if(!q||typeof q!=="object"||Array.isArray(q))return;let J=q;if(["sessionId","name","branch","baseCommit","originalBranch","repositoryRoot","originalWorkspaceRoot","worktreeRoot","workspaceRoot"].some((X)=>typeof J[X]!=="string"||!J[X])||typeof J.sourceHadChanges!=="boolean")return;return J}function Aq(q){if(!q||typeof q!=="object"||Array.isArray(q))return;let J=q;if(["changedFiles","additions","deletions","commits"].some((X)=>typeof J[X]!=="number"||!Number.isInteger(J[X])||J[X]<0))return;return J}var kq={stat(q){return aq(q,{bigint:!0})},readFile(q){return g(q,"utf-8")}},f=kq;function jG(q){f=q}function gG(){f=kq}class bq extends Error{constructor(q){super(`Session has no durable creation record: ${q}`);this.name="SessionMissingCreationError"}}class W{static toUISafeMessages(q){let J=Date.now(),G=q.length,X=[];return q.forEach(($,Y)=>{if($.role!=="user"&&$.role!=="assistant")return;let H;if(typeof $.content==="string")H=$.content;else if(Array.isArray($.content))H=$.content.map((Q)=>Q.type==="text"?Q.text:"[Image]").join("");else H="";let K=H.trim();if(!K)return;let Z=X[X.length-1];if(Z&&Z.role===$.role&&Z.content===K)return;X.push({id:`restored-${J}-${Y}`,role:$.role,content:K,timestamp:J-(G-Y)*1000,metadata:$.metadata&&typeof $.metadata==="object"?$.metadata:void 0})}),X}static async listSessionPage(q={}){let J=o(q),X=(await this.scanStoredSessions(J.cwd??void 0,J.includeSubagents)).sort(c),$=Wq(X,J);return{sessions:$.sessions.map((Y)=>this.toPublicMetadata(Y)),nextCursor:$.nextCursor}}static async listSessions(q={}){let J=o(q),G=await this.scanStoredSessions(J.cwd??void 0,J.includeSubagents),X=new Set;return G.sort(c).flatMap(($)=>{let Y=`${$.projectPath}\x00${$.sessionId}`;if(X.has(Y))return[];return X.add(Y),[this.toPublicMetadata($)]})}static async findSessionMetadata(q,J){if(R(q),J!==void 0){if(!O.isAbsolute(J))throw Error("Session catalog cwd must be absolute");let X=O.resolve(J),$=this.getSessionFilePath(X,q);try{let Y=await this.readStoredSessionMetadata($,q,X);if(Y.projectPath!==X)return;return this.toPublicMetadata(Y)}catch(Y){if(Y.code==="ENOENT")return;throw Y}}let G=(await this.scanStoredSessions(void 0,!0)).filter((X)=>X.sessionId===q);if(G.length===0)return;if(G.length>1)throw Error(`Ambiguous session ID: ${q}`);return this.toPublicMetadata(G[0])}static async loadSession(q,J){try{if(J){if(!O.isAbsolute(J))throw Error("Session catalog cwd must be absolute");let X=O.resolve(J),$=this.getSessionFilePath(X,q);try{return await this.loadSessionFromFile($,q,X)}catch(Y){if(Y.code==="ENOENT")throw Error(`未找到会话: ${q}`);throw Y}}let G=(await this.scanStoredSessions(void 0,!0)).find((X)=>X.sessionId===q);if(!G)throw Error(`未找到会话: ${q}`);return await this.loadSessionFromFile(G.filePath,q)}catch(G){throw t.error(`[SessionService] 加载会话失败 (${q}):`,G),G}}static async listRewindCheckpoints(q,J){R(q);let G=this.resolveCatalogWorkspace(J),X=x(G,q),$=await this.readStableSessionSnapshot(X,q);this.validateSessionWorkspace($,q,G);let Y=new h({sessionId:q,workspaceRoot:G});await Y.initialize();let H=Cq($),K=[];for(let Z of H){let Q=e($,Z.messageId),V=await Y.previewRewind(Q.snapshotMessageIds);K.push({...Z,fileCount:V.files.length})}return K}static async rewindSession(q,J,G){R(q);let X=this.resolveCatalogWorkspace(J),$=x(X,q),Y=new F($),H;try{await Y.appendValidatedAsync(async(K)=>{this.validateSessionWorkspace(K,q,X);let Z=e(K,G.targetMessageId),Q=new h({sessionId:q,workspaceRoot:X});await Q.initialize();let V=await Q.previewRewind(Z.snapshotMessageIds),B=G.mode==="conversation"?await Q.commitSnapshots(Z.snapshotMessageIds):await Q.rewindSnapshots(Z.snapshotMessageIds),N=new Date().toISOString(),C={id:T(),sessionId:q,timestamp:N,type:"session_rewound",cwd:X,gitBranch:E(X),version:w(),data:{rewindId:T(),targetMessageId:G.targetMessageId,mode:G.mode,restoredFiles:G.mode==="conversation"?[]:B.files,createdAt:N}},D=j([...K,C]);return H={checkpoint:{...Z.checkpoint,fileCount:V.files.length},mode:G.mode,removedTurns:Z.removedTurns,restoredFiles:C.data.restoredFiles,messages:this.convertJSONLToMessages(D)},C})}catch(K){throw this.sanitizeStoredSessionError(K,q)}if(!H)throw Error(`Session rewind did not produce a result: ${q}`);for(let K of H.restoredFiles)Mq.getInstance().clearFileRecord(K);return H}static async forkSession(q,J){R(q);let G=J.newSessionId??`fork-${Date.now()}-${T(8)}`;R(G);let X=this.resolveForkWorkspace(J.sourceProjectPath),$=this.resolveForkWorkspace(J.targetProjectPath);if(X!==$)throw Error("Session forks must stay in the source workspace");let Y=x(X,q),H=await this.readStableSessionSnapshot(Y,q),K=this.getSessionCreatedEntry(H,q);if(K.data.sessionId!==q)throw Error("Fork source session_created.data.sessionId must match the requested session ID");if(!O.isAbsolute(K.cwd)||O.resolve(K.cwd)!==X)throw Error("Fork source session_created.cwd must resolve to the requested source workspace");let Z=j(H),Q=new Date().toISOString(),V=K.data.rootId||q,B=E($),N=w(),{status:C,taskStatus:D,taskStatusReason:p,taskStartedAt:m,taskCompletedAt:k,taskOwnerPid:Jq,taskPromptSummary:Xq,taskIsolation:Yq,taskSourceProjectPath:$q,taskWorktree:L,taskDiffStat:d,taskQueuePosition:oq,taskQueueDepth:tq,taskConcurrencyLimit:sq,...yq}=K.data,Sq={id:T(),sessionId:G,timestamp:Q,type:"session_created",cwd:$,gitBranch:B,version:N,data:{...yq,sessionId:G,rootId:V,parentId:q,relationType:"fork",taskStatus:"completed",taskCompletedAt:Q,taskIsolation:"local",taskSourceProjectPath:$,createdAt:Q,updatedAt:Q}},vq=Z.filter((z)=>z.type!=="session_created"&&z.type!=="inbox_acknowledged").map((z)=>{let i={...z,id:T(),sessionId:G,cwd:$,gitBranch:B,version:N};if(z.type==="session_updated"){let{status:fq,taskStatus:Zq,taskStatusReason:eq,taskStartedAt:qG,taskCompletedAt:GG,taskOwnerPid:JG,taskPromptSummary:XG,taskIsolation:YG,taskSourceProjectPath:$G,taskWorktree:KG,taskDiffStat:ZG,taskQueuePosition:HG,taskQueueDepth:QG,taskConcurrencyLimit:VG,...mq}=z.data;return{...i,type:"session_updated",data:{...mq,sessionId:G,rootId:V,parentId:q,relationType:"fork"}}}if(z.type==="message_created"){let{inboxMessageId:fq,...Zq}=z.data;return{...i,type:"message_created",data:Zq}}return i}),jq={id:T(),sessionId:G,timestamp:Q,type:"session_updated",cwd:$,gitBranch:B,version:N,data:{sessionId:G,rootId:V,parentId:q,relationType:"fork",taskStatus:"completed",taskStatusReason:null,taskStartedAt:null,taskCompletedAt:Q,taskOwnerPid:null,taskIsolation:"local",taskSourceProjectPath:$,taskWorktree:null,taskDiffStat:null,taskQueuePosition:null,taskQueueDepth:null,taskConcurrencyLimit:null,updatedAt:Q}},n=[Sq,...vq,jq],Kq=x($,G);try{await new F(Kq).createExclusive(n)}catch(z){if(z.code==="EEXIST")throw Error(`Fork session already exists: ${G}`,{cause:z});throw z}let gq=this.projectMetadataFromEntries(n,G,$,Kq);return{sessionId:G,parentSessionId:q,projectPath:$,messages:this.convertJSONLToMessages(n),metadata:this.toPublicMetadata(gq)}}static async deleteSession(q,J){if(R(q),J){if(!O.isAbsolute(J))throw Error("Session catalog cwd must be absolute");let X=O.resolve(J),$=this.getSessionFilePath(X,q),Y=new F($),H;try{H=await Y.deleteValidated((K)=>{return this.projectMetadataFromEntries(K,q,X,$).projectPath===X})}catch(K){if(!this.isCorruptSessionJSONLError(K))throw K;H=await Y.delete()}if(!H)return 0;return await l(O.join(O.dirname($),`${q}.inbox.json`),{force:!0}),await l(s(X,q),{force:!0}),await this.removeFromProjection(q,X),1}let G=(await this.scanStoredSessions(void 0,!0)).filter((X)=>X.sessionId===q);if(G.length===0)return 0;return await Promise.all(G.map(async(X)=>{await new F(X.filePath).delete(),await l(O.join(O.dirname(X.filePath),`${X.sessionId}.inbox.json`),{force:!0}),await l(s(X.projectPath,X.sessionId),{force:!0}),await this.removeFromProjection(X.sessionId,X.projectPath)})),G.length}static async removeFromProjection(q,J){try{let G=await qq();if(G)wq(G,q,J)}catch{}}static validateTaskMetadataUpdate(q,J){if(q.taskPromptSummary!==void 0&&q.taskPromptSummary!==null&&(!q.taskPromptSummary.trim()||q.taskPromptSummary.length>1000))throw Error("Session task prompt summary must contain 1-1000 characters");if(q.taskIsolation!==void 0&&q.taskIsolation!==null&&!Rq.has(q.taskIsolation))throw Error(`Invalid session task isolation: ${String(q.taskIsolation)}`);if(q.taskSourceProjectPath!==void 0&&q.taskSourceProjectPath!==null&&!O.isAbsolute(q.taskSourceProjectPath))throw Error("Session task source project path must be absolute");if(q.taskWorktree!==void 0&&q.taskWorktree!==null){let G=Lq(q.taskWorktree);if(!G||G.sessionId!==J||![G.repositoryRoot,G.originalWorkspaceRoot,G.worktreeRoot,G.workspaceRoot].every((X)=>O.isAbsolute(X)))throw Error("Invalid session task worktree metadata")}if(q.taskDiffStat!==void 0&&q.taskDiffStat!==null&&!Aq(q.taskDiffStat))throw Error("Invalid session task diff stat");if(q.taskQueuePosition!==void 0&&q.taskQueuePosition!==null&&(!Number.isInteger(q.taskQueuePosition)||q.taskQueuePosition<1))throw Error("Invalid session task queue position");if(q.taskQueueDepth!==void 0&&q.taskQueueDepth!==null&&(!Number.isInteger(q.taskQueueDepth)||q.taskQueueDepth<0))throw Error("Invalid session task queue depth");if(q.taskConcurrencyLimit!==void 0&&q.taskConcurrencyLimit!==null&&(!Number.isInteger(q.taskConcurrencyLimit)||q.taskConcurrencyLimit<1))throw Error("Invalid session task concurrency limit");if(typeof q.taskQueuePosition==="number"&&typeof q.taskQueueDepth==="number"&&q.taskQueuePosition>q.taskQueueDepth)throw Error("Session task queue position exceeds queue depth")}static async createSessionMetadata(q,J,G={}){R(q),W.validateTaskMetadataUpdate(G,q);let X=W.resolveCatalogWorkspace(J);if(G.taskWorktree&&O.resolve(G.taskWorktree.workspaceRoot)!==X)throw Error("Session task worktree must match the catalog workspace");let $=new Date().toISOString(),Y={id:T(),sessionId:q,timestamp:$,type:"session_created",cwd:X,gitBranch:E(X),version:w(),data:{sessionId:q,rootId:q,...G.title!==void 0?{title:G.title}:{},taskStatus:"queued",...G.taskPromptSummary!==void 0?{taskPromptSummary:G.taskPromptSummary}:{},...G.taskIsolation!==void 0?{taskIsolation:G.taskIsolation}:{},...G.taskSourceProjectPath!==void 0?{taskSourceProjectPath:G.taskSourceProjectPath}:{},...G.taskWorktree!==void 0?{taskWorktree:G.taskWorktree}:{},createdAt:$,updatedAt:$}},H=W.getSessionFilePath(X,q);return await new F(H).createExclusive([Y]),W.toPublicMetadata(W.projectMetadataFromEntries([Y],q,X,H))}static async updateSessionMetadata(q,J,G){if(R(q),W.validateTaskMetadataUpdate(G,q),G.taskStatus!==void 0&&!zq.has(G.taskStatus))throw Error(`Invalid session task status: ${String(G.taskStatus)}`);if(G.taskOwnerPid!==void 0&&G.taskOwnerPid!==null&&(!Number.isInteger(G.taskOwnerPid)||G.taskOwnerPid<=0))throw Error("Session task owner PID must be a positive integer");let X=W.resolveCatalogWorkspace(J);if(G.taskWorktree&&O.resolve(G.taskWorktree.workspaceRoot)!==X)throw Error("Session task worktree must match the catalog workspace");let $=W.getSessionFilePath(X,q),Y=new F($),H=[];try{await Y.appendValidated((K)=>{let Z=W.getSessionCreatedEntry(K,q);if(Z.data.sessionId!==q)throw Error(`Session metadata creation record sessionId mismatch: ${q}`);if(!O.isAbsolute(Z.cwd)||O.resolve(Z.cwd)!==X)throw Error(`Session metadata creation record cwd mismatch: ${q}`);let Q=new Date().toISOString(),V={id:T(),sessionId:q,timestamp:Q,type:"session_updated",cwd:X,gitBranch:E(X),version:w(),data:{sessionId:q,...G.title!==void 0?{title:G.title}:{},...G.taskStatus!==void 0?{taskStatus:G.taskStatus}:{},...G.taskStatusReason!==void 0?{taskStatusReason:G.taskStatusReason}:{},...G.taskStartedAt!==void 0?{taskStartedAt:G.taskStartedAt}:{},...G.taskCompletedAt!==void 0?{taskCompletedAt:G.taskCompletedAt}:{},...G.taskOwnerPid!==void 0?{taskOwnerPid:G.taskOwnerPid}:{},...G.taskPromptSummary!==void 0?{taskPromptSummary:G.taskPromptSummary}:{},...G.taskIsolation!==void 0?{taskIsolation:G.taskIsolation}:{},...G.taskSourceProjectPath!==void 0?{taskSourceProjectPath:G.taskSourceProjectPath}:{},...G.taskWorktree!==void 0?{taskWorktree:G.taskWorktree}:{},...G.taskDiffStat!==void 0?{taskDiffStat:G.taskDiffStat}:{},...G.taskQueuePosition!==void 0?{taskQueuePosition:G.taskQueuePosition}:{},...G.taskQueueDepth!==void 0?{taskQueueDepth:G.taskQueueDepth}:{},...G.taskConcurrencyLimit!==void 0?{taskConcurrencyLimit:G.taskConcurrencyLimit}:{},updatedAt:Q}};return H=[...K,V],V})}catch(K){throw W.sanitizeStoredSessionError(K,q)}return W.toPublicMetadata(W.projectMetadataFromEntries(H,q,X,$))}static async findSessionTaskWorktree(q,J){R(q);let G=W.resolveCatalogWorkspace(J),X=W.getSessionFilePath(G,q);try{return(await W.readStoredSessionMetadata(X,q,G)).taskWorktree}catch($){if($.code==="ENOENT")return;throw W.sanitizeStoredSessionError($,q)}}static async loadSessionFromFile(q,J,G){let X=await g(q,"utf-8"),$=this.parseStoredSession(X,J);if(G!==void 0){if(this.projectMetadataFromEntries($,J,G,q).projectPath!==G)throw Error(`未找到会话: ${J}`)}return this.convertJSONLToMessages($)}static convertJSONLToMessages(q){let J=[],G=new Map,X=new Map,$=new Map,Y=new Map,H=new Map;for(let K of j(q)){if(K.type==="message_created"){let Z=K.data.role==="assistant"&&K.data.parentMessageId?$.get(K.data.parentMessageId):void 0,Q=Z??{role:K.data.role,content:"",...K.data.inboxMessageId?{metadata:{inboxMessageId:K.data.inboxMessageId}}:{}};if(G.set(K.data.messageId,Q),X.set(K.data.messageId,[]),!Z)J.push(Q)}if(K.type==="part_created"){if(K.data.partType==="text"){let Z=G.get(K.data.messageId);if(Z){let Q=K.data.payload,V=X.get(K.data.messageId);if(V)V.push({type:"text",text:Q.text??""}),Z.content=Tq(V);else Z.content=Q.text??""}}if(K.data.partType==="image"){let Z=G.get(K.data.messageId);if(Z){let Q=K.data.payload,V=X.get(K.data.messageId);if(V&&Q.dataUrl)V.push({type:"image_url",image_url:{url:Q.dataUrl}}),Z.content=Tq(V)}}if(K.data.partType==="tool_call"){let Z=G.get(K.data.messageId);if(Z?.role!=="assistant"){if(Z=$.get(K.data.messageId),!Z)Z={role:"assistant",content:"",tool_calls:[]},$.set(K.data.messageId,Z),J.push(Z)}if(Z.role==="assistant"){let Q=K.data.payload,V=Q.toolCallId??K.data.partId;Y.set(K.data.partId,V),H.set(V,Z),Z.tool_calls??=[],Z.tool_calls.push({id:V,type:"function",function:{name:Q.toolName??"unknown",arguments:JSON.stringify(Q.input??{})}})}}if(K.data.partType==="tool_result"){let Z=K.data.payload,Q=typeof Z.error==="string"?`Error: ${Z.error}`:typeof Z.output==="string"?Z.output:JSON.stringify(Z.output??""),V=Z;J.push({role:"tool",content:Q,tool_call_id:Y.get(K.data.messageId)??Z.toolCallId,name:Z.toolName,metadata:V})}if(K.data.partType==="summary"){let Z=K.data.payload,Q=K.data.payload;J.push({role:"system",content:Z.text??"",metadata:Q})}if(K.data.partType==="subtask_ref"){let Z=G.get(K.data.messageId)??H.get(K.data.messageId);if(Z){let Q=K.data.payload,V=Z.metadata??{};Z.metadata={...V,subtaskRef:Q}}}}}return J}static projectionDeriver(){return(q,J,G)=>{try{let X=x(G,J);return this.projectMetadataFromEntries(q,J,G,X)}catch{return null}}}static projectionDeriverForSearch(){return this.projectionDeriver()}static async scanStoredSessionsFromProjection(q,J){try{let G=await qq();if(!G)return null;await Eq(G,this.projectionDeriver());let X=q?G.prepare("SELECT metadata_json, is_subagent FROM sessions WHERE project_path=?").all(q):G.prepare("SELECT metadata_json, is_subagent FROM sessions").all(),$=[];for(let Y of X){if(!J&&Y.is_subagent===1)continue;try{let H=JSON.parse(Y.metadata_json);if(q!==void 0&&H.projectPath!==q)continue;$.push(H)}catch{}}return $}catch{return null}}static async scanStoredSessions(q,J=!1){let G=q?O.resolve(q):void 0,X=await this.scanStoredSessionsFromProjection(G,J);if(X)return X;let $=G?[{storagePath:P(G),projectPath:G}]:await this.listAllProjectStorageDirectories(),Y=[];for(let H of $){let K;try{K=await Bq(H.storagePath)}catch(Z){if(Z.code==="ENOENT")continue;throw Z}for(let Z of K){if(!Z.endsWith(".jsonl"))continue;let Q=Z.slice(0,-6),V=O.join(H.storagePath,Z);try{let B=await this.readStoredSessionMetadata(V,Q,H.projectPath);if(G!==void 0&&B.projectPath!==G){t.warn(`[SessionService] Skipping out-of-scope session transcript: ${Q}`);continue}if(!J&&B.relationType==="subagent")continue;Y.push(B)}catch(B){let N=B.code;if(N==="ENOENT")continue;if(N)throw B;t.warn(`[SessionService] Skipping invalid session transcript: ${Q}`)}}}return Y}static async listAllProjectStorageDirectories(){let q=O.join(v(),"projects"),J;try{J=await Bq(q,{withFileTypes:!0,encoding:"utf8"})}catch(G){if(G.code==="ENOENT")return[];throw G}return J.filter((G)=>G.isDirectory()).map((G)=>({storagePath:O.join(q,G.name),projectPath:Fq(G.name)}))}static async readStoredSessionMetadata(q,J,G){let X=await g(q,"utf-8"),$=this.parseStoredSession(X,J);return this.reconcileInterruptedTask(this.projectMetadataFromEntries($,J,G,q))}static async reconcileInterruptedTask(q){let J=q.taskOwnerPid;if(q.taskStatus!=="running"||J===void 0||Nq(J))return q;let G;try{G=await y.acquire(q.sessionId,q.projectPath)}catch(Y){if(!(Y instanceof b))throw Y;let H=await g(q.filePath,"utf-8");return this.projectMetadataFromEntries(this.parseStoredSession(H,q.sessionId),q.sessionId,q.projectPath,q.filePath)}let X=new F(q.filePath),$;try{try{await X.appendValidated((Y)=>{let H=this.projectMetadataFromEntries(Y,q.sessionId,q.projectPath,q.filePath);if(H.taskStatus!=="running"||H.taskOwnerPid!==J||Nq(J))throw new Gq;let K=new Date().toISOString(),Z={id:T(),sessionId:q.sessionId,timestamp:K,type:"session_updated",cwd:q.projectPath,gitBranch:E(q.projectPath),version:w(),data:{sessionId:q.sessionId,taskStatus:"interrupted",taskStatusReason:"Task owner process exited before completion",taskCompletedAt:K,taskOwnerPid:null,taskQueuePosition:null,taskQueueDepth:null,updatedAt:K}};return $=[...Y,Z],Z})}catch(Y){if(!(Y instanceof Gq))throw Y}if(!$){let Y=await g(q.filePath,"utf-8");$=this.parseStoredSession(Y,q.sessionId)}return this.projectMetadataFromEntries($,q.sessionId,q.projectPath,q.filePath)}finally{await G.release()}}static projectMetadataFromEntries(q,J,G,X){if(q.length===0)throw Error(`Empty session transcript: ${J}`);let $=this.getSessionCreatedEntry(q,J),Y=q.reduce((L,d)=>d.type==="session_updated"?{...L,...d.data}:L,{...$.data}),H=j(q),K=H.filter((L)=>L.type==="message_created"&&["user","assistant"].includes(L.data.role)).length,Z=H.some((L)=>L.type==="part_created"&&L.data.partType==="tool_result"&&typeof L.data.payload.error==="string"),V=(zq.has(Y.taskStatus)?Y.taskStatus:void 0)??(Z?"failed":"completed"),B=typeof Y.taskOwnerPid==="number"&&Number.isInteger(Y.taskOwnerPid)&&Y.taskOwnerPid>0?Y.taskOwnerPid:void 0,N=Rq.has(Y.taskIsolation)?Y.taskIsolation:void 0,C=typeof Y.taskSourceProjectPath==="string"&&O.isAbsolute(Y.taskSourceProjectPath)?O.resolve(Y.taskSourceProjectPath):void 0,D=$.cwd;if(D!==void 0&&!O.isAbsolute(D))throw Error(`Session catalog cwd must be absolute: ${J}`);let p=D===void 0?G:O.resolve(D),m=Lq(Y.taskWorktree),k=m?.sessionId===J&&O.resolve(m.workspaceRoot)===p?m:void 0,Jq=Aq(Y.taskDiffStat),Xq=typeof Y.taskQueuePosition==="number"&&Number.isInteger(Y.taskQueuePosition)&&Y.taskQueuePosition>0?Y.taskQueuePosition:void 0,Yq=typeof Y.taskQueueDepth==="number"&&Number.isInteger(Y.taskQueueDepth)&&Y.taskQueueDepth>=0?Y.taskQueueDepth:void 0,$q=typeof Y.taskConcurrencyLimit==="number"&&Number.isInteger(Y.taskConcurrencyLimit)&&Y.taskConcurrencyLimit>0?Y.taskConcurrencyLimit:void 0;return{sessionId:J,projectPath:p,gitBranch:$.gitBranch,rootId:Y.rootId||J,parentId:Y.parentId,relationType:Y.relationType,resumedFrom:Y.resumedFrom,rootAgentId:Y.rootAgentId,resumeDepth:Y.resumeDepth,title:Y.title,agentType:Y.agentType,model:Y.model,taskStatus:V,taskStatusReason:typeof Y.taskStatusReason==="string"?Y.taskStatusReason:void 0,taskStartedAt:typeof Y.taskStartedAt==="string"?Y.taskStartedAt:void 0,taskCompletedAt:typeof Y.taskCompletedAt==="string"?Y.taskCompletedAt:void 0,taskPromptSummary:typeof Y.taskPromptSummary==="string"?Y.taskPromptSummary:void 0,taskIsolation:N,taskSourceProjectPath:C,taskWorktreePath:k?.worktreeRoot,taskWorktreeBranch:k?.branch,taskBaseCommit:k?.baseCommit,taskDiffStat:Jq,taskQueuePosition:Xq,taskQueueDepth:Yq,taskConcurrencyLimit:$q,taskOwnerPid:B,taskWorktree:k,messageCount:K,firstMessageTime:q[0].timestamp,lastMessageTime:q.at(-1).timestamp,hasErrors:Z||V==="failed",filePath:X}}static toPublicMetadata(q){let{filePath:J,taskOwnerPid:G,taskWorktree:X,...$}=q;return $}static getSessionFilePath(q,J){return x(q,J)}static getSessionCreatedEntry(q,J){let G=q.find((X)=>X.type==="session_created");if(!G)throw new bq(J);return G}static resolveCatalogWorkspace(q){if(!O.isAbsolute(q))throw Error("Session catalog cwd must be absolute");return O.resolve(q)}static validateSessionWorkspace(q,J,G){let X=this.getSessionCreatedEntry(q,J);if(X.data.sessionId!==J)throw Error(`Session creation record sessionId mismatch: ${J}`);if(!O.isAbsolute(X.cwd)||O.resolve(X.cwd)!==G)throw Error(`Session creation record cwd mismatch: ${J}`)}static resolveForkWorkspace(q){if(!O.isAbsolute(q))throw Error("Fork workspace paths must be absolute");return O.resolve(q)}static parseStoredSession(q,J){return xq(q,`session ${J}`)}static isCorruptSessionJSONLError(q){return q instanceof Error&&q.message.startsWith("Invalid session JSONL ")}static sanitizeStoredSessionError(q,J){if(!this.isCorruptSessionJSONLError(q)||!(q instanceof Error))return q;let G=q.message.match(/ at line (\d+)$/)?.[1];return Error(`Invalid session JSONL in session ${J}${G?` at line ${G}`:""}`,{cause:q.cause})}static async readStableSessionSnapshot(q,J,G=3){for(let X=0;X<G;X+=1){let $=await f.stat(q),Y=await f.readFile(q),H=this.parseStoredSession(Y,J),K=await f.stat(q);if($.size===K.size&&$.mtimeNs===K.mtimeNs&&$.dev===K.dev&&$.ino===K.ino)return H}throw Error("Session changed while creating fork; retry the operation")}}function Tq(q){if(q.length===1&&q[0]?.type==="text")return q[0].text;return[...q]}
3
+ export{h as Nb,b as Ob,y as Pb,jG as Qb,gG as Rb,bq as Sb,W as Tb};