@aaronsb/kg-cli 0.6.1

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 (266) hide show
  1. package/README.md +112 -0
  2. package/dist/api/client.d.ts +867 -0
  3. package/dist/api/client.d.ts.map +1 -0
  4. package/dist/api/client.js +1362 -0
  5. package/dist/api/client.js.map +1 -0
  6. package/dist/cli/admin/backup.d.ts +9 -0
  7. package/dist/cli/admin/backup.d.ts.map +1 -0
  8. package/dist/cli/admin/backup.js +363 -0
  9. package/dist/cli/admin/backup.js.map +1 -0
  10. package/dist/cli/admin/index.d.ts +7 -0
  11. package/dist/cli/admin/index.d.ts.map +1 -0
  12. package/dist/cli/admin/index.js +52 -0
  13. package/dist/cli/admin/index.js.map +1 -0
  14. package/dist/cli/admin/scheduler.d.ts +7 -0
  15. package/dist/cli/admin/scheduler.d.ts.map +1 -0
  16. package/dist/cli/admin/scheduler.js +125 -0
  17. package/dist/cli/admin/scheduler.js.map +1 -0
  18. package/dist/cli/admin/status.d.ts +7 -0
  19. package/dist/cli/admin/status.d.ts.map +1 -0
  20. package/dist/cli/admin/status.js +134 -0
  21. package/dist/cli/admin/status.js.map +1 -0
  22. package/dist/cli/admin/utils.d.ts +34 -0
  23. package/dist/cli/admin/utils.d.ts.map +1 -0
  24. package/dist/cli/admin/utils.js +441 -0
  25. package/dist/cli/admin/utils.js.map +1 -0
  26. package/dist/cli/ai-config/embedding.d.ts +11 -0
  27. package/dist/cli/ai-config/embedding.d.ts.map +1 -0
  28. package/dist/cli/ai-config/embedding.js +598 -0
  29. package/dist/cli/ai-config/embedding.js.map +1 -0
  30. package/dist/cli/ai-config/extraction.d.ts +11 -0
  31. package/dist/cli/ai-config/extraction.d.ts.map +1 -0
  32. package/dist/cli/ai-config/extraction.js +206 -0
  33. package/dist/cli/ai-config/extraction.js.map +1 -0
  34. package/dist/cli/ai-config/index.d.ts +21 -0
  35. package/dist/cli/ai-config/index.d.ts.map +1 -0
  36. package/dist/cli/ai-config/index.js +27 -0
  37. package/dist/cli/ai-config/index.js.map +1 -0
  38. package/dist/cli/ai-config/keys.d.ts +11 -0
  39. package/dist/cli/ai-config/keys.d.ts.map +1 -0
  40. package/dist/cli/ai-config/keys.js +182 -0
  41. package/dist/cli/ai-config/keys.js.map +1 -0
  42. package/dist/cli/ai-config/utils.d.ts +13 -0
  43. package/dist/cli/ai-config/utils.d.ts.map +1 -0
  44. package/dist/cli/ai-config/utils.js +84 -0
  45. package/dist/cli/ai-config/utils.js.map +1 -0
  46. package/dist/cli/artifact.d.ts +8 -0
  47. package/dist/cli/artifact.d.ts.map +1 -0
  48. package/dist/cli/artifact.js +296 -0
  49. package/dist/cli/artifact.js.map +1 -0
  50. package/dist/cli/auth-admin.d.ts +11 -0
  51. package/dist/cli/auth-admin.d.ts.map +1 -0
  52. package/dist/cli/auth-admin.js +415 -0
  53. package/dist/cli/auth-admin.js.map +1 -0
  54. package/dist/cli/colors.d.ts +105 -0
  55. package/dist/cli/colors.d.ts.map +1 -0
  56. package/dist/cli/colors.js +164 -0
  57. package/dist/cli/colors.js.map +1 -0
  58. package/dist/cli/commands.d.ts +6 -0
  59. package/dist/cli/commands.d.ts.map +1 -0
  60. package/dist/cli/commands.js +164 -0
  61. package/dist/cli/commands.js.map +1 -0
  62. package/dist/cli/config.d.ts +6 -0
  63. package/dist/cli/config.d.ts.map +1 -0
  64. package/dist/cli/config.js +694 -0
  65. package/dist/cli/config.js.map +1 -0
  66. package/dist/cli/curve-viz.d.ts +89 -0
  67. package/dist/cli/curve-viz.d.ts.map +1 -0
  68. package/dist/cli/curve-viz.js +228 -0
  69. package/dist/cli/curve-viz.js.map +1 -0
  70. package/dist/cli/database.d.ts +6 -0
  71. package/dist/cli/database.d.ts.map +1 -0
  72. package/dist/cli/database.js +324 -0
  73. package/dist/cli/database.js.map +1 -0
  74. package/dist/cli/document.d.ts +6 -0
  75. package/dist/cli/document.d.ts.map +1 -0
  76. package/dist/cli/document.js +458 -0
  77. package/dist/cli/document.js.map +1 -0
  78. package/dist/cli/group.d.ts +8 -0
  79. package/dist/cli/group.d.ts.map +1 -0
  80. package/dist/cli/group.js +174 -0
  81. package/dist/cli/group.js.map +1 -0
  82. package/dist/cli/health.d.ts +6 -0
  83. package/dist/cli/health.d.ts.map +1 -0
  84. package/dist/cli/health.js +34 -0
  85. package/dist/cli/health.js.map +1 -0
  86. package/dist/cli/help-formatter.d.ts +16 -0
  87. package/dist/cli/help-formatter.d.ts.map +1 -0
  88. package/dist/cli/help-formatter.js +248 -0
  89. package/dist/cli/help-formatter.js.map +1 -0
  90. package/dist/cli/help.d.ts +9 -0
  91. package/dist/cli/help.d.ts.map +1 -0
  92. package/dist/cli/help.js +227 -0
  93. package/dist/cli/help.js.map +1 -0
  94. package/dist/cli/ingest.d.ts +6 -0
  95. package/dist/cli/ingest.d.ts.map +1 -0
  96. package/dist/cli/ingest.js +722 -0
  97. package/dist/cli/ingest.js.map +1 -0
  98. package/dist/cli/jobs.d.ts +6 -0
  99. package/dist/cli/jobs.d.ts.map +1 -0
  100. package/dist/cli/jobs.js +663 -0
  101. package/dist/cli/jobs.js.map +1 -0
  102. package/dist/cli/login.d.ts +21 -0
  103. package/dist/cli/login.d.ts.map +1 -0
  104. package/dist/cli/login.js +221 -0
  105. package/dist/cli/login.js.map +1 -0
  106. package/dist/cli/logout.d.ts +16 -0
  107. package/dist/cli/logout.d.ts.map +1 -0
  108. package/dist/cli/logout.js +141 -0
  109. package/dist/cli/logout.js.map +1 -0
  110. package/dist/cli/mcp-config.d.ts +10 -0
  111. package/dist/cli/mcp-config.d.ts.map +1 -0
  112. package/dist/cli/mcp-config.js +358 -0
  113. package/dist/cli/mcp-config.js.map +1 -0
  114. package/dist/cli/oauth.d.ts +15 -0
  115. package/dist/cli/oauth.d.ts.map +1 -0
  116. package/dist/cli/oauth.js +296 -0
  117. package/dist/cli/oauth.js.map +1 -0
  118. package/dist/cli/ontology.d.ts +6 -0
  119. package/dist/cli/ontology.d.ts.map +1 -0
  120. package/dist/cli/ontology.js +231 -0
  121. package/dist/cli/ontology.js.map +1 -0
  122. package/dist/cli/polarity.d.ts +6 -0
  123. package/dist/cli/polarity.d.ts.map +1 -0
  124. package/dist/cli/polarity.js +295 -0
  125. package/dist/cli/polarity.js.map +1 -0
  126. package/dist/cli/projection.d.ts +8 -0
  127. package/dist/cli/projection.d.ts.map +1 -0
  128. package/dist/cli/projection.js +297 -0
  129. package/dist/cli/projection.js.map +1 -0
  130. package/dist/cli/query-def.d.ts +8 -0
  131. package/dist/cli/query-def.d.ts.map +1 -0
  132. package/dist/cli/query-def.js +163 -0
  133. package/dist/cli/query-def.js.map +1 -0
  134. package/dist/cli/rbac.d.ts +12 -0
  135. package/dist/cli/rbac.d.ts.map +1 -0
  136. package/dist/cli/rbac.js +615 -0
  137. package/dist/cli/rbac.js.map +1 -0
  138. package/dist/cli/search.d.ts +6 -0
  139. package/dist/cli/search.d.ts.map +1 -0
  140. package/dist/cli/search.js +829 -0
  141. package/dist/cli/search.js.map +1 -0
  142. package/dist/cli/source.d.ts +6 -0
  143. package/dist/cli/source.d.ts.map +1 -0
  144. package/dist/cli/source.js +202 -0
  145. package/dist/cli/source.js.map +1 -0
  146. package/dist/cli/verb-router.d.ts +25 -0
  147. package/dist/cli/verb-router.d.ts.map +1 -0
  148. package/dist/cli/verb-router.js +415 -0
  149. package/dist/cli/verb-router.js.map +1 -0
  150. package/dist/cli/vocabulary/config.d.ts +7 -0
  151. package/dist/cli/vocabulary/config.d.ts.map +1 -0
  152. package/dist/cli/vocabulary/config.js +201 -0
  153. package/dist/cli/vocabulary/config.js.map +1 -0
  154. package/dist/cli/vocabulary/consolidate.d.ts +8 -0
  155. package/dist/cli/vocabulary/consolidate.d.ts.map +1 -0
  156. package/dist/cli/vocabulary/consolidate.js +192 -0
  157. package/dist/cli/vocabulary/consolidate.js.map +1 -0
  158. package/dist/cli/vocabulary/embeddings.d.ts +9 -0
  159. package/dist/cli/vocabulary/embeddings.d.ts.map +1 -0
  160. package/dist/cli/vocabulary/embeddings.js +205 -0
  161. package/dist/cli/vocabulary/embeddings.js.map +1 -0
  162. package/dist/cli/vocabulary/epistemic.d.ts +7 -0
  163. package/dist/cli/vocabulary/epistemic.d.ts.map +1 -0
  164. package/dist/cli/vocabulary/epistemic.js +315 -0
  165. package/dist/cli/vocabulary/epistemic.js.map +1 -0
  166. package/dist/cli/vocabulary/index.d.ts +7 -0
  167. package/dist/cli/vocabulary/index.d.ts.map +1 -0
  168. package/dist/cli/vocabulary/index.js +45 -0
  169. package/dist/cli/vocabulary/index.js.map +1 -0
  170. package/dist/cli/vocabulary/profiles.d.ts +7 -0
  171. package/dist/cli/vocabulary/profiles.d.ts.map +1 -0
  172. package/dist/cli/vocabulary/profiles.js +171 -0
  173. package/dist/cli/vocabulary/profiles.js.map +1 -0
  174. package/dist/cli/vocabulary/similarity.d.ts +9 -0
  175. package/dist/cli/vocabulary/similarity.d.ts.map +1 -0
  176. package/dist/cli/vocabulary/similarity.js +199 -0
  177. package/dist/cli/vocabulary/similarity.js.map +1 -0
  178. package/dist/cli/vocabulary/status.d.ts +8 -0
  179. package/dist/cli/vocabulary/status.d.ts.map +1 -0
  180. package/dist/cli/vocabulary/status.js +280 -0
  181. package/dist/cli/vocabulary/status.js.map +1 -0
  182. package/dist/cli/vocabulary/sync.d.ts +7 -0
  183. package/dist/cli/vocabulary/sync.d.ts.map +1 -0
  184. package/dist/cli/vocabulary/sync.js +111 -0
  185. package/dist/cli/vocabulary/sync.js.map +1 -0
  186. package/dist/index.d.ts +9 -0
  187. package/dist/index.d.ts.map +1 -0
  188. package/dist/index.js +16 -0
  189. package/dist/index.js.map +1 -0
  190. package/dist/lib/auth/auth-client.d.ts +247 -0
  191. package/dist/lib/auth/auth-client.d.ts.map +1 -0
  192. package/dist/lib/auth/auth-client.js +305 -0
  193. package/dist/lib/auth/auth-client.js.map +1 -0
  194. package/dist/lib/auth/challenge.d.ts +39 -0
  195. package/dist/lib/auth/challenge.d.ts.map +1 -0
  196. package/dist/lib/auth/challenge.js +125 -0
  197. package/dist/lib/auth/challenge.js.map +1 -0
  198. package/dist/lib/auth/client-credentials-flow.d.ts +58 -0
  199. package/dist/lib/auth/client-credentials-flow.d.ts.map +1 -0
  200. package/dist/lib/auth/client-credentials-flow.js +118 -0
  201. package/dist/lib/auth/client-credentials-flow.js.map +1 -0
  202. package/dist/lib/auth/device-flow.d.ts +75 -0
  203. package/dist/lib/auth/device-flow.d.ts.map +1 -0
  204. package/dist/lib/auth/device-flow.js +177 -0
  205. package/dist/lib/auth/device-flow.js.map +1 -0
  206. package/dist/lib/auth/index.d.ts +14 -0
  207. package/dist/lib/auth/index.d.ts.map +1 -0
  208. package/dist/lib/auth/index.js +34 -0
  209. package/dist/lib/auth/index.js.map +1 -0
  210. package/dist/lib/auth/oauth-types.d.ts +69 -0
  211. package/dist/lib/auth/oauth-types.d.ts.map +1 -0
  212. package/dist/lib/auth/oauth-types.js +10 -0
  213. package/dist/lib/auth/oauth-types.js.map +1 -0
  214. package/dist/lib/auth/oauth-utils.d.ts +51 -0
  215. package/dist/lib/auth/oauth-utils.d.ts.map +1 -0
  216. package/dist/lib/auth/oauth-utils.js +110 -0
  217. package/dist/lib/auth/oauth-utils.js.map +1 -0
  218. package/dist/lib/auth/token-manager.d.ts +87 -0
  219. package/dist/lib/auth/token-manager.d.ts.map +1 -0
  220. package/dist/lib/auth/token-manager.js +139 -0
  221. package/dist/lib/auth/token-manager.js.map +1 -0
  222. package/dist/lib/auth/token-refresh.d.ts +63 -0
  223. package/dist/lib/auth/token-refresh.d.ts.map +1 -0
  224. package/dist/lib/auth/token-refresh.js +141 -0
  225. package/dist/lib/auth/token-refresh.js.map +1 -0
  226. package/dist/lib/config.d.ts +286 -0
  227. package/dist/lib/config.d.ts.map +1 -0
  228. package/dist/lib/config.js +537 -0
  229. package/dist/lib/config.js.map +1 -0
  230. package/dist/lib/job-stream.d.ts +53 -0
  231. package/dist/lib/job-stream.d.ts.map +1 -0
  232. package/dist/lib/job-stream.js +153 -0
  233. package/dist/lib/job-stream.js.map +1 -0
  234. package/dist/lib/mcp-allowlist.d.ts +101 -0
  235. package/dist/lib/mcp-allowlist.d.ts.map +1 -0
  236. package/dist/lib/mcp-allowlist.js +340 -0
  237. package/dist/lib/mcp-allowlist.js.map +1 -0
  238. package/dist/lib/table-example.d.ts +7 -0
  239. package/dist/lib/table-example.d.ts.map +1 -0
  240. package/dist/lib/table-example.js +105 -0
  241. package/dist/lib/table-example.js.map +1 -0
  242. package/dist/lib/table.d.ts +95 -0
  243. package/dist/lib/table.d.ts.map +1 -0
  244. package/dist/lib/table.js +263 -0
  245. package/dist/lib/table.js.map +1 -0
  246. package/dist/lib/terminal-images.d.ts +66 -0
  247. package/dist/lib/terminal-images.d.ts.map +1 -0
  248. package/dist/lib/terminal-images.js +268 -0
  249. package/dist/lib/terminal-images.js.map +1 -0
  250. package/dist/mcp/formatters.d.ts +100 -0
  251. package/dist/mcp/formatters.d.ts.map +1 -0
  252. package/dist/mcp/formatters.js +1411 -0
  253. package/dist/mcp/formatters.js.map +1 -0
  254. package/dist/mcp-server.d.ts +9 -0
  255. package/dist/mcp-server.d.ts.map +1 -0
  256. package/dist/mcp-server.js +1810 -0
  257. package/dist/mcp-server.js.map +1 -0
  258. package/dist/types/index.d.ts +742 -0
  259. package/dist/types/index.d.ts.map +1 -0
  260. package/dist/types/index.js +6 -0
  261. package/dist/types/index.js.map +1 -0
  262. package/dist/version.d.ts +10 -0
  263. package/dist/version.d.ts.map +1 -0
  264. package/dist/version.js +13 -0
  265. package/dist/version.js.map +1 -0
  266. package/package.json +84 -0
@@ -0,0 +1,694 @@
1
+ "use strict";
2
+ /**
3
+ * Configuration Commands
4
+ */
5
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
6
+ if (k2 === undefined) k2 = k;
7
+ var desc = Object.getOwnPropertyDescriptor(m, k);
8
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
9
+ desc = { enumerable: true, get: function() { return m[k]; } };
10
+ }
11
+ Object.defineProperty(o, k2, desc);
12
+ }) : (function(o, m, k, k2) {
13
+ if (k2 === undefined) k2 = k;
14
+ o[k2] = m[k];
15
+ }));
16
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
17
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
18
+ }) : function(o, v) {
19
+ o["default"] = v;
20
+ });
21
+ var __importStar = (this && this.__importStar) || (function () {
22
+ var ownKeys = function(o) {
23
+ ownKeys = Object.getOwnPropertyNames || function (o) {
24
+ var ar = [];
25
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
26
+ return ar;
27
+ };
28
+ return ownKeys(o);
29
+ };
30
+ return function (mod) {
31
+ if (mod && mod.__esModule) return mod;
32
+ var result = {};
33
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
34
+ __setModuleDefault(result, mod);
35
+ return result;
36
+ };
37
+ })();
38
+ var __importDefault = (this && this.__importDefault) || function (mod) {
39
+ return (mod && mod.__esModule) ? mod : { "default": mod };
40
+ };
41
+ Object.defineProperty(exports, "__esModule", { value: true });
42
+ exports.configCommand = void 0;
43
+ const commander_1 = require("commander");
44
+ const config_1 = require("../lib/config");
45
+ const readline = __importStar(require("readline"));
46
+ const colors = __importStar(require("./colors"));
47
+ const colors_1 = require("./colors");
48
+ const help_formatter_1 = require("./help-formatter");
49
+ const table_1 = require("../lib/table");
50
+ const axios_1 = __importDefault(require("axios"));
51
+ /**
52
+ * Test if a URL points to the API root (returns JSON with API info)
53
+ * Returns true if the URL returns valid API JSON response
54
+ */
55
+ async function testApiUrl(url) {
56
+ try {
57
+ const response = await axios_1.default.get(url, {
58
+ timeout: 5000,
59
+ validateStatus: () => true // Don't throw on any status
60
+ });
61
+ // Check if response is JSON and looks like our API
62
+ const contentType = response.headers['content-type'] || '';
63
+ if (!contentType.includes('application/json')) {
64
+ return false;
65
+ }
66
+ // Check for API signature fields
67
+ const data = response.data;
68
+ return data && (data.service || data.status === 'healthy' || data.endpoints);
69
+ }
70
+ catch {
71
+ return false;
72
+ }
73
+ }
74
+ /**
75
+ * Normalize API URL by testing if /api suffix is needed
76
+ *
77
+ * Many deployments mount the API at /api while serving the web UI at root.
78
+ * This function detects that pattern and returns the correct URL.
79
+ *
80
+ * @param url The URL to normalize
81
+ * @returns The normalized URL (possibly with /api appended)
82
+ */
83
+ async function normalizeApiUrl(url) {
84
+ // Remove trailing slash for consistency
85
+ url = url.replace(/\/+$/, '');
86
+ // If URL already ends with /api, test it directly
87
+ if (url.endsWith('/api')) {
88
+ const works = await testApiUrl(url);
89
+ if (works) {
90
+ return { url, wasNormalized: false };
91
+ }
92
+ return { url, wasNormalized: false, error: 'API not reachable at this URL' };
93
+ }
94
+ // Test the URL as-is first
95
+ if (await testApiUrl(url)) {
96
+ return { url, wasNormalized: false };
97
+ }
98
+ // Try with /api suffix
99
+ const apiUrl = `${url}/api`;
100
+ if (await testApiUrl(apiUrl)) {
101
+ return { url: apiUrl, wasNormalized: true };
102
+ }
103
+ // Neither worked - return original with warning
104
+ return { url, wasNormalized: false, error: 'API not reachable (tried both URL and URL/api)' };
105
+ }
106
+ /**
107
+ * Prompt for input from user
108
+ */
109
+ function prompt(question) {
110
+ const rl = readline.createInterface({
111
+ input: process.stdin,
112
+ output: process.stdout
113
+ });
114
+ return new Promise((resolve) => {
115
+ rl.question(question, (answer) => {
116
+ rl.close();
117
+ resolve(answer);
118
+ });
119
+ });
120
+ }
121
+ /**
122
+ * Prompt for password (hidden input)
123
+ */
124
+ function promptPassword(question) {
125
+ return new Promise((resolve) => {
126
+ const rl = readline.createInterface({
127
+ input: process.stdin,
128
+ output: process.stdout
129
+ });
130
+ // @ts-ignore - _writeToOutput exists but not in types
131
+ rl._writeToOutput = function (stringToWrite) {
132
+ if (stringToWrite.charCodeAt(0) === 13) { // carriage return
133
+ // @ts-ignore
134
+ rl.output.write('\n');
135
+ }
136
+ else {
137
+ // Don't display password characters
138
+ }
139
+ };
140
+ rl.question(question, (password) => {
141
+ rl.close();
142
+ console.log(); // New line after password input
143
+ resolve(password);
144
+ });
145
+ });
146
+ }
147
+ exports.configCommand = (0, help_formatter_1.setCommandHelp)(new commander_1.Command('config'), 'Manage CLI configuration', 'Manage kg CLI configuration settings. Controls API connection, authentication tokens, MCP tool preferences, and job auto-approval. Configuration stored in JSON file (typically ~/.kg/config.json).')
148
+ .alias('cfg') // Short alias
149
+ .showHelpAfterError('(add --help for additional information)')
150
+ .showSuggestionAfterError()
151
+ .addCommand(new commander_1.Command('get')
152
+ .description('Get one or all configuration values. Supports dot notation for nested keys (e.g., "mcp.enabled", "client.id").')
153
+ .argument('[key]', 'Configuration key (supports dot notation, e.g., "mcp.enabled"). Omit to show all configuration.')
154
+ .option('--json', 'Output as JSON')
155
+ .action(async (key, options) => {
156
+ try {
157
+ const config = (0, config_1.getConfig)();
158
+ if (!key) {
159
+ // Show all config
160
+ const allConfig = config.getAll();
161
+ if (options.json) {
162
+ console.log(JSON.stringify(allConfig, null, 2));
163
+ }
164
+ else {
165
+ console.log('\n' + (0, colors_1.separator)());
166
+ console.log(colors.ui.title('⚙️ Current Configuration'));
167
+ console.log((0, colors_1.separator)());
168
+ console.log('\n' + colors.ui.value(JSON.stringify(allConfig, null, 2)));
169
+ console.log('\n' + (0, colors_1.separator)());
170
+ }
171
+ }
172
+ else {
173
+ // Show specific key
174
+ const value = config.get(key);
175
+ if (value === undefined) {
176
+ console.error(colors.status.error(`✗ Configuration key '${key}' not found`));
177
+ process.exit(1);
178
+ }
179
+ if (options.json) {
180
+ console.log(JSON.stringify({ [key]: value }, null, 2));
181
+ }
182
+ else {
183
+ console.log(`\n${colors.ui.key(key + ':')} ${colors.ui.value(typeof value === 'object' ? JSON.stringify(value, null, 2) : value)}\n`);
184
+ }
185
+ }
186
+ }
187
+ catch (error) {
188
+ console.error(colors.status.error('✗ Failed to get config'));
189
+ console.error(colors.status.error(error.message));
190
+ process.exit(1);
191
+ }
192
+ }))
193
+ .addCommand(new commander_1.Command('set')
194
+ .description('Set a configuration value. Auto-detects data types (boolean, number, JSON). Use --string to force literal string interpretation.')
195
+ .argument('<key>', 'Configuration key (supports dot notation, e.g., "apiUrl", "mcp.enabled")')
196
+ .argument('<value>', 'Value to set (auto-detects JSON arrays/objects, booleans, numbers)')
197
+ .option('--json', 'Force parse value as JSON')
198
+ .option('--string', 'Force treat value as string (no JSON parsing)')
199
+ .option('--no-test', 'Skip API URL validation (for api_url only)')
200
+ .action(async (key, value, options) => {
201
+ try {
202
+ const config = (0, config_1.getConfig)();
203
+ let parsedValue = value;
204
+ // If --string flag, treat as literal string
205
+ if (options.string) {
206
+ parsedValue = value;
207
+ }
208
+ // If --json flag or value looks like JSON, try to parse
209
+ else if (options.json || value.startsWith('[') || value.startsWith('{')) {
210
+ try {
211
+ parsedValue = JSON.parse(value);
212
+ }
213
+ catch (e) {
214
+ if (options.json) {
215
+ // Only error if --json was explicitly requested
216
+ console.error(colors.status.error('✗ Invalid JSON value'));
217
+ process.exit(1);
218
+ }
219
+ // Otherwise treat as string
220
+ parsedValue = value;
221
+ }
222
+ }
223
+ // Auto-detect boolean and number values
224
+ else if (value === 'true' || value === 'false') {
225
+ parsedValue = value === 'true';
226
+ }
227
+ else if (!isNaN(Number(value)) && value.trim() !== '') {
228
+ parsedValue = Number(value);
229
+ }
230
+ // Special handling for api_url: test and normalize
231
+ if (key === 'api_url' && typeof parsedValue === 'string' && options.test !== false) {
232
+ console.log(colors.status.info(`Testing API URL: ${parsedValue}`));
233
+ const result = await normalizeApiUrl(parsedValue);
234
+ if (result.error) {
235
+ console.log(colors.status.warning(`⚠ ${result.error}`));
236
+ console.log(colors.status.dim('Saving URL anyway. Use --no-test to skip validation.'));
237
+ }
238
+ else if (result.wasNormalized) {
239
+ console.log(colors.status.success(`✓ Auto-detected API at ${result.url}`));
240
+ parsedValue = result.url;
241
+ }
242
+ else {
243
+ console.log(colors.status.success('✓ API reachable'));
244
+ }
245
+ }
246
+ config.set(key, parsedValue);
247
+ console.log(colors.status.success(`✓ Set ${colors.ui.key(key)} = ${colors.ui.value(typeof parsedValue === 'object' ? JSON.stringify(parsedValue) : parsedValue)}`));
248
+ }
249
+ catch (error) {
250
+ console.error(colors.status.error('✗ Failed to set config'));
251
+ console.error(colors.status.error(error.message));
252
+ process.exit(1);
253
+ }
254
+ }))
255
+ .addCommand(new commander_1.Command('delete')
256
+ .description('Delete configuration key')
257
+ .argument('<key>', 'Configuration key to delete')
258
+ .action(async (key) => {
259
+ try {
260
+ const config = (0, config_1.getConfig)();
261
+ config.delete(key);
262
+ console.log(colors.status.success(`✓ Deleted ${colors.ui.key(key)}`));
263
+ }
264
+ catch (error) {
265
+ console.error(colors.status.error('✗ Failed to delete config key'));
266
+ console.error(colors.status.error(error.message));
267
+ process.exit(1);
268
+ }
269
+ }))
270
+ .addCommand(new commander_1.Command('list')
271
+ .description('List all configuration')
272
+ .option('--json', 'Output as JSON')
273
+ .action(async (options) => {
274
+ try {
275
+ const config = (0, config_1.getConfig)();
276
+ const allConfig = config.getAll();
277
+ if (options.json) {
278
+ console.log(JSON.stringify(allConfig, null, 2));
279
+ return;
280
+ }
281
+ console.log('\n' + (0, colors_1.separator)());
282
+ console.log(colors.ui.title('⚙️ Configuration'));
283
+ console.log((0, colors_1.separator)());
284
+ // Build flat config rows for table display
285
+ const configRows = [];
286
+ // Authentication section
287
+ if (allConfig.username !== undefined) {
288
+ configRows.push({
289
+ key: 'username',
290
+ value: allConfig.username,
291
+ category: 'auth'
292
+ });
293
+ }
294
+ if (allConfig.secret !== undefined) {
295
+ configRows.push({
296
+ key: 'secret',
297
+ value: '***hidden***',
298
+ category: 'auth'
299
+ });
300
+ }
301
+ // Show OAuth credentials status
302
+ const oauthCreds = config.getOAuthCredentials();
303
+ if (oauthCreds) {
304
+ configRows.push({
305
+ key: 'auth.oauth_client_id',
306
+ value: oauthCreds.client_id,
307
+ category: 'auth'
308
+ });
309
+ configRows.push({
310
+ key: 'auth.oauth_client_name',
311
+ value: oauthCreds.client_name,
312
+ category: 'auth'
313
+ });
314
+ configRows.push({
315
+ key: 'auth.status',
316
+ value: '✓ authenticated',
317
+ category: 'auth'
318
+ });
319
+ }
320
+ else {
321
+ configRows.push({
322
+ key: 'auth.status',
323
+ value: '✗ not authenticated',
324
+ category: 'auth'
325
+ });
326
+ }
327
+ // Connection section
328
+ if (allConfig.api_url !== undefined) {
329
+ configRows.push({
330
+ key: 'api_url',
331
+ value: allConfig.api_url,
332
+ category: 'connection'
333
+ });
334
+ }
335
+ // Behavior section
336
+ if (allConfig.backup_dir !== undefined) {
337
+ configRows.push({
338
+ key: 'backup_dir',
339
+ value: allConfig.backup_dir,
340
+ category: 'behavior'
341
+ });
342
+ }
343
+ if (allConfig.auto_approve !== undefined) {
344
+ configRows.push({
345
+ key: 'auto_approve',
346
+ value: allConfig.auto_approve ? 'true' : 'false',
347
+ category: 'behavior'
348
+ });
349
+ }
350
+ // Display section (ADR-057) - show defaults even if not in config
351
+ configRows.push({
352
+ key: 'display.enableChafa',
353
+ value: config.isChafaEnabled() ? 'true' : 'false',
354
+ category: 'display'
355
+ });
356
+ configRows.push({
357
+ key: 'display.chafaScale',
358
+ value: config.getChafaScale().toString(),
359
+ category: 'display'
360
+ });
361
+ configRows.push({
362
+ key: 'display.chafaAlign',
363
+ value: config.getChafaAlign(),
364
+ category: 'display'
365
+ });
366
+ configRows.push({
367
+ key: 'display.chafaColors',
368
+ value: config.getChafaColors(),
369
+ category: 'display'
370
+ });
371
+ // Search section (ADR-057) - show defaults even if not in config
372
+ configRows.push({
373
+ key: 'search.showEvidence',
374
+ value: config.getSearchShowEvidence() ? 'true' : 'false',
375
+ category: 'search'
376
+ });
377
+ configRows.push({
378
+ key: 'search.showImages',
379
+ value: config.getSearchShowImages() ? 'true' : 'false',
380
+ category: 'search'
381
+ });
382
+ if (configRows.length === 0) {
383
+ console.log(colors.status.dim('\nNo configuration found\n'));
384
+ console.log(colors.status.dim(`Run: kg config init\n`));
385
+ return;
386
+ }
387
+ // Create table
388
+ const table = new table_1.Table({
389
+ columns: [
390
+ {
391
+ header: 'Key',
392
+ field: 'key',
393
+ type: 'heading',
394
+ width: 'flex',
395
+ priority: 2
396
+ },
397
+ {
398
+ header: 'Value',
399
+ field: 'value',
400
+ type: 'value',
401
+ width: 'flex',
402
+ priority: 3,
403
+ customFormat: (val, row) => {
404
+ // Special formatting based on key
405
+ if (row.key === 'secret')
406
+ return colors.status.dim(val);
407
+ if (row.key === 'auto_approve' && val === 'true')
408
+ return colors.status.warning(val);
409
+ if (row.key === 'auto_approve' && val === 'false')
410
+ return colors.status.dim(val);
411
+ if (row.key.startsWith('mcp.') && val.includes('true'))
412
+ return colors.status.success(val);
413
+ if (row.key.startsWith('mcp.') && val.includes('false'))
414
+ return colors.status.dim(val);
415
+ if (row.key === 'auth.status') {
416
+ if (val.includes('authenticated'))
417
+ return colors.status.success(val);
418
+ if (val.includes('not authenticated'))
419
+ return colors.status.warning(val);
420
+ }
421
+ // Display section (ADR-057)
422
+ if (row.key.startsWith('display.') && val === 'true')
423
+ return colors.status.success(val);
424
+ if (row.key.startsWith('display.') && val === 'false')
425
+ return colors.status.dim(val);
426
+ // Search section (ADR-057)
427
+ if (row.key.startsWith('search.') && val === 'true')
428
+ return colors.status.success(val);
429
+ if (row.key.startsWith('search.') && val === 'false')
430
+ return colors.status.dim(val);
431
+ return val;
432
+ }
433
+ },
434
+ {
435
+ header: 'Category',
436
+ field: 'category',
437
+ type: 'text',
438
+ width: 'auto',
439
+ customFormat: (type) => {
440
+ switch (type) {
441
+ case 'auth': return colors.ui.value('auth');
442
+ case 'connection': return colors.ui.value('connection');
443
+ case 'behavior': return colors.ui.value('behavior');
444
+ case 'display': return colors.ui.value('display');
445
+ case 'search': return colors.ui.value('search');
446
+ default: return type;
447
+ }
448
+ }
449
+ }
450
+ ],
451
+ spacing: 2,
452
+ showHeader: true,
453
+ showSeparator: true
454
+ });
455
+ table.print(configRows);
456
+ // Helpful footer
457
+ console.log(colors.status.dim(`Config file: ${config.getConfigPath()}`));
458
+ console.log(colors.status.dim(`Usage: kg config set <key> <value>\n`));
459
+ }
460
+ catch (error) {
461
+ console.error(colors.status.error('✗ Failed to list config'));
462
+ console.error(colors.status.error(error.message));
463
+ process.exit(1);
464
+ }
465
+ }))
466
+ .addCommand(new commander_1.Command('path')
467
+ .description('Show configuration file path')
468
+ .action(() => {
469
+ const config = (0, config_1.getConfig)();
470
+ console.log('\n' + colors.ui.key('Config file:') + ' ' + colors.ui.value(config.getConfigPath()));
471
+ console.log(colors.status.dim(`(Directory: ${config.getConfigDir()})\n`));
472
+ }))
473
+ .addCommand(new commander_1.Command('init')
474
+ .description('Initialize configuration file with defaults')
475
+ .option('-f, --force', 'Overwrite existing configuration')
476
+ .action(async (options) => {
477
+ try {
478
+ const config = (0, config_1.getConfig)();
479
+ if (config.exists() && !options.force) {
480
+ console.log(colors.status.warning('\n⚠ Configuration file already exists'));
481
+ console.log(colors.status.dim(`Use --force to overwrite: ${config.getConfigPath()}\n`));
482
+ return;
483
+ }
484
+ config.init();
485
+ console.log(colors.status.success('✓ Configuration initialized'));
486
+ console.log(colors.status.dim(`Location: ${config.getConfigPath()}\n`));
487
+ }
488
+ catch (error) {
489
+ console.error(colors.status.error('✗ Failed to initialize config'));
490
+ console.error(colors.status.error(error.message));
491
+ process.exit(1);
492
+ }
493
+ }))
494
+ .addCommand(new commander_1.Command('reset')
495
+ .description('Reset configuration to defaults')
496
+ .option('-y, --yes', 'Skip confirmation')
497
+ .action(async (options) => {
498
+ try {
499
+ const config = (0, config_1.getConfig)();
500
+ if (!options.yes) {
501
+ const answer = await prompt(colors.status.warning('⚠️ This will reset all configuration to defaults. Continue? (y/N) '));
502
+ if (answer.toLowerCase() !== 'y') {
503
+ console.log(colors.status.dim('Cancelled\n'));
504
+ return;
505
+ }
506
+ }
507
+ config.reset();
508
+ console.log(colors.status.success('✓ Configuration reset to defaults'));
509
+ console.log(colors.status.dim(`Location: ${config.getConfigPath()}\n`));
510
+ }
511
+ catch (error) {
512
+ console.error(colors.status.error('✗ Failed to reset config'));
513
+ console.error(colors.status.error(error.message));
514
+ process.exit(1);
515
+ }
516
+ }))
517
+ .addCommand(new commander_1.Command('auto-approve')
518
+ .description('Enable or disable automatic approval of ingestion jobs. When enabled, jobs skip the cost estimate review step and start processing immediately (ADR-014).')
519
+ .argument('[value]', 'Enable (true/on/yes) or disable (false/off/no). Omit to show current status.', 'status')
520
+ .action(async (value) => {
521
+ try {
522
+ const config = (0, config_1.getConfig)();
523
+ // If no value, show current status
524
+ if (value === 'status') {
525
+ const current = config.getAutoApprove();
526
+ console.log('\n' + (0, colors_1.separator)());
527
+ console.log(colors.ui.title('🔄 Auto-Approve Configuration'));
528
+ console.log((0, colors_1.separator)());
529
+ const statusText = current ? colors.status.success('✓ enabled') : colors.status.dim('✗ disabled');
530
+ console.log(`\n${colors.ui.key('Status:')} ${statusText}`);
531
+ console.log(colors.status.dim('\nWhen enabled, all jobs are automatically approved without manual review'));
532
+ console.log(colors.status.dim('Override: Use --yes flag on individual ingest commands\n'));
533
+ console.log((0, colors_1.separator)());
534
+ return;
535
+ }
536
+ // Parse boolean value
537
+ const enableValues = ['true', 'on', 'yes', 'enable', 'enabled', '1'];
538
+ const disableValues = ['false', 'off', 'no', 'disable', 'disabled', '0'];
539
+ let newValue;
540
+ if (enableValues.includes(value.toLowerCase())) {
541
+ newValue = true;
542
+ }
543
+ else if (disableValues.includes(value.toLowerCase())) {
544
+ newValue = false;
545
+ }
546
+ else {
547
+ console.error(colors.status.error(`✗ Invalid value: ${value}`));
548
+ console.log(colors.status.dim('Use: true/false, on/off, yes/no, enable/disable'));
549
+ process.exit(1);
550
+ }
551
+ config.setAutoApprove(newValue);
552
+ const statusText = newValue ? colors.status.success('enabled') : colors.status.dim('disabled');
553
+ console.log(colors.status.success(`✓ Auto-approve ${statusText}`));
554
+ if (newValue) {
555
+ console.log(colors.status.warning('\n⚠️ All jobs will now be automatically approved'));
556
+ console.log(colors.status.dim('Jobs will skip the analysis review step and start processing immediately\n'));
557
+ }
558
+ }
559
+ catch (error) {
560
+ console.error(colors.status.error('✗ Failed to configure auto-approve'));
561
+ console.error(colors.status.error(error.message));
562
+ process.exit(1);
563
+ }
564
+ }))
565
+ .addCommand(new commander_1.Command('update-secret')
566
+ .description('Authenticate with username/password and update the stored API secret or key. Password is never stored; only the resulting authentication token is persisted.')
567
+ .option('-u, --username <username>', 'Username (will prompt if not provided)')
568
+ .action(async (options) => {
569
+ try {
570
+ const config = (0, config_1.getConfig)();
571
+ // Get username
572
+ let username = options.username || config.get('username');
573
+ if (!username) {
574
+ username = await prompt('Username: ');
575
+ }
576
+ // Get password (never stored)
577
+ const password = await promptPassword('Password: ');
578
+ if (!password) {
579
+ console.error(colors.status.error('✗ Password is required'));
580
+ process.exit(1);
581
+ }
582
+ console.log(colors.status.info('\nAuthenticating...'));
583
+ // TODO: Call API endpoint to authenticate and get new secret
584
+ // For now, this is a placeholder
585
+ console.log('\n' + (0, colors_1.separator)());
586
+ console.log(colors.status.warning('⚠️ API authentication endpoint not yet implemented'));
587
+ console.log((0, colors_1.separator)());
588
+ console.log(colors.status.dim('\nThis feature will be available in a future update'));
589
+ console.log(colors.status.dim('\nExpected flow:'));
590
+ console.log(colors.status.dim('1. POST /auth/login with username + password'));
591
+ console.log(colors.status.dim('2. Server validates credentials'));
592
+ console.log(colors.status.dim('3. Server generates salted API key'));
593
+ console.log(colors.status.dim('4. Key is stored in config (password is never stored)\n'));
594
+ // When implemented:
595
+ // const client = createClientFromEnv();
596
+ // const response = await client.authenticate(username, password);
597
+ // config.set('username', username);
598
+ // config.set('secret', response.api_key);
599
+ // console.log(colors.status.success('✓ API secret updated successfully'));
600
+ }
601
+ catch (error) {
602
+ console.error(colors.status.error('✗ Authentication failed'));
603
+ console.error(colors.status.error(error.response?.data?.detail || error.message));
604
+ process.exit(1);
605
+ }
606
+ }))
607
+ .addCommand(new commander_1.Command('json')
608
+ .description('JSON-based configuration operations (machine-friendly)')
609
+ .addCommand(new commander_1.Command('get')
610
+ .description('Get entire configuration as JSON')
611
+ .action(() => {
612
+ const config = (0, config_1.getConfig)();
613
+ const allConfig = config.getAll();
614
+ console.log(JSON.stringify(allConfig, null, 2));
615
+ }))
616
+ .addCommand(new commander_1.Command('set')
617
+ .description('Set configuration from JSON (full or partial)')
618
+ .argument('<json>', 'JSON string or path to JSON file')
619
+ .action(async (jsonInput) => {
620
+ try {
621
+ const config = (0, config_1.getConfig)();
622
+ let parsedConfig;
623
+ // Check if input is a file path
624
+ if (jsonInput.endsWith('.json')) {
625
+ const fs = require('fs');
626
+ if (fs.existsSync(jsonInput)) {
627
+ const fileContent = fs.readFileSync(jsonInput, 'utf-8');
628
+ parsedConfig = JSON.parse(fileContent);
629
+ }
630
+ else {
631
+ // Not a file, try to parse as JSON string
632
+ parsedConfig = JSON.parse(jsonInput);
633
+ }
634
+ }
635
+ else {
636
+ // Parse as JSON string
637
+ parsedConfig = JSON.parse(jsonInput);
638
+ }
639
+ // Apply each key-value pair
640
+ const keys = Object.keys(parsedConfig);
641
+ for (const key of keys) {
642
+ config.set(key, parsedConfig[key]);
643
+ }
644
+ console.log(colors.status.success(`✓ Set ${keys.length} configuration value(s)`));
645
+ }
646
+ catch (error) {
647
+ console.error(colors.status.error('✗ Failed to set config from JSON'));
648
+ if (error instanceof SyntaxError) {
649
+ console.error(colors.status.error('Invalid JSON syntax'));
650
+ }
651
+ else {
652
+ console.error(colors.status.error(error.message));
653
+ }
654
+ process.exit(1);
655
+ }
656
+ }))
657
+ .addCommand(new commander_1.Command('dto')
658
+ .description('Output configuration template/schema')
659
+ .action(() => {
660
+ const template = {
661
+ username: "your-username",
662
+ secret: "your-api-key",
663
+ api_url: "http://localhost:8000",
664
+ backup_dir: "~/.local/share/kg/backups",
665
+ auto_approve: false,
666
+ mcp: {
667
+ enabled: true,
668
+ tools: {
669
+ search_concepts: { enabled: true, description: "Search for concepts using natural language" },
670
+ get_concept_details: { enabled: true, description: "Get detailed information about a concept" },
671
+ find_related_concepts: { enabled: true, description: "Find concepts related through graph traversal" },
672
+ find_connection: { enabled: true, description: "Find shortest path between concepts" },
673
+ ingest_document: { enabled: true, description: "Ingest a document into the knowledge graph" },
674
+ list_ontologies: { enabled: true, description: "List all ontologies" },
675
+ get_database_stats: { enabled: true, description: "Get database statistics" }
676
+ }
677
+ },
678
+ auth: {
679
+ token: "your-jwt-token",
680
+ token_type: "bearer",
681
+ expires_at: 0,
682
+ username: "your-username",
683
+ role: "your-role"
684
+ }
685
+ };
686
+ console.log(colors.status.dim('# kg Configuration Template (DTO)\n'));
687
+ console.log(JSON.stringify(template, null, 2));
688
+ console.log(colors.status.dim('\n# Usage:'));
689
+ console.log(colors.status.dim('# kg config json set \'{"username": "alice", "auto_approve": true}\''));
690
+ console.log(colors.status.dim('# kg config json set config.json'));
691
+ })));
692
+ // Configure colored help for all config subcommands
693
+ exports.configCommand.commands.forEach(help_formatter_1.configureColoredHelp);
694
+ //# sourceMappingURL=config.js.map