@raindrop-ai/opencode-plugin 0.3.0 → 0.3.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.
- package/README.md +55 -0
- package/dist/{chunk-FCORH4YS.js → chunk-ZG47FVK7.js} +251 -9
- package/dist/index.cjs +279 -16
- package/dist/index.d.cts +7 -2
- package/dist/index.d.ts +7 -2
- package/dist/index.js +33 -8
- package/dist/{self-diagnostics-NiAq-SZ8.d.cts → self-diagnostics-CLW6h4zB.d.cts} +27 -1
- package/dist/{self-diagnostics-NiAq-SZ8.d.ts → self-diagnostics-CLW6h4zB.d.ts} +27 -1
- package/dist/v2.cjs +283 -20
- package/dist/v2.d.cts +7 -2
- package/dist/v2.d.ts +7 -2
- package/dist/v2.js +37 -12
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -87,7 +87,7 @@ function evalScopeAttributes() {
|
|
|
87
87
|
return { [EVAL_CORRELATION_ID_ATTRIBUTE]: scope.correlationId };
|
|
88
88
|
}
|
|
89
89
|
|
|
90
|
-
// ../core/dist/chunk-
|
|
90
|
+
// ../core/dist/chunk-I6TVJQEC.js
|
|
91
91
|
var STATE_KEY = /* @__PURE__ */ Symbol.for("raindrop.tracing.replayTraceRoutingState");
|
|
92
92
|
function state() {
|
|
93
93
|
const holder = globalThis;
|
|
@@ -2096,6 +2096,151 @@ var TraceShipper = class {
|
|
|
2096
2096
|
}
|
|
2097
2097
|
}
|
|
2098
2098
|
};
|
|
2099
|
+
var PROMPT_TOOLS_ATTRIBUTE = "ai.prompt.tools";
|
|
2100
|
+
function isRecord(value) {
|
|
2101
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
2102
|
+
}
|
|
2103
|
+
var JSON_SCHEMA_KEYS = [
|
|
2104
|
+
"type",
|
|
2105
|
+
"properties",
|
|
2106
|
+
"$schema",
|
|
2107
|
+
"$ref",
|
|
2108
|
+
"anyOf",
|
|
2109
|
+
"oneOf",
|
|
2110
|
+
"allOf",
|
|
2111
|
+
"enum",
|
|
2112
|
+
"const",
|
|
2113
|
+
"items",
|
|
2114
|
+
"additionalProperties",
|
|
2115
|
+
"required"
|
|
2116
|
+
];
|
|
2117
|
+
function isJsonSchema(value) {
|
|
2118
|
+
if (!isRecord(value)) return false;
|
|
2119
|
+
if (typeof value["~standard"] === "object") return false;
|
|
2120
|
+
if (isRecord(value._def) || isRecord(value._zod)) return false;
|
|
2121
|
+
if (Object.keys(value).length === 0) return true;
|
|
2122
|
+
return JSON_SCHEMA_KEYS.some((key) => key in value);
|
|
2123
|
+
}
|
|
2124
|
+
function toJsonSchema(value, options) {
|
|
2125
|
+
if (value === void 0 || value === null) return void 0;
|
|
2126
|
+
if (isJsonSchema(value)) return value;
|
|
2127
|
+
if (isRecord(value) && isJsonSchema(value.jsonSchema)) return value.jsonSchema;
|
|
2128
|
+
if (isRecord(value) && isJsonSchema(value.json)) return value.json;
|
|
2129
|
+
if (options == null ? void 0 : options.schema) {
|
|
2130
|
+
try {
|
|
2131
|
+
return options.schema(value);
|
|
2132
|
+
} catch (e) {
|
|
2133
|
+
return void 0;
|
|
2134
|
+
}
|
|
2135
|
+
}
|
|
2136
|
+
return void 0;
|
|
2137
|
+
}
|
|
2138
|
+
function pickString(value) {
|
|
2139
|
+
return typeof value === "string" && value.length > 0 ? value : void 0;
|
|
2140
|
+
}
|
|
2141
|
+
function functionTool(name, description, schema, options) {
|
|
2142
|
+
const tool2 = { type: "function", name };
|
|
2143
|
+
const desc = pickString(description);
|
|
2144
|
+
if (desc !== void 0) tool2.description = desc;
|
|
2145
|
+
const inputSchema = toJsonSchema(schema, options);
|
|
2146
|
+
if (inputSchema !== void 0) tool2.inputSchema = inputSchema;
|
|
2147
|
+
return tool2;
|
|
2148
|
+
}
|
|
2149
|
+
function normalizeToolDeclaration(tool2, options, fallbackName) {
|
|
2150
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
|
|
2151
|
+
if (!isRecord(tool2)) return void 0;
|
|
2152
|
+
if (tool2.type === "provider-defined" || tool2.type === "provider") {
|
|
2153
|
+
const name2 = (_b = (_a = pickString(tool2.name)) != null ? _a : pickString(tool2.id)) != null ? _b : fallbackName;
|
|
2154
|
+
if (name2 === void 0) return void 0;
|
|
2155
|
+
const declaration = { type: "provider-defined", name: name2 };
|
|
2156
|
+
const id = pickString(tool2.id);
|
|
2157
|
+
if (id !== void 0) declaration.id = id;
|
|
2158
|
+
if (isRecord(tool2.args)) declaration.args = tool2.args;
|
|
2159
|
+
return declaration;
|
|
2160
|
+
}
|
|
2161
|
+
if (isRecord(tool2.toolSpec)) {
|
|
2162
|
+
const spec = tool2.toolSpec;
|
|
2163
|
+
const name2 = (_c = pickString(spec.name)) != null ? _c : fallbackName;
|
|
2164
|
+
if (name2 === void 0) return void 0;
|
|
2165
|
+
return functionTool(name2, spec.description, spec.inputSchema, options);
|
|
2166
|
+
}
|
|
2167
|
+
if (isRecord(tool2.function)) {
|
|
2168
|
+
const fn = tool2.function;
|
|
2169
|
+
const name2 = (_d = pickString(fn.name)) != null ? _d : fallbackName;
|
|
2170
|
+
if (name2 === void 0) return void 0;
|
|
2171
|
+
return functionTool(name2, fn.description, (_e = fn.parameters) != null ? _e : fn.input_schema, options);
|
|
2172
|
+
}
|
|
2173
|
+
const name = (_g = (_f = pickString(tool2.name)) != null ? _f : pickString(tool2.id)) != null ? _g : fallbackName;
|
|
2174
|
+
if (name === void 0) return void 0;
|
|
2175
|
+
const type = pickString(tool2.type);
|
|
2176
|
+
if (type !== void 0 && type !== "function" && type !== "dynamic" && type !== "custom") {
|
|
2177
|
+
if (!("input_schema" in tool2) && !("inputSchema" in tool2) && !("parameters" in tool2)) {
|
|
2178
|
+
return { type: "provider-defined", id: type, name };
|
|
2179
|
+
}
|
|
2180
|
+
}
|
|
2181
|
+
return functionTool(
|
|
2182
|
+
name,
|
|
2183
|
+
tool2.description,
|
|
2184
|
+
(_j = (_i = (_h = tool2.inputSchema) != null ? _h : tool2.input_schema) != null ? _i : tool2.parameters) != null ? _j : tool2.schema,
|
|
2185
|
+
options
|
|
2186
|
+
);
|
|
2187
|
+
}
|
|
2188
|
+
var NOT_A_GEMINI_GROUP_KEYS = ["name", "id", "type", "function", "toolSpec", "cachePoint"];
|
|
2189
|
+
function isGeminiToolGroup(tool2) {
|
|
2190
|
+
if (Array.isArray(tool2.functionDeclarations)) return true;
|
|
2191
|
+
const keys = Object.keys(tool2);
|
|
2192
|
+
if (keys.length === 0 || NOT_A_GEMINI_GROUP_KEYS.some((key) => key in tool2)) return false;
|
|
2193
|
+
return keys.every((key) => isRecord(tool2[key]));
|
|
2194
|
+
}
|
|
2195
|
+
function expandGeminiTool(tool2, options) {
|
|
2196
|
+
const declarations = [];
|
|
2197
|
+
for (const [key, value] of Object.entries(tool2)) {
|
|
2198
|
+
if (key === "functionDeclarations" && Array.isArray(value)) {
|
|
2199
|
+
for (const declaration of value) {
|
|
2200
|
+
const normalized = normalizeToolDeclaration(declaration, options);
|
|
2201
|
+
if (normalized) declarations.push(normalized);
|
|
2202
|
+
}
|
|
2203
|
+
} else if (isRecord(value)) {
|
|
2204
|
+
declarations.push({ type: "provider-defined", id: key, name: key, args: value });
|
|
2205
|
+
}
|
|
2206
|
+
}
|
|
2207
|
+
return declarations;
|
|
2208
|
+
}
|
|
2209
|
+
function normalizeToolDeclarations(tools, options) {
|
|
2210
|
+
if (tools === void 0 || tools === null) return void 0;
|
|
2211
|
+
if (Array.isArray(tools)) {
|
|
2212
|
+
return tools.flatMap((tool2) => {
|
|
2213
|
+
if (isRecord(tool2) && isGeminiToolGroup(tool2)) {
|
|
2214
|
+
return expandGeminiTool(tool2, options);
|
|
2215
|
+
}
|
|
2216
|
+
const declaration = normalizeToolDeclaration(tool2, options);
|
|
2217
|
+
return declaration ? [declaration] : [];
|
|
2218
|
+
});
|
|
2219
|
+
}
|
|
2220
|
+
if (!isRecord(tools)) return void 0;
|
|
2221
|
+
return Object.entries(tools).flatMap(([key, tool2]) => {
|
|
2222
|
+
const declaration = normalizeToolDeclaration(tool2, options, key);
|
|
2223
|
+
return declaration ? [declaration] : [];
|
|
2224
|
+
});
|
|
2225
|
+
}
|
|
2226
|
+
function promptToolsAttribute(tools) {
|
|
2227
|
+
const values = promptToolsAttributeValue(tools);
|
|
2228
|
+
if (values === void 0) return void 0;
|
|
2229
|
+
return {
|
|
2230
|
+
key: PROMPT_TOOLS_ATTRIBUTE,
|
|
2231
|
+
value: { arrayValue: { values: values.map((stringValue) => ({ stringValue })) } }
|
|
2232
|
+
};
|
|
2233
|
+
}
|
|
2234
|
+
function promptToolsAttributeValue(tools) {
|
|
2235
|
+
if (tools === void 0) return void 0;
|
|
2236
|
+
return tools.map((tool2) => {
|
|
2237
|
+
try {
|
|
2238
|
+
return JSON.stringify(tool2);
|
|
2239
|
+
} catch (e) {
|
|
2240
|
+
return JSON.stringify({ type: tool2.type, name: tool2.name });
|
|
2241
|
+
}
|
|
2242
|
+
});
|
|
2243
|
+
}
|
|
2099
2244
|
|
|
2100
2245
|
// ../core/dist/index.node.js
|
|
2101
2246
|
var import_async_hooks = require("async_hooks");
|
|
@@ -2310,15 +2455,16 @@ function loadConfig(projectDirectory) {
|
|
|
2310
2455
|
eventMetadata,
|
|
2311
2456
|
localWorkshopUrl: resolveLocalWorkshopUrl(merged.local_workshop_url),
|
|
2312
2457
|
appGit: mapAppGit(merged.app_git),
|
|
2313
|
-
selfDiagnostics: mapSelfDiagnostics(merged.self_diagnostics)
|
|
2458
|
+
selfDiagnostics: mapSelfDiagnostics(merged.self_diagnostics),
|
|
2459
|
+
tools: Array.isArray(merged.tools) ? merged.tools : void 0
|
|
2314
2460
|
};
|
|
2315
2461
|
}
|
|
2316
|
-
function
|
|
2462
|
+
function isRecord2(value) {
|
|
2317
2463
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
2318
2464
|
}
|
|
2319
2465
|
function mapSelfDiagnostics(value) {
|
|
2320
2466
|
const env = process.env["RAINDROP_SELF_DIAGNOSTICS"];
|
|
2321
|
-
const record =
|
|
2467
|
+
const record = isRecord2(value) ? value : {};
|
|
2322
2468
|
const enabled = env !== void 0 ? env === "true" : typeof record["enabled"] === "boolean" ? record["enabled"] : void 0;
|
|
2323
2469
|
const signals = mapSelfDiagnosticsSignals(record["signals"]);
|
|
2324
2470
|
const options = {
|
|
@@ -2330,10 +2476,10 @@ function mapSelfDiagnostics(value) {
|
|
|
2330
2476
|
return Object.keys(options).length > 0 ? options : void 0;
|
|
2331
2477
|
}
|
|
2332
2478
|
function mapSelfDiagnosticsSignals(value) {
|
|
2333
|
-
if (!
|
|
2479
|
+
if (!isRecord2(value)) return void 0;
|
|
2334
2480
|
const out = {};
|
|
2335
2481
|
for (const [key, entry] of Object.entries(value)) {
|
|
2336
|
-
if (!
|
|
2482
|
+
if (!isRecord2(entry)) continue;
|
|
2337
2483
|
const definition = entry;
|
|
2338
2484
|
if (typeof definition["description"] !== "string") continue;
|
|
2339
2485
|
const sentiment = definition["sentiment"];
|
|
@@ -2370,7 +2516,7 @@ function resolveLocalWorkshopUrl(fileValue) {
|
|
|
2370
2516
|
// package.json
|
|
2371
2517
|
var package_default = {
|
|
2372
2518
|
name: "@raindrop-ai/opencode-plugin",
|
|
2373
|
-
version: "0.3.
|
|
2519
|
+
version: "0.3.1",
|
|
2374
2520
|
description: "Raindrop observability plugin for OpenCode \u2014 automatic session/event/span tracing",
|
|
2375
2521
|
type: "module",
|
|
2376
2522
|
main: "dist/index.js",
|
|
@@ -2562,13 +2708,13 @@ Categories:
|
|
|
2562
2708
|
};
|
|
2563
2709
|
}
|
|
2564
2710
|
var SELF_DIAGNOSTICS_ACK = '{"acknowledged":true}';
|
|
2565
|
-
function
|
|
2711
|
+
function isRecord3(value) {
|
|
2566
2712
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
2567
2713
|
}
|
|
2568
2714
|
async function trackSelfDiagnosticsSignal(toolInput, config, eventShipper, eventId, debug) {
|
|
2569
2715
|
var _a, _b;
|
|
2570
2716
|
try {
|
|
2571
|
-
const input =
|
|
2717
|
+
const input = isRecord3(toolInput) ? toolInput : void 0;
|
|
2572
2718
|
const fallbackCategory = (_a = config.signalKeys[0]) != null ? _a : "unknown";
|
|
2573
2719
|
const categoryCandidate = normalizeString(input == null ? void 0 : input["category"]);
|
|
2574
2720
|
const category = categoryCandidate && config.signalKeySet.has(categoryCandidate) ? categoryCandidate : fallbackCategory;
|
|
@@ -2655,6 +2801,100 @@ var TraceShipper3 = class extends TraceShipper2 {
|
|
|
2655
2801
|
}
|
|
2656
2802
|
};
|
|
2657
2803
|
|
|
2804
|
+
// src/tool-catalog.ts
|
|
2805
|
+
var PROMPT_TOOLS_SOURCE_ATTRIBUTE = "ai.prompt.tools.source";
|
|
2806
|
+
var OPENCODE_TOOL_LIST_SOURCE = "opencode.tool.list";
|
|
2807
|
+
var TOOL_CATALOG_TIMEOUT_MS = 2e3;
|
|
2808
|
+
function isRecord4(value) {
|
|
2809
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
2810
|
+
}
|
|
2811
|
+
function catalogItems(raw) {
|
|
2812
|
+
var _a;
|
|
2813
|
+
const list = Array.isArray(raw) ? raw : isRecord4(raw) && Array.isArray(raw.data) ? raw.data : void 0;
|
|
2814
|
+
if (!list) return void 0;
|
|
2815
|
+
const items = [];
|
|
2816
|
+
for (const item of list) {
|
|
2817
|
+
if (!isRecord4(item)) continue;
|
|
2818
|
+
const name = typeof item.id === "string" ? item.id : typeof item.name === "string" ? item.name : void 0;
|
|
2819
|
+
if (!name) continue;
|
|
2820
|
+
const schema = (_a = item.parameters) != null ? _a : item.input;
|
|
2821
|
+
items.push({
|
|
2822
|
+
type: "function",
|
|
2823
|
+
name,
|
|
2824
|
+
...typeof item.description === "string" ? { description: item.description } : {},
|
|
2825
|
+
...isJsonSchema(schema) ? { inputSchema: schema } : {}
|
|
2826
|
+
});
|
|
2827
|
+
}
|
|
2828
|
+
return items;
|
|
2829
|
+
}
|
|
2830
|
+
function withTimeout(promise, ms) {
|
|
2831
|
+
return new Promise((resolve2) => {
|
|
2832
|
+
const timer = setTimeout(() => resolve2(void 0), ms);
|
|
2833
|
+
if (typeof timer === "object" && "unref" in timer) timer.unref();
|
|
2834
|
+
promise.then(
|
|
2835
|
+
(value) => {
|
|
2836
|
+
clearTimeout(timer);
|
|
2837
|
+
resolve2(value);
|
|
2838
|
+
},
|
|
2839
|
+
() => {
|
|
2840
|
+
clearTimeout(timer);
|
|
2841
|
+
resolve2(void 0);
|
|
2842
|
+
}
|
|
2843
|
+
);
|
|
2844
|
+
});
|
|
2845
|
+
}
|
|
2846
|
+
function createToolCatalog(options = {}) {
|
|
2847
|
+
var _a, _b;
|
|
2848
|
+
const override = options.override !== void 0 ? { tools: (_a = normalizeToolDeclarations(options.override)) != null ? _a : [] } : void 0;
|
|
2849
|
+
const timeoutMs = (_b = options.timeoutMs) != null ? _b : TOOL_CATALOG_TIMEOUT_MS;
|
|
2850
|
+
const cache = /* @__PURE__ */ new Map();
|
|
2851
|
+
async function lookup(query) {
|
|
2852
|
+
const fetch2 = options.fetch;
|
|
2853
|
+
if (!fetch2) return void 0;
|
|
2854
|
+
let raw;
|
|
2855
|
+
try {
|
|
2856
|
+
raw = await withTimeout(Promise.resolve().then(() => fetch2(query)), timeoutMs);
|
|
2857
|
+
} catch (error) {
|
|
2858
|
+
if (options.debug) console.log(`[raindrop-ai/opencode-plugin] tool catalog lookup failed: ${String(error)}`);
|
|
2859
|
+
return void 0;
|
|
2860
|
+
}
|
|
2861
|
+
const tools = normalizeToolDeclarations(catalogItems(raw));
|
|
2862
|
+
if (!tools) {
|
|
2863
|
+
if (options.debug) console.log("[raindrop-ai/opencode-plugin] tool catalog lookup returned no tool list");
|
|
2864
|
+
return void 0;
|
|
2865
|
+
}
|
|
2866
|
+
return { tools, source: OPENCODE_TOOL_LIST_SOURCE };
|
|
2867
|
+
}
|
|
2868
|
+
return {
|
|
2869
|
+
resolve(sessionID, query) {
|
|
2870
|
+
if (override) return Promise.resolve(override);
|
|
2871
|
+
if (!options.fetch) return Promise.resolve(void 0);
|
|
2872
|
+
let perSession = cache.get(sessionID);
|
|
2873
|
+
if (!perSession) {
|
|
2874
|
+
perSession = /* @__PURE__ */ new Map();
|
|
2875
|
+
cache.set(sessionID, perSession);
|
|
2876
|
+
}
|
|
2877
|
+
const key = `${query.provider}\0${query.model}`;
|
|
2878
|
+
let pending = perSession.get(key);
|
|
2879
|
+
if (!pending) {
|
|
2880
|
+
pending = lookup(query).catch(() => void 0);
|
|
2881
|
+
perSession.set(key, pending);
|
|
2882
|
+
}
|
|
2883
|
+
return pending;
|
|
2884
|
+
},
|
|
2885
|
+
forget(sessionID) {
|
|
2886
|
+
cache.delete(sessionID);
|
|
2887
|
+
}
|
|
2888
|
+
};
|
|
2889
|
+
}
|
|
2890
|
+
function promptToolsAttributes(resolved) {
|
|
2891
|
+
if (!resolved) return [];
|
|
2892
|
+
return [
|
|
2893
|
+
promptToolsAttribute(resolved.tools),
|
|
2894
|
+
resolved.source !== void 0 ? attrString(PROMPT_TOOLS_SOURCE_ATTRIBUTE, resolved.source) : void 0
|
|
2895
|
+
];
|
|
2896
|
+
}
|
|
2897
|
+
|
|
2658
2898
|
// src/tracing.ts
|
|
2659
2899
|
var import_node_os2 = require("os");
|
|
2660
2900
|
|
|
@@ -2950,7 +3190,7 @@ function getHostname() {
|
|
|
2950
3190
|
return h;
|
|
2951
3191
|
}
|
|
2952
3192
|
}
|
|
2953
|
-
function createTracing(config, worktree, directory, eventShipper, traceShipper) {
|
|
3193
|
+
function createTracing(config, worktree, directory, eventShipper, traceShipper, toolCatalog) {
|
|
2954
3194
|
function log(msg, data) {
|
|
2955
3195
|
if (!config.debug) return;
|
|
2956
3196
|
const prefix = `[raindrop-ai/opencode-plugin] [info] ${msg}`;
|
|
@@ -2977,6 +3217,14 @@ function createTracing(config, worktree, directory, eventShipper, traceShipper)
|
|
|
2977
3217
|
log
|
|
2978
3218
|
});
|
|
2979
3219
|
const hooks = {
|
|
3220
|
+
// Fires before each model call with the model already resolved: start the
|
|
3221
|
+
// catalog lookup now so the span attributes rarely wait on it later.
|
|
3222
|
+
"chat.params": async (input) => {
|
|
3223
|
+
void (toolCatalog == null ? void 0 : toolCatalog.resolve(input.sessionID, {
|
|
3224
|
+
provider: input.model.providerID,
|
|
3225
|
+
model: input.model.id
|
|
3226
|
+
}));
|
|
3227
|
+
},
|
|
2980
3228
|
// ------------------------------------------------------------------
|
|
2981
3229
|
// event — session lifecycle + streaming parts
|
|
2982
3230
|
// ------------------------------------------------------------------
|
|
@@ -3101,6 +3349,9 @@ function createTracing(config, worktree, directory, eventShipper, traceShipper)
|
|
|
3101
3349
|
"message.updated: providerID and modelID are required non-empty strings"
|
|
3102
3350
|
);
|
|
3103
3351
|
const modelName = `${providerID}/${modelID}`;
|
|
3352
|
+
const promptTools = promptToolsAttributes(
|
|
3353
|
+
await (toolCatalog == null ? void 0 : toolCatalog.resolve(String(msgSessionID), { provider: providerID, model: modelID }))
|
|
3354
|
+
);
|
|
3104
3355
|
const finishReason = info2["finish"];
|
|
3105
3356
|
const outputText = state2.outputParts.get(messageId);
|
|
3106
3357
|
const reasoningText = state2.reasoningParts.get(messageId);
|
|
@@ -3126,7 +3377,8 @@ type: ${name != null ? name : "UnknownError"}`;
|
|
|
3126
3377
|
const llmAttrs = [
|
|
3127
3378
|
attrString("ai.operationId", "generateText"),
|
|
3128
3379
|
attrString("ai.response.text", responseText),
|
|
3129
|
-
...buildLlmGenAiAttributes({ providerID, modelID, tokens: tokensObj })
|
|
3380
|
+
...buildLlmGenAiAttributes({ providerID, modelID, tokens: tokensObj }),
|
|
3381
|
+
...promptTools
|
|
3130
3382
|
];
|
|
3131
3383
|
if (state2.currentSystemPrompt) {
|
|
3132
3384
|
llmAttrs.push(
|
|
@@ -3162,7 +3414,8 @@ type: ${name != null ? name : "UnknownError"}`;
|
|
|
3162
3414
|
buildPromptMessages(state2.currentSystemPrompt, state2.currentInput)
|
|
3163
3415
|
),
|
|
3164
3416
|
attrString("ai.response.text", turnOutputText),
|
|
3165
|
-
...buildLlmGenAiAttributes({ providerID, modelID, tokens: tokensObj })
|
|
3417
|
+
...buildLlmGenAiAttributes({ providerID, modelID, tokens: tokensObj }),
|
|
3418
|
+
...promptTools
|
|
3166
3419
|
];
|
|
3167
3420
|
if (state2.currentSystemPrompt) {
|
|
3168
3421
|
llmAttrs.push(
|
|
@@ -3207,7 +3460,8 @@ type: ${name != null ? name : "UnknownError"}`;
|
|
|
3207
3460
|
buildPromptMessages(state2.currentSystemPrompt, state2.currentInput)
|
|
3208
3461
|
),
|
|
3209
3462
|
attrString("ai.response.text", turnOutputText),
|
|
3210
|
-
...buildLlmGenAiAttributes({ providerID, modelID, tokens: tokensObj })
|
|
3463
|
+
...buildLlmGenAiAttributes({ providerID, modelID, tokens: tokensObj }),
|
|
3464
|
+
...promptTools
|
|
3211
3465
|
];
|
|
3212
3466
|
if (isCompaction) {
|
|
3213
3467
|
rootAttrs.push(attrString("is_compaction", "true"));
|
|
@@ -3273,6 +3527,7 @@ type: ${name != null ? name : "UnknownError"}`;
|
|
|
3273
3527
|
if (state2.parentId) {
|
|
3274
3528
|
cleanupSessionParentMap(String(sessionID));
|
|
3275
3529
|
sessions.delete(String(sessionID));
|
|
3530
|
+
toolCatalog == null ? void 0 : toolCatalog.forget(String(sessionID));
|
|
3276
3531
|
} else {
|
|
3277
3532
|
}
|
|
3278
3533
|
} else if (event.type === "session.deleted") {
|
|
@@ -3289,6 +3544,7 @@ type: ${name != null ? name : "UnknownError"}`;
|
|
|
3289
3544
|
cleanupSessionParentMap(String(sessionID));
|
|
3290
3545
|
await Promise.all([eventShipper.flush(), traceShipper.flush()]);
|
|
3291
3546
|
sessions.delete(String(sessionID));
|
|
3547
|
+
toolCatalog == null ? void 0 : toolCatalog.forget(String(sessionID));
|
|
3292
3548
|
} else if (event.type === "session.error") {
|
|
3293
3549
|
const errorSessionID = (_h = props["sessionID"]) != null ? _h : sessionID;
|
|
3294
3550
|
if (errorSessionID === void 0 || errorSessionID === "")
|
|
@@ -3314,6 +3570,7 @@ type: ${errorName != null ? errorName : "UnknownError"}`;
|
|
|
3314
3570
|
cleanupSessionParentMap(String(errorSessionID));
|
|
3315
3571
|
await Promise.all([eventShipper.flush(), traceShipper.flush()]);
|
|
3316
3572
|
sessions.delete(String(errorSessionID));
|
|
3573
|
+
toolCatalog == null ? void 0 : toolCatalog.forget(String(errorSessionID));
|
|
3317
3574
|
}
|
|
3318
3575
|
} catch (err) {
|
|
3319
3576
|
rateLimitedErrorLog(
|
|
@@ -3625,7 +3882,7 @@ function createRaindropHandle(eventShipper, traceShipper, appGitContext, current
|
|
|
3625
3882
|
};
|
|
3626
3883
|
}
|
|
3627
3884
|
async function plugin(input, opts = {}) {
|
|
3628
|
-
var _a, _b, _c, _d;
|
|
3885
|
+
var _a, _b, _c, _d, _e;
|
|
3629
3886
|
const config = loadConfig(input.directory);
|
|
3630
3887
|
function appLog(level, message) {
|
|
3631
3888
|
console.log(`[raindrop-ai/opencode-plugin] [${level}] ${message}`);
|
|
@@ -3669,16 +3926,22 @@ async function plugin(input, opts = {}) {
|
|
|
3669
3926
|
appGitContext
|
|
3670
3927
|
});
|
|
3671
3928
|
const worktree = (_c = input.worktree) != null ? _c : input.directory;
|
|
3929
|
+
const toolCatalog = createToolCatalog({
|
|
3930
|
+
override: (_d = opts.tools) != null ? _d : config.tools,
|
|
3931
|
+
fetch: (query) => input.client.tool.list({ query }),
|
|
3932
|
+
debug: config.debug
|
|
3933
|
+
});
|
|
3672
3934
|
const tracing = createTracing(
|
|
3673
3935
|
config,
|
|
3674
3936
|
worktree,
|
|
3675
3937
|
input.directory,
|
|
3676
3938
|
eventShipper,
|
|
3677
|
-
traceShipper
|
|
3939
|
+
traceShipper,
|
|
3940
|
+
toolCatalog
|
|
3678
3941
|
);
|
|
3679
3942
|
const hooks = tracing.hooks;
|
|
3680
3943
|
const selfDiagnostics = normalizeSelfDiagnosticsConfig(
|
|
3681
|
-
(
|
|
3944
|
+
(_e = opts.selfDiagnostics) != null ? _e : config.selfDiagnostics
|
|
3682
3945
|
);
|
|
3683
3946
|
if (selfDiagnostics && !config.writeKey.trim()) {
|
|
3684
3947
|
appLog(
|
package/dist/index.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { I as IdentifyInput, A as AppGitOptions, S as SelfDiagnosticsOptions } from './self-diagnostics-
|
|
2
|
-
export { a as SelfDiagnosticsSignalDefinition, b as SelfDiagnosticsSignalDefinitions } from './self-diagnostics-
|
|
1
|
+
import { I as IdentifyInput, A as AppGitOptions, S as SelfDiagnosticsOptions, P as PromptToolsOverride } from './self-diagnostics-CLW6h4zB.cjs';
|
|
2
|
+
export { a as SelfDiagnosticsSignalDefinition, b as SelfDiagnosticsSignalDefinitions } from './self-diagnostics-CLW6h4zB.cjs';
|
|
3
3
|
import { Hooks, PluginInput } from '@opencode-ai/plugin';
|
|
4
4
|
|
|
5
5
|
interface RaindropOpencodeOptions {
|
|
@@ -7,6 +7,11 @@ interface RaindropOpencodeOptions {
|
|
|
7
7
|
appGit?: AppGitOptions | false;
|
|
8
8
|
/** Built-in self-diagnostics: injects a `__raindrop_report` tool when enabled. */
|
|
9
9
|
selfDiagnostics?: SelfDiagnosticsOptions;
|
|
10
|
+
/**
|
|
11
|
+
* Overrides the tool catalog recorded as `ai.prompt.tools` on every model
|
|
12
|
+
* span; skips the OpenCode `client.tool.list` lookup entirely.
|
|
13
|
+
*/
|
|
14
|
+
tools?: PromptToolsOverride;
|
|
10
15
|
}
|
|
11
16
|
/**
|
|
12
17
|
* The Raindrop control handle exposed alongside the OpenCode hooks.
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { I as IdentifyInput, A as AppGitOptions, S as SelfDiagnosticsOptions } from './self-diagnostics-
|
|
2
|
-
export { a as SelfDiagnosticsSignalDefinition, b as SelfDiagnosticsSignalDefinitions } from './self-diagnostics-
|
|
1
|
+
import { I as IdentifyInput, A as AppGitOptions, S as SelfDiagnosticsOptions, P as PromptToolsOverride } from './self-diagnostics-CLW6h4zB.js';
|
|
2
|
+
export { a as SelfDiagnosticsSignalDefinition, b as SelfDiagnosticsSignalDefinitions } from './self-diagnostics-CLW6h4zB.js';
|
|
3
3
|
import { Hooks, PluginInput } from '@opencode-ai/plugin';
|
|
4
4
|
|
|
5
5
|
interface RaindropOpencodeOptions {
|
|
@@ -7,6 +7,11 @@ interface RaindropOpencodeOptions {
|
|
|
7
7
|
appGit?: AppGitOptions | false;
|
|
8
8
|
/** Built-in self-diagnostics: injects a `__raindrop_report` tool when enabled. */
|
|
9
9
|
selfDiagnostics?: SelfDiagnosticsOptions;
|
|
10
|
+
/**
|
|
11
|
+
* Overrides the tool catalog recorded as `ai.prompt.tools` on every model
|
|
12
|
+
* span; skips the OpenCode `client.tool.list` lookup entirely.
|
|
13
|
+
*/
|
|
14
|
+
tools?: PromptToolsOverride;
|
|
10
15
|
}
|
|
11
16
|
/**
|
|
12
17
|
* The Raindrop control handle exposed alongside the OpenCode hooks.
|
package/dist/index.js
CHANGED
|
@@ -9,13 +9,15 @@ import {
|
|
|
9
9
|
buildLlmGenAiAttributes,
|
|
10
10
|
capText,
|
|
11
11
|
createAppGitContext,
|
|
12
|
+
createToolCatalog,
|
|
12
13
|
generateId,
|
|
13
14
|
loadConfig,
|
|
14
15
|
normalizeSelfDiagnosticsConfig,
|
|
15
16
|
nowUnixNanoString,
|
|
17
|
+
promptToolsAttributes,
|
|
16
18
|
resolveLocalDebuggerBaseUrl,
|
|
17
19
|
trackSelfDiagnosticsSignal
|
|
18
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-ZG47FVK7.js";
|
|
19
21
|
|
|
20
22
|
// src/index.ts
|
|
21
23
|
import { tool } from "@opencode-ai/plugin";
|
|
@@ -194,7 +196,7 @@ function getHostname() {
|
|
|
194
196
|
return h;
|
|
195
197
|
}
|
|
196
198
|
}
|
|
197
|
-
function createTracing(config, worktree, directory, eventShipper, traceShipper) {
|
|
199
|
+
function createTracing(config, worktree, directory, eventShipper, traceShipper, toolCatalog) {
|
|
198
200
|
function log(msg, data) {
|
|
199
201
|
if (!config.debug) return;
|
|
200
202
|
const prefix = `[raindrop-ai/opencode-plugin] [info] ${msg}`;
|
|
@@ -221,6 +223,14 @@ function createTracing(config, worktree, directory, eventShipper, traceShipper)
|
|
|
221
223
|
log
|
|
222
224
|
});
|
|
223
225
|
const hooks = {
|
|
226
|
+
// Fires before each model call with the model already resolved: start the
|
|
227
|
+
// catalog lookup now so the span attributes rarely wait on it later.
|
|
228
|
+
"chat.params": async (input) => {
|
|
229
|
+
void (toolCatalog == null ? void 0 : toolCatalog.resolve(input.sessionID, {
|
|
230
|
+
provider: input.model.providerID,
|
|
231
|
+
model: input.model.id
|
|
232
|
+
}));
|
|
233
|
+
},
|
|
224
234
|
// ------------------------------------------------------------------
|
|
225
235
|
// event — session lifecycle + streaming parts
|
|
226
236
|
// ------------------------------------------------------------------
|
|
@@ -345,6 +355,9 @@ function createTracing(config, worktree, directory, eventShipper, traceShipper)
|
|
|
345
355
|
"message.updated: providerID and modelID are required non-empty strings"
|
|
346
356
|
);
|
|
347
357
|
const modelName = `${providerID}/${modelID}`;
|
|
358
|
+
const promptTools = promptToolsAttributes(
|
|
359
|
+
await (toolCatalog == null ? void 0 : toolCatalog.resolve(String(msgSessionID), { provider: providerID, model: modelID }))
|
|
360
|
+
);
|
|
348
361
|
const finishReason = info2["finish"];
|
|
349
362
|
const outputText = state.outputParts.get(messageId);
|
|
350
363
|
const reasoningText = state.reasoningParts.get(messageId);
|
|
@@ -370,7 +383,8 @@ type: ${name != null ? name : "UnknownError"}`;
|
|
|
370
383
|
const llmAttrs = [
|
|
371
384
|
attrString("ai.operationId", "generateText"),
|
|
372
385
|
attrString("ai.response.text", responseText),
|
|
373
|
-
...buildLlmGenAiAttributes({ providerID, modelID, tokens: tokensObj })
|
|
386
|
+
...buildLlmGenAiAttributes({ providerID, modelID, tokens: tokensObj }),
|
|
387
|
+
...promptTools
|
|
374
388
|
];
|
|
375
389
|
if (state.currentSystemPrompt) {
|
|
376
390
|
llmAttrs.push(
|
|
@@ -406,7 +420,8 @@ type: ${name != null ? name : "UnknownError"}`;
|
|
|
406
420
|
buildPromptMessages(state.currentSystemPrompt, state.currentInput)
|
|
407
421
|
),
|
|
408
422
|
attrString("ai.response.text", turnOutputText),
|
|
409
|
-
...buildLlmGenAiAttributes({ providerID, modelID, tokens: tokensObj })
|
|
423
|
+
...buildLlmGenAiAttributes({ providerID, modelID, tokens: tokensObj }),
|
|
424
|
+
...promptTools
|
|
410
425
|
];
|
|
411
426
|
if (state.currentSystemPrompt) {
|
|
412
427
|
llmAttrs.push(
|
|
@@ -451,7 +466,8 @@ type: ${name != null ? name : "UnknownError"}`;
|
|
|
451
466
|
buildPromptMessages(state.currentSystemPrompt, state.currentInput)
|
|
452
467
|
),
|
|
453
468
|
attrString("ai.response.text", turnOutputText),
|
|
454
|
-
...buildLlmGenAiAttributes({ providerID, modelID, tokens: tokensObj })
|
|
469
|
+
...buildLlmGenAiAttributes({ providerID, modelID, tokens: tokensObj }),
|
|
470
|
+
...promptTools
|
|
455
471
|
];
|
|
456
472
|
if (isCompaction) {
|
|
457
473
|
rootAttrs.push(attrString("is_compaction", "true"));
|
|
@@ -517,6 +533,7 @@ type: ${name != null ? name : "UnknownError"}`;
|
|
|
517
533
|
if (state.parentId) {
|
|
518
534
|
cleanupSessionParentMap(String(sessionID));
|
|
519
535
|
sessions.delete(String(sessionID));
|
|
536
|
+
toolCatalog == null ? void 0 : toolCatalog.forget(String(sessionID));
|
|
520
537
|
} else {
|
|
521
538
|
}
|
|
522
539
|
} else if (event.type === "session.deleted") {
|
|
@@ -533,6 +550,7 @@ type: ${name != null ? name : "UnknownError"}`;
|
|
|
533
550
|
cleanupSessionParentMap(String(sessionID));
|
|
534
551
|
await Promise.all([eventShipper.flush(), traceShipper.flush()]);
|
|
535
552
|
sessions.delete(String(sessionID));
|
|
553
|
+
toolCatalog == null ? void 0 : toolCatalog.forget(String(sessionID));
|
|
536
554
|
} else if (event.type === "session.error") {
|
|
537
555
|
const errorSessionID = (_h = props["sessionID"]) != null ? _h : sessionID;
|
|
538
556
|
if (errorSessionID === void 0 || errorSessionID === "")
|
|
@@ -558,6 +576,7 @@ type: ${errorName != null ? errorName : "UnknownError"}`;
|
|
|
558
576
|
cleanupSessionParentMap(String(errorSessionID));
|
|
559
577
|
await Promise.all([eventShipper.flush(), traceShipper.flush()]);
|
|
560
578
|
sessions.delete(String(errorSessionID));
|
|
579
|
+
toolCatalog == null ? void 0 : toolCatalog.forget(String(errorSessionID));
|
|
561
580
|
}
|
|
562
581
|
} catch (err) {
|
|
563
582
|
rateLimitedErrorLog(
|
|
@@ -869,7 +888,7 @@ function createRaindropHandle(eventShipper, traceShipper, appGitContext, current
|
|
|
869
888
|
};
|
|
870
889
|
}
|
|
871
890
|
async function plugin(input, opts = {}) {
|
|
872
|
-
var _a, _b, _c, _d;
|
|
891
|
+
var _a, _b, _c, _d, _e;
|
|
873
892
|
const config = loadConfig(input.directory);
|
|
874
893
|
function appLog(level, message) {
|
|
875
894
|
console.log(`[raindrop-ai/opencode-plugin] [${level}] ${message}`);
|
|
@@ -913,16 +932,22 @@ async function plugin(input, opts = {}) {
|
|
|
913
932
|
appGitContext
|
|
914
933
|
});
|
|
915
934
|
const worktree = (_c = input.worktree) != null ? _c : input.directory;
|
|
935
|
+
const toolCatalog = createToolCatalog({
|
|
936
|
+
override: (_d = opts.tools) != null ? _d : config.tools,
|
|
937
|
+
fetch: (query) => input.client.tool.list({ query }),
|
|
938
|
+
debug: config.debug
|
|
939
|
+
});
|
|
916
940
|
const tracing = createTracing(
|
|
917
941
|
config,
|
|
918
942
|
worktree,
|
|
919
943
|
input.directory,
|
|
920
944
|
eventShipper,
|
|
921
|
-
traceShipper
|
|
945
|
+
traceShipper,
|
|
946
|
+
toolCatalog
|
|
922
947
|
);
|
|
923
948
|
const hooks = tracing.hooks;
|
|
924
949
|
const selfDiagnostics = normalizeSelfDiagnosticsConfig(
|
|
925
|
-
(
|
|
950
|
+
(_e = opts.selfDiagnostics) != null ? _e : config.selfDiagnostics
|
|
926
951
|
);
|
|
927
952
|
if (selfDiagnostics && !config.writeKey.trim()) {
|
|
928
953
|
appLog(
|
|
@@ -85,6 +85,32 @@ declare global {
|
|
|
85
85
|
var RAINDROP_CONTEXT_MANAGER: (new () => ContextManager) | undefined;
|
|
86
86
|
var RAINDROP_ASYNC_LOCAL_STORAGE: (new <T>() => AsyncLocalStorageLike<T>) | undefined;
|
|
87
87
|
}
|
|
88
|
+
type JsonSchema = Record<string, unknown>;
|
|
89
|
+
type FunctionToolDeclaration = {
|
|
90
|
+
type: "function";
|
|
91
|
+
name: string;
|
|
92
|
+
description?: string;
|
|
93
|
+
inputSchema?: JsonSchema;
|
|
94
|
+
};
|
|
95
|
+
type ProviderDefinedToolDeclaration = {
|
|
96
|
+
type: "provider-defined";
|
|
97
|
+
id?: string;
|
|
98
|
+
name: string;
|
|
99
|
+
args?: Record<string, unknown>;
|
|
100
|
+
};
|
|
101
|
+
type ToolDeclaration = FunctionToolDeclaration | ProviderDefinedToolDeclaration;
|
|
102
|
+
/**
|
|
103
|
+
* What callers hand to a `tools` override. The canonical `ToolDeclaration`
|
|
104
|
+
* shape is accepted as-is; so is any framework shape `normalizeToolDeclarations`
|
|
105
|
+
* recognizes (OpenAI, Anthropic, Bedrock, LangChain, Pi, Mastra, AI SDK).
|
|
106
|
+
*/
|
|
107
|
+
type ToolDeclarationInput = ToolDeclaration | {
|
|
108
|
+
name: string;
|
|
109
|
+
description?: string;
|
|
110
|
+
inputSchema?: JsonSchema;
|
|
111
|
+
parameters?: JsonSchema;
|
|
112
|
+
};
|
|
113
|
+
type PromptToolsOverride = ReadonlyArray<ToolDeclarationInput | unknown>;
|
|
88
114
|
|
|
89
115
|
type SelfDiagnosticsSignalDefinition = {
|
|
90
116
|
/**
|
|
@@ -119,4 +145,4 @@ type SelfDiagnosticsOptions = {
|
|
|
119
145
|
toolName?: string;
|
|
120
146
|
};
|
|
121
147
|
|
|
122
|
-
export type { AppGitOptions as A, IdentifyInput as I, SelfDiagnosticsOptions as S, SelfDiagnosticsSignalDefinition as a, SelfDiagnosticsSignalDefinitions as b, SignalInput as c };
|
|
148
|
+
export type { AppGitOptions as A, IdentifyInput as I, PromptToolsOverride as P, SelfDiagnosticsOptions as S, SelfDiagnosticsSignalDefinition as a, SelfDiagnosticsSignalDefinitions as b, SignalInput as c };
|