agentflow-core 0.3.1 → 0.3.3
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/dist/{chunk-NPH34CAL.js → chunk-M5CGDXAO.js} +119 -11
- package/dist/cli.cjs +119 -11
- package/dist/cli.js +1 -1
- package/dist/index.cjs +119 -11
- package/dist/index.js +1 -1
- package/package.json +1 -1
|
@@ -867,14 +867,120 @@ function processJsonlFile(file) {
|
|
|
867
867
|
const content = readFileSync(file.path, "utf8").trim();
|
|
868
868
|
if (!content) return [];
|
|
869
869
|
const lines = content.split("\n");
|
|
870
|
-
const
|
|
871
|
-
const
|
|
872
|
-
const name =
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
870
|
+
const lineCount = lines.length;
|
|
871
|
+
const lastObj = JSON.parse(lines[lines.length - 1]);
|
|
872
|
+
const name = lastObj.jobId ?? lastObj.agentId ?? lastObj.name ?? lastObj.id ?? nameFromFile(file.filename);
|
|
873
|
+
if (lastObj.action !== void 0 || lastObj.jobId !== void 0) {
|
|
874
|
+
const status2 = findStatus(lastObj);
|
|
875
|
+
const ts2 = findTimestamp(lastObj) || file.mtime;
|
|
876
|
+
const action = lastObj.action;
|
|
877
|
+
const detail2 = action ? `${action} (${lineCount} entries)` : `${lineCount} entries`;
|
|
878
|
+
return [{ id: String(name), source: "session", status: status2, lastActive: ts2, detail: detail2, file: file.filename }];
|
|
879
|
+
}
|
|
880
|
+
const tail = lines.slice(Math.max(0, lineCount - 30));
|
|
881
|
+
let model = "";
|
|
882
|
+
let totalTokens = 0;
|
|
883
|
+
let totalCost = 0;
|
|
884
|
+
let toolCalls = [];
|
|
885
|
+
let lastUserMsg = "";
|
|
886
|
+
let lastAssistantMsg = "";
|
|
887
|
+
let errorCount = 0;
|
|
888
|
+
let lastRole = "";
|
|
889
|
+
let sessionId = "";
|
|
890
|
+
for (const line of tail) {
|
|
891
|
+
let entry;
|
|
892
|
+
try {
|
|
893
|
+
entry = JSON.parse(line);
|
|
894
|
+
} catch {
|
|
895
|
+
continue;
|
|
896
|
+
}
|
|
897
|
+
const entryType = entry.type;
|
|
898
|
+
if (entryType === "session") {
|
|
899
|
+
sessionId = entry.id ?? "";
|
|
900
|
+
continue;
|
|
901
|
+
}
|
|
902
|
+
if (entryType === "model_change") {
|
|
903
|
+
model = entry.modelId ?? "";
|
|
904
|
+
continue;
|
|
905
|
+
}
|
|
906
|
+
if (entryType !== "message") continue;
|
|
907
|
+
const msg = entry.message;
|
|
908
|
+
if (!msg) continue;
|
|
909
|
+
const role = msg.role;
|
|
910
|
+
lastRole = role;
|
|
911
|
+
if (msg.model && !model) model = msg.model;
|
|
912
|
+
const usage = msg.usage;
|
|
913
|
+
if (usage) {
|
|
914
|
+
const input = usage.input ?? 0;
|
|
915
|
+
const output = usage.output ?? 0;
|
|
916
|
+
totalTokens += input + output;
|
|
917
|
+
const cost = usage.cost;
|
|
918
|
+
if (cost && typeof cost.total === "number") totalCost += cost.total;
|
|
919
|
+
}
|
|
920
|
+
const msgContent = msg.content;
|
|
921
|
+
if (role === "user") {
|
|
922
|
+
if (typeof msgContent === "string") {
|
|
923
|
+
lastUserMsg = msgContent.slice(0, 80);
|
|
924
|
+
} else if (Array.isArray(msgContent)) {
|
|
925
|
+
for (const c of msgContent) {
|
|
926
|
+
if (c.type === "text" && typeof c.text === "string") {
|
|
927
|
+
lastUserMsg = c.text.slice(0, 80);
|
|
928
|
+
break;
|
|
929
|
+
}
|
|
930
|
+
}
|
|
931
|
+
}
|
|
932
|
+
}
|
|
933
|
+
if (role === "assistant" && Array.isArray(msgContent)) {
|
|
934
|
+
for (const c of msgContent) {
|
|
935
|
+
if (c.type === "tool_use" || c.type === "toolCall") {
|
|
936
|
+
const toolName = c.name ?? "";
|
|
937
|
+
if (toolName && !toolCalls.includes(toolName)) toolCalls.push(toolName);
|
|
938
|
+
}
|
|
939
|
+
if (c.type === "text" && typeof c.text === "string" && c.text.length > 5) {
|
|
940
|
+
lastAssistantMsg = c.text.slice(0, 80);
|
|
941
|
+
}
|
|
942
|
+
}
|
|
943
|
+
}
|
|
944
|
+
if (role === "toolResult") {
|
|
945
|
+
if (typeof msgContent === "string" && /error|ENOENT|failed|exception/i.test(msgContent)) {
|
|
946
|
+
errorCount++;
|
|
947
|
+
} else if (Array.isArray(msgContent)) {
|
|
948
|
+
for (const c of msgContent) {
|
|
949
|
+
if (typeof c.text === "string" && /error|ENOENT|failed|exception/i.test(c.text)) {
|
|
950
|
+
errorCount++;
|
|
951
|
+
}
|
|
952
|
+
}
|
|
953
|
+
}
|
|
954
|
+
}
|
|
955
|
+
}
|
|
956
|
+
const parts = [];
|
|
957
|
+
if (model) {
|
|
958
|
+
const shortModel = model.includes("/") ? model.split("/").pop() : model;
|
|
959
|
+
parts.push(shortModel.slice(0, 20));
|
|
960
|
+
}
|
|
961
|
+
if (toolCalls.length > 0) {
|
|
962
|
+
const recent = toolCalls.slice(-3);
|
|
963
|
+
parts.push(`tools: ${recent.join(", ")}`);
|
|
964
|
+
}
|
|
965
|
+
if (totalCost > 0) {
|
|
966
|
+
parts.push(`$${totalCost.toFixed(3)}`);
|
|
967
|
+
} else if (totalTokens > 0) {
|
|
968
|
+
const k = (totalTokens / 1e3).toFixed(1);
|
|
969
|
+
parts.push(`${k}k tok`);
|
|
970
|
+
}
|
|
971
|
+
if (lastAssistantMsg && lastRole === "assistant") {
|
|
972
|
+
parts.push(lastAssistantMsg.slice(0, 40));
|
|
973
|
+
} else if (lastUserMsg && !parts.some((p) => p.startsWith("tools:"))) {
|
|
974
|
+
parts.push(`user: ${lastUserMsg.slice(0, 35)}`);
|
|
975
|
+
}
|
|
976
|
+
if (errorCount > 0) {
|
|
977
|
+
parts.push(`${errorCount} errors`);
|
|
978
|
+
}
|
|
979
|
+
const detail = parts.join(" | ") || `${lineCount} messages`;
|
|
980
|
+
const status = errorCount > lineCount / 4 ? "error" : lastRole === "assistant" ? "ok" : "running";
|
|
981
|
+
const ts = findTimestamp(lastObj) || file.mtime;
|
|
982
|
+
const sessionName = sessionId ? sessionId.slice(0, 8) : nameFromFile(file.filename);
|
|
983
|
+
return [{ id: String(name !== "unknown" ? name : sessionName), source: "session", status, lastActive: ts, detail, file: file.filename }];
|
|
878
984
|
} catch {
|
|
879
985
|
return [];
|
|
880
986
|
}
|
|
@@ -1030,6 +1136,8 @@ function render(config) {
|
|
|
1030
1136
|
function truncate(s, max) {
|
|
1031
1137
|
return s.length > max ? s.slice(0, max - 1) + "\u2026" : s;
|
|
1032
1138
|
}
|
|
1139
|
+
const termWidth = process.stdout.columns || 120;
|
|
1140
|
+
const detailWidth = Math.max(20, termWidth - 60);
|
|
1033
1141
|
if (firstRender) {
|
|
1034
1142
|
process.stdout.write("\x1B[2J");
|
|
1035
1143
|
firstRender = false;
|
|
@@ -1057,7 +1165,7 @@ function render(config) {
|
|
|
1057
1165
|
if (g.children.length === 0) {
|
|
1058
1166
|
const name = truncate(g.name, 26).padEnd(26);
|
|
1059
1167
|
const st = statusText(g);
|
|
1060
|
-
const det = truncate(g.detail,
|
|
1168
|
+
const det = truncate(g.detail, detailWidth);
|
|
1061
1169
|
writeLine(L, ` ${icon} ${name} ${st.padEnd(20)} ${active.padEnd(20)} ${C.dim}${det}${C.reset}`);
|
|
1062
1170
|
lineCount++;
|
|
1063
1171
|
} else {
|
|
@@ -1075,7 +1183,7 @@ function render(config) {
|
|
|
1075
1183
|
const cIcon = statusIcon(child.status, Date.now() - child.lastActive < 3e5);
|
|
1076
1184
|
const cName = truncate(child.id, 22).padEnd(22);
|
|
1077
1185
|
const cActive = `${C.dim}${timeStr(child.lastActive)}${C.reset}`;
|
|
1078
|
-
const cDet = truncate(child.detail,
|
|
1186
|
+
const cDet = truncate(child.detail, detailWidth - 5);
|
|
1079
1187
|
writeLine(L, ` ${C.dim}${connector}${C.reset} ${cIcon} ${cName} ${cActive.padEnd(20)} ${C.dim}${cDet}${C.reset}`);
|
|
1080
1188
|
lineCount++;
|
|
1081
1189
|
}
|
|
@@ -1117,7 +1225,7 @@ function render(config) {
|
|
|
1117
1225
|
const agent = truncate(r.id, 26).padEnd(26);
|
|
1118
1226
|
const age = Math.floor((Date.now() - r.lastActive) / 1e3);
|
|
1119
1227
|
const ageStr = age < 60 ? age + "s ago" : age < 3600 ? Math.floor(age / 60) + "m ago" : Math.floor(age / 3600) + "h ago";
|
|
1120
|
-
const det = truncate(r.detail,
|
|
1228
|
+
const det = truncate(r.detail, detailWidth);
|
|
1121
1229
|
writeLine(L, ` ${icon} ${agent} ${C.dim}${t} ${ageStr.padStart(8)}${C.reset} ${C.dim}${det}${C.reset}`);
|
|
1122
1230
|
}
|
|
1123
1231
|
}
|
package/dist/cli.cjs
CHANGED
|
@@ -807,14 +807,120 @@ function processJsonlFile(file) {
|
|
|
807
807
|
const content = (0, import_node_fs2.readFileSync)(file.path, "utf8").trim();
|
|
808
808
|
if (!content) return [];
|
|
809
809
|
const lines = content.split("\n");
|
|
810
|
-
const
|
|
811
|
-
const
|
|
812
|
-
const name =
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
810
|
+
const lineCount = lines.length;
|
|
811
|
+
const lastObj = JSON.parse(lines[lines.length - 1]);
|
|
812
|
+
const name = lastObj.jobId ?? lastObj.agentId ?? lastObj.name ?? lastObj.id ?? nameFromFile(file.filename);
|
|
813
|
+
if (lastObj.action !== void 0 || lastObj.jobId !== void 0) {
|
|
814
|
+
const status2 = findStatus(lastObj);
|
|
815
|
+
const ts2 = findTimestamp(lastObj) || file.mtime;
|
|
816
|
+
const action = lastObj.action;
|
|
817
|
+
const detail2 = action ? `${action} (${lineCount} entries)` : `${lineCount} entries`;
|
|
818
|
+
return [{ id: String(name), source: "session", status: status2, lastActive: ts2, detail: detail2, file: file.filename }];
|
|
819
|
+
}
|
|
820
|
+
const tail = lines.slice(Math.max(0, lineCount - 30));
|
|
821
|
+
let model = "";
|
|
822
|
+
let totalTokens = 0;
|
|
823
|
+
let totalCost = 0;
|
|
824
|
+
let toolCalls = [];
|
|
825
|
+
let lastUserMsg = "";
|
|
826
|
+
let lastAssistantMsg = "";
|
|
827
|
+
let errorCount = 0;
|
|
828
|
+
let lastRole = "";
|
|
829
|
+
let sessionId = "";
|
|
830
|
+
for (const line of tail) {
|
|
831
|
+
let entry;
|
|
832
|
+
try {
|
|
833
|
+
entry = JSON.parse(line);
|
|
834
|
+
} catch {
|
|
835
|
+
continue;
|
|
836
|
+
}
|
|
837
|
+
const entryType = entry.type;
|
|
838
|
+
if (entryType === "session") {
|
|
839
|
+
sessionId = entry.id ?? "";
|
|
840
|
+
continue;
|
|
841
|
+
}
|
|
842
|
+
if (entryType === "model_change") {
|
|
843
|
+
model = entry.modelId ?? "";
|
|
844
|
+
continue;
|
|
845
|
+
}
|
|
846
|
+
if (entryType !== "message") continue;
|
|
847
|
+
const msg = entry.message;
|
|
848
|
+
if (!msg) continue;
|
|
849
|
+
const role = msg.role;
|
|
850
|
+
lastRole = role;
|
|
851
|
+
if (msg.model && !model) model = msg.model;
|
|
852
|
+
const usage = msg.usage;
|
|
853
|
+
if (usage) {
|
|
854
|
+
const input = usage.input ?? 0;
|
|
855
|
+
const output = usage.output ?? 0;
|
|
856
|
+
totalTokens += input + output;
|
|
857
|
+
const cost = usage.cost;
|
|
858
|
+
if (cost && typeof cost.total === "number") totalCost += cost.total;
|
|
859
|
+
}
|
|
860
|
+
const msgContent = msg.content;
|
|
861
|
+
if (role === "user") {
|
|
862
|
+
if (typeof msgContent === "string") {
|
|
863
|
+
lastUserMsg = msgContent.slice(0, 80);
|
|
864
|
+
} else if (Array.isArray(msgContent)) {
|
|
865
|
+
for (const c of msgContent) {
|
|
866
|
+
if (c.type === "text" && typeof c.text === "string") {
|
|
867
|
+
lastUserMsg = c.text.slice(0, 80);
|
|
868
|
+
break;
|
|
869
|
+
}
|
|
870
|
+
}
|
|
871
|
+
}
|
|
872
|
+
}
|
|
873
|
+
if (role === "assistant" && Array.isArray(msgContent)) {
|
|
874
|
+
for (const c of msgContent) {
|
|
875
|
+
if (c.type === "tool_use" || c.type === "toolCall") {
|
|
876
|
+
const toolName = c.name ?? "";
|
|
877
|
+
if (toolName && !toolCalls.includes(toolName)) toolCalls.push(toolName);
|
|
878
|
+
}
|
|
879
|
+
if (c.type === "text" && typeof c.text === "string" && c.text.length > 5) {
|
|
880
|
+
lastAssistantMsg = c.text.slice(0, 80);
|
|
881
|
+
}
|
|
882
|
+
}
|
|
883
|
+
}
|
|
884
|
+
if (role === "toolResult") {
|
|
885
|
+
if (typeof msgContent === "string" && /error|ENOENT|failed|exception/i.test(msgContent)) {
|
|
886
|
+
errorCount++;
|
|
887
|
+
} else if (Array.isArray(msgContent)) {
|
|
888
|
+
for (const c of msgContent) {
|
|
889
|
+
if (typeof c.text === "string" && /error|ENOENT|failed|exception/i.test(c.text)) {
|
|
890
|
+
errorCount++;
|
|
891
|
+
}
|
|
892
|
+
}
|
|
893
|
+
}
|
|
894
|
+
}
|
|
895
|
+
}
|
|
896
|
+
const parts = [];
|
|
897
|
+
if (model) {
|
|
898
|
+
const shortModel = model.includes("/") ? model.split("/").pop() : model;
|
|
899
|
+
parts.push(shortModel.slice(0, 20));
|
|
900
|
+
}
|
|
901
|
+
if (toolCalls.length > 0) {
|
|
902
|
+
const recent = toolCalls.slice(-3);
|
|
903
|
+
parts.push(`tools: ${recent.join(", ")}`);
|
|
904
|
+
}
|
|
905
|
+
if (totalCost > 0) {
|
|
906
|
+
parts.push(`$${totalCost.toFixed(3)}`);
|
|
907
|
+
} else if (totalTokens > 0) {
|
|
908
|
+
const k = (totalTokens / 1e3).toFixed(1);
|
|
909
|
+
parts.push(`${k}k tok`);
|
|
910
|
+
}
|
|
911
|
+
if (lastAssistantMsg && lastRole === "assistant") {
|
|
912
|
+
parts.push(lastAssistantMsg.slice(0, 40));
|
|
913
|
+
} else if (lastUserMsg && !parts.some((p) => p.startsWith("tools:"))) {
|
|
914
|
+
parts.push(`user: ${lastUserMsg.slice(0, 35)}`);
|
|
915
|
+
}
|
|
916
|
+
if (errorCount > 0) {
|
|
917
|
+
parts.push(`${errorCount} errors`);
|
|
918
|
+
}
|
|
919
|
+
const detail = parts.join(" | ") || `${lineCount} messages`;
|
|
920
|
+
const status = errorCount > lineCount / 4 ? "error" : lastRole === "assistant" ? "ok" : "running";
|
|
921
|
+
const ts = findTimestamp(lastObj) || file.mtime;
|
|
922
|
+
const sessionName = sessionId ? sessionId.slice(0, 8) : nameFromFile(file.filename);
|
|
923
|
+
return [{ id: String(name !== "unknown" ? name : sessionName), source: "session", status, lastActive: ts, detail, file: file.filename }];
|
|
818
924
|
} catch {
|
|
819
925
|
return [];
|
|
820
926
|
}
|
|
@@ -970,6 +1076,8 @@ function render(config) {
|
|
|
970
1076
|
function truncate(s, max) {
|
|
971
1077
|
return s.length > max ? s.slice(0, max - 1) + "\u2026" : s;
|
|
972
1078
|
}
|
|
1079
|
+
const termWidth = process.stdout.columns || 120;
|
|
1080
|
+
const detailWidth = Math.max(20, termWidth - 60);
|
|
973
1081
|
if (firstRender) {
|
|
974
1082
|
process.stdout.write("\x1B[2J");
|
|
975
1083
|
firstRender = false;
|
|
@@ -997,7 +1105,7 @@ function render(config) {
|
|
|
997
1105
|
if (g.children.length === 0) {
|
|
998
1106
|
const name = truncate(g.name, 26).padEnd(26);
|
|
999
1107
|
const st = statusText(g);
|
|
1000
|
-
const det = truncate(g.detail,
|
|
1108
|
+
const det = truncate(g.detail, detailWidth);
|
|
1001
1109
|
writeLine(L, ` ${icon} ${name} ${st.padEnd(20)} ${active.padEnd(20)} ${C.dim}${det}${C.reset}`);
|
|
1002
1110
|
lineCount++;
|
|
1003
1111
|
} else {
|
|
@@ -1015,7 +1123,7 @@ function render(config) {
|
|
|
1015
1123
|
const cIcon = statusIcon(child.status, Date.now() - child.lastActive < 3e5);
|
|
1016
1124
|
const cName = truncate(child.id, 22).padEnd(22);
|
|
1017
1125
|
const cActive = `${C.dim}${timeStr(child.lastActive)}${C.reset}`;
|
|
1018
|
-
const cDet = truncate(child.detail,
|
|
1126
|
+
const cDet = truncate(child.detail, detailWidth - 5);
|
|
1019
1127
|
writeLine(L, ` ${C.dim}${connector}${C.reset} ${cIcon} ${cName} ${cActive.padEnd(20)} ${C.dim}${cDet}${C.reset}`);
|
|
1020
1128
|
lineCount++;
|
|
1021
1129
|
}
|
|
@@ -1057,7 +1165,7 @@ function render(config) {
|
|
|
1057
1165
|
const agent = truncate(r.id, 26).padEnd(26);
|
|
1058
1166
|
const age = Math.floor((Date.now() - r.lastActive) / 1e3);
|
|
1059
1167
|
const ageStr = age < 60 ? age + "s ago" : age < 3600 ? Math.floor(age / 60) + "m ago" : Math.floor(age / 3600) + "h ago";
|
|
1060
|
-
const det = truncate(r.detail,
|
|
1168
|
+
const det = truncate(r.detail, detailWidth);
|
|
1061
1169
|
writeLine(L, ` ${icon} ${agent} ${C.dim}${t} ${ageStr.padStart(8)}${C.reset} ${C.dim}${det}${C.reset}`);
|
|
1062
1170
|
}
|
|
1063
1171
|
}
|
package/dist/cli.js
CHANGED
package/dist/index.cjs
CHANGED
|
@@ -914,14 +914,120 @@ function processJsonlFile(file) {
|
|
|
914
914
|
const content = (0, import_node_fs2.readFileSync)(file.path, "utf8").trim();
|
|
915
915
|
if (!content) return [];
|
|
916
916
|
const lines = content.split("\n");
|
|
917
|
-
const
|
|
918
|
-
const
|
|
919
|
-
const name =
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
917
|
+
const lineCount = lines.length;
|
|
918
|
+
const lastObj = JSON.parse(lines[lines.length - 1]);
|
|
919
|
+
const name = lastObj.jobId ?? lastObj.agentId ?? lastObj.name ?? lastObj.id ?? nameFromFile(file.filename);
|
|
920
|
+
if (lastObj.action !== void 0 || lastObj.jobId !== void 0) {
|
|
921
|
+
const status2 = findStatus(lastObj);
|
|
922
|
+
const ts2 = findTimestamp(lastObj) || file.mtime;
|
|
923
|
+
const action = lastObj.action;
|
|
924
|
+
const detail2 = action ? `${action} (${lineCount} entries)` : `${lineCount} entries`;
|
|
925
|
+
return [{ id: String(name), source: "session", status: status2, lastActive: ts2, detail: detail2, file: file.filename }];
|
|
926
|
+
}
|
|
927
|
+
const tail = lines.slice(Math.max(0, lineCount - 30));
|
|
928
|
+
let model = "";
|
|
929
|
+
let totalTokens = 0;
|
|
930
|
+
let totalCost = 0;
|
|
931
|
+
let toolCalls = [];
|
|
932
|
+
let lastUserMsg = "";
|
|
933
|
+
let lastAssistantMsg = "";
|
|
934
|
+
let errorCount = 0;
|
|
935
|
+
let lastRole = "";
|
|
936
|
+
let sessionId = "";
|
|
937
|
+
for (const line of tail) {
|
|
938
|
+
let entry;
|
|
939
|
+
try {
|
|
940
|
+
entry = JSON.parse(line);
|
|
941
|
+
} catch {
|
|
942
|
+
continue;
|
|
943
|
+
}
|
|
944
|
+
const entryType = entry.type;
|
|
945
|
+
if (entryType === "session") {
|
|
946
|
+
sessionId = entry.id ?? "";
|
|
947
|
+
continue;
|
|
948
|
+
}
|
|
949
|
+
if (entryType === "model_change") {
|
|
950
|
+
model = entry.modelId ?? "";
|
|
951
|
+
continue;
|
|
952
|
+
}
|
|
953
|
+
if (entryType !== "message") continue;
|
|
954
|
+
const msg = entry.message;
|
|
955
|
+
if (!msg) continue;
|
|
956
|
+
const role = msg.role;
|
|
957
|
+
lastRole = role;
|
|
958
|
+
if (msg.model && !model) model = msg.model;
|
|
959
|
+
const usage = msg.usage;
|
|
960
|
+
if (usage) {
|
|
961
|
+
const input = usage.input ?? 0;
|
|
962
|
+
const output = usage.output ?? 0;
|
|
963
|
+
totalTokens += input + output;
|
|
964
|
+
const cost = usage.cost;
|
|
965
|
+
if (cost && typeof cost.total === "number") totalCost += cost.total;
|
|
966
|
+
}
|
|
967
|
+
const msgContent = msg.content;
|
|
968
|
+
if (role === "user") {
|
|
969
|
+
if (typeof msgContent === "string") {
|
|
970
|
+
lastUserMsg = msgContent.slice(0, 80);
|
|
971
|
+
} else if (Array.isArray(msgContent)) {
|
|
972
|
+
for (const c of msgContent) {
|
|
973
|
+
if (c.type === "text" && typeof c.text === "string") {
|
|
974
|
+
lastUserMsg = c.text.slice(0, 80);
|
|
975
|
+
break;
|
|
976
|
+
}
|
|
977
|
+
}
|
|
978
|
+
}
|
|
979
|
+
}
|
|
980
|
+
if (role === "assistant" && Array.isArray(msgContent)) {
|
|
981
|
+
for (const c of msgContent) {
|
|
982
|
+
if (c.type === "tool_use" || c.type === "toolCall") {
|
|
983
|
+
const toolName = c.name ?? "";
|
|
984
|
+
if (toolName && !toolCalls.includes(toolName)) toolCalls.push(toolName);
|
|
985
|
+
}
|
|
986
|
+
if (c.type === "text" && typeof c.text === "string" && c.text.length > 5) {
|
|
987
|
+
lastAssistantMsg = c.text.slice(0, 80);
|
|
988
|
+
}
|
|
989
|
+
}
|
|
990
|
+
}
|
|
991
|
+
if (role === "toolResult") {
|
|
992
|
+
if (typeof msgContent === "string" && /error|ENOENT|failed|exception/i.test(msgContent)) {
|
|
993
|
+
errorCount++;
|
|
994
|
+
} else if (Array.isArray(msgContent)) {
|
|
995
|
+
for (const c of msgContent) {
|
|
996
|
+
if (typeof c.text === "string" && /error|ENOENT|failed|exception/i.test(c.text)) {
|
|
997
|
+
errorCount++;
|
|
998
|
+
}
|
|
999
|
+
}
|
|
1000
|
+
}
|
|
1001
|
+
}
|
|
1002
|
+
}
|
|
1003
|
+
const parts = [];
|
|
1004
|
+
if (model) {
|
|
1005
|
+
const shortModel = model.includes("/") ? model.split("/").pop() : model;
|
|
1006
|
+
parts.push(shortModel.slice(0, 20));
|
|
1007
|
+
}
|
|
1008
|
+
if (toolCalls.length > 0) {
|
|
1009
|
+
const recent = toolCalls.slice(-3);
|
|
1010
|
+
parts.push(`tools: ${recent.join(", ")}`);
|
|
1011
|
+
}
|
|
1012
|
+
if (totalCost > 0) {
|
|
1013
|
+
parts.push(`$${totalCost.toFixed(3)}`);
|
|
1014
|
+
} else if (totalTokens > 0) {
|
|
1015
|
+
const k = (totalTokens / 1e3).toFixed(1);
|
|
1016
|
+
parts.push(`${k}k tok`);
|
|
1017
|
+
}
|
|
1018
|
+
if (lastAssistantMsg && lastRole === "assistant") {
|
|
1019
|
+
parts.push(lastAssistantMsg.slice(0, 40));
|
|
1020
|
+
} else if (lastUserMsg && !parts.some((p) => p.startsWith("tools:"))) {
|
|
1021
|
+
parts.push(`user: ${lastUserMsg.slice(0, 35)}`);
|
|
1022
|
+
}
|
|
1023
|
+
if (errorCount > 0) {
|
|
1024
|
+
parts.push(`${errorCount} errors`);
|
|
1025
|
+
}
|
|
1026
|
+
const detail = parts.join(" | ") || `${lineCount} messages`;
|
|
1027
|
+
const status = errorCount > lineCount / 4 ? "error" : lastRole === "assistant" ? "ok" : "running";
|
|
1028
|
+
const ts = findTimestamp(lastObj) || file.mtime;
|
|
1029
|
+
const sessionName = sessionId ? sessionId.slice(0, 8) : nameFromFile(file.filename);
|
|
1030
|
+
return [{ id: String(name !== "unknown" ? name : sessionName), source: "session", status, lastActive: ts, detail, file: file.filename }];
|
|
925
1031
|
} catch {
|
|
926
1032
|
return [];
|
|
927
1033
|
}
|
|
@@ -1077,6 +1183,8 @@ function render(config) {
|
|
|
1077
1183
|
function truncate(s, max) {
|
|
1078
1184
|
return s.length > max ? s.slice(0, max - 1) + "\u2026" : s;
|
|
1079
1185
|
}
|
|
1186
|
+
const termWidth = process.stdout.columns || 120;
|
|
1187
|
+
const detailWidth = Math.max(20, termWidth - 60);
|
|
1080
1188
|
if (firstRender) {
|
|
1081
1189
|
process.stdout.write("\x1B[2J");
|
|
1082
1190
|
firstRender = false;
|
|
@@ -1104,7 +1212,7 @@ function render(config) {
|
|
|
1104
1212
|
if (g.children.length === 0) {
|
|
1105
1213
|
const name = truncate(g.name, 26).padEnd(26);
|
|
1106
1214
|
const st = statusText(g);
|
|
1107
|
-
const det = truncate(g.detail,
|
|
1215
|
+
const det = truncate(g.detail, detailWidth);
|
|
1108
1216
|
writeLine(L, ` ${icon} ${name} ${st.padEnd(20)} ${active.padEnd(20)} ${C.dim}${det}${C.reset}`);
|
|
1109
1217
|
lineCount++;
|
|
1110
1218
|
} else {
|
|
@@ -1122,7 +1230,7 @@ function render(config) {
|
|
|
1122
1230
|
const cIcon = statusIcon(child.status, Date.now() - child.lastActive < 3e5);
|
|
1123
1231
|
const cName = truncate(child.id, 22).padEnd(22);
|
|
1124
1232
|
const cActive = `${C.dim}${timeStr(child.lastActive)}${C.reset}`;
|
|
1125
|
-
const cDet = truncate(child.detail,
|
|
1233
|
+
const cDet = truncate(child.detail, detailWidth - 5);
|
|
1126
1234
|
writeLine(L, ` ${C.dim}${connector}${C.reset} ${cIcon} ${cName} ${cActive.padEnd(20)} ${C.dim}${cDet}${C.reset}`);
|
|
1127
1235
|
lineCount++;
|
|
1128
1236
|
}
|
|
@@ -1164,7 +1272,7 @@ function render(config) {
|
|
|
1164
1272
|
const agent = truncate(r.id, 26).padEnd(26);
|
|
1165
1273
|
const age = Math.floor((Date.now() - r.lastActive) / 1e3);
|
|
1166
1274
|
const ageStr = age < 60 ? age + "s ago" : age < 3600 ? Math.floor(age / 60) + "m ago" : Math.floor(age / 3600) + "h ago";
|
|
1167
|
-
const det = truncate(r.detail,
|
|
1275
|
+
const det = truncate(r.detail, detailWidth);
|
|
1168
1276
|
writeLine(L, ` ${icon} ${agent} ${C.dim}${t} ${ageStr.padStart(8)}${C.reset} ${C.dim}${det}${C.reset}`);
|
|
1169
1277
|
}
|
|
1170
1278
|
}
|
package/dist/index.js
CHANGED
package/package.json
CHANGED