arc-1 0.6.9 → 0.6.10
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/README.md +6 -4
- package/dist/adt/abapgit.d.ts +39 -0
- package/dist/adt/abapgit.d.ts.map +1 -0
- package/dist/adt/abapgit.js +333 -0
- package/dist/adt/abapgit.js.map +1 -0
- package/dist/adt/config.d.ts +1 -0
- package/dist/adt/config.d.ts.map +1 -1
- package/dist/adt/config.js +1 -0
- package/dist/adt/config.js.map +1 -1
- package/dist/adt/crud.d.ts.map +1 -1
- package/dist/adt/crud.js +42 -3
- package/dist/adt/crud.js.map +1 -1
- package/dist/adt/errors.d.ts +22 -1
- package/dist/adt/errors.d.ts.map +1 -1
- package/dist/adt/errors.js +71 -2
- package/dist/adt/errors.js.map +1 -1
- package/dist/adt/features.d.ts.map +1 -1
- package/dist/adt/features.js +3 -0
- package/dist/adt/features.js.map +1 -1
- package/dist/adt/gcts.d.ts +68 -0
- package/dist/adt/gcts.d.ts.map +1 -0
- package/dist/adt/gcts.js +239 -0
- package/dist/adt/gcts.js.map +1 -0
- package/dist/adt/safety.d.ts +3 -0
- package/dist/adt/safety.d.ts.map +1 -1
- package/dist/adt/safety.js +9 -0
- package/dist/adt/safety.js.map +1 -1
- package/dist/adt/transport.d.ts.map +1 -1
- package/dist/adt/transport.js +4 -1
- package/dist/adt/transport.js.map +1 -1
- package/dist/adt/types.d.ts +137 -0
- package/dist/adt/types.d.ts.map +1 -1
- package/dist/adt/xml-parser.d.ts +2 -0
- package/dist/adt/xml-parser.d.ts.map +1 -1
- package/dist/adt/xml-parser.js +2 -0
- package/dist/adt/xml-parser.js.map +1 -1
- package/dist/handlers/intent.d.ts.map +1 -1
- package/dist/handlers/intent.js +235 -0
- package/dist/handlers/intent.js.map +1 -1
- package/dist/handlers/schemas.d.ts +45 -1
- package/dist/handlers/schemas.d.ts.map +1 -1
- package/dist/handlers/schemas.js +46 -0
- package/dist/handlers/schemas.js.map +1 -1
- package/dist/handlers/tools.d.ts +4 -3
- package/dist/handlers/tools.d.ts.map +1 -1
- package/dist/handlers/tools.js +115 -3
- package/dist/handlers/tools.js.map +1 -1
- package/dist/probe/catalog.d.ts +30 -0
- package/dist/probe/catalog.d.ts.map +1 -0
- package/dist/probe/catalog.js +196 -0
- package/dist/probe/catalog.js.map +1 -0
- package/dist/probe/fixtures.d.ts +54 -0
- package/dist/probe/fixtures.d.ts.map +1 -0
- package/dist/probe/fixtures.js +94 -0
- package/dist/probe/fixtures.js.map +1 -0
- package/dist/probe/format.d.ts +10 -0
- package/dist/probe/format.d.ts.map +1 -0
- package/dist/probe/format.js +114 -0
- package/dist/probe/format.js.map +1 -0
- package/dist/probe/quality.d.ts +13 -0
- package/dist/probe/quality.d.ts.map +1 -0
- package/dist/probe/quality.js +50 -0
- package/dist/probe/quality.js.map +1 -0
- package/dist/probe/runner.d.ts +48 -0
- package/dist/probe/runner.d.ts.map +1 -0
- package/dist/probe/runner.js +211 -0
- package/dist/probe/runner.js.map +1 -0
- package/dist/probe/types.d.ts +159 -0
- package/dist/probe/types.d.ts.map +1 -0
- package/dist/probe/types.js +11 -0
- package/dist/probe/types.js.map +1 -0
- package/dist/server/audit.d.ts.map +1 -1
- package/dist/server/audit.js +12 -1
- package/dist/server/audit.js.map +1 -1
- package/dist/server/config.d.ts.map +1 -1
- package/dist/server/config.js +15 -2
- package/dist/server/config.js.map +1 -1
- package/dist/server/server.d.ts +2 -2
- package/dist/server/server.d.ts.map +1 -1
- package/dist/server/server.js +5 -3
- package/dist/server/server.js.map +1 -1
- package/dist/server/types.d.ts +3 -1
- package/dist/server/types.d.ts.map +1 -1
- package/dist/server/types.js +2 -0
- package/dist/server/types.js.map +1 -1
- package/package.json +4 -1
package/dist/handlers/intent.js
CHANGED
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
* responses. Internal details (stack traces, SAP XML) are NOT
|
|
10
10
|
* leaked to the LLM — only user-friendly error messages.
|
|
11
11
|
*/
|
|
12
|
+
import { checkRepo as abapGitCheckRepo, createBranch as abapGitCreateBranch, createRepo as abapGitCreateRepo, getExternalInfo as abapGitGetExternalInfo, listRepos as abapGitListRepos, pullRepo as abapGitPullRepo, pushRepo as abapGitPushRepo, stageRepo as abapGitStageRepo, switchBranch as abapGitSwitchBranch, unlinkRepo as abapGitUnlinkRepo, } from '../adt/abapgit.js';
|
|
12
13
|
import { classifyCdsImpact } from '../adt/cds-impact.js';
|
|
13
14
|
import { findDefinition, findReferences, findWhereUsed, getCompletion, } from '../adt/codeintel.js';
|
|
14
15
|
import { createObject, deleteObject, lockObject, safeUpdateObject, safeUpdateSource, unlockObject, updateObject, } from '../adt/crud.js';
|
|
@@ -18,6 +19,7 @@ import { getDump, getTraceDbAccesses, getTraceHitlist, getTraceStatements, listD
|
|
|
18
19
|
import { AdtApiError, AdtNetworkError, AdtSafetyError, classifySapDomainError, isNotFoundError, } from '../adt/errors.js';
|
|
19
20
|
import { classifyTextSearchError, mapSapReleaseToAbaplintVersion, probeFeatures } from '../adt/features.js';
|
|
20
21
|
import { addTileToGroup, createCatalog, createGroup, createTile, deleteCatalog, listCatalogs, listGroups, listTiles, } from '../adt/flp.js';
|
|
22
|
+
import { cloneRepo as gctsCloneRepo, commitRepo as gctsCommitRepo, createBranch as gctsCreateBranch, deleteRepo as gctsDeleteRepo, getCommitHistory as gctsGetCommitHistory, getConfig as gctsGetConfig, getUserInfo as gctsGetUserInfo, listBranches as gctsListBranches, listRepoObjects as gctsListRepoObjects, listRepos as gctsListRepos, pullRepo as gctsPullRepo, switchBranch as gctsSwitchBranch, } from '../adt/gcts.js';
|
|
21
23
|
import { changePackage } from '../adt/refactoring.js';
|
|
22
24
|
import { checkOperation, checkPackage, isOperationAllowed, OperationType } from '../adt/safety.js';
|
|
23
25
|
import { createTransport, deleteTransport, getObjectTransports, getTransport, getTransportInfo, listTransports, reassignTransport, releaseTransport, releaseTransportRecursive, } from '../adt/transport.js';
|
|
@@ -48,6 +50,7 @@ export const TOOL_SCOPES = {
|
|
|
48
50
|
SAPRead: 'read',
|
|
49
51
|
SAPSearch: 'read',
|
|
50
52
|
SAPQuery: 'sql',
|
|
53
|
+
SAPGit: 'read',
|
|
51
54
|
SAPNavigate: 'read',
|
|
52
55
|
SAPContext: 'read',
|
|
53
56
|
SAPLint: 'read',
|
|
@@ -57,6 +60,24 @@ export const TOOL_SCOPES = {
|
|
|
57
60
|
SAPManage: 'write',
|
|
58
61
|
SAPTransport: 'write',
|
|
59
62
|
};
|
|
63
|
+
const SAPGIT_ACTION_SCOPES = {
|
|
64
|
+
list_repos: 'read',
|
|
65
|
+
whoami: 'read',
|
|
66
|
+
config: 'read',
|
|
67
|
+
branches: 'read',
|
|
68
|
+
external_info: 'read',
|
|
69
|
+
history: 'read',
|
|
70
|
+
objects: 'read',
|
|
71
|
+
check: 'read',
|
|
72
|
+
clone: 'write',
|
|
73
|
+
pull: 'write',
|
|
74
|
+
push: 'write',
|
|
75
|
+
commit: 'write',
|
|
76
|
+
stage: 'write',
|
|
77
|
+
switch_branch: 'write',
|
|
78
|
+
create_branch: 'write',
|
|
79
|
+
unlink: 'write',
|
|
80
|
+
};
|
|
60
81
|
/**
|
|
61
82
|
* Check if authInfo has the required scope, respecting implied scopes:
|
|
62
83
|
* - `write` implies `read`
|
|
@@ -366,6 +387,9 @@ export async function handleToolCall(client, config, toolName, args, authInfo, _
|
|
|
366
387
|
case 'SAPTransport':
|
|
367
388
|
result = await handleSAPTransport(client, args);
|
|
368
389
|
break;
|
|
390
|
+
case 'SAPGit':
|
|
391
|
+
result = await handleSAPGit(client, args, authInfo);
|
|
392
|
+
break;
|
|
369
393
|
case 'SAPContext':
|
|
370
394
|
result = await handleSAPContext(client, args, cachingLayer);
|
|
371
395
|
break;
|
|
@@ -2569,6 +2593,217 @@ async function handleSAPDiagnose(client, args) {
|
|
|
2569
2593
|
return errorResult(`Unknown SAPDiagnose action: ${action}. Supported: syntax, unittest, atc, quickfix, apply_quickfix, dumps, traces`);
|
|
2570
2594
|
}
|
|
2571
2595
|
}
|
|
2596
|
+
function resolveSapGitBackend(args) {
|
|
2597
|
+
const forced = args.backend;
|
|
2598
|
+
const hasGcts = Boolean(cachedFeatures?.gcts?.available);
|
|
2599
|
+
const hasAbapGit = Boolean(cachedFeatures?.abapGit?.available);
|
|
2600
|
+
if (!hasGcts && !hasAbapGit) {
|
|
2601
|
+
return {
|
|
2602
|
+
error: 'Neither gCTS nor abapGit is available on this SAP system. Run SAPManage(action="probe") to refresh feature detection.',
|
|
2603
|
+
};
|
|
2604
|
+
}
|
|
2605
|
+
if (forced) {
|
|
2606
|
+
if (forced === 'gcts' && !hasGcts)
|
|
2607
|
+
return { error: 'gCTS backend is not available on this SAP system.' };
|
|
2608
|
+
if (forced === 'abapgit' && !hasAbapGit)
|
|
2609
|
+
return { error: 'abapGit backend is not available on this SAP system.' };
|
|
2610
|
+
return { backend: forced };
|
|
2611
|
+
}
|
|
2612
|
+
return { backend: hasGcts ? 'gcts' : 'abapgit' };
|
|
2613
|
+
}
|
|
2614
|
+
async function loadAbapGitRepo(client, repoId) {
|
|
2615
|
+
const repos = await abapGitListRepos(client.http, client.safety);
|
|
2616
|
+
const repo = repos.find((candidate) => candidate.key === repoId);
|
|
2617
|
+
if (!repo) {
|
|
2618
|
+
throw new Error(`abapGit repository "${repoId}" was not found. Run SAPGit(action="list_repos", backend="abapgit").`);
|
|
2619
|
+
}
|
|
2620
|
+
return repo;
|
|
2621
|
+
}
|
|
2622
|
+
async function handleSAPGit(client, args, authInfo) {
|
|
2623
|
+
const action = String(args.action ?? '');
|
|
2624
|
+
const scope = SAPGIT_ACTION_SCOPES[action];
|
|
2625
|
+
if (!scope) {
|
|
2626
|
+
return errorResult(`Unknown SAPGit action: ${action}`);
|
|
2627
|
+
}
|
|
2628
|
+
if (authInfo && !hasRequiredScope(authInfo, scope)) {
|
|
2629
|
+
return errorResult(`Insufficient scope: '${scope}' required for SAPGit(action="${action}"). Your scopes: [${authInfo.scopes.join(', ')}]`);
|
|
2630
|
+
}
|
|
2631
|
+
const resolved = resolveSapGitBackend(args);
|
|
2632
|
+
if (!resolved.backend) {
|
|
2633
|
+
return errorResult(resolved.error ?? 'Unable to resolve SAPGit backend.');
|
|
2634
|
+
}
|
|
2635
|
+
const backend = resolved.backend;
|
|
2636
|
+
const repoId = String(args.repoId ?? '').trim();
|
|
2637
|
+
const url = String(args.url ?? '').trim();
|
|
2638
|
+
const branch = String(args.branch ?? '').trim();
|
|
2639
|
+
const packageName = String(args.package ?? '').trim();
|
|
2640
|
+
const user = String(args.user ?? '').trim() || undefined;
|
|
2641
|
+
const password = String(args.password ?? '').trim() || undefined;
|
|
2642
|
+
const token = String(args.token ?? '').trim() || undefined;
|
|
2643
|
+
const limit = Number(args.limit ?? 20);
|
|
2644
|
+
const gctsOnlyActions = new Set(['whoami', 'config', 'branches', 'history', 'objects', 'commit']);
|
|
2645
|
+
const abapGitOnlyActions = new Set(['external_info', 'check', 'stage', 'push']);
|
|
2646
|
+
if (backend === 'abapgit' && gctsOnlyActions.has(action)) {
|
|
2647
|
+
return errorResult(`Action '${action}' is only supported by gCTS; this system uses abapGit.`);
|
|
2648
|
+
}
|
|
2649
|
+
if (backend === 'gcts' && abapGitOnlyActions.has(action)) {
|
|
2650
|
+
return errorResult(`Action '${action}' is only supported by abapGit; this system uses gCTS.`);
|
|
2651
|
+
}
|
|
2652
|
+
let result;
|
|
2653
|
+
switch (action) {
|
|
2654
|
+
case 'list_repos':
|
|
2655
|
+
result =
|
|
2656
|
+
backend === 'gcts'
|
|
2657
|
+
? await gctsListRepos(client.http, client.safety)
|
|
2658
|
+
: await abapGitListRepos(client.http, client.safety);
|
|
2659
|
+
break;
|
|
2660
|
+
case 'whoami':
|
|
2661
|
+
result = await gctsGetUserInfo(client.http, client.safety);
|
|
2662
|
+
break;
|
|
2663
|
+
case 'config':
|
|
2664
|
+
result = await gctsGetConfig(client.http, client.safety, repoId || undefined);
|
|
2665
|
+
break;
|
|
2666
|
+
case 'branches':
|
|
2667
|
+
if (!repoId)
|
|
2668
|
+
return errorResult('SAPGit(action="branches") requires repoId.');
|
|
2669
|
+
result = await gctsListBranches(client.http, client.safety, repoId);
|
|
2670
|
+
break;
|
|
2671
|
+
case 'external_info':
|
|
2672
|
+
if (!url)
|
|
2673
|
+
return errorResult('SAPGit(action="external_info") requires url.');
|
|
2674
|
+
result = await abapGitGetExternalInfo(client.http, client.safety, url, user, password);
|
|
2675
|
+
break;
|
|
2676
|
+
case 'history':
|
|
2677
|
+
if (!repoId)
|
|
2678
|
+
return errorResult('SAPGit(action="history") requires repoId.');
|
|
2679
|
+
result = await gctsGetCommitHistory(client.http, client.safety, repoId, Number.isFinite(limit) ? limit : 20);
|
|
2680
|
+
break;
|
|
2681
|
+
case 'objects':
|
|
2682
|
+
if (!repoId)
|
|
2683
|
+
return errorResult('SAPGit(action="objects") requires repoId.');
|
|
2684
|
+
result = await gctsListRepoObjects(client.http, client.safety, repoId);
|
|
2685
|
+
break;
|
|
2686
|
+
case 'check': {
|
|
2687
|
+
if (!repoId)
|
|
2688
|
+
return errorResult('SAPGit(action="check") requires repoId.');
|
|
2689
|
+
const repo = await loadAbapGitRepo(client, repoId);
|
|
2690
|
+
result = await abapGitCheckRepo(client.http, client.safety, repo);
|
|
2691
|
+
break;
|
|
2692
|
+
}
|
|
2693
|
+
case 'stage': {
|
|
2694
|
+
if (!repoId)
|
|
2695
|
+
return errorResult('SAPGit(action="stage") requires repoId.');
|
|
2696
|
+
const repo = await loadAbapGitRepo(client, repoId);
|
|
2697
|
+
result = await abapGitStageRepo(client.http, client.safety, repo);
|
|
2698
|
+
break;
|
|
2699
|
+
}
|
|
2700
|
+
case 'clone':
|
|
2701
|
+
if (!url)
|
|
2702
|
+
return errorResult('SAPGit(action="clone") requires url.');
|
|
2703
|
+
if (backend === 'gcts') {
|
|
2704
|
+
const params = {
|
|
2705
|
+
rid: repoId || undefined,
|
|
2706
|
+
name: repoId || undefined,
|
|
2707
|
+
url,
|
|
2708
|
+
...(packageName ? { package: packageName } : {}),
|
|
2709
|
+
user,
|
|
2710
|
+
password,
|
|
2711
|
+
token,
|
|
2712
|
+
};
|
|
2713
|
+
result = await gctsCloneRepo(client.http, client.safety, params);
|
|
2714
|
+
}
|
|
2715
|
+
else {
|
|
2716
|
+
if (!packageName)
|
|
2717
|
+
return errorResult('SAPGit(action="clone", backend="abapgit") requires package.');
|
|
2718
|
+
result = await abapGitCreateRepo(client.http, client.safety, {
|
|
2719
|
+
package: packageName,
|
|
2720
|
+
url,
|
|
2721
|
+
branchName: branch || undefined,
|
|
2722
|
+
transportRequest: String(args.transport ?? '').trim() || undefined,
|
|
2723
|
+
user,
|
|
2724
|
+
password,
|
|
2725
|
+
});
|
|
2726
|
+
}
|
|
2727
|
+
break;
|
|
2728
|
+
case 'pull':
|
|
2729
|
+
if (!repoId)
|
|
2730
|
+
return errorResult('SAPGit(action="pull") requires repoId.');
|
|
2731
|
+
if (backend === 'gcts') {
|
|
2732
|
+
result = await gctsPullRepo(client.http, client.safety, repoId, String(args.commit ?? '').trim() || undefined);
|
|
2733
|
+
}
|
|
2734
|
+
else {
|
|
2735
|
+
result = await abapGitPullRepo(client.http, client.safety, repoId, {
|
|
2736
|
+
...(packageName ? { package: packageName } : {}),
|
|
2737
|
+
...(url ? { url } : {}),
|
|
2738
|
+
...(branch ? { branchName: branch } : {}),
|
|
2739
|
+
transportRequest: String(args.transport ?? '').trim() || undefined,
|
|
2740
|
+
user,
|
|
2741
|
+
password,
|
|
2742
|
+
});
|
|
2743
|
+
}
|
|
2744
|
+
break;
|
|
2745
|
+
case 'push': {
|
|
2746
|
+
if (!repoId)
|
|
2747
|
+
return errorResult('SAPGit(action="push") requires repoId.');
|
|
2748
|
+
const repo = await loadAbapGitRepo(client, repoId);
|
|
2749
|
+
const staging = Array.isArray(args.objects) && args.objects.length > 0
|
|
2750
|
+
? { repoKey: repo.key, branchName: repo.branchName, objects: args.objects }
|
|
2751
|
+
: await abapGitStageRepo(client.http, client.safety, repo);
|
|
2752
|
+
await abapGitPushRepo(client.http, client.safety, repo, staging);
|
|
2753
|
+
result = { ok: true };
|
|
2754
|
+
break;
|
|
2755
|
+
}
|
|
2756
|
+
case 'commit':
|
|
2757
|
+
if (!repoId)
|
|
2758
|
+
return errorResult('SAPGit(action="commit") requires repoId.');
|
|
2759
|
+
result = await gctsCommitRepo(client.http, client.safety, repoId, {
|
|
2760
|
+
message: String(args.message ?? '').trim() || undefined,
|
|
2761
|
+
description: String(args.description ?? '').trim() || undefined,
|
|
2762
|
+
objects: Array.isArray(args.objects) ? args.objects : undefined,
|
|
2763
|
+
});
|
|
2764
|
+
break;
|
|
2765
|
+
case 'switch_branch':
|
|
2766
|
+
if (!repoId || !branch)
|
|
2767
|
+
return errorResult('SAPGit(action="switch_branch") requires repoId and branch.');
|
|
2768
|
+
if (backend === 'gcts') {
|
|
2769
|
+
result = await gctsSwitchBranch(client.http, client.safety, repoId, branch);
|
|
2770
|
+
}
|
|
2771
|
+
else {
|
|
2772
|
+
await abapGitSwitchBranch(client.http, client.safety, repoId, branch, false);
|
|
2773
|
+
result = { ok: true };
|
|
2774
|
+
}
|
|
2775
|
+
break;
|
|
2776
|
+
case 'create_branch':
|
|
2777
|
+
if (!repoId || !branch)
|
|
2778
|
+
return errorResult('SAPGit(action="create_branch") requires repoId and branch.');
|
|
2779
|
+
if (backend === 'gcts') {
|
|
2780
|
+
result = await gctsCreateBranch(client.http, client.safety, repoId, {
|
|
2781
|
+
branch,
|
|
2782
|
+
...(packageName ? { package: packageName } : {}),
|
|
2783
|
+
});
|
|
2784
|
+
}
|
|
2785
|
+
else {
|
|
2786
|
+
await abapGitCreateBranch(client.http, client.safety, repoId, branch);
|
|
2787
|
+
result = { ok: true };
|
|
2788
|
+
}
|
|
2789
|
+
break;
|
|
2790
|
+
case 'unlink':
|
|
2791
|
+
if (!repoId)
|
|
2792
|
+
return errorResult('SAPGit(action="unlink") requires repoId.');
|
|
2793
|
+
if (backend === 'gcts') {
|
|
2794
|
+
await gctsDeleteRepo(client.http, client.safety, repoId);
|
|
2795
|
+
}
|
|
2796
|
+
else {
|
|
2797
|
+
await abapGitUnlinkRepo(client.http, client.safety, repoId);
|
|
2798
|
+
}
|
|
2799
|
+
result = { ok: true };
|
|
2800
|
+
break;
|
|
2801
|
+
default:
|
|
2802
|
+
return errorResult(`Unknown SAPGit action: ${action}`);
|
|
2803
|
+
}
|
|
2804
|
+
const payload = backend === 'gcts' || backend === 'abapgit' ? { backend, result } : result;
|
|
2805
|
+
return textResult(JSON.stringify(payload, null, 2));
|
|
2806
|
+
}
|
|
2572
2807
|
// ─── SAPTransport Handler ────────────────────────────────────────────
|
|
2573
2808
|
async function handleSAPTransport(client, args) {
|
|
2574
2809
|
const action = String(args.action ?? '');
|