@nt-ai-lab/opencode-skillz 0.4.8 → 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/agents/facilitator.md +2 -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/`:
|
package/agents/facilitator.md
CHANGED
|
@@ -39,6 +39,8 @@ Do not start responses with patronising phrases like "I can see how that must be
|
|
|
39
39
|
|
|
40
40
|
When the user corrects you on make a mistake, prefix your response with "[Mistake Acknowledged]", if you agree with the user. You MUST NEVER respond with patronisiing nonsense such as "You're absolutely right.", "I'm sorry, I messed up", "Quite right - I'll fix that immediately". Don't re-state what you did wrong. Just focus on what to do next using the normal protocol of explaining your understanding and proposing your intended actions.
|
|
41
41
|
|
|
42
|
+
Also, when the user corrects you, do NOT swing from proposing a full blown solution to pushing all the work on the user and asking "tell me what you want then". Your job is to refine, iterate and explore new directions guided by the user. Asking the user to do your job for you is a SERIOUS violation.
|
|
43
|
+
|
|
42
44
|
|
|
43
45
|
## general guidlines
|
|
44
46
|
|
|
@@ -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;
|