@skastr0/quartz-opencode-plugin 0.1.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/LICENSE +21 -0
- package/README.md +76 -0
- package/dist/server.d.ts +7 -0
- package/dist/server.js +351 -0
- package/package.json +55 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Guilherme Castro
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# @skastr0/quartz-opencode-plugin
|
|
2
|
+
|
|
3
|
+
OpenCode plugin wrapper for Quartz TypeScript code intelligence.
|
|
4
|
+
|
|
5
|
+
## Status
|
|
6
|
+
|
|
7
|
+
Experimental. The plugin is publishable as a Bun/ESM package, but the repository is still using explicit release gates before any real npm upload.
|
|
8
|
+
|
|
9
|
+
## Install
|
|
10
|
+
|
|
11
|
+
After the first npm release:
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
bun add -d @skastr0/quartz-opencode-plugin
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
The package exports `@skastr0/quartz-opencode-plugin/server`.
|
|
18
|
+
|
|
19
|
+
## Build
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
bun run build
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
The bundle is written to `dist/server.js` and exported as `@skastr0/quartz-opencode-plugin/server`.
|
|
26
|
+
|
|
27
|
+
## Runtime Behavior
|
|
28
|
+
|
|
29
|
+
The plugin roots Quartz at the OpenCode workspace directory. It creates one Effect runtime, reuses the analyzer across tool calls, and marks the analyzer cache dirty after file-modifying tools such as `edit`, `write`, or `morph-mcp_edit_file`.
|
|
30
|
+
|
|
31
|
+
Use the optional `package` argument when the workspace has multiple discovered TypeScript packages.
|
|
32
|
+
|
|
33
|
+
## Tools
|
|
34
|
+
|
|
35
|
+
Discovery:
|
|
36
|
+
|
|
37
|
+
- `type_packages`
|
|
38
|
+
- `type_symbols`
|
|
39
|
+
- `type_info`
|
|
40
|
+
- `type_expand`
|
|
41
|
+
- `type_related`
|
|
42
|
+
- `type_search`
|
|
43
|
+
|
|
44
|
+
Analysis:
|
|
45
|
+
|
|
46
|
+
- `type_eval`
|
|
47
|
+
- `type_diagnostics`
|
|
48
|
+
- `type_check_snippet`
|
|
49
|
+
- `type_at_position`
|
|
50
|
+
- `type_file`
|
|
51
|
+
- `type_refresh`
|
|
52
|
+
|
|
53
|
+
Relationships and refactors:
|
|
54
|
+
|
|
55
|
+
- `type_compatible`
|
|
56
|
+
- `type_graph`
|
|
57
|
+
- `type_refactor_preview`
|
|
58
|
+
- `type_why_error`
|
|
59
|
+
- `type_explain`
|
|
60
|
+
- `type_transform_search`
|
|
61
|
+
|
|
62
|
+
## Examples
|
|
63
|
+
|
|
64
|
+
```json
|
|
65
|
+
{"tool":"type_symbols","args":{"pattern":"^User","kind":"interface","limit":10}}
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
```json
|
|
69
|
+
{"tool":"type_info","args":{"symbol":"User"}}
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
```json
|
|
73
|
+
{"tool":"type_transform_search","args":{"from":"User","to":"UserDTO","limit":5}}
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
The plugin returns JSON strings for most tool results, matching the core analyzer data shapes. `type_refresh` clears cached TypeScript projects and returns the analyzer refresh result.
|
package/dist/server.d.ts
ADDED
package/dist/server.js
ADDED
|
@@ -0,0 +1,351 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
// src/server.ts
|
|
3
|
+
import { tool } from "@opencode-ai/plugin";
|
|
4
|
+
import { Effect, ManagedRuntime } from "effect";
|
|
5
|
+
import { CoreLayer, TypeAnalyzerService } from "@skastr0/quartz-core";
|
|
6
|
+
var run = (effect) => Effect.runPromise(effect.pipe(Effect.mapError((error) => error instanceof Error ? error : new Error(String(error)))));
|
|
7
|
+
var optionalPackageArg = tool.schema.string().optional().describe("Package/directory to analyze. Omit for root or single-package projects.");
|
|
8
|
+
var limitArg = tool.schema.number().optional().describe("Maximum number of results");
|
|
9
|
+
var json = (value) => JSON.stringify(value, null, 2);
|
|
10
|
+
var FILE_MODIFYING_TOOLS = new Set(["edit", "morph-mcp_edit_file", "write"]);
|
|
11
|
+
var packageOption = (packageName) => packageName === undefined ? {} : { packageName };
|
|
12
|
+
var optionalOption = (key, value) => value === undefined ? {} : { [key]: value };
|
|
13
|
+
var createDiscoveryTools = (analyzer) => ({
|
|
14
|
+
type_packages: tool({
|
|
15
|
+
description: "List TypeScript packages discovered from tsconfig.json files.",
|
|
16
|
+
args: {},
|
|
17
|
+
async execute() {
|
|
18
|
+
return json(await run(analyzer.getPackages()));
|
|
19
|
+
}
|
|
20
|
+
}),
|
|
21
|
+
type_symbols: tool({
|
|
22
|
+
description: "List exported TypeScript symbols.",
|
|
23
|
+
args: {
|
|
24
|
+
package: optionalPackageArg,
|
|
25
|
+
pattern: tool.schema.string().optional().describe("Case-insensitive regex pattern"),
|
|
26
|
+
kind: tool.schema.string().optional().describe("Symbol kind, such as interface, type, class, or function"),
|
|
27
|
+
limit: limitArg
|
|
28
|
+
},
|
|
29
|
+
async execute(args) {
|
|
30
|
+
return json(await run(analyzer.listSymbols({
|
|
31
|
+
...packageOption(args.package),
|
|
32
|
+
...optionalOption("pattern", args.pattern),
|
|
33
|
+
...optionalOption("kind", args.kind),
|
|
34
|
+
...optionalOption("limit", args.limit)
|
|
35
|
+
})));
|
|
36
|
+
}
|
|
37
|
+
}),
|
|
38
|
+
type_info: tool({
|
|
39
|
+
description: "Show type information for an exported TypeScript symbol.",
|
|
40
|
+
args: {
|
|
41
|
+
symbol: tool.schema.string().describe("Exported symbol name"),
|
|
42
|
+
package: optionalPackageArg
|
|
43
|
+
},
|
|
44
|
+
async execute(args) {
|
|
45
|
+
return json(await run(analyzer.getTypeInfo(args.symbol, args.package)));
|
|
46
|
+
}
|
|
47
|
+
}),
|
|
48
|
+
type_expand: tool({
|
|
49
|
+
description: "Expand an exported TypeScript symbol type.",
|
|
50
|
+
args: {
|
|
51
|
+
symbol: tool.schema.string().describe("Exported symbol name"),
|
|
52
|
+
package: optionalPackageArg
|
|
53
|
+
},
|
|
54
|
+
async execute(args) {
|
|
55
|
+
return json(await run(analyzer.expandType(args.symbol, args.package)));
|
|
56
|
+
}
|
|
57
|
+
}),
|
|
58
|
+
type_related: tool({
|
|
59
|
+
description: "Find types that reference or are referenced by a TypeScript symbol.",
|
|
60
|
+
args: {
|
|
61
|
+
symbol: tool.schema.string().describe("Exported symbol name"),
|
|
62
|
+
package: optionalPackageArg
|
|
63
|
+
},
|
|
64
|
+
async execute(args) {
|
|
65
|
+
return json(await run(analyzer.findRelated(args.symbol, args.package)));
|
|
66
|
+
}
|
|
67
|
+
}),
|
|
68
|
+
type_search: tool({
|
|
69
|
+
description: "Search exported types by name, property, or base type.",
|
|
70
|
+
args: {
|
|
71
|
+
query: tool.schema.string().describe("Case-insensitive symbol query"),
|
|
72
|
+
package: optionalPackageArg,
|
|
73
|
+
pattern: tool.schema.string().optional().describe("Case-insensitive regex pattern"),
|
|
74
|
+
hasProperty: tool.schema.string().optional().describe("Only include types with this property"),
|
|
75
|
+
extends: tool.schema.string().optional().describe("Only include types extending this base symbol"),
|
|
76
|
+
limit: limitArg
|
|
77
|
+
},
|
|
78
|
+
async execute(args) {
|
|
79
|
+
return json(await run(analyzer.searchTypes({
|
|
80
|
+
query: args.query,
|
|
81
|
+
...optionalOption("pattern", args.pattern),
|
|
82
|
+
...optionalOption("hasProperty", args.hasProperty),
|
|
83
|
+
...optionalOption("extends", args.extends),
|
|
84
|
+
...packageOption(args.package),
|
|
85
|
+
...optionalOption("limit", args.limit)
|
|
86
|
+
})));
|
|
87
|
+
}
|
|
88
|
+
})
|
|
89
|
+
});
|
|
90
|
+
var createAnalysisTools = (analyzer) => ({
|
|
91
|
+
type_eval: tool({
|
|
92
|
+
description: "Evaluate a TypeScript type expression and return the computed type.",
|
|
93
|
+
args: {
|
|
94
|
+
expression: tool.schema.string().describe("TypeScript type expression"),
|
|
95
|
+
package: optionalPackageArg
|
|
96
|
+
},
|
|
97
|
+
async execute(args) {
|
|
98
|
+
return json(await run(analyzer.evalType(args.expression, args.package)));
|
|
99
|
+
}
|
|
100
|
+
}),
|
|
101
|
+
type_diagnostics: tool({
|
|
102
|
+
description: "Show TypeScript diagnostics.",
|
|
103
|
+
args: {
|
|
104
|
+
package: optionalPackageArg,
|
|
105
|
+
explain: tool.schema.boolean().optional().describe("Include explanations for diagnostics")
|
|
106
|
+
},
|
|
107
|
+
async execute(args) {
|
|
108
|
+
return json(await run(analyzer.getDiagnostics({
|
|
109
|
+
...packageOption(args.package),
|
|
110
|
+
...optionalOption("explain", args.explain)
|
|
111
|
+
})));
|
|
112
|
+
}
|
|
113
|
+
}),
|
|
114
|
+
type_check_snippet: tool({
|
|
115
|
+
description: "Type-check a TypeScript code snippet without writing to disk.",
|
|
116
|
+
args: {
|
|
117
|
+
code: tool.schema.string().describe("TypeScript code snippet"),
|
|
118
|
+
package: optionalPackageArg
|
|
119
|
+
},
|
|
120
|
+
async execute(args) {
|
|
121
|
+
return json(await run(analyzer.checkSnippet(args.code, args.package)));
|
|
122
|
+
}
|
|
123
|
+
}),
|
|
124
|
+
type_at_position: tool({
|
|
125
|
+
description: "Show the type at a TypeScript source position.",
|
|
126
|
+
args: {
|
|
127
|
+
file: tool.schema.string().describe("TypeScript file path"),
|
|
128
|
+
line: tool.schema.number().describe("One-based line number"),
|
|
129
|
+
column: tool.schema.number().describe("One-based column number"),
|
|
130
|
+
package: optionalPackageArg
|
|
131
|
+
},
|
|
132
|
+
async execute(args) {
|
|
133
|
+
return json(await run(analyzer.getTypeAtPosition(args.file, args.line, args.column, args.package)));
|
|
134
|
+
}
|
|
135
|
+
}),
|
|
136
|
+
type_file: tool({
|
|
137
|
+
description: "Inspect declarations in a specific TypeScript file.",
|
|
138
|
+
args: {
|
|
139
|
+
file: tool.schema.string().describe("TypeScript file path"),
|
|
140
|
+
symbol: tool.schema.string().optional().describe("Optional declaration name regex"),
|
|
141
|
+
includePrivate: tool.schema.boolean().optional().describe("Include non-exported declarations"),
|
|
142
|
+
package: optionalPackageArg
|
|
143
|
+
},
|
|
144
|
+
async execute(args) {
|
|
145
|
+
return json(await run(analyzer.getFileDeclarations(args.file, {
|
|
146
|
+
...packageOption(args.package),
|
|
147
|
+
...optionalOption("symbol", args.symbol),
|
|
148
|
+
...optionalOption("includePrivate", args.includePrivate)
|
|
149
|
+
})));
|
|
150
|
+
}
|
|
151
|
+
}),
|
|
152
|
+
type_refresh: tool({
|
|
153
|
+
description: "Clear cached TypeScript projects to pick up external file changes.",
|
|
154
|
+
args: {
|
|
155
|
+
package: optionalPackageArg
|
|
156
|
+
},
|
|
157
|
+
async execute(args) {
|
|
158
|
+
return await run(analyzer.refresh(args.package));
|
|
159
|
+
}
|
|
160
|
+
})
|
|
161
|
+
});
|
|
162
|
+
var createRelationshipTools = (analyzer) => ({
|
|
163
|
+
...createCompatibilityTools(analyzer),
|
|
164
|
+
...createGraphTools(analyzer),
|
|
165
|
+
...createRefactorTools(analyzer),
|
|
166
|
+
...createExplanationTools(analyzer),
|
|
167
|
+
...createTransformSearchTools(analyzer),
|
|
168
|
+
...createVerifyContractTools(analyzer)
|
|
169
|
+
});
|
|
170
|
+
var createCompatibilityTools = (analyzer) => ({
|
|
171
|
+
type_compatible: tool({
|
|
172
|
+
description: "Check if one type is assignable to another.",
|
|
173
|
+
args: {
|
|
174
|
+
from: tool.schema.string().describe("Source type or symbol"),
|
|
175
|
+
to: tool.schema.string().describe("Target type or symbol"),
|
|
176
|
+
package: optionalPackageArg
|
|
177
|
+
},
|
|
178
|
+
async execute(args) {
|
|
179
|
+
return json(await run(analyzer.checkCompatibility(args.from, args.to, args.package)));
|
|
180
|
+
}
|
|
181
|
+
})
|
|
182
|
+
});
|
|
183
|
+
var createGraphTools = (analyzer) => ({
|
|
184
|
+
type_graph: tool({
|
|
185
|
+
description: "Generate a type dependency graph as Mermaid or DOT.",
|
|
186
|
+
args: {
|
|
187
|
+
symbol: tool.schema.string().describe("Root symbol"),
|
|
188
|
+
depth: tool.schema.number().optional().describe("Traversal depth"),
|
|
189
|
+
format: tool.schema.enum(["mermaid", "dot"]).optional().describe("Graph output format"),
|
|
190
|
+
package: optionalPackageArg
|
|
191
|
+
},
|
|
192
|
+
async execute(args) {
|
|
193
|
+
return json(await run(analyzer.generateGraph(args.symbol, {
|
|
194
|
+
...packageOption(args.package),
|
|
195
|
+
...optionalOption("depth", args.depth),
|
|
196
|
+
...optionalOption("format", args.format)
|
|
197
|
+
})));
|
|
198
|
+
}
|
|
199
|
+
})
|
|
200
|
+
});
|
|
201
|
+
var createRefactorTools = (analyzer) => ({
|
|
202
|
+
type_refactor_preview: tool({
|
|
203
|
+
description: "Preview a rename refactor without applying it.",
|
|
204
|
+
args: {
|
|
205
|
+
symbol: tool.schema.string().describe("Symbol to rename"),
|
|
206
|
+
to: tool.schema.string().describe("New name"),
|
|
207
|
+
package: optionalPackageArg
|
|
208
|
+
},
|
|
209
|
+
async execute(args) {
|
|
210
|
+
return json(await run(analyzer.previewRefactor({
|
|
211
|
+
action: "rename",
|
|
212
|
+
symbol: args.symbol,
|
|
213
|
+
to: args.to,
|
|
214
|
+
...packageOption(args.package)
|
|
215
|
+
})));
|
|
216
|
+
}
|
|
217
|
+
})
|
|
218
|
+
});
|
|
219
|
+
var createExplanationTools = (analyzer) => ({
|
|
220
|
+
type_why_error: tool({
|
|
221
|
+
description: "Explain a TypeScript diagnostic in human terms.",
|
|
222
|
+
args: {
|
|
223
|
+
code: tool.schema.number().optional().describe("TypeScript diagnostic code"),
|
|
224
|
+
message: tool.schema.string().optional().describe("Diagnostic message"),
|
|
225
|
+
file: tool.schema.string().optional().describe("File path with the diagnostic"),
|
|
226
|
+
line: tool.schema.number().optional().describe("One-based diagnostic line"),
|
|
227
|
+
package: optionalPackageArg
|
|
228
|
+
},
|
|
229
|
+
async execute(args) {
|
|
230
|
+
return json(await run(analyzer.explainError({
|
|
231
|
+
...packageOption(args.package),
|
|
232
|
+
...optionalOption("code", args.code),
|
|
233
|
+
...optionalOption("message", args.message),
|
|
234
|
+
...optionalOption("file", args.file),
|
|
235
|
+
...optionalOption("line", args.line)
|
|
236
|
+
})));
|
|
237
|
+
}
|
|
238
|
+
}),
|
|
239
|
+
type_explain: tool({
|
|
240
|
+
description: "Show step-by-step resolution of a complex TypeScript type expression.",
|
|
241
|
+
args: {
|
|
242
|
+
expression: tool.schema.string().describe("TypeScript type expression"),
|
|
243
|
+
package: optionalPackageArg
|
|
244
|
+
},
|
|
245
|
+
async execute(args) {
|
|
246
|
+
return json(await run(analyzer.explainType(args.expression, args.package)));
|
|
247
|
+
}
|
|
248
|
+
})
|
|
249
|
+
});
|
|
250
|
+
var createTransformSearchTools = (analyzer) => ({
|
|
251
|
+
type_transform_search: tool({
|
|
252
|
+
description: "Search for functions by structural input/output type compatibility.",
|
|
253
|
+
args: {
|
|
254
|
+
from: tool.schema.string().optional().describe("Input type"),
|
|
255
|
+
to: tool.schema.string().optional().describe("Output type"),
|
|
256
|
+
paramPosition: tool.schema.union([tool.schema.number(), tool.schema.literal("any")]).optional(),
|
|
257
|
+
unwrapReturn: tool.schema.boolean().optional(),
|
|
258
|
+
exportedOnly: tool.schema.boolean().optional(),
|
|
259
|
+
limit: limitArg,
|
|
260
|
+
allowTypeErasure: tool.schema.boolean().optional(),
|
|
261
|
+
verifiedOnly: tool.schema.boolean().optional(),
|
|
262
|
+
minVerificationStatus: tool.schema.enum(["verified", "unverified", "unverifiable"]).optional().describe("Minimum verification status to return"),
|
|
263
|
+
includeDiagnostics: tool.schema.boolean().optional(),
|
|
264
|
+
includeSyntheticCode: tool.schema.boolean().optional(),
|
|
265
|
+
includeFailedVerification: tool.schema.boolean().optional(),
|
|
266
|
+
package: optionalPackageArg
|
|
267
|
+
},
|
|
268
|
+
async execute(args) {
|
|
269
|
+
return await run(analyzer.transformSearch({
|
|
270
|
+
...packageOption(args.package),
|
|
271
|
+
...optionalOption("from", args.from),
|
|
272
|
+
...optionalOption("to", args.to),
|
|
273
|
+
...optionalOption("paramPosition", args.paramPosition),
|
|
274
|
+
...optionalOption("unwrapReturn", args.unwrapReturn),
|
|
275
|
+
...optionalOption("exportedOnly", args.exportedOnly),
|
|
276
|
+
...optionalOption("limit", args.limit),
|
|
277
|
+
...optionalOption("allowTypeErasure", args.allowTypeErasure),
|
|
278
|
+
...optionalOption("verifiedOnly", args.verifiedOnly),
|
|
279
|
+
...optionalOption("minVerificationStatus", args.minVerificationStatus),
|
|
280
|
+
...optionalOption("includeDiagnostics", args.includeDiagnostics),
|
|
281
|
+
...optionalOption("includeSyntheticCode", args.includeSyntheticCode),
|
|
282
|
+
...optionalOption("includeFailedVerification", args.includeFailedVerification)
|
|
283
|
+
}));
|
|
284
|
+
}
|
|
285
|
+
})
|
|
286
|
+
});
|
|
287
|
+
var createVerifyContractTools = (analyzer) => ({
|
|
288
|
+
type_verify_contract: tool({
|
|
289
|
+
description: "Compose compatibility, snippet, diagnostics, and transform evidence for a proposed type contract.",
|
|
290
|
+
args: {
|
|
291
|
+
from: tool.schema.string().optional().describe("Source type or symbol"),
|
|
292
|
+
to: tool.schema.string().optional().describe("Target type or symbol"),
|
|
293
|
+
symbol: tool.schema.string().optional().describe("Expected transform symbol"),
|
|
294
|
+
snippet: tool.schema.string().optional().describe("Concrete TypeScript call-site snippet to check"),
|
|
295
|
+
includeDiagnostics: tool.schema.boolean().optional(),
|
|
296
|
+
includeTransformEvidence: tool.schema.boolean().optional(),
|
|
297
|
+
transformLimit: limitArg,
|
|
298
|
+
package: optionalPackageArg
|
|
299
|
+
},
|
|
300
|
+
async execute(args) {
|
|
301
|
+
return json(await run(analyzer.verifyContract({
|
|
302
|
+
...packageOption(args.package),
|
|
303
|
+
...optionalOption("from", args.from),
|
|
304
|
+
...optionalOption("to", args.to),
|
|
305
|
+
...optionalOption("symbol", args.symbol),
|
|
306
|
+
...optionalOption("snippet", args.snippet),
|
|
307
|
+
...optionalOption("includeDiagnostics", args.includeDiagnostics),
|
|
308
|
+
...optionalOption("includeTransformEvidence", args.includeTransformEvidence),
|
|
309
|
+
...optionalOption("transformLimit", args.transformLimit)
|
|
310
|
+
})));
|
|
311
|
+
}
|
|
312
|
+
})
|
|
313
|
+
});
|
|
314
|
+
var createToolDefinitions = (analyzer) => ({
|
|
315
|
+
...createDiscoveryTools(analyzer),
|
|
316
|
+
...createAnalysisTools(analyzer),
|
|
317
|
+
...createRelationshipTools(analyzer)
|
|
318
|
+
});
|
|
319
|
+
var QuartzPlugin = async (ctx) => {
|
|
320
|
+
const runtime = ManagedRuntime.make(CoreLayer(ctx.directory));
|
|
321
|
+
const analyzer = runtime.runSync(TypeAnalyzerService);
|
|
322
|
+
const client = ctx.client;
|
|
323
|
+
return {
|
|
324
|
+
event: async ({ event }) => {
|
|
325
|
+
if (event.type === "session.idle") {
|
|
326
|
+
await client.app?.log?.({
|
|
327
|
+
body: {
|
|
328
|
+
service: "quartz",
|
|
329
|
+
level: "debug",
|
|
330
|
+
message: "session idle observed by quartz plugin",
|
|
331
|
+
extra: { sessionID: event.properties.sessionID }
|
|
332
|
+
}
|
|
333
|
+
});
|
|
334
|
+
}
|
|
335
|
+
},
|
|
336
|
+
"tool.execute.after": async (input) => {
|
|
337
|
+
if (FILE_MODIFYING_TOOLS.has(input.tool)) {
|
|
338
|
+
await run(analyzer.markDirty());
|
|
339
|
+
}
|
|
340
|
+
},
|
|
341
|
+
tool: createToolDefinitions(analyzer)
|
|
342
|
+
};
|
|
343
|
+
};
|
|
344
|
+
var server_default = {
|
|
345
|
+
id: "quartz",
|
|
346
|
+
server: QuartzPlugin
|
|
347
|
+
};
|
|
348
|
+
export {
|
|
349
|
+
server_default as default,
|
|
350
|
+
QuartzPlugin
|
|
351
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@skastr0/quartz-opencode-plugin",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"main": "./dist/server.js",
|
|
6
|
+
"types": "./dist/server.d.ts",
|
|
7
|
+
"exports": {
|
|
8
|
+
"./server": {
|
|
9
|
+
"types": "./dist/server.d.ts",
|
|
10
|
+
"import": "./dist/server.js",
|
|
11
|
+
"default": "./dist/server.js"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"files": [
|
|
15
|
+
"dist",
|
|
16
|
+
"LICENSE",
|
|
17
|
+
"README.md"
|
|
18
|
+
],
|
|
19
|
+
"scripts": {
|
|
20
|
+
"build": "rm -rf dist && bun build ./src/server.ts --outdir ./dist --target bun --format esm --external @opencode-ai/plugin --external @skastr0/quartz-core --external effect && tsc -p tsconfig.build.json",
|
|
21
|
+
"prepack": "bun run build"
|
|
22
|
+
},
|
|
23
|
+
"dependencies": {
|
|
24
|
+
"@skastr0/quartz-core": "0.1.0",
|
|
25
|
+
"effect": "^3.21.2"
|
|
26
|
+
},
|
|
27
|
+
"peerDependencies": {
|
|
28
|
+
"@opencode-ai/plugin": ">=1.4.0"
|
|
29
|
+
},
|
|
30
|
+
"license": "MIT",
|
|
31
|
+
"description": "OpenCode plugin wrapper for quartz TypeScript code intelligence.",
|
|
32
|
+
"keywords": [
|
|
33
|
+
"quartz",
|
|
34
|
+
"opencode",
|
|
35
|
+
"plugin",
|
|
36
|
+
"typescript",
|
|
37
|
+
"code-intelligence",
|
|
38
|
+
"agent-tools"
|
|
39
|
+
],
|
|
40
|
+
"repository": {
|
|
41
|
+
"type": "git",
|
|
42
|
+
"url": "git+https://github.com/skastr0/quartz.git",
|
|
43
|
+
"directory": "apps/opencode-plugin"
|
|
44
|
+
},
|
|
45
|
+
"homepage": "https://github.com/skastr0/quartz#readme",
|
|
46
|
+
"bugs": {
|
|
47
|
+
"url": "https://github.com/skastr0/quartz/issues"
|
|
48
|
+
},
|
|
49
|
+
"engines": {
|
|
50
|
+
"bun": ">=1.3.0"
|
|
51
|
+
},
|
|
52
|
+
"publishConfig": {
|
|
53
|
+
"access": "public"
|
|
54
|
+
}
|
|
55
|
+
}
|