@yeyuan98/opencode-bioresearcher-plugin 1.5.0 → 1.5.2-alpha.2

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.
Files changed (173) hide show
  1. package/README.md +50 -50
  2. package/dist/agents/bioresearcher/prompt.d.ts +1 -1
  3. package/dist/agents/bioresearcher/prompt.js +235 -27
  4. package/dist/agents/bioresearcherDR/prompt.d.ts +1 -1
  5. package/dist/agents/bioresearcherDR/prompt.js +8 -8
  6. package/dist/agents/bioresearcherDR_worker/prompt.d.ts +3 -2
  7. package/dist/agents/bioresearcherDR_worker/prompt.js +37 -12
  8. package/dist/index.js +6 -6
  9. package/dist/shared/tool-restrictions.d.ts +2 -2
  10. package/dist/shared/tool-restrictions.js +4 -3
  11. package/dist/skills/bioresearcher-core/SKILL.md +58 -1
  12. package/dist/skills/bioresearcher-core/patterns/bioresearcher/analysis-methods.md +551 -0
  13. package/dist/skills/bioresearcher-core/patterns/bioresearcher/best-practices.md +647 -0
  14. package/dist/skills/bioresearcher-core/patterns/bioresearcher/python-standards.md +944 -0
  15. package/dist/skills/bioresearcher-core/patterns/bioresearcher/report-template.md +613 -0
  16. package/dist/skills/bioresearcher-core/patterns/bioresearcher/tool-selection.md +481 -0
  17. package/dist/skills/bioresearcher-core/patterns/citations.md +234 -0
  18. package/dist/skills/bioresearcher-core/patterns/rate-limiting.md +167 -0
  19. package/dist/skills/bioresearcher-tests/README.md +90 -0
  20. package/dist/skills/bioresearcher-tests/SKILL.md +255 -0
  21. package/dist/skills/bioresearcher-tests/pyproject.toml +6 -0
  22. package/dist/skills/bioresearcher-tests/resources/json_samples/in_markdown.md.gz +0 -0
  23. package/dist/skills/bioresearcher-tests/resources/json_samples/nested_object.json.gz +0 -0
  24. package/dist/skills/bioresearcher-tests/resources/json_samples/schema_draft7.json.gz +0 -0
  25. package/dist/skills/bioresearcher-tests/resources/json_samples/simple_array.json.gz +0 -0
  26. package/dist/skills/bioresearcher-tests/resources/json_samples/simple_object.json.gz +0 -0
  27. package/dist/skills/bioresearcher-tests/resources/obo_sample.obo.gz +0 -0
  28. package/dist/skills/bioresearcher-tests/resources/pubmed_sample.xml.gz +0 -0
  29. package/dist/skills/bioresearcher-tests/resources/table_sample.xlsx.gz +0 -0
  30. package/dist/skills/bioresearcher-tests/test_cases/json_tests.md +137 -0
  31. package/dist/skills/bioresearcher-tests/test_cases/misc_tests.md +141 -0
  32. package/dist/skills/bioresearcher-tests/test_cases/parser_tests.md +80 -0
  33. package/dist/skills/bioresearcher-tests/test_cases/skill_tests.md +59 -0
  34. package/dist/skills/bioresearcher-tests/test_cases/table_tests.md +194 -0
  35. package/dist/skills/bioresearcher-tests/test_runner.py +607 -0
  36. package/dist/skills/env-jsonc-setup/SKILL.md +206 -206
  37. package/dist/skills/long-table-summary/SKILL.md +117 -46
  38. package/dist/skills/long-table-summary/combine_outputs.py +55 -9
  39. package/dist/skills/long-table-summary/generate_prompts.py +9 -0
  40. package/dist/skills/pubmed-weekly/pubmed_weekly.py +130 -29
  41. package/dist/{db-tools → tools/db}/backends/mysql/translator.js +23 -23
  42. package/dist/{db-tools → tools/db}/tools.js +34 -34
  43. package/dist/{misc-tools → tools/misc}/json-validate.js +4 -5
  44. package/dist/tools/sandbox/bash-parser.d.ts +17 -0
  45. package/dist/tools/sandbox/bash-parser.js +166 -0
  46. package/dist/tools/sandbox/escape-scenarios.test.d.ts +7 -0
  47. package/dist/tools/sandbox/escape-scenarios.test.js +182 -0
  48. package/dist/tools/sandbox/expander.d.ts +30 -0
  49. package/dist/tools/sandbox/expander.js +57 -0
  50. package/dist/tools/sandbox/final-verification.test.d.ts +6 -0
  51. package/dist/tools/sandbox/final-verification.test.js +70 -0
  52. package/dist/tools/sandbox/hooks.d.ts +25 -0
  53. package/dist/tools/sandbox/hooks.js +217 -0
  54. package/dist/tools/sandbox/index.d.ts +19 -0
  55. package/dist/tools/sandbox/index.js +24 -0
  56. package/dist/tools/sandbox/manager.d.ts +60 -0
  57. package/dist/tools/sandbox/manager.js +113 -0
  58. package/dist/tools/sandbox/sandbox.integration.test.d.ts +7 -0
  59. package/dist/tools/sandbox/sandbox.integration.test.js +106 -0
  60. package/dist/tools/sandbox/sandbox.test.d.ts +6 -0
  61. package/dist/tools/sandbox/sandbox.test.js +160 -0
  62. package/dist/tools/sandbox/tool.d.ts +66 -0
  63. package/dist/tools/sandbox/tool.js +163 -0
  64. package/dist/tools/sandbox/types.d.ts +38 -0
  65. package/dist/tools/sandbox/types.js +6 -0
  66. package/dist/tools/sandbox/validator.d.ts +33 -0
  67. package/dist/tools/sandbox/validator.js +150 -0
  68. package/dist/{skill-tools → tools/skill}/registry.js +1 -2
  69. package/dist/{table-tools → tools/table}/utils.js +4 -4
  70. package/package.json +1 -1
  71. package/dist/db-tools/executor.d.ts +0 -13
  72. package/dist/db-tools/executor.js +0 -54
  73. package/dist/db-tools/pool.d.ts +0 -8
  74. package/dist/db-tools/pool.js +0 -49
  75. package/dist/db-tools/tools/index.d.ts +0 -27
  76. package/dist/db-tools/tools/index.js +0 -191
  77. package/dist/db-tools/types.d.ts +0 -94
  78. package/dist/db-tools/types.js +0 -40
  79. package/dist/misc-tools/json-tools.d.ts +0 -33
  80. package/dist/misc-tools/json-tools.js +0 -187
  81. package/dist/skill/frontmatter.d.ts +0 -2
  82. package/dist/skill/frontmatter.js +0 -65
  83. package/dist/skill/index.d.ts +0 -3
  84. package/dist/skill/index.js +0 -2
  85. package/dist/skill/registry.d.ts +0 -11
  86. package/dist/skill/registry.js +0 -64
  87. package/dist/skill/tool.d.ts +0 -9
  88. package/dist/skill/tool.js +0 -115
  89. package/dist/skill/types.d.ts +0 -22
  90. package/dist/skill/types.js +0 -7
  91. /package/dist/{db-tools → tools/db}/backends/index.d.ts +0 -0
  92. /package/dist/{db-tools → tools/db}/backends/index.js +0 -0
  93. /package/dist/{db-tools → tools/db}/backends/mongodb/backend.d.ts +0 -0
  94. /package/dist/{db-tools → tools/db}/backends/mongodb/backend.js +0 -0
  95. /package/dist/{db-tools → tools/db}/backends/mongodb/connection.d.ts +0 -0
  96. /package/dist/{db-tools → tools/db}/backends/mongodb/connection.js +0 -0
  97. /package/dist/{db-tools → tools/db}/backends/mongodb/index.d.ts +0 -0
  98. /package/dist/{db-tools → tools/db}/backends/mongodb/index.js +0 -0
  99. /package/dist/{db-tools → tools/db}/backends/mongodb/translator.d.ts +0 -0
  100. /package/dist/{db-tools → tools/db}/backends/mongodb/translator.js +0 -0
  101. /package/dist/{db-tools → tools/db}/backends/mysql/backend.d.ts +0 -0
  102. /package/dist/{db-tools → tools/db}/backends/mysql/backend.js +0 -0
  103. /package/dist/{db-tools → tools/db}/backends/mysql/connection.d.ts +0 -0
  104. /package/dist/{db-tools → tools/db}/backends/mysql/connection.js +0 -0
  105. /package/dist/{db-tools → tools/db}/backends/mysql/index.d.ts +0 -0
  106. /package/dist/{db-tools → tools/db}/backends/mysql/index.js +0 -0
  107. /package/dist/{db-tools → tools/db}/backends/mysql/translator.d.ts +0 -0
  108. /package/dist/{db-tools → tools/db}/core/base.d.ts +0 -0
  109. /package/dist/{db-tools → tools/db}/core/base.js +0 -0
  110. /package/dist/{db-tools → tools/db}/core/config-loader.d.ts +0 -0
  111. /package/dist/{db-tools → tools/db}/core/config-loader.js +0 -0
  112. /package/dist/{db-tools → tools/db}/core/index.d.ts +0 -0
  113. /package/dist/{db-tools → tools/db}/core/index.js +0 -0
  114. /package/dist/{db-tools → tools/db}/core/jsonc-parser.d.ts +0 -0
  115. /package/dist/{db-tools → tools/db}/core/jsonc-parser.js +0 -0
  116. /package/dist/{db-tools → tools/db}/core/validator.d.ts +0 -0
  117. /package/dist/{db-tools → tools/db}/core/validator.js +0 -0
  118. /package/dist/{db-tools → tools/db}/index.d.ts +0 -0
  119. /package/dist/{db-tools → tools/db}/index.js +0 -0
  120. /package/dist/{db-tools → tools/db}/interface/backend.d.ts +0 -0
  121. /package/dist/{db-tools → tools/db}/interface/backend.js +0 -0
  122. /package/dist/{db-tools → tools/db}/interface/connection.d.ts +0 -0
  123. /package/dist/{db-tools → tools/db}/interface/connection.js +0 -0
  124. /package/dist/{db-tools → tools/db}/interface/index.d.ts +0 -0
  125. /package/dist/{db-tools → tools/db}/interface/index.js +0 -0
  126. /package/dist/{db-tools → tools/db}/interface/query.d.ts +0 -0
  127. /package/dist/{db-tools → tools/db}/interface/query.js +0 -0
  128. /package/dist/{db-tools → tools/db}/interface/schema.d.ts +0 -0
  129. /package/dist/{db-tools → tools/db}/interface/schema.js +0 -0
  130. /package/dist/{db-tools → tools/db}/tools.d.ts +0 -0
  131. /package/dist/{db-tools → tools/db}/utils.d.ts +0 -0
  132. /package/dist/{db-tools → tools/db}/utils.js +0 -0
  133. /package/dist/{misc-tools → tools/misc}/calculator.d.ts +0 -0
  134. /package/dist/{misc-tools → tools/misc}/calculator.js +0 -0
  135. /package/dist/{misc-tools → tools/misc}/index.d.ts +0 -0
  136. /package/dist/{misc-tools → tools/misc}/index.js +0 -0
  137. /package/dist/{misc-tools → tools/misc}/json-extract.d.ts +0 -0
  138. /package/dist/{misc-tools → tools/misc}/json-extract.js +0 -0
  139. /package/dist/{misc-tools → tools/misc}/json-infer.d.ts +0 -0
  140. /package/dist/{misc-tools → tools/misc}/json-infer.js +0 -0
  141. /package/dist/{misc-tools → tools/misc}/json-validate.d.ts +0 -0
  142. /package/dist/{misc-tools → tools/misc}/timer.d.ts +0 -0
  143. /package/dist/{misc-tools → tools/misc}/timer.js +0 -0
  144. /package/dist/{parser-tools → tools/parser}/obo/index.d.ts +0 -0
  145. /package/dist/{parser-tools → tools/parser}/obo/index.js +0 -0
  146. /package/dist/{parser-tools → tools/parser}/obo/obo.d.ts +0 -0
  147. /package/dist/{parser-tools → tools/parser}/obo/obo.js +0 -0
  148. /package/dist/{parser-tools → tools/parser}/obo/types.d.ts +0 -0
  149. /package/dist/{parser-tools → tools/parser}/obo/types.js +0 -0
  150. /package/dist/{parser-tools → tools/parser}/obo/utils.d.ts +0 -0
  151. /package/dist/{parser-tools → tools/parser}/obo/utils.js +0 -0
  152. /package/dist/{parser-tools → tools/parser}/pubmed/index.d.ts +0 -0
  153. /package/dist/{parser-tools → tools/parser}/pubmed/index.js +0 -0
  154. /package/dist/{parser-tools → tools/parser}/pubmed/pubmed.d.ts +0 -0
  155. /package/dist/{parser-tools → tools/parser}/pubmed/pubmed.js +0 -0
  156. /package/dist/{parser-tools → tools/parser}/pubmed/types.d.ts +0 -0
  157. /package/dist/{parser-tools → tools/parser}/pubmed/types.js +0 -0
  158. /package/dist/{parser-tools → tools/parser}/pubmed/utils.d.ts +0 -0
  159. /package/dist/{parser-tools → tools/parser}/pubmed/utils.js +0 -0
  160. /package/dist/{skill-tools → tools/skill}/frontmatter.d.ts +0 -0
  161. /package/dist/{skill-tools → tools/skill}/frontmatter.js +0 -0
  162. /package/dist/{skill-tools → tools/skill}/index.d.ts +0 -0
  163. /package/dist/{skill-tools → tools/skill}/index.js +0 -0
  164. /package/dist/{skill-tools → tools/skill}/registry.d.ts +0 -0
  165. /package/dist/{skill-tools → tools/skill}/tool.d.ts +0 -0
  166. /package/dist/{skill-tools → tools/skill}/tool.js +0 -0
  167. /package/dist/{skill-tools → tools/skill}/types.d.ts +0 -0
  168. /package/dist/{skill-tools → tools/skill}/types.js +0 -0
  169. /package/dist/{table-tools → tools/table}/index.d.ts +0 -0
  170. /package/dist/{table-tools → tools/table}/index.js +0 -0
  171. /package/dist/{table-tools → tools/table}/tools.d.ts +0 -0
  172. /package/dist/{table-tools → tools/table}/tools.js +0 -0
  173. /package/dist/{table-tools → tools/table}/utils.d.ts +0 -0
@@ -1,94 +0,0 @@
1
- import type { RowDataPacket } from 'mysql2/promise';
2
- export interface DbConfig {
3
- host: string;
4
- port: number;
5
- user: string;
6
- password: string;
7
- database: string;
8
- charset?: string;
9
- connectionTimeout?: number;
10
- }
11
- export interface QueryOptions {
12
- sql: string;
13
- params?: Record<string, unknown> | unknown[];
14
- }
15
- export interface FieldInfo {
16
- name: string;
17
- type: string;
18
- nullable: boolean;
19
- key: string | null;
20
- default: unknown;
21
- extra: string | null;
22
- }
23
- export interface StructuredError {
24
- code: string;
25
- message: string;
26
- details?: string;
27
- hints?: string[];
28
- }
29
- export interface ToolResponse<T> {
30
- success: boolean;
31
- data?: T;
32
- error?: StructuredError;
33
- metadata?: {
34
- executionTimeMs: number;
35
- [key: string]: unknown;
36
- };
37
- }
38
- export interface QueryResultData {
39
- rows: RowDataPacket[];
40
- rowCount: number;
41
- fields: FieldInfo[];
42
- }
43
- export interface QueryResult extends ToolResponse<QueryResultData> {
44
- success: true;
45
- data: QueryResultData;
46
- }
47
- export interface QueryError extends ToolResponse<never> {
48
- success: false;
49
- error: StructuredError;
50
- }
51
- export type QueryResponse = QueryResult | QueryError;
52
- export interface TableInfo {
53
- tableName: string;
54
- tableType: string;
55
- engine: string | null;
56
- rowCount: number | null;
57
- createdAt: string | null;
58
- comment: string | null;
59
- }
60
- export interface TablesResultData {
61
- tables: TableInfo[];
62
- count: number;
63
- }
64
- export interface ColumnSchema {
65
- field: string;
66
- type: string;
67
- nullable: boolean;
68
- key: string | null;
69
- defaultValue: unknown;
70
- extra: string | null;
71
- comment: string | null;
72
- }
73
- export interface SchemaResultData {
74
- table: string;
75
- columns: ColumnSchema[];
76
- columnCount: number;
77
- }
78
- export type MySQLError = Error & {
79
- code?: string;
80
- errno?: number;
81
- sql?: string;
82
- sqlState?: string;
83
- };
84
- export declare const DEFAULT_CONFIG: Partial<DbConfig>;
85
- export declare const ERROR_HINTS: {
86
- readonly CONNECTION: readonly ["Check that the database server is running", "Verify DB_HOST and DB_PORT environment variables", "Ensure network connectivity to the database"];
87
- readonly AUTH: readonly ["Verify DB_USER and DB_PASSWORD environment variables", "Check that the user has permissions for the database"];
88
- readonly UNKNOWN_TABLE: readonly ["Use dbListTables to see available tables", "Check the table name for typos"];
89
- readonly UNKNOWN_COLUMN: readonly ["Use dbDescribeTable to see available columns", "Check the column name for typos"];
90
- readonly SYNTAX: readonly ["Check your SQL syntax", "Ensure all identifiers are properly quoted if needed"];
91
- readonly GENERIC: readonly ["Check your query syntax", "Use dbListTables to see available tables", "Use dbDescribeTable to check column names"];
92
- };
93
- export declare function isQueryResult(response: QueryResponse): response is QueryResult;
94
- export declare function isQueryError(response: QueryResponse): response is QueryError;
@@ -1,40 +0,0 @@
1
- export const DEFAULT_CONFIG = {
2
- host: 'localhost',
3
- port: 3306,
4
- charset: 'utf8mb4',
5
- connectionTimeout: 10000,
6
- };
7
- export const ERROR_HINTS = {
8
- CONNECTION: [
9
- 'Check that the database server is running',
10
- 'Verify DB_HOST and DB_PORT environment variables',
11
- 'Ensure network connectivity to the database',
12
- ],
13
- AUTH: [
14
- 'Verify DB_USER and DB_PASSWORD environment variables',
15
- 'Check that the user has permissions for the database',
16
- ],
17
- UNKNOWN_TABLE: [
18
- 'Use dbListTables to see available tables',
19
- 'Check the table name for typos',
20
- ],
21
- UNKNOWN_COLUMN: [
22
- 'Use dbDescribeTable to see available columns',
23
- 'Check the column name for typos',
24
- ],
25
- SYNTAX: [
26
- 'Check your SQL syntax',
27
- 'Ensure all identifiers are properly quoted if needed',
28
- ],
29
- GENERIC: [
30
- 'Check your query syntax',
31
- 'Use dbListTables to see available tables',
32
- 'Use dbDescribeTable to check column names',
33
- ],
34
- };
35
- export function isQueryResult(response) {
36
- return response.success === true;
37
- }
38
- export function isQueryError(response) {
39
- return response.success === false;
40
- }
@@ -1,33 +0,0 @@
1
- import { ToolContext } from '@opencode-ai/plugin/tool';
2
- export declare const jsonValidate: {
3
- description: string;
4
- args: {
5
- data: any;
6
- schema: any;
7
- version: any;
8
- };
9
- execute(args: {
10
- [x: string]: any;
11
- }, context: ToolContext): Promise<string>;
12
- };
13
- export declare const jsonExtract: {
14
- description: string;
15
- args: {
16
- content: any;
17
- path: any;
18
- };
19
- execute(args: {
20
- [x: string]: any;
21
- }, context: ToolContext): Promise<string>;
22
- };
23
- export declare const jsonInferSchema: {
24
- description: string;
25
- args: {
26
- data: any;
27
- title: any;
28
- strict: any;
29
- };
30
- execute(args: {
31
- [x: string]: any;
32
- }, context: ToolContext): Promise<string>;
33
- };
@@ -1,187 +0,0 @@
1
- import { tool } from '@opencode-ai/plugin/tool';
2
- const zod = require('zod');
3
- function getFromJSONSchema() {
4
- if (zod.fromJSONSchema) {
5
- return zod.fromJSONSchema;
6
- }
7
- const v4classic = require('zod/v4/classic/external.js');
8
- if (v4classic.fromJSONSchema) {
9
- return v4classic.fromJSONSchema;
10
- }
11
- throw new Error('fromJSONSchema not available in zod package');
12
- }
13
- const fromJSONSchema = getFromJSONSchema();
14
- export const jsonValidate = tool({
15
- description: `Validate JSON data against a JSON Schema.
16
- Returns validation result with detailed error paths and messages.
17
- Supports JSON Schema draft-04, draft-07, draft-2020-12, and OpenAPI 3.0.`,
18
- args: {
19
- data: z.any().describe("JSON data to validate (object, array, or primitive)"),
20
- schema: z.any().describe("JSON Schema object to validate against"),
21
- version: z.enum(["draft-04", "draft-07", "draft-2020-12", "openapi-3.0"])
22
- .optional()
23
- .default("draft-2020-12")
24
- .describe("JSON Schema version (default: draft-2020-12)")
25
- },
26
- execute: async (args) => {
27
- try {
28
- const zodSchema = z.fromJSONSchema(args.schema, {
29
- defaultTarget: args.version
30
- });
31
- const result = zodSchema.safeParse(args.data);
32
- if (result.success) {
33
- return JSON.stringify({
34
- valid: true,
35
- data: result.data
36
- }, null, 2);
37
- }
38
- else {
39
- const errors = result.error.issues.map((issue) => ({
40
- path: issue.path.join('.') || '(root)',
41
- message: issue.message,
42
- code: issue.code
43
- }));
44
- return JSON.stringify({
45
- valid: false,
46
- errors,
47
- errorCount: errors.length
48
- }, null, 2);
49
- }
50
- }
51
- catch (e) {
52
- return JSON.stringify({
53
- valid: false,
54
- schemaError: e instanceof Error ? e.message : 'Unknown schema error'
55
- }, null, 2);
56
- }
57
- }
58
- });
59
- export const jsonExtract = tool({
60
- description: `Extract JSON from markdown or text content.
61
- Handles code blocks (\`\`\`json) and raw {...} or [...] patterns.
62
- Returns extracted JSON or error with details.`,
63
- args: {
64
- content: z.string().describe("Markdown or text content containing JSON"),
65
- path: z.string().optional()
66
- .describe("JSONPath to extract nested value (e.g., 'data.items.0')")
67
- },
68
- execute: async (args) => {
69
- let jsonStr = null;
70
- const codeBlockMatch = args.content.match(/```(?:json)?\s*([\s\S]*?)\s*```/);
71
- if (codeBlockMatch) {
72
- jsonStr = codeBlockMatch[1].trim();
73
- }
74
- if (!jsonStr) {
75
- const objStart = args.content.indexOf('{');
76
- const arrStart = args.content.indexOf('[');
77
- if (objStart !== -1 || arrStart !== -1) {
78
- const startChar = objStart !== -1 && (arrStart === -1 || objStart < arrStart) ? '{' : '[';
79
- const endChar = startChar === '{' ? '}' : ']';
80
- const startIndex = args.content.indexOf(startChar);
81
- let depth = 0;
82
- let endIndex = -1;
83
- for (let i = startIndex; i < args.content.length; i++) {
84
- if (args.content[i] === startChar)
85
- depth++;
86
- if (args.content[i] === endChar)
87
- depth--;
88
- if (depth === 0) {
89
- endIndex = i + 1;
90
- break;
91
- }
92
- }
93
- if (endIndex !== -1) {
94
- jsonStr = args.content.slice(startIndex, endIndex);
95
- }
96
- }
97
- }
98
- if (!jsonStr) {
99
- return JSON.stringify({
100
- success: false,
101
- error: "No JSON found in content"
102
- }, null, 2);
103
- }
104
- try {
105
- let data = JSON.parse(jsonStr);
106
- if (args.path) {
107
- const parts = args.path.split('.');
108
- for (const part of parts) {
109
- if (data === null || data === undefined) {
110
- return JSON.stringify({
111
- success: false,
112
- error: `Path '${args.path}' not found (null/undefined at '${part}')`
113
- }, null, 2);
114
- }
115
- data = data[part];
116
- }
117
- }
118
- return JSON.stringify({
119
- success: true,
120
- data
121
- }, null, 2);
122
- }
123
- catch (e) {
124
- return JSON.stringify({
125
- success: false,
126
- error: `Invalid JSON: ${e instanceof Error ? e.message : 'Unknown error'}`,
127
- extractedText: jsonStr.length > 200 ? jsonStr.slice(0, 200) + '...' : jsonStr
128
- }, null, 2);
129
- }
130
- }
131
- });
132
- export const jsonInferSchema = tool({
133
- description: `Infer a JSON Schema from example JSON data.
134
- Useful for creating schemas from sample data.`,
135
- args: {
136
- data: z.any().describe("Example JSON data to infer schema from"),
137
- title: z.string().optional().describe("Optional schema title"),
138
- strict: z.boolean().optional().default(false)
139
- .describe("If true, set additionalProperties: false for objects")
140
- },
141
- execute: async (args) => {
142
- function inferType(value, strict) {
143
- if (value === null)
144
- return { type: "null" };
145
- if (typeof value === "string")
146
- return { type: "string" };
147
- if (typeof value === "boolean")
148
- return { type: "boolean" };
149
- if (typeof value === "number") {
150
- return Number.isInteger(value) ? { type: "integer" } : { type: "number" };
151
- }
152
- if (Array.isArray(value)) {
153
- if (value.length === 0) {
154
- return { type: "array", items: {} };
155
- }
156
- return { type: "array", items: inferType(value[0], strict) };
157
- }
158
- if (typeof value === "object" && value !== null) {
159
- const obj = value;
160
- const properties = {};
161
- const required = [];
162
- for (const [key, val] of Object.entries(obj)) {
163
- properties[key] = inferType(val, strict);
164
- required.push(key);
165
- }
166
- const schema = {
167
- type: "object",
168
- properties,
169
- required
170
- };
171
- if (strict) {
172
- schema.additionalProperties = false;
173
- }
174
- return schema;
175
- }
176
- return {};
177
- }
178
- const schema = {
179
- $schema: "https://json-schema.org/draft/2020-12/schema",
180
- ...inferType(args.data, args.strict ?? false)
181
- };
182
- if (args.title) {
183
- schema.title = args.title;
184
- }
185
- return JSON.stringify(schema, null, 2);
186
- }
187
- });
@@ -1,2 +0,0 @@
1
- import { ParsedSkill } from "./types";
2
- export declare function parseSkillFrontmatter(filePath: string): Promise<ParsedSkill | null>;
@@ -1,65 +0,0 @@
1
- import { ExtendedSkillFrontmatter } from "./types";
2
- const FRONTMATTER_REGEX = /^---\s*\n([\s\S]*?)\n---\s*\n([\s\S]*)$/;
3
- export async function parseSkillFrontmatter(filePath) {
4
- const file = Bun.file(filePath);
5
- const content = await file.text().catch(() => null);
6
- if (!content)
7
- return null;
8
- const match = content.match(FRONTMATTER_REGEX);
9
- if (!match)
10
- return null;
11
- const [, frontmatterYaml, body] = match;
12
- let data;
13
- try {
14
- data = parseSimpleYaml(frontmatterYaml);
15
- }
16
- catch {
17
- return null;
18
- }
19
- const parsed = ExtendedSkillFrontmatter.safeParse(data);
20
- if (!parsed.success)
21
- return null;
22
- return {
23
- frontmatter: parsed.data,
24
- content: body.trim(),
25
- location: filePath,
26
- };
27
- }
28
- function parseSimpleYaml(yaml) {
29
- const result = {};
30
- let currentKey = "";
31
- let currentArray = null;
32
- for (const line of yaml.split("\n")) {
33
- const trimmed = line.trimEnd();
34
- if (!trimmed)
35
- continue;
36
- if (trimmed.startsWith(" - ")) {
37
- if (currentArray !== null) {
38
- currentArray.push(trimmed.slice(4));
39
- }
40
- continue;
41
- }
42
- if (currentArray !== null && currentKey) {
43
- result[currentKey] = currentArray;
44
- currentArray = null;
45
- }
46
- const colonIndex = trimmed.indexOf(":");
47
- if (colonIndex === -1)
48
- continue;
49
- const key = trimmed.slice(0, colonIndex).trim();
50
- const value = trimmed.slice(colonIndex + 1).trim();
51
- if (value === "") {
52
- currentKey = key;
53
- currentArray = [];
54
- }
55
- else {
56
- result[key] = value;
57
- currentKey = "";
58
- currentArray = null;
59
- }
60
- }
61
- if (currentArray !== null && currentKey) {
62
- result[currentKey] = currentArray;
63
- }
64
- return result;
65
- }
@@ -1,3 +0,0 @@
1
- export { SkillTool } from "./tool";
2
- export { getAllSkills, getSkill, clearCache, SkillConflictError } from "./registry";
3
- export type { ExtendedSkill, ExtendedSkillFrontmatter, ParsedSkill } from "./types";
@@ -1,2 +0,0 @@
1
- export { SkillTool } from "./tool";
2
- export { getAllSkills, getSkill, clearCache, SkillConflictError } from "./registry";
@@ -1,11 +0,0 @@
1
- import { ExtendedSkill } from "./types";
2
- export declare class SkillConflictError extends Error {
3
- skillName: string;
4
- pluginLocation: string;
5
- userLocation: string;
6
- constructor(skillName: string, pluginLocation: string, userLocation: string);
7
- }
8
- export declare function loadPluginSkills(): Promise<ExtendedSkill[]>;
9
- export declare function getAllSkills(): Promise<ExtendedSkill[]>;
10
- export declare function getSkill(name: string): Promise<ExtendedSkill | undefined>;
11
- export declare function clearCache(): void;
@@ -1,64 +0,0 @@
1
- import path from "path";
2
- import { fileURLToPath } from "url";
3
- import { parseSkillFrontmatter } from "./frontmatter";
4
- const SKILL_GLOB = new Bun.Glob("**/SKILL.md");
5
- export class SkillConflictError extends Error {
6
- skillName;
7
- pluginLocation;
8
- userLocation;
9
- constructor(skillName, pluginLocation, userLocation) {
10
- super(`Skill name conflict: "${skillName}" is reserved by the plugin. ` +
11
- `Please rename your skill at ${userLocation}.`);
12
- this.skillName = skillName;
13
- this.pluginLocation = pluginLocation;
14
- this.userLocation = userLocation;
15
- this.name = "SkillConflictError";
16
- }
17
- }
18
- function getPluginSkillsDir() {
19
- const currentDir = path.dirname(fileURLToPath(import.meta.url));
20
- return path.join(currentDir, "..", "skills");
21
- }
22
- export async function loadPluginSkills() {
23
- const skillsDir = getPluginSkillsDir();
24
- const skills = [];
25
- try {
26
- for await (const match of SKILL_GLOB.scan({
27
- cwd: skillsDir,
28
- absolute: true,
29
- onlyFiles: true,
30
- })) {
31
- const parsed = await parseSkillFrontmatter(match);
32
- if (!parsed)
33
- continue;
34
- skills.push({
35
- name: parsed.frontmatter.name,
36
- description: parsed.frontmatter.description,
37
- location: parsed.location,
38
- content: parsed.content,
39
- agent: parsed.frontmatter.agent,
40
- allowedTools: parsed.frontmatter.allowedTools,
41
- source: "plugin",
42
- });
43
- }
44
- }
45
- catch {
46
- // Plugin skills directory may not exist
47
- }
48
- return skills;
49
- }
50
- let cachedSkills = null;
51
- export async function getAllSkills() {
52
- if (cachedSkills)
53
- return cachedSkills;
54
- const pluginSkills = await loadPluginSkills();
55
- cachedSkills = pluginSkills;
56
- return pluginSkills;
57
- }
58
- export async function getSkill(name) {
59
- const skills = await getAllSkills();
60
- return skills.find((s) => s.name === name);
61
- }
62
- export function clearCache() {
63
- cachedSkills = null;
64
- }
@@ -1,9 +0,0 @@
1
- export declare const SkillTool: {
2
- description: string;
3
- args: {
4
- name: import("zod").ZodString;
5
- };
6
- execute(args: {
7
- name: string;
8
- }, context: import("@opencode-ai/plugin").ToolContext): Promise<string>;
9
- };
@@ -1,115 +0,0 @@
1
- import path from "path";
2
- import { pathToFileURL } from "url";
3
- import { tool } from "@opencode-ai/plugin";
4
- import { getAllSkills, getSkill } from "./registry";
5
- function formatDescription(skills) {
6
- if (skills.length === 0) {
7
- return "Load a specialized skill that provides domain-specific instructions and workflows. No skills are currently available.";
8
- }
9
- return [
10
- "Load a specialized skill that provides domain-specific instructions and workflows.",
11
- "",
12
- "When you recognize that a task matches one of the available skills listed below, use this tool to load the full skill instructions.",
13
- "",
14
- "The skill will inject detailed instructions, workflows, and access to bundled resources (scripts, references, templates) into the conversation context.",
15
- "",
16
- 'Tool output includes a `<skill_content name="...">` block with the loaded content.',
17
- "",
18
- "The following skills provide specialized sets of instructions for particular tasks:",
19
- "",
20
- "<available_skills>",
21
- ...skills.flatMap((skill) => [
22
- ` <skill>`,
23
- ` <name>${skill.name}</name>`,
24
- ` <description>${skill.description}</description>`,
25
- skill.agent ? ` <restricted_to_agent>${skill.agent}</restricted_to_agent>` : null,
26
- ` <location>${pathToFileURL(skill.location).href}</location>`,
27
- ` </skill>`,
28
- ].filter(Boolean)),
29
- "</available_skills>",
30
- ].join("\n");
31
- }
32
- async function listSkillFiles(dir, signal) {
33
- const limit = 10;
34
- const files = [];
35
- const glob = new Bun.Glob("*");
36
- try {
37
- for await (const file of glob.scan({ cwd: dir, onlyFiles: true })) {
38
- if (file === "SKILL.md")
39
- continue;
40
- files.push(path.resolve(dir, file));
41
- if (files.length >= limit)
42
- break;
43
- }
44
- }
45
- catch {
46
- // Directory may not exist
47
- }
48
- return files.map((f) => `<file>${f}</file>`).join("\n");
49
- }
50
- export const SkillTool = tool({
51
- description: "", // Set dynamically below
52
- args: {
53
- name: tool.schema.string().describe("The name of the skill from available_skills"),
54
- },
55
- async execute(params, ctx) {
56
- const skills = await getAllSkills();
57
- const skill = await getSkill(params.name);
58
- if (!skill) {
59
- const available = skills.map((s) => s.name).join(", ");
60
- throw new Error(`Skill "${params.name}" not found. Available skills: ${available || "none"}`);
61
- }
62
- // Agent routing enforcement
63
- if (skill.agent && ctx.agent !== skill.agent) {
64
- throw new Error(`Skill "${skill.name}" is restricted to agent "${skill.agent}". Current agent: "${ctx.agent || "unknown"}".`);
65
- }
66
- await ctx.ask({
67
- permission: "skill",
68
- patterns: [params.name],
69
- always: [params.name],
70
- metadata: {},
71
- });
72
- const dir = path.dirname(skill.location);
73
- const base = pathToFileURL(dir).href;
74
- const files = await listSkillFiles(dir, ctx.abort);
75
- const allowedToolsSection = skill.allowedTools
76
- ? [
77
- "",
78
- "<allowed_tools>",
79
- "This skill is designed to work with the following tools:",
80
- ...skill.allowedTools.map((t) => ` - ${t}`),
81
- "</allowed_tools>",
82
- ].join("\n")
83
- : "";
84
- ctx.metadata({
85
- title: `Loaded skill: ${skill.name}`,
86
- metadata: {
87
- name: skill.name,
88
- dir,
89
- allowedTools: skill.allowedTools,
90
- agent: skill.agent,
91
- },
92
- });
93
- return [
94
- `<skill_content name="${skill.name}">`,
95
- `# Skill: ${skill.name}`,
96
- "",
97
- skill.content.trim(),
98
- "",
99
- `Base directory for this skill: ${base}`,
100
- "Relative paths in this skill (e.g., scripts/, reference/) are relative to this base directory.",
101
- "Note: file list is sampled.",
102
- "",
103
- "<skill_files>",
104
- files,
105
- "</skill_files>",
106
- allowedToolsSection,
107
- "</skill_content>",
108
- ].join("\n");
109
- },
110
- });
111
- // Set description dynamically based on available skills
112
- getAllSkills().then((skills) => {
113
- ;
114
- SkillTool.description = formatDescription(skills);
115
- });
@@ -1,22 +0,0 @@
1
- import z from "zod";
2
- export declare const ExtendedSkillFrontmatter: z.ZodObject<{
3
- name: z.ZodString;
4
- description: z.ZodString;
5
- agent: z.ZodOptional<z.ZodString>;
6
- allowedTools: z.ZodOptional<z.ZodArray<z.ZodString>>;
7
- }, z.core.$strip>;
8
- export type ExtendedSkillFrontmatter = z.infer<typeof ExtendedSkillFrontmatter>;
9
- export interface ExtendedSkill {
10
- name: string;
11
- description: string;
12
- location: string;
13
- content: string;
14
- agent?: string;
15
- allowedTools?: string[];
16
- source: "plugin";
17
- }
18
- export interface ParsedSkill {
19
- frontmatter: ExtendedSkillFrontmatter;
20
- content: string;
21
- location: string;
22
- }
@@ -1,7 +0,0 @@
1
- import z from "zod";
2
- export const ExtendedSkillFrontmatter = z.object({
3
- name: z.string(),
4
- description: z.string(),
5
- agent: z.string().optional(),
6
- allowedTools: z.array(z.string()).optional(),
7
- });
File without changes
File without changes