@dev-guard/cli 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.
Files changed (111) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +79 -0
  3. package/dist/agent-strategies.d.ts +23 -0
  4. package/dist/agent-strategies.js +130 -0
  5. package/dist/agent-strategies.js.map +1 -0
  6. package/dist/ai-context.d.ts +10 -0
  7. package/dist/ai-context.js +143 -0
  8. package/dist/ai-context.js.map +1 -0
  9. package/dist/check.d.ts +6 -0
  10. package/dist/check.js +89 -0
  11. package/dist/check.js.map +1 -0
  12. package/dist/clipboard.d.ts +6 -0
  13. package/dist/clipboard.js +43 -0
  14. package/dist/clipboard.js.map +1 -0
  15. package/dist/codex-notify.d.ts +23 -0
  16. package/dist/codex-notify.js +146 -0
  17. package/dist/codex-notify.js.map +1 -0
  18. package/dist/command-targets.d.ts +10 -0
  19. package/dist/command-targets.js +124 -0
  20. package/dist/command-targets.js.map +1 -0
  21. package/dist/config.d.ts +22 -0
  22. package/dist/config.js +180 -0
  23. package/dist/config.js.map +1 -0
  24. package/dist/configure.d.ts +1 -0
  25. package/dist/configure.js +79 -0
  26. package/dist/configure.js.map +1 -0
  27. package/dist/doctor.d.ts +1 -0
  28. package/dist/doctor.js +326 -0
  29. package/dist/doctor.js.map +1 -0
  30. package/dist/drift-telemetry.d.ts +13 -0
  31. package/dist/drift-telemetry.js +64 -0
  32. package/dist/drift-telemetry.js.map +1 -0
  33. package/dist/effective-task.d.ts +44 -0
  34. package/dist/effective-task.js +355 -0
  35. package/dist/effective-task.js.map +1 -0
  36. package/dist/fs.d.ts +10 -0
  37. package/dist/fs.js +58 -0
  38. package/dist/fs.js.map +1 -0
  39. package/dist/git.d.ts +24 -0
  40. package/dist/git.js +235 -0
  41. package/dist/git.js.map +1 -0
  42. package/dist/hooks.d.ts +39 -0
  43. package/dist/hooks.js +513 -0
  44. package/dist/hooks.js.map +1 -0
  45. package/dist/index.d.ts +2 -0
  46. package/dist/index.js +555 -0
  47. package/dist/index.js.map +1 -0
  48. package/dist/infer-task.d.ts +1 -0
  49. package/dist/infer-task.js +120 -0
  50. package/dist/infer-task.js.map +1 -0
  51. package/dist/init.d.ts +1 -0
  52. package/dist/init.js +50 -0
  53. package/dist/init.js.map +1 -0
  54. package/dist/install-agent-instructions.d.ts +1 -0
  55. package/dist/install-agent-instructions.js +113 -0
  56. package/dist/install-agent-instructions.js.map +1 -0
  57. package/dist/migration.d.ts +8 -0
  58. package/dist/migration.js +43 -0
  59. package/dist/migration.js.map +1 -0
  60. package/dist/paths.d.ts +38 -0
  61. package/dist/paths.js +41 -0
  62. package/dist/paths.js.map +1 -0
  63. package/dist/project-detection.d.ts +10 -0
  64. package/dist/project-detection.js +144 -0
  65. package/dist/project-detection.js.map +1 -0
  66. package/dist/project-identity.d.ts +7 -0
  67. package/dist/project-identity.js +93 -0
  68. package/dist/project-identity.js.map +1 -0
  69. package/dist/project-memory.d.ts +4 -0
  70. package/dist/project-memory.js +32 -0
  71. package/dist/project-memory.js.map +1 -0
  72. package/dist/prompt.d.ts +13 -0
  73. package/dist/prompt.js +125 -0
  74. package/dist/prompt.js.map +1 -0
  75. package/dist/refresh.d.ts +15 -0
  76. package/dist/refresh.js +146 -0
  77. package/dist/refresh.js.map +1 -0
  78. package/dist/report.d.ts +1 -0
  79. package/dist/report.js +109 -0
  80. package/dist/report.js.map +1 -0
  81. package/dist/review.d.ts +2 -0
  82. package/dist/review.js +653 -0
  83. package/dist/review.js.map +1 -0
  84. package/dist/rule-filter.d.ts +8 -0
  85. package/dist/rule-filter.js +79 -0
  86. package/dist/rule-filter.js.map +1 -0
  87. package/dist/runs.d.ts +21 -0
  88. package/dist/runs.js +142 -0
  89. package/dist/runs.js.map +1 -0
  90. package/dist/runtime-state.d.ts +69 -0
  91. package/dist/runtime-state.js +1383 -0
  92. package/dist/runtime-state.js.map +1 -0
  93. package/dist/scan.d.ts +1 -0
  94. package/dist/scan.js +55 -0
  95. package/dist/scan.js.map +1 -0
  96. package/dist/self.d.ts +3 -0
  97. package/dist/self.js +235 -0
  98. package/dist/self.js.map +1 -0
  99. package/dist/task-ai.d.ts +1 -0
  100. package/dist/task-ai.js +643 -0
  101. package/dist/task-ai.js.map +1 -0
  102. package/dist/telemetry.d.ts +1 -0
  103. package/dist/telemetry.js +11 -0
  104. package/dist/telemetry.js.map +1 -0
  105. package/dist/update.d.ts +6 -0
  106. package/dist/update.js +154 -0
  107. package/dist/update.js.map +1 -0
  108. package/dist/watch.d.ts +1 -0
  109. package/dist/watch.js +303 -0
  110. package/dist/watch.js.map +1 -0
  111. package/package.json +31 -0
@@ -0,0 +1,146 @@
1
+ import { chmod, copyFile } from "node:fs/promises";
2
+ import { existsSync, readFileSync } from "node:fs";
3
+ import { homedir } from "node:os";
4
+ import { join } from "node:path";
5
+ import { readTextFile, writeTextFile } from "./fs.js";
6
+ export const codexNotifyConfigPath = join(homedir(), ".codex", "config.toml");
7
+ export const codexNotifyDispatcherPath = join(homedir(), ".codex", "dev-guard-notify-dispatcher.sh");
8
+ export const codexNotifyDispatcherLogPath = join(homedir(), ".codex", "dev-guard-notify-dispatcher.log");
9
+ export async function getCodexNotifyConfigStatus() {
10
+ const text = await readTextFile(codexNotifyConfigPath);
11
+ const notify = parseTopLevelNotify(text);
12
+ const notifyIsDispatcher = Boolean(notify?.[0] === codexNotifyDispatcherPath);
13
+ return {
14
+ configPath: codexNotifyConfigPath,
15
+ dispatcherPath: codexNotifyDispatcherPath,
16
+ dispatcherInstalled: existsSync(codexNotifyDispatcherPath),
17
+ notify,
18
+ notifyConfigured: Boolean(notify),
19
+ notifyIsDispatcher,
20
+ existingNotifyDetected: Boolean(notify && !notifyIsDispatcher)
21
+ };
22
+ }
23
+ export async function installCodexNotifyDispatcher(options = {}) {
24
+ const text = await readTextFile(codexNotifyConfigPath);
25
+ const notify = parseTopLevelNotify(text);
26
+ const notifyIsDispatcher = Boolean(notify?.[0] === codexNotifyDispatcherPath);
27
+ const originalNotify = notifyIsDispatcher ? readOriginalNotifyFromDispatcher() ?? [] : notify ?? [];
28
+ if (notifyIsDispatcher && existsSync(codexNotifyDispatcherPath) && !options.force) {
29
+ return {
30
+ changed: false,
31
+ dispatcherPath: codexNotifyDispatcherPath,
32
+ message: "Codex notify dispatcher already installed"
33
+ };
34
+ }
35
+ await writeTextFile(codexNotifyDispatcherPath, dispatcherScript(originalNotify));
36
+ await chmod(codexNotifyDispatcherPath, 0o755);
37
+ const backupPath = `${codexNotifyConfigPath}.devguard-backup-${timestampForFile()}`;
38
+ if (existsSync(codexNotifyConfigPath)) {
39
+ await copyFile(codexNotifyConfigPath, backupPath);
40
+ }
41
+ const nextText = replaceTopLevelNotify(text, [codexNotifyDispatcherPath]);
42
+ await writeTextFile(codexNotifyConfigPath, nextText);
43
+ return {
44
+ changed: true,
45
+ backupPath,
46
+ dispatcherPath: codexNotifyDispatcherPath,
47
+ message: originalNotify.length > 0 ? "Codex notify dispatcher installed and existing notify preserved" : "Codex notify dispatcher installed"
48
+ };
49
+ }
50
+ export function formatNotifyCommand(command) {
51
+ return command && command.length > 0 ? command.map((part) => JSON.stringify(part)).join(" ") : "none";
52
+ }
53
+ function readOriginalNotifyFromDispatcher() {
54
+ const text = existsSync(codexNotifyDispatcherPath) ? readFileSync(codexNotifyDispatcherPath, "utf8") : "";
55
+ const match = /^ORIGINAL_NOTIFY=\((.*)\)$/m.exec(text);
56
+ return match ? parseShellArray(match[1]) : undefined;
57
+ }
58
+ function parseTopLevelNotify(text) {
59
+ const match = /^notify\s*=\s*\[([^\n]*)\]\s*$/m.exec(text);
60
+ if (!match)
61
+ return undefined;
62
+ return parseTomlStringArray(match[1]);
63
+ }
64
+ function parseTomlStringArray(value) {
65
+ const result = [];
66
+ const pattern = /"((?:\\"|\\\\|[^"])*)"/g;
67
+ let match;
68
+ while ((match = pattern.exec(value)) !== null) {
69
+ result.push(match[1].replace(/\\"/g, '"').replace(/\\\\/g, "\\"));
70
+ }
71
+ return result;
72
+ }
73
+ function replaceTopLevelNotify(text, notify) {
74
+ const line = `notify = [${notify.map((item) => JSON.stringify(item)).join(", ")}]`;
75
+ if (/^notify\s*=/m.test(text)) {
76
+ return text.replace(/^notify\s*=\s*\[[^\n]*\]\s*$/m, line);
77
+ }
78
+ return `${line}\n${text}`;
79
+ }
80
+ function dispatcherScript(originalNotify) {
81
+ return `#!/usr/bin/env bash
82
+ set +e
83
+
84
+ LOG="${codexNotifyDispatcherLogPath}"
85
+ ORIGINAL_NOTIFY=(${originalNotify.map(shellQuote).join(" ")})
86
+
87
+ mkdir -p "$(dirname "$LOG")"
88
+ timestamp() { date -u +"%Y-%m-%dT%H:%M:%SZ"; }
89
+ log() { printf 'timestamp=%s dispatcher=codex.notify %s\\n' "$(timestamp)" "$*" >> "$LOG"; }
90
+
91
+ log "status=start argc=$#"
92
+
93
+ if [ "\${#ORIGINAL_NOTIFY[@]}" -gt 0 ]; then
94
+ log "original_notify=status_running command=\${ORIGINAL_NOTIFY[0]}"
95
+ "\${ORIGINAL_NOTIFY[@]}" "$@"
96
+ original_status=$?
97
+ log "original_notify=status_completed exit=$original_status"
98
+ else
99
+ original_status=0
100
+ log "original_notify=none"
101
+ fi
102
+
103
+ payload="$*"
104
+ json_root="$(printf '%s\\n' "$payload" | sed -n 's/.*"cwd"[[:space:]]*:[[:space:]]*"\\([^"]*\\)".*/\\1/p' | head -n 1)"
105
+ if [ -z "$json_root" ]; then
106
+ json_root="$(printf '%s\\n' "$payload" | sed -n 's/.*"project_root"[[:space:]]*:[[:space:]]*"\\([^"]*\\)".*/\\1/p' | head -n 1)"
107
+ fi
108
+ if [ -z "$json_root" ]; then
109
+ json_root="$(printf '%s\\n' "$payload" | sed -n 's/.*"workspace_root"[[:space:]]*:[[:space:]]*"\\([^"]*\\)".*/\\1/p' | head -n 1)"
110
+ fi
111
+
112
+ for candidate in "$json_root" "\${CODEX_WORKSPACE_ROOT:-}" "\${CODEX_PROJECT_DIR:-}" "\${INIT_CWD:-}" "$PWD"; do
113
+ [ -z "$candidate" ] && continue
114
+ if [ -x "$candidate/.devguard/hooks/codex-notify.sh" ]; then
115
+ log "devguard_notify=status_running root=$candidate"
116
+ DEV_GUARD_HOOK_SOURCE=agent_runtime "$candidate/.devguard/hooks/codex-notify.sh" "$@"
117
+ devguard_status=$?
118
+ log "devguard_notify=status_completed exit=$devguard_status root=$candidate"
119
+ log "status=completed original=$original_status devguard=$devguard_status"
120
+ exit 0
121
+ fi
122
+ done
123
+
124
+ log "devguard_notify=skipped reason=no_project_hook"
125
+ log "status=completed original=$original_status devguard=skipped"
126
+ exit 0
127
+ `;
128
+ }
129
+ function parseShellArray(value) {
130
+ const result = [];
131
+ const pattern = /'((?:'\\''|[^'])*)'/g;
132
+ let match;
133
+ while ((match = pattern.exec(value)) !== null) {
134
+ result.push(match[1].replace(/'\\''/g, "'"));
135
+ }
136
+ return result;
137
+ }
138
+ function shellQuote(value) {
139
+ return `'${value.replace(/'/g, `'\\''`)}'`;
140
+ }
141
+ function timestampForFile() {
142
+ const date = new Date();
143
+ const pad = (value) => String(value).padStart(2, "0");
144
+ return `${date.getFullYear()}${pad(date.getMonth() + 1)}${pad(date.getDate())}-${pad(date.getHours())}${pad(date.getMinutes())}${pad(date.getSeconds())}`;
145
+ }
146
+ //# sourceMappingURL=codex-notify.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"codex-notify.js","sourceRoot":"","sources":["../src/codex-notify.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ import type { TaskAIFileCandidate } from "@dev-guard/core";
2
+ interface CommandTarget {
3
+ command: string;
4
+ edit: string[];
5
+ reference: string[];
6
+ }
7
+ export declare function inferCommandTargetFiles(requirement: string, projectFiles: string[]): CommandTarget | undefined;
8
+ export declare function mergeCommandTargetCandidates(candidates: TaskAIFileCandidate[], target: CommandTarget | undefined): TaskAIFileCandidate[];
9
+ export declare function filterCommandTargetCandidates(candidates: TaskAIFileCandidate[], target: CommandTarget | undefined): TaskAIFileCandidate[];
10
+ export {};
@@ -0,0 +1,124 @@
1
+ const knownCommands = ["task-ai", "fix-prompt", "self-check", "done", "handoff", "status", "update", "watch", "review", "check", "prompt", "doctor", "report", "scan", "refresh", "telemetry", "self"];
2
+ export function inferCommandTargetFiles(requirement, projectFiles) {
3
+ const command = detectCommand(requirement);
4
+ if (!command) {
5
+ return undefined;
6
+ }
7
+ const fileSet = new Set(projectFiles);
8
+ const indexFile = existing(fileSet, "packages/cli/src/index.ts");
9
+ const commandFile = commandFileFor(command, fileSet);
10
+ const updateFile = existing(fileSet, "packages/cli/src/update.ts");
11
+ const references = [];
12
+ const edits = [];
13
+ if (command === "done" || command === "handoff" || command === "status") {
14
+ if (indexFile) {
15
+ edits.push(indexFile);
16
+ }
17
+ if (/update\s*preview|preview|업데이트\s*미리|문서\s*후보/i.test(requirement) && updateFile) {
18
+ references.push(updateFile);
19
+ }
20
+ }
21
+ else if (commandFile) {
22
+ edits.push(commandFile);
23
+ if (indexFile && commandFile !== indexFile) {
24
+ references.push(indexFile);
25
+ }
26
+ }
27
+ else if (indexFile) {
28
+ edits.push(indexFile);
29
+ }
30
+ if ((command === "update" || /update\s*preview|preview/i.test(requirement)) && updateFile && !edits.includes(updateFile) && !references.includes(updateFile)) {
31
+ references.push(updateFile);
32
+ }
33
+ return {
34
+ command,
35
+ edit: unique(edits),
36
+ reference: unique(references)
37
+ };
38
+ }
39
+ export function mergeCommandTargetCandidates(candidates, target) {
40
+ if (!target) {
41
+ return candidates;
42
+ }
43
+ const byPath = new Map(candidates.map((candidate) => [candidate.path, candidate]));
44
+ for (const path of target.edit) {
45
+ byPath.set(path, bumpCandidate(byPath.get(path), path, 120, "edit", `command target:${target.command}`));
46
+ }
47
+ for (const path of target.reference) {
48
+ byPath.set(path, bumpCandidate(byPath.get(path), path, 80, "reference", relatedReason(target.command, path), true));
49
+ }
50
+ return [...byPath.values()].sort((a, b) => b.score - a.score || a.path.localeCompare(b.path)).slice(0, 30);
51
+ }
52
+ export function filterCommandTargetCandidates(candidates, target) {
53
+ if (!target) {
54
+ return candidates;
55
+ }
56
+ const allowedCommandFiles = new Set([...target.edit, ...target.reference]);
57
+ return candidates.filter((candidate) => {
58
+ if (allowedCommandFiles.has(candidate.path)) {
59
+ return true;
60
+ }
61
+ if ((target.command === "done" || target.command === "handoff" || target.command === "status") && /(^|\/)update\.ts$/i.test(candidate.path)) {
62
+ return false;
63
+ }
64
+ return true;
65
+ });
66
+ }
67
+ function bumpCandidate(candidate, path, score, role, reason, forceRole = false) {
68
+ const next = candidate ??
69
+ {
70
+ path,
71
+ score: 0,
72
+ reasons: [],
73
+ negativeReasons: [],
74
+ role
75
+ };
76
+ return {
77
+ ...next,
78
+ score: Math.max(next.score, score),
79
+ role: forceRole ? role : role === "edit" ? "edit" : next.role === "edit" ? "edit" : role,
80
+ reasons: [...new Set([reason, ...next.reasons])].slice(0, 8)
81
+ };
82
+ }
83
+ function detectCommand(requirement) {
84
+ const normalized = requirement.toLowerCase();
85
+ return knownCommands.find((command) => new RegExp(`(^|[^a-z0-9-])${escapeRegExp(command)}([^a-z0-9-]|$)`, "i").test(normalized));
86
+ }
87
+ function commandFileFor(command, fileSet) {
88
+ const normalized = command.replace(/-/g, "");
89
+ const candidates = [
90
+ `packages/cli/src/${command}.ts`,
91
+ `packages/cli/src/${normalized}.ts`,
92
+ command === "handoff" ? "packages/cli/src/runtime-state.ts" : "",
93
+ command === "task-ai" ? "packages/cli/src/task-ai.ts" : "",
94
+ command === "fix-prompt" ? "packages/cli/src/review.ts" : "",
95
+ command === "review" ? "packages/cli/src/review.ts" : "",
96
+ command === "check" ? "packages/cli/src/check.ts" : "",
97
+ command === "prompt" ? "packages/cli/src/prompt.ts" : "",
98
+ command === "doctor" ? "packages/cli/src/doctor.ts" : "",
99
+ command === "watch" ? "packages/cli/src/watch.ts" : "",
100
+ command === "update" ? "packages/cli/src/update.ts" : "",
101
+ command === "self" || command === "self-check" ? "packages/cli/src/self.ts" : "",
102
+ command === "scan" ? "packages/cli/src/scan.ts" : "",
103
+ command === "refresh" ? "packages/cli/src/refresh.ts" : "",
104
+ command === "telemetry" ? "packages/cli/src/telemetry.ts" : "",
105
+ command === "report" ? "packages/cli/src/report.ts" : ""
106
+ ].filter(Boolean);
107
+ return candidates.find((file) => fileSet.has(file));
108
+ }
109
+ function existing(fileSet, path) {
110
+ return fileSet.has(path) ? path : undefined;
111
+ }
112
+ function relatedReason(command, path) {
113
+ if (command === "done" && path.endsWith("/update.ts")) {
114
+ return "related update preview output";
115
+ }
116
+ return `command router/reference for ${command}`;
117
+ }
118
+ function unique(items) {
119
+ return [...new Set(items)];
120
+ }
121
+ function escapeRegExp(value) {
122
+ return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
123
+ }
124
+ //# sourceMappingURL=command-targets.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"command-targets.js","sourceRoot":"","sources":["../src/command-targets.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ import { type AIConfig, type DevGuardConfig } from "@dev-guard/core";
2
+ export interface ResolvedConfig {
3
+ config: DevGuardConfig;
4
+ source: string;
5
+ warnings: string[];
6
+ env: EnvResolution;
7
+ }
8
+ export interface EnvResolution {
9
+ apiKey: {
10
+ checked: Array<{
11
+ name: "DEV_GUARD_OPENAI_API_KEY" | "OPENAI_API_KEY";
12
+ found: boolean;
13
+ }>;
14
+ selectedKey?: "DEV_GUARD_OPENAI_API_KEY" | "OPENAI_API_KEY";
15
+ found: boolean;
16
+ };
17
+ }
18
+ export declare function loadConfig(root: string, cliAI?: Partial<AIConfig>): Promise<ResolvedConfig>;
19
+ export declare function writeConfigValue(root: string, key: string, value: string): Promise<DevGuardConfig>;
20
+ export declare function printConfigSummary(label: string, resolved: ResolvedConfig): void;
21
+ export declare function resolveOpenAIEnv(env?: NodeJS.ProcessEnv): EnvResolution;
22
+ export declare function readOpenAIApiKey(env?: NodeJS.ProcessEnv): string | undefined;
package/dist/config.js ADDED
@@ -0,0 +1,180 @@
1
+ import { defaultConfig } from "@dev-guard/core";
2
+ import { fromRoot, readJsonFile, readTextFile, writeTextFile } from "./fs.js";
3
+ const configCandidates = [".devguard/config.json", ".devguardrc", "devguard.config.json"];
4
+ export async function loadConfig(root, cliAI = {}) {
5
+ const warnings = [];
6
+ const local = await loadLocalConfig(root, warnings);
7
+ const envResolution = resolveOpenAIEnv();
8
+ const env = envConfig(envResolution);
9
+ const merged = mergeDevGuardConfig(defaultConfig, env, local.config, { ai: cliAI });
10
+ if (envResolution.apiKey.found) {
11
+ merged.ai = {
12
+ ...(merged.ai ?? {}),
13
+ provider: "openai",
14
+ model: merged.ai?.model ?? defaultConfig.ai.model
15
+ };
16
+ }
17
+ return {
18
+ config: merged,
19
+ source: sourceLabel(local.source, env),
20
+ warnings,
21
+ env: envResolution
22
+ };
23
+ }
24
+ export async function writeConfigValue(root, key, value) {
25
+ const configPath = fromRoot(root, ".devguard/config.json");
26
+ const current = await readJsonFile(configPath, defaultConfig);
27
+ const next = applyConfigValue(current, key, value);
28
+ await writeTextFile(configPath, `${JSON.stringify(next, null, 2)}\n`);
29
+ return next;
30
+ }
31
+ export function printConfigSummary(label, resolved) {
32
+ const ai = resolved.config.ai ?? {};
33
+ console.log(label);
34
+ console.log(`- provider: ${ai.provider ?? defaultConfig.ai.provider}`);
35
+ console.log(`- model: ${ai.model ?? defaultConfig.ai.model}`);
36
+ console.log(`- temperature: ${ai.temperature ?? defaultConfig.ai.temperature}`);
37
+ console.log(`- maxTokens: ${ai.maxTokens ?? defaultConfig.ai.maxTokens}`);
38
+ if (ai.reasoningEffort) {
39
+ console.log(`- reasoning effort: ${ai.reasoningEffort}`);
40
+ }
41
+ if (ai.baseURL) {
42
+ console.log(`- baseURL: ${ai.baseURL}`);
43
+ }
44
+ console.log(`- config source: ${resolved.source}`);
45
+ console.log(`- env DEV_GUARD_OPENAI_API_KEY: ${resolved.env.apiKey.checked[0]?.found ? "found" : "missing"}`);
46
+ console.log(`- env OPENAI_API_KEY: ${resolved.env.apiKey.checked[1]?.found ? "found" : "missing"}`);
47
+ console.log(`- selected API key source: ${resolved.env.apiKey.selectedKey ?? "none"}`);
48
+ for (const warning of resolved.warnings) {
49
+ console.log(`- warning: ${warning}`);
50
+ }
51
+ }
52
+ async function loadLocalConfig(root, warnings) {
53
+ for (const path of configCandidates) {
54
+ const text = await readTextFile(fromRoot(root, path));
55
+ if (!text.trim()) {
56
+ continue;
57
+ }
58
+ try {
59
+ return { config: JSON.parse(text), source: path };
60
+ }
61
+ catch (error) {
62
+ warnings.push(`${path} is invalid JSON; ignored (${errorMessage(error)})`);
63
+ continue;
64
+ }
65
+ }
66
+ const packageJson = await readJsonFile(fromRoot(root, "package.json"), {});
67
+ if (packageJson.devGuard) {
68
+ return { config: packageJson.devGuard, source: "package.json#devGuard" };
69
+ }
70
+ return { config: {}, source: "defaults/env" };
71
+ }
72
+ function envConfig(envResolution) {
73
+ const ai = {};
74
+ if (process.env.DEV_GUARD_PROVIDER === "openai" || process.env.DEV_GUARD_PROVIDER === "none") {
75
+ ai.provider = process.env.DEV_GUARD_PROVIDER;
76
+ }
77
+ if (envResolution.apiKey.found) {
78
+ ai.provider = "openai";
79
+ }
80
+ if (process.env.DEV_GUARD_MODEL) {
81
+ ai.model = process.env.DEV_GUARD_MODEL.trim();
82
+ }
83
+ if (process.env.DEV_GUARD_TEMPERATURE) {
84
+ ai.temperature = Number(process.env.DEV_GUARD_TEMPERATURE);
85
+ }
86
+ if (process.env.DEV_GUARD_MAX_TOKENS) {
87
+ ai.maxTokens = Number(process.env.DEV_GUARD_MAX_TOKENS);
88
+ }
89
+ if (process.env.DEV_GUARD_REASONING_EFFORT) {
90
+ ai.reasoningEffort = process.env.DEV_GUARD_REASONING_EFFORT;
91
+ }
92
+ if (process.env.DEV_GUARD_BASE_URL) {
93
+ ai.baseURL = process.env.DEV_GUARD_BASE_URL;
94
+ }
95
+ return Object.keys(ai).length > 0 ? { ai } : {};
96
+ }
97
+ export function resolveOpenAIEnv(env = process.env) {
98
+ const checked = [
99
+ { name: "DEV_GUARD_OPENAI_API_KEY", found: hasNonEmptyEnv(env.DEV_GUARD_OPENAI_API_KEY) },
100
+ { name: "OPENAI_API_KEY", found: hasNonEmptyEnv(env.OPENAI_API_KEY) }
101
+ ];
102
+ const selected = checked.find((entry) => entry.found);
103
+ return {
104
+ apiKey: {
105
+ checked,
106
+ selectedKey: selected?.name,
107
+ found: Boolean(selected)
108
+ }
109
+ };
110
+ }
111
+ export function readOpenAIApiKey(env = process.env) {
112
+ const devGuardKey = env.DEV_GUARD_OPENAI_API_KEY?.trim();
113
+ if (devGuardKey) {
114
+ return devGuardKey;
115
+ }
116
+ const openAIKey = env.OPENAI_API_KEY?.trim();
117
+ return openAIKey || undefined;
118
+ }
119
+ function hasNonEmptyEnv(value) {
120
+ return Boolean(value?.trim());
121
+ }
122
+ function sourceLabel(localSource, env) {
123
+ if (Object.keys(env.ai ?? {}).length === 0) {
124
+ return localSource;
125
+ }
126
+ return localSource.includes("env") ? localSource : `${localSource}+env`;
127
+ }
128
+ function mergeDevGuardConfig(...configs) {
129
+ return configs.reduce((merged, config) => ({
130
+ ...merged,
131
+ ...config,
132
+ ai: {
133
+ ...(merged.ai ?? {}),
134
+ ...(config.ai ?? {})
135
+ }
136
+ }), {});
137
+ }
138
+ function applyConfigValue(config, key, value) {
139
+ const ai = { ...(config.ai ?? {}) };
140
+ if (key === "provider") {
141
+ if (value !== "openai" && value !== "none") {
142
+ throw new Error("provider 값은 openai 또는 none만 지원합니다.");
143
+ }
144
+ ai.provider = value;
145
+ }
146
+ else if (key === "model") {
147
+ ai.model = value;
148
+ }
149
+ else if (key === "temperature") {
150
+ const numberValue = Number(value);
151
+ if (!Number.isFinite(numberValue)) {
152
+ throw new Error("temperature 값은 숫자여야 합니다.");
153
+ }
154
+ ai.temperature = numberValue;
155
+ }
156
+ else if (key === "maxTokens") {
157
+ const numberValue = Number(value);
158
+ if (!Number.isFinite(numberValue) || numberValue <= 0) {
159
+ throw new Error("maxTokens 값은 양수여야 합니다.");
160
+ }
161
+ ai.maxTokens = numberValue;
162
+ }
163
+ else if (key === "reasoningEffort") {
164
+ ai.reasoningEffort = value;
165
+ }
166
+ else if (key === "baseURL") {
167
+ ai.baseURL = value;
168
+ }
169
+ else {
170
+ throw new Error("지원하는 config key: provider, model, temperature, maxTokens, reasoningEffort, baseURL");
171
+ }
172
+ return {
173
+ ...config,
174
+ ai
175
+ };
176
+ }
177
+ function errorMessage(error) {
178
+ return error instanceof Error ? error.message : String(error);
179
+ }
180
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export declare function runConfigure(root: string, args: string[]): Promise<void>;
@@ -0,0 +1,79 @@
1
+ import { defaultConfig } from "@dev-guard/core";
2
+ import { fromRoot, readJsonFile, writeTextFile } from "./fs.js";
3
+ import { loadConfig, printConfigSummary, writeConfigValue } from "./config.js";
4
+ export async function runConfigure(root, args) {
5
+ const target = args[0];
6
+ if (target === "set") {
7
+ const key = args[1];
8
+ const value = args[2];
9
+ if (!key || value === undefined) {
10
+ throw new Error("사용법: dev-guard config set <provider|model|temperature|maxTokens|reasoningEffort|baseURL> <value>");
11
+ }
12
+ const next = await writeConfigValue(root, key, value);
13
+ console.log("dev-guard config set");
14
+ console.log(`- ${key}: ${value}`);
15
+ console.log("- wrote: .devguard/config.json");
16
+ console.log(`- provider: ${next.ai?.provider ?? defaultConfig.ai.provider}`);
17
+ console.log(`- model: ${next.ai?.model ?? defaultConfig.ai.model}`);
18
+ return;
19
+ }
20
+ if (target === "show" || target === undefined) {
21
+ printConfigSummary("dev-guard config", await loadConfig(root));
22
+ return;
23
+ }
24
+ if (target !== "ai") {
25
+ throw new Error("지원하는 configure 대상: ai, set, show. 예: dev-guard config set model gpt-5");
26
+ }
27
+ const options = parseConfigureAIOptions(args.slice(1));
28
+ const configPath = fromRoot(root, ".devguard/config.json");
29
+ const current = await readJsonFile(configPath, defaultConfig);
30
+ const next = {
31
+ ...current,
32
+ ai: {
33
+ provider: options.provider,
34
+ model: options.model
35
+ }
36
+ };
37
+ await writeTextFile(configPath, `${JSON.stringify(next, null, 2)}\n`);
38
+ const resolved = await loadConfig(root);
39
+ const storedAI = next.ai ?? {};
40
+ const resolvedAI = resolved.config.ai ?? {};
41
+ console.log("dev-guard configure ai");
42
+ console.log("Stored Config:");
43
+ console.log(`- provider: ${storedAI.provider ?? defaultConfig.ai.provider}`);
44
+ console.log(`- model: ${storedAI.model ?? defaultConfig.ai.model}`);
45
+ console.log("- config source: .devguard/config.json");
46
+ console.log("");
47
+ console.log("Runtime Resolution:");
48
+ console.log(`- resolved provider: ${resolvedAI.provider ?? defaultConfig.ai.provider}`);
49
+ console.log(`- resolved model: ${resolvedAI.model ?? defaultConfig.ai.model}`);
50
+ console.log(`- API key: ${resolved.env.apiKey.found ? "found" : "missing"}`);
51
+ console.log(`- API key source: ${resolved.env.apiKey.selectedKey ?? "none"}`);
52
+ console.log(`- config source: ${resolved.source}`);
53
+ console.log("");
54
+ console.log("Note:");
55
+ console.log("- API key is not stored. It is read from environment at runtime.");
56
+ }
57
+ function parseConfigureAIOptions(args) {
58
+ const provider = readOption(args, "--provider") ?? "none";
59
+ const model = readOption(args, "--model") ?? "gpt-4o-mini";
60
+ if (provider !== "openai" && provider !== "none") {
61
+ throw new Error("지원하지 않는 AI provider입니다. 가능한 값: openai, none");
62
+ }
63
+ return {
64
+ provider,
65
+ model
66
+ };
67
+ }
68
+ function readOption(args, name) {
69
+ const index = args.indexOf(name);
70
+ if (index < 0) {
71
+ return undefined;
72
+ }
73
+ const value = args[index + 1];
74
+ if (!value || value.startsWith("--")) {
75
+ throw new Error(`${name} 옵션에는 값이 필요합니다.`);
76
+ }
77
+ return value;
78
+ }
79
+ //# sourceMappingURL=configure.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"configure.js","sourceRoot":"","sources":["../src/configure.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export declare function runDoctor(root: string, args?: string[]): Promise<void>;