@vymalo/opencode-devtools 0.11.0 → 0.14.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/opencode.js CHANGED
@@ -2,90 +2,86 @@ import { DEFAULT_GROUPS, TOOL_GROUPS } from "./catalog.js";
2
2
  import { createJsonConsoleLogger, DEFAULT_LOG_LEVEL, fromOpenCodeLogLevel, LOG_LEVEL_PRIORITY } from "./logging.js";
3
3
  import { createDevtoolsTools } from "./tools.js";
4
4
  const PLUGIN_SERVICE_NAME = "opencode-devtools-plugin";
5
- const DEFAULTS = {
6
- httpTimeoutMs: 30_000
7
- };
5
+ const DEFAULTS = { httpTimeoutMs: 3e4 };
8
6
  function resolveGroups(raw) {
9
- if (!Array.isArray(raw)) {
10
- return [...DEFAULT_GROUPS];
11
- }
12
- const valid = raw.filter((g) => TOOL_GROUPS.includes(g));
13
- // An explicit but empty/invalid list falls back to the defaults rather than
14
- // registering nothing — matches the browser plugin's behaviour.
15
- return valid.length > 0 ? Array.from(new Set(valid)) : [...DEFAULT_GROUPS];
7
+ if (!Array.isArray(raw)) {
8
+ return [...DEFAULT_GROUPS];
9
+ }
10
+ const valid = raw.filter((g) => TOOL_GROUPS.includes(g));
11
+ // An explicit but empty/invalid list falls back to the defaults rather than
12
+ // registering nothing — matches the browser plugin's behaviour.
13
+ return valid.length > 0 ? Array.from(new Set(valid)) : [...DEFAULT_GROUPS];
16
14
  }
17
15
  export function resolveOptions(raw) {
18
- const opts = (raw ?? {});
19
- return {
20
- enabled: opts.enabled !== false,
21
- groups: resolveGroups(opts.groups),
22
- http: {
23
- allowPrivateNetwork: opts.http?.allowPrivateNetwork === true,
24
- timeoutMs: typeof opts.http?.timeoutMs === "number" && opts.http.timeoutMs > 0
25
- ? opts.http.timeoutMs
26
- : DEFAULTS.httpTimeoutMs
27
- }
28
- };
16
+ const opts = raw ?? {};
17
+ return {
18
+ enabled: opts.enabled !== false,
19
+ groups: resolveGroups(opts.groups),
20
+ http: {
21
+ allowPrivateNetwork: opts.http?.allowPrivateNetwork === true,
22
+ timeoutMs: typeof opts.http?.timeoutMs === "number" && opts.http.timeoutMs > 0 ? opts.http.timeoutMs : DEFAULTS.httpTimeoutMs
23
+ }
24
+ };
29
25
  }
30
26
  /**
31
- * Pipe plugin logs through OpenCode's `client.app.log` so they show up in the
32
- * host's structured log stream, with the JSON console as a reliable fallback.
33
- * Mirrors `@vymalo/opencode-browser`.
34
- */
27
+ * Pipe plugin logs through OpenCode's `client.app.log` so they show up in the
28
+ * host's structured log stream, with the JSON console as a reliable fallback.
29
+ * Mirrors `@vymalo/opencode-browser`.
30
+ */
35
31
  function createOpenCodeLogger(client, getMinLevel) {
36
- const fallback = createJsonConsoleLogger("debug");
37
- const consoleAll = /^(1|true|yes|on)$/i.test(process.env.VYMALO_PLUGIN_CONSOLE_LOG ?? "");
38
- const write = (level, event, fields) => {
39
- if (LOG_LEVEL_PRIORITY[level] < LOG_LEVEL_PRIORITY[getMinLevel()]) {
40
- return;
41
- }
42
- if (consoleAll || level === "warn" || level === "error") {
43
- fallback[level](event, fields);
44
- }
45
- const hostLevel = level === "trace" ? "debug" : level;
46
- void client.app
47
- .log({
48
- body: { service: PLUGIN_SERVICE_NAME, level: hostLevel, message: event, extra: fields }
49
- })
50
- .catch(() => {
51
- /* best-effort */
52
- });
53
- };
54
- return {
55
- trace: (event, fields) => write("trace", event, fields),
56
- debug: (event, fields) => write("debug", event, fields),
57
- info: (event, fields) => write("info", event, fields),
58
- warn: (event, fields) => write("warn", event, fields),
59
- error: (event, fields) => write("error", event, fields)
60
- };
32
+ const fallback = createJsonConsoleLogger("debug");
33
+ const consoleAll = /^(1|true|yes|on)$/i.test(process.env.VYMALO_PLUGIN_CONSOLE_LOG ?? "");
34
+ const write = (level, event, fields) => {
35
+ if (LOG_LEVEL_PRIORITY[level] < LOG_LEVEL_PRIORITY[getMinLevel()]) {
36
+ return;
37
+ }
38
+ if (consoleAll || level === "warn" || level === "error") {
39
+ fallback[level](event, fields);
40
+ }
41
+ const hostLevel = level === "trace" ? "debug" : level;
42
+ void client.app.log({ body: {
43
+ service: PLUGIN_SERVICE_NAME,
44
+ level: hostLevel,
45
+ message: event,
46
+ extra: fields
47
+ } }).catch(() => {
48
+ /* best-effort */
49
+ });
50
+ };
51
+ return {
52
+ trace: (event, fields) => write("trace", event, fields),
53
+ debug: (event, fields) => write("debug", event, fields),
54
+ info: (event, fields) => write("info", event, fields),
55
+ warn: (event, fields) => write("warn", event, fields),
56
+ error: (event, fields) => write("error", event, fields)
57
+ };
61
58
  }
62
59
  export function createDevtoolsPlugin(factoryOptions = {}) {
63
- return async ({ client }, pluginOptions) => {
64
- let currentLogLevel = DEFAULT_LOG_LEVEL;
65
- const logger = factoryOptions.logger ?? createOpenCodeLogger(client, () => currentLogLevel);
66
- const options = resolveOptions(pluginOptions);
67
- if (!options.enabled) {
68
- logger.info("devtools_plugin_disabled", {});
69
- return {
70
- config: async (config) => {
71
- currentLogLevel = fromOpenCodeLogLevel(config.logLevel) ?? DEFAULT_LOG_LEVEL;
72
- }
73
- };
74
- }
75
- logger.info("devtools_plugin_enabled", { groups: options.groups });
76
- const tools = createDevtoolsTools({
77
- options,
78
- logger,
79
- context: factoryOptions.context
80
- });
81
- return {
82
- tool: tools,
83
- config: async (config) => {
84
- currentLogLevel = fromOpenCodeLogLevel(config.logLevel) ?? DEFAULT_LOG_LEVEL;
85
- }
86
- };
87
- };
60
+ return async ({ client }, pluginOptions) => {
61
+ let currentLogLevel = DEFAULT_LOG_LEVEL;
62
+ const logger = factoryOptions.logger ?? createOpenCodeLogger(client, () => currentLogLevel);
63
+ const options = resolveOptions(pluginOptions);
64
+ if (!options.enabled) {
65
+ logger.info("devtools_plugin_disabled", {});
66
+ return { config: async (config) => {
67
+ currentLogLevel = fromOpenCodeLogLevel(config.logLevel) ?? DEFAULT_LOG_LEVEL;
68
+ } };
69
+ }
70
+ logger.info("devtools_plugin_enabled", { groups: options.groups });
71
+ const tools = createDevtoolsTools({
72
+ options,
73
+ logger,
74
+ context: factoryOptions.context
75
+ });
76
+ return {
77
+ tool: tools,
78
+ config: async (config) => {
79
+ currentLogLevel = fromOpenCodeLogLevel(config.logLevel) ?? DEFAULT_LOG_LEVEL;
80
+ }
81
+ };
82
+ };
88
83
  }
89
84
  export const OpencodeDevtoolsPlugin = createDevtoolsPlugin();
90
85
  export default OpencodeDevtoolsPlugin;
86
+
91
87
  //# sourceMappingURL=opencode.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"opencode.js","sourceRoot":"","sources":["../src/opencode.ts"],"names":[],"mappings":"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"}
1
+ {"mappings":"AAEA,SAAS,gBAAgB,mBAAmB;AAC5C,SACE,yBACA,mBACA,sBAEA,0BAGK;AAEP,SAAS,2BAA0C;AAGnD,MAAM,sBAAsB;AAE5B,MAAM,WAAW,EACf,eAAe,IACjB;AAWA,SAAS,cAAc,KAA2B;CAChD,IAAI,CAAC,MAAM,QAAQ,GAAG,GAAG;EACvB,OAAO,CAAC,GAAG,cAAc;CAC3B;CACA,MAAM,QAAQ,IAAI,QAAQ,MAAsB,YAAY,SAAS,CAAc,CAAC;;;CAGpF,OAAO,MAAM,SAAS,IAAI,MAAM,KAAK,IAAI,IAAI,KAAK,CAAC,IAAI,CAAC,GAAG,cAAc;AAC3E;AAEA,OAAO,SAAS,eAAe,KAAyD;CACtF,MAAM,OAAQ,OAAO,CAAC;CACtB,OAAO;EACL,SAAS,KAAK,YAAY;EAC1B,QAAQ,cAAc,KAAK,MAAM;EACjC,MAAM;GACJ,qBAAqB,KAAK,MAAM,wBAAwB;GACxD,WACE,OAAO,KAAK,MAAM,cAAc,YAAY,KAAK,KAAK,YAAY,IAC9D,KAAK,KAAK,YACV,SAAS;EACjB;CACF;AACF;;;;;;AAOA,SAAS,qBAAqB,QAA+B,aAAqC;CAChG,MAAM,WAAW,wBAAwB,OAAO;CAChD,MAAM,aAAa,qBAAqB,KAAK,QAAQ,IAAI,6BAA6B,EAAE;CAExF,MAAM,SAAS,OAAiB,OAAe,WAAuB;EACpE,IAAI,mBAAmB,SAAS,mBAAmB,YAAY,IAAI;GACjE;EACF;EACA,IAAI,cAAc,UAAU,UAAU,UAAU,SAAS;GACvD,SAAS,MAAM,CAAC,OAAO,MAAM;EAC/B;EACA,MAAM,YAAY,UAAU,UAAU,UAAU;EAChD,KAAK,OAAO,IACT,IAAI,EACH,MAAM;GAAE,SAAS;GAAqB,OAAO;GAAW,SAAS;GAAO,OAAO;EAAO,EACxF,CAAC,CAAC,CACD,YAAY;;EAEb,CAAC;CACL;CAEA,OAAO;EACL,QAAQ,OAAO,WAAW,MAAM,SAAS,OAAO,MAAM;EACtD,QAAQ,OAAO,WAAW,MAAM,SAAS,OAAO,MAAM;EACtD,OAAO,OAAO,WAAW,MAAM,QAAQ,OAAO,MAAM;EACpD,OAAO,OAAO,WAAW,MAAM,QAAQ,OAAO,MAAM;EACpD,QAAQ,OAAO,WAAW,MAAM,SAAS,OAAO,MAAM;CACxD;AACF;AAEA,OAAO,SAAS,qBAAqB,iBAA+C,CAAC,GAAW;CAC9F,OAAO,OAAO,EAAE,UAAU,kBAAkB;EAC1C,IAAI,kBAA4B;EAChC,MAAM,SAAS,eAAe,UAAU,qBAAqB,cAAc,eAAe;EAE1F,MAAM,UAAU,eAAe,aAAa;EAE5C,IAAI,CAAC,QAAQ,SAAS;GACpB,OAAO,KAAK,4BAA4B,CAAC,CAAC;GAC1C,OAAO,EACL,QAAQ,OAAO,WAA2B;IACxC,kBAAkB,qBAAqB,OAAO,QAAQ,KAAK;GAC7D,EACF;EACF;EAEA,OAAO,KAAK,2BAA2B,EAAE,QAAQ,QAAQ,OAAO,CAAC;EAEjE,MAAM,QAAQ,oBAAoB;GAChC;GACA;GACA,SAAS,eAAe;EAC1B,CAAC;EAED,OAAO;GACL,MAAM;GACN,QAAQ,OAAO,WAA2B;IACxC,kBAAkB,qBAAqB,OAAO,QAAQ,KAAK;GAC7D;EACF;CACF;AACF;AAEA,OAAO,MAAM,yBAAiC,qBAAqB;AAEnE,eAAe","names":[],"sources":["../src/opencode.ts"],"version":3,"file":"opencode.js","sourceRoot":""}
package/dist/schema.d.ts CHANGED
@@ -1,63 +1,63 @@
1
1
  /**
2
- * A tiny, neutral schema vocabulary for tool arguments. The tool catalog
3
- * (`catalog.ts`) is the single source of truth; each adapter turns these specs
4
- * into its own format:
5
- * - the OpenCode plugin builds a zod shape (see `buildShape` in tools.ts),
6
- * - the MCP server emits standard JSON Schema via `toJsonSchema` below.
7
- *
8
- * Lifted verbatim from `@vymalo/opencode-browser` so the two tool-registering
9
- * plugins describe their surface the same way. Keeping the vocabulary small
10
- * avoids dragging a specific zod version across the package boundary.
11
- */
2
+ * A tiny, neutral schema vocabulary for tool arguments. The tool catalog
3
+ * (`catalog.ts`) is the single source of truth; each adapter turns these specs
4
+ * into its own format:
5
+ * - the OpenCode plugin builds a zod shape (see `buildShape` in tools.ts),
6
+ * - the MCP server emits standard JSON Schema via `toJsonSchema` below.
7
+ *
8
+ * Lifted verbatim from `@vymalo/opencode-browser` so the two tool-registering
9
+ * plugins describe their surface the same way. Keeping the vocabulary small
10
+ * avoids dragging a specific zod version across the package boundary.
11
+ */
12
12
  export type ToolGroup = "math" | "codec" | "crypto" | "datetime" | "convert" | "http";
13
13
  export interface StringField {
14
- type: "string";
15
- description?: string;
16
- optional?: boolean;
17
- enum?: readonly string[];
14
+ type: "string";
15
+ description?: string;
16
+ optional?: boolean;
17
+ enum?: readonly string[];
18
18
  }
19
19
  export interface NumberField {
20
- type: "number";
21
- description?: string;
22
- optional?: boolean;
20
+ type: "number";
21
+ description?: string;
22
+ optional?: boolean;
23
23
  }
24
24
  export interface BooleanField {
25
- type: "boolean";
26
- description?: string;
27
- optional?: boolean;
25
+ type: "boolean";
26
+ description?: string;
27
+ optional?: boolean;
28
28
  }
29
29
  export interface ArrayField {
30
- type: "array";
31
- description?: string;
32
- optional?: boolean;
33
- items: Field;
30
+ type: "array";
31
+ description?: string;
32
+ optional?: boolean;
33
+ items: Field;
34
34
  }
35
35
  export interface ObjectField {
36
- type: "object";
37
- description?: string;
38
- optional?: boolean;
39
- properties: Record<string, Field>;
36
+ type: "object";
37
+ description?: string;
38
+ optional?: boolean;
39
+ properties: Record<string, Field>;
40
40
  }
41
41
  /**
42
- * An open key→value map with arbitrary keys (e.g. HTTP headers, GraphQL
43
- * variables). Unlike `object`, it does NOT set `additionalProperties: false`,
44
- * so real keys aren't stripped/rejected by a validating client. `valueType`
45
- * picks the value schema (`string` for headers, `any` for variables).
46
- */
42
+ * An open key→value map with arbitrary keys (e.g. HTTP headers, GraphQL
43
+ * variables). Unlike `object`, it does NOT set `additionalProperties: false`,
44
+ * so real keys aren't stripped/rejected by a validating client. `valueType`
45
+ * picks the value schema (`string` for headers, `any` for variables).
46
+ */
47
47
  export interface RecordField {
48
- type: "record";
49
- description?: string;
50
- optional?: boolean;
51
- valueType?: "string" | "any";
48
+ type: "record";
49
+ description?: string;
50
+ optional?: boolean;
51
+ valueType?: "string" | "any";
52
52
  }
53
53
  export type Field = StringField | NumberField | BooleanField | ArrayField | ObjectField | RecordField;
54
54
  /** Top-level argument map for a tool. */
55
55
  export type JsonInput = Record<string, Field>;
56
56
  export interface JsonSchema {
57
- type: "object";
58
- properties: Record<string, unknown>;
59
- required: string[];
60
- additionalProperties: false;
57
+ type: "object";
58
+ properties: Record<string, unknown>;
59
+ required: string[];
60
+ additionalProperties: false;
61
61
  }
62
62
  /** Convert a tool's input spec to a standard JSON Schema object (for MCP). */
63
63
  export declare function toJsonSchema(input: JsonInput): JsonSchema;
package/dist/schema.js CHANGED
@@ -1,54 +1,49 @@
1
- /**
2
- * A tiny, neutral schema vocabulary for tool arguments. The tool catalog
3
- * (`catalog.ts`) is the single source of truth; each adapter turns these specs
4
- * into its own format:
5
- * - the OpenCode plugin builds a zod shape (see `buildShape` in tools.ts),
6
- * - the MCP server emits standard JSON Schema via `toJsonSchema` below.
7
- *
8
- * Lifted verbatim from `@vymalo/opencode-browser` so the two tool-registering
9
- * plugins describe their surface the same way. Keeping the vocabulary small
10
- * avoids dragging a specific zod version across the package boundary.
11
- */
12
1
  function fieldToJsonSchema(field) {
13
- const out = { type: field.type };
14
- if (field.description) {
15
- out.description = field.description;
16
- }
17
- if (field.type === "string" && field.enum) {
18
- out.enum = [...field.enum];
19
- }
20
- if (field.type === "array") {
21
- out.items = fieldToJsonSchema(field.items);
22
- }
23
- if (field.type === "record") {
24
- out.type = "object";
25
- out.additionalProperties = field.valueType === "any" ? true : { type: "string" };
26
- }
27
- if (field.type === "object") {
28
- const properties = {};
29
- const required = [];
30
- for (const [key, value] of Object.entries(field.properties)) {
31
- properties[key] = fieldToJsonSchema(value);
32
- if (!value.optional) {
33
- required.push(key);
34
- }
35
- }
36
- out.properties = properties;
37
- out.required = required;
38
- out.additionalProperties = false;
39
- }
40
- return out;
2
+ const out = { type: field.type };
3
+ if (field.description) {
4
+ out.description = field.description;
5
+ }
6
+ if (field.type === "string" && field.enum) {
7
+ out.enum = [...field.enum];
8
+ }
9
+ if (field.type === "array") {
10
+ out.items = fieldToJsonSchema(field.items);
11
+ }
12
+ if (field.type === "record") {
13
+ out.type = "object";
14
+ out.additionalProperties = field.valueType === "any" ? true : { type: "string" };
15
+ }
16
+ if (field.type === "object") {
17
+ const properties = {};
18
+ const required = [];
19
+ for (const [key, value] of Object.entries(field.properties)) {
20
+ properties[key] = fieldToJsonSchema(value);
21
+ if (!value.optional) {
22
+ required.push(key);
23
+ }
24
+ }
25
+ out.properties = properties;
26
+ out.required = required;
27
+ out.additionalProperties = false;
28
+ }
29
+ return out;
41
30
  }
42
31
  /** Convert a tool's input spec to a standard JSON Schema object (for MCP). */
43
32
  export function toJsonSchema(input) {
44
- const properties = {};
45
- const required = [];
46
- for (const [key, field] of Object.entries(input)) {
47
- properties[key] = fieldToJsonSchema(field);
48
- if (!field.optional) {
49
- required.push(key);
50
- }
51
- }
52
- return { type: "object", properties, required, additionalProperties: false };
33
+ const properties = {};
34
+ const required = [];
35
+ for (const [key, field] of Object.entries(input)) {
36
+ properties[key] = fieldToJsonSchema(field);
37
+ if (!field.optional) {
38
+ required.push(key);
39
+ }
40
+ }
41
+ return {
42
+ type: "object",
43
+ properties,
44
+ required,
45
+ additionalProperties: false
46
+ };
53
47
  }
48
+
54
49
  //# sourceMappingURL=schema.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"schema.js","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AA8DH,SAAS,iBAAiB,CAAC,KAAY;IACrC,MAAM,GAAG,GAA4B,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,CAAC;IAC1D,IAAI,KAAK,CAAC,WAAW,EAAE,CAAC;QACtB,GAAG,CAAC,WAAW,GAAG,KAAK,CAAC,WAAW,CAAC;IACtC,CAAC;IACD,IAAI,KAAK,CAAC,IAAI,KAAK,QAAQ,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC;QAC1C,GAAG,CAAC,IAAI,GAAG,CAAC,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC;IAC7B,CAAC;IACD,IAAI,KAAK,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;QAC3B,GAAG,CAAC,KAAK,GAAG,iBAAiB,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IAC7C,CAAC;IACD,IAAI,KAAK,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;QAC5B,GAAG,CAAC,IAAI,GAAG,QAAQ,CAAC;QACpB,GAAG,CAAC,oBAAoB,GAAG,KAAK,CAAC,SAAS,KAAK,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;IACnF,CAAC;IACD,IAAI,KAAK,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;QAC5B,MAAM,UAAU,GAA4B,EAAE,CAAC;QAC/C,MAAM,QAAQ,GAAa,EAAE,CAAC;QAC9B,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,UAAU,CAAC,EAAE,CAAC;YAC5D,UAAU,CAAC,GAAG,CAAC,GAAG,iBAAiB,CAAC,KAAK,CAAC,CAAC;YAC3C,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC;gBACpB,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YACrB,CAAC;QACH,CAAC;QACD,GAAG,CAAC,UAAU,GAAG,UAAU,CAAC;QAC5B,GAAG,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACxB,GAAG,CAAC,oBAAoB,GAAG,KAAK,CAAC;IACnC,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,8EAA8E;AAC9E,MAAM,UAAU,YAAY,CAAC,KAAgB;IAC3C,MAAM,UAAU,GAA4B,EAAE,CAAC;IAC/C,MAAM,QAAQ,GAAa,EAAE,CAAC;IAC9B,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACjD,UAAU,CAAC,GAAG,CAAC,GAAG,iBAAiB,CAAC,KAAK,CAAC,CAAC;QAC3C,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC;YACpB,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACrB,CAAC;IACH,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,UAAU,EAAE,QAAQ,EAAE,oBAAoB,EAAE,KAAK,EAAE,CAAC;AAC/E,CAAC"}
1
+ {"mappings":"AAwEA,SAAS,kBAAkB,OAAuC;CAChE,MAAM,MAA+B,EAAE,MAAM,MAAM,KAAK;CACxD,IAAI,MAAM,aAAa;EACrB,IAAI,cAAc,MAAM;CAC1B;CACA,IAAI,MAAM,SAAS,YAAY,MAAM,MAAM;EACzC,IAAI,OAAO,CAAC,GAAG,MAAM,IAAI;CAC3B;CACA,IAAI,MAAM,SAAS,SAAS;EAC1B,IAAI,QAAQ,kBAAkB,MAAM,KAAK;CAC3C;CACA,IAAI,MAAM,SAAS,UAAU;EAC3B,IAAI,OAAO;EACX,IAAI,uBAAuB,MAAM,cAAc,QAAQ,OAAO,EAAE,MAAM,SAAS;CACjF;CACA,IAAI,MAAM,SAAS,UAAU;EAC3B,MAAM,aAAsC,CAAC;EAC7C,MAAM,WAAqB,CAAC;EAC5B,KAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,MAAM,UAAU,GAAG;GAC3D,WAAW,OAAO,kBAAkB,KAAK;GACzC,IAAI,CAAC,MAAM,UAAU;IACnB,SAAS,KAAK,GAAG;GACnB;EACF;EACA,IAAI,aAAa;EACjB,IAAI,WAAW;EACf,IAAI,uBAAuB;CAC7B;CACA,OAAO;AACT;;AAGA,OAAO,SAAS,aAAa,OAA8B;CACzD,MAAM,aAAsC,CAAC;CAC7C,MAAM,WAAqB,CAAC;CAC5B,KAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,KAAK,GAAG;EAChD,WAAW,OAAO,kBAAkB,KAAK;EACzC,IAAI,CAAC,MAAM,UAAU;GACnB,SAAS,KAAK,GAAG;EACnB;CACF;CACA,OAAO;EAAE,MAAM;EAAU;EAAY;EAAU,sBAAsB;CAAM;AAC7E","names":[],"sources":["../src/schema.ts"],"version":3,"file":"schema.js","sourceRoot":""}
@@ -1,40 +1,40 @@
1
1
  import type { JsonInput, ToolGroup } from "./schema.js";
2
2
  import type { ResolvedDevtoolsOptions } from "./types.js";
3
3
  /**
4
- * Execution context handed to every tool handler. The clock, randomness and
5
- * fetch are injected (not imported) so the deterministic groups stay unit-
6
- * testable: a test pins `now`/`randomBytes` and asserts exact output, and the
7
- * `http` group runs against a fake `fetchImpl` with no network.
8
- */
4
+ * Execution context handed to every tool handler. The clock, randomness and
5
+ * fetch are injected (not imported) so the deterministic groups stay unit-
6
+ * testable: a test pins `now`/`randomBytes` and asserts exact output, and the
7
+ * `http` group runs against a fake `fetchImpl` with no network.
8
+ */
9
9
  export interface ToolContext {
10
- options: ResolvedDevtoolsOptions;
11
- /** Current time. Default `() => new Date()`. */
12
- now: () => Date;
13
- /** Cryptographically-strong random bytes. Default `node:crypto.randomBytes`. */
14
- randomBytes: (size: number) => Buffer;
15
- /** Fetch implementation for the `http` group. Default the global `fetch`. */
16
- fetchImpl: typeof fetch;
10
+ options: ResolvedDevtoolsOptions;
11
+ /** Current time. Default `() => new Date()`. */
12
+ now: () => Date;
13
+ /** Cryptographically-strong random bytes. Default `node:crypto.randomBytes`. */
14
+ randomBytes: (size: number) => Buffer;
15
+ /** Fetch implementation for the `http` group. Default the global `fetch`. */
16
+ fetchImpl: typeof fetch;
17
17
  }
18
18
  /**
19
- * Adapter-neutral result of a tool call. `text` is always the self-sufficient
20
- * human/agent-readable output; `data` (json only) carries optional structured
21
- * metadata the OpenCode adapter surfaces as `metadata`. There is no image
22
- * variant — unlike the browser plugin, devtools tools return text/json only.
23
- */
19
+ * Adapter-neutral result of a tool call. `text` is always the self-sufficient
20
+ * human/agent-readable output; `data` (json only) carries optional structured
21
+ * metadata the OpenCode adapter surfaces as `metadata`. There is no image
22
+ * variant — unlike the browser plugin, devtools tools return text/json only.
23
+ */
24
24
  export type NeutralResult = {
25
- kind: "text";
26
- text: string;
25
+ kind: "text";
26
+ text: string;
27
27
  } | {
28
- kind: "json";
29
- text: string;
30
- data: unknown;
28
+ kind: "json";
29
+ text: string;
30
+ data: unknown;
31
31
  };
32
32
  export interface ToolSpec {
33
- name: string;
34
- group: ToolGroup;
35
- description: string;
36
- input: JsonInput;
37
- handler: (args: Record<string, unknown>, ctx: ToolContext) => NeutralResult | Promise<NeutralResult>;
33
+ name: string;
34
+ group: ToolGroup;
35
+ description: string;
36
+ input: JsonInput;
37
+ handler: (args: Record<string, unknown>, ctx: ToolContext) => NeutralResult | Promise<NeutralResult>;
38
38
  }
39
39
  export declare const text: (t: string) => NeutralResult;
40
40
  export declare const json: (data: unknown, t: string) => NeutralResult;
package/dist/tool-spec.js CHANGED
@@ -1,27 +1,35 @@
1
1
  // ─── result builders ─────────────────────────────────────────────────────────
2
- export const text = (t) => ({ kind: "text", text: t });
3
- export const json = (data, t) => ({ kind: "json", data, text: t });
2
+ export const text = (t) => ({
3
+ kind: "text",
4
+ text: t
5
+ });
6
+ export const json = (data, t) => ({
7
+ kind: "json",
8
+ data,
9
+ text: t
10
+ });
4
11
  // ─── arg coercion (args are pre-validated by the adapter's schema) ───────────
5
12
  export function reqString(args, key) {
6
- const v = args[key];
7
- if (typeof v !== "string") {
8
- throw new Error(`"${key}" must be a string`);
9
- }
10
- return v;
13
+ const v = args[key];
14
+ if (typeof v !== "string") {
15
+ throw new Error(`"${key}" must be a string`);
16
+ }
17
+ return v;
11
18
  }
12
19
  export function optString(args, key) {
13
- const v = args[key];
14
- return typeof v === "string" ? v : undefined;
20
+ const v = args[key];
21
+ return typeof v === "string" ? v : undefined;
15
22
  }
16
23
  export function reqNumber(args, key) {
17
- const v = args[key];
18
- if (typeof v !== "number" || Number.isNaN(v)) {
19
- throw new Error(`"${key}" must be a number`);
20
- }
21
- return v;
24
+ const v = args[key];
25
+ if (typeof v !== "number" || Number.isNaN(v)) {
26
+ throw new Error(`"${key}" must be a number`);
27
+ }
28
+ return v;
22
29
  }
23
30
  export function optBool(args, key) {
24
- const v = args[key];
25
- return typeof v === "boolean" ? v : undefined;
31
+ const v = args[key];
32
+ return typeof v === "boolean" ? v : undefined;
26
33
  }
34
+
27
35
  //# sourceMappingURL=tool-spec.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"tool-spec.js","sourceRoot":"","sources":["../src/tool-spec.ts"],"names":[],"mappings":"AAwCA,gFAAgF;AAChF,MAAM,CAAC,MAAM,IAAI,GAAG,CAAC,CAAS,EAAiB,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC;AAC9E,MAAM,CAAC,MAAM,IAAI,GAAG,CAAC,IAAa,EAAE,CAAS,EAAiB,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC;AAEnG,gFAAgF;AAChF,MAAM,UAAU,SAAS,CAAC,IAA6B,EAAE,GAAW;IAClE,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC;IACpB,IAAI,OAAO,CAAC,KAAK,QAAQ,EAAE,CAAC;QAC1B,MAAM,IAAI,KAAK,CAAC,IAAI,GAAG,oBAAoB,CAAC,CAAC;IAC/C,CAAC;IACD,OAAO,CAAC,CAAC;AACX,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,IAA6B,EAAE,GAAW;IAClE,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC;IACpB,OAAO,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;AAC/C,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,IAA6B,EAAE,GAAW;IAClE,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC;IACpB,IAAI,OAAO,CAAC,KAAK,QAAQ,IAAI,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;QAC7C,MAAM,IAAI,KAAK,CAAC,IAAI,GAAG,oBAAoB,CAAC,CAAC;IAC/C,CAAC;IACD,OAAO,CAAC,CAAC;AACX,CAAC;AAED,MAAM,UAAU,OAAO,CAAC,IAA6B,EAAE,GAAW;IAChE,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC;IACpB,OAAO,OAAO,CAAC,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;AAChD,CAAC"}
1
+ {"mappings":";AAyCA,OAAO,MAAM,QAAQ,OAA8B;CAAE,MAAM;CAAQ,MAAM;AAAE;AAC3E,OAAO,MAAM,QAAQ,MAAe,OAA8B;CAAE,MAAM;CAAQ;CAAM,MAAM;AAAE;;AAGhG,OAAO,SAAS,UAAU,MAA+B,KAAqB;CAC5E,MAAM,IAAI,KAAK;CACf,IAAI,OAAO,MAAM,UAAU;EACzB,MAAM,IAAI,MAAM,IAAI,IAAI,mBAAmB;CAC7C;CACA,OAAO;AACT;AAEA,OAAO,SAAS,UAAU,MAA+B,KAAiC;CACxF,MAAM,IAAI,KAAK;CACf,OAAO,OAAO,MAAM,WAAW,IAAI;AACrC;AAEA,OAAO,SAAS,UAAU,MAA+B,KAAqB;CAC5E,MAAM,IAAI,KAAK;CACf,IAAI,OAAO,MAAM,YAAY,OAAO,MAAM,CAAC,GAAG;EAC5C,MAAM,IAAI,MAAM,IAAI,IAAI,mBAAmB;CAC7C;CACA,OAAO;AACT;AAEA,OAAO,SAAS,QAAQ,MAA+B,KAAkC;CACvF,MAAM,IAAI,KAAK;CACf,OAAO,OAAO,MAAM,YAAY,IAAI;AACtC","names":[],"sources":["../src/tool-spec.ts"],"version":3,"file":"tool-spec.js","sourceRoot":""}
package/dist/tools.d.ts CHANGED
@@ -3,16 +3,16 @@ import type { Logger } from "./logging.js";
3
3
  import type { ToolContext } from "./tool-spec.js";
4
4
  import type { ResolvedDevtoolsOptions } from "./types.js";
5
5
  export interface ToolDeps {
6
- options: ResolvedDevtoolsOptions;
7
- logger: Logger;
8
- /** Inject the execution context (clock / randomness / fetch) for tests. */
9
- context?: Partial<Omit<ToolContext, "options">>;
6
+ options: ResolvedDevtoolsOptions;
7
+ logger: Logger;
8
+ /** Inject the execution context (clock / randomness / fetch) for tests. */
9
+ context?: Partial<Omit<ToolContext, "options">>;
10
10
  }
11
11
  /** Build the full execution context, applying DI overrides. */
12
12
  export declare function buildContext(options: ResolvedDevtoolsOptions, overrides?: Partial<Omit<ToolContext, "options">>): ToolContext;
13
13
  /**
14
- * Build the devtools tool map registered under `Hooks.tool`, filtered to the
15
- * enabled groups. Each tool is a thin adapter over the shared catalog: validate
16
- * args (zod), run the handler with the execution context, render the result.
17
- */
14
+ * Build the devtools tool map registered under `Hooks.tool`, filtered to the
15
+ * enabled groups. Each tool is a thin adapter over the shared catalog: validate
16
+ * args (zod), run the handler with the execution context, render the result.
17
+ */
18
18
  export declare function createDevtoolsTools(deps: ToolDeps): Record<string, ToolDefinition>;