@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/README.md +4 -0
- package/dist/cli.js +433 -46
- package/dist/index.cjs +423 -33
- package/dist/index.d.cts +60 -2
- package/dist/index.d.ts +60 -2
- package/dist/index.js +415 -28
- package/package.json +1 -1
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.
|
|
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: (
|
|
743
|
-
endpoint: (
|
|
744
|
-
userId: (
|
|
745
|
-
debug: process.env["RAINDROP_DEBUG"] === "true" ? true : (
|
|
746
|
-
enabled: (
|
|
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
|
|
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,
|
|
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,
|
|
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,
|
|
814
|
-
return (0,
|
|
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,
|
|
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
|
|
1053
|
+
await handleStopOrFailure(payload, getCurrentEventId(payload.session_id), config, baseProperties, eventShipper, traceShipper);
|
|
899
1054
|
break;
|
|
900
1055
|
case "StopFailure":
|
|
901
|
-
await
|
|
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:
|
|
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:
|
|
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
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
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
|
-
|
|
1085
|
-
|
|
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
|
-
|
|
1091
|
-
|
|
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.
|
|
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
|
|
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,
|
|
1118
|
-
const data = JSON.parse((0,
|
|
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,
|
|
1128
|
-
(0,
|
|
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
|
});
|