raindrop-ai 0.7.0 → 0.7.1

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.
@@ -1,12 +1,19 @@
1
1
  import {
2
+ APP_BRANCH,
3
+ APP_COMMIT_DIRTY,
4
+ APP_COMMIT_SHA,
2
5
  DEFAULT_REQUEST_TIMEOUT_MS,
6
+ EVAL_CORRELATION_ID_ATTRIBUTE,
3
7
  MAX_RETRY_DELAY_MS,
4
8
  POST_SHUTDOWN_TIMEOUT_MS,
5
9
  SHUTDOWN_DEADLINE_MS,
6
10
  authHintForKey,
7
11
  boundedClone,
8
12
  capText,
13
+ createAppGitContext,
14
+ currentEvalScope,
9
15
  currentReplayTraceDestination,
16
+ currentRoutingBinding,
10
17
  evalScopeAttributes,
11
18
  localDebuggerEnabled,
12
19
  mirrorPartialEventToLocalDebugger,
@@ -24,11 +31,13 @@ import {
24
31
  setDefaultMaxTextFieldChars,
25
32
  stringifyBounded,
26
33
  tracing,
34
+ validAppCommitSha,
35
+ withAppGitProperties,
27
36
  withEvalScope,
28
37
  withReplayTraceDestination,
29
38
  withRoutingContext,
30
39
  withTask
31
- } from "./chunk-OX6X4ZWQ.mjs";
40
+ } from "./chunk-SHH4SYVY.mjs";
32
41
  import {
33
42
  CapturedTraceSnapshotSchema,
34
43
  EvalCaseTracePairSchema,
@@ -775,10 +784,10 @@ var require_lodash = __commonJS({
775
784
  })();
776
785
  var ctxClearTimeout = context3.clearTimeout !== root.clearTimeout && context3.clearTimeout, ctxNow = Date2 && Date2.now !== root.Date.now && Date2.now, ctxSetTimeout = context3.setTimeout !== root.setTimeout && context3.setTimeout;
777
786
  var nativeCeil = Math2.ceil, nativeFloor = Math2.floor, nativeGetSymbols = Object2.getOwnPropertySymbols, nativeIsBuffer = Buffer2 ? Buffer2.isBuffer : undefined2, nativeIsFinite = context3.isFinite, nativeJoin = arrayProto.join, nativeKeys = overArg(Object2.keys, Object2), nativeMax = Math2.max, nativeMin = Math2.min, nativeNow = Date2.now, nativeParseInt = context3.parseInt, nativeRandom = Math2.random, nativeReverse = arrayProto.reverse;
778
- var DataView = getNative(context3, "DataView"), Map2 = getNative(context3, "Map"), Promise2 = getNative(context3, "Promise"), Set2 = getNative(context3, "Set"), WeakMap = getNative(context3, "WeakMap"), nativeCreate = getNative(Object2, "create");
779
- var metaMap = WeakMap && new WeakMap();
787
+ var DataView = getNative(context3, "DataView"), Map2 = getNative(context3, "Map"), Promise2 = getNative(context3, "Promise"), Set2 = getNative(context3, "Set"), WeakMap2 = getNative(context3, "WeakMap"), nativeCreate = getNative(Object2, "create");
788
+ var metaMap = WeakMap2 && new WeakMap2();
780
789
  var realNames = {};
781
- var dataViewCtorString = toSource(DataView), mapCtorString = toSource(Map2), promiseCtorString = toSource(Promise2), setCtorString = toSource(Set2), weakMapCtorString = toSource(WeakMap);
790
+ var dataViewCtorString = toSource(DataView), mapCtorString = toSource(Map2), promiseCtorString = toSource(Promise2), setCtorString = toSource(Set2), weakMapCtorString = toSource(WeakMap2);
782
791
  var symbolProto = Symbol2 ? Symbol2.prototype : undefined2, symbolValueOf = symbolProto ? symbolProto.valueOf : undefined2, symbolToString = symbolProto ? symbolProto.toString : undefined2;
783
792
  function lodash(value) {
784
793
  if (isObjectLike(value) && !isArray(value) && !(value instanceof LazyWrapper)) {
@@ -2845,7 +2854,7 @@ var require_lodash = __commonJS({
2845
2854
  return result2;
2846
2855
  };
2847
2856
  var getTag = baseGetTag;
2848
- if (DataView && getTag(new DataView(new ArrayBuffer(1))) != dataViewTag || Map2 && getTag(new Map2()) != mapTag || Promise2 && getTag(Promise2.resolve()) != promiseTag || Set2 && getTag(new Set2()) != setTag || WeakMap && getTag(new WeakMap()) != weakMapTag) {
2857
+ if (DataView && getTag(new DataView(new ArrayBuffer(1))) != dataViewTag || Map2 && getTag(new Map2()) != mapTag || Promise2 && getTag(Promise2.resolve()) != promiseTag || Set2 && getTag(new Set2()) != setTag || WeakMap2 && getTag(new WeakMap2()) != weakMapTag) {
2849
2858
  getTag = function(value) {
2850
2859
  var result2 = baseGetTag(value), Ctor = result2 == objectTag ? value.constructor : undefined2, ctorString = Ctor ? toSource(Ctor) : "";
2851
2860
  if (ctorString) {
@@ -5788,7 +5797,7 @@ var require_dist = __commonJS({
5788
5797
  }
5789
5798
  });
5790
5799
 
5791
- // ../schemas/dist/chunk-VQNKQ4ZC.js
5800
+ // ../schemas/dist/chunk-HA2X6666.js
5792
5801
  var __defProp = Object.defineProperty;
5793
5802
  var __export = (target, all) => {
5794
5803
  for (var name in all)
@@ -9828,6 +9837,14 @@ var coerce = {
9828
9837
  date: ((arg) => ZodDate.create({ ...arg, coerce: true }))
9829
9838
  };
9830
9839
  var NEVER = INVALID;
9840
+ var AppGitOptionsSchema = external_exports.object({
9841
+ commitSha: external_exports.string().nullable().optional(),
9842
+ commitDirty: external_exports.boolean().nullable().optional(),
9843
+ branch: external_exports.string().nullable().optional(),
9844
+ detectBranch: external_exports.boolean().optional(),
9845
+ sourceDirectory: external_exports.string().optional(),
9846
+ autoDetect: external_exports.boolean().optional()
9847
+ });
9831
9848
  var BaseAttachmentSchema = external_exports.object({
9832
9849
  attachment_id: external_exports.string().optional(),
9833
9850
  name: external_exports.string().default("").optional(),
@@ -10142,32 +10159,6 @@ function replayIngestEndpoint(value, trustedUrl) {
10142
10159
  return url.href;
10143
10160
  }
10144
10161
 
10145
- // src/replay/git.ts
10146
- import { execFileSync } from "child_process";
10147
- function readGitCommit() {
10148
- const sha = git(["rev-parse", "HEAD"]);
10149
- if (sha === null) return null;
10150
- const branch = git(["rev-parse", "--abbrev-ref", "HEAD"]);
10151
- const status = git(["status", "--porcelain"]);
10152
- if (status === null) return null;
10153
- return {
10154
- sha,
10155
- branch: branch === null || branch === "HEAD" ? null : branch,
10156
- dirty: status !== ""
10157
- };
10158
- }
10159
- function git(args) {
10160
- try {
10161
- return execFileSync("git", [...args], {
10162
- encoding: "utf8",
10163
- stdio: ["ignore", "pipe", "ignore"],
10164
- timeout: 2e3
10165
- }).trim();
10166
- } catch (e) {
10167
- return null;
10168
- }
10169
- }
10170
-
10171
10162
  // src/replay/index.ts
10172
10163
  var DEFAULT_QUERY_URL = "https://query.raindrop.ai";
10173
10164
  var DEFAULT_TRACE_WAIT_MS = 3e4;
@@ -10559,6 +10550,47 @@ var WireEvalCaseTracePairReadSchema = z3.discriminatedUnion("state", [
10559
10550
  reason: z3.string()
10560
10551
  })
10561
10552
  ]);
10553
+ var replayGitSnapshots = /* @__PURE__ */ new WeakMap();
10554
+ var replayPropertySnapshots = /* @__PURE__ */ new WeakMap();
10555
+ var replayOverrideSnapshots = /* @__PURE__ */ new WeakSet();
10556
+ function withReplayGit(snapshot, run) {
10557
+ var _a;
10558
+ return withRoutingContext({
10559
+ ...currentRoutingBinding(),
10560
+ appGit: (_a = replayPropertySnapshots.get(snapshot)) != null ? _a : snapshot,
10561
+ appGitSource: replayOverrideSnapshots.has(snapshot) ? "replay-override" : void 0
10562
+ }, run);
10563
+ }
10564
+ function captureReplayGit(client, options) {
10565
+ var _a, _b;
10566
+ try {
10567
+ if (options === void 0 && client.getAppGitSnapshot) {
10568
+ const properties = Object.freeze({ ...client.getAppGitSnapshot() });
10569
+ const snapshot2 = Object.freeze({ ...(_b = (_a = client.getReplayAppGitSnapshot) == null ? void 0 : _a.call(client)) != null ? _b : properties });
10570
+ replayPropertySnapshots.set(snapshot2, properties);
10571
+ return snapshot2;
10572
+ }
10573
+ const resolver = createAppGitContext(options, { allowLocalGit: false });
10574
+ const snapshot = resolver.snapshot();
10575
+ resolver.dispose();
10576
+ if (options && typeof options === "object") replayOverrideSnapshots.add(snapshot);
10577
+ return snapshot;
10578
+ } catch (e) {
10579
+ return {};
10580
+ }
10581
+ }
10582
+ function replayGitFields(snapshot) {
10583
+ const rawSha = snapshot[APP_COMMIT_SHA];
10584
+ const sha = typeof rawSha === "string" && validAppCommitSha(rawSha) ? rawSha.trim() : void 0;
10585
+ const dirty = snapshot[APP_COMMIT_DIRTY];
10586
+ const rawBranch = snapshot[APP_BRANCH];
10587
+ const branch = typeof rawBranch === "string" && rawBranch.length <= 1024 ? rawBranch.trim() : "";
10588
+ return {
10589
+ commit_sha: sha != null ? sha : null,
10590
+ commit_dirty: sha && typeof dirty === "boolean" ? dirty : null,
10591
+ commit_branch: branch.length > 0 && branch.length <= 400 ? branch : null
10592
+ };
10593
+ }
10562
10594
  function toReading(wire) {
10563
10595
  return {
10564
10596
  replayId: wire.replay.id,
@@ -10576,11 +10608,11 @@ function toReading(wire) {
10576
10608
  };
10577
10609
  }
10578
10610
  async function createReplay(client, options) {
10579
- var _a, _b, _c, _d;
10611
+ var _a;
10612
+ const gitSnapshot = captureReplayGit(client, options.appGit);
10580
10613
  const queryUrl = (_a = options.queryUrl) != null ? _a : DEFAULT_QUERY_URL;
10581
10614
  const manifest = typeof options.dataset === "string" ? await readEvalDataset(client, options.dataset, { queryUrl }) : validateEvalDatasetManifest(options.dataset);
10582
10615
  const rowIds = selectEvalDatasetRows(manifest, options.rowIds);
10583
- const commit = readGitCommit();
10584
10616
  const created = await queryApi({
10585
10617
  client,
10586
10618
  queryUrl,
@@ -10593,9 +10625,7 @@ async function createReplay(client, options) {
10593
10625
  dataset_version_id: manifest.version.id,
10594
10626
  dataset_fingerprint: manifest.version.fingerprint,
10595
10627
  request_key: randomUUID(),
10596
- commit_sha: (_b = commit == null ? void 0 : commit.sha) != null ? _b : null,
10597
- commit_branch: (_c = commit == null ? void 0 : commit.branch) != null ? _c : null,
10598
- commit_dirty: (_d = commit == null ? void 0 : commit.dirty) != null ? _d : null,
10628
+ ...replayGitFields(gitSnapshot),
10599
10629
  row_ids: rowIds
10600
10630
  }
10601
10631
  });
@@ -10607,6 +10637,7 @@ async function createReplay(client, options) {
10607
10637
  }
10608
10638
  };
10609
10639
  assertSelectedRows(handle, rowIds);
10640
+ replayGitSnapshots.set(handle, gitSnapshot);
10610
10641
  return handle;
10611
10642
  }
10612
10643
  function selectEvalDatasetRows(manifest, requestedRowIds) {
@@ -10655,15 +10686,19 @@ function toHandle(wire) {
10655
10686
  }
10656
10687
  async function claimReplay(client, replayId, options) {
10657
10688
  var _a;
10658
- return toHandle(
10689
+ const gitSnapshot = captureReplayGit(client, options == null ? void 0 : options.appGit);
10690
+ const handle = toHandle(
10659
10691
  await queryApi({
10660
10692
  client,
10661
10693
  queryUrl: (_a = options == null ? void 0 : options.queryUrl) != null ? _a : DEFAULT_QUERY_URL,
10662
10694
  path: `/v1/replays/${encodeURIComponent(replayId)}/claim`,
10663
10695
  method: "POST",
10664
- schema: WirePlanSchema
10696
+ schema: WirePlanSchema,
10697
+ body: replayGitFields(gitSnapshot)
10665
10698
  })
10666
10699
  );
10700
+ replayGitSnapshots.set(handle, gitSnapshot);
10701
+ return handle;
10667
10702
  }
10668
10703
  async function readReplay(client, replayId, options) {
10669
10704
  var _a;
@@ -10739,7 +10774,7 @@ async function runReplay(client, handle, options) {
10739
10774
  return (await runReplayRows(client, handle, options)).reading;
10740
10775
  }
10741
10776
  async function runReplayRows(client, handle, options) {
10742
- var _a, _b, _c, _d, _e, _f, _g;
10777
+ var _a, _b, _c, _d, _e, _f, _g, _h;
10743
10778
  if (!Number.isSafeInteger((_a = options.concurrency) != null ? _a : DEFAULT_CONCURRENCY) || ((_b = options.concurrency) != null ? _b : DEFAULT_CONCURRENCY) < 1) {
10744
10779
  throw new Error("Raindrop replay concurrency must be a positive safe integer");
10745
10780
  }
@@ -10760,7 +10795,9 @@ async function runReplayRows(client, handle, options) {
10760
10795
  body,
10761
10796
  maxRetries: MAX_REPLAY_REPORT_RETRIES
10762
10797
  });
10763
- await report({ type: "started" });
10798
+ const gitSnapshot = (_e = replayGitSnapshots.get(handle)) != null ? _e : captureReplayGit(client);
10799
+ replayGitSnapshots.set(handle, gitSnapshot);
10800
+ await report({ type: "started", ...replayGitFields(gitSnapshot) });
10764
10801
  const rows = [...handle.rows];
10765
10802
  const results = /* @__PURE__ */ new Map();
10766
10803
  const captures = /* @__PURE__ */ new Map();
@@ -10784,7 +10821,7 @@ async function runReplayRows(client, handle, options) {
10784
10821
  exportedSpanIds: spanIds,
10785
10822
  exportedTraceIds: traceIds
10786
10823
  };
10787
- const result = await context.with(
10824
+ const result = await withReplayGit(gitSnapshot, () => context.with(
10788
10825
  trace.deleteSpan(context.active()),
10789
10826
  () => withReplayTraceDestination(
10790
10827
  replayDestination,
@@ -10811,7 +10848,7 @@ async function runReplayRows(client, handle, options) {
10811
10848
  )
10812
10849
  )
10813
10850
  )
10814
- );
10851
+ ));
10815
10852
  results.set(row.id, { value: result });
10816
10853
  } catch (cause) {
10817
10854
  const error = describeError(cause);
@@ -10842,7 +10879,7 @@ async function runReplayRows(client, handle, options) {
10842
10879
  };
10843
10880
  await Promise.all(
10844
10881
  Array.from(
10845
- { length: Math.min((_e = options.concurrency) != null ? _e : DEFAULT_CONCURRENCY, rows.length) },
10882
+ { length: Math.min((_f = options.concurrency) != null ? _f : DEFAULT_CONCURRENCY, rows.length) },
10846
10883
  () => worker()
10847
10884
  )
10848
10885
  );
@@ -10868,7 +10905,7 @@ async function runReplayRows(client, handle, options) {
10868
10905
  client,
10869
10906
  queryUrl,
10870
10907
  replayId: handle.replayId,
10871
- deadlineAt: Date.now() + ((_f = options.traceWaitMs) != null ? _f : DEFAULT_TRACE_WAIT_MS)
10908
+ deadlineAt: Date.now() + ((_g = options.traceWaitMs) != null ? _g : DEFAULT_TRACE_WAIT_MS)
10872
10909
  });
10873
10910
  for (const row of settled.rows) {
10874
10911
  if (row.status !== "pending") continue;
@@ -10877,7 +10914,7 @@ async function runReplayRows(client, handle, options) {
10877
10914
  row_id: row.rowId,
10878
10915
  attempt: row.attempt,
10879
10916
  error: `no trace arrived for this row within ${Math.round(
10880
- ((_g = options.traceWaitMs) != null ? _g : DEFAULT_TRACE_WAIT_MS) / 1e3
10917
+ ((_h = options.traceWaitMs) != null ? _h : DEFAULT_TRACE_WAIT_MS) / 1e3
10881
10918
  )}s`
10882
10919
  });
10883
10920
  }
@@ -10951,7 +10988,7 @@ async function readEvalCaseTracePair(input, evidence, attempt) {
10951
10988
  });
10952
10989
  }
10953
10990
  async function createLocalEvalReplaySession(client, options) {
10954
- var _a;
10991
+ var _a, _b, _c;
10955
10992
  if (options.evaluators.length === 0) {
10956
10993
  throw new Error("Raindrop local eval replay requires at least one evaluator");
10957
10994
  }
@@ -10972,7 +11009,8 @@ async function createLocalEvalReplaySession(client, options) {
10972
11009
  ...handle,
10973
11010
  ingestUrl: replayIngestEndpoint(requireReplayIngestUrl(handle), options.replayIngestUrl)
10974
11011
  };
10975
- await reportReplay(client, queryUrl, handle.replayId, { type: "started" });
11012
+ replayGitSnapshots.set(validatedHandle, (_b = replayGitSnapshots.get(handle)) != null ? _b : {});
11013
+ await reportReplay(client, queryUrl, handle.replayId, { type: "started", ...replayGitFields((_c = replayGitSnapshots.get(handle)) != null ? _c : {}) });
10976
11014
  const parents = await Promise.all(
10977
11015
  options.evaluators.map(async (evaluator) => {
10978
11016
  const registered = await registerLocalEvaluator(client, evaluator, queryUrl);
@@ -11017,7 +11055,7 @@ var LocalEvalReplaySessionImpl = class {
11017
11055
  );
11018
11056
  }
11019
11057
  async run(input) {
11020
- var _a, _b, _c, _d;
11058
+ var _a, _b, _c, _d, _e;
11021
11059
  validateWait("traceWaitMs", (_a = input.traceWaitMs) != null ? _a : DEFAULT_TRACE_WAIT_MS, true);
11022
11060
  if (this.state !== "open") {
11023
11061
  throw new Error(`Raindrop replay ${this.replayId} is already finishing`);
@@ -11043,30 +11081,33 @@ var LocalEvalReplaySessionImpl = class {
11043
11081
  exportedTraceIds: traceIds
11044
11082
  };
11045
11083
  try {
11046
- result = await context.with(
11047
- trace.deleteSpan(context.active()),
11048
- () => withReplayTraceDestination(
11049
- replayDestination,
11050
- () => withEvalScope(
11051
- { correlationId },
11052
- () => withTask(
11053
- { name: "raindrop.replay.row", inputParameters: [row], traceContent: true },
11054
- () => {
11055
- var _a2;
11056
- const parent = (_a2 = trace.getSpan(context.active())) == null ? void 0 : _a2.spanContext();
11057
- if (!parent) return input.run(row);
11058
- return withReplayTraceDestination(
11059
- {
11060
- ...replayDestination,
11061
- parentSpanContext: {
11062
- traceIdB64: Buffer.from(parent.traceId, "hex").toString("base64"),
11063
- spanIdB64: Buffer.from(parent.spanId, "hex").toString("base64"),
11064
- eventId: parent.traceId
11065
- }
11066
- },
11067
- () => input.run(row)
11068
- );
11069
- }
11084
+ result = await withReplayGit(
11085
+ (_c = replayGitSnapshots.get(this.handle)) != null ? _c : {},
11086
+ () => context.with(
11087
+ trace.deleteSpan(context.active()),
11088
+ () => withReplayTraceDestination(
11089
+ replayDestination,
11090
+ () => withEvalScope(
11091
+ { correlationId },
11092
+ () => withTask(
11093
+ { name: "raindrop.replay.row", inputParameters: [row], traceContent: true },
11094
+ () => {
11095
+ var _a2;
11096
+ const parent = (_a2 = trace.getSpan(context.active())) == null ? void 0 : _a2.spanContext();
11097
+ if (!parent) return input.run(row);
11098
+ return withReplayTraceDestination(
11099
+ {
11100
+ ...replayDestination,
11101
+ parentSpanContext: {
11102
+ traceIdB64: Buffer.from(parent.traceId, "hex").toString("base64"),
11103
+ spanIdB64: Buffer.from(parent.spanId, "hex").toString("base64"),
11104
+ eventId: parent.traceId
11105
+ }
11106
+ },
11107
+ () => input.run(row)
11108
+ );
11109
+ }
11110
+ )
11070
11111
  )
11071
11112
  )
11072
11113
  )
@@ -11090,7 +11131,7 @@ var LocalEvalReplaySessionImpl = class {
11090
11131
  attempt: input.attempt,
11091
11132
  traceIds,
11092
11133
  spanIds,
11093
- waitMs: (_c = input.traceWaitMs) != null ? _c : DEFAULT_TRACE_WAIT_MS
11134
+ waitMs: (_d = input.traceWaitMs) != null ? _d : DEFAULT_TRACE_WAIT_MS
11094
11135
  });
11095
11136
  } catch (retentionCause) {
11096
11137
  throw failedTraceRetentionError(cause, retentionCause, row.id);
@@ -11115,7 +11156,7 @@ var LocalEvalReplaySessionImpl = class {
11115
11156
  replayId: this.replayId,
11116
11157
  datasetVersion: this.handle.datasetVersion,
11117
11158
  evidence: [evidence],
11118
- waitMs: (_d = input.traceWaitMs) != null ? _d : DEFAULT_TRACE_WAIT_MS,
11159
+ waitMs: (_e = input.traceWaitMs) != null ? _e : DEFAULT_TRACE_WAIT_MS,
11119
11160
  attempt: input.attempt
11120
11161
  });
11121
11162
  const captured = pairs.get(row.id);
@@ -13501,6 +13542,15 @@ function isPortableEvaluator(value) {
13501
13542
  }
13502
13543
 
13503
13544
  // src/index.ts
13545
+ function rawAppGitProperties(properties) {
13546
+ const result = {};
13547
+ for (const key of [APP_COMMIT_SHA, APP_COMMIT_DIRTY, APP_BRANCH]) {
13548
+ if (properties && Object.prototype.hasOwnProperty.call(properties, key)) {
13549
+ result[key] = properties[key];
13550
+ }
13551
+ }
13552
+ return result;
13553
+ }
13504
13554
  var MAX_INGEST_SIZE_BYTES = 1 * 1024 * 1024;
13505
13555
  var SELF_DIAGNOSTICS_TOOL_NAME_DEFAULT = "__raindrop_report";
13506
13556
  var SELF_DIAGNOSTICS_SOURCE_DEFAULT = "agent_reporting_tool";
@@ -13683,18 +13733,23 @@ var Raindrop = class {
13683
13733
  */
13684
13734
  this.hasShutdown = false;
13685
13735
  var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
13736
+ const writeKey = (_a = config.writeKey) != null ? _a : "";
13737
+ const disabled = (_b = config.disabled) != null ? _b : false;
13738
+ const localDebuggerUrlOpt = config.localWorkshopUrl === false ? null : config.localWorkshopUrl;
13739
+ const apiUrl = (_c = this.formatEndpoint(config.endpoint)) != null ? _c : `https://api.raindrop.ai/v1/`;
13740
+ const url = new URL(apiUrl);
13686
13741
  setDefaultMaxTextFieldChars(config.maxTextFieldChars);
13687
13742
  this.maxTextFieldChars = resolveMaxTextFieldChars(config.maxTextFieldChars);
13688
- this.writeKey = (_a = config.writeKey) != null ? _a : "";
13743
+ this.writeKey = writeKey;
13689
13744
  this.apiKey = config.apiKey;
13690
13745
  this.authHint = authHintForKey(this.writeKey);
13691
- this.localDebuggerUrlOpt = config.localWorkshopUrl === false ? null : config.localWorkshopUrl;
13746
+ this.localDebuggerUrlOpt = localDebuggerUrlOpt;
13692
13747
  this.awaitSpanFlushOpt = config.awaitSpanFlush;
13693
- this.apiUrl = (_b = this.formatEndpoint(config.endpoint)) != null ? _b : `https://api.raindrop.ai/v1/`;
13694
- this.bufferSize = (_c = config.bufferSize) != null ? _c : 50;
13695
- this.bufferTimeout = (_d = config.bufferTimeout) != null ? _d : 1e3;
13748
+ this.apiUrl = apiUrl;
13749
+ this.bufferSize = (_d = config.bufferSize) != null ? _d : 50;
13750
+ this.bufferTimeout = (_e = config.bufferTimeout) != null ? _e : 1e3;
13696
13751
  this.buffer = new Array();
13697
- this.disabled = (_e = config.disabled) != null ? _e : false;
13752
+ this.disabled = disabled;
13698
13753
  this.wizardSession = (_f = config.wizardSession) != null ? _f : null;
13699
13754
  this.debugLogs = (_g = config.debugLogs) != null ? _g : false;
13700
13755
  this.projectId = normalizeProjectId(config.projectId, {
@@ -13712,34 +13767,43 @@ var Raindrop = class {
13712
13767
  );
13713
13768
  }
13714
13769
  const useExternalOtel = (_j = (_i = config.useExternalOtel) != null ? _i : config.disableTracing) != null ? _j : false;
13715
- const url = new URL(this.apiUrl);
13716
13770
  const disableBatching = resolveDisableBatching(config.disableBatching, {
13717
13771
  isProduction: process.env.NODE_ENV === "production",
13718
13772
  isLocalDebugger: localDebuggerEnabled(this.localDebuggerUrlOpt)
13719
13773
  });
13720
- this._tracing = tracing(
13721
- this,
13722
- url.origin,
13723
- this.writeKey,
13724
- {
13725
- disableBatch: disableBatching,
13726
- disableBatching,
13727
- logLevel: this.debugLogs ? "debug" : "error",
13728
- // Pass through disabled state - tracer-core handles no-op exporter logic
13729
- tracingEnabled: !this.disabled,
13730
- useExternalOtel,
13731
- instrumentModules: config.instrumentModules,
13732
- bypassOtelForTools: config.bypassOtelForTools,
13733
- // Pass full API URL (with /v1/ path) for DirectTraceShipper.
13734
- // url.origin strips the path, which traceloop handles internally,
13735
- // but the direct shipper needs the full path to post to /v1/traces.
13736
- directEndpoint: this.apiUrl,
13737
- localDebuggerUrl: this.localDebuggerUrlOpt,
13738
- cloudEnabled: !this.localOnly,
13739
- projectId: this.projectId
13740
- },
13741
- this.debugLogs
13742
- );
13774
+ const hasDestination = !this.disabled && (this.writeKey.trim().length > 0 || localDebuggerEnabled(this.localDebuggerUrlOpt));
13775
+ this.appGitContext = createAppGitContext(this.disabled ? false : config.appGit, {
13776
+ captureLegacyReplayBranch: true,
13777
+ allowDiscovery: hasDestination
13778
+ });
13779
+ try {
13780
+ this._tracing = tracing(
13781
+ this,
13782
+ url.origin,
13783
+ this.writeKey,
13784
+ {
13785
+ disableBatch: disableBatching,
13786
+ disableBatching,
13787
+ logLevel: this.debugLogs ? "debug" : "error",
13788
+ // Pass through disabled state - tracer-core handles no-op exporter logic
13789
+ tracingEnabled: !this.disabled,
13790
+ useExternalOtel,
13791
+ instrumentModules: config.instrumentModules,
13792
+ bypassOtelForTools: config.bypassOtelForTools,
13793
+ // Pass full API URL (with /v1/ path) for DirectTraceShipper.
13794
+ // url.origin strips the path, which traceloop handles internally,
13795
+ // but the direct shipper needs the full path to post to /v1/traces.
13796
+ directEndpoint: this.apiUrl,
13797
+ localDebuggerUrl: this.localDebuggerUrlOpt,
13798
+ cloudEnabled: !this.localOnly,
13799
+ projectId: this.projectId
13800
+ },
13801
+ this.debugLogs
13802
+ );
13803
+ } catch (error) {
13804
+ this.appGitContext.dispose();
13805
+ throw error;
13806
+ }
13743
13807
  }
13744
13808
  get localOnly() {
13745
13809
  return !this.writeKey;
@@ -13780,7 +13844,29 @@ var Raindrop = class {
13780
13844
  * @returns The interaction object.
13781
13845
  */
13782
13846
  begin(traceContext) {
13783
- return this._tracing.begin(traceContext);
13847
+ var _a;
13848
+ const eventId = (_a = traceContext.eventId) != null ? _a : crypto.randomUUID();
13849
+ return this._tracing.begin({
13850
+ ...traceContext,
13851
+ eventId,
13852
+ properties: this.propertiesWithAppGit(traceContext.properties, eventId)
13853
+ });
13854
+ }
13855
+ /** @internal Snapshot only; this never waits for optional Git discovery. */
13856
+ getAppGitSnapshot(properties, eventId) {
13857
+ return this.appGitContext.forOperation(eventId, properties);
13858
+ }
13859
+ /** @internal Existing replay branch reporting; ordinary properties remain opt-in. */
13860
+ getReplayAppGitSnapshot() {
13861
+ return this.appGitContext.snapshotForReplay();
13862
+ }
13863
+ propertiesWithAppGit(properties, eventId) {
13864
+ const result = { ...properties };
13865
+ for (const [key, value] of Object.entries(this.getAppGitSnapshot(properties, eventId))) {
13866
+ if (Object.prototype.hasOwnProperty.call(result, key)) continue;
13867
+ if (value === null || typeof value === "string" || typeof value === "boolean") result[key] = value;
13868
+ }
13869
+ return result;
13784
13870
  }
13785
13871
  /**
13786
13872
  * Returns a tracer object that can be used to create spans and tools that aren't tied to any interaction.
@@ -13807,7 +13893,7 @@ var Raindrop = class {
13807
13893
  * ```
13808
13894
  */
13809
13895
  asCurrent(fn) {
13810
- return withRoutingContext({ projectId: this.projectId, authHint: this.authHint }, fn);
13896
+ return withRoutingContext({ projectId: this.projectId, authHint: this.authHint, appGit: this.appGitContext.snapshot() }, fn);
13811
13897
  }
13812
13898
  createSpanProcessor(processorOptions) {
13813
13899
  return this._tracing.createSpanProcessor(processorOptions);
@@ -14013,7 +14099,6 @@ var Raindrop = class {
14013
14099
  const destination = currentReplayTraceDestination();
14014
14100
  const cloudReplay = destination !== void 0 && destination.kind !== "workshop";
14015
14101
  const addEvent = (e) => {
14016
- var _a;
14017
14102
  const {
14018
14103
  eventId,
14019
14104
  userId,
@@ -14059,28 +14144,38 @@ var Raindrop = class {
14059
14144
  return;
14060
14145
  }
14061
14146
  const toSave = this.redactPii ? redactPII(parsed.data) : parsed.data;
14062
- toSave.properties = {
14063
- ...(_a = toSave.properties) != null ? _a : {},
14064
- ...this.wizardSession ? { "raindrop.wizardSession": this.wizardSession } : {},
14065
- // Last, so a caller-supplied property cannot shadow the replay row the
14066
- // event belongs to.
14067
- ...evalScopeAttributes(),
14068
- $context: this.context
14069
- };
14070
- const size = this.getSize(toSave);
14071
- if (size > MAX_INGEST_SIZE_BYTES) {
14072
- console.warn(
14073
- `[raindrop] Events larger than ${(MAX_INGEST_SIZE_BYTES / (1024 * 1024)).toFixed(2)} MB may have properties truncated - an event of size ${(size / (1024 * 1024)).toFixed(2)} MB was logged`
14074
- );
14075
- }
14076
- if (!cloudReplay) {
14077
- this.saveToBuffer({
14078
- type: "ai",
14079
- ...toSave
14080
- });
14147
+ const appGitSnapshot = this.getAppGitSnapshot(toSave.properties, customEventId);
14148
+ const eventProperties = withAppGitProperties(toSave.properties, appGitSnapshot);
14149
+ const usageProperties = withAppGitProperties(
14150
+ rawAppGitProperties(toSave.properties),
14151
+ appGitSnapshot
14152
+ );
14153
+ try {
14154
+ toSave.properties = {
14155
+ ...eventProperties,
14156
+ ...this.wizardSession ? { "raindrop.wizardSession": this.wizardSession } : {},
14157
+ // Last, so a caller-supplied property cannot shadow the replay row the
14158
+ // event belongs to.
14159
+ ...evalScopeAttributes(),
14160
+ $context: this.context
14161
+ };
14162
+ const size = this.getSize(toSave);
14163
+ if (size > MAX_INGEST_SIZE_BYTES) {
14164
+ console.warn(
14165
+ `[raindrop] Events larger than ${(MAX_INGEST_SIZE_BYTES / (1024 * 1024)).toFixed(2)} MB may have properties truncated - an event of size ${(size / (1024 * 1024)).toFixed(2)} MB was logged`
14166
+ );
14167
+ }
14168
+ if (!cloudReplay) {
14169
+ this.saveToBuffer({
14170
+ type: "ai",
14171
+ ...toSave
14172
+ });
14173
+ }
14174
+ this._recordModelUsage(customEventId, model, usage, usageProperties, appGitSnapshot);
14175
+ return customEventId;
14176
+ } finally {
14177
+ this.appGitContext.finishOperation(customEventId);
14081
14178
  }
14082
- this._recordModelUsage(customEventId, model, usage);
14083
- return customEventId;
14084
14179
  };
14085
14180
  if (Array.isArray(event)) {
14086
14181
  return event.map(addEvent);
@@ -14395,6 +14490,7 @@ var Raindrop = class {
14395
14490
  return Promise.resolve();
14396
14491
  }
14397
14492
  const { eventId, isPending, ...rest } = event;
14493
+ rest.properties = this.propertiesWithAppGit(rest.properties, eventId);
14398
14494
  if (!eventId) {
14399
14495
  console.warn("[raindrop] trackAiPartial requires an eventId.");
14400
14496
  return Promise.resolve();
@@ -14406,6 +14502,7 @@ var Raindrop = class {
14406
14502
  if (replayOnly) {
14407
14503
  if (isPending === false) {
14408
14504
  this.partialEventBuffer.delete(eventId);
14505
+ this.appGitContext.finishOperation(eventId);
14409
14506
  } else if (!captured) {
14410
14507
  this.partialEventBuffer.set(eventId, {
14411
14508
  replayOnly: true
@@ -14510,6 +14607,7 @@ var Raindrop = class {
14510
14607
  });
14511
14608
  } else {
14512
14609
  this.partialEventBuffer.delete(eventId);
14610
+ this.appGitContext.finishOperation(eventId);
14513
14611
  }
14514
14612
  if (!accumulatedEvent) {
14515
14613
  if (this.debugLogs) {
@@ -14680,7 +14778,7 @@ var Raindrop = class {
14680
14778
  * Emit one model span carrying raw provider usage facts.
14681
14779
  * @internal
14682
14780
  */
14683
- _recordModelUsage(eventId, model, usage) {
14781
+ _recordModelUsage(eventId, model, usage, properties = {}, appGitSnapshot = this.getAppGitSnapshot(properties)) {
14684
14782
  if (usage === void 0) return;
14685
14783
  const parsed = AiTrackUsageSchema.safeParse(usage);
14686
14784
  if (!parsed.success) {
@@ -14696,7 +14794,9 @@ var Raindrop = class {
14696
14794
  this._tracing.recordModelUsage({
14697
14795
  eventId,
14698
14796
  model,
14699
- usage: parsed.data
14797
+ usage: parsed.data,
14798
+ appGitProperties: rawAppGitProperties(properties),
14799
+ appGitSnapshot
14700
14800
  });
14701
14801
  }
14702
14802
  /**
@@ -14728,6 +14828,7 @@ var Raindrop = class {
14728
14828
  return this.awaitSpanFlushOpt !== false;
14729
14829
  }
14730
14830
  async close() {
14831
+ this.appGitContext.dispose();
14731
14832
  this.hasShutdown = true;
14732
14833
  this.shutdownDeadlineAt = Date.now() + SHUTDOWN_DEADLINE_MS;
14733
14834
  try {
@@ -14792,6 +14893,9 @@ var Raindrop = class {
14792
14893
  }
14793
14894
  };
14794
14895
  var index_default = Raindrop;
14896
+ var EVAL_CORRELATION_ID_ATTRIBUTE2 = EVAL_CORRELATION_ID_ATTRIBUTE;
14897
+ var currentEvalScope2 = currentEvalScope;
14898
+ var withEvalScope2 = withEvalScope;
14795
14899
 
14796
14900
  export {
14797
14901
  DEFAULT_QUERY_URL,
@@ -14834,7 +14938,10 @@ export {
14834
14938
  MAX_INGEST_SIZE_BYTES,
14835
14939
  resolveDisableBatching,
14836
14940
  Raindrop,
14837
- index_default
14941
+ index_default,
14942
+ EVAL_CORRELATION_ID_ATTRIBUTE2 as EVAL_CORRELATION_ID_ATTRIBUTE,
14943
+ currentEvalScope2 as currentEvalScope,
14944
+ withEvalScope2 as withEvalScope
14838
14945
  };
14839
14946
  /*! Bundled license information:
14840
14947