@raindrop-ai/opencode-plugin 0.2.0 → 0.3.0

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
@@ -23,6 +23,7 @@ __export(index_exports, {
23
23
  default: () => plugin
24
24
  });
25
25
  module.exports = __toCommonJS(index_exports);
26
+ var import_plugin = require("@opencode-ai/plugin");
26
27
 
27
28
  // ../core/dist/chunk-BYBMRLZM.js
28
29
  var EVAL_CORRELATION_ID_ATTRIBUTE = "raindrop.eval_correlation_id";
@@ -2308,9 +2309,41 @@ function loadConfig(projectDirectory) {
2308
2309
  captureSystemPrompt: process.env["RAINDROP_CAPTURE_SYSTEM_PROMPT"] !== void 0 ? process.env["RAINDROP_CAPTURE_SYSTEM_PROMPT"] === "true" : (_h = merged.capture_system_prompt) != null ? _h : false,
2309
2310
  eventMetadata,
2310
2311
  localWorkshopUrl: resolveLocalWorkshopUrl(merged.local_workshop_url),
2311
- appGit: mapAppGit(merged.app_git)
2312
+ appGit: mapAppGit(merged.app_git),
2313
+ selfDiagnostics: mapSelfDiagnostics(merged.self_diagnostics)
2312
2314
  };
2313
2315
  }
2316
+ function isRecord(value) {
2317
+ return typeof value === "object" && value !== null && !Array.isArray(value);
2318
+ }
2319
+ function mapSelfDiagnostics(value) {
2320
+ const env = process.env["RAINDROP_SELF_DIAGNOSTICS"];
2321
+ const record = isRecord(value) ? value : {};
2322
+ const enabled = env !== void 0 ? env === "true" : typeof record["enabled"] === "boolean" ? record["enabled"] : void 0;
2323
+ const signals = mapSelfDiagnosticsSignals(record["signals"]);
2324
+ const options = {
2325
+ ...enabled !== void 0 ? { enabled } : {},
2326
+ ...signals ? { signals } : {},
2327
+ ...typeof record["guidance"] === "string" ? { guidance: record["guidance"] } : {},
2328
+ ...typeof record["tool_name"] === "string" ? { toolName: record["tool_name"] } : {}
2329
+ };
2330
+ return Object.keys(options).length > 0 ? options : void 0;
2331
+ }
2332
+ function mapSelfDiagnosticsSignals(value) {
2333
+ if (!isRecord(value)) return void 0;
2334
+ const out = {};
2335
+ for (const [key, entry] of Object.entries(value)) {
2336
+ if (!isRecord(entry)) continue;
2337
+ const definition = entry;
2338
+ if (typeof definition["description"] !== "string") continue;
2339
+ const sentiment = definition["sentiment"];
2340
+ out[key] = {
2341
+ description: definition["description"],
2342
+ ...sentiment === "POSITIVE" || sentiment === "NEGATIVE" ? { sentiment } : {}
2343
+ };
2344
+ }
2345
+ return Object.keys(out).length > 0 ? out : void 0;
2346
+ }
2314
2347
  function mapAppGit(value) {
2315
2348
  if (value === false) return false;
2316
2349
  if (value === null || typeof value !== "object" || Array.isArray(value)) return void 0;
@@ -2337,7 +2370,7 @@ function resolveLocalWorkshopUrl(fileValue) {
2337
2370
  // package.json
2338
2371
  var package_default = {
2339
2372
  name: "@raindrop-ai/opencode-plugin",
2340
- version: "0.2.0",
2373
+ version: "0.3.0",
2341
2374
  description: "Raindrop observability plugin for OpenCode \u2014 automatic session/event/span tracing",
2342
2375
  type: "module",
2343
2376
  main: "dist/index.js",
@@ -2426,6 +2459,167 @@ var package_default = {
2426
2459
  var PLUGIN_NAME = package_default.name;
2427
2460
  var PLUGIN_VERSION = package_default.version;
2428
2461
 
2462
+ // src/self-diagnostics.ts
2463
+ var SELF_DIAGNOSTICS_TOOL_NAME_DEFAULT = "__raindrop_report";
2464
+ var SELF_DIAGNOSTICS_SIGNALS_DEFAULT = {
2465
+ missing_context: {
2466
+ description: "You cannot complete the task because critical information, credentials, or access is missing and the user cannot provide it. Do NOT report this for normal clarifying questions \u2014 only when you are blocked.",
2467
+ sentiment: "NEGATIVE"
2468
+ },
2469
+ repeatedly_broken_tool: {
2470
+ description: "A tool has failed or not returned the expected response on multiple distinct attempts in this conversation, preventing task completion. A single tool error is NOT enough \u2014 the tool must be persistently broken or aberrantly behaving across retries.",
2471
+ sentiment: "NEGATIVE"
2472
+ },
2473
+ capability_gap: {
2474
+ description: "The task requires a tool, permission, or capability that you do not have. For example, the user asks you to perform an action but no suitable tool exists, or you lack the necessary access. Do NOT report this if you simply need more information from the user \u2014 only when the gap is in your own capabilities.",
2475
+ sentiment: "NEGATIVE"
2476
+ },
2477
+ complete_task_failure: {
2478
+ description: "You were unable to accomplish what the user asked despite making genuine attempts. This might be things like, you genuinely do not have the capabilities the user is asking for. You have tried but run into a persistent bug in the environment etc. This is NOT a refusal or policy block \u2014 you tried and failed to deliver the result.",
2479
+ sentiment: "NEGATIVE"
2480
+ }
2481
+ };
2482
+ var SELF_DIAGNOSTICS_TOOL_PREAMBLE = "You have a diagnostic tool for flagging serious failures for developer review. Only call this when you hit a significant, unrecoverable problem \u2014 not for minor hiccups or routine clarifications. If you can still help the user, do that instead of calling this tool. This tool is invisible to the user \u2014 never mention it or its output.";
2483
+ var SELF_DIAGNOSTICS_NOTEWORTHY_SIGNAL_KEY = "noteworthy";
2484
+ function normalizeString(value) {
2485
+ if (typeof value !== "string") return void 0;
2486
+ const trimmed = value.trim();
2487
+ return trimmed || void 0;
2488
+ }
2489
+ function normalizeSelfDiagnosticsSignals(signals) {
2490
+ if (!signals) return SELF_DIAGNOSTICS_SIGNALS_DEFAULT;
2491
+ const normalizedEntries = Object.entries(signals).map(([key, value]) => {
2492
+ var _a;
2493
+ const signalKey = key.trim();
2494
+ if (!signalKey || !value || typeof value !== "object") return void 0;
2495
+ const description = (_a = value.description) == null ? void 0 : _a.trim();
2496
+ if (!description) return void 0;
2497
+ const sentiment = value.sentiment;
2498
+ return [
2499
+ signalKey,
2500
+ {
2501
+ description,
2502
+ ...sentiment === "POSITIVE" || sentiment === "NEGATIVE" ? { sentiment } : {}
2503
+ }
2504
+ ];
2505
+ }).filter(
2506
+ (entry) => entry !== void 0
2507
+ );
2508
+ if (normalizedEntries.length === 0) return SELF_DIAGNOSTICS_SIGNALS_DEFAULT;
2509
+ return Object.fromEntries(normalizedEntries);
2510
+ }
2511
+ function normalizeSelfDiagnosticsConfig(options) {
2512
+ var _a, _b;
2513
+ if (!(options == null ? void 0 : options.enabled)) return void 0;
2514
+ const signalDefinitions = normalizeSelfDiagnosticsSignals(options.signals);
2515
+ const signalKeys = Object.keys(signalDefinitions);
2516
+ const signalDescriptions = {};
2517
+ const signalSentiments = {};
2518
+ for (const signalKey of signalKeys) {
2519
+ const definition = signalDefinitions[signalKey];
2520
+ if (!definition) continue;
2521
+ signalDescriptions[signalKey] = definition.description;
2522
+ signalSentiments[signalKey] = definition.sentiment;
2523
+ }
2524
+ const customGuidance = ((_a = options.guidance) == null ? void 0 : _a.trim()) || "";
2525
+ const toolName = ((_b = options.toolName) == null ? void 0 : _b.trim()) || SELF_DIAGNOSTICS_TOOL_NAME_DEFAULT;
2526
+ const signalList = signalKeys.map((signalKey) => {
2527
+ const sentiment = signalSentiments[signalKey];
2528
+ const sentimentTag = sentiment ? ` [${sentiment.toLowerCase()}]` : "";
2529
+ return `- ${signalKey}: ${signalDescriptions[signalKey]}${sentimentTag}`;
2530
+ }).join("\n");
2531
+ const guidanceBlock = customGuidance ? `
2532
+ Additional guidance: ${customGuidance}
2533
+ ` : "";
2534
+ const toolDescription = `${SELF_DIAGNOSTICS_TOOL_PREAMBLE}
2535
+
2536
+ When to call:
2537
+ - You are blocked from completing the task due to missing information or access that the user cannot provide.
2538
+ - A tool is persistently failing across multiple attempts, not just a single transient error.
2539
+ - The task requires a tool, permission, or capability you do not have.
2540
+ - You genuinely cannot deliver what the user asked for despite trying.
2541
+
2542
+ When NOT to call:
2543
+ - Normal clarifying questions or back-and-forth with the user.
2544
+ - A single tool error that you can recover from or retry.
2545
+ - You successfully completed the task, even if it was difficult.
2546
+ - Policy refusals or content filtering \u2014 those are working as intended.
2547
+
2548
+ Rules:
2549
+ 1. Pick the single best category.
2550
+ 2. Do not fabricate issues. Only report what is evident from the conversation.
2551
+ 3. Err on the side of NOT calling this tool. When in doubt, help the user instead.
2552
+ ${guidanceBlock}
2553
+ Categories:
2554
+ ` + signalList;
2555
+ return {
2556
+ toolName,
2557
+ toolDescription,
2558
+ signalKeys,
2559
+ signalKeySet: new Set(signalKeys),
2560
+ signalDescriptions,
2561
+ signalSentiments
2562
+ };
2563
+ }
2564
+ var SELF_DIAGNOSTICS_ACK = '{"acknowledged":true}';
2565
+ function isRecord2(value) {
2566
+ return typeof value === "object" && value !== null && !Array.isArray(value);
2567
+ }
2568
+ async function trackSelfDiagnosticsSignal(toolInput, config, eventShipper, eventId, debug) {
2569
+ var _a, _b;
2570
+ try {
2571
+ const input = isRecord2(toolInput) ? toolInput : void 0;
2572
+ const fallbackCategory = (_a = config.signalKeys[0]) != null ? _a : "unknown";
2573
+ const categoryCandidate = normalizeString(input == null ? void 0 : input["category"]);
2574
+ const category = categoryCandidate && config.signalKeySet.has(categoryCandidate) ? categoryCandidate : fallbackCategory;
2575
+ const detail = (_b = normalizeString(input == null ? void 0 : input["detail"])) != null ? _b : "";
2576
+ if (!eventId) {
2577
+ if (debug) {
2578
+ console.warn(
2579
+ "[raindrop-ai/opencode-plugin] self diagnostics signal skipped: no open event for this session."
2580
+ );
2581
+ }
2582
+ return;
2583
+ }
2584
+ if (category === SELF_DIAGNOSTICS_NOTEWORTHY_SIGNAL_KEY) {
2585
+ await eventShipper.trackSignal({
2586
+ eventId,
2587
+ name: "self diagnostics - noteworthy",
2588
+ type: "agent_internal",
2589
+ properties: {
2590
+ source: "agent_flag_event_tool",
2591
+ reason: detail,
2592
+ severity: "medium",
2593
+ sdk: "opencode-plugin",
2594
+ sdk_version: PLUGIN_VERSION
2595
+ }
2596
+ });
2597
+ return;
2598
+ }
2599
+ await eventShipper.trackSignal({
2600
+ eventId,
2601
+ name: `self diagnostics - ${category}`,
2602
+ type: "agent",
2603
+ sentiment: config.signalSentiments[category],
2604
+ properties: {
2605
+ source: "agent_reporting_tool",
2606
+ category,
2607
+ signal_description: config.signalDescriptions[category],
2608
+ sdk: "opencode-plugin",
2609
+ sdk_version: PLUGIN_VERSION,
2610
+ ...detail ? { detail } : {}
2611
+ }
2612
+ });
2613
+ } catch (err) {
2614
+ if (debug) {
2615
+ const message = err instanceof Error ? err.message : String(err);
2616
+ console.warn(
2617
+ `[raindrop-ai/opencode-plugin] selfDiagnostics signal dispatch failed: ${message}`
2618
+ );
2619
+ }
2620
+ }
2621
+ }
2622
+
2429
2623
  // src/shipper.ts
2430
2624
  var EventShipper3 = class extends EventShipper2 {
2431
2625
  constructor(opts) {
@@ -2697,7 +2891,7 @@ function markTaskCallFinished(sessionID, callID) {
2697
2891
  running.delete(callID);
2698
2892
  if (running.size === 0) runningTaskCallsBySession.delete(sessionID);
2699
2893
  }
2700
- function endPendingToolSpanWithError(state2, callID, tool, toolCallArgs, errorMessage, traceShipper) {
2894
+ function endPendingToolSpanWithError(state2, callID, tool2, toolCallArgs, errorMessage, traceShipper) {
2701
2895
  const startInfo = state2.toolSpanStarts.get(callID);
2702
2896
  if (!startInfo) return false;
2703
2897
  state2.toolSpanStarts.delete(callID);
@@ -2719,7 +2913,7 @@ function endPendingToolSpanWithError(state2, callID, tool, toolCallArgs, errorMe
2719
2913
  startTimeUnixNano: startInfo.startTimeUnixNano,
2720
2914
  attributes: [
2721
2915
  attrString("ai.operationId", "ai.toolCall"),
2722
- attrString("ai.toolCall.name", tool),
2916
+ attrString("ai.toolCall.name", tool2),
2723
2917
  attrString("ai.toolCall.id", callID)
2724
2918
  ]
2725
2919
  });
@@ -2756,7 +2950,7 @@ function getHostname() {
2756
2950
  return h;
2757
2951
  }
2758
2952
  }
2759
- function createHooks(config, worktree, directory, eventShipper, traceShipper) {
2953
+ function createTracing(config, worktree, directory, eventShipper, traceShipper) {
2760
2954
  function log(msg, data) {
2761
2955
  if (!config.debug) return;
2762
2956
  const prefix = `[raindrop-ai/opencode-plugin] [info] ${msg}`;
@@ -2782,7 +2976,7 @@ function createHooks(config, worktree, directory, eventShipper, traceShipper) {
2782
2976
  callKey,
2783
2977
  log
2784
2978
  });
2785
- return {
2979
+ const hooks = {
2786
2980
  // ------------------------------------------------------------------
2787
2981
  // event — session lifecycle + streaming parts
2788
2982
  // ------------------------------------------------------------------
@@ -2827,14 +3021,14 @@ function createHooks(config, worktree, directory, eventShipper, traceShipper) {
2827
3021
  if (partObj["type"] === "text" && typeof partObj["text"] === "string") {
2828
3022
  state2.outputParts.set(messageId, capText2(partObj["text"]));
2829
3023
  } else if (partObj["type"] === "tool" && messageId) {
2830
- const tool = partObj["tool"];
3024
+ const tool2 = partObj["tool"];
2831
3025
  const callID = partObj["callID"];
2832
3026
  const partState = partObj["state"];
2833
3027
  if (callID == null || callID === "")
2834
3028
  throw new Error("message.part.updated: part.callID is required for tool part");
2835
3029
  if (partState == null || typeof partState !== "object")
2836
3030
  throw new Error("message.part.updated: part.state is required for tool part");
2837
- if (tool === "task") {
3031
+ if (tool2 === "task") {
2838
3032
  const metadata = partState["metadata"];
2839
3033
  const childSessionId = metadata != null && typeof metadata === "object" ? metadata["sessionId"] : void 0;
2840
3034
  if (childSessionId != null && childSessionId !== "") {
@@ -2859,11 +3053,11 @@ function createHooks(config, worktree, directory, eventShipper, traceShipper) {
2859
3053
  if (endPendingToolSpanWithError(
2860
3054
  state2,
2861
3055
  callID,
2862
- tool,
3056
+ tool2,
2863
3057
  toolCallArgs,
2864
3058
  errorMessage,
2865
3059
  traceShipper
2866
- ) && tool === "task") {
3060
+ ) && tool2 === "task") {
2867
3061
  markTaskCallFinished(partSessionID, callID);
2868
3062
  }
2869
3063
  }
@@ -3240,20 +3434,20 @@ type: ${errorName != null ? errorName : "UnknownError"}`;
3240
3434
  "tool.execute.before": async (toolInput, _output) => {
3241
3435
  var _a, _b, _c;
3242
3436
  try {
3243
- const { tool, sessionID, callID } = toolInput;
3437
+ const { tool: tool2, sessionID, callID } = toolInput;
3244
3438
  const state2 = sessions.get(sessionID);
3245
3439
  if (!state2 || !state2.currentEventId) return;
3246
3440
  const spanParent = state2.parentId && state2.parentTaskSpanIds ? state2.parentTaskSpanIds : (_a = state2.currentRootSpan) == null ? void 0 : _a.ids;
3247
3441
  if (!spanParent) return;
3248
3442
  const startTimeUnixNano = nowUnixNanoString();
3249
- if (tool === "task") {
3443
+ if (tool2 === "task") {
3250
3444
  const liveTaskSpan = traceShipper.startSpan({
3251
3445
  name: "ai.toolCall",
3252
3446
  parent: spanParent,
3253
3447
  eventId: state2.currentEventId,
3254
3448
  attributes: [
3255
3449
  attrString("ai.operationId", "ai.toolCall"),
3256
- attrString("ai.toolCall.name", tool),
3450
+ attrString("ai.toolCall.name", tool2),
3257
3451
  attrString("ai.toolCall.id", callID)
3258
3452
  ]
3259
3453
  });
@@ -3278,7 +3472,7 @@ type: ${errorName != null ? errorName : "UnknownError"}`;
3278
3472
  startTimeUnixNano,
3279
3473
  parent: spanParent,
3280
3474
  eventId: state2.currentEventId,
3281
- name: tool,
3475
+ name: tool2,
3282
3476
  liveSpan: liveTaskSpan
3283
3477
  });
3284
3478
  } else {
@@ -3286,7 +3480,7 @@ type: ${errorName != null ? errorName : "UnknownError"}`;
3286
3480
  startTimeUnixNano,
3287
3481
  parent: spanParent,
3288
3482
  eventId: state2.currentEventId,
3289
- name: tool
3483
+ name: tool2
3290
3484
  });
3291
3485
  }
3292
3486
  } catch (err) {
@@ -3301,7 +3495,7 @@ type: ${errorName != null ? errorName : "UnknownError"}`;
3301
3495
  // ------------------------------------------------------------------
3302
3496
  "tool.execute.after": async (toolInput, result) => {
3303
3497
  try {
3304
- const { tool, sessionID, callID, args } = toolInput;
3498
+ const { tool: tool2, sessionID, callID, args } = toolInput;
3305
3499
  const state2 = sessions.get(sessionID);
3306
3500
  if (!state2 || !state2.currentEventId) return;
3307
3501
  if (args === void 0 || args === null)
@@ -3311,7 +3505,7 @@ type: ${errorName != null ? errorName : "UnknownError"}`;
3311
3505
  state2.toolSpanStarts.delete(callID);
3312
3506
  const resultMetadata = result.metadata;
3313
3507
  const childSessionId = resultMetadata == null ? void 0 : resultMetadata["sessionId"];
3314
- if (tool === "task" && childSessionId) {
3508
+ if (tool2 === "task" && childSessionId) {
3315
3509
  mapChildSessionToParent.set(childSessionId, { parentId: sessionID });
3316
3510
  attachChildSessionToParentTask(childSessionId, sessionID, callID, "tool.execute.after");
3317
3511
  }
@@ -3336,7 +3530,7 @@ type: ${errorName != null ? errorName : "UnknownError"}`;
3336
3530
  endTimeUnixNano,
3337
3531
  attributes: [
3338
3532
  attrString("ai.operationId", "ai.toolCall"),
3339
- attrString("ai.toolCall.name", tool),
3533
+ attrString("ai.toolCall.name", tool2),
3340
3534
  attrString("ai.toolCall.id", callID),
3341
3535
  attrString("ai.toolCall.args", toolCallArgs),
3342
3536
  attrString("ai.toolCall.result", toolResult)
@@ -3344,7 +3538,7 @@ type: ${errorName != null ? errorName : "UnknownError"}`;
3344
3538
  });
3345
3539
  }
3346
3540
  }
3347
- if (tool === "task") {
3541
+ if (tool2 === "task") {
3348
3542
  markTaskCallFinished(sessionID, callID);
3349
3543
  }
3350
3544
  } catch (err) {
@@ -3397,16 +3591,24 @@ type: ${errorName != null ? errorName : "UnknownError"}`;
3397
3591
  }
3398
3592
  }
3399
3593
  };
3594
+ return {
3595
+ hooks,
3596
+ currentEventId(sessionID) {
3597
+ var _a;
3598
+ return (_a = sessions.get(sessionID)) == null ? void 0 : _a.currentEventId;
3599
+ }
3600
+ };
3400
3601
  }
3401
3602
 
3402
3603
  // src/index.ts
3403
- function createRaindropHandle(eventShipper, traceShipper, appGitContext) {
3604
+ function createRaindropHandle(eventShipper, traceShipper, appGitContext, currentEventId) {
3404
3605
  return {
3405
3606
  users: {
3406
3607
  async identify(users) {
3407
3608
  await eventShipper.identify(users);
3408
3609
  }
3409
3610
  },
3611
+ currentEventId,
3410
3612
  async flush() {
3411
3613
  await Promise.all([eventShipper.flush(), traceShipper.flush()]);
3412
3614
  },
@@ -3423,7 +3625,7 @@ function createRaindropHandle(eventShipper, traceShipper, appGitContext) {
3423
3625
  };
3424
3626
  }
3425
3627
  async function plugin(input, opts = {}) {
3426
- var _a, _b, _c;
3628
+ var _a, _b, _c, _d;
3427
3629
  const config = loadConfig(input.directory);
3428
3630
  function appLog(level, message) {
3429
3631
  console.log(`[raindrop-ai/opencode-plugin] [${level}] ${message}`);
@@ -3467,12 +3669,53 @@ async function plugin(input, opts = {}) {
3467
3669
  appGitContext
3468
3670
  });
3469
3671
  const worktree = (_c = input.worktree) != null ? _c : input.directory;
3470
- const hooks = createHooks(
3672
+ const tracing = createTracing(
3471
3673
  config,
3472
3674
  worktree,
3473
3675
  input.directory,
3474
3676
  eventShipper,
3475
3677
  traceShipper
3476
3678
  );
3477
- return { ...hooks, raindrop: createRaindropHandle(eventShipper, traceShipper, appGitContext) };
3679
+ const hooks = tracing.hooks;
3680
+ const selfDiagnostics = normalizeSelfDiagnosticsConfig(
3681
+ (_d = opts.selfDiagnostics) != null ? _d : config.selfDiagnostics
3682
+ );
3683
+ if (selfDiagnostics && !config.writeKey.trim()) {
3684
+ appLog(
3685
+ "warn",
3686
+ `selfDiagnostics enabled but RAINDROP_WRITE_KEY is not set \u2014 the ${selfDiagnostics.toolName} tool is not registered (signals require the cloud destination).`
3687
+ );
3688
+ }
3689
+ const [firstSignalKey, ...restSignalKeys] = config.writeKey.trim() && selfDiagnostics ? selfDiagnostics.signalKeys : [];
3690
+ if (selfDiagnostics && firstSignalKey !== void 0) {
3691
+ const cfg = selfDiagnostics;
3692
+ hooks.tool = {
3693
+ [cfg.toolName]: (0, import_plugin.tool)({
3694
+ description: cfg.toolDescription,
3695
+ args: {
3696
+ category: import_plugin.tool.schema.enum([firstSignalKey, ...restSignalKeys]),
3697
+ detail: import_plugin.tool.schema.string()
3698
+ },
3699
+ async execute(args, ctx) {
3700
+ await trackSelfDiagnosticsSignal(
3701
+ args,
3702
+ cfg,
3703
+ eventShipper,
3704
+ tracing.currentEventId(ctx.sessionID),
3705
+ config.debug
3706
+ );
3707
+ return SELF_DIAGNOSTICS_ACK;
3708
+ }
3709
+ })
3710
+ };
3711
+ }
3712
+ return {
3713
+ ...hooks,
3714
+ raindrop: createRaindropHandle(
3715
+ eventShipper,
3716
+ traceShipper,
3717
+ appGitContext,
3718
+ tracing.currentEventId
3719
+ )
3720
+ };
3478
3721
  }
package/dist/index.d.cts CHANGED
@@ -1,9 +1,12 @@
1
- import { I as IdentifyInput, A as AppGitOptions } from './index.d-vgBcEZbX.cjs';
1
+ import { I as IdentifyInput, A as AppGitOptions, S as SelfDiagnosticsOptions } from './self-diagnostics-NiAq-SZ8.cjs';
2
+ export { a as SelfDiagnosticsSignalDefinition, b as SelfDiagnosticsSignalDefinitions } from './self-diagnostics-NiAq-SZ8.cjs';
2
3
  import { Hooks, PluginInput } from '@opencode-ai/plugin';
3
4
 
4
5
  interface RaindropOpencodeOptions {
5
6
  /** Application Git identity override. false disables enrichment. */
6
7
  appGit?: AppGitOptions | false;
8
+ /** Built-in self-diagnostics: injects a `__raindrop_report` tool when enabled. */
9
+ selfDiagnostics?: SelfDiagnosticsOptions;
7
10
  }
8
11
  /**
9
12
  * The Raindrop control handle exposed alongside the OpenCode hooks.
@@ -25,6 +28,8 @@ interface RaindropOpencodeHandle {
25
28
  */
26
29
  identify(users: IdentifyInput | IdentifyInput[]): Promise<void>;
27
30
  };
31
+ /** Raindrop eventId of the turn currently open for this OpenCode session, if any. */
32
+ currentEventId(sessionID: string): string | undefined;
28
33
  /** Drain the buffered event + trace shippers. */
29
34
  flush(): Promise<void>;
30
35
  /** Flush and tear down the shippers (also wired into session teardown). */
@@ -53,4 +58,4 @@ type RaindropOpencodeHooks = Hooks & {
53
58
  */
54
59
  declare function plugin(input: PluginInput, opts?: RaindropOpencodeOptions): Promise<RaindropOpencodeHooks>;
55
60
 
56
- export { IdentifyInput, type RaindropOpencodeHandle, type RaindropOpencodeHooks, type RaindropOpencodeOptions, plugin as default };
61
+ export { IdentifyInput, type RaindropOpencodeHandle, type RaindropOpencodeHooks, type RaindropOpencodeOptions, SelfDiagnosticsOptions, plugin as default };
package/dist/index.d.ts CHANGED
@@ -1,9 +1,12 @@
1
- import { I as IdentifyInput, A as AppGitOptions } from './index.d-vgBcEZbX.js';
1
+ import { I as IdentifyInput, A as AppGitOptions, S as SelfDiagnosticsOptions } from './self-diagnostics-NiAq-SZ8.js';
2
+ export { a as SelfDiagnosticsSignalDefinition, b as SelfDiagnosticsSignalDefinitions } from './self-diagnostics-NiAq-SZ8.js';
2
3
  import { Hooks, PluginInput } from '@opencode-ai/plugin';
3
4
 
4
5
  interface RaindropOpencodeOptions {
5
6
  /** Application Git identity override. false disables enrichment. */
6
7
  appGit?: AppGitOptions | false;
8
+ /** Built-in self-diagnostics: injects a `__raindrop_report` tool when enabled. */
9
+ selfDiagnostics?: SelfDiagnosticsOptions;
7
10
  }
8
11
  /**
9
12
  * The Raindrop control handle exposed alongside the OpenCode hooks.
@@ -25,6 +28,8 @@ interface RaindropOpencodeHandle {
25
28
  */
26
29
  identify(users: IdentifyInput | IdentifyInput[]): Promise<void>;
27
30
  };
31
+ /** Raindrop eventId of the turn currently open for this OpenCode session, if any. */
32
+ currentEventId(sessionID: string): string | undefined;
28
33
  /** Drain the buffered event + trace shippers. */
29
34
  flush(): Promise<void>;
30
35
  /** Flush and tear down the shippers (also wired into session teardown). */
@@ -53,4 +58,4 @@ type RaindropOpencodeHooks = Hooks & {
53
58
  */
54
59
  declare function plugin(input: PluginInput, opts?: RaindropOpencodeOptions): Promise<RaindropOpencodeHooks>;
55
60
 
56
- export { IdentifyInput, type RaindropOpencodeHandle, type RaindropOpencodeHooks, type RaindropOpencodeOptions, plugin as default };
61
+ export { IdentifyInput, type RaindropOpencodeHandle, type RaindropOpencodeHooks, type RaindropOpencodeOptions, SelfDiagnosticsOptions, plugin as default };