@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 +82 -5
- package/dist/cli/remove.js +1 -1
- package/dist/cli/systems.js +1 -1
- package/dist/postinstall.js +88 -0
- package/package.json +3 -2
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(), ".
|
|
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
|
|
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: ${
|
|
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
|
-
|
|
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.
|
|
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");
|
package/dist/cli/remove.js
CHANGED
|
@@ -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(), ".
|
|
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;
|
package/dist/cli/systems.js
CHANGED
|
@@ -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(), ".
|
|
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.
|
|
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",
|