@raindrop-ai/claude-code 0.0.3 → 0.0.5

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
@@ -25,10 +25,13 @@ __export(src_exports, {
25
25
  PACKAGE_VERSION: () => PACKAGE_VERSION,
26
26
  TraceShipper: () => TraceShipper2,
27
27
  detectLocalDebugger: () => detectLocalDebugger,
28
+ extractAppendSystemPrompt: () => extractAppendSystemPrompt,
28
29
  getConfigPath: () => getConfigPath,
29
30
  loadConfig: () => loadConfig,
30
31
  mapHookToRaindrop: () => mapHookToRaindrop,
31
32
  mirrorEventToLocalDebugger: () => mirrorEventToLocalDebugger,
33
+ parseTranscript: () => parseTranscript,
34
+ transcriptToProperties: () => transcriptToProperties,
32
35
  updateConfig: () => updateConfig
33
36
  });
34
37
  module.exports = __toCommonJS(src_exports);
@@ -680,7 +683,7 @@ globalThis.RAINDROP_ASYNC_LOCAL_STORAGE = import_async_hooks.AsyncLocalStorage;
680
683
 
681
684
  // src/package-info.ts
682
685
  var PACKAGE_NAME = "@raindrop-ai/claude-code";
683
- var PACKAGE_VERSION = "0.0.1";
686
+ var PACKAGE_VERSION = "0.0.5";
684
687
 
685
688
  // src/shipper.ts
686
689
  var EventShipper2 = class extends EventShipper {
@@ -723,7 +726,7 @@ var import_node_os = require("os");
723
726
  var import_node_path = require("path");
724
727
  var CONFIG_PATH = (0, import_node_path.join)((0, import_node_os.homedir)(), ".config", "raindrop", "config.json");
725
728
  function loadConfig() {
726
- var _a, _b, _c, _d, _e, _f, _g, _h;
729
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
727
730
  let file = {};
728
731
  try {
729
732
  if ((0, import_node_fs.existsSync)(CONFIG_PATH)) {
@@ -738,12 +741,25 @@ function loadConfig() {
738
741
  return "unknown";
739
742
  }
740
743
  })();
744
+ let customProperties = (_a = file.custom_properties) != null ? _a : {};
745
+ const envProps = process.env["RAINDROP_PROPERTIES"];
746
+ if (envProps) {
747
+ try {
748
+ const parsed = JSON.parse(envProps);
749
+ if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
750
+ customProperties = { ...customProperties, ...parsed };
751
+ }
752
+ } catch (e) {
753
+ }
754
+ }
741
755
  return {
742
- writeKey: (_b = (_a = process.env["RAINDROP_WRITE_KEY"]) != null ? _a : file.write_key) != null ? _b : "",
743
- endpoint: (_d = (_c = process.env["RAINDROP_API_URL"]) != null ? _c : file.api_url) != null ? _d : "https://api.raindrop.ai/v1",
744
- userId: (_f = (_e = process.env["RAINDROP_USER_ID"]) != null ? _e : file.user_id) != null ? _f : systemUser,
745
- debug: process.env["RAINDROP_DEBUG"] === "true" ? true : (_g = file.debug) != null ? _g : false,
746
- enabled: (_h = file.enabled) != null ? _h : true
756
+ writeKey: (_c = (_b = process.env["RAINDROP_WRITE_KEY"]) != null ? _b : file.write_key) != null ? _c : "",
757
+ endpoint: (_e = (_d = process.env["RAINDROP_API_URL"]) != null ? _d : file.api_url) != null ? _e : "https://api.raindrop.ai/v1",
758
+ userId: (_g = (_f = process.env["RAINDROP_USER_ID"]) != null ? _f : file.user_id) != null ? _g : systemUser,
759
+ debug: process.env["RAINDROP_DEBUG"] === "true" ? true : (_h = file.debug) != null ? _h : false,
760
+ enabled: (_i = file.enabled) != null ? _i : true,
761
+ eventName: (_k = (_j = process.env["RAINDROP_EVENT_NAME"]) != null ? _j : file.event_name) != null ? _k : "claude_code_session",
762
+ customProperties
747
763
  };
748
764
  }
749
765
  function getConfigPath() {
@@ -763,10 +779,145 @@ function updateConfig(patch) {
763
779
  }
764
780
 
765
781
  // src/event-mapper.ts
766
- var import_node_fs2 = require("fs");
782
+ var import_node_fs3 = require("fs");
783
+ var import_node_child_process = require("child_process");
767
784
  var import_node_crypto = require("crypto");
768
785
  var import_node_os2 = require("os");
769
786
  var import_node_path2 = require("path");
787
+
788
+ // src/transcript.ts
789
+ var import_node_fs2 = require("fs");
790
+ function parseTranscript(transcriptPath) {
791
+ var _a, _b, _c, _d, _e;
792
+ try {
793
+ if (!(0, import_node_fs2.existsSync)(transcriptPath)) return void 0;
794
+ const content = (0, import_node_fs2.readFileSync)(transcriptPath, "utf-8");
795
+ const lines = content.split("\n").filter((l) => l.trim());
796
+ const summary = {
797
+ totalInputTokens: 0,
798
+ totalOutputTokens: 0,
799
+ totalCacheReadTokens: 0,
800
+ totalCacheCreationTokens: 0,
801
+ turnCount: 0,
802
+ toolsUsed: [],
803
+ hasThinking: false
804
+ };
805
+ const toolNames = /* @__PURE__ */ new Set();
806
+ let lastUsage;
807
+ for (const line of lines) {
808
+ let entry;
809
+ try {
810
+ entry = JSON.parse(line);
811
+ } catch (e) {
812
+ continue;
813
+ }
814
+ if (entry.type === "system" && entry.subtype === "turn_duration") {
815
+ const durationMs = entry["durationMs"];
816
+ if (typeof durationMs === "number") {
817
+ summary.totalDurationMs = ((_a = summary.totalDurationMs) != null ? _a : 0) + durationMs;
818
+ }
819
+ const version = entry["version"];
820
+ if (typeof version === "string") {
821
+ summary.codeVersion = version;
822
+ }
823
+ const branch = entry["gitBranch"];
824
+ if (typeof branch === "string") {
825
+ summary.gitBranch = branch;
826
+ }
827
+ continue;
828
+ }
829
+ if (entry.type !== "assistant") continue;
830
+ const msg = entry.message;
831
+ if (!msg) continue;
832
+ summary.turnCount++;
833
+ if (msg.model) {
834
+ summary.model = msg.model;
835
+ }
836
+ if (msg.stop_reason) {
837
+ summary.stopReason = msg.stop_reason;
838
+ }
839
+ const entryVersion = entry["version"];
840
+ if (typeof entryVersion === "string") {
841
+ summary.codeVersion = entryVersion;
842
+ }
843
+ const entryBranch = entry["gitBranch"];
844
+ if (typeof entryBranch === "string") {
845
+ summary.gitBranch = entryBranch;
846
+ }
847
+ if (msg.usage) {
848
+ const u = msg.usage;
849
+ summary.totalInputTokens += (_b = u.input_tokens) != null ? _b : 0;
850
+ summary.totalOutputTokens += (_c = u.output_tokens) != null ? _c : 0;
851
+ summary.totalCacheReadTokens += (_d = u.cache_read_input_tokens) != null ? _d : 0;
852
+ summary.totalCacheCreationTokens += (_e = u.cache_creation_input_tokens) != null ? _e : 0;
853
+ if (u.service_tier) {
854
+ summary.serviceTier = u.service_tier;
855
+ }
856
+ lastUsage = u;
857
+ }
858
+ if (Array.isArray(msg.content)) {
859
+ for (const block of msg.content) {
860
+ if (block.type === "tool_use" && block.name) {
861
+ toolNames.add(block.name);
862
+ }
863
+ if (block.type === "thinking") {
864
+ summary.hasThinking = true;
865
+ }
866
+ }
867
+ }
868
+ }
869
+ if (lastUsage) {
870
+ summary.lastTurnInputTokens = lastUsage.input_tokens;
871
+ summary.lastTurnOutputTokens = lastUsage.output_tokens;
872
+ summary.lastTurnCacheReadTokens = lastUsage.cache_read_input_tokens;
873
+ }
874
+ summary.toolsUsed = [...toolNames].sort();
875
+ return summary;
876
+ } catch (e) {
877
+ return void 0;
878
+ }
879
+ }
880
+ function transcriptToProperties(summary) {
881
+ var _a, _b;
882
+ const props = {};
883
+ props["ai.usage.prompt_tokens"] = (_a = summary.lastTurnInputTokens) != null ? _a : summary.totalInputTokens;
884
+ props["ai.usage.completion_tokens"] = (_b = summary.lastTurnOutputTokens) != null ? _b : summary.totalOutputTokens;
885
+ if (summary.lastTurnCacheReadTokens !== void 0) {
886
+ props["ai.usage.cache_read_tokens"] = summary.lastTurnCacheReadTokens;
887
+ }
888
+ props["ai.usage.session_total.prompt_tokens"] = summary.totalInputTokens;
889
+ props["ai.usage.session_total.completion_tokens"] = summary.totalOutputTokens;
890
+ props["ai.usage.session_total.cache_read_tokens"] = summary.totalCacheReadTokens;
891
+ props["ai.usage.session_total.cache_creation_tokens"] = summary.totalCacheCreationTokens;
892
+ if (summary.model) {
893
+ props["ai.model"] = summary.model;
894
+ }
895
+ if (summary.serviceTier) {
896
+ props["ai.service_tier"] = summary.serviceTier;
897
+ }
898
+ if (summary.stopReason) {
899
+ props["ai.stop_reason"] = summary.stopReason;
900
+ }
901
+ if (summary.toolsUsed.length > 0) {
902
+ props["ai.tools_used"] = summary.toolsUsed.join(", ");
903
+ }
904
+ props["ai.turn_count"] = summary.turnCount;
905
+ if (summary.totalDurationMs !== void 0) {
906
+ props["ai.duration_ms"] = summary.totalDurationMs;
907
+ }
908
+ if (summary.codeVersion) {
909
+ props["claude_code.version"] = summary.codeVersion;
910
+ }
911
+ if (summary.gitBranch) {
912
+ props["git.branch"] = summary.gitBranch;
913
+ }
914
+ if (summary.hasThinking) {
915
+ props["ai.has_thinking"] = true;
916
+ }
917
+ return props;
918
+ }
919
+
920
+ // src/event-mapper.ts
770
921
  var MAX_ATTR_LENGTH = 32768;
771
922
  function truncate(value) {
772
923
  if (value === void 0) return void 0;
@@ -785,7 +936,7 @@ function safeStringify(value) {
785
936
  var STATE_DIR = (0, import_node_path2.join)((0, import_node_os2.tmpdir)(), "raindrop-claude-code");
786
937
  function ensureStateDir() {
787
938
  try {
788
- (0, import_node_fs2.mkdirSync)(STATE_DIR, { recursive: true });
939
+ (0, import_node_fs3.mkdirSync)(STATE_DIR, { recursive: true });
789
940
  } catch (e) {
790
941
  }
791
942
  }
@@ -803,22 +954,22 @@ function statePath(key) {
803
954
  function writeState(key, value) {
804
955
  try {
805
956
  ensureStateDir();
806
- (0, import_node_fs2.writeFileSync)(statePath(key), value, "utf-8");
957
+ (0, import_node_fs3.writeFileSync)(statePath(key), value, "utf-8");
807
958
  } catch (e) {
808
959
  }
809
960
  }
810
961
  function readState(key) {
811
962
  try {
812
963
  const filePath = statePath(key);
813
- if (!(0, import_node_fs2.existsSync)(filePath)) return void 0;
814
- return (0, import_node_fs2.readFileSync)(filePath, "utf-8");
964
+ if (!(0, import_node_fs3.existsSync)(filePath)) return void 0;
965
+ return (0, import_node_fs3.readFileSync)(filePath, "utf-8");
815
966
  } catch (e) {
816
967
  return void 0;
817
968
  }
818
969
  }
819
970
  function deleteState(key) {
820
971
  try {
821
- (0, import_node_fs2.unlinkSync)(statePath(key));
972
+ (0, import_node_fs3.unlinkSync)(statePath(key));
822
973
  } catch (e) {
823
974
  }
824
975
  }
@@ -872,15 +1023,19 @@ async function mapHookToRaindrop(payload, config, eventShipper, traceShipper) {
872
1023
  var _a;
873
1024
  const convoId = payload.session_id;
874
1025
  const baseProperties = {
1026
+ ...config.customProperties,
875
1027
  cwd: payload.cwd,
876
1028
  permission_mode: payload.permission_mode,
877
1029
  plugin_version: PACKAGE_VERSION,
1030
+ sdk: PACKAGE_NAME,
1031
+ sdk_version: PACKAGE_VERSION,
878
1032
  ...payload.agent_id ? { agent_id: payload.agent_id } : {},
879
1033
  ...payload.agent_type ? { agent_type: payload.agent_type } : {}
880
1034
  };
881
1035
  switch (payload.hook_event_name) {
882
1036
  case "SessionStart":
883
1037
  writeState(`model_${payload.session_id}`, (_a = payload.model) != null ? _a : "");
1038
+ tryCaptureAppendSystemPrompt(payload.session_id);
884
1039
  break;
885
1040
  case "UserPromptSubmit":
886
1041
  await handleUserPromptSubmit(payload, convoId, config, baseProperties, eventShipper, traceShipper);
@@ -895,10 +1050,13 @@ async function mapHookToRaindrop(payload, config, eventShipper, traceShipper) {
895
1050
  handlePostToolUseFailure(payload, getCurrentEventId(payload.session_id), traceShipper);
896
1051
  break;
897
1052
  case "Stop":
898
- await handleStop(payload, getCurrentEventId(payload.session_id), config, baseProperties, eventShipper);
1053
+ await handleStopOrFailure(payload, getCurrentEventId(payload.session_id), config, baseProperties, eventShipper, traceShipper);
899
1054
  break;
900
1055
  case "StopFailure":
901
- await handleStopFailure(payload, getCurrentEventId(payload.session_id), config, baseProperties, eventShipper);
1056
+ await handleStopOrFailure(payload, getCurrentEventId(payload.session_id), config, baseProperties, eventShipper, traceShipper, {
1057
+ error: payload.error,
1058
+ error_details: payload.error_details
1059
+ });
902
1060
  break;
903
1061
  case "SubagentStart":
904
1062
  handleSubagentStart(payload, getCurrentEventId(payload.session_id), traceShipper);
@@ -909,6 +1067,9 @@ async function mapHookToRaindrop(payload, config, eventShipper, traceShipper) {
909
1067
  case "PermissionDenied":
910
1068
  handlePermissionDenied(payload, getCurrentEventId(payload.session_id), traceShipper);
911
1069
  break;
1070
+ case "InstructionsLoaded":
1071
+ handleInstructionsLoaded(payload);
1072
+ break;
912
1073
  case "PostCompact":
913
1074
  await handlePostCompact(payload, getCurrentEventId(payload.session_id), config, baseProperties, eventShipper);
914
1075
  break;
@@ -917,6 +1078,8 @@ async function mapHookToRaindrop(payload, config, eventShipper, traceShipper) {
917
1078
  deleteState(turnEventKey(payload.session_id));
918
1079
  deleteState(rootSpanKey(payload.session_id));
919
1080
  deleteState(`model_${payload.session_id}`);
1081
+ deleteState(appendSystemPromptKey(payload.session_id));
1082
+ cleanupInstructions(payload.session_id);
920
1083
  break;
921
1084
  default:
922
1085
  if (config.debug) {
@@ -946,7 +1109,7 @@ async function handleUserPromptSubmit(payload, convoId, config, properties, even
946
1109
  isPending: true,
947
1110
  userId: config.userId,
948
1111
  convoId,
949
- eventName: "claude_code_session",
1112
+ eventName: config.eventName,
950
1113
  input: payload.prompt,
951
1114
  model,
952
1115
  properties
@@ -1066,7 +1229,7 @@ async function handlePostCompact(payload, eventId, config, properties, eventShip
1066
1229
  isPending: true,
1067
1230
  userId: config.userId,
1068
1231
  convoId: payload.session_id,
1069
- eventName: "claude_code_session",
1232
+ eventName: config.eventName,
1070
1233
  properties: {
1071
1234
  ...properties,
1072
1235
  compaction_trigger: payload.trigger,
@@ -1074,27 +1237,251 @@ async function handlePostCompact(payload, eventId, config, properties, eventShip
1074
1237
  }
1075
1238
  });
1076
1239
  }
1077
- async function handleStop(payload, eventId, config, properties, eventShipper) {
1078
- await eventShipper.finish(eventId, {
1079
- userId: config.userId,
1080
- output: payload.last_assistant_message,
1081
- properties
1082
- });
1240
+ function handleInstructionsLoaded(payload) {
1241
+ var _a;
1242
+ if (!payload.file_path || !payload.session_id) return;
1243
+ try {
1244
+ if ((0, import_node_fs3.existsSync)(payload.file_path)) {
1245
+ const content = (0, import_node_fs3.readFileSync)(payload.file_path, "utf-8");
1246
+ const MAX_INSTRUCTIONS_LENGTH = 8192;
1247
+ const truncated = content.length > MAX_INSTRUCTIONS_LENGTH ? content.slice(0, MAX_INSTRUCTIONS_LENGTH) + "\n...[truncated]" : content;
1248
+ const fileKey = safeKey(payload.file_path);
1249
+ const header = `# ${(_a = payload.memory_type) != null ? _a : "instructions"}: ${payload.file_path}
1250
+ `;
1251
+ writeState(
1252
+ `instr_${payload.session_id}_${fileKey}`,
1253
+ header + truncated
1254
+ );
1255
+ }
1256
+ } catch (e) {
1257
+ }
1258
+ }
1259
+ function gatherInstructions(sessionId) {
1260
+ try {
1261
+ if (!(0, import_node_fs3.existsSync)(STATE_DIR)) return void 0;
1262
+ const prefix = safeKey(`instr_${sessionId}_`);
1263
+ const files = (0, import_node_fs3.readdirSync)(STATE_DIR).filter((f) => f.startsWith(prefix));
1264
+ if (files.length === 0) return void 0;
1265
+ const parts = [];
1266
+ for (const file of files.sort()) {
1267
+ try {
1268
+ parts.push((0, import_node_fs3.readFileSync)((0, import_node_path2.join)(STATE_DIR, file), "utf-8"));
1269
+ } catch (e) {
1270
+ continue;
1271
+ }
1272
+ }
1273
+ return parts.length > 0 ? parts.join("\n\n---\n\n") : void 0;
1274
+ } catch (e) {
1275
+ return void 0;
1276
+ }
1277
+ }
1278
+ function cleanupInstructions(sessionId) {
1279
+ try {
1280
+ if (!(0, import_node_fs3.existsSync)(STATE_DIR)) return;
1281
+ const prefix = safeKey(`instr_${sessionId}_`);
1282
+ for (const file of (0, import_node_fs3.readdirSync)(STATE_DIR).filter((f) => f.startsWith(prefix))) {
1283
+ try {
1284
+ (0, import_node_fs3.unlinkSync)((0, import_node_path2.join)(STATE_DIR, file));
1285
+ } catch (e) {
1286
+ }
1287
+ }
1288
+ } catch (e) {
1289
+ }
1290
+ }
1291
+ var APPEND_FLAG = "--append-system-prompt";
1292
+ var APPEND_FILE_FLAG = "--append-system-prompt-file";
1293
+ var MAX_ANCESTOR_DEPTH = 15;
1294
+ var PS_TIMEOUT_MS = 3e3;
1295
+ function appendSystemPromptKey(sessionId) {
1296
+ return `append_sysprompt_${sessionId}`;
1083
1297
  }
1084
- async function handleStopFailure(payload, eventId, config, properties, eventShipper) {
1085
- await eventShipper.finish(eventId, {
1298
+ function tryCaptureAppendSystemPrompt(sessionId) {
1299
+ try {
1300
+ const content = readAncestorAppendSystemPrompt();
1301
+ if (content) {
1302
+ writeState(appendSystemPromptKey(sessionId), content);
1303
+ }
1304
+ } catch (e) {
1305
+ }
1306
+ }
1307
+ function readAncestorAppendSystemPrompt() {
1308
+ let pid;
1309
+ try {
1310
+ pid = process.ppid;
1311
+ } catch (e) {
1312
+ return void 0;
1313
+ }
1314
+ if (!pid || pid <= 1) return void 0;
1315
+ for (let depth = 0; depth < MAX_ANCESTOR_DEPTH && pid != null && pid > 1; depth++) {
1316
+ try {
1317
+ const args = getProcessArgs(pid);
1318
+ if (args && args.length > 0) {
1319
+ const content = extractAppendSystemPrompt(args);
1320
+ if (content) return content;
1321
+ }
1322
+ } catch (e) {
1323
+ }
1324
+ try {
1325
+ pid = getParentPid(pid);
1326
+ } catch (e) {
1327
+ break;
1328
+ }
1329
+ }
1330
+ return void 0;
1331
+ }
1332
+ function getProcessArgs(pid) {
1333
+ if (process.platform === "linux") {
1334
+ try {
1335
+ const raw = (0, import_node_fs3.readFileSync)(`/proc/${pid}/cmdline`, "utf-8");
1336
+ const args = raw.split("\0").filter(Boolean);
1337
+ return args.length > 0 ? args : void 0;
1338
+ } catch (e) {
1339
+ }
1340
+ }
1341
+ try {
1342
+ const output = (0, import_node_child_process.execSync)(`ps -ww -o args= -p ${pid}`, {
1343
+ encoding: "utf-8",
1344
+ timeout: PS_TIMEOUT_MS,
1345
+ stdio: ["ignore", "pipe", "ignore"]
1346
+ });
1347
+ const trimmed = output.trim();
1348
+ if (!trimmed) return void 0;
1349
+ return trimmed.split(/\s+/);
1350
+ } catch (e) {
1351
+ return void 0;
1352
+ }
1353
+ }
1354
+ function getParentPid(pid) {
1355
+ try {
1356
+ const output = (0, import_node_child_process.execSync)(`ps -o ppid= -p ${pid}`, {
1357
+ encoding: "utf-8",
1358
+ timeout: PS_TIMEOUT_MS,
1359
+ stdio: ["ignore", "pipe", "ignore"]
1360
+ });
1361
+ const ppid = parseInt(output.trim(), 10);
1362
+ return Number.isFinite(ppid) && ppid > 0 ? ppid : void 0;
1363
+ } catch (e) {
1364
+ return void 0;
1365
+ }
1366
+ }
1367
+ function extractAppendSystemPrompt(args) {
1368
+ const parts = [];
1369
+ for (let i = 0; i < args.length; i++) {
1370
+ const arg = args[i];
1371
+ try {
1372
+ if (arg === APPEND_FILE_FLAG && i + 1 < args.length) {
1373
+ const filePath = args[i + 1];
1374
+ i++;
1375
+ try {
1376
+ if ((0, import_node_fs3.existsSync)(filePath)) {
1377
+ parts.push((0, import_node_fs3.readFileSync)(filePath, "utf-8"));
1378
+ }
1379
+ } catch (e) {
1380
+ }
1381
+ continue;
1382
+ }
1383
+ if (arg.startsWith(APPEND_FILE_FLAG + "=")) {
1384
+ const filePath = arg.slice(APPEND_FILE_FLAG.length + 1);
1385
+ try {
1386
+ if (filePath && (0, import_node_fs3.existsSync)(filePath)) {
1387
+ parts.push((0, import_node_fs3.readFileSync)(filePath, "utf-8"));
1388
+ }
1389
+ } catch (e) {
1390
+ }
1391
+ continue;
1392
+ }
1393
+ if (arg === APPEND_FLAG && i + 1 < args.length) {
1394
+ const valueParts = [];
1395
+ for (let j = i + 1; j < args.length; j++) {
1396
+ if (args[j].startsWith("--")) break;
1397
+ valueParts.push(args[j]);
1398
+ i = j;
1399
+ }
1400
+ if (valueParts.length > 0) {
1401
+ parts.push(valueParts.join(" "));
1402
+ }
1403
+ continue;
1404
+ }
1405
+ if (arg.startsWith(APPEND_FLAG + "=") && !arg.startsWith(APPEND_FILE_FLAG)) {
1406
+ const value = arg.slice(APPEND_FLAG.length + 1);
1407
+ if (value) {
1408
+ parts.push(value);
1409
+ }
1410
+ continue;
1411
+ }
1412
+ } catch (e) {
1413
+ continue;
1414
+ }
1415
+ }
1416
+ return parts.length > 0 ? parts.join("\n") : void 0;
1417
+ }
1418
+ function readAppendSystemPrompt(sessionId) {
1419
+ try {
1420
+ return readState(appendSystemPromptKey(sessionId)) || void 0;
1421
+ } catch (e) {
1422
+ return void 0;
1423
+ }
1424
+ }
1425
+ function enrichFromTranscript(payload, eventId, traceShipper) {
1426
+ var _a, _b;
1427
+ if (!payload.transcript_path) {
1428
+ return { summary: void 0, props: {} };
1429
+ }
1430
+ try {
1431
+ const summary = parseTranscript(payload.transcript_path);
1432
+ if (!summary) return { summary: void 0, props: {} };
1433
+ const props = transcriptToProperties(summary);
1434
+ const spanInputTokens = (_a = summary.lastTurnInputTokens) != null ? _a : summary.totalInputTokens;
1435
+ const spanOutputTokens = (_b = summary.lastTurnOutputTokens) != null ? _b : summary.totalOutputTokens;
1436
+ if (summary.model && (spanInputTokens > 0 || spanOutputTokens > 0)) {
1437
+ const parent = getParentContext(payload);
1438
+ const now = nowUnixNanoString();
1439
+ traceShipper.createSpan({
1440
+ name: summary.model,
1441
+ eventId,
1442
+ parent,
1443
+ startTimeUnixNano: now,
1444
+ endTimeUnixNano: now,
1445
+ attributes: [
1446
+ attrString("ai.operationId", "generateText"),
1447
+ attrString("gen_ai.response.model", summary.model),
1448
+ attrString("gen_ai.system", "anthropic"),
1449
+ attrInt("gen_ai.usage.prompt_tokens", spanInputTokens),
1450
+ attrInt("gen_ai.usage.completion_tokens", spanOutputTokens),
1451
+ ...summary.lastTurnCacheReadTokens != null && summary.lastTurnCacheReadTokens > 0 ? [attrInt("gen_ai.usage.cache_read_tokens", summary.lastTurnCacheReadTokens)] : []
1452
+ ]
1453
+ });
1454
+ }
1455
+ return { summary, props };
1456
+ } catch (e) {
1457
+ return { summary: void 0, props: {} };
1458
+ }
1459
+ }
1460
+ async function handleStopOrFailure(payload, eventId, config, properties, eventShipper, traceShipper, extraProperties) {
1461
+ const { summary, props: transcriptProps } = enrichFromTranscript(payload, eventId, traceShipper);
1462
+ const instructions = gatherInstructions(payload.session_id);
1463
+ const appendSysPrompt = readAppendSystemPrompt(payload.session_id);
1464
+ await eventShipper.patch(eventId, {
1465
+ isPending: false,
1086
1466
  userId: config.userId,
1467
+ convoId: payload.session_id,
1468
+ eventName: config.eventName,
1087
1469
  output: payload.last_assistant_message,
1470
+ ...(summary == null ? void 0 : summary.model) ? { model: summary.model } : {},
1088
1471
  properties: {
1089
1472
  ...properties,
1090
- error: payload.error,
1091
- error_details: payload.error_details
1473
+ ...transcriptProps,
1474
+ ...instructions ? { system_instructions: truncate(instructions) } : {},
1475
+ ...appendSysPrompt ? { append_system_prompt: truncate(appendSysPrompt) } : {},
1476
+ ...extraProperties
1092
1477
  }
1093
1478
  });
1094
1479
  }
1095
1480
  async function handleSessionEnd(payload, eventId, config, properties, eventShipper) {
1096
- await eventShipper.finish(eventId, {
1481
+ await eventShipper.patch(eventId, {
1482
+ isPending: false,
1097
1483
  userId: config.userId,
1484
+ eventName: config.eventName,
1098
1485
  properties: {
1099
1486
  ...properties,
1100
1487
  session_end_reason: payload.reason
@@ -1103,7 +1490,7 @@ async function handleSessionEnd(payload, eventId, config, properties, eventShipp
1103
1490
  }
1104
1491
 
1105
1492
  // src/local-debugger.ts
1106
- var import_node_fs3 = require("fs");
1493
+ var import_node_fs4 = require("fs");
1107
1494
  var import_node_os3 = require("os");
1108
1495
  var import_node_path3 = require("path");
1109
1496
  var DEFAULT_PORT = 5899;
@@ -1114,8 +1501,8 @@ var CACHE_FILE = (0, import_node_path3.join)(CACHE_DIR, "debugger_cache");
1114
1501
  var CACHE_TTL_MS = 5e3;
1115
1502
  function readCache() {
1116
1503
  try {
1117
- if (!(0, import_node_fs3.existsSync)(CACHE_FILE)) return void 0;
1118
- const data = JSON.parse((0, import_node_fs3.readFileSync)(CACHE_FILE, "utf-8"));
1504
+ if (!(0, import_node_fs4.existsSync)(CACHE_FILE)) return void 0;
1505
+ const data = JSON.parse((0, import_node_fs4.readFileSync)(CACHE_FILE, "utf-8"));
1119
1506
  if (Date.now() - data.ts > CACHE_TTL_MS) return void 0;
1120
1507
  return data;
1121
1508
  } catch (e) {
@@ -1124,8 +1511,8 @@ function readCache() {
1124
1511
  }
1125
1512
  function writeCache(url) {
1126
1513
  try {
1127
- (0, import_node_fs3.mkdirSync)(CACHE_DIR, { recursive: true });
1128
- (0, import_node_fs3.writeFileSync)(CACHE_FILE, JSON.stringify({ url, ts: Date.now() }), "utf-8");
1514
+ (0, import_node_fs4.mkdirSync)(CACHE_DIR, { recursive: true });
1515
+ (0, import_node_fs4.writeFileSync)(CACHE_FILE, JSON.stringify({ url, ts: Date.now() }), "utf-8");
1129
1516
  } catch (e) {
1130
1517
  }
1131
1518
  }
@@ -1189,9 +1576,12 @@ function mirrorEventToLocalDebugger(baseUrl, payload, debug) {
1189
1576
  PACKAGE_VERSION,
1190
1577
  TraceShipper,
1191
1578
  detectLocalDebugger,
1579
+ extractAppendSystemPrompt,
1192
1580
  getConfigPath,
1193
1581
  loadConfig,
1194
1582
  mapHookToRaindrop,
1195
1583
  mirrorEventToLocalDebugger,
1584
+ parseTranscript,
1585
+ transcriptToProperties,
1196
1586
  updateConfig
1197
1587
  });