deuk-agent-rule 2.2.0 → 2.2.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.
@@ -1,123 +1,123 @@
1
- import { createInterface } from "readline";
2
- import { existsSync, readFileSync, writeFileSync } from "fs";
3
- import { join } from "path";
4
-
5
- const INIT_CONFIG_FILENAME = ".deuk-agent-rule.config.json";
6
- const INIT_CONFIG_VERSION = 1;
7
-
8
- export async function ask(rl, question) {
9
- return new Promise((resolve) => rl.question(question, resolve));
10
- }
11
-
12
- export async function askYesNo(question, defaultYes = true) {
13
- const rl = createInterface({ input: process.stdin, output: process.stdout });
14
- try {
15
- const ans = (await ask(rl, question + (defaultYes ? " [Y/n]: " : " [y/N]: "))).trim().toLowerCase();
16
- if (!ans) return defaultYes;
17
- return ans === "y" || ans === "yes";
18
- } finally {
19
- rl.close();
20
- }
21
- }
22
-
23
- export async function selectOne(rl, prompt, choices) {
24
- console.log("\n" + prompt);
25
- choices.forEach((c, i) => console.log(` ${i + 1}) ${c.label}`));
26
- while (true) {
27
- const ans = (await ask(rl, ` Choice [1-${choices.length}]: `)).trim();
28
- const idx = parseInt(ans, 10) - 1;
29
- if (idx >= 0 && idx < choices.length) return choices[idx].value;
30
- }
31
- }
32
-
33
- export async function selectMany(rl, prompt, choices) {
34
- console.log("\n" + prompt + " (comma-separated numbers, or 'all')");
35
- choices.forEach((c, i) => console.log(` ${i + 1}) ${c.label}`));
36
- while (true) {
37
- const ans = (await ask(rl, ` Choices: `)).trim().toLowerCase();
38
- if (ans === "all" || ans === "") return choices.map((c) => c.value);
39
- const parts = ans.split(/[,\s]+/).map((s) => parseInt(s, 10) - 1);
40
- if (parts.every((i) => i >= 0 && i < choices.length)) return parts.map((i) => choices[i].value);
41
- }
42
- }
43
-
44
- export function loadInitConfig(cwd) {
45
- const p = join(cwd, INIT_CONFIG_FILENAME);
46
- if (!existsSync(p)) return null;
47
- try {
48
- const j = JSON.parse(readFileSync(p, "utf8"));
49
- if (j.version !== INIT_CONFIG_VERSION) return null;
50
- return j;
51
- } catch {
52
- return null;
53
- }
54
- }
55
-
56
- export function writeInitConfig(cwd, opts) {
57
- const p = join(cwd, INIT_CONFIG_FILENAME);
58
- const body = {
59
- version: INIT_CONFIG_VERSION,
60
- stack: opts.stack,
61
- agentTools: opts.agentTools,
62
- agentsMode: opts.agents ?? "inject",
63
- updatedAt: new Date().toISOString(),
64
- };
65
- writeFileSync(p, JSON.stringify(body, null, 2) + "\n", "utf8");
66
- }
67
-
68
- export const STACKS = [
69
- { label: "Unity / C#", value: "unity" },
70
- { label: "Next.js + C#", value: "nextjs-dotnet" },
71
- { label: "Web (React / Vue / general)", value: "web" },
72
- { label: "Java / Spring Boot", value: "java" },
73
- { label: "Other / skip", value: "other" },
74
- ];
75
-
76
- export const AGENT_TOOLS = [
77
- { label: "Cursor", value: "cursor" },
78
- { label: "GitHub Copilot", value: "copilot" },
79
- { label: "Gemini / Antigravity", value: "gemini" },
80
- { label: "Claude (Cursor / Claude Code)", value: "claude" },
81
- { label: "Windsurf", value: "windsurf" },
82
- { label: "JetBrains AI Assistant", value: "jetbrains" },
83
- { label: "All of the above", value: "all" },
84
- { label: "Other / skip", value: "other" },
85
- ];
86
-
87
- export async function runInteractive(opts) {
88
- const rl = createInterface({ input: process.stdin, output: process.stdout });
89
- try {
90
- console.log("\nDeukAgentRules init — let's configure your workspace.\n");
91
-
92
- const stack = await selectOne(rl, "What is your primary tech stack?", STACKS);
93
- const tools = await selectMany(rl, "Which agent tools do you use?", AGENT_TOOLS);
94
-
95
- const targetAgents = join(opts.cwd, "AGENTS.md");
96
- let agentsDefault = "inject";
97
- if (!existsSync(targetAgents)) {
98
- agentsDefault = "inject"; // will append markers
99
- console.log("\n No AGENTS.md found — will create with markers.");
100
- } else {
101
- const content = readFileSync(targetAgents, "utf8");
102
- const hasMarkers = content.includes("deuk-agent-rule:begin");
103
- if (!hasMarkers) {
104
- const choice = await selectOne(rl, "AGENTS.md exists but has no markers. How to apply?", [
105
- { label: "Append managed block at the end (safe)", value: "inject" },
106
- { label: "Overwrite entire AGENTS.md", value: "overwrite" },
107
- { label: "Skip AGENTS.md", value: "skip" },
108
- ]);
109
- agentsDefault = choice;
110
- }
111
- }
112
-
113
- opts.agents = opts.agents ?? agentsDefault;
114
- opts.stack = stack;
115
- opts.agentTools = tools;
116
-
117
- console.log("\n Stack : " + stack);
118
- console.log(" Tools : " + (tools.join(", ") || "none"));
119
- console.log(" AGENTS: " + opts.agents + "\n");
120
- } finally {
121
- rl.close();
122
- }
123
- }
1
+ import { createInterface } from "readline";
2
+ import { existsSync, readFileSync, writeFileSync } from "fs";
3
+ import { join } from "path";
4
+
5
+ const INIT_CONFIG_FILENAME = ".deuk-agent-rule.config.json";
6
+ const INIT_CONFIG_VERSION = 1;
7
+
8
+ export async function ask(rl, question) {
9
+ return new Promise((resolve) => rl.question(question, resolve));
10
+ }
11
+
12
+ export async function askYesNo(question, defaultYes = true) {
13
+ const rl = createInterface({ input: process.stdin, output: process.stdout });
14
+ try {
15
+ const ans = (await ask(rl, question + (defaultYes ? " [Y/n]: " : " [y/N]: "))).trim().toLowerCase();
16
+ if (!ans) return defaultYes;
17
+ return ans === "y" || ans === "yes";
18
+ } finally {
19
+ rl.close();
20
+ }
21
+ }
22
+
23
+ export async function selectOne(rl, prompt, choices) {
24
+ console.log("\n" + prompt);
25
+ choices.forEach((c, i) => console.log(` ${i + 1}) ${c.label}`));
26
+ while (true) {
27
+ const ans = (await ask(rl, ` Choice [1-${choices.length}]: `)).trim();
28
+ const idx = parseInt(ans, 10) - 1;
29
+ if (idx >= 0 && idx < choices.length) return choices[idx].value;
30
+ }
31
+ }
32
+
33
+ export async function selectMany(rl, prompt, choices) {
34
+ console.log("\n" + prompt + " (comma-separated numbers, or 'all')");
35
+ choices.forEach((c, i) => console.log(` ${i + 1}) ${c.label}`));
36
+ while (true) {
37
+ const ans = (await ask(rl, ` Choices: `)).trim().toLowerCase();
38
+ if (ans === "all" || ans === "") return choices.map((c) => c.value);
39
+ const parts = ans.split(/[,\s]+/).map((s) => parseInt(s, 10) - 1);
40
+ if (parts.every((i) => i >= 0 && i < choices.length)) return parts.map((i) => choices[i].value);
41
+ }
42
+ }
43
+
44
+ export function loadInitConfig(cwd) {
45
+ const p = join(cwd, INIT_CONFIG_FILENAME);
46
+ if (!existsSync(p)) return null;
47
+ try {
48
+ const j = JSON.parse(readFileSync(p, "utf8"));
49
+ if (j.version !== INIT_CONFIG_VERSION) return null;
50
+ return j;
51
+ } catch {
52
+ return null;
53
+ }
54
+ }
55
+
56
+ export function writeInitConfig(cwd, opts) {
57
+ const p = join(cwd, INIT_CONFIG_FILENAME);
58
+ const body = {
59
+ version: INIT_CONFIG_VERSION,
60
+ stack: opts.stack,
61
+ agentTools: opts.agentTools,
62
+ agentsMode: opts.agents ?? "inject",
63
+ updatedAt: new Date().toISOString(),
64
+ };
65
+ writeFileSync(p, JSON.stringify(body, null, 2) + "\n", "utf8");
66
+ }
67
+
68
+ export const STACKS = [
69
+ { label: "Unity / C#", value: "unity" },
70
+ { label: "Next.js + C#", value: "nextjs-dotnet" },
71
+ { label: "Web (React / Vue / general)", value: "web" },
72
+ { label: "Java / Spring Boot", value: "java" },
73
+ { label: "Other / skip", value: "other" },
74
+ ];
75
+
76
+ export const AGENT_TOOLS = [
77
+ { label: "Cursor", value: "cursor" },
78
+ { label: "GitHub Copilot", value: "copilot" },
79
+ { label: "Gemini / Antigravity", value: "gemini" },
80
+ { label: "Claude (Cursor / Claude Code)", value: "claude" },
81
+ { label: "Windsurf", value: "windsurf" },
82
+ { label: "JetBrains AI Assistant", value: "jetbrains" },
83
+ { label: "All of the above", value: "all" },
84
+ { label: "Other / skip", value: "other" },
85
+ ];
86
+
87
+ export async function runInteractive(opts) {
88
+ const rl = createInterface({ input: process.stdin, output: process.stdout });
89
+ try {
90
+ console.log("\nDeukAgentRules init — let's configure your workspace.\n");
91
+
92
+ const stack = await selectOne(rl, "What is your primary tech stack?", STACKS);
93
+ const tools = await selectMany(rl, "Which agent tools do you use?", AGENT_TOOLS);
94
+
95
+ const targetAgents = join(opts.cwd, "AGENTS.md");
96
+ let agentsDefault = "inject";
97
+ if (!existsSync(targetAgents)) {
98
+ agentsDefault = "inject"; // will append markers
99
+ console.log("\n No AGENTS.md found — will create with markers.");
100
+ } else {
101
+ const content = readFileSync(targetAgents, "utf8");
102
+ const hasMarkers = content.includes("deuk-agent-rule:begin");
103
+ if (!hasMarkers) {
104
+ const choice = await selectOne(rl, "AGENTS.md exists but has no markers. How to apply?", [
105
+ { label: "Append managed block at the end (safe)", value: "inject" },
106
+ { label: "Overwrite entire AGENTS.md", value: "overwrite" },
107
+ { label: "Skip AGENTS.md", value: "skip" },
108
+ ]);
109
+ agentsDefault = choice;
110
+ }
111
+ }
112
+
113
+ opts.agents = opts.agents ?? agentsDefault;
114
+ opts.stack = stack;
115
+ opts.agentTools = tools;
116
+
117
+ console.log("\n Stack : " + stack);
118
+ console.log(" Tools : " + (tools.join(", ") || "none"));
119
+ console.log(" AGENTS: " + opts.agents + "\n");
120
+ } finally {
121
+ rl.close();
122
+ }
123
+ }