@nt-ai-lab/opencode-skillz 0.4.9 → 0.4.10
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 +26 -0
- package/dist/git-workflow-gates.d.ts +1 -1
- package/dist/git-workflow-gates.js +4 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/plugin-registry/index.d.ts +3 -2
- package/dist/plugin-registry/index.js +27 -8
- package/dist/types.d.ts +5 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -17,6 +17,32 @@ Add the package name to the plugin list:
|
|
|
17
17
|
|
|
18
18
|
This is the simplest update path for consumers: declare the plugin once and keep your package pinning strategy up to date.
|
|
19
19
|
|
|
20
|
+
### Lint mode
|
|
21
|
+
|
|
22
|
+
`lint.mode` controls the bundled `nt_skillz_lint` tool and its commit gate. It defaults to `"auto"`.
|
|
23
|
+
|
|
24
|
+
```json
|
|
25
|
+
{
|
|
26
|
+
"$schema": "https://opencode.ai/config.json",
|
|
27
|
+
"plugin": [
|
|
28
|
+
[
|
|
29
|
+
"@nt-ai-lab/opencode-skillz",
|
|
30
|
+
{
|
|
31
|
+
"lint": {
|
|
32
|
+
"mode": "manual"
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
]
|
|
36
|
+
]
|
|
37
|
+
}
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
- `"auto"`: provides the lint tool and requires it before committing changed TypeScript files.
|
|
41
|
+
- `"manual"`: provides the lint tool without the commit requirement.
|
|
42
|
+
- `"disabled"`: does not provide the lint tool or the lint commit requirement.
|
|
43
|
+
|
|
44
|
+
An unsupported mode prevents the plugin from starting and reports the accepted values.
|
|
45
|
+
|
|
20
46
|
### Option B: local typed wrapper plugin file
|
|
21
47
|
|
|
22
48
|
If a consumer prefers local TypeScript wiring, create a file in `.opencode/plugins/`:
|
|
@@ -18,4 +18,4 @@ export interface GitWorkflowGate {
|
|
|
18
18
|
recordLintedFiles(filePaths: string[]): void;
|
|
19
19
|
}
|
|
20
20
|
export declare const directPullRequestCreationBlockedMessage: string;
|
|
21
|
-
export declare function createGitWorkflowGate(repositoryRoot: string, commandRunner: CommandRunner): GitWorkflowGate;
|
|
21
|
+
export declare function createGitWorkflowGate(repositoryRoot: string, commandRunner: CommandRunner, requireLintBeforeCommit?: boolean): GitWorkflowGate;
|
|
@@ -49,7 +49,7 @@ function createUnlintedCommitMessage(filePaths) {
|
|
|
49
49
|
"Then retry the commit.",
|
|
50
50
|
].join("\n");
|
|
51
51
|
}
|
|
52
|
-
export function createGitWorkflowGate(repositoryRoot, commandRunner) {
|
|
52
|
+
export function createGitWorkflowGate(repositoryRoot, commandRunner, requireLintBeforeCommit = true) {
|
|
53
53
|
const lintedFingerprints = new Map();
|
|
54
54
|
function runGit(commandArguments, description) {
|
|
55
55
|
return normalizeCommandOutput(commandRunner.run("git", commandArguments, repositoryRoot), description);
|
|
@@ -73,6 +73,9 @@ export function createGitWorkflowGate(repositoryRoot, commandRunner) {
|
|
|
73
73
|
return output.split("\n").map((filePath) => filePath.trim()).filter(Boolean);
|
|
74
74
|
}
|
|
75
75
|
function ensureStagedTypeScriptFilesAreLinted() {
|
|
76
|
+
if (!requireLintBeforeCommit) {
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
76
79
|
const stagedFilePaths = readStagedTypeScriptFilePaths();
|
|
77
80
|
const unlintedFilePaths = stagedFilePaths.filter((filePath) => lintedFingerprints.get(filePath) !== readStagedFingerprint(filePath));
|
|
78
81
|
if (unlintedFilePaths.length === 0) {
|
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import type { PluginInput } from "./types.js";
|
|
2
|
-
export declare const opencodeSkillzPlugin: (input: PluginInput) => Promise<import("./types.js").PluginHooks>;
|
|
1
|
+
import type { PluginInput, PluginOptions } from "./types.js";
|
|
2
|
+
export declare const opencodeSkillzPlugin: (input: PluginInput, options?: PluginOptions) => Promise<import("./types.js").PluginHooks>;
|
|
3
3
|
export default opencodeSkillzPlugin;
|
package/dist/index.js
CHANGED
|
@@ -3,5 +3,5 @@ import { fileURLToPath } from "node:url";
|
|
|
3
3
|
import { createPluginRegistry } from "./plugin-registry/index.js";
|
|
4
4
|
const currentDirectory = path.dirname(fileURLToPath(import.meta.url));
|
|
5
5
|
const pluginRoot = path.resolve(currentDirectory, "..");
|
|
6
|
-
export const opencodeSkillzPlugin = async (input) => createPluginRegistry(input, pluginRoot);
|
|
6
|
+
export const opencodeSkillzPlugin = async (input, options) => createPluginRegistry(input, pluginRoot, options);
|
|
7
7
|
export default opencodeSkillzPlugin;
|
|
@@ -1,2 +1,3 @@
|
|
|
1
|
-
import type { PluginHooks, PluginInput } from "../types.js";
|
|
2
|
-
export
|
|
1
|
+
import type { PluginHooks, PluginInput, PluginOptions } from "../types.js";
|
|
2
|
+
export type LintMode = "auto" | "manual" | "disabled";
|
|
3
|
+
export declare function createPluginRegistry(input: PluginInput, pluginRoot: string, options?: PluginOptions): PluginHooks;
|
|
@@ -14,6 +14,21 @@ function readLintedFilePaths(request) {
|
|
|
14
14
|
}
|
|
15
15
|
return request.files.filter((filePath) => typeof filePath === "string");
|
|
16
16
|
}
|
|
17
|
+
class InvalidLintModeError extends Error {
|
|
18
|
+
constructor(mode) {
|
|
19
|
+
super(`Expected lint.mode to be 'auto', 'manual', or 'disabled'. Got ${String(mode)}.`);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
function resolveLintMode(options) {
|
|
23
|
+
const mode = options?.lint?.mode;
|
|
24
|
+
if (mode === undefined) {
|
|
25
|
+
return "auto";
|
|
26
|
+
}
|
|
27
|
+
if (mode === "auto" || mode === "manual" || mode === "disabled") {
|
|
28
|
+
return mode;
|
|
29
|
+
}
|
|
30
|
+
throw new InvalidLintModeError(mode);
|
|
31
|
+
}
|
|
17
32
|
function createGateAwareLintTool(gate) {
|
|
18
33
|
return {
|
|
19
34
|
...lintTool,
|
|
@@ -24,17 +39,21 @@ function createGateAwareLintTool(gate) {
|
|
|
24
39
|
},
|
|
25
40
|
};
|
|
26
41
|
}
|
|
27
|
-
export function createPluginRegistry(input, pluginRoot) {
|
|
42
|
+
export function createPluginRegistry(input, pluginRoot, options) {
|
|
43
|
+
const lintMode = resolveLintMode(options);
|
|
28
44
|
const dontStopHooks = createDontStopHooks(input.client);
|
|
29
|
-
const gitWorkflowGate = createGitWorkflowGate(input.worktree ?? process.cwd(), childProcessCommandRunner);
|
|
45
|
+
const gitWorkflowGate = createGitWorkflowGate(input.worktree ?? process.cwd(), childProcessCommandRunner, lintMode === "auto");
|
|
46
|
+
const tools = {
|
|
47
|
+
nt_skillz_create_pr: createPullRequestTool,
|
|
48
|
+
[PULL_REQUEST_FEEDBACK_TOOL_NAME]: pullRequestFeedbackTool,
|
|
49
|
+
[VITEST_COVERAGE_TOOL_NAME]: vitestCoverageTool,
|
|
50
|
+
};
|
|
51
|
+
if (lintMode !== "disabled") {
|
|
52
|
+
tools[LINT_TOOL_NAME] = lintMode === "auto" ? createGateAwareLintTool(gitWorkflowGate) : lintTool;
|
|
53
|
+
}
|
|
30
54
|
return {
|
|
31
55
|
...dontStopHooks,
|
|
32
|
-
tool:
|
|
33
|
-
nt_skillz_create_pr: createPullRequestTool,
|
|
34
|
-
[LINT_TOOL_NAME]: createGateAwareLintTool(gitWorkflowGate),
|
|
35
|
-
[PULL_REQUEST_FEEDBACK_TOOL_NAME]: pullRequestFeedbackTool,
|
|
36
|
-
[VITEST_COVERAGE_TOOL_NAME]: vitestCoverageTool,
|
|
37
|
-
},
|
|
56
|
+
tool: tools,
|
|
38
57
|
"tool.execute.before": async (hookInput, hookOutput) => {
|
|
39
58
|
gitWorkflowGate.beforeToolExecution(hookInput, hookOutput);
|
|
40
59
|
},
|
package/dist/types.d.ts
CHANGED
|
@@ -20,6 +20,11 @@ export interface PluginConfig {
|
|
|
20
20
|
agent?: Record<string, AgentDefinition>;
|
|
21
21
|
default_agent?: string;
|
|
22
22
|
}
|
|
23
|
+
export interface PluginOptions {
|
|
24
|
+
lint?: {
|
|
25
|
+
mode?: unknown;
|
|
26
|
+
};
|
|
27
|
+
}
|
|
23
28
|
export interface CommandExecuteBeforeInput {
|
|
24
29
|
command: string;
|
|
25
30
|
sessionID: string;
|