@linkup-ai/abap-ai 2.2.1 → 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.
@@ -37,8 +37,9 @@ exports.readLicense = readLicense;
37
37
  exports.activate = activate;
38
38
  const crypto = __importStar(require("crypto"));
39
39
  const fs = __importStar(require("fs"));
40
+ const os = __importStar(require("os"));
40
41
  const path = __importStar(require("path"));
41
- const LICENSE_DIR = path.join(process.env.HOME || "~", ".abap-ai");
42
+ const LICENSE_DIR = path.join(os.homedir(), ".abap-ai");
42
43
  const LICENSE_PATH = path.join(LICENSE_DIR, "license.json");
43
44
  // ── Beta key validation (offline, HMAC-based) ───────────────────────
44
45
  // Em produção será substituído por fetch ao license server (api.lkpabap.ai)
package/dist/cli/init.js CHANGED
@@ -39,11 +39,12 @@ Object.defineProperty(exports, "__esModule", { value: true });
39
39
  exports.init = init;
40
40
  const prompts_1 = __importDefault(require("prompts"));
41
41
  const fs = __importStar(require("fs"));
42
+ const os = __importStar(require("os"));
42
43
  const path = __importStar(require("path"));
43
44
  const https = __importStar(require("https"));
44
45
  const http = __importStar(require("http"));
45
- const GLOBAL_MCP_PATH = path.join(process.env.HOME || "~", ".claude", "mcp.json");
46
- const LOCAL_MCP_PATH = path.join(process.cwd(), ".claude", "mcp.json");
46
+ const GLOBAL_MCP_PATH = path.join(os.homedir(), ".claude", "mcp.json");
47
+ const LOCAL_MCP_PATH = path.join(process.cwd(), ".mcp.json"); // VS Code lê .mcp.json na raiz do workspace
47
48
  function getMcpPath(local) {
48
49
  return local ? LOCAL_MCP_PATH : GLOBAL_MCP_PATH;
49
50
  }
@@ -136,13 +137,8 @@ function writeMcpConfig(config, mcpPath) {
136
137
  fs.writeFileSync(mcpPath, JSON.stringify(config, null, 2) + "\n", "utf-8");
137
138
  }
138
139
  function detectServerPath() {
139
- // Tentar encontrar o index.js relativo ao CLI
140
- const fromCli = path.resolve(__dirname, "..", "index.js");
141
- if (fs.existsSync(fromCli))
142
- return fromCli;
143
- // Fallback: path global do pacote
144
- const globalPath = path.resolve(__dirname, "..", "index.js");
145
- return globalPath;
140
+ // cli.js e index.js ficam ambos em dist/ após o build
141
+ return path.resolve(__dirname, "index.js");
146
142
  }
147
143
  function addSystemToConfig(config, system) {
148
144
  const serverName = `abap-${system.name}`;
@@ -159,12 +155,72 @@ function addSystemToConfig(config, system) {
159
155
  env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
160
156
  }
161
157
  config.mcpServers[serverName] = {
162
- command: "node",
158
+ command: process.execPath,
163
159
  args: [serverPath],
164
160
  env,
165
161
  };
166
162
  }
167
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
+ // ---------------------------------------------------------------------------
168
224
  // Wizard
169
225
  // ---------------------------------------------------------------------------
170
226
  async function promptSystem() {
@@ -256,14 +312,16 @@ async function promptSystem() {
256
312
  async function init(options = {}) {
257
313
  const local = options.local ?? false;
258
314
  const mcpPath = getMcpPath(local);
259
- const scope = local ? `projeto (${process.cwd()})` : "global";
315
+ const scopeLabel = local
316
+ ? `projeto → ${mcpPath}`
317
+ : `global → ${mcpPath}`;
260
318
  console.log(`
261
319
  ╭─────────────────────────────────────╮
262
320
  │ LKPABAP.ai — Setup │
263
321
  │ Conecte o Claude ao seu SAP │
264
322
  ╰─────────────────────────────────────╯
265
323
 
266
- Escopo: ${scope}
324
+ Escopo: ${scopeLabel}
267
325
  `);
268
326
  const config = readMcpConfig(mcpPath);
269
327
  const existingCount = Object.keys(config.mcpServers).filter((k) => k.startsWith("abap-")).length;
@@ -330,6 +388,11 @@ async function init(options = {}) {
330
388
  }
331
389
  if (addedSystems.length > 0) {
332
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);
333
396
  const total = Object.keys(config.mcpServers).filter((k) => k.startsWith("abap-")).length;
334
397
  console.log(`
335
398
  ✓ Configuração salva em ${mcpPath}
@@ -345,11 +408,22 @@ async function init(options = {}) {
345
408
  const line = ` │ • ${name} (client ${client}, ${roleTag})`;
346
409
  console.log(`${line}${" ".repeat(Math.max(1, 48 - line.length))}│`);
347
410
  }
348
- console.log(` │${" ".repeat(46)}│
411
+ if (local) {
412
+ console.log(` │${" ".repeat(46)}│
413
+ │ Próximo passo no VS Code:${" ".repeat(19)}│
414
+ │ 1. Ctrl+Shift+P → "Reload Window"${" ".repeat(8)}│
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)}│
349
422
  │ Próximo passo:${" ".repeat(29)}│
350
- │ Abra o VS Code / Claude Code e use!${" ".repeat(6)}│
423
+ │ Abra o Claude Code e use!${" ".repeat(16)}│
351
424
  ╰──────────────────────────────────────────────╯
352
425
  `);
426
+ }
353
427
  }
354
428
  else {
355
429
  console.log("\n Nenhum sistema adicionado.\n");
@@ -39,9 +39,10 @@ Object.defineProperty(exports, "__esModule", { value: true });
39
39
  exports.remove = remove;
40
40
  const prompts_1 = __importDefault(require("prompts"));
41
41
  const fs = __importStar(require("fs"));
42
+ const os = __importStar(require("os"));
42
43
  const path = __importStar(require("path"));
43
- const GLOBAL_MCP_PATH = path.join(process.env.HOME || "~", ".claude", "mcp.json");
44
- const LOCAL_MCP_PATH = path.join(process.cwd(), ".claude", "mcp.json");
44
+ const GLOBAL_MCP_PATH = path.join(os.homedir(), ".claude", "mcp.json");
45
+ const LOCAL_MCP_PATH = path.join(process.cwd(), ".mcp.json");
45
46
  async function remove(name, options = {}) {
46
47
  const serverName = name.startsWith("abap-") ? name : `abap-${name}`;
47
48
  const mcpPath = options.local ? LOCAL_MCP_PATH : GLOBAL_MCP_PATH;
@@ -35,13 +35,15 @@ var __importStar = (this && this.__importStar) || (function () {
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
36
  exports.status = status;
37
37
  const fs = __importStar(require("fs"));
38
+ const os = __importStar(require("os"));
38
39
  const path = __importStar(require("path"));
39
40
  const https = __importStar(require("https"));
40
41
  const http = __importStar(require("http"));
41
42
  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";
43
+ const MCP_JSON_PATH = path.join(os.homedir(), ".claude", "mcp.json");
44
+ const LOG_DIR = path.join(os.homedir(), ".abap-ai", "logs");
45
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
46
+ const VERSION = require("../../package.json").version;
45
47
  // ---------------------------------------------------------------------------
46
48
  // Teste rápido de conexão (timeout 5s)
47
49
  // ---------------------------------------------------------------------------
@@ -35,9 +35,10 @@ var __importStar = (this && this.__importStar) || (function () {
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
36
  exports.systems = systems;
37
37
  const fs = __importStar(require("fs"));
38
+ const os = __importStar(require("os"));
38
39
  const path = __importStar(require("path"));
39
- const GLOBAL_MCP_PATH = path.join(process.env.HOME || "~", ".claude", "mcp.json");
40
- const LOCAL_MCP_PATH = path.join(process.cwd(), ".claude", "mcp.json");
40
+ const GLOBAL_MCP_PATH = path.join(os.homedir(), ".claude", "mcp.json");
41
+ const LOCAL_MCP_PATH = path.join(process.cwd(), ".mcp.json");
41
42
  async function systems(options = {}) {
42
43
  const mcpPath = options.local ? LOCAL_MCP_PATH : GLOBAL_MCP_PATH;
43
44
  let config;
package/dist/cli.js CHANGED
@@ -6,7 +6,8 @@ const activate_js_1 = require("./cli/activate.js");
6
6
  const status_js_1 = require("./cli/status.js");
7
7
  const remove_js_1 = require("./cli/remove.js");
8
8
  const systems_js_1 = require("./cli/systems.js");
9
- const VERSION = "2.2.1";
9
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
10
+ const VERSION = require("../package.json").version;
10
11
  const HELP = `
11
12
  LKPABAP.ai — AI-powered ABAP development for SAP
12
13
 
@@ -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.1",
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",