agentflow-core 0.3.0 → 0.3.2

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.
@@ -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 lastLine = lines[lines.length - 1];
871
- const obj = JSON.parse(lastLine);
872
- const name = obj.jobId ?? obj.agentId ?? obj.name ?? obj.id ?? nameFromFile(file.filename);
873
- const status = findStatus(obj);
874
- const ts = findTimestamp(obj) || file.mtime;
875
- const action = obj.action;
876
- const detail = action ? `${action} (${lines.length} entries)` : `${lines.length} entries`;
877
- return [{ id: String(name), source: "session", status, lastActive: ts, detail, file: file.filename }];
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
  }
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 lastLine = lines[lines.length - 1];
811
- const obj = JSON.parse(lastLine);
812
- const name = obj.jobId ?? obj.agentId ?? obj.name ?? obj.id ?? nameFromFile(file.filename);
813
- const status = findStatus(obj);
814
- const ts = findTimestamp(obj) || file.mtime;
815
- const action = obj.action;
816
- const detail = action ? `${action} (${lines.length} entries)` : `${lines.length} entries`;
817
- return [{ id: String(name), source: "session", status, lastActive: ts, detail, file: file.filename }];
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
  }
package/dist/cli.js CHANGED
@@ -3,7 +3,7 @@ import {
3
3
  runTraced,
4
4
  startLive,
5
5
  startWatch
6
- } from "./chunk-NPH34CAL.js";
6
+ } from "./chunk-VVWZJ63D.js";
7
7
 
8
8
  // src/cli.ts
9
9
  import { basename } from "path";
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 lastLine = lines[lines.length - 1];
918
- const obj = JSON.parse(lastLine);
919
- const name = obj.jobId ?? obj.agentId ?? obj.name ?? obj.id ?? nameFromFile(file.filename);
920
- const status = findStatus(obj);
921
- const ts = findTimestamp(obj) || file.mtime;
922
- const action = obj.action;
923
- const detail = action ? `${action} (${lines.length} entries)` : `${lines.length} entries`;
924
- return [{ id: String(name), source: "session", status, lastActive: ts, detail, file: file.filename }];
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
  }
package/dist/index.js CHANGED
@@ -19,7 +19,7 @@ import {
19
19
  startLive,
20
20
  startWatch,
21
21
  stitchTrace
22
- } from "./chunk-NPH34CAL.js";
22
+ } from "./chunk-VVWZJ63D.js";
23
23
  export {
24
24
  createGraphBuilder,
25
25
  findWaitingOn,
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "agentflow-core",
3
- "version": "0.3.0",
4
- "description": "Universal execution tracing for AI agent systems",
3
+ "version": "0.3.2",
4
+ "description": "Monitor any AI agent system. Auto-detects failures, sends alerts. Zero config, zero dependencies.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
7
7
  "module": "./dist/index.js",
@@ -23,11 +23,32 @@
23
23
  "keywords": [
24
24
  "ai",
25
25
  "agent",
26
+ "monitoring",
27
+ "alerting",
28
+ "observability",
26
29
  "tracing",
27
30
  "execution-graph",
28
- "observability"
31
+ "ai-agent",
32
+ "llm",
33
+ "openai",
34
+ "anthropic",
35
+ "langchain",
36
+ "crewai",
37
+ "autogen",
38
+ "cron",
39
+ "watchdog",
40
+ "health-check"
29
41
  ],
30
42
  "license": "MIT",
43
+ "repository": {
44
+ "type": "git",
45
+ "url": "https://github.com/ClemenceChee/AgentFlow.git"
46
+ },
47
+ "homepage": "https://github.com/ClemenceChee/AgentFlow#readme",
48
+ "author": "Clemence Chee",
49
+ "engines": {
50
+ "node": ">=20"
51
+ },
31
52
  "bin": {
32
53
  "agentflow": "./dist/cli.js"
33
54
  }