@linkup-ai/abap-ai 2.2.2 → 2.2.4

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.
package/dist/cli/init.js CHANGED
@@ -44,7 +44,7 @@ const path = __importStar(require("path"));
44
44
  const https = __importStar(require("https"));
45
45
  const http = __importStar(require("http"));
46
46
  const GLOBAL_MCP_PATH = path.join(os.homedir(), ".claude", "mcp.json");
47
- const LOCAL_MCP_PATH = path.join(process.cwd(), ".claude", "mcp.json");
47
+ const LOCAL_MCP_PATH = path.join(process.cwd(), ".mcp.json"); // VS Code lê .mcp.json na raiz do workspace
48
48
  function getMcpPath(local) {
49
49
  return local ? LOCAL_MCP_PATH : GLOBAL_MCP_PATH;
50
50
  }
@@ -161,6 +161,66 @@ function addSystemToConfig(config, system) {
161
161
  };
162
162
  }
163
163
  // ---------------------------------------------------------------------------
164
+ // CLAUDE.md — contexto para o Claude Code
165
+ // ---------------------------------------------------------------------------
166
+ function buildClaudeMdSection(config) {
167
+ const sapServers = Object.entries(config.mcpServers).filter(([k]) => k.startsWith("abap-"));
168
+ if (sapServers.length === 0)
169
+ return "";
170
+ const lines = [
171
+ "## LKPABAP.ai — Sistemas SAP configurados",
172
+ "",
173
+ "Este projeto tem o MCP `@linkup-ai/abap-ai` ativo. Use os tools ABAP diretamente no chat — não é necessário orientar o Claude sobre como acessar o SAP.",
174
+ "",
175
+ "### Sistemas disponíveis",
176
+ "",
177
+ ];
178
+ for (const [name, server] of sapServers) {
179
+ const env = server.env || {};
180
+ const url = env.SAP_URL || "?";
181
+ const client = env.SAP_CLIENT || "?";
182
+ const role = env.ABAP_AI_ENV_ROLE || "DEVELOPMENT";
183
+ const roleLabel = role === "PRODUCTION" ? "PRD — somente leitura"
184
+ : role === "QUALITY" ? "QAS — somente leitura"
185
+ : "DEV — leitura, escrita e criação permitidas";
186
+ lines.push(`- **${name}** — \`${url}\` (client ${client}) — ${roleLabel}`);
187
+ }
188
+ lines.push("", "### Exemplos de uso", "");
189
+ lines.push('- "Leia a classe ZCL_PEDIDO no sistema abap-dev"');
190
+ lines.push('- "Crie um report YTESTE sem request de transporte"');
191
+ lines.push('- "Busque onde a FM BAPI_SALESORDER_CREATEFROMDAT2 é usada"');
192
+ lines.push('- "Rode o ATC no pacote ZVENDAS e corrija os erros"');
193
+ lines.push("");
194
+ return lines.join("\n");
195
+ }
196
+ const CLAUDE_MD_MARKER_START = "<!-- lkpabap:start -->";
197
+ const CLAUDE_MD_MARKER_END = "<!-- lkpabap:end -->";
198
+ function updateClaudeMd(claudeMdPath, config) {
199
+ const section = buildClaudeMdSection(config);
200
+ if (!section)
201
+ return;
202
+ const block = `${CLAUDE_MD_MARKER_START}\n${section}${CLAUDE_MD_MARKER_END}\n`;
203
+ let existing = "";
204
+ try {
205
+ existing = fs.readFileSync(claudeMdPath, "utf-8");
206
+ }
207
+ catch { /* novo arquivo */ }
208
+ let updated;
209
+ if (existing.includes(CLAUDE_MD_MARKER_START)) {
210
+ // Atualiza bloco existente
211
+ const re = new RegExp(`${CLAUDE_MD_MARKER_START}[\\s\\S]*?${CLAUDE_MD_MARKER_END}\\n?`, "g");
212
+ updated = existing.replace(re, block);
213
+ }
214
+ else {
215
+ // Acrescenta ao final
216
+ updated = existing ? `${existing.trimEnd()}\n\n${block}` : block;
217
+ }
218
+ const dir = path.dirname(claudeMdPath);
219
+ if (!fs.existsSync(dir))
220
+ fs.mkdirSync(dir, { recursive: true });
221
+ fs.writeFileSync(claudeMdPath, updated, "utf-8");
222
+ }
223
+ // ---------------------------------------------------------------------------
164
224
  // Wizard
165
225
  // ---------------------------------------------------------------------------
166
226
  async function promptSystem() {
@@ -252,14 +312,16 @@ async function promptSystem() {
252
312
  async function init(options = {}) {
253
313
  const local = options.local ?? false;
254
314
  const mcpPath = getMcpPath(local);
255
- const scope = local ? `projeto (${process.cwd()})` : "global";
315
+ const scopeLabel = local
316
+ ? `projeto → ${mcpPath}`
317
+ : `global → ${mcpPath}`;
256
318
  console.log(`
257
319
  ╭─────────────────────────────────────╮
258
320
  │ LKPABAP.ai — Setup │
259
321
  │ Conecte o Claude ao seu SAP │
260
322
  ╰─────────────────────────────────────╯
261
323
 
262
- Escopo: ${scope}
324
+ Escopo: ${scopeLabel}
263
325
  `);
264
326
  const config = readMcpConfig(mcpPath);
265
327
  const existingCount = Object.keys(config.mcpServers).filter((k) => k.startsWith("abap-")).length;
@@ -326,6 +388,11 @@ async function init(options = {}) {
326
388
  }
327
389
  if (addedSystems.length > 0) {
328
390
  writeMcpConfig(config, mcpPath);
391
+ // Gera/atualiza CLAUDE.md com contexto sobre os sistemas SAP
392
+ const claudeMdPath = local
393
+ ? path.join(process.cwd(), "CLAUDE.md")
394
+ : path.join(os.homedir(), ".claude", "CLAUDE.md");
395
+ updateClaudeMd(claudeMdPath, config);
329
396
  const total = Object.keys(config.mcpServers).filter((k) => k.startsWith("abap-")).length;
330
397
  console.log(`
331
398
  ✓ Configuração salva em ${mcpPath}
@@ -341,12 +408,22 @@ async function init(options = {}) {
341
408
  const line = ` │ • ${name} (client ${client}, ${roleTag})`;
342
409
  console.log(`${line}${" ".repeat(Math.max(1, 48 - line.length))}│`);
343
410
  }
344
- console.log(` │${" ".repeat(46)}│
411
+ if (local) {
412
+ console.log(` │${" ".repeat(46)}│
345
413
  │ Próximo passo no VS Code:${" ".repeat(19)}│
346
414
  │ 1. Ctrl+Shift+P → "Reload Window"${" ".repeat(8)}│
347
- │ 2. Abra o Claude Code e use!${" ".repeat(13)}│
415
+ │ 2. Clique "Allow" no aviso do MCP${" ".repeat(8)}│
416
+ │ 3. Converse com o Claude Code!${" ".repeat(11)}│
417
+ ╰──────────────────────────────────────────────╯
418
+ `);
419
+ }
420
+ else {
421
+ console.log(` │${" ".repeat(46)}│
422
+ │ Próximo passo:${" ".repeat(29)}│
423
+ │ Abra o Claude Code e use!${" ".repeat(16)}│
348
424
  ╰──────────────────────────────────────────────╯
349
425
  `);
426
+ }
350
427
  }
351
428
  else {
352
429
  console.log("\n Nenhum sistema adicionado.\n");
@@ -42,7 +42,7 @@ const fs = __importStar(require("fs"));
42
42
  const os = __importStar(require("os"));
43
43
  const path = __importStar(require("path"));
44
44
  const GLOBAL_MCP_PATH = path.join(os.homedir(), ".claude", "mcp.json");
45
- const LOCAL_MCP_PATH = path.join(process.cwd(), ".claude", "mcp.json");
45
+ const LOCAL_MCP_PATH = path.join(process.cwd(), ".mcp.json");
46
46
  async function remove(name, options = {}) {
47
47
  const serverName = name.startsWith("abap-") ? name : `abap-${name}`;
48
48
  const mcpPath = options.local ? LOCAL_MCP_PATH : GLOBAL_MCP_PATH;
@@ -38,7 +38,7 @@ const fs = __importStar(require("fs"));
38
38
  const os = __importStar(require("os"));
39
39
  const path = __importStar(require("path"));
40
40
  const GLOBAL_MCP_PATH = path.join(os.homedir(), ".claude", "mcp.json");
41
- const LOCAL_MCP_PATH = path.join(process.cwd(), ".claude", "mcp.json");
41
+ const LOCAL_MCP_PATH = path.join(process.cwd(), ".mcp.json");
42
42
  async function systems(options = {}) {
43
43
  const mcpPath = options.local ? LOCAL_MCP_PATH : GLOBAL_MCP_PATH;
44
44
  let config;
@@ -0,0 +1,88 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
4
+ if (k2 === undefined) k2 = k;
5
+ var desc = Object.getOwnPropertyDescriptor(m, k);
6
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
7
+ desc = { enumerable: true, get: function() { return m[k]; } };
8
+ }
9
+ Object.defineProperty(o, k2, desc);
10
+ }) : (function(o, m, k, k2) {
11
+ if (k2 === undefined) k2 = k;
12
+ o[k2] = m[k];
13
+ }));
14
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
15
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
16
+ }) : function(o, v) {
17
+ o["default"] = v;
18
+ });
19
+ var __importStar = (this && this.__importStar) || (function () {
20
+ var ownKeys = function(o) {
21
+ ownKeys = Object.getOwnPropertyNames || function (o) {
22
+ var ar = [];
23
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
24
+ return ar;
25
+ };
26
+ return ownKeys(o);
27
+ };
28
+ return function (mod) {
29
+ if (mod && mod.__esModule) return mod;
30
+ var result = {};
31
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
32
+ __setModuleDefault(result, mod);
33
+ return result;
34
+ };
35
+ })();
36
+ Object.defineProperty(exports, "__esModule", { value: true });
37
+ const fs = __importStar(require("fs"));
38
+ const os = __importStar(require("os"));
39
+ const path = __importStar(require("path"));
40
+ const child_process_1 = require("child_process");
41
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
42
+ const VERSION = require("../package.json").version;
43
+ function checkNode() {
44
+ const version = process.version; // e.g. "v20.11.0"
45
+ const major = parseInt(version.slice(1).split(".")[0], 10);
46
+ return { ok: major >= 18, version };
47
+ }
48
+ function checkClaudeCode() {
49
+ // Verifica se o Claude Code CLI está instalado
50
+ try {
51
+ (0, child_process_1.execSync)("claude --version", { stdio: "pipe" });
52
+ return { ok: true, detail: "encontrado" };
53
+ }
54
+ catch {
55
+ // Verifica se a pasta ~/.claude existe (extensão VS Code cria ela)
56
+ const claudeDir = path.join(os.homedir(), ".claude");
57
+ if (fs.existsSync(claudeDir)) {
58
+ return { ok: true, detail: "pasta ~/.claude encontrada (VS Code extension)" };
59
+ }
60
+ return { ok: false, detail: "não encontrado" };
61
+ }
62
+ }
63
+ function main() {
64
+ const node = checkNode();
65
+ const claude = checkClaudeCode();
66
+ const nodeIcon = node.ok ? "✓" : "✗";
67
+ const claudeIcon = claude.ok ? "✓" : "⚠";
68
+ const title = ` LKPABAP.ai v${VERSION} instalado!`;
69
+ console.log(`
70
+ ╭──────────────────────────────────────────────╮
71
+ │${title}${" ".repeat(Math.max(1, 47 - title.length))}│
72
+ ╰──────────────────────────────────────────────╯
73
+
74
+ Pré-requisitos:
75
+ ${nodeIcon} Node.js ${node.version}${node.ok ? "" : " ← precisa de v18+"}
76
+ ${claudeIcon} Claude Code: ${claude.detail}${claude.ok ? "" : "\n → Instale em: https://claude.ai/download"}
77
+
78
+ Próximos passos:
79
+ 1. abap-ai activate LK-XXXX-XXXX-XXXX ← ative sua licença
80
+ 2. cd <pasta-do-projeto>
81
+ abap-ai init --local ← configure o sistema SAP
82
+ 3. Abra o VS Code nesta pasta e use!
83
+ `);
84
+ if (!node.ok) {
85
+ console.error(" AVISO: Node.js 18+ é obrigatório. Versão atual: " + node.version + "\n");
86
+ }
87
+ }
88
+ main();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@linkup-ai/abap-ai",
3
- "version": "2.2.2",
3
+ "version": "2.2.4",
4
4
  "description": "LKPABAP.ai — AI-powered ABAP development tools for SAP S/4HANA via ADT REST API",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
@@ -31,7 +31,8 @@
31
31
  "build": "tsc && rm -rf dist/knowledge && cp -r src/knowledge dist/knowledge",
32
32
  "start": "node dist/index.js",
33
33
  "dev": "tsc --watch",
34
- "prepublishOnly": "npm run build"
34
+ "prepublishOnly": "npm run build",
35
+ "postinstall": "node dist/postinstall.js || true"
35
36
  },
36
37
  "dependencies": {
37
38
  "@modelcontextprotocol/sdk": "^1.0.0",