@linkup-ai/abap-ai 2.0.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 (114) hide show
  1. package/README.md +384 -0
  2. package/dist/adt-client.js +364 -0
  3. package/dist/cli/activate.js +113 -0
  4. package/dist/cli/init.js +333 -0
  5. package/dist/cli/remove.js +80 -0
  6. package/dist/cli/status.js +229 -0
  7. package/dist/cli/systems.js +68 -0
  8. package/dist/cli.js +81 -0
  9. package/dist/index.js +1318 -0
  10. package/dist/knowledge/abap/abap-dictionary.md +199 -0
  11. package/dist/knowledge/abap/abap-sql.md +296 -0
  12. package/dist/knowledge/abap/amdp.md +273 -0
  13. package/dist/knowledge/abap/clean-code.md +293 -0
  14. package/dist/knowledge/abap/cloud-background-processing.md +250 -0
  15. package/dist/knowledge/abap/cloud-communication.md +265 -0
  16. package/dist/knowledge/abap/cloud-development.md +176 -0
  17. package/dist/knowledge/abap/cloud-extensibility.md +252 -0
  18. package/dist/knowledge/abap/cloud-released-apis.md +261 -0
  19. package/dist/knowledge/abap/constructor-expressions.md +289 -0
  20. package/dist/knowledge/abap/enhancements.md +232 -0
  21. package/dist/knowledge/abap/exceptions.md +271 -0
  22. package/dist/knowledge/abap/internal-tables.md +205 -0
  23. package/dist/knowledge/abap/object-orientation.md +298 -0
  24. package/dist/knowledge/abap/performance.md +216 -0
  25. package/dist/knowledge/abap/rap-abstract-entities.md +206 -0
  26. package/dist/knowledge/abap/rap-business-events.md +216 -0
  27. package/dist/knowledge/abap/rap-draft.md +191 -0
  28. package/dist/knowledge/abap/rap-eml.md +453 -0
  29. package/dist/knowledge/abap/rap-end-to-end.md +486 -0
  30. package/dist/knowledge/abap/rap-feature-control.md +185 -0
  31. package/dist/knowledge/abap/rap-numbering.md +280 -0
  32. package/dist/knowledge/abap/rap-service-exposure.md +163 -0
  33. package/dist/knowledge/abap/rap-unmanaged.md +468 -0
  34. package/dist/knowledge/abap/string-processing.md +180 -0
  35. package/dist/knowledge/abap/unit-testing.md +303 -0
  36. package/dist/knowledge/abap-cds/access-control.md +241 -0
  37. package/dist/knowledge/abap-cds/annotations.md +331 -0
  38. package/dist/knowledge/abap-cds/associations.md +254 -0
  39. package/dist/knowledge/abap-cds/expressions.md +230 -0
  40. package/dist/knowledge/abap-cds/functions.md +245 -0
  41. package/dist/knowledge/abap-cds/metadata-extensions.md +294 -0
  42. package/dist/knowledge/cap/authentication.md +278 -0
  43. package/dist/knowledge/cap/cdl-syntax.md +247 -0
  44. package/dist/knowledge/cap/cql-queries.md +266 -0
  45. package/dist/knowledge/cap/deployment.md +343 -0
  46. package/dist/knowledge/cap/event-handlers.md +287 -0
  47. package/dist/knowledge/cap/fiori-integration.md +303 -0
  48. package/dist/knowledge/cap/service-definitions.md +287 -0
  49. package/dist/knowledge/fiori/annotations.md +347 -0
  50. package/dist/knowledge/fiori/deployment.md +340 -0
  51. package/dist/knowledge/fiori/fiori-elements.md +332 -0
  52. package/dist/knowledge/fiori/fiori-side-effects.md +107 -0
  53. package/dist/knowledge/fiori/fiori-valuelist.md +144 -0
  54. package/dist/knowledge/fiori/ui5-controllers.md +358 -0
  55. package/dist/knowledge/fiori/ui5-data-binding.md +311 -0
  56. package/dist/knowledge/fiori/ui5-fragments-dialogs.md +330 -0
  57. package/dist/knowledge/fiori/ui5-manifest.md +411 -0
  58. package/dist/knowledge/fiori/ui5-routing.md +303 -0
  59. package/dist/knowledge/fiori/ui5-xml-views.md +294 -0
  60. package/dist/logger.js +114 -0
  61. package/dist/system-profile.js +207 -0
  62. package/dist/tools/abap-doc.js +72 -0
  63. package/dist/tools/abapgit.js +161 -0
  64. package/dist/tools/activate.js +68 -0
  65. package/dist/tools/atc-check.js +117 -0
  66. package/dist/tools/auth-object.js +56 -0
  67. package/dist/tools/breakpoints.js +76 -0
  68. package/dist/tools/call-hierarchy.js +84 -0
  69. package/dist/tools/cds-annotations.js +98 -0
  70. package/dist/tools/cds-dependencies.js +65 -0
  71. package/dist/tools/check.js +47 -0
  72. package/dist/tools/code-completion.js +70 -0
  73. package/dist/tools/code-coverage.js +111 -0
  74. package/dist/tools/create-amdp.js +111 -0
  75. package/dist/tools/create-dcl.js +81 -0
  76. package/dist/tools/create-transport.js +38 -0
  77. package/dist/tools/create.js +285 -0
  78. package/dist/tools/data-preview.js +37 -0
  79. package/dist/tools/delete.js +45 -0
  80. package/dist/tools/deploy-bsp.js +298 -0
  81. package/dist/tools/discovery.js +59 -0
  82. package/dist/tools/element-info.js +93 -0
  83. package/dist/tools/enhancements.js +186 -0
  84. package/dist/tools/extract-method.js +44 -0
  85. package/dist/tools/function-group.js +59 -0
  86. package/dist/tools/knowledge.js +275 -0
  87. package/dist/tools/lock-object.js +75 -0
  88. package/dist/tools/message-class.js +67 -0
  89. package/dist/tools/navigate.js +80 -0
  90. package/dist/tools/number-range.js +57 -0
  91. package/dist/tools/object-documentation.js +43 -0
  92. package/dist/tools/object-structure.js +78 -0
  93. package/dist/tools/object-versions.js +57 -0
  94. package/dist/tools/package-contents.js +60 -0
  95. package/dist/tools/pretty-printer.js +35 -0
  96. package/dist/tools/publish-binding.js +49 -0
  97. package/dist/tools/quick-fix.js +69 -0
  98. package/dist/tools/read.js +167 -0
  99. package/dist/tools/refactor-rename.js +60 -0
  100. package/dist/tools/release-transport.js +24 -0
  101. package/dist/tools/released-apis.js +51 -0
  102. package/dist/tools/repository-tree.js +90 -0
  103. package/dist/tools/scaffold-rap.js +642 -0
  104. package/dist/tools/search.js +73 -0
  105. package/dist/tools/shared/data-format.js +101 -0
  106. package/dist/tools/sql-console.js +17 -0
  107. package/dist/tools/system-info.js +270 -0
  108. package/dist/tools/traces.js +66 -0
  109. package/dist/tools/transport-contents.js +83 -0
  110. package/dist/tools/transports.js +67 -0
  111. package/dist/tools/unit-test.js +135 -0
  112. package/dist/tools/where-used.js +59 -0
  113. package/dist/tools/write.js +101 -0
  114. package/package.json +49 -0
@@ -0,0 +1,333 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.init = init;
40
+ const prompts_1 = __importDefault(require("prompts"));
41
+ const fs = __importStar(require("fs"));
42
+ const path = __importStar(require("path"));
43
+ const https = __importStar(require("https"));
44
+ const http = __importStar(require("http"));
45
+ const MCP_JSON_PATH = path.join(process.env.HOME || "~", ".claude", "mcp.json");
46
+ // ---------------------------------------------------------------------------
47
+ // Teste de conexão SAP
48
+ // ---------------------------------------------------------------------------
49
+ async function testConnection(system) {
50
+ const url = new URL(`${system.url}/sap/bc/adt/discovery`);
51
+ const options = {
52
+ hostname: url.hostname,
53
+ port: url.port || (url.protocol === "https:" ? 443 : 80),
54
+ path: url.pathname,
55
+ method: "GET",
56
+ headers: {
57
+ Authorization: "Basic " + Buffer.from(`${system.user}:${system.pass}`).toString("base64"),
58
+ "sap-client": system.client,
59
+ "sap-language": system.language,
60
+ Accept: "application/atomsvc+xml",
61
+ },
62
+ rejectAuthorized: !system.selfSignedSsl,
63
+ timeout: 10000,
64
+ };
65
+ // workaround: rejectUnauthorized
66
+ if (system.selfSignedSsl) {
67
+ options.rejectUnauthorized = false;
68
+ }
69
+ return new Promise((resolve) => {
70
+ const transport = url.protocol === "https:" ? https : http;
71
+ const req = transport.request(options, (res) => {
72
+ let body = "";
73
+ res.on("data", (chunk) => (body += chunk));
74
+ res.on("end", () => {
75
+ if (res.statusCode === 200) {
76
+ // Contar APIs
77
+ const apiCount = (body.match(/<(?:app:)?collection/gi) || []).length;
78
+ // Tentar extrair versão
79
+ const versionMatch = body.match(/SAP_BASIS\s+(\d+)/i) || body.match(/release="(\d+)"/i);
80
+ const version = versionMatch ? `BASIS ${versionMatch[1]}` : "";
81
+ resolve({ ok: true, info: `${apiCount} APIs ADT disponíveis${version ? ` | ${version}` : ""}` });
82
+ }
83
+ else if (res.statusCode === 401) {
84
+ resolve({ ok: false, info: "Credenciais inválidas (401)" });
85
+ }
86
+ else if (res.statusCode === 403) {
87
+ resolve({ ok: false, info: "Sem autorização para ADT (403). Verifique perfil S_ADT_RES." });
88
+ }
89
+ else {
90
+ resolve({ ok: false, info: `HTTP ${res.statusCode}: ${res.statusMessage}` });
91
+ }
92
+ });
93
+ });
94
+ req.on("error", (err) => {
95
+ if (err.code === "ECONNREFUSED") {
96
+ resolve({ ok: false, info: "Conexão recusada. Verifique URL e porta." });
97
+ }
98
+ else if (err.code === "ETIMEDOUT" || err.code === "ESOCKETTIMEDOUT") {
99
+ resolve({ ok: false, info: "Timeout. Verifique VPN e firewall." });
100
+ }
101
+ else if (err.message.includes("certificate") || err.message.includes("SSL")) {
102
+ resolve({ ok: false, info: "Erro SSL. Marque 'Sim' para certificado self-signed." });
103
+ }
104
+ else {
105
+ resolve({ ok: false, info: err.message });
106
+ }
107
+ });
108
+ req.on("timeout", () => {
109
+ req.destroy();
110
+ resolve({ ok: false, info: "Timeout (10s). Verifique VPN e firewall." });
111
+ });
112
+ req.end();
113
+ });
114
+ }
115
+ // ---------------------------------------------------------------------------
116
+ // mcp.json management
117
+ // ---------------------------------------------------------------------------
118
+ function readMcpConfig() {
119
+ try {
120
+ const raw = fs.readFileSync(MCP_JSON_PATH, "utf-8");
121
+ return JSON.parse(raw);
122
+ }
123
+ catch {
124
+ return { mcpServers: {} };
125
+ }
126
+ }
127
+ function writeMcpConfig(config) {
128
+ const dir = path.dirname(MCP_JSON_PATH);
129
+ if (!fs.existsSync(dir)) {
130
+ fs.mkdirSync(dir, { recursive: true });
131
+ }
132
+ fs.writeFileSync(MCP_JSON_PATH, JSON.stringify(config, null, 2) + "\n", "utf-8");
133
+ }
134
+ function detectServerPath() {
135
+ // Tentar encontrar o index.js relativo ao CLI
136
+ const fromCli = path.resolve(__dirname, "..", "index.js");
137
+ if (fs.existsSync(fromCli))
138
+ return fromCli;
139
+ // Fallback: path global do pacote
140
+ const globalPath = path.resolve(__dirname, "..", "index.js");
141
+ return globalPath;
142
+ }
143
+ function addSystemToConfig(config, system) {
144
+ const serverName = `abap-${system.name}`;
145
+ const serverPath = detectServerPath();
146
+ const env = {
147
+ SAP_URL: system.url,
148
+ SAP_CLIENT: system.client,
149
+ SAP_USER: system.user,
150
+ SAP_PASS: system.pass,
151
+ SAP_LANGUAGE: system.language,
152
+ };
153
+ if (system.selfSignedSsl) {
154
+ env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
155
+ }
156
+ config.mcpServers[serverName] = {
157
+ command: "node",
158
+ args: [serverPath],
159
+ env,
160
+ };
161
+ }
162
+ // ---------------------------------------------------------------------------
163
+ // Wizard
164
+ // ---------------------------------------------------------------------------
165
+ async function promptSystem() {
166
+ const response = await (0, prompts_1.default)([
167
+ {
168
+ type: "text",
169
+ name: "name",
170
+ message: "Nome deste sistema (identificador curto)",
171
+ validate: (v) => v.trim().length > 0 ? true : "Informe um nome (ex: novaforma-dev)",
172
+ },
173
+ {
174
+ type: "text",
175
+ name: "url",
176
+ message: "URL do SAP (com porta)",
177
+ validate: (v) => {
178
+ try {
179
+ new URL(v);
180
+ return true;
181
+ }
182
+ catch {
183
+ return "URL inválida (ex: https://sap-host:8443)";
184
+ }
185
+ },
186
+ },
187
+ {
188
+ type: "text",
189
+ name: "client",
190
+ message: "Client (mandant)",
191
+ initial: "100",
192
+ },
193
+ {
194
+ type: "text",
195
+ name: "user",
196
+ message: "Usuário SAP",
197
+ validate: (v) => v.trim().length > 0 ? true : "Informe o usuário",
198
+ },
199
+ {
200
+ type: "password",
201
+ name: "pass",
202
+ message: "Senha SAP",
203
+ validate: (v) => v.length > 0 ? true : "Informe a senha",
204
+ },
205
+ {
206
+ type: "text",
207
+ name: "language",
208
+ message: "Idioma (EN, PT, DE...)",
209
+ initial: "PT",
210
+ },
211
+ {
212
+ type: "confirm",
213
+ name: "selfSignedSsl",
214
+ message: "Certificado SSL self-signed?",
215
+ initial: true,
216
+ },
217
+ ], {
218
+ onCancel: () => {
219
+ console.log("\n Cancelado.");
220
+ process.exit(0);
221
+ },
222
+ });
223
+ if (!response.name || !response.url || !response.user || !response.pass) {
224
+ return null;
225
+ }
226
+ return {
227
+ name: response.name.trim().toLowerCase().replace(/\s+/g, "-"),
228
+ url: response.url.trim().replace(/\/+$/, ""),
229
+ client: response.client?.trim() || "100",
230
+ user: response.user.trim().toUpperCase(),
231
+ pass: response.pass,
232
+ language: (response.language?.trim() || "PT").toUpperCase(),
233
+ selfSignedSsl: response.selfSignedSsl ?? true,
234
+ };
235
+ }
236
+ // ---------------------------------------------------------------------------
237
+ // Main
238
+ // ---------------------------------------------------------------------------
239
+ async function init() {
240
+ console.log(`
241
+ ╭─────────────────────────────────────╮
242
+ │ LKPABAP.ia — Setup │
243
+ │ Conecte o Claude ao seu SAP │
244
+ ╰─────────────────────────────────────╯
245
+ `);
246
+ const config = readMcpConfig();
247
+ const existingCount = Object.keys(config.mcpServers).filter((k) => k.startsWith("abap-")).length;
248
+ if (existingCount > 0) {
249
+ console.log(` ${existingCount} sistema(s) SAP já configurado(s).\n`);
250
+ }
251
+ const addedSystems = [];
252
+ let addMore = true;
253
+ while (addMore) {
254
+ const system = await promptSystem();
255
+ if (!system)
256
+ break;
257
+ const serverName = `abap-${system.name}`;
258
+ // Verificar duplicata
259
+ if (config.mcpServers[serverName]) {
260
+ const { overwrite } = await (0, prompts_1.default)({
261
+ type: "confirm",
262
+ name: "overwrite",
263
+ message: `Sistema "${serverName}" já existe. Sobrescrever?`,
264
+ initial: false,
265
+ });
266
+ if (!overwrite)
267
+ continue;
268
+ }
269
+ // Testar conexão
270
+ console.log("\n ⏳ Testando conexão com SAP...");
271
+ const result = await testConnection(system);
272
+ if (result.ok) {
273
+ console.log(` ✓ Conectado! ${result.info}\n`);
274
+ addSystemToConfig(config, system);
275
+ addedSystems.push(system.name);
276
+ }
277
+ else {
278
+ console.log(` ✗ Falha: ${result.info}\n`);
279
+ const { retry } = await (0, prompts_1.default)({
280
+ type: "select",
281
+ name: "retry",
282
+ message: "O que deseja fazer?",
283
+ choices: [
284
+ { title: "Tentar novamente com outros dados", value: "retry" },
285
+ { title: "Adicionar mesmo assim (sem validar)", value: "force" },
286
+ { title: "Pular este sistema", value: "skip" },
287
+ ],
288
+ });
289
+ if (retry === "force") {
290
+ addSystemToConfig(config, system);
291
+ addedSystems.push(system.name);
292
+ console.log(` ⚠️ Sistema adicionado sem validação.\n`);
293
+ }
294
+ else if (retry === "retry") {
295
+ continue;
296
+ }
297
+ else {
298
+ // skip
299
+ }
300
+ }
301
+ const { more } = await (0, prompts_1.default)({
302
+ type: "confirm",
303
+ name: "more",
304
+ message: "Deseja adicionar outro sistema?",
305
+ initial: false,
306
+ });
307
+ addMore = more;
308
+ }
309
+ if (addedSystems.length > 0) {
310
+ writeMcpConfig(config);
311
+ const total = Object.keys(config.mcpServers).filter((k) => k.startsWith("abap-")).length;
312
+ console.log(`
313
+ ✓ Configuração salva em ${MCP_JSON_PATH}
314
+
315
+ ╭──────────────────────────────────────────────╮
316
+ │ ${total} sistema(s) configurado(s):${" ".repeat(Math.max(0, 23 - total.toString().length))}│`);
317
+ for (const name of addedSystems) {
318
+ const sn = `abap-${name}`;
319
+ const env = config.mcpServers[sn]?.env || {};
320
+ const client = env.SAP_CLIENT || "?";
321
+ const line = ` │ • ${name} (client ${client})`;
322
+ console.log(`${line}${" ".repeat(Math.max(1, 48 - line.length))}│`);
323
+ }
324
+ console.log(` │${" ".repeat(46)}│
325
+ │ Próximo passo:${" ".repeat(29)}│
326
+ │ Abra o VS Code / Claude Code e use!${" ".repeat(6)}│
327
+ ╰──────────────────────────────────────────────╯
328
+ `);
329
+ }
330
+ else {
331
+ console.log("\n Nenhum sistema adicionado.\n");
332
+ }
333
+ }
@@ -0,0 +1,80 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.remove = remove;
40
+ const prompts_1 = __importDefault(require("prompts"));
41
+ const fs = __importStar(require("fs"));
42
+ const path = __importStar(require("path"));
43
+ const MCP_JSON_PATH = path.join(process.env.HOME || "~", ".claude", "mcp.json");
44
+ async function remove(name) {
45
+ const serverName = name.startsWith("abap-") ? name : `abap-${name}`;
46
+ let config;
47
+ try {
48
+ const raw = fs.readFileSync(MCP_JSON_PATH, "utf-8");
49
+ config = JSON.parse(raw);
50
+ }
51
+ catch {
52
+ console.error(` ✗ Arquivo ${MCP_JSON_PATH} não encontrado.`);
53
+ process.exit(1);
54
+ return;
55
+ }
56
+ if (!config.mcpServers[serverName]) {
57
+ console.error(` ✗ Sistema "${serverName}" não encontrado no mcp.json.`);
58
+ const available = Object.keys(config.mcpServers).filter((k) => k.startsWith("abap-"));
59
+ if (available.length > 0) {
60
+ console.log(` Sistemas disponíveis: ${available.join(", ")}`);
61
+ }
62
+ process.exit(1);
63
+ return;
64
+ }
65
+ const { confirm } = await (0, prompts_1.default)({
66
+ type: "confirm",
67
+ name: "confirm",
68
+ message: `Confirma remoção do sistema "${serverName}"?`,
69
+ initial: false,
70
+ });
71
+ if (!confirm) {
72
+ console.log(" Cancelado.\n");
73
+ return;
74
+ }
75
+ delete config.mcpServers[serverName];
76
+ fs.writeFileSync(MCP_JSON_PATH, JSON.stringify(config, null, 2) + "\n", "utf-8");
77
+ const remaining = Object.keys(config.mcpServers).filter((k) => k.startsWith("abap-")).length;
78
+ console.log(`\n ✓ Sistema "${serverName}" removido de ${MCP_JSON_PATH}`);
79
+ console.log(` ${remaining} sistema(s) restante(s).\n`);
80
+ }
@@ -0,0 +1,229 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.status = status;
37
+ const fs = __importStar(require("fs"));
38
+ const path = __importStar(require("path"));
39
+ const https = __importStar(require("https"));
40
+ const http = __importStar(require("http"));
41
+ const activate_js_1 = require("./activate.js");
42
+ const MCP_JSON_PATH = path.join(process.env.HOME || "~", ".claude", "mcp.json");
43
+ const LOG_DIR = path.join(process.env.HOME || "~", ".abap-ai", "logs");
44
+ const VERSION = "2.0.0";
45
+ // ---------------------------------------------------------------------------
46
+ // Teste rápido de conexão (timeout 5s)
47
+ // ---------------------------------------------------------------------------
48
+ async function quickTest(url, user, pass, client, selfSigned) {
49
+ const parsed = new URL(`${url}/sap/bc/adt/discovery`);
50
+ return new Promise((resolve) => {
51
+ const transport = parsed.protocol === "https:" ? https : http;
52
+ const req = transport.request({
53
+ hostname: parsed.hostname,
54
+ port: parsed.port || (parsed.protocol === "https:" ? 443 : 80),
55
+ path: parsed.pathname,
56
+ method: "GET",
57
+ headers: {
58
+ Authorization: "Basic " + Buffer.from(`${user}:${pass}`).toString("base64"),
59
+ "sap-client": client,
60
+ Accept: "application/atomsvc+xml",
61
+ },
62
+ rejectUnauthorized: !selfSigned,
63
+ timeout: 5000,
64
+ }, (res) => {
65
+ let body = "";
66
+ res.on("data", (chunk) => (body += chunk));
67
+ res.on("end", () => {
68
+ if (res.statusCode === 200) {
69
+ // Extrair info básica
70
+ const versionMatch = body.match(/release="(\d+)"/i);
71
+ const version = versionMatch ? `BASIS ${versionMatch[1]}` : "";
72
+ resolve({ ok: true, info: version || "OK" });
73
+ }
74
+ else {
75
+ resolve({ ok: false, info: `HTTP ${res.statusCode}` });
76
+ }
77
+ });
78
+ });
79
+ req.on("error", () => resolve({ ok: false, info: "Sem conexão" }));
80
+ req.on("timeout", () => { req.destroy(); resolve({ ok: false, info: "Timeout" }); });
81
+ req.end();
82
+ });
83
+ }
84
+ // ---------------------------------------------------------------------------
85
+ // Métricas do dia (do logger)
86
+ // ---------------------------------------------------------------------------
87
+ function getTodayMetrics() {
88
+ const today = new Date().toISOString().split("T")[0];
89
+ const logFile = path.join(LOG_DIR, `adt-${today}.jsonl`);
90
+ if (!fs.existsSync(logFile)) {
91
+ return { calls: 0, success: 0, errors: 0, avgMs: 0 };
92
+ }
93
+ const lines = fs.readFileSync(logFile, "utf-8").trim().split("\n").filter(Boolean);
94
+ let success = 0;
95
+ let errors = 0;
96
+ let totalMs = 0;
97
+ for (const line of lines) {
98
+ try {
99
+ const entry = JSON.parse(line);
100
+ if (entry.status && entry.status < 400) {
101
+ success++;
102
+ }
103
+ else {
104
+ errors++;
105
+ }
106
+ if (entry.duration)
107
+ totalMs += entry.duration;
108
+ }
109
+ catch {
110
+ // skip malformed lines
111
+ }
112
+ }
113
+ const calls = success + errors;
114
+ return { calls, success, errors, avgMs: calls > 0 ? Math.round(totalMs / calls) : 0 };
115
+ }
116
+ // ---------------------------------------------------------------------------
117
+ // Contar knowledge files
118
+ // ---------------------------------------------------------------------------
119
+ function countKnowledge() {
120
+ // Tentar dist/knowledge primeiro, depois src/knowledge
121
+ const candidates = [
122
+ path.resolve(__dirname, "..", "knowledge"),
123
+ path.resolve(process.cwd(), "src", "knowledge"),
124
+ path.resolve(process.cwd(), "dist", "knowledge"),
125
+ ];
126
+ for (const dir of candidates) {
127
+ if (fs.existsSync(dir)) {
128
+ let files = 0;
129
+ let domains = 0;
130
+ const entries = fs.readdirSync(dir, { withFileTypes: true });
131
+ for (const entry of entries) {
132
+ if (entry.isDirectory()) {
133
+ domains++;
134
+ const domainFiles = fs.readdirSync(path.join(dir, entry.name)).filter((f) => f.endsWith(".md"));
135
+ files += domainFiles.length;
136
+ }
137
+ }
138
+ return { files, domains };
139
+ }
140
+ }
141
+ return { files: 0, domains: 0 };
142
+ }
143
+ // ---------------------------------------------------------------------------
144
+ // Main
145
+ // ---------------------------------------------------------------------------
146
+ async function status() {
147
+ console.log(`
148
+ ╭──────────────────────────────────────────────╮
149
+ │ LKPABAP.ia v${VERSION}${" ".repeat(30 - VERSION.length)}│
150
+ ╰──────────────────────────────────────────────╯`);
151
+ // Licença
152
+ console.log(`
153
+ Licença
154
+ ───────`);
155
+ const license = (0, activate_js_1.readLicense)();
156
+ if (license) {
157
+ const now = new Date();
158
+ const expires = new Date(license.expires);
159
+ const daysLeft = Math.ceil((expires.getTime() - now.getTime()) / (1000 * 60 * 60 * 24));
160
+ const expired = daysLeft <= 0;
161
+ const planLabel = `${license.plan.charAt(0).toUpperCase() + license.plan.slice(1)} (${license.mode === "byok" ? "BYOK" : "All-in-One"})`;
162
+ console.log(` Plano: ${planLabel}`);
163
+ console.log(` Válido até: ${license.expires} (${expired ? "EXPIRADA" : `${daysLeft} dias restantes`})`);
164
+ console.log(` Status: ${expired ? "✗ Expirada — renove em https://lkpabap.ai" : "✓ Ativa"}`);
165
+ }
166
+ else {
167
+ console.log(` Status: ✗ Nenhuma licença configurada`);
168
+ console.log(` → Execute: abap-ai activate <LICENSE_KEY>`);
169
+ }
170
+ // Sistemas SAP
171
+ console.log(`
172
+ Sistemas SAP configurados
173
+ ─────────────────────────`);
174
+ let mcpConfig = { mcpServers: {} };
175
+ try {
176
+ const raw = fs.readFileSync(MCP_JSON_PATH, "utf-8");
177
+ mcpConfig = JSON.parse(raw);
178
+ }
179
+ catch {
180
+ // no mcp.json
181
+ }
182
+ const sapServers = Object.entries(mcpConfig.mcpServers || {}).filter(([k]) => k.startsWith("abap-"));
183
+ if (sapServers.length === 0) {
184
+ console.log(` Nenhum configurado`);
185
+ console.log(` → Execute: abap-ai init`);
186
+ }
187
+ else {
188
+ for (const [name, server] of sapServers) {
189
+ const env = server.env || {};
190
+ const url = env.SAP_URL || "?";
191
+ const client = env.SAP_CLIENT || "?";
192
+ const selfSigned = env.NODE_TLS_REJECT_UNAUTHORIZED === "0";
193
+ const shortUrl = url.replace(/^https?:\/\//, "").replace(/\.local$/, "");
194
+ if (env.SAP_URL && env.SAP_USER && env.SAP_PASS) {
195
+ const result = await quickTest(env.SAP_URL, env.SAP_USER, env.SAP_PASS, client, selfSigned);
196
+ if (result.ok) {
197
+ console.log(` ✓ ${name} ${shortUrl} (client ${client}) ${result.info}`);
198
+ }
199
+ else {
200
+ console.log(` ✗ ${name} ${shortUrl} (client ${client}) ${result.info}`);
201
+ }
202
+ }
203
+ else {
204
+ console.log(` ⚠ ${name} ${shortUrl} (client ${client}) Credenciais incompletas`);
205
+ }
206
+ }
207
+ }
208
+ // Uso hoje
209
+ const metrics = getTodayMetrics();
210
+ if (metrics.calls > 0) {
211
+ const successRate = metrics.calls > 0 ? Math.round((metrics.success / metrics.calls) * 100) : 0;
212
+ console.log(`
213
+ Uso hoje
214
+ ────────
215
+ Chamadas ADT: ${metrics.calls}
216
+ Sucesso: ${metrics.success} (${successRate}%)
217
+ Erros: ${metrics.errors}
218
+ Tempo médio: ${metrics.avgMs}ms`);
219
+ }
220
+ // Knowledge
221
+ const knowledge = countKnowledge();
222
+ if (knowledge.files > 0) {
223
+ console.log(`
224
+ Knowledge Base
225
+ ──────────────
226
+ ${knowledge.files} guias | ${knowledge.domains} domínios`);
227
+ }
228
+ console.log("");
229
+ }