codesesh 0.7.2 → 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.
- package/README.md +2 -1
- package/dist/{chunk-XANARSZG.js → chunk-LXHUIQZI.js} +610 -18
- package/dist/chunk-LXHUIQZI.js.map +1 -0
- package/dist/{dist-WJUBVCLN.js → dist-3Q4YTTEX.js} +2 -2
- package/dist/index.js +8 -3
- package/dist/index.js.map +1 -1
- package/dist/scan-refresh-worker.js +1 -1
- package/dist/search-index-worker.js +1 -1
- package/dist/smart-tag-worker.js +1 -1
- package/dist/web/assets/index-BHmQBGNx.css +2 -0
- package/dist/web/assets/index-CahEAHys.js +111 -0
- package/dist/web/assets/markdown-Bm__FT1K.js +14 -0
- package/dist/web/assets/{react-DT3QPCDf.js → react-CGUTVnhO.js} +5 -5
- package/dist/web/assets/rolldown-runtime-QTnfLwEv.js +1 -0
- package/dist/web/assets/{syntax-DcanuzfQ.js → syntax-Cjw-OADI.js} +2 -2
- package/dist/web/assets/vendor-Da5am_Td.js +40 -0
- package/dist/web/icon/agent/pi.svg +20 -0
- package/dist/web/index.html +7 -7
- package/package.json +6 -5
- package/dist/chunk-XANARSZG.js.map +0 -1
- package/dist/web/assets/index-Dfz6SLxJ.js +0 -108
- package/dist/web/assets/index-xfiMbcgm.css +0 -2
- package/dist/web/assets/markdown-CnUlvKkZ.js +0 -14
- package/dist/web/assets/rolldown-runtime-Dw2cE7zH.js +0 -1
- package/dist/web/assets/vendor-Bs5B_LvM.js +0 -43
- /package/dist/{dist-WJUBVCLN.js.map → dist-3Q4YTTEX.js.map} +0 -0
|
@@ -31,18 +31,20 @@ import {
|
|
|
31
31
|
import { join as join7, basename as basename5 } from "path";
|
|
32
32
|
import { existsSync as existsSync8, readdirSync as readdirSync4, readFileSync as readFileSync6, statSync as statSync5 } from "fs";
|
|
33
33
|
import { join as join8, normalize } from "path";
|
|
34
|
+
import { existsSync as existsSync9, readFileSync as readFileSync7, readdirSync as readdirSync5, statSync as statSync6 } from "fs";
|
|
35
|
+
import { basename as basename6, join as join9 } from "path";
|
|
34
36
|
import { availableParallelism } from "os";
|
|
35
37
|
import { Worker } from "worker_threads";
|
|
36
|
-
import { existsSync as
|
|
38
|
+
import { existsSync as existsSync10, readFileSync as readFileSync8 } from "fs";
|
|
37
39
|
import { spawnSync } from "child_process";
|
|
38
40
|
import * as os from "os";
|
|
39
41
|
import * as path from "path";
|
|
40
42
|
import { resolve, sep } from "path";
|
|
41
|
-
import { existsSync as
|
|
42
|
-
import { join as
|
|
43
|
+
import { existsSync as existsSync11, rmSync, unlinkSync } from "fs";
|
|
44
|
+
import { join as join10 } from "path";
|
|
43
45
|
import { homedir as homedir4 } from "os";
|
|
44
46
|
import { homedir as homedir5, platform as platform2 } from "os";
|
|
45
|
-
import { join as
|
|
47
|
+
import { join as join11 } from "path";
|
|
46
48
|
var registrations = [];
|
|
47
49
|
function registerAgent(reg) {
|
|
48
50
|
registrations.push(reg);
|
|
@@ -112,7 +114,8 @@ function resolveProviderRoots() {
|
|
|
112
114
|
codexRoot: envPath("CODEX_HOME") ?? join(home, ".codex"),
|
|
113
115
|
claudeRoot: envPath("CLAUDE_CONFIG_DIR") ?? join(home, ".claude"),
|
|
114
116
|
kimiRoot: envPath("KIMI_SHARE_DIR") ?? join(home, ".kimi"),
|
|
115
|
-
opencodeRoot: join(getDataHome(), "opencode")
|
|
117
|
+
opencodeRoot: join(getDataHome(), "opencode"),
|
|
118
|
+
piRoot: envPath("PI_HOME") ?? join(home, ".pi")
|
|
116
119
|
};
|
|
117
120
|
}
|
|
118
121
|
function getCursorDataPath() {
|
|
@@ -4664,6 +4667,589 @@ var CursorAgent = class extends BaseAgent {
|
|
|
4664
4667
|
}
|
|
4665
4668
|
}
|
|
4666
4669
|
};
|
|
4670
|
+
var HEAD_INDEX_VERSION3 = "pi-head-v1";
|
|
4671
|
+
var PARSER_VERSION2 = "pi-parser-v1";
|
|
4672
|
+
function parseTimestampMs3(value) {
|
|
4673
|
+
if (typeof value === "number") return Number.isFinite(value) ? value : 0;
|
|
4674
|
+
const text = String(value ?? "").trim();
|
|
4675
|
+
if (!text) return 0;
|
|
4676
|
+
const ts = Date.parse(text);
|
|
4677
|
+
return Number.isNaN(ts) ? 0 : ts;
|
|
4678
|
+
}
|
|
4679
|
+
function extractSessionIdFromFilename(filePath) {
|
|
4680
|
+
const stem = basename6(filePath, ".jsonl");
|
|
4681
|
+
const underscore = stem.indexOf("_");
|
|
4682
|
+
return underscore >= 0 ? stem.slice(underscore + 1) || stem : stem;
|
|
4683
|
+
}
|
|
4684
|
+
function isObject(value) {
|
|
4685
|
+
return typeof value === "object" && value !== null;
|
|
4686
|
+
}
|
|
4687
|
+
function contentToText(content) {
|
|
4688
|
+
if (typeof content === "string") return content;
|
|
4689
|
+
if (!Array.isArray(content)) return "";
|
|
4690
|
+
return content.map((item) => {
|
|
4691
|
+
if (!isObject(item)) return "";
|
|
4692
|
+
if (item["type"] === "text") return String(item["text"] ?? "");
|
|
4693
|
+
if (item["type"] === "image") return "[image]";
|
|
4694
|
+
return "";
|
|
4695
|
+
}).filter(Boolean).join("\n");
|
|
4696
|
+
}
|
|
4697
|
+
function normalizeTextParts(content, timestampMs) {
|
|
4698
|
+
const text = cleanInternalText(contentToText(content));
|
|
4699
|
+
return text ? [{ type: "text", text, time_created: timestampMs }] : [];
|
|
4700
|
+
}
|
|
4701
|
+
function buildMessage(params) {
|
|
4702
|
+
return {
|
|
4703
|
+
id: params.id,
|
|
4704
|
+
role: params.role,
|
|
4705
|
+
agent: params.agent,
|
|
4706
|
+
time_created: params.timestampMs,
|
|
4707
|
+
provider: params.provider,
|
|
4708
|
+
model: params.model,
|
|
4709
|
+
tokens: params.tokens,
|
|
4710
|
+
cost: params.cost,
|
|
4711
|
+
cost_source: params.costSource,
|
|
4712
|
+
parts: params.parts
|
|
4713
|
+
};
|
|
4714
|
+
}
|
|
4715
|
+
function getEntryTimestamp(entry) {
|
|
4716
|
+
return parseTimestampMs3(entry["timestamp"]);
|
|
4717
|
+
}
|
|
4718
|
+
function chooseLeafEntry(entries) {
|
|
4719
|
+
for (let index = entries.length - 1; index >= 0; index -= 1) {
|
|
4720
|
+
if (typeof entries[index]?.["id"] === "string") return entries[index];
|
|
4721
|
+
}
|
|
4722
|
+
return null;
|
|
4723
|
+
}
|
|
4724
|
+
function buildCurrentPathEntries(entries) {
|
|
4725
|
+
const byId = /* @__PURE__ */ new Map();
|
|
4726
|
+
for (const entry of entries) {
|
|
4727
|
+
const id = entry["id"];
|
|
4728
|
+
if (typeof id === "string" && id) byId.set(id, entry);
|
|
4729
|
+
}
|
|
4730
|
+
const leaf = chooseLeafEntry(entries);
|
|
4731
|
+
if (!leaf) return [];
|
|
4732
|
+
const path2 = [];
|
|
4733
|
+
const seen = /* @__PURE__ */ new Set();
|
|
4734
|
+
let current = leaf;
|
|
4735
|
+
while (current) {
|
|
4736
|
+
const id = String(current["id"] ?? "");
|
|
4737
|
+
if (!id || seen.has(id)) break;
|
|
4738
|
+
seen.add(id);
|
|
4739
|
+
path2.push(current);
|
|
4740
|
+
const parentId = current["parentId"];
|
|
4741
|
+
current = typeof parentId === "string" ? byId.get(parentId) : void 0;
|
|
4742
|
+
}
|
|
4743
|
+
return path2.reverse();
|
|
4744
|
+
}
|
|
4745
|
+
var PiAgent = class extends BaseAgent {
|
|
4746
|
+
name = "pi";
|
|
4747
|
+
displayName = "Pi";
|
|
4748
|
+
basePath = null;
|
|
4749
|
+
sessionMetaMap = /* @__PURE__ */ new Map();
|
|
4750
|
+
findBasePath() {
|
|
4751
|
+
const roots = resolveProviderRoots();
|
|
4752
|
+
return firstExisting(join9(roots.piRoot, "agent", "sessions"), "data/pi");
|
|
4753
|
+
}
|
|
4754
|
+
isAvailable() {
|
|
4755
|
+
this.basePath = this.findBasePath();
|
|
4756
|
+
if (!this.basePath) return false;
|
|
4757
|
+
return this.listSessionFiles().length > 0;
|
|
4758
|
+
}
|
|
4759
|
+
scan(options) {
|
|
4760
|
+
if (!this.basePath) return [];
|
|
4761
|
+
const scanMarker = perf.start("pi:scan");
|
|
4762
|
+
const files = this.listSessionFiles(options);
|
|
4763
|
+
options?.onProgress?.({ total: files.length, processed: 0, sessions: 0 });
|
|
4764
|
+
const heads = [];
|
|
4765
|
+
let processed = 0;
|
|
4766
|
+
for (const file of files) {
|
|
4767
|
+
try {
|
|
4768
|
+
const head = getParsedSession(this.parseSessionHeadResult(file));
|
|
4769
|
+
if (head) {
|
|
4770
|
+
heads.push(head);
|
|
4771
|
+
this.sessionMetaMap.set(head.id, this.buildSessionMeta(head, file));
|
|
4772
|
+
}
|
|
4773
|
+
} catch {
|
|
4774
|
+
} finally {
|
|
4775
|
+
processed += 1;
|
|
4776
|
+
options?.onProgress?.({ total: files.length, processed, sessions: heads.length });
|
|
4777
|
+
}
|
|
4778
|
+
}
|
|
4779
|
+
perf.end(scanMarker);
|
|
4780
|
+
return heads;
|
|
4781
|
+
}
|
|
4782
|
+
listSessionSources() {
|
|
4783
|
+
if (!this.basePath) return [];
|
|
4784
|
+
return this.listSessionFiles().map((file) => ({
|
|
4785
|
+
sessionId: extractSessionIdFromFilename(file),
|
|
4786
|
+
sourcePath: file,
|
|
4787
|
+
fingerprint: this.sourceFingerprint(file)
|
|
4788
|
+
}));
|
|
4789
|
+
}
|
|
4790
|
+
scanSessionSource(sourcePath) {
|
|
4791
|
+
const head = getParsedSession(this.parseSessionHeadResult(sourcePath));
|
|
4792
|
+
if (head) {
|
|
4793
|
+
this.sessionMetaMap.set(head.id, this.buildSessionMeta(head, sourcePath));
|
|
4794
|
+
}
|
|
4795
|
+
return head;
|
|
4796
|
+
}
|
|
4797
|
+
getSessionMetaMap() {
|
|
4798
|
+
return this.sessionMetaMap;
|
|
4799
|
+
}
|
|
4800
|
+
setSessionMetaMap(meta) {
|
|
4801
|
+
this.sessionMetaMap = meta;
|
|
4802
|
+
}
|
|
4803
|
+
checkForChanges(_sinceTimestamp, cachedSessions) {
|
|
4804
|
+
if (!this.basePath) return { hasChanges: false, timestamp: Date.now() };
|
|
4805
|
+
const currentFiles = this.listSessionFiles();
|
|
4806
|
+
const currentIds = new Set(currentFiles.map((file) => extractSessionIdFromFilename(file)));
|
|
4807
|
+
const cachedIds = new Set(cachedSessions.map((session) => session.id));
|
|
4808
|
+
const changedIds = /* @__PURE__ */ new Set();
|
|
4809
|
+
for (const session of cachedSessions) {
|
|
4810
|
+
if (!currentIds.has(session.id)) {
|
|
4811
|
+
changedIds.add(session.id);
|
|
4812
|
+
continue;
|
|
4813
|
+
}
|
|
4814
|
+
const meta = this.sessionMetaMap.get(session.id);
|
|
4815
|
+
if (!meta) {
|
|
4816
|
+
changedIds.add(session.id);
|
|
4817
|
+
continue;
|
|
4818
|
+
}
|
|
4819
|
+
try {
|
|
4820
|
+
if (this.hasMetaChanged(meta)) changedIds.add(session.id);
|
|
4821
|
+
} catch {
|
|
4822
|
+
changedIds.add(session.id);
|
|
4823
|
+
}
|
|
4824
|
+
}
|
|
4825
|
+
const hasAddedSessions = currentFiles.some(
|
|
4826
|
+
(file) => !cachedIds.has(extractSessionIdFromFilename(file))
|
|
4827
|
+
);
|
|
4828
|
+
return {
|
|
4829
|
+
hasChanges: changedIds.size > 0 || hasAddedSessions,
|
|
4830
|
+
changedIds: [...changedIds],
|
|
4831
|
+
timestamp: Date.now()
|
|
4832
|
+
};
|
|
4833
|
+
}
|
|
4834
|
+
incrementalScan(cachedSessions, changedIds) {
|
|
4835
|
+
if (!this.basePath) return cachedSessions;
|
|
4836
|
+
const sessionMap = new Map(cachedSessions.map((session) => [session.id, session]));
|
|
4837
|
+
const changedSet = new Set(changedIds);
|
|
4838
|
+
const currentFiles = this.listSessionFiles();
|
|
4839
|
+
const currentIds = new Set(currentFiles.map((file) => extractSessionIdFromFilename(file)));
|
|
4840
|
+
for (const session of cachedSessions) {
|
|
4841
|
+
if (!currentIds.has(session.id)) {
|
|
4842
|
+
sessionMap.delete(session.id);
|
|
4843
|
+
this.sessionMetaMap.delete(session.id);
|
|
4844
|
+
}
|
|
4845
|
+
}
|
|
4846
|
+
for (const file of currentFiles) {
|
|
4847
|
+
try {
|
|
4848
|
+
const sessionId = extractSessionIdFromFilename(file);
|
|
4849
|
+
if (!changedSet.has(sessionId) && sessionMap.has(sessionId)) continue;
|
|
4850
|
+
const head = getParsedSession(this.parseSessionHeadResult(file));
|
|
4851
|
+
if (head) {
|
|
4852
|
+
sessionMap.set(head.id, head);
|
|
4853
|
+
this.sessionMetaMap.set(head.id, this.buildSessionMeta(head, file));
|
|
4854
|
+
}
|
|
4855
|
+
} catch {
|
|
4856
|
+
}
|
|
4857
|
+
}
|
|
4858
|
+
return [...sessionMap.values()];
|
|
4859
|
+
}
|
|
4860
|
+
getSessionData(sessionId) {
|
|
4861
|
+
const meta = this.sessionMetaMap.get(sessionId);
|
|
4862
|
+
if (!meta) throw new Error(`Session not found: ${sessionId}`);
|
|
4863
|
+
if (!existsSync9(meta.sourcePath)) throw new Error(`Session file missing: ${meta.sourcePath}`);
|
|
4864
|
+
const parsed2 = this.parsePiFile(meta.sourcePath);
|
|
4865
|
+
const state = this.convertEntries(parsed2.pathEntries);
|
|
4866
|
+
const cleanedMessages = cleanParsedMessages(state.messages);
|
|
4867
|
+
return {
|
|
4868
|
+
id: meta.id,
|
|
4869
|
+
title: meta.title,
|
|
4870
|
+
slug: `pi/${meta.id}`,
|
|
4871
|
+
directory: meta.directory,
|
|
4872
|
+
time_created: meta.createdAt,
|
|
4873
|
+
time_updated: meta.updatedAt,
|
|
4874
|
+
stats: {
|
|
4875
|
+
message_count: cleanedMessages.length,
|
|
4876
|
+
total_input_tokens: state.totalInputTokens,
|
|
4877
|
+
total_output_tokens: state.totalOutputTokens,
|
|
4878
|
+
total_cache_read_tokens: state.totalCacheReadTokens || void 0,
|
|
4879
|
+
total_cache_create_tokens: state.totalCacheCreateTokens || void 0,
|
|
4880
|
+
total_cost: state.totalCost,
|
|
4881
|
+
cost_source: state.totalCost > 0 ? "recorded" : void 0
|
|
4882
|
+
},
|
|
4883
|
+
messages: cleanedMessages
|
|
4884
|
+
};
|
|
4885
|
+
}
|
|
4886
|
+
listSessionFiles(options) {
|
|
4887
|
+
if (!this.basePath) return [];
|
|
4888
|
+
return this.walkJsonlFiles(this.basePath, options);
|
|
4889
|
+
}
|
|
4890
|
+
walkJsonlFiles(dir, options) {
|
|
4891
|
+
const files = [];
|
|
4892
|
+
try {
|
|
4893
|
+
for (const entry of readdirSync5(dir, { withFileTypes: true })) {
|
|
4894
|
+
const fullPath = join9(dir, entry.name);
|
|
4895
|
+
if (entry.isDirectory()) {
|
|
4896
|
+
files.push(...this.walkJsonlFiles(fullPath, options));
|
|
4897
|
+
continue;
|
|
4898
|
+
}
|
|
4899
|
+
if (!entry.isFile() || !entry.name.endsWith(".jsonl")) continue;
|
|
4900
|
+
if (!matchesScanWindow(statSync6(fullPath).mtimeMs, options)) continue;
|
|
4901
|
+
files.push(fullPath);
|
|
4902
|
+
}
|
|
4903
|
+
} catch {
|
|
4904
|
+
}
|
|
4905
|
+
return files;
|
|
4906
|
+
}
|
|
4907
|
+
buildSessionMeta(head, file) {
|
|
4908
|
+
return {
|
|
4909
|
+
id: head.id,
|
|
4910
|
+
title: head.title,
|
|
4911
|
+
sourcePath: file,
|
|
4912
|
+
sourceFingerprint: this.sourceFingerprint(file),
|
|
4913
|
+
sourceMtimeMs: statSync6(file).mtimeMs,
|
|
4914
|
+
headIndexVersion: HEAD_INDEX_VERSION3,
|
|
4915
|
+
parserVersion: PARSER_VERSION2,
|
|
4916
|
+
directory: head.directory,
|
|
4917
|
+
messageCount: head.stats.message_count,
|
|
4918
|
+
createdAt: head.time_created,
|
|
4919
|
+
updatedAt: head.time_updated ?? head.time_created
|
|
4920
|
+
};
|
|
4921
|
+
}
|
|
4922
|
+
hasMetaChanged(meta) {
|
|
4923
|
+
if (meta.headIndexVersion !== HEAD_INDEX_VERSION3) return true;
|
|
4924
|
+
if (meta.parserVersion !== PARSER_VERSION2) return true;
|
|
4925
|
+
return statSync6(meta.sourcePath).mtimeMs !== meta.sourceMtimeMs;
|
|
4926
|
+
}
|
|
4927
|
+
sourceFingerprint(file) {
|
|
4928
|
+
const stat = statSync6(file);
|
|
4929
|
+
return JSON.stringify([HEAD_INDEX_VERSION3, PARSER_VERSION2, stat.mtimeMs, stat.size]);
|
|
4930
|
+
}
|
|
4931
|
+
parseSessionHeadResult(filePath) {
|
|
4932
|
+
const parsed2 = this.parsePiFile(filePath);
|
|
4933
|
+
const state = this.convertEntries(parsed2.pathEntries);
|
|
4934
|
+
const messageCount = state.messages.length;
|
|
4935
|
+
if (messageCount === 0) return filteredSession("no visible messages");
|
|
4936
|
+
const modelUsage = Object.keys(state.modelUsage).length > 0 ? state.modelUsage : void 0;
|
|
4937
|
+
return parsedSession({
|
|
4938
|
+
id: parsed2.sessionId,
|
|
4939
|
+
slug: `pi/${parsed2.sessionId}`,
|
|
4940
|
+
title: parsed2.title,
|
|
4941
|
+
directory: parsed2.directory,
|
|
4942
|
+
time_created: parsed2.createdAt,
|
|
4943
|
+
time_updated: parsed2.updatedAt,
|
|
4944
|
+
stats: {
|
|
4945
|
+
message_count: messageCount,
|
|
4946
|
+
total_input_tokens: state.totalInputTokens,
|
|
4947
|
+
total_output_tokens: state.totalOutputTokens,
|
|
4948
|
+
total_cache_read_tokens: state.totalCacheReadTokens || void 0,
|
|
4949
|
+
total_cache_create_tokens: state.totalCacheCreateTokens || void 0,
|
|
4950
|
+
total_cost: state.totalCost,
|
|
4951
|
+
cost_source: state.totalCost > 0 ? "recorded" : void 0
|
|
4952
|
+
},
|
|
4953
|
+
model_usage: modelUsage
|
|
4954
|
+
});
|
|
4955
|
+
}
|
|
4956
|
+
parsePiFile(filePath) {
|
|
4957
|
+
const records = Array.from(parseJsonlLines(readFileSync7(filePath, "utf-8")));
|
|
4958
|
+
if (records.length === 0) throw new Error("empty file");
|
|
4959
|
+
const header = records.find((record) => record["type"] === "session");
|
|
4960
|
+
if (!header) throw new Error("missing session header");
|
|
4961
|
+
const entries = records.filter((record) => record["type"] !== "session");
|
|
4962
|
+
const pathEntries = buildCurrentPathEntries(entries);
|
|
4963
|
+
if (pathEntries.length === 0) throw new Error("empty session tree");
|
|
4964
|
+
const sessionId = String(header["id"] ?? extractSessionIdFromFilename(filePath)).trim();
|
|
4965
|
+
if (!sessionId) throw new Error("missing session id");
|
|
4966
|
+
const stat = statSync6(filePath);
|
|
4967
|
+
const directory = String(header["cwd"] ?? "").trim() || basename6(filePath, ".jsonl");
|
|
4968
|
+
const createdAt = parseTimestampMs3(header["timestamp"]) || stat.mtimeMs;
|
|
4969
|
+
const updatedAt = pathEntries.reduce(
|
|
4970
|
+
(max, entry) => Math.max(max, getEntryTimestamp(entry)),
|
|
4971
|
+
createdAt
|
|
4972
|
+
);
|
|
4973
|
+
const explicitTitle = this.extractSessionName(pathEntries);
|
|
4974
|
+
const messageTitle = this.extractTitle(pathEntries);
|
|
4975
|
+
const directoryTitle = basenameTitle(directory);
|
|
4976
|
+
return {
|
|
4977
|
+
sessionId,
|
|
4978
|
+
directory,
|
|
4979
|
+
createdAt,
|
|
4980
|
+
updatedAt,
|
|
4981
|
+
title: resolveSessionTitle(explicitTitle, messageTitle, directoryTitle),
|
|
4982
|
+
pathEntries
|
|
4983
|
+
};
|
|
4984
|
+
}
|
|
4985
|
+
extractSessionName(entries) {
|
|
4986
|
+
for (let index = entries.length - 1; index >= 0; index -= 1) {
|
|
4987
|
+
const entry = entries[index];
|
|
4988
|
+
if (entry["type"] !== "session_info") continue;
|
|
4989
|
+
const name = normalizeTitleText(String(entry["name"] ?? ""));
|
|
4990
|
+
if (name) return name;
|
|
4991
|
+
}
|
|
4992
|
+
return null;
|
|
4993
|
+
}
|
|
4994
|
+
extractTitle(entries) {
|
|
4995
|
+
for (const entry of entries) {
|
|
4996
|
+
if (entry["type"] !== "message") continue;
|
|
4997
|
+
const message = entry["message"];
|
|
4998
|
+
if (!isObject(message) || message["role"] !== "user") continue;
|
|
4999
|
+
const title = normalizeTitleText(contentToText(message["content"]));
|
|
5000
|
+
if (title) return title;
|
|
5001
|
+
}
|
|
5002
|
+
return null;
|
|
5003
|
+
}
|
|
5004
|
+
convertEntries(entries) {
|
|
5005
|
+
const messages = [];
|
|
5006
|
+
const pendingToolCalls = /* @__PURE__ */ new Map();
|
|
5007
|
+
const modelUsage = {};
|
|
5008
|
+
let totalInputTokens = 0;
|
|
5009
|
+
let totalOutputTokens = 0;
|
|
5010
|
+
let totalCacheReadTokens = 0;
|
|
5011
|
+
let totalCacheCreateTokens = 0;
|
|
5012
|
+
let totalCost = 0;
|
|
5013
|
+
for (const entry of entries) {
|
|
5014
|
+
const timestampMs = getEntryTimestamp(entry);
|
|
5015
|
+
const type = String(entry["type"] ?? "");
|
|
5016
|
+
if (type === "message") {
|
|
5017
|
+
const message = entry["message"];
|
|
5018
|
+
if (!isObject(message)) continue;
|
|
5019
|
+
const result = this.convertAgentMessage(
|
|
5020
|
+
entry,
|
|
5021
|
+
message,
|
|
5022
|
+
timestampMs,
|
|
5023
|
+
pendingToolCalls,
|
|
5024
|
+
messages.length,
|
|
5025
|
+
messages
|
|
5026
|
+
);
|
|
5027
|
+
if (!result) continue;
|
|
5028
|
+
if (result.message) messages.push(result.message);
|
|
5029
|
+
totalInputTokens += result.inputTokens;
|
|
5030
|
+
totalOutputTokens += result.outputTokens;
|
|
5031
|
+
totalCacheReadTokens += result.cacheReadTokens;
|
|
5032
|
+
totalCacheCreateTokens += result.cacheCreateTokens;
|
|
5033
|
+
totalCost += result.cost;
|
|
5034
|
+
if (result.model && result.totalTokens > 0) {
|
|
5035
|
+
modelUsage[result.model] = (modelUsage[result.model] ?? 0) + result.totalTokens;
|
|
5036
|
+
}
|
|
5037
|
+
continue;
|
|
5038
|
+
}
|
|
5039
|
+
const summary = this.convertSummaryEntry(entry, timestampMs);
|
|
5040
|
+
if (summary) messages.push(summary);
|
|
5041
|
+
}
|
|
5042
|
+
return {
|
|
5043
|
+
messages,
|
|
5044
|
+
totalInputTokens,
|
|
5045
|
+
totalOutputTokens,
|
|
5046
|
+
totalCacheReadTokens,
|
|
5047
|
+
totalCacheCreateTokens,
|
|
5048
|
+
totalCost,
|
|
5049
|
+
modelUsage
|
|
5050
|
+
};
|
|
5051
|
+
}
|
|
5052
|
+
convertAgentMessage(entry, message, timestampMs, pendingToolCalls, nextMessageIndex, messages) {
|
|
5053
|
+
const id = String(entry["id"] ?? "");
|
|
5054
|
+
const role = String(message["role"] ?? "");
|
|
5055
|
+
if (role === "user") {
|
|
5056
|
+
const parts = normalizeTextParts(message["content"], timestampMs);
|
|
5057
|
+
if (parts.length === 0) return null;
|
|
5058
|
+
return this.emptyUsageResult(buildMessage({ id, role: "user", timestampMs, parts }));
|
|
5059
|
+
}
|
|
5060
|
+
if (role === "assistant") {
|
|
5061
|
+
const parts = this.normalizeAssistantParts(
|
|
5062
|
+
message["content"],
|
|
5063
|
+
timestampMs,
|
|
5064
|
+
pendingToolCalls,
|
|
5065
|
+
nextMessageIndex
|
|
5066
|
+
);
|
|
5067
|
+
if (parts.length === 0) return null;
|
|
5068
|
+
const usage = this.normalizeUsage(message["usage"]);
|
|
5069
|
+
const model = typeof message["model"] === "string" ? message["model"].trim() : null;
|
|
5070
|
+
const cost = usage.cost ?? estimateTokenCost(model, usage.tokens) ?? 0;
|
|
5071
|
+
return {
|
|
5072
|
+
message: buildMessage({
|
|
5073
|
+
id,
|
|
5074
|
+
role: "assistant",
|
|
5075
|
+
agent: "pi",
|
|
5076
|
+
timestampMs,
|
|
5077
|
+
parts,
|
|
5078
|
+
provider: typeof message["provider"] === "string" ? message["provider"] : null,
|
|
5079
|
+
model,
|
|
5080
|
+
tokens: usage.tokens,
|
|
5081
|
+
cost: cost || void 0,
|
|
5082
|
+
costSource: cost > 0 ? "recorded" : void 0
|
|
5083
|
+
}),
|
|
5084
|
+
inputTokens: usage.inputTokens,
|
|
5085
|
+
outputTokens: usage.outputTokens,
|
|
5086
|
+
cacheReadTokens: usage.cacheReadTokens,
|
|
5087
|
+
cacheCreateTokens: usage.cacheCreateTokens,
|
|
5088
|
+
totalTokens: usage.totalTokens,
|
|
5089
|
+
cost,
|
|
5090
|
+
model
|
|
5091
|
+
};
|
|
5092
|
+
}
|
|
5093
|
+
if (role === "toolResult") {
|
|
5094
|
+
this.attachToolResult(message, timestampMs, pendingToolCalls, messages);
|
|
5095
|
+
return this.emptyUsageResult();
|
|
5096
|
+
}
|
|
5097
|
+
if (role === "bashExecution") {
|
|
5098
|
+
return this.emptyUsageResult(this.convertBashExecution(id, message, timestampMs));
|
|
5099
|
+
}
|
|
5100
|
+
if (role === "custom" && message["display"] === true) {
|
|
5101
|
+
const parts = normalizeTextParts(message["content"], timestampMs);
|
|
5102
|
+
if (parts.length === 0) return null;
|
|
5103
|
+
return this.emptyUsageResult(buildMessage({ id, role: "user", timestampMs, parts }));
|
|
5104
|
+
}
|
|
5105
|
+
if (role === "branchSummary" || role === "compactionSummary") {
|
|
5106
|
+
const summary = String(message["summary"] ?? "").trim();
|
|
5107
|
+
if (!summary) return null;
|
|
5108
|
+
return this.emptyUsageResult(
|
|
5109
|
+
buildMessage({
|
|
5110
|
+
id,
|
|
5111
|
+
role: "assistant",
|
|
5112
|
+
agent: "pi",
|
|
5113
|
+
timestampMs,
|
|
5114
|
+
parts: [{ type: "text", text: summary, time_created: timestampMs }]
|
|
5115
|
+
})
|
|
5116
|
+
);
|
|
5117
|
+
}
|
|
5118
|
+
return null;
|
|
5119
|
+
}
|
|
5120
|
+
normalizeAssistantParts(content, timestampMs, pendingToolCalls, messageIndex) {
|
|
5121
|
+
if (!Array.isArray(content)) return [];
|
|
5122
|
+
const parts = [];
|
|
5123
|
+
for (const item of content) {
|
|
5124
|
+
if (!isObject(item)) continue;
|
|
5125
|
+
const type = item["type"];
|
|
5126
|
+
if (type === "text") {
|
|
5127
|
+
const text = cleanInternalText(String(item["text"] ?? ""));
|
|
5128
|
+
if (text) parts.push({ type: "text", text, time_created: timestampMs });
|
|
5129
|
+
continue;
|
|
5130
|
+
}
|
|
5131
|
+
if (type === "thinking") {
|
|
5132
|
+
const text = cleanInternalText(String(item["thinking"] ?? ""));
|
|
5133
|
+
if (text) parts.push({ type: "reasoning", text, time_created: timestampMs });
|
|
5134
|
+
continue;
|
|
5135
|
+
}
|
|
5136
|
+
if (type === "toolCall") {
|
|
5137
|
+
const callId = String(item["id"] ?? "").trim();
|
|
5138
|
+
const toolName = String(item["name"] ?? "").trim() || "tool";
|
|
5139
|
+
const toolPart = {
|
|
5140
|
+
type: "tool",
|
|
5141
|
+
tool: toolName,
|
|
5142
|
+
title: `Tool: ${toolName}`,
|
|
5143
|
+
callID: callId || void 0,
|
|
5144
|
+
time_created: timestampMs,
|
|
5145
|
+
state: {
|
|
5146
|
+
status: "running",
|
|
5147
|
+
input: item["arguments"] ?? {}
|
|
5148
|
+
}
|
|
5149
|
+
};
|
|
5150
|
+
parts.push(toolPart);
|
|
5151
|
+
if (callId) pendingToolCalls.set(callId, [messageIndex, parts.length - 1]);
|
|
5152
|
+
}
|
|
5153
|
+
}
|
|
5154
|
+
return parts;
|
|
5155
|
+
}
|
|
5156
|
+
attachToolResult(message, timestampMs, pendingToolCalls, messages) {
|
|
5157
|
+
const callId = String(message["toolCallId"] ?? "").trim();
|
|
5158
|
+
const output = normalizeTextParts(message["content"], timestampMs);
|
|
5159
|
+
const location = callId ? pendingToolCalls.get(callId) : void 0;
|
|
5160
|
+
if (!location) return;
|
|
5161
|
+
const [messageIndex, partIndex] = location;
|
|
5162
|
+
const target = messages[messageIndex]?.parts[partIndex];
|
|
5163
|
+
if (!target?.state) return;
|
|
5164
|
+
target.state.output = output;
|
|
5165
|
+
target.state.status = message["isError"] === true ? "error" : "completed";
|
|
5166
|
+
target.state.metadata = message["details"];
|
|
5167
|
+
pendingToolCalls.delete(callId);
|
|
5168
|
+
}
|
|
5169
|
+
convertBashExecution(id, message, timestampMs) {
|
|
5170
|
+
const command = String(message["command"] ?? "");
|
|
5171
|
+
const output = String(message["output"] ?? "");
|
|
5172
|
+
const isError = Number(message["exitCode"] ?? 0) !== 0 || message["cancelled"] === true;
|
|
5173
|
+
return buildMessage({
|
|
5174
|
+
id,
|
|
5175
|
+
role: "tool",
|
|
5176
|
+
timestampMs,
|
|
5177
|
+
parts: [
|
|
5178
|
+
{
|
|
5179
|
+
type: "tool",
|
|
5180
|
+
tool: "bash",
|
|
5181
|
+
title: "Tool: bash",
|
|
5182
|
+
time_created: timestampMs,
|
|
5183
|
+
state: {
|
|
5184
|
+
status: isError ? "error" : "completed",
|
|
5185
|
+
input: { command },
|
|
5186
|
+
output: output ? [{ type: "text", text: output, time_created: timestampMs }] : [],
|
|
5187
|
+
metadata: {
|
|
5188
|
+
exitCode: message["exitCode"],
|
|
5189
|
+
cancelled: message["cancelled"],
|
|
5190
|
+
truncated: message["truncated"],
|
|
5191
|
+
fullOutputPath: message["fullOutputPath"]
|
|
5192
|
+
}
|
|
5193
|
+
}
|
|
5194
|
+
}
|
|
5195
|
+
]
|
|
5196
|
+
});
|
|
5197
|
+
}
|
|
5198
|
+
convertSummaryEntry(entry, timestampMs) {
|
|
5199
|
+
const type = entry["type"];
|
|
5200
|
+
if (type !== "compaction" && type !== "branch_summary" && type !== "custom_message") {
|
|
5201
|
+
return null;
|
|
5202
|
+
}
|
|
5203
|
+
if (type === "custom_message" && entry["display"] !== true) return null;
|
|
5204
|
+
const rawText = type === "custom_message" ? contentToText(entry["content"]) : String(entry["summary"] ?? "");
|
|
5205
|
+
const text = cleanInternalText(rawText);
|
|
5206
|
+
if (!text) return null;
|
|
5207
|
+
return buildMessage({
|
|
5208
|
+
id: String(entry["id"] ?? ""),
|
|
5209
|
+
role: type === "custom_message" ? "user" : "assistant",
|
|
5210
|
+
agent: type === "custom_message" ? void 0 : "pi",
|
|
5211
|
+
timestampMs,
|
|
5212
|
+
parts: [{ type: "text", text, time_created: timestampMs }]
|
|
5213
|
+
});
|
|
5214
|
+
}
|
|
5215
|
+
normalizeUsage(raw) {
|
|
5216
|
+
const usage = isObject(raw) ? raw : {};
|
|
5217
|
+
const inputTokens = Number(usage["input"] ?? 0);
|
|
5218
|
+
const outputTokens = Number(usage["output"] ?? 0);
|
|
5219
|
+
const cacheReadTokens = Number(usage["cacheRead"] ?? 0);
|
|
5220
|
+
const cacheCreateTokens = Number(usage["cacheWrite"] ?? 0);
|
|
5221
|
+
const totalTokens = Number(
|
|
5222
|
+
usage["totalTokens"] ?? inputTokens + outputTokens + cacheReadTokens + cacheCreateTokens
|
|
5223
|
+
);
|
|
5224
|
+
const cost = isObject(usage["cost"]) ? Number(usage["cost"]["total"] ?? 0) : null;
|
|
5225
|
+
return {
|
|
5226
|
+
inputTokens: inputTokens + cacheReadTokens + cacheCreateTokens,
|
|
5227
|
+
outputTokens,
|
|
5228
|
+
cacheReadTokens,
|
|
5229
|
+
cacheCreateTokens,
|
|
5230
|
+
totalTokens,
|
|
5231
|
+
cost: cost && Number.isFinite(cost) ? cost : null,
|
|
5232
|
+
tokens: {
|
|
5233
|
+
input: inputTokens + cacheReadTokens + cacheCreateTokens,
|
|
5234
|
+
output: outputTokens,
|
|
5235
|
+
cache_read: cacheReadTokens || void 0,
|
|
5236
|
+
cache_create: cacheCreateTokens || void 0
|
|
5237
|
+
}
|
|
5238
|
+
};
|
|
5239
|
+
}
|
|
5240
|
+
emptyUsageResult(message) {
|
|
5241
|
+
return {
|
|
5242
|
+
message,
|
|
5243
|
+
inputTokens: 0,
|
|
5244
|
+
outputTokens: 0,
|
|
5245
|
+
cacheReadTokens: 0,
|
|
5246
|
+
cacheCreateTokens: 0,
|
|
5247
|
+
totalTokens: 0,
|
|
5248
|
+
cost: 0,
|
|
5249
|
+
model: null
|
|
5250
|
+
};
|
|
5251
|
+
}
|
|
5252
|
+
};
|
|
4667
5253
|
registerAgent({
|
|
4668
5254
|
name: "claudecode",
|
|
4669
5255
|
displayName: "Claude Code",
|
|
@@ -4688,6 +5274,12 @@ registerAgent({
|
|
|
4688
5274
|
icon: "/icon/agent/codex.svg",
|
|
4689
5275
|
create: () => new CodexAgent()
|
|
4690
5276
|
});
|
|
5277
|
+
registerAgent({
|
|
5278
|
+
name: "pi",
|
|
5279
|
+
displayName: "Pi",
|
|
5280
|
+
icon: "/icon/agent/pi.svg",
|
|
5281
|
+
create: () => new PiAgent()
|
|
5282
|
+
});
|
|
4691
5283
|
registerAgent({
|
|
4692
5284
|
name: "cursor",
|
|
4693
5285
|
displayName: "Cursor",
|
|
@@ -4702,11 +5294,11 @@ function fallbackDisplayName(input) {
|
|
|
4702
5294
|
}
|
|
4703
5295
|
var realFs = {
|
|
4704
5296
|
exists(path2) {
|
|
4705
|
-
return
|
|
5297
|
+
return existsSync10(path2);
|
|
4706
5298
|
},
|
|
4707
5299
|
readText(path2) {
|
|
4708
5300
|
try {
|
|
4709
|
-
return
|
|
5301
|
+
return readFileSync8(path2, "utf8");
|
|
4710
5302
|
} catch {
|
|
4711
5303
|
return null;
|
|
4712
5304
|
}
|
|
@@ -5196,16 +5788,16 @@ var LEGACY_CACHE_FILENAME = "scan-cache.json";
|
|
|
5196
5788
|
var SEARCH_INDEX_BULK_SYNC_THRESHOLD = 100;
|
|
5197
5789
|
var ftsIntegrityCheckedPath = null;
|
|
5198
5790
|
function getCacheDir2() {
|
|
5199
|
-
return
|
|
5791
|
+
return join10(homedir4(), ".cache", "codesesh");
|
|
5200
5792
|
}
|
|
5201
5793
|
function getCachePath2() {
|
|
5202
|
-
return
|
|
5794
|
+
return join10(getCacheDir2(), CACHE_FILENAME);
|
|
5203
5795
|
}
|
|
5204
5796
|
function getLegacyCachePath() {
|
|
5205
|
-
return
|
|
5797
|
+
return join10(getCacheDir2(), LEGACY_CACHE_FILENAME);
|
|
5206
5798
|
}
|
|
5207
5799
|
function hasCacheStorage() {
|
|
5208
|
-
return
|
|
5800
|
+
return existsSync11(getCachePath2());
|
|
5209
5801
|
}
|
|
5210
5802
|
function withCacheDb(fn) {
|
|
5211
5803
|
const cachePath = getCachePath2();
|
|
@@ -6644,7 +7236,7 @@ function buildSessionContentFromMessages(title, messages) {
|
|
|
6644
7236
|
}
|
|
6645
7237
|
function deleteLegacyCacheFile() {
|
|
6646
7238
|
const legacyPath = getLegacyCachePath();
|
|
6647
|
-
if (!
|
|
7239
|
+
if (!existsSync11(legacyPath)) {
|
|
6648
7240
|
return;
|
|
6649
7241
|
}
|
|
6650
7242
|
try {
|
|
@@ -6971,7 +7563,7 @@ function clearCache() {
|
|
|
6971
7563
|
const walPath = `${cachePath}-wal`;
|
|
6972
7564
|
const shmPath = `${cachePath}-shm`;
|
|
6973
7565
|
for (const filePath of [walPath, shmPath]) {
|
|
6974
|
-
if (!
|
|
7566
|
+
if (!existsSync11(filePath)) {
|
|
6975
7567
|
continue;
|
|
6976
7568
|
}
|
|
6977
7569
|
try {
|
|
@@ -8179,16 +8771,16 @@ function getStateDir() {
|
|
|
8179
8771
|
}
|
|
8180
8772
|
const p = platform2();
|
|
8181
8773
|
if (p === "darwin") {
|
|
8182
|
-
return
|
|
8774
|
+
return join11(homedir5(), "Library", "Application Support", "codesesh");
|
|
8183
8775
|
}
|
|
8184
8776
|
if (p === "win32") {
|
|
8185
8777
|
const appData = process.env.APPDATA ?? process.env.LOCALAPPDATA;
|
|
8186
|
-
return
|
|
8778
|
+
return join11(appData ?? join11(homedir5(), "AppData", "Roaming"), "codesesh");
|
|
8187
8779
|
}
|
|
8188
|
-
return
|
|
8780
|
+
return join11(process.env.XDG_DATA_HOME ?? join11(homedir5(), ".local", "share"), "codesesh");
|
|
8189
8781
|
}
|
|
8190
8782
|
function getStateDbPath() {
|
|
8191
|
-
return
|
|
8783
|
+
return join11(getStateDir(), BOOKMARK_DB_FILENAME);
|
|
8192
8784
|
}
|
|
8193
8785
|
function useMemoryStateStore() {
|
|
8194
8786
|
return process.env.CODESESH_STATE_STORE === MEMORY_STATE_STORE;
|
|
@@ -8556,4 +9148,4 @@ export {
|
|
|
8556
9148
|
importBookmarks,
|
|
8557
9149
|
deleteBookmark
|
|
8558
9150
|
};
|
|
8559
|
-
//# sourceMappingURL=chunk-
|
|
9151
|
+
//# sourceMappingURL=chunk-LXHUIQZI.js.map
|