@raindrop-ai/opencode-plugin 0.0.10 → 0.0.11

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/index.cjs CHANGED
@@ -66,7 +66,7 @@ function loadConfig(projectDirectory) {
66
66
  // package.json
67
67
  var package_default = {
68
68
  name: "@raindrop-ai/opencode-plugin",
69
- version: "0.0.10",
69
+ version: "0.0.11",
70
70
  description: "Raindrop observability plugin for OpenCode \u2014 automatic session/event/span tracing",
71
71
  type: "module",
72
72
  main: "dist/index.js",
@@ -919,6 +919,46 @@ function createSessionState(sessionId) {
919
919
  function callKey(sessionId, callId) {
920
920
  return `${sessionId}:${callId}`;
921
921
  }
922
+ function markTaskCallFinished(sessionID, callID) {
923
+ const running = runningTaskCallsBySession.get(sessionID);
924
+ if (!running) return;
925
+ running.delete(callID);
926
+ if (running.size === 0) runningTaskCallsBySession.delete(sessionID);
927
+ }
928
+ function endPendingToolSpanWithError(state, callID, tool, toolCallArgs, errorMessage, traceShipper) {
929
+ const startInfo = state.toolSpanStarts.get(callID);
930
+ if (!startInfo) return false;
931
+ state.toolSpanStarts.delete(callID);
932
+ const error = new Error(errorMessage);
933
+ const endAttrs = [
934
+ attrString("ai.toolCall.args", toolCallArgs),
935
+ attrString("error.message", errorMessage)
936
+ ];
937
+ if (startInfo.liveSpan) {
938
+ traceShipper.endSpan(startInfo.liveSpan, {
939
+ attributes: endAttrs,
940
+ error
941
+ });
942
+ } else {
943
+ const toolSpan = traceShipper.startSpan({
944
+ name: "ai.toolCall",
945
+ parent: startInfo.parent,
946
+ eventId: startInfo.eventId,
947
+ startTimeUnixNano: startInfo.startTimeUnixNano,
948
+ attributes: [
949
+ attrString("ai.operationId", "ai.toolCall"),
950
+ attrString("ai.toolCall.name", tool),
951
+ attrString("ai.toolCall.id", callID)
952
+ ]
953
+ });
954
+ traceShipper.endSpan(toolSpan, {
955
+ attributes: endAttrs,
956
+ error,
957
+ endTimeUnixNano: nowUnixNanoString()
958
+ });
959
+ }
960
+ return true;
961
+ }
922
962
  function getHostname() {
923
963
  var _a;
924
964
  try {
@@ -1003,13 +1043,13 @@ function createHooks(config, worktree, directory, eventShipper, traceShipper) {
1003
1043
  state.outputParts.set(messageId, partObj["text"]);
1004
1044
  } else if (partObj["type"] === "tool" && messageId) {
1005
1045
  const tool = partObj["tool"];
1046
+ const callID = partObj["callID"];
1047
+ const partState = partObj["state"];
1048
+ if (callID == null || callID === "")
1049
+ throw new Error("message.part.updated: part.callID is required for tool part");
1050
+ if (partState == null || typeof partState !== "object")
1051
+ throw new Error("message.part.updated: part.state is required for tool part");
1006
1052
  if (tool === "task") {
1007
- const callID = partObj["callID"];
1008
- const partState = partObj["state"];
1009
- if (callID == null || callID === "")
1010
- throw new Error("message.part.updated: part.callID is required for tool part");
1011
- if (partState == null || typeof partState !== "object")
1012
- throw new Error("message.part.updated: part.state is required for tool part");
1013
1053
  const metadata = partState["metadata"];
1014
1054
  const childSessionId = metadata != null && typeof metadata === "object" ? metadata["sessionId"] : void 0;
1015
1055
  if (childSessionId != null && childSessionId !== "") {
@@ -1024,6 +1064,24 @@ function createHooks(config, worktree, directory, eventShipper, traceShipper) {
1024
1064
  );
1025
1065
  }
1026
1066
  }
1067
+ const toolState = partState;
1068
+ if (toolState["status"] === "error") {
1069
+ const errorMessage = toolState["error"];
1070
+ if (typeof errorMessage !== "string" || errorMessage === "")
1071
+ throw new Error("message.part.updated: error tool state must have error string");
1072
+ const input = toolState["input"];
1073
+ const toolCallArgs = input === void 0 ? void 0 : typeof input === "string" ? input : JSON.stringify(input);
1074
+ if (endPendingToolSpanWithError(
1075
+ state,
1076
+ callID,
1077
+ tool,
1078
+ toolCallArgs,
1079
+ errorMessage,
1080
+ traceShipper
1081
+ ) && tool === "task") {
1082
+ markTaskCallFinished(partSessionID, callID);
1083
+ }
1084
+ }
1027
1085
  } else if (partObj["type"] === "reasoning" && typeof partObj["text"] === "string") {
1028
1086
  state.reasoningParts.set(messageId, partObj["text"]);
1029
1087
  }
@@ -1507,11 +1565,7 @@ type: ${errorName != null ? errorName : "UnknownError"}`;
1507
1565
  }
1508
1566
  }
1509
1567
  if (tool === "task") {
1510
- const running = runningTaskCallsBySession.get(sessionID);
1511
- if (running) {
1512
- running.delete(callID);
1513
- if (running.size === 0) runningTaskCallsBySession.delete(sessionID);
1514
- }
1568
+ markTaskCallFinished(sessionID, callID);
1515
1569
  }
1516
1570
  } catch (err) {
1517
1571
  console.log(
package/dist/index.js CHANGED
@@ -47,7 +47,7 @@ function loadConfig(projectDirectory) {
47
47
  // package.json
48
48
  var package_default = {
49
49
  name: "@raindrop-ai/opencode-plugin",
50
- version: "0.0.10",
50
+ version: "0.0.11",
51
51
  description: "Raindrop observability plugin for OpenCode \u2014 automatic session/event/span tracing",
52
52
  type: "module",
53
53
  main: "dist/index.js",
@@ -900,6 +900,46 @@ function createSessionState(sessionId) {
900
900
  function callKey(sessionId, callId) {
901
901
  return `${sessionId}:${callId}`;
902
902
  }
903
+ function markTaskCallFinished(sessionID, callID) {
904
+ const running = runningTaskCallsBySession.get(sessionID);
905
+ if (!running) return;
906
+ running.delete(callID);
907
+ if (running.size === 0) runningTaskCallsBySession.delete(sessionID);
908
+ }
909
+ function endPendingToolSpanWithError(state, callID, tool, toolCallArgs, errorMessage, traceShipper) {
910
+ const startInfo = state.toolSpanStarts.get(callID);
911
+ if (!startInfo) return false;
912
+ state.toolSpanStarts.delete(callID);
913
+ const error = new Error(errorMessage);
914
+ const endAttrs = [
915
+ attrString("ai.toolCall.args", toolCallArgs),
916
+ attrString("error.message", errorMessage)
917
+ ];
918
+ if (startInfo.liveSpan) {
919
+ traceShipper.endSpan(startInfo.liveSpan, {
920
+ attributes: endAttrs,
921
+ error
922
+ });
923
+ } else {
924
+ const toolSpan = traceShipper.startSpan({
925
+ name: "ai.toolCall",
926
+ parent: startInfo.parent,
927
+ eventId: startInfo.eventId,
928
+ startTimeUnixNano: startInfo.startTimeUnixNano,
929
+ attributes: [
930
+ attrString("ai.operationId", "ai.toolCall"),
931
+ attrString("ai.toolCall.name", tool),
932
+ attrString("ai.toolCall.id", callID)
933
+ ]
934
+ });
935
+ traceShipper.endSpan(toolSpan, {
936
+ attributes: endAttrs,
937
+ error,
938
+ endTimeUnixNano: nowUnixNanoString()
939
+ });
940
+ }
941
+ return true;
942
+ }
903
943
  function getHostname() {
904
944
  var _a;
905
945
  try {
@@ -984,13 +1024,13 @@ function createHooks(config, worktree, directory, eventShipper, traceShipper) {
984
1024
  state.outputParts.set(messageId, partObj["text"]);
985
1025
  } else if (partObj["type"] === "tool" && messageId) {
986
1026
  const tool = partObj["tool"];
1027
+ const callID = partObj["callID"];
1028
+ const partState = partObj["state"];
1029
+ if (callID == null || callID === "")
1030
+ throw new Error("message.part.updated: part.callID is required for tool part");
1031
+ if (partState == null || typeof partState !== "object")
1032
+ throw new Error("message.part.updated: part.state is required for tool part");
987
1033
  if (tool === "task") {
988
- const callID = partObj["callID"];
989
- const partState = partObj["state"];
990
- if (callID == null || callID === "")
991
- throw new Error("message.part.updated: part.callID is required for tool part");
992
- if (partState == null || typeof partState !== "object")
993
- throw new Error("message.part.updated: part.state is required for tool part");
994
1034
  const metadata = partState["metadata"];
995
1035
  const childSessionId = metadata != null && typeof metadata === "object" ? metadata["sessionId"] : void 0;
996
1036
  if (childSessionId != null && childSessionId !== "") {
@@ -1005,6 +1045,24 @@ function createHooks(config, worktree, directory, eventShipper, traceShipper) {
1005
1045
  );
1006
1046
  }
1007
1047
  }
1048
+ const toolState = partState;
1049
+ if (toolState["status"] === "error") {
1050
+ const errorMessage = toolState["error"];
1051
+ if (typeof errorMessage !== "string" || errorMessage === "")
1052
+ throw new Error("message.part.updated: error tool state must have error string");
1053
+ const input = toolState["input"];
1054
+ const toolCallArgs = input === void 0 ? void 0 : typeof input === "string" ? input : JSON.stringify(input);
1055
+ if (endPendingToolSpanWithError(
1056
+ state,
1057
+ callID,
1058
+ tool,
1059
+ toolCallArgs,
1060
+ errorMessage,
1061
+ traceShipper
1062
+ ) && tool === "task") {
1063
+ markTaskCallFinished(partSessionID, callID);
1064
+ }
1065
+ }
1008
1066
  } else if (partObj["type"] === "reasoning" && typeof partObj["text"] === "string") {
1009
1067
  state.reasoningParts.set(messageId, partObj["text"]);
1010
1068
  }
@@ -1488,11 +1546,7 @@ type: ${errorName != null ? errorName : "UnknownError"}`;
1488
1546
  }
1489
1547
  }
1490
1548
  if (tool === "task") {
1491
- const running = runningTaskCallsBySession.get(sessionID);
1492
- if (running) {
1493
- running.delete(callID);
1494
- if (running.size === 0) runningTaskCallsBySession.delete(sessionID);
1495
- }
1549
+ markTaskCallFinished(sessionID, callID);
1496
1550
  }
1497
1551
  } catch (err) {
1498
1552
  console.log(
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@raindrop-ai/opencode-plugin",
3
- "version": "0.0.10",
3
+ "version": "0.0.11",
4
4
  "description": "Raindrop observability plugin for OpenCode — automatic session/event/span tracing",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",