inkos-n 1.2.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 (221) hide show
  1. package/dist/commands/agent.d.ts +3 -0
  2. package/dist/commands/agent.d.ts.map +1 -0
  3. package/dist/commands/agent.js +59 -0
  4. package/dist/commands/agent.js.map +1 -0
  5. package/dist/commands/analytics.d.ts +3 -0
  6. package/dist/commands/analytics.d.ts.map +1 -0
  7. package/dist/commands/analytics.js +74 -0
  8. package/dist/commands/analytics.js.map +1 -0
  9. package/dist/commands/audit.d.ts +3 -0
  10. package/dist/commands/audit.d.ts.map +1 -0
  11. package/dist/commands/audit.js +52 -0
  12. package/dist/commands/audit.js.map +1 -0
  13. package/dist/commands/book.d.ts +3 -0
  14. package/dist/commands/book.d.ts.map +1 -0
  15. package/dist/commands/book.js +250 -0
  16. package/dist/commands/book.js.map +1 -0
  17. package/dist/commands/compose.d.ts +3 -0
  18. package/dist/commands/compose.d.ts.map +1 -0
  19. package/dist/commands/compose.js +47 -0
  20. package/dist/commands/compose.js.map +1 -0
  21. package/dist/commands/config.d.ts +3 -0
  22. package/dist/commands/config.d.ts.map +1 -0
  23. package/dist/commands/config.js +293 -0
  24. package/dist/commands/config.js.map +1 -0
  25. package/dist/commands/consolidate.d.ts +3 -0
  26. package/dist/commands/consolidate.d.ts.map +1 -0
  27. package/dist/commands/consolidate.js +50 -0
  28. package/dist/commands/consolidate.js.map +1 -0
  29. package/dist/commands/daemon.d.ts +4 -0
  30. package/dist/commands/daemon.d.ts.map +1 -0
  31. package/dist/commands/daemon.js +118 -0
  32. package/dist/commands/daemon.js.map +1 -0
  33. package/dist/commands/detect.d.ts +3 -0
  34. package/dist/commands/detect.d.ts.map +1 -0
  35. package/dist/commands/detect.js +104 -0
  36. package/dist/commands/detect.js.map +1 -0
  37. package/dist/commands/doctor.d.ts +3 -0
  38. package/dist/commands/doctor.d.ts.map +1 -0
  39. package/dist/commands/doctor.js +233 -0
  40. package/dist/commands/doctor.js.map +1 -0
  41. package/dist/commands/draft.d.ts +3 -0
  42. package/dist/commands/draft.d.ts.map +1 -0
  43. package/dist/commands/draft.js +42 -0
  44. package/dist/commands/draft.js.map +1 -0
  45. package/dist/commands/eval.d.ts +3 -0
  46. package/dist/commands/eval.d.ts.map +1 -0
  47. package/dist/commands/eval.js +168 -0
  48. package/dist/commands/eval.js.map +1 -0
  49. package/dist/commands/export.d.ts +3 -0
  50. package/dist/commands/export.d.ts.map +1 -0
  51. package/dist/commands/export.js +115 -0
  52. package/dist/commands/export.js.map +1 -0
  53. package/dist/commands/fanfic.d.ts +3 -0
  54. package/dist/commands/fanfic.d.ts.map +1 -0
  55. package/dist/commands/fanfic.js +180 -0
  56. package/dist/commands/fanfic.js.map +1 -0
  57. package/dist/commands/genre.d.ts +3 -0
  58. package/dist/commands/genre.d.ts.map +1 -0
  59. package/dist/commands/genre.js +152 -0
  60. package/dist/commands/genre.js.map +1 -0
  61. package/dist/commands/import.d.ts +3 -0
  62. package/dist/commands/import.d.ts.map +1 -0
  63. package/dist/commands/import.js +136 -0
  64. package/dist/commands/import.js.map +1 -0
  65. package/dist/commands/init.d.ts +3 -0
  66. package/dist/commands/init.d.ts.map +1 -0
  67. package/dist/commands/init.js +132 -0
  68. package/dist/commands/init.js.map +1 -0
  69. package/dist/commands/interact.d.ts +25 -0
  70. package/dist/commands/interact.d.ts.map +1 -0
  71. package/dist/commands/interact.js +73 -0
  72. package/dist/commands/interact.js.map +1 -0
  73. package/dist/commands/plan.d.ts +3 -0
  74. package/dist/commands/plan.d.ts.map +1 -0
  75. package/dist/commands/plan.js +51 -0
  76. package/dist/commands/plan.js.map +1 -0
  77. package/dist/commands/radar.d.ts +3 -0
  78. package/dist/commands/radar.d.ts.map +1 -0
  79. package/dist/commands/radar.js +52 -0
  80. package/dist/commands/radar.js.map +1 -0
  81. package/dist/commands/review.d.ts +3 -0
  82. package/dist/commands/review.d.ts.map +1 -0
  83. package/dist/commands/review.js +229 -0
  84. package/dist/commands/review.js.map +1 -0
  85. package/dist/commands/revise.d.ts +3 -0
  86. package/dist/commands/revise.d.ts.map +1 -0
  87. package/dist/commands/revise.js +60 -0
  88. package/dist/commands/revise.js.map +1 -0
  89. package/dist/commands/status.d.ts +3 -0
  90. package/dist/commands/status.d.ts.map +1 -0
  91. package/dist/commands/status.js +123 -0
  92. package/dist/commands/status.js.map +1 -0
  93. package/dist/commands/studio.d.ts +14 -0
  94. package/dist/commands/studio.d.ts.map +1 -0
  95. package/dist/commands/studio.js +120 -0
  96. package/dist/commands/studio.js.map +1 -0
  97. package/dist/commands/style.d.ts +3 -0
  98. package/dist/commands/style.d.ts.map +1 -0
  99. package/dist/commands/style.js +95 -0
  100. package/dist/commands/style.js.map +1 -0
  101. package/dist/commands/tui.d.ts +6 -0
  102. package/dist/commands/tui.d.ts.map +1 -0
  103. package/dist/commands/tui.js +14 -0
  104. package/dist/commands/tui.js.map +1 -0
  105. package/dist/commands/update.d.ts +3 -0
  106. package/dist/commands/update.d.ts.map +1 -0
  107. package/dist/commands/update.js +40 -0
  108. package/dist/commands/update.js.map +1 -0
  109. package/dist/commands/write.d.ts +3 -0
  110. package/dist/commands/write.d.ts.map +1 -0
  111. package/dist/commands/write.js +323 -0
  112. package/dist/commands/write.js.map +1 -0
  113. package/dist/index.d.ts +3 -0
  114. package/dist/index.d.ts.map +1 -0
  115. package/dist/index.js +4 -0
  116. package/dist/index.js.map +1 -0
  117. package/dist/localization.d.ts +38 -0
  118. package/dist/localization.d.ts.map +1 -0
  119. package/dist/localization.js +144 -0
  120. package/dist/localization.js.map +1 -0
  121. package/dist/program.d.ts +10 -0
  122. package/dist/program.d.ts.map +1 -0
  123. package/dist/program.js +85 -0
  124. package/dist/program.js.map +1 -0
  125. package/dist/progress-text.d.ts +26 -0
  126. package/dist/progress-text.d.ts.map +1 -0
  127. package/dist/progress-text.js +35 -0
  128. package/dist/progress-text.js.map +1 -0
  129. package/dist/runtime-requirements.d.ts +28 -0
  130. package/dist/runtime-requirements.d.ts.map +1 -0
  131. package/dist/runtime-requirements.js +99 -0
  132. package/dist/runtime-requirements.js.map +1 -0
  133. package/dist/tui/__tests__/markdown.test.d.ts +2 -0
  134. package/dist/tui/__tests__/markdown.test.d.ts.map +1 -0
  135. package/dist/tui/__tests__/markdown.test.js +58 -0
  136. package/dist/tui/__tests__/markdown.test.js.map +1 -0
  137. package/dist/tui/activity-state.d.ts +10 -0
  138. package/dist/tui/activity-state.d.ts.map +1 -0
  139. package/dist/tui/activity-state.js +27 -0
  140. package/dist/tui/activity-state.js.map +1 -0
  141. package/dist/tui/ansi.d.ts +40 -0
  142. package/dist/tui/ansi.d.ts.map +1 -0
  143. package/dist/tui/ansi.js +62 -0
  144. package/dist/tui/ansi.js.map +1 -0
  145. package/dist/tui/app.d.ts +103 -0
  146. package/dist/tui/app.d.ts.map +1 -0
  147. package/dist/tui/app.js +151 -0
  148. package/dist/tui/app.js.map +1 -0
  149. package/dist/tui/chat-depth.d.ts +9 -0
  150. package/dist/tui/chat-depth.d.ts.map +1 -0
  151. package/dist/tui/chat-depth.js +14 -0
  152. package/dist/tui/chat-depth.js.map +1 -0
  153. package/dist/tui/chat-draft.d.ts +4 -0
  154. package/dist/tui/chat-draft.d.ts.map +1 -0
  155. package/dist/tui/chat-draft.js +28 -0
  156. package/dist/tui/chat-draft.js.map +1 -0
  157. package/dist/tui/composer-caret.d.ts +10 -0
  158. package/dist/tui/composer-caret.d.ts.map +1 -0
  159. package/dist/tui/composer-caret.js +13 -0
  160. package/dist/tui/composer-caret.js.map +1 -0
  161. package/dist/tui/composer-display.d.ts +7 -0
  162. package/dist/tui/composer-display.d.ts.map +1 -0
  163. package/dist/tui/composer-display.js +17 -0
  164. package/dist/tui/composer-display.js.map +1 -0
  165. package/dist/tui/dashboard-model.d.ts +46 -0
  166. package/dist/tui/dashboard-model.d.ts.map +1 -0
  167. package/dist/tui/dashboard-model.js +105 -0
  168. package/dist/tui/dashboard-model.js.map +1 -0
  169. package/dist/tui/dashboard.d.ts +39 -0
  170. package/dist/tui/dashboard.d.ts.map +1 -0
  171. package/dist/tui/dashboard.js +348 -0
  172. package/dist/tui/dashboard.js.map +1 -0
  173. package/dist/tui/effects.d.ts +61 -0
  174. package/dist/tui/effects.d.ts.map +1 -0
  175. package/dist/tui/effects.js +459 -0
  176. package/dist/tui/effects.js.map +1 -0
  177. package/dist/tui/i18n.d.ts +69 -0
  178. package/dist/tui/i18n.d.ts.map +1 -0
  179. package/dist/tui/i18n.js +239 -0
  180. package/dist/tui/i18n.js.map +1 -0
  181. package/dist/tui/input-history.d.ts +12 -0
  182. package/dist/tui/input-history.d.ts.map +1 -0
  183. package/dist/tui/input-history.js +47 -0
  184. package/dist/tui/input-history.js.map +1 -0
  185. package/dist/tui/local-commands.d.ts +5 -0
  186. package/dist/tui/local-commands.d.ts.map +1 -0
  187. package/dist/tui/local-commands.js +43 -0
  188. package/dist/tui/local-commands.js.map +1 -0
  189. package/dist/tui/markdown.d.ts +2 -0
  190. package/dist/tui/markdown.d.ts.map +1 -0
  191. package/dist/tui/markdown.js +60 -0
  192. package/dist/tui/markdown.js.map +1 -0
  193. package/dist/tui/output.d.ts +11 -0
  194. package/dist/tui/output.d.ts.map +1 -0
  195. package/dist/tui/output.js +24 -0
  196. package/dist/tui/output.js.map +1 -0
  197. package/dist/tui/session-store.d.ts +2 -0
  198. package/dist/tui/session-store.d.ts.map +1 -0
  199. package/dist/tui/session-store.js +2 -0
  200. package/dist/tui/session-store.js.map +1 -0
  201. package/dist/tui/setup.d.ts +49 -0
  202. package/dist/tui/setup.d.ts.map +1 -0
  203. package/dist/tui/setup.js +268 -0
  204. package/dist/tui/setup.js.map +1 -0
  205. package/dist/tui/slash-autocomplete.d.ts +6 -0
  206. package/dist/tui/slash-autocomplete.d.ts.map +1 -0
  207. package/dist/tui/slash-autocomplete.js +50 -0
  208. package/dist/tui/slash-autocomplete.js.map +1 -0
  209. package/dist/tui/theme.d.ts +13 -0
  210. package/dist/tui/theme.d.ts.map +1 -0
  211. package/dist/tui/theme.js +15 -0
  212. package/dist/tui/theme.js.map +1 -0
  213. package/dist/tui/tools.d.ts +15 -0
  214. package/dist/tui/tools.d.ts.map +1 -0
  215. package/dist/tui/tools.js +17 -0
  216. package/dist/tui/tools.js.map +1 -0
  217. package/dist/utils.d.ts +25 -0
  218. package/dist/utils.d.ts.map +1 -0
  219. package/dist/utils.js +114 -0
  220. package/dist/utils.js.map +1 -0
  221. package/package.json +65 -0
@@ -0,0 +1,293 @@
1
+ import { Command } from "commander";
2
+ import { readFile, writeFile, mkdir } from "node:fs/promises";
3
+ import { join } from "node:path";
4
+ import { findProjectRoot, log, logError, GLOBAL_CONFIG_DIR, GLOBAL_ENV_PATH } from "../utils.js";
5
+ export const configCommand = new Command("config")
6
+ .description("Manage project configuration");
7
+ configCommand
8
+ .command("set")
9
+ .description("Set a configuration value")
10
+ .argument("<key>", "Config key (e.g., llm.apiKey)")
11
+ .argument("<value>", "Config value")
12
+ .action(async (key, value) => {
13
+ const root = findProjectRoot();
14
+ const configPath = join(root, "inkos.json");
15
+ try {
16
+ const raw = await readFile(configPath, "utf-8");
17
+ const config = JSON.parse(raw);
18
+ const keys = key.split(".");
19
+ const KNOWN_KEYS = new Set([
20
+ "llm.provider", "llm.baseUrl", "llm.model", "llm.temperature",
21
+ "llm.maxTokens", "llm.thinkingBudget", "llm.apiFormat", "llm.stream",
22
+ "inputGovernanceMode",
23
+ "daemon.schedule.radarCron", "daemon.schedule.writeCron",
24
+ "daemon.maxConcurrentBooks", "daemon.chaptersPerCycle",
25
+ "daemon.retryDelayMs", "daemon.cooldownAfterChapterMs",
26
+ "daemon.maxChaptersPerDay",
27
+ ]);
28
+ // Allow any key under llm.extra.* (passthrough to API)
29
+ if (!KNOWN_KEYS.has(key) && !key.startsWith("llm.extra.")) {
30
+ // Find closest match by edit distance on the last segment
31
+ const candidates = [...KNOWN_KEYS];
32
+ const inputParts = key.split(".");
33
+ const samePrefixCandidates = candidates.filter(k => {
34
+ const parts = k.split(".");
35
+ return parts.length === inputParts.length && parts.slice(0, -1).join(".") === inputParts.slice(0, -1).join(".");
36
+ });
37
+ const editDist = (a, b) => {
38
+ const m = a.length, n = b.length;
39
+ const dp = Array.from({ length: m + 1 }, (_, i) => Array.from({ length: n + 1 }, (_, j) => i === 0 ? j : j === 0 ? i : 0));
40
+ for (let i = 1; i <= m; i++)
41
+ for (let j = 1; j <= n; j++)
42
+ dp[i][j] = Math.min(dp[i - 1][j] + 1, dp[i][j - 1] + 1, dp[i - 1][j - 1] + (a[i - 1] !== b[j - 1] ? 1 : 0));
43
+ return dp[m][n];
44
+ };
45
+ const inputLast = inputParts[inputParts.length - 1];
46
+ const suggestion = samePrefixCandidates
47
+ .map(k => ({ k, d: editDist(k.split(".").pop(), inputLast) }))
48
+ .sort((a, b) => a.d - b.d)
49
+ .find(x => x.d <= 3)?.k;
50
+ logError(`Unknown config key "${key}".${suggestion ? ` Did you mean "${suggestion}"?` : ""}`);
51
+ log(`Known keys: ${candidates.join(", ")}`);
52
+ process.exit(1);
53
+ }
54
+ let target = config;
55
+ for (let i = 0; i < keys.length - 1; i++) {
56
+ const k = keys[i];
57
+ if (!(k in target)) {
58
+ target[k] = {};
59
+ }
60
+ target = target[k];
61
+ }
62
+ const finalKey = keys[keys.length - 1];
63
+ // Auto-coerce types: numbers and booleans shouldn't be stored as strings
64
+ if (/^\d+(\.\d+)?$/.test(value)) {
65
+ target[finalKey] = parseFloat(value);
66
+ }
67
+ else if (value === "true") {
68
+ target[finalKey] = true;
69
+ }
70
+ else if (value === "false") {
71
+ target[finalKey] = false;
72
+ }
73
+ else {
74
+ target[finalKey] = value;
75
+ }
76
+ await writeFile(configPath, JSON.stringify(config, null, 2), "utf-8");
77
+ log(`Set ${key} = ${value}`);
78
+ }
79
+ catch (e) {
80
+ logError(`Failed to update config: ${e}`);
81
+ process.exit(1);
82
+ }
83
+ });
84
+ configCommand
85
+ .command("set-global")
86
+ .description("Set global LLM config (~/.inkos/.env), shared by all projects")
87
+ .requiredOption("--provider <provider>", "LLM provider (openai / anthropic)")
88
+ .requiredOption("--base-url <url>", "API base URL")
89
+ .requiredOption("--api-key <key>", "API key")
90
+ .requiredOption("--model <model>", "Model name")
91
+ .option("--temperature <n>", "Temperature")
92
+ .option("--max-tokens <n>", "Max output tokens")
93
+ .option("--thinking-budget <n>", "Anthropic thinking budget")
94
+ .option("--api-format <format>", "API format (chat / responses)")
95
+ .option("--lang <language>", "Default writing language: zh (Chinese) or en (English)")
96
+ .action(async (opts) => {
97
+ try {
98
+ await mkdir(GLOBAL_CONFIG_DIR, { recursive: true });
99
+ const lines = [
100
+ "# InkOS Global LLM Configuration",
101
+ `INKOS_LLM_PROVIDER=${opts.provider}`,
102
+ `INKOS_LLM_BASE_URL=${opts.baseUrl}`,
103
+ `INKOS_LLM_API_KEY=${opts.apiKey}`,
104
+ `INKOS_LLM_MODEL=${opts.model}`,
105
+ ];
106
+ if (opts.temperature)
107
+ lines.push(`INKOS_LLM_TEMPERATURE=${opts.temperature}`);
108
+ if (opts.maxTokens)
109
+ lines.push(`INKOS_LLM_MAX_TOKENS=${opts.maxTokens}`);
110
+ if (opts.thinkingBudget)
111
+ lines.push(`INKOS_LLM_THINKING_BUDGET=${opts.thinkingBudget}`);
112
+ if (opts.apiFormat)
113
+ lines.push(`INKOS_LLM_API_FORMAT=${opts.apiFormat}`);
114
+ if (opts.lang)
115
+ lines.push(`INKOS_DEFAULT_LANGUAGE=${opts.lang}`);
116
+ await writeFile(GLOBAL_ENV_PATH, lines.join("\n") + "\n", "utf-8");
117
+ log(`Global config saved to ${GLOBAL_ENV_PATH}`);
118
+ log("All projects will use this config unless overridden by project .env");
119
+ }
120
+ catch (e) {
121
+ logError(`Failed to set global config: ${e}`);
122
+ process.exit(1);
123
+ }
124
+ });
125
+ configCommand
126
+ .command("show-global")
127
+ .description("Show global LLM config (~/.inkos/.env)")
128
+ .action(async () => {
129
+ try {
130
+ const content = await readFile(GLOBAL_ENV_PATH, "utf-8");
131
+ const masked = content.replace(/(INKOS_LLM_API_KEY=)(.{8})(.*)(.{4})/, "$1$2...$4");
132
+ log(masked);
133
+ }
134
+ catch {
135
+ log("No global config found. Run 'inkos config set-global' to create one.");
136
+ }
137
+ });
138
+ configCommand
139
+ .command("show")
140
+ .description("Show current project configuration")
141
+ .action(async () => {
142
+ const root = findProjectRoot();
143
+ const configPath = join(root, "inkos.json");
144
+ try {
145
+ const raw = await readFile(configPath, "utf-8");
146
+ const config = JSON.parse(raw);
147
+ // Mask API key
148
+ if (config.llm?.apiKey) {
149
+ const key = config.llm.apiKey;
150
+ config.llm.apiKey = key.slice(0, 8) + "..." + key.slice(-4);
151
+ }
152
+ log(JSON.stringify(config, null, 2));
153
+ }
154
+ catch (e) {
155
+ logError(`Failed to read config: ${e}`);
156
+ process.exit(1);
157
+ }
158
+ });
159
+ const KNOWN_AGENTS = ["writer", "auditor", "reviser", "architect", "radar", "chapter-analyzer"];
160
+ const ENV_VAR_NAME_PATTERN = /^[A-Za-z_][A-Za-z0-9_]*$/;
161
+ function validateApiKeyEnvName(value) {
162
+ if (ENV_VAR_NAME_PATTERN.test(value))
163
+ return undefined;
164
+ if (/^(sk-|sess-|rk-|pk-)/i.test(value) || value.includes("://")) {
165
+ return "--api-key-env expects an environment variable name like PACKY_API_KEY, not a raw API key or URL.";
166
+ }
167
+ return `--api-key-env expects an environment variable name like PACKY_API_KEY. "${value}" is not a valid env var name.`;
168
+ }
169
+ configCommand
170
+ .command("set-model")
171
+ .description("Set model override for a specific agent (with optional provider routing)")
172
+ .argument("<agent>", `Agent name (${KNOWN_AGENTS.join(", ")})`)
173
+ .argument("<model>", "Model name")
174
+ .option("--base-url <url>", "API base URL (for different provider)")
175
+ .option("--provider <provider>", "Provider type (openai / anthropic / custom)")
176
+ .option("--api-key-env <envVar>", "Env variable name for API key (e.g., PACKYAPI_KEY)")
177
+ .option("--stream", "Enable streaming (default)")
178
+ .option("--no-stream", "Disable streaming")
179
+ .action(async (agent, model, opts) => {
180
+ if (!KNOWN_AGENTS.includes(agent)) {
181
+ logError(`Unknown agent "${agent}". Valid agents: ${KNOWN_AGENTS.join(", ")}`);
182
+ process.exit(1);
183
+ }
184
+ if (opts.apiKeyEnv) {
185
+ const validationError = validateApiKeyEnvName(opts.apiKeyEnv);
186
+ if (validationError) {
187
+ logError(validationError);
188
+ process.exit(1);
189
+ }
190
+ }
191
+ const root = findProjectRoot();
192
+ const configPath = join(root, "inkos.json");
193
+ try {
194
+ const raw = await readFile(configPath, "utf-8");
195
+ const config = JSON.parse(raw);
196
+ const overrides = config.modelOverrides ?? {};
197
+ const hasProviderOpts = opts.baseUrl || opts.provider || opts.apiKeyEnv || opts.stream === false;
198
+ if (hasProviderOpts) {
199
+ const override = { model };
200
+ if (opts.baseUrl)
201
+ override.baseUrl = opts.baseUrl;
202
+ if (opts.provider)
203
+ override.provider = opts.provider;
204
+ if (opts.apiKeyEnv)
205
+ override.apiKeyEnv = opts.apiKeyEnv;
206
+ if (opts.stream === false)
207
+ override.stream = false;
208
+ config.modelOverrides = { ...overrides, [agent]: override };
209
+ }
210
+ else {
211
+ config.modelOverrides = { ...overrides, [agent]: model };
212
+ }
213
+ await writeFile(configPath, JSON.stringify(config, null, 2), "utf-8");
214
+ log(`Model override: ${agent} → ${model}${opts.baseUrl ? ` (${opts.baseUrl})` : ""}`);
215
+ }
216
+ catch (e) {
217
+ logError(`Failed to update config: ${e}`);
218
+ process.exit(1);
219
+ }
220
+ });
221
+ configCommand
222
+ .command("remove-model")
223
+ .description("Remove model override for a specific agent (falls back to default)")
224
+ .argument("<agent>", "Agent name")
225
+ .action(async (agent) => {
226
+ const root = findProjectRoot();
227
+ const configPath = join(root, "inkos.json");
228
+ try {
229
+ const raw = await readFile(configPath, "utf-8");
230
+ const config = JSON.parse(raw);
231
+ const overrides = config.modelOverrides;
232
+ if (!overrides || !(agent in overrides)) {
233
+ log(`No model override for "${agent}".`);
234
+ return;
235
+ }
236
+ const { [agent]: _, ...rest } = overrides;
237
+ config.modelOverrides = Object.keys(rest).length > 0 ? rest : undefined;
238
+ await writeFile(configPath, JSON.stringify(config, null, 2), "utf-8");
239
+ log(`Removed model override for ${agent}. Will use default model.`);
240
+ }
241
+ catch (e) {
242
+ logError(`Failed to update config: ${e}`);
243
+ process.exit(1);
244
+ }
245
+ });
246
+ configCommand
247
+ .command("show-models")
248
+ .description("Show model routing for all agents")
249
+ .option("--json", "Output JSON")
250
+ .action(async (opts) => {
251
+ const root = findProjectRoot();
252
+ const configPath = join(root, "inkos.json");
253
+ try {
254
+ const raw = await readFile(configPath, "utf-8");
255
+ const config = JSON.parse(raw);
256
+ const defaultModel = config.llm?.model ?? "(not set)";
257
+ const overrides = config.modelOverrides ?? {};
258
+ if (opts.json) {
259
+ log(JSON.stringify({ defaultModel, overrides }, null, 2));
260
+ return;
261
+ }
262
+ log(`Default model: ${defaultModel}\n`);
263
+ if (Object.keys(overrides).length === 0) {
264
+ log("No agent-specific overrides. All agents use the default model.");
265
+ return;
266
+ }
267
+ log("Agent overrides:");
268
+ for (const [agent, value] of Object.entries(overrides)) {
269
+ if (typeof value === "string") {
270
+ log(` ${agent} → ${value}`);
271
+ }
272
+ else {
273
+ const o = value;
274
+ const parts = [o.model];
275
+ if (o.baseUrl)
276
+ parts.push(`@ ${o.baseUrl}`);
277
+ if (o.stream === false)
278
+ parts.push("[no-stream]");
279
+ log(` ${agent} → ${parts.join(" ")}`);
280
+ }
281
+ }
282
+ log("");
283
+ const usingDefault = KNOWN_AGENTS.filter((a) => !(a in overrides));
284
+ if (usingDefault.length > 0) {
285
+ log(`Using default: ${usingDefault.join(", ")}`);
286
+ }
287
+ }
288
+ catch (e) {
289
+ logError(`Failed to read config: ${e}`);
290
+ process.exit(1);
291
+ }
292
+ });
293
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/commands/config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { Command } from "commander";
2
+ export declare const consolidateCommand: Command;
3
+ //# sourceMappingURL=consolidate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"consolidate.d.ts","sourceRoot":"","sources":["../../src/commands/consolidate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAIpC,eAAO,MAAM,kBAAkB,SA6C3B,CAAC"}
@@ -0,0 +1,50 @@
1
+ import { Command } from "commander";
2
+ import { ConsolidatorAgent } from "@actalk/inkos-core";
3
+ import { loadConfig, buildPipelineConfig, findProjectRoot, resolveBookId, log, logError } from "../utils.js";
4
+ export const consolidateCommand = new Command("consolidate")
5
+ .description("Consolidate chapter summaries into volume-level summaries (reduces context for long books)")
6
+ .argument("[book-id]", "Book ID (auto-detected if only one book)")
7
+ .option("--json", "Output JSON")
8
+ .action(async (bookIdArg, opts) => {
9
+ try {
10
+ const config = await loadConfig();
11
+ const root = findProjectRoot();
12
+ const bookId = await resolveBookId(bookIdArg, root);
13
+ const pipelineConfig = buildPipelineConfig(config, root);
14
+ const consolidator = new ConsolidatorAgent({
15
+ client: pipelineConfig.client,
16
+ model: pipelineConfig.model,
17
+ projectRoot: root,
18
+ });
19
+ const { StateManager } = await import("@actalk/inkos-core");
20
+ const state = new StateManager(root);
21
+ const bookDir = state.bookDir(bookId);
22
+ if (!opts.json)
23
+ log(`Consolidating chapter summaries for "${bookId}"...`);
24
+ const result = await consolidator.consolidate(bookDir);
25
+ if (opts.json) {
26
+ log(JSON.stringify(result, null, 2));
27
+ }
28
+ else {
29
+ if (result.archivedVolumes === 0) {
30
+ log("No completed volumes found to consolidate.");
31
+ }
32
+ else {
33
+ log(`Consolidated ${result.archivedVolumes} volume(s).`);
34
+ log(`Retained ${result.retainedChapters} recent chapter summaries.`);
35
+ log(`Volume summaries saved to story/volume_summaries.md`);
36
+ log(`Detailed summaries archived to story/summaries_archive/`);
37
+ }
38
+ }
39
+ }
40
+ catch (e) {
41
+ if (opts.json) {
42
+ log(JSON.stringify({ error: String(e) }));
43
+ }
44
+ else {
45
+ logError(`Consolidation failed: ${e}`);
46
+ }
47
+ process.exit(1);
48
+ }
49
+ });
50
+ //# sourceMappingURL=consolidate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"consolidate.js","sourceRoot":"","sources":["../../src/commands/consolidate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,EAAE,UAAU,EAAE,mBAAmB,EAAE,eAAe,EAAE,aAAa,EAAE,GAAG,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAE7G,MAAM,CAAC,MAAM,kBAAkB,GAAG,IAAI,OAAO,CAAC,aAAa,CAAC;KACzD,WAAW,CAAC,4FAA4F,CAAC;KACzG,QAAQ,CAAC,WAAW,EAAE,0CAA0C,CAAC;KACjE,MAAM,CAAC,QAAQ,EAAE,aAAa,CAAC;KAC/B,MAAM,CAAC,KAAK,EAAE,SAA6B,EAAE,IAAI,EAAE,EAAE;IACpD,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,UAAU,EAAE,CAAC;QAClC,MAAM,IAAI,GAAG,eAAe,EAAE,CAAC;QAC/B,MAAM,MAAM,GAAG,MAAM,aAAa,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;QAEpD,MAAM,cAAc,GAAG,mBAAmB,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;QACzD,MAAM,YAAY,GAAG,IAAI,iBAAiB,CAAC;YACzC,MAAM,EAAE,cAAc,CAAC,MAAM;YAC7B,KAAK,EAAE,cAAc,CAAC,KAAK;YAC3B,WAAW,EAAE,IAAI;SAClB,CAAC,CAAC;QAEH,MAAM,EAAE,YAAY,EAAE,GAAG,MAAM,MAAM,CAAC,oBAAoB,CAAC,CAAC;QAC5D,MAAM,KAAK,GAAG,IAAI,YAAY,CAAC,IAAI,CAAC,CAAC;QACrC,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QAEtC,IAAI,CAAC,IAAI,CAAC,IAAI;YAAE,GAAG,CAAC,wCAAwC,MAAM,MAAM,CAAC,CAAC;QAE1E,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;QAEvD,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;YACd,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QACvC,CAAC;aAAM,CAAC;YACN,IAAI,MAAM,CAAC,eAAe,KAAK,CAAC,EAAE,CAAC;gBACjC,GAAG,CAAC,4CAA4C,CAAC,CAAC;YACpD,CAAC;iBAAM,CAAC;gBACN,GAAG,CAAC,gBAAgB,MAAM,CAAC,eAAe,aAAa,CAAC,CAAC;gBACzD,GAAG,CAAC,YAAY,MAAM,CAAC,gBAAgB,4BAA4B,CAAC,CAAC;gBACrE,GAAG,CAAC,qDAAqD,CAAC,CAAC;gBAC3D,GAAG,CAAC,yDAAyD,CAAC,CAAC;YACjE,CAAC;QACH,CAAC;IACH,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;YACd,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QAC5C,CAAC;aAAM,CAAC;YACN,QAAQ,CAAC,yBAAyB,CAAC,EAAE,CAAC,CAAC;QACzC,CAAC;QACD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC,CAAC,CAAC"}
@@ -0,0 +1,4 @@
1
+ import { Command } from "commander";
2
+ export declare const upCommand: Command;
3
+ export declare const downCommand: Command;
4
+ //# sourceMappingURL=daemon.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"daemon.d.ts","sourceRoot":"","sources":["../../src/commands/daemon.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AASpC,eAAO,MAAM,SAAS,SA2FlB,CAAC;AAEL,eAAO,MAAM,WAAW,SAkBpB,CAAC"}
@@ -0,0 +1,118 @@
1
+ import { Command } from "commander";
2
+ import { Scheduler } from "@actalk/inkos-core";
3
+ import { loadConfig, findProjectRoot, buildPipelineConfig, log, logError } from "../utils.js";
4
+ import { createWriteStream } from "node:fs";
5
+ import { writeFile, readFile, unlink } from "node:fs/promises";
6
+ import { join } from "node:path";
7
+ const PID_FILE = "inkos.pid";
8
+ export const upCommand = new Command("up")
9
+ .description("Start the InkOS daemon (autonomous mode)")
10
+ .option("-q, --quiet", "Suppress console output")
11
+ .action(async (opts) => {
12
+ let logStream;
13
+ let pidPath;
14
+ try {
15
+ const config = await loadConfig();
16
+ const root = findProjectRoot();
17
+ // Check if already running
18
+ pidPath = join(root, PID_FILE);
19
+ try {
20
+ const existingPid = await readFile(pidPath, "utf-8");
21
+ logError(`Daemon already running (PID: ${existingPid.trim()}). Run 'inkos down' first.`);
22
+ process.exit(1);
23
+ }
24
+ catch {
25
+ // No PID file, good
26
+ }
27
+ log("Starting InkOS daemon...");
28
+ log(` Write cycle: ${config.daemon.schedule.writeCron}`);
29
+ log(` Radar scan: ${config.daemon.schedule.radarCron}`);
30
+ log(` Max concurrent books: ${config.daemon.maxConcurrentBooks}`);
31
+ log("");
32
+ // Write PID file
33
+ await writeFile(pidPath, String(process.pid), "utf-8");
34
+ // File logging for daemon
35
+ const logPath = join(root, "inkos.log");
36
+ logStream = createWriteStream(logPath, { flags: "a" });
37
+ const scheduler = new Scheduler({
38
+ ...buildPipelineConfig(config, root, { logFile: logStream, quiet: opts.quiet }),
39
+ radarCron: config.daemon.schedule.radarCron,
40
+ writeCron: config.daemon.schedule.writeCron,
41
+ maxConcurrentBooks: config.daemon.maxConcurrentBooks,
42
+ chaptersPerCycle: config.daemon.chaptersPerCycle,
43
+ retryDelayMs: config.daemon.retryDelayMs,
44
+ cooldownAfterChapterMs: config.daemon.cooldownAfterChapterMs,
45
+ maxChaptersPerDay: config.daemon.maxChaptersPerDay,
46
+ onChapterComplete: (bookId, chapter, status) => {
47
+ const icon = status === "ready-for-review"
48
+ ? "+"
49
+ : status === "state-degraded"
50
+ ? "x"
51
+ : "!";
52
+ log(` [${icon}] ${bookId} Ch.${chapter} — ${status}`);
53
+ },
54
+ onError: (bookId, error) => {
55
+ logError(`${bookId}: ${error.message}`);
56
+ },
57
+ });
58
+ // Handle shutdown
59
+ const shutdown = async () => {
60
+ log("\nShutting down daemon...");
61
+ scheduler.stop();
62
+ logStream?.end();
63
+ const currentPidPath = pidPath;
64
+ if (currentPidPath !== undefined) {
65
+ try {
66
+ await unlink(currentPidPath);
67
+ }
68
+ catch {
69
+ // ignore
70
+ }
71
+ }
72
+ process.exit(0);
73
+ };
74
+ process.on("SIGINT", shutdown);
75
+ process.on("SIGTERM", shutdown);
76
+ await scheduler.start();
77
+ log("Daemon running. Press Ctrl+C to stop.");
78
+ // Keep process alive
79
+ await new Promise(() => { });
80
+ }
81
+ catch (e) {
82
+ logStream?.end();
83
+ if (pidPath !== undefined) {
84
+ try {
85
+ await unlink(pidPath);
86
+ }
87
+ catch {
88
+ // ignore
89
+ }
90
+ }
91
+ logError(`Failed to start daemon: ${e}`);
92
+ process.exit(1);
93
+ }
94
+ });
95
+ export const downCommand = new Command("down")
96
+ .description("Stop the InkOS daemon")
97
+ .action(async () => {
98
+ const root = findProjectRoot();
99
+ const pidPath = join(root, PID_FILE);
100
+ try {
101
+ const pid = (await readFile(pidPath, "utf-8")).trim();
102
+ try {
103
+ process.kill(parseInt(pid, 10), "SIGTERM");
104
+ log(`Daemon (PID: ${pid}) stopped.`);
105
+ }
106
+ catch {
107
+ log(`Daemon (PID: ${pid}) not found. Cleaning up.`);
108
+ }
109
+ try {
110
+ await unlink(pidPath);
111
+ }
112
+ catch { /* already cleaned up by daemon */ }
113
+ }
114
+ catch {
115
+ log("No daemon running.");
116
+ }
117
+ });
118
+ //# sourceMappingURL=daemon.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"daemon.js","sourceRoot":"","sources":["../../src/commands/daemon.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC/C,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,mBAAmB,EAAE,GAAG,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAC9F,OAAO,EAAE,iBAAiB,EAAoB,MAAM,SAAS,CAAC;AAC9D,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC/D,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,MAAM,QAAQ,GAAG,WAAW,CAAC;AAE7B,MAAM,CAAC,MAAM,SAAS,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC;KACvC,WAAW,CAAC,0CAA0C,CAAC;KACvD,MAAM,CAAC,aAAa,EAAE,yBAAyB,CAAC;KAChD,MAAM,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;IACrB,IAAI,SAAkC,CAAC;IACvC,IAAI,OAA2B,CAAC;IAChC,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,UAAU,EAAE,CAAC;QAClC,MAAM,IAAI,GAAG,eAAe,EAAE,CAAC;QAE/B,2BAA2B;QAC3B,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;QAC/B,IAAI,CAAC;YACH,MAAM,WAAW,GAAG,MAAM,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;YACrD,QAAQ,CAAC,gCAAgC,WAAW,CAAC,IAAI,EAAE,4BAA4B,CAAC,CAAC;YACzF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAAC,MAAM,CAAC;YACP,oBAAoB;QACtB,CAAC;QAED,GAAG,CAAC,0BAA0B,CAAC,CAAC;QAChC,GAAG,CAAC,kBAAkB,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,EAAE,CAAC,CAAC;QAC1D,GAAG,CAAC,iBAAiB,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,EAAE,CAAC,CAAC;QACzD,GAAG,CAAC,2BAA2B,MAAM,CAAC,MAAM,CAAC,kBAAkB,EAAE,CAAC,CAAC;QACnE,GAAG,CAAC,EAAE,CAAC,CAAC;QAER,iBAAiB;QACjB,MAAM,SAAS,CAAC,OAAO,EAAE,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC,CAAC;QAEvD,0BAA0B;QAC1B,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC;QACxC,SAAS,GAAG,iBAAiB,CAAC,OAAO,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC;QAEvD,MAAM,SAAS,GAAG,IAAI,SAAS,CAAC;YAC9B,GAAG,mBAAmB,CAAC,MAAM,EAAE,IAAI,EAAE,EAAE,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC;YAC/E,SAAS,EAAE,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS;YAC3C,SAAS,EAAE,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS;YAC3C,kBAAkB,EAAE,MAAM,CAAC,MAAM,CAAC,kBAAkB;YACpD,gBAAgB,EAAE,MAAM,CAAC,MAAM,CAAC,gBAAgB;YAChD,YAAY,EAAE,MAAM,CAAC,MAAM,CAAC,YAAY;YACxC,sBAAsB,EAAE,MAAM,CAAC,MAAM,CAAC,sBAAsB;YAC5D,iBAAiB,EAAE,MAAM,CAAC,MAAM,CAAC,iBAAiB;YAClD,iBAAiB,EAAE,CAAC,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE;gBAC7C,MAAM,IAAI,GAAG,MAAM,KAAK,kBAAkB;oBACxC,CAAC,CAAC,GAAG;oBACL,CAAC,CAAC,MAAM,KAAK,gBAAgB;wBAC3B,CAAC,CAAC,GAAG;wBACL,CAAC,CAAC,GAAG,CAAC;gBACV,GAAG,CAAC,MAAM,IAAI,KAAK,MAAM,OAAO,OAAO,MAAM,MAAM,EAAE,CAAC,CAAC;YACzD,CAAC;YACD,OAAO,EAAE,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE;gBACzB,QAAQ,CAAC,GAAG,MAAM,KAAK,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;YAC1C,CAAC;SACF,CAAC,CAAC;QAEH,kBAAkB;QAClB,MAAM,QAAQ,GAAG,KAAK,IAAI,EAAE;YAC1B,GAAG,CAAC,2BAA2B,CAAC,CAAC;YACjC,SAAS,CAAC,IAAI,EAAE,CAAC;YACjB,SAAS,EAAE,GAAG,EAAE,CAAC;YACjB,MAAM,cAAc,GAAG,OAAO,CAAC;YAC/B,IAAI,cAAc,KAAK,SAAS,EAAE,CAAC;gBACjC,IAAI,CAAC;oBACH,MAAM,MAAM,CAAC,cAAc,CAAC,CAAC;gBAC/B,CAAC;gBAAC,MAAM,CAAC;oBACP,SAAS;gBACX,CAAC;YACH,CAAC;YACD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC,CAAC;QAEF,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;QAC/B,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;QAEhC,MAAM,SAAS,CAAC,KAAK,EAAE,CAAC;QACxB,GAAG,CAAC,uCAAuC,CAAC,CAAC;QAE7C,qBAAqB;QACrB,MAAM,IAAI,OAAO,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;IAC9B,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,SAAS,EAAE,GAAG,EAAE,CAAC;QACjB,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;YAC1B,IAAI,CAAC;gBACH,MAAM,MAAM,CAAC,OAAO,CAAC,CAAC;YACxB,CAAC;YAAC,MAAM,CAAC;gBACP,SAAS;YACX,CAAC;QACH,CAAC;QACD,QAAQ,CAAC,2BAA2B,CAAC,EAAE,CAAC,CAAC;QACzC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC,CAAC,CAAC;AAEL,MAAM,CAAC,MAAM,WAAW,GAAG,IAAI,OAAO,CAAC,MAAM,CAAC;KAC3C,WAAW,CAAC,uBAAuB,CAAC;KACpC,MAAM,CAAC,KAAK,IAAI,EAAE;IACjB,MAAM,IAAI,GAAG,eAAe,EAAE,CAAC;IAC/B,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IAErC,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,CAAC,MAAM,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QACtD,IAAI,CAAC;YACH,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE,EAAE,CAAC,EAAE,SAAS,CAAC,CAAC;YAC3C,GAAG,CAAC,gBAAgB,GAAG,YAAY,CAAC,CAAC;QACvC,CAAC;QAAC,MAAM,CAAC;YACP,GAAG,CAAC,gBAAgB,GAAG,2BAA2B,CAAC,CAAC;QACtD,CAAC;QACD,IAAI,CAAC;YAAC,MAAM,MAAM,CAAC,OAAO,CAAC,CAAC;QAAC,CAAC;QAAC,MAAM,CAAC,CAAC,kCAAkC,CAAC,CAAC;IAC7E,CAAC;IAAC,MAAM,CAAC;QACP,GAAG,CAAC,oBAAoB,CAAC,CAAC;IAC5B,CAAC;AACH,CAAC,CAAC,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { Command } from "commander";
2
+ export declare const detectCommand: Command;
3
+ //# sourceMappingURL=detect.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"detect.d.ts","sourceRoot":"","sources":["../../src/commands/detect.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAYpC,eAAO,MAAM,aAAa,SA6EtB,CAAC"}
@@ -0,0 +1,104 @@
1
+ import { Command } from "commander";
2
+ import { StateManager, detectChapter, loadDetectionHistory, analyzeDetectionInsights, } from "@actalk/inkos-core";
3
+ import { loadConfig, findProjectRoot, resolveBookId, log, logError } from "../utils.js";
4
+ import { readFile, readdir } from "node:fs/promises";
5
+ import { join } from "node:path";
6
+ export const detectCommand = new Command("detect")
7
+ .description("Run AIGC detection on chapters")
8
+ .argument("[book-id]", "Book ID (auto-detected if only one book)")
9
+ .argument("[chapter]", "Chapter number (defaults to latest)")
10
+ .option("--all", "Detect all chapters")
11
+ .option("--stats", "Show detection statistics")
12
+ .option("--json", "Output JSON")
13
+ .action(async (bookIdArg, chapterStr, opts) => {
14
+ try {
15
+ const config = await loadConfig();
16
+ const root = findProjectRoot();
17
+ if (!config.detection?.enabled) {
18
+ logError("AIGC detection is not enabled. Add detection config to inkos.json.");
19
+ process.exit(1);
20
+ }
21
+ // If first arg looks like a number, treat it as chapter
22
+ let bookId;
23
+ let chapterNumber;
24
+ if (bookIdArg && /^\d+$/.test(bookIdArg)) {
25
+ bookId = await resolveBookId(undefined, root);
26
+ chapterNumber = parseInt(bookIdArg, 10);
27
+ }
28
+ else {
29
+ bookId = await resolveBookId(bookIdArg, root);
30
+ chapterNumber = chapterStr ? parseInt(chapterStr, 10) : undefined;
31
+ }
32
+ const state = new StateManager(root);
33
+ const bookDir = state.bookDir(bookId);
34
+ if (opts.stats) {
35
+ const history = await loadDetectionHistory(bookDir);
36
+ const stats = analyzeDetectionInsights(history);
37
+ if (opts.json) {
38
+ log(JSON.stringify(stats, null, 2));
39
+ }
40
+ else {
41
+ log(`Detection Statistics:`);
42
+ log(` Total detections: ${stats.totalDetections}`);
43
+ log(` Total rewrites: ${stats.totalRewrites}`);
44
+ log(` Avg original score: ${stats.avgOriginalScore.toFixed(3)}`);
45
+ log(` Avg final score: ${stats.avgFinalScore.toFixed(3)}`);
46
+ log(` Avg score reduction: ${stats.avgScoreReduction.toFixed(3)}`);
47
+ log(` Pass rate: ${(stats.passRate * 100).toFixed(0)}%`);
48
+ if (stats.chapterBreakdown.length > 0) {
49
+ log(` Chapters:`);
50
+ for (const ch of stats.chapterBreakdown) {
51
+ log(` Ch.${ch.chapterNumber}: ${ch.originalScore.toFixed(3)} → ${ch.finalScore.toFixed(3)} (${ch.rewriteAttempts} rewrites)`);
52
+ }
53
+ }
54
+ }
55
+ return;
56
+ }
57
+ const detectionConfig = config.detection;
58
+ if (opts.all) {
59
+ const index = await state.loadChapterIndex(bookId);
60
+ for (const ch of index) {
61
+ const content = await readChapterContent(bookDir, ch.number);
62
+ const result = await detectChapter(detectionConfig, content, ch.number);
63
+ printResult(result, opts.json);
64
+ }
65
+ }
66
+ else {
67
+ const targetChapter = chapterNumber ?? (await state.getNextChapterNumber(bookId)) - 1;
68
+ if (targetChapter < 1) {
69
+ logError("No chapters to detect.");
70
+ process.exit(1);
71
+ }
72
+ const content = await readChapterContent(bookDir, targetChapter);
73
+ const result = await detectChapter(detectionConfig, content, targetChapter);
74
+ printResult(result, opts.json);
75
+ }
76
+ }
77
+ catch (e) {
78
+ logError(`Detection failed: ${e}`);
79
+ process.exit(1);
80
+ }
81
+ });
82
+ function printResult(result, json) {
83
+ if (json) {
84
+ log(JSON.stringify(result, null, 2));
85
+ }
86
+ else {
87
+ const icon = result.passed ? "✅" : "⚠️";
88
+ log(` ${icon} Chapter ${result.chapterNumber}: score=${result.detection.score.toFixed(3)} (${result.detection.provider}) ${result.passed ? "PASS" : "FAIL"}`);
89
+ }
90
+ }
91
+ async function readChapterContent(bookDir, chapterNumber) {
92
+ const chaptersDir = join(bookDir, "chapters");
93
+ const files = await readdir(chaptersDir);
94
+ const paddedNum = String(chapterNumber).padStart(4, "0");
95
+ const chapterFile = files.find((f) => f.startsWith(paddedNum) && f.endsWith(".md"));
96
+ if (!chapterFile) {
97
+ throw new Error(`Chapter ${chapterNumber} file not found`);
98
+ }
99
+ const raw = await readFile(join(chaptersDir, chapterFile), "utf-8");
100
+ const lines = raw.split("\n");
101
+ const contentStart = lines.findIndex((l, i) => i > 0 && l.trim().length > 0);
102
+ return contentStart >= 0 ? lines.slice(contentStart).join("\n") : raw;
103
+ }
104
+ //# sourceMappingURL=detect.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"detect.js","sourceRoot":"","sources":["../../src/commands/detect.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { Command } from "commander";
2
+ export declare const doctorCommand: Command;
3
+ //# sourceMappingURL=doctor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../../src/commands/doctor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAUpC,eAAO,MAAM,aAAa,SAyOtB,CAAC"}