abapgit-agent 1.5.0 → 1.6.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 (117) hide show
  1. package/README.md +1 -0
  2. package/abap/guidelines/00_index.md +35 -0
  3. package/abap/guidelines/01_sql.md +72 -0
  4. package/abap/guidelines/02_exceptions.md +108 -0
  5. package/abap/guidelines/03_testing.md +252 -0
  6. package/abap/guidelines/04_cds.md +120 -0
  7. package/abap/guidelines/05_classes.md +50 -0
  8. package/abap/guidelines/06_objects.md +103 -0
  9. package/abap/guidelines/07_json.md +22 -0
  10. package/abap/guidelines/08_abapgit.md +193 -0
  11. package/bin/abapgit-agent +467 -30
  12. package/bin/abgagt +24 -0
  13. package/package.json +8 -2
  14. package/src/abap-client.js +65 -2
  15. package/src/agent.js +57 -3
  16. package/src/ref-search.js +989 -0
  17. package/.abapGitAgent.example +0 -11
  18. package/.github/workflows/release.yml +0 -60
  19. package/API.md +0 -710
  20. package/CLAUDE.md +0 -1058
  21. package/CLAUDE_MEM.md +0 -88
  22. package/ERROR_HANDLING.md +0 -30
  23. package/INSTALL.md +0 -155
  24. package/RELEASE_NOTES.md +0 -143
  25. package/abap/CLAUDE.md +0 -1010
  26. package/abap/copilot-instructions.md +0 -79
  27. package/abap/package.devc.xml +0 -10
  28. package/abap/zcl_abgagt_agent.clas.abap +0 -420
  29. package/abap/zcl_abgagt_agent.clas.xml +0 -15
  30. package/abap/zcl_abgagt_cmd_factory.clas.abap +0 -48
  31. package/abap/zcl_abgagt_cmd_factory.clas.xml +0 -15
  32. package/abap/zcl_abgagt_command_create.clas.abap +0 -95
  33. package/abap/zcl_abgagt_command_create.clas.xml +0 -15
  34. package/abap/zcl_abgagt_command_import.clas.abap +0 -138
  35. package/abap/zcl_abgagt_command_import.clas.xml +0 -15
  36. package/abap/zcl_abgagt_command_inspect.clas.abap +0 -456
  37. package/abap/zcl_abgagt_command_inspect.clas.testclasses.abap +0 -121
  38. package/abap/zcl_abgagt_command_inspect.clas.xml +0 -16
  39. package/abap/zcl_abgagt_command_preview.clas.abap +0 -386
  40. package/abap/zcl_abgagt_command_preview.clas.xml +0 -15
  41. package/abap/zcl_abgagt_command_pull.clas.abap +0 -80
  42. package/abap/zcl_abgagt_command_pull.clas.testclasses.abap +0 -87
  43. package/abap/zcl_abgagt_command_pull.clas.xml +0 -16
  44. package/abap/zcl_abgagt_command_tree.clas.abap +0 -237
  45. package/abap/zcl_abgagt_command_tree.clas.xml +0 -15
  46. package/abap/zcl_abgagt_command_unit.clas.abap +0 -297
  47. package/abap/zcl_abgagt_command_unit.clas.xml +0 -15
  48. package/abap/zcl_abgagt_command_view.clas.abap +0 -240
  49. package/abap/zcl_abgagt_command_view.clas.xml +0 -15
  50. package/abap/zcl_abgagt_resource_create.clas.abap +0 -71
  51. package/abap/zcl_abgagt_resource_create.clas.xml +0 -15
  52. package/abap/zcl_abgagt_resource_health.clas.abap +0 -25
  53. package/abap/zcl_abgagt_resource_health.clas.xml +0 -15
  54. package/abap/zcl_abgagt_resource_import.clas.abap +0 -66
  55. package/abap/zcl_abgagt_resource_import.clas.xml +0 -15
  56. package/abap/zcl_abgagt_resource_inspect.clas.abap +0 -63
  57. package/abap/zcl_abgagt_resource_inspect.clas.xml +0 -15
  58. package/abap/zcl_abgagt_resource_preview.clas.abap +0 -67
  59. package/abap/zcl_abgagt_resource_preview.clas.xml +0 -15
  60. package/abap/zcl_abgagt_resource_pull.clas.abap +0 -71
  61. package/abap/zcl_abgagt_resource_pull.clas.xml +0 -15
  62. package/abap/zcl_abgagt_resource_tree.clas.abap +0 -70
  63. package/abap/zcl_abgagt_resource_tree.clas.xml +0 -15
  64. package/abap/zcl_abgagt_resource_unit.clas.abap +0 -64
  65. package/abap/zcl_abgagt_resource_unit.clas.xml +0 -15
  66. package/abap/zcl_abgagt_resource_view.clas.abap +0 -68
  67. package/abap/zcl_abgagt_resource_view.clas.xml +0 -15
  68. package/abap/zcl_abgagt_rest_handler.clas.abap +0 -32
  69. package/abap/zcl_abgagt_rest_handler.clas.xml +0 -15
  70. package/abap/zcl_abgagt_util.clas.abap +0 -93
  71. package/abap/zcl_abgagt_util.clas.testclasses.abap +0 -84
  72. package/abap/zcl_abgagt_util.clas.xml +0 -16
  73. package/abap/zcl_abgagt_viewer_clas.clas.abap +0 -58
  74. package/abap/zcl_abgagt_viewer_clas.clas.xml +0 -15
  75. package/abap/zcl_abgagt_viewer_ddls.clas.abap +0 -83
  76. package/abap/zcl_abgagt_viewer_ddls.clas.xml +0 -15
  77. package/abap/zcl_abgagt_viewer_dtel.clas.abap +0 -98
  78. package/abap/zcl_abgagt_viewer_dtel.clas.xml +0 -15
  79. package/abap/zcl_abgagt_viewer_factory.clas.abap +0 -41
  80. package/abap/zcl_abgagt_viewer_factory.clas.xml +0 -15
  81. package/abap/zcl_abgagt_viewer_intf.clas.abap +0 -58
  82. package/abap/zcl_abgagt_viewer_intf.clas.xml +0 -15
  83. package/abap/zcl_abgagt_viewer_stru.clas.abap +0 -59
  84. package/abap/zcl_abgagt_viewer_stru.clas.xml +0 -15
  85. package/abap/zcl_abgagt_viewer_tabl.clas.abap +0 -59
  86. package/abap/zcl_abgagt_viewer_tabl.clas.xml +0 -15
  87. package/abap/zcl_abgagt_viewer_ttyp.clas.abap +0 -93
  88. package/abap/zcl_abgagt_viewer_ttyp.clas.xml +0 -15
  89. package/abap/zif_abgagt_agent.intf.abap +0 -53
  90. package/abap/zif_abgagt_agent.intf.xml +0 -15
  91. package/abap/zif_abgagt_cmd_factory.intf.abap +0 -7
  92. package/abap/zif_abgagt_cmd_factory.intf.xml +0 -15
  93. package/abap/zif_abgagt_command.intf.abap +0 -26
  94. package/abap/zif_abgagt_command.intf.xml +0 -15
  95. package/abap/zif_abgagt_util.intf.abap +0 -28
  96. package/abap/zif_abgagt_util.intf.xml +0 -15
  97. package/abap/zif_abgagt_viewer.intf.abap +0 -12
  98. package/abap/zif_abgagt_viewer.intf.xml +0 -15
  99. package/docs/commands.md +0 -142
  100. package/docs/create-command.md +0 -129
  101. package/docs/health-command.md +0 -89
  102. package/docs/import-command.md +0 -195
  103. package/docs/init-command.md +0 -189
  104. package/docs/inspect-command.md +0 -169
  105. package/docs/list-command.md +0 -289
  106. package/docs/preview-command.md +0 -528
  107. package/docs/pull-command.md +0 -202
  108. package/docs/status-command.md +0 -68
  109. package/docs/tree-command.md +0 -303
  110. package/docs/unit-command.md +0 -167
  111. package/docs/view-command.md +0 -501
  112. package/img/claude.png +0 -0
  113. package/scripts/claude-integration.js +0 -351
  114. package/scripts/release.js +0 -298
  115. package/scripts/release.sh +0 -60
  116. package/scripts/test-integration.js +0 -139
  117. package/scripts/unrelease.js +0 -277
package/bin/abapgit-agent CHANGED
@@ -3,7 +3,8 @@
3
3
  * ABAP Git Agent - CLI Tool
4
4
  *
5
5
  * Usage:
6
- * abapgit-agent init --folder <folder> --package <package>
6
+ * abapgit-agent init --folder <folder> --package <package> # Initialize: copies config, CLAUDE.md, guidelines
7
+ * abapgit-agent init --update # Update existing files to latest version
7
8
  * abapgit-agent create
8
9
  * abapgit-agent import [--message <message>]
9
10
  * abapgit-agent pull [--branch <branch>]
@@ -23,6 +24,27 @@ const TERM_WIDTH = getTermWidth();
23
24
 
24
25
  const COOKIE_FILE = '.abapgit_agent_cookies.txt';
25
26
 
27
+ /**
28
+ * Convert ISO date formats (YYYY-MM-DD) to ABAP DATS format (YYYYMMDD) in WHERE clause
29
+ * This allows users to use familiar ISO date formats while ensuring compatibility with ABAP SQL
30
+ * @param {string} whereClause - SQL WHERE clause
31
+ * @returns {string} - WHERE clause with dates converted to YYYYMMDD format
32
+ */
33
+ function convertDatesInWhereClause(whereClause) {
34
+ if (!whereClause) return whereClause;
35
+
36
+ // Pattern to match ISO date format: 'YYYY-MM-DD'
37
+ const isoDatePattern = /'\d{4}-\d{2}-\d{2}'/g;
38
+
39
+ return whereClause.replace(isoDatePattern, (match) => {
40
+ // Extract YYYY, MM, DD from 'YYYY-MM-DD'
41
+ const dateContent = match.slice(1, -1); // Remove quotes: YYYY-MM-DD
42
+ const [year, month, day] = dateContent.split('-');
43
+ // Return in ABAP format: 'YYYYMMDD'
44
+ return `'${year}${month}${day}'`;
45
+ });
46
+ }
47
+
26
48
  /**
27
49
  * Get CLI version from package.json
28
50
  */
@@ -706,11 +728,11 @@ async function runUnitTestForFile(sourceFile, csrfToken, config) {
706
728
  /**
707
729
  * Run tree command and return raw result
708
730
  */
709
- async function runTreeCommand(packageName, depth, includeObjects, csrfToken, config) {
731
+ async function runTreeCommand(packageName, depth, includeTypes, csrfToken, config) {
710
732
  const data = {
711
733
  package: packageName,
712
734
  depth: depth,
713
- include_objects: includeObjects
735
+ include_objects: includeTypes
714
736
  };
715
737
 
716
738
  return await request('POST', '/sap/bc/z_abapgit_agent/tree', data, { csrfToken });
@@ -719,13 +741,13 @@ async function runTreeCommand(packageName, depth, includeObjects, csrfToken, con
719
741
  /**
720
742
  * Display tree output in human-readable format
721
743
  */
722
- async function displayTreeOutput(packageName, depth, includeObjects) {
744
+ async function displayTreeOutput(packageName, depth, includeTypes) {
723
745
  const config = loadConfig();
724
746
  const csrfToken = await fetchCsrfToken(config);
725
747
 
726
748
  console.log(`\n Getting package tree for: ${packageName}`);
727
749
 
728
- const result = await runTreeCommand(packageName, depth, includeObjects, csrfToken, config);
750
+ const result = await runTreeCommand(packageName, depth, includeTypes, csrfToken, config);
729
751
 
730
752
  // Handle uppercase keys from ABAP
731
753
  const success = result.SUCCESS || result.success;
@@ -765,7 +787,7 @@ async function displayTreeOutput(packageName, depth, includeObjects) {
765
787
  console.log(` OBJECTS: ${totalObjects}`);
766
788
 
767
789
  // Display object types if available
768
- if (includeObjects && objectTypes.length > 0) {
790
+ if (includeTypes && objectTypes.length > 0) {
769
791
  const typeStr = objectTypes.map(t => `${t.OBJECT || t.object}=${t.COUNT || t.count}`).join(' ');
770
792
  console.log(` TYPES: ${typeStr}`);
771
793
  }
@@ -1068,12 +1090,86 @@ async function pull(gitUrl, branch = 'main', files = null, transportRequest = nu
1068
1090
  }
1069
1091
  }
1070
1092
 
1093
+ /**
1094
+ * Copy a file if source exists (helper for init --update)
1095
+ * @param {string} srcPath - Source file path
1096
+ * @param {string} destPath - Destination file path
1097
+ * @param {string} label - Label for console output
1098
+ * @param {boolean} createParentDir - Whether to create parent directory
1099
+ * @returns {Promise<void>}
1100
+ */
1101
+ async function copyFileIfExists(srcPath, destPath, label, createParentDir = false) {
1102
+ try {
1103
+ if (fs.existsSync(srcPath)) {
1104
+ if (createParentDir) {
1105
+ const parentDir = pathModule.dirname(destPath);
1106
+ if (!fs.existsSync(parentDir)) {
1107
+ fs.mkdirSync(parentDir, { recursive: true });
1108
+ }
1109
+ }
1110
+ fs.copyFileSync(srcPath, destPath);
1111
+ console.log(`✅ Updated ${label}`);
1112
+ } else {
1113
+ console.log(`⚠️ ${label} not found in abapgit-agent`);
1114
+ }
1115
+ } catch (error) {
1116
+ console.error(`Error copying ${label}: ${error.message}`);
1117
+ }
1118
+ }
1119
+
1120
+ /**
1121
+ * Copy guidelines folder (helper for init --update)
1122
+ * @param {string} srcPath - Source folder path
1123
+ * @param {string} destPath - Destination folder path
1124
+ * @param {boolean} overwrite - Whether to overwrite existing files
1125
+ * @returns {Promise<void>}
1126
+ */
1127
+ async function copyGuidelinesFolder(srcPath, destPath, overwrite = false) {
1128
+ try {
1129
+ if (fs.existsSync(srcPath)) {
1130
+ // Create destination directory if needed
1131
+ if (!fs.existsSync(destPath)) {
1132
+ fs.mkdirSync(destPath, { recursive: true });
1133
+ }
1134
+
1135
+ const files = fs.readdirSync(srcPath);
1136
+ let copied = 0;
1137
+
1138
+ for (const file of files) {
1139
+ if (file.endsWith('.md')) {
1140
+ const srcFile = pathModule.join(srcPath, file);
1141
+ const destFile = pathModule.join(destPath, file);
1142
+
1143
+ // Skip if file exists and not overwriting
1144
+ if (fs.existsSync(destFile) && !overwrite) {
1145
+ continue;
1146
+ }
1147
+
1148
+ fs.copyFileSync(srcFile, destFile);
1149
+ copied++;
1150
+ }
1151
+ }
1152
+
1153
+ if (copied > 0) {
1154
+ console.log(`✅ Updated guidelines/ (${copied} files)`);
1155
+ } else {
1156
+ console.log(`⚠️ No guideline files found`);
1157
+ }
1158
+ } else {
1159
+ console.log(`⚠️ guidelines folder not found in abapgit-agent`);
1160
+ }
1161
+ } catch (error) {
1162
+ console.error(`Error copying guidelines: ${error.message}`);
1163
+ }
1164
+ }
1165
+
1071
1166
  /**
1072
1167
  * Run init command - Initialize local configuration
1073
1168
  */
1074
1169
  async function runInit(args) {
1075
1170
  const folderArgIndex = args.indexOf('--folder');
1076
1171
  const packageArgIndex = args.indexOf('--package');
1172
+ const updateMode = args.includes('--update');
1077
1173
 
1078
1174
  // Get parameters
1079
1175
  const folder = folderArgIndex !== -1 && folderArgIndex + 1 < args.length
@@ -1084,18 +1180,14 @@ async function runInit(args) {
1084
1180
  ? args[packageArgIndex + 1]
1085
1181
  : null;
1086
1182
 
1087
- // Validate package is required
1088
- if (!packageName) {
1183
+ // Validate package is required for non-update mode
1184
+ if (!updateMode && !packageName) {
1089
1185
  console.error('Error: --package is required');
1090
1186
  console.error('Usage: abapgit-agent init --folder /src --package ZMY_PACKAGE');
1187
+ console.error(' abapgit-agent init --update # Update files to latest version');
1091
1188
  process.exit(1);
1092
1189
  }
1093
1190
 
1094
- console.log(`\n🚀 Initializing abapGit Agent for local repository`);
1095
- console.log(` Folder: ${folder}`);
1096
- console.log(` Package: ${packageName}`);
1097
- console.log('');
1098
-
1099
1191
  // Check if current folder is git repo root
1100
1192
  const gitDir = pathModule.join(process.cwd(), '.git');
1101
1193
  if (!fs.existsSync(gitDir)) {
@@ -1104,6 +1196,53 @@ async function runInit(args) {
1104
1196
  process.exit(1);
1105
1197
  }
1106
1198
 
1199
+ // In update mode, just copy the files and return
1200
+ if (updateMode) {
1201
+ console.log(`\n🔄 Updating abapGit Agent files`);
1202
+ console.log('');
1203
+
1204
+ // Copy CLAUDE.md
1205
+ await copyFileIfExists(
1206
+ pathModule.join(__dirname, '..', 'abap', 'CLAUDE.md'),
1207
+ pathModule.join(process.cwd(), 'CLAUDE.md'),
1208
+ 'CLAUDE.md'
1209
+ );
1210
+
1211
+ // Copy copilot-instructions.md
1212
+ await copyFileIfExists(
1213
+ pathModule.join(__dirname, '..', 'abap', '.github', 'copilot-instructions.md'),
1214
+ pathModule.join(process.cwd(), '.github', 'copilot-instructions.md'),
1215
+ '.github/copilot-instructions.md',
1216
+ true // create parent dir
1217
+ );
1218
+
1219
+ // Copy guidelines folder to project root
1220
+ await copyGuidelinesFolder(
1221
+ pathModule.join(__dirname, '..', 'abap', 'guidelines'),
1222
+ pathModule.join(process.cwd(), 'guidelines'),
1223
+ true // overwrite
1224
+ );
1225
+
1226
+ console.log(`
1227
+ 📋 Update complete!
1228
+ Run 'abapgit-agent ref --list-topics' to see available topics.
1229
+ `);
1230
+ return;
1231
+ }
1232
+
1233
+ // Validate package is required
1234
+ if (!packageName) {
1235
+ console.error('Error: --package is required');
1236
+ console.error('Usage: abapgit-agent init --folder /src --package ZMY_PACKAGE');
1237
+ console.error(' abapgit-agent init --update # Update files to latest version');
1238
+ process.exit(1);
1239
+ }
1240
+
1241
+ console.log(`\n🚀 Initializing abapGit Agent for local repository`);
1242
+ console.log(` Folder: ${folder}`);
1243
+ console.log(` Package: ${packageName}`);
1244
+ console.log('');
1245
+
1107
1246
  // Detect git remote URL
1108
1247
  const gitUrl = getGitRemoteUrl();
1109
1248
  if (!gitUrl) {
@@ -1188,7 +1327,7 @@ async function runInit(args) {
1188
1327
  }
1189
1328
 
1190
1329
  // Copy copilot-instructions.md for GitHub Copilot
1191
- const copilotMdPath = pathModule.join(__dirname, '..', 'abap', 'copilot-instructions.md');
1330
+ const copilotMdPath = pathModule.join(__dirname, '..', 'abap', '.github', 'copilot-instructions.md');
1192
1331
  const githubDir = pathModule.join(process.cwd(), '.github');
1193
1332
  const localCopilotMdPath = pathModule.join(githubDir, 'copilot-instructions.md');
1194
1333
  try {
@@ -1206,6 +1345,35 @@ async function runInit(args) {
1206
1345
  console.error(`Error copying copilot-instructions.md: ${error.message}`);
1207
1346
  }
1208
1347
 
1348
+ // Copy guidelines folder to project root
1349
+ const guidelinesSrcPath = pathModule.join(__dirname, '..', 'abap', 'guidelines');
1350
+ const guidelinesDestPath = pathModule.join(process.cwd(), 'guidelines');
1351
+ try {
1352
+ if (fs.existsSync(guidelinesSrcPath)) {
1353
+ if (!fs.existsSync(guidelinesDestPath)) {
1354
+ // Create guidelines directory
1355
+ fs.mkdirSync(guidelinesDestPath, { recursive: true });
1356
+ // Copy all files from guidelines folder
1357
+ const files = fs.readdirSync(guidelinesSrcPath);
1358
+ for (const file of files) {
1359
+ if (file.endsWith('.md')) {
1360
+ fs.copyFileSync(
1361
+ pathModule.join(guidelinesSrcPath, file),
1362
+ pathModule.join(guidelinesDestPath, file)
1363
+ );
1364
+ }
1365
+ }
1366
+ console.log(`✅ Created guidelines/ (${files.filter(f => f.endsWith('.md')).length} files)`);
1367
+ } else {
1368
+ console.log(`⚠️ guidelines/ already exists, skipped`);
1369
+ }
1370
+ } else {
1371
+ console.log(`⚠️ guidelines folder not found in abap/ directory`);
1372
+ }
1373
+ } catch (error) {
1374
+ console.error(`Error copying guidelines: ${error.message}`);
1375
+ }
1376
+
1209
1377
  // Create folder
1210
1378
  const folderPath = pathModule.join(process.cwd(), folder);
1211
1379
  try {
@@ -1253,8 +1421,9 @@ async function main() {
1253
1421
  const command = args[0];
1254
1422
 
1255
1423
  // Check if ABAP integration is enabled for this repo
1256
- // (skip for init, help commands)
1257
- if (command && command !== 'init' && command !== 'help' && command !== '--help' && command !== '-h') {
1424
+ // (skip for init, help, ref commands - these don't need ABAP connection)
1425
+ const noAbapRequired = ['init', 'help', '--help', '-h', 'ref'];
1426
+ if (command && !noAbapRequired.includes(command)) {
1258
1427
  if (!isAbapIntegrationEnabled()) {
1259
1428
  console.log(`
1260
1429
  ⚠️ ABAP Git Agent not configured for this repository.
@@ -1278,7 +1447,7 @@ To enable integration:
1278
1447
  }
1279
1448
 
1280
1449
  // Version compatibility check for commands that interact with ABAP
1281
- const abapCommands = ['create', 'import', 'pull', 'inspect', 'unit', 'tree', 'view', 'preview'];
1450
+ const abapCommands = ['create', 'import', 'pull', 'inspect', 'unit', 'tree', 'view', 'preview', 'list'];
1282
1451
  if (command && abapCommands.includes(command)) {
1283
1452
  await checkVersionCompatibility();
1284
1453
  }
@@ -1581,7 +1750,7 @@ Examples:
1581
1750
  const packageArgIndex = args.indexOf('--package');
1582
1751
  if (packageArgIndex === -1) {
1583
1752
  console.error('Error: --package parameter required');
1584
- console.error('Usage: abapgit-agent tree --package <package> [--depth <n>] [--include-objects] [--json]');
1753
+ console.error('Usage: abapgit-agent tree --package <package> [--depth <n>] [--include-types] [--json]');
1585
1754
  console.error('Example: abapgit-agent tree --package ZMY_PACKAGE');
1586
1755
  process.exit(1);
1587
1756
  }
@@ -1595,7 +1764,7 @@ Examples:
1595
1764
  console.error(' or escape the $ character:');
1596
1765
  console.error(' abapgit-agent tree --package \\$ZMY_PACKAGE');
1597
1766
  console.error('');
1598
- console.error('Usage: abapgit-agent tree --package <package> [--depth <n>] [--include-objects] [--json]');
1767
+ console.error('Usage: abapgit-agent tree --package <package> [--depth <n>] [--include-types] [--json]');
1599
1768
  console.error('Example: abapgit-agent tree --package ZMY_PACKAGE');
1600
1769
  process.exit(1);
1601
1770
  }
@@ -1605,7 +1774,7 @@ Examples:
1605
1774
  // Check for empty/whitespace-only package name
1606
1775
  if (!packageName || packageName.trim() === '') {
1607
1776
  console.error('Error: --package parameter cannot be empty');
1608
- console.error('Usage: abapgit-agent tree --package <package> [--depth <n>] [--include-objects] [--json]');
1777
+ console.error('Usage: abapgit-agent tree --package <package> [--depth <n>] [--include-types] [--json]');
1609
1778
  console.error('Example: abapgit-agent tree --package ZMY_PACKAGE');
1610
1779
  process.exit(1);
1611
1780
  }
@@ -1621,8 +1790,8 @@ Examples:
1621
1790
  }
1622
1791
  }
1623
1792
 
1624
- // Optional include-objects parameter
1625
- const includeObjects = args.includes('--include-objects');
1793
+ // Optional include-types parameter (--include-objects is deprecated alias)
1794
+ const includeTypes = args.includes('--include-types') || args.includes('--include-objects');
1626
1795
 
1627
1796
  // Optional json parameter
1628
1797
  const jsonOutput = args.includes('--json');
@@ -1630,10 +1799,141 @@ Examples:
1630
1799
  if (jsonOutput) {
1631
1800
  const config = loadConfig();
1632
1801
  const csrfToken = await fetchCsrfToken(config);
1633
- const result = await runTreeCommand(packageName, depth, includeObjects, csrfToken, config);
1802
+ const result = await runTreeCommand(packageName, depth, includeTypes, csrfToken, config);
1634
1803
  console.log(JSON.stringify(result, null, 2));
1635
1804
  } else {
1636
- await displayTreeOutput(packageName, depth, includeObjects);
1805
+ await displayTreeOutput(packageName, depth, includeTypes);
1806
+ }
1807
+ break;
1808
+ }
1809
+
1810
+ case 'list': {
1811
+ const packageArgIndex = args.indexOf('--package');
1812
+ if (packageArgIndex === -1) {
1813
+ console.error('Error: --package parameter required');
1814
+ console.error('Usage: abapgit-agent list --package <package> [--type <types>] [--name <pattern>] [--limit <n>] [--offset <n>] [--json]');
1815
+ console.error('Example: abapgit-agent list --package $ZMY_PACKAGE');
1816
+ console.error('Example: abapgit-agent list --package $ZMY_PACKAGE --type CLAS,INTF');
1817
+ process.exit(1);
1818
+ }
1819
+
1820
+ // Check if package value is missing
1821
+ if (packageArgIndex + 1 >= args.length) {
1822
+ console.error('Error: --package parameter value is missing');
1823
+ process.exit(1);
1824
+ }
1825
+
1826
+ const packageName = args[packageArgIndex + 1];
1827
+
1828
+ // Validate package name
1829
+ if (!packageName || packageName.trim() === '') {
1830
+ console.error('Error: --package parameter cannot be empty');
1831
+ process.exit(1);
1832
+ }
1833
+
1834
+ // Optional type parameter
1835
+ const typeArgIndex = args.indexOf('--type');
1836
+ const type = typeArgIndex !== -1 && typeArgIndex + 1 < args.length ? args[typeArgIndex + 1] : null;
1837
+
1838
+ // Optional name pattern
1839
+ const nameArgIndex = args.indexOf('--name');
1840
+ const name = nameArgIndex !== -1 && nameArgIndex + 1 < args.length ? args[nameArgIndex + 1] : null;
1841
+
1842
+ // Optional limit
1843
+ const limitArgIndex = args.indexOf('--limit');
1844
+ let limit = 100;
1845
+ if (limitArgIndex !== -1 && limitArgIndex + 1 < args.length) {
1846
+ limit = parseInt(args[limitArgIndex + 1], 10);
1847
+ if (isNaN(limit) || limit < 1) {
1848
+ console.error('Error: --limit must be a positive number');
1849
+ process.exit(1);
1850
+ }
1851
+ if (limit > 1000) {
1852
+ console.error('Error: --limit value too high (max: 1000)');
1853
+ process.exit(1);
1854
+ }
1855
+ }
1856
+
1857
+ // Optional offset
1858
+ const offsetArgIndex = args.indexOf('--offset');
1859
+ let offset = 0;
1860
+ if (offsetArgIndex !== -1 && offsetArgIndex + 1 < args.length) {
1861
+ offset = parseInt(args[offsetArgIndex + 1], 10);
1862
+ if (isNaN(offset) || offset < 0) {
1863
+ console.error('Error: --offset must be a non-negative number');
1864
+ process.exit(1);
1865
+ }
1866
+ }
1867
+
1868
+ // Optional json parameter
1869
+ const jsonOutput = args.includes('--json');
1870
+
1871
+ const config = loadConfig();
1872
+ const csrfToken = await fetchCsrfToken(config);
1873
+
1874
+ const data = {
1875
+ package: packageName,
1876
+ limit: limit,
1877
+ offset: offset
1878
+ };
1879
+
1880
+ if (type) {
1881
+ data.type = type;
1882
+ }
1883
+
1884
+ if (name) {
1885
+ data.name = name;
1886
+ }
1887
+
1888
+ const result = await request('POST', '/sap/bc/z_abapgit_agent/list', data, { csrfToken });
1889
+
1890
+ // Handle uppercase keys from ABAP
1891
+ const success = result.SUCCESS || result.success;
1892
+ const error = result.ERROR || result.error;
1893
+ const objects = result.OBJECTS || result.objects || [];
1894
+ const byType = result.BY_TYPE || result.by_type || [];
1895
+ const total = result.TOTAL || result.total || 0;
1896
+
1897
+ if (!success || error) {
1898
+ console.error(`\n Error: ${error || 'Failed to list objects'}`);
1899
+ process.exit(1);
1900
+ }
1901
+
1902
+ if (jsonOutput) {
1903
+ console.log(JSON.stringify(result, null, 2));
1904
+ } else {
1905
+ // Display human-readable output
1906
+ let title = `Objects in ${packageName}`;
1907
+ if (type) {
1908
+ title += ` (${type} only`;
1909
+ if (total !== objects.length) {
1910
+ title += `, Total: ${total}`;
1911
+ }
1912
+ title += ')';
1913
+ } else if (total !== objects.length) {
1914
+ title += ` (Total: ${total})`;
1915
+ }
1916
+ console.log(`\n${title}\n`);
1917
+
1918
+ // Group objects by type
1919
+ const objectsByType = {};
1920
+ for (const obj of objects) {
1921
+ const objType = (obj.TYPE || obj.type || '???').toUpperCase();
1922
+ if (!objectsByType[objType]) {
1923
+ objectsByType[objType] = [];
1924
+ }
1925
+ objectsByType[objType].push(obj.NAME || obj.name);
1926
+ }
1927
+
1928
+ // Display grouped objects
1929
+ for (const objType of Object.keys(objectsByType).sort()) {
1930
+ const objNames = objectsByType[objType];
1931
+ console.log(` ${objType} (${objNames.length})`);
1932
+ for (const objName of objNames) {
1933
+ console.log(` ${objName}`);
1934
+ }
1935
+ console.log('');
1936
+ }
1637
1937
  }
1638
1938
  break;
1639
1939
  }
@@ -1881,7 +2181,7 @@ Examples:
1881
2181
  }
1882
2182
 
1883
2183
  if (where) {
1884
- data.where = where;
2184
+ data.where = convertDatesInWhereClause(where);
1885
2185
  }
1886
2186
 
1887
2187
  if (columns) {
@@ -2079,6 +2379,109 @@ Examples:
2079
2379
  break;
2080
2380
  }
2081
2381
 
2382
+ case 'ref': {
2383
+ const refSearch = require('../src/ref-search');
2384
+ const topicIndex = args.indexOf('--topic');
2385
+ const listTopics = args.includes('--list-topics') || args.includes('-l');
2386
+ const listRepos = args.includes('--list-repos') || args.includes('-r');
2387
+ const exportGuidelines = args.includes('--export') || args.includes('-e');
2388
+ const jsonOutput = args.includes('--json');
2389
+
2390
+ if (exportGuidelines) {
2391
+ const result = await refSearch.exportGuidelines();
2392
+ if (jsonOutput) {
2393
+ console.log(JSON.stringify(result, null, 2));
2394
+ } else {
2395
+ refSearch.displayExportResult(result);
2396
+ }
2397
+ break;
2398
+ }
2399
+
2400
+ if (listRepos) {
2401
+ const result = await refSearch.listRepositories();
2402
+ if (jsonOutput) {
2403
+ console.log(JSON.stringify(result, null, 2));
2404
+ } else {
2405
+ refSearch.displayRepositories(result);
2406
+ }
2407
+ break;
2408
+ }
2409
+
2410
+ if (listTopics) {
2411
+ const result = await refSearch.listTopics();
2412
+ if (jsonOutput) {
2413
+ console.log(JSON.stringify(result, null, 2));
2414
+ } else {
2415
+ refSearch.displayTopics(result);
2416
+ }
2417
+ break;
2418
+ }
2419
+
2420
+ if (topicIndex !== -1 && topicIndex + 1 < args.length) {
2421
+ const topic = args[topicIndex + 1];
2422
+ const result = await refSearch.getTopic(topic);
2423
+ if (jsonOutput) {
2424
+ console.log(JSON.stringify(result, null, 2));
2425
+ } else {
2426
+ refSearch.displayTopic(result);
2427
+ }
2428
+ break;
2429
+ }
2430
+
2431
+ // Pattern search (default)
2432
+ const patternIndex = args.findIndex((arg, idx) => idx > 0 && !arg.startsWith('--'));
2433
+ if (patternIndex === -1) {
2434
+ console.error('Error: No pattern specified');
2435
+ console.error('');
2436
+ console.error('Usage:');
2437
+ console.error(' abapgit-agent ref <pattern> Search for pattern');
2438
+ console.error(' abapgit-agent ref --topic <name> View specific topic');
2439
+ console.error(' abapgit-agent ref --list-topics List available topics');
2440
+ console.error(' abapgit-agent ref --list-repos List reference repositories');
2441
+ console.error(' abapgit-agent ref --export Export local guidelines to reference folder');
2442
+ console.error('');
2443
+ console.error('Examples:');
2444
+ console.error(' abapgit-agent ref "CORRESPONDING"');
2445
+ console.error(' abapgit-agent ref --topic exceptions');
2446
+ console.error(' abapgit-agent ref --list-topics');
2447
+ console.error(' abapgit-agent ref --list-repos');
2448
+ console.error(' abapgit-agent ref --export');
2449
+ process.exit(1);
2450
+ }
2451
+
2452
+ const pattern = args[patternIndex];
2453
+ const result = await refSearch.searchPattern(pattern);
2454
+
2455
+ // Also search guidelines if available
2456
+ const guidelinesResult = await refSearch.searchGuidelines(pattern);
2457
+ if (guidelinesResult && guidelinesResult.guidelinesFound && guidelinesResult.matches.length > 0) {
2458
+ result.guidelines = guidelinesResult;
2459
+ }
2460
+
2461
+ if (jsonOutput) {
2462
+ console.log(JSON.stringify(result, null, 2));
2463
+ } else {
2464
+ refSearch.displaySearchResults(result);
2465
+ // Display guidelines results if found
2466
+ if (guidelinesResult && guidelinesResult.guidelinesFound && guidelinesResult.matches.length > 0) {
2467
+ console.log('\n 📋 Custom Guidelines:');
2468
+ for (const match of guidelinesResult.matches.slice(0, 5)) {
2469
+ console.log(` 📄 ${match.file} (line ${match.line}):`);
2470
+ const lines = match.context.split('\n');
2471
+ lines.forEach((line, idx) => {
2472
+ const prefix = idx === 1 ? ' → ' : ' ';
2473
+ const trimmed = line.slice(0, 80);
2474
+ console.log(`${prefix}${trimmed}`);
2475
+ });
2476
+ }
2477
+ if (guidelinesResult.matches.length > 5) {
2478
+ console.log(` ... and ${guidelinesResult.matches.length - 5} more matches`);
2479
+ }
2480
+ }
2481
+ }
2482
+ break;
2483
+ }
2484
+
2082
2485
  case 'help':
2083
2486
  case '--help':
2084
2487
  case '-h':
@@ -2091,6 +2494,8 @@ Usage:
2091
2494
  Commands:
2092
2495
  init --folder <folder> --package <package>
2093
2496
  Initialize local configuration for an existing git repository.
2497
+ init --update
2498
+ Update existing files (CLAUDE.md, copilot-instructions.md, guidelines) to latest version.
2094
2499
 
2095
2500
  create
2096
2501
  Create abapGit online repository in ABAP system.
@@ -2112,12 +2517,30 @@ Commands:
2112
2517
  unit --files <file1>,<file2>,...
2113
2518
  Run AUnit tests for ABAP test class files (.testclasses.abap)
2114
2519
 
2115
- tree --package <package> [--depth <n>] [--include-objects] [--json]
2520
+ tree --package <package> [--depth <n>] [--include-types] [--json]
2116
2521
  Display package hierarchy tree from ABAP system
2117
2522
 
2523
+ list --package <package> [--type <types>] [--name <pattern>] [--limit <n>] [--offset <n>] [--json]
2524
+ List ABAP objects in a package with filtering and pagination
2525
+
2118
2526
  view --objects <obj1>,<obj2>,... [--type <type>] [--json]
2119
2527
  View ABAP object definitions from the ABAP system
2120
2528
 
2529
+ ref <pattern> [--json]
2530
+ Search ABAP reference repositories for patterns. Requires referenceFolder in .abapGitAgent.
2531
+
2532
+ ref --topic <topic> [--json]
2533
+ View specific topic from cheat sheets (exceptions, sql, unit-tests, etc.)
2534
+
2535
+ ref --list-topics
2536
+ List available topics for reference search
2537
+
2538
+ ref --list-repos
2539
+ List all reference repositories in the reference folder
2540
+
2541
+ ref --export
2542
+ Export custom guidelines (abap/guidelines/) to reference folder
2543
+
2121
2544
  health
2122
2545
  Check if ABAP REST API is healthy
2123
2546
 
@@ -2126,6 +2549,7 @@ Commands:
2126
2549
 
2127
2550
  Examples:
2128
2551
  abapgit-agent init --folder /src --package ZMY_PACKAGE # Initialize
2552
+ abapgit-agent init --update # Update files to latest
2129
2553
  abapgit-agent create # Create repo
2130
2554
  abapgit-agent import # Import objects to git
2131
2555
  abapgit-agent import --message "Initial import" # Import with message
@@ -2135,14 +2559,27 @@ Examples:
2135
2559
  abapgit-agent pull --transport DEVK900001 # With transport
2136
2560
  abapgit-agent inspect --files zcl_my_class.clas.abap # Syntax check
2137
2561
  abapgit-agent unit --files zcl_my_test.clas.testclasses.abap # Run tests
2138
- abapgit-agent tree --package $ZMY_PACKAGE # Show package tree
2139
- abapgit-agent tree --package $ZMY_PACKAGE --depth 2 # Shallow tree
2140
- abapgit-agent tree --package $ZMY_PACKAGE --include-objects # With object counts
2141
- abapgit-agent tree --package $ZMY_PACKAGE --json # JSON output
2562
+ abapgit-agent tree --package \$ZMY_PACKAGE # Show package tree
2563
+ abapgit-agent tree --package \$ZMY_PACKAGE --depth 2 # Shallow tree
2564
+ abapgit-agent tree --package \$ZMY_PACKAGE --include-types # With type counts
2565
+ abapgit-agent tree --package \$ZMY_PACKAGE --json # JSON output
2566
+ abapgit-agent list --package $ZMY_PACKAGE # List all objects
2567
+ abapgit-agent list --package $ZMY_PACKAGE --type CLAS,INTF # Filter by type
2568
+ abapgit-agent list --package $ZMY_PACKAGE --name ZCL_* # Filter by name
2569
+ abapgit-agent list --package $ZMY_PACKAGE --limit 50 # Limit results
2570
+ abapgit-agent list --package $ZMY_PACKAGE --json # JSON output
2142
2571
  abapgit-agent view --objects ZCL_MY_CLASS # View class definition
2143
2572
  abapgit-agent view --objects ZIF_MY_INTERFACE --type INTF # View interface
2144
2573
  abapgit-agent view --objects ZMY_TABLE --type TABL # View table structure
2145
2574
  abapgit-agent view --objects ZCL_CLASS1,ZCL_CLASS2 --json # Multiple objects
2575
+ abapgit-agent ref "CORRESPONDING" # Search all reference repos
2576
+ abapgit-agent ref "CX_SY_" # Search exceptions
2577
+ abapgit-agent ref --topic exceptions # View exception topic
2578
+ abapgit-agent ref --topic sql # View SQL topic
2579
+ abapgit-agent ref --topic unit-tests # View unit test topic
2580
+ abapgit-agent ref --list-topics # List all topics
2581
+ abapgit-agent ref --list-repos # List reference repositories
2582
+ abapgit-agent ref --export # Export custom guidelines
2146
2583
  abapgit-agent health
2147
2584
  abapgit-agent status
2148
2585
  `);