@cspeach/cli 1.1.2 → 1.1.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.
Files changed (45) hide show
  1. package/dist/agent/loop.js +31 -4
  2. package/dist/agent/session-context.js +24 -0
  3. package/dist/agent/tool-dispatch.js +17 -1
  4. package/dist/cli-args.js +24 -0
  5. package/dist/cli.js +33 -4
  6. package/dist/commands/config-set.js +155 -4
  7. package/dist/commands/cost.js +56 -4
  8. package/dist/commands/export-audit.js +4 -1
  9. package/dist/commands/plan-chain.js +8 -1
  10. package/dist/config/loader.js +44 -0
  11. package/dist/cost/cost-log.js +6 -1
  12. package/dist/cost/credits-wire.js +101 -0
  13. package/dist/cost/credits.js +199 -0
  14. package/dist/cost/display-mode.js +29 -0
  15. package/dist/cost/pricing.js +4 -0
  16. package/dist/doctor/checks/_standalone-skip.js +37 -0
  17. package/dist/doctor/checks/cert.js +5 -0
  18. package/dist/doctor/checks/credits.js +48 -0
  19. package/dist/doctor/checks/forge-rules.js +6 -0
  20. package/dist/doctor/checks/sap.js +5 -0
  21. package/dist/doctor/checks/standards.js +27 -0
  22. package/dist/doctor/checks/system-roles.js +5 -0
  23. package/dist/doctor/checks/zcspeach.js +5 -0
  24. package/dist/doctor/run.js +4 -0
  25. package/dist/one-shot.js +43 -11
  26. package/dist/renderer/status-footer.js +13 -3
  27. package/dist/repl/post-turn-status.js +5 -0
  28. package/dist/repl/session-spend-line.js +20 -0
  29. package/dist/repl.js +48 -9
  30. package/dist/sap/offline-adt-client.js +58 -0
  31. package/dist/sap/standalone-onboarding.js +118 -0
  32. package/dist/sap/standalone-profile.js +237 -0
  33. package/dist/session/audit-export.js +23 -4
  34. package/dist/standards/standards-file.js +107 -0
  35. package/dist/standards/standards-init.js +194 -0
  36. package/dist/tools/capability/tool.js +2 -0
  37. package/dist/tools/index.js +25 -0
  38. package/dist/tools/sap-read.js +18 -0
  39. package/dist/tools/sap-write.js +14 -0
  40. package/dist/tools/snapshot.js +3 -0
  41. package/dist/tools/transport.js +4 -0
  42. package/dist/ui/header.js +3 -1
  43. package/dist/ui/sap-state-store.js +4 -0
  44. package/dist/ui/status-line.js +20 -1
  45. package/package.json +109 -109
@@ -36,6 +36,7 @@ registerTool({
36
36
  + 'created object with NO active version yet, the inactive (working) '
37
37
  + 'source is returned with version="inactive" and an honest note.',
38
38
  isMutating: false,
39
+ requiresSap: true,
39
40
  input_schema: {
40
41
  type: 'object',
41
42
  properties: {
@@ -130,6 +131,7 @@ registerTool({
130
131
  name: 'sap_object_structure',
131
132
  description: 'Retrieve metadata and structural information for an ABAP repository object (package, description, lock state, etc.).',
132
133
  isMutating: false,
134
+ requiresSap: true,
133
135
  input_schema: {
134
136
  type: 'object',
135
137
  properties: {
@@ -165,6 +167,7 @@ registerTool({
165
167
  name: 'sap_search_object',
166
168
  description: 'Search the SAP repository by object name pattern. Supports wildcard * (e.g. ZCL_ORDER*).',
167
169
  isMutating: false,
170
+ requiresSap: true,
168
171
  input_schema: {
169
172
  type: 'object',
170
173
  properties: {
@@ -192,6 +195,7 @@ registerTool({
192
195
  name: 'sap_change_log',
193
196
  description: 'Retrieve the version history (change log) of an ABAP object — date, author, description per revision.',
194
197
  isMutating: false,
198
+ requiresSap: true,
195
199
  input_schema: {
196
200
  type: 'object',
197
201
  properties: {
@@ -214,6 +218,7 @@ registerTool({
214
218
  + 'Dialect limits (violations return an opaque "SAP HTTP 400: sqlQuery"): no IN-lists and at most one LIKE per WHERE clause '
215
219
  + '(multi-OR LIKE chains are rejected) — use a single LIKE or split into separate queries.',
216
220
  isMutating: false,
221
+ requiresSap: true,
217
222
  input_schema: {
218
223
  type: 'object',
219
224
  properties: {
@@ -237,6 +242,7 @@ registerTool({
237
242
  + 'result includes a `coverage` line stating exactly which window was fetched — trust it '
238
243
  + 'over assumptions. With dumpId returns the full diagnostic detail.',
239
244
  isMutating: false,
245
+ requiresSap: true,
240
246
  input_schema: {
241
247
  type: 'object',
242
248
  properties: {
@@ -293,6 +299,7 @@ registerTool({
293
299
  name: 'sap_atc_run',
294
300
  description: 'Run ABAP Test Cockpit (ATC) checks on a specific object and return all findings.',
295
301
  isMutating: false,
302
+ requiresSap: true,
296
303
  input_schema: {
297
304
  type: 'object',
298
305
  properties: {
@@ -318,6 +325,7 @@ registerTool({
318
325
  name: 'sap_usage_references',
319
326
  description: 'Find all places where a given ABAP object is referenced (where-used list).',
320
327
  isMutating: false,
328
+ requiresSap: true,
321
329
  input_schema: {
322
330
  type: 'object',
323
331
  properties: {
@@ -339,6 +347,7 @@ registerTool({
339
347
  name: 'sap_api_state',
340
348
  description: 'Check the ABAP Cloud / clean-core release state of SAP objects. Pass comma-separated TYPE:NAME pairs, e.g. "CLAS:CL_GUI_ALV_GRID,FUNC:BAPI_SALESORDER_GETLIST".',
341
349
  isMutating: false,
350
+ requiresSap: true,
342
351
  input_schema: {
343
352
  type: 'object',
344
353
  properties: {
@@ -362,6 +371,7 @@ registerTool({
362
371
  name: 'sap_abap_docu',
363
372
  description: 'Retrieve official ABAP language documentation from the SAP system for a keyword, class, or function module.',
364
373
  isMutating: false,
374
+ requiresSap: true,
365
375
  input_schema: {
366
376
  type: 'object',
367
377
  properties: {
@@ -384,6 +394,7 @@ registerTool({
384
394
  name: 'sap_class_includes',
385
395
  description: 'List the includes of an ABAP class, or read one specific include source (testclasses, locals_def, locals_imp, macros).',
386
396
  isMutating: false,
397
+ requiresSap: true,
387
398
  input_schema: {
388
399
  type: 'object',
389
400
  properties: {
@@ -415,6 +426,7 @@ registerTool({
415
426
  name: 'sap_inactive_objects',
416
427
  description: 'List all ABAP objects that are currently inactive (not yet activated) in the system.',
417
428
  isMutating: false,
429
+ requiresSap: true,
418
430
  input_schema: {
419
431
  type: 'object',
420
432
  properties: {},
@@ -432,6 +444,7 @@ registerTool({
432
444
  name: 'sap_syntax_check',
433
445
  description: 'Run a syntax check on an ABAP object and return any errors or warnings without activating it.',
434
446
  isMutating: false,
447
+ requiresSap: true,
435
448
  input_schema: {
436
449
  type: 'object',
437
450
  properties: {
@@ -453,6 +466,7 @@ registerTool({
453
466
  name: 'sap_diff',
454
467
  description: 'Compute a unified diff for an ABAP object between two optional source strings; if omitted, diffs the current version against the previous from the change log.',
455
468
  isMutating: false,
469
+ requiresSap: true,
456
470
  input_schema: {
457
471
  type: 'object',
458
472
  properties: {
@@ -482,6 +496,7 @@ registerTool({
482
496
  name: 'sap_preview_change',
483
497
  description: 'Preview a proposed source change for an ABAP object as a unified diff without writing anything to the system.',
484
498
  isMutating: false,
499
+ requiresSap: true,
485
500
  input_schema: {
486
501
  type: 'object',
487
502
  properties: {
@@ -507,6 +522,7 @@ registerTool({
507
522
  name: 'sap_run_unit_test',
508
523
  description: 'Execute ABAP Unit tests for an object and return a structured pass/fail report with method-level results.',
509
524
  isMutating: false,
525
+ requiresSap: true,
510
526
  input_schema: {
511
527
  type: 'object',
512
528
  properties: {
@@ -553,6 +569,7 @@ registerTool({
553
569
  name: 'sap_odata_test',
554
570
  description: 'Test an OData service endpoint (V2 or V4). Fetches $metadata or reads an entity set and returns the real HTTP status, the request URL/Accept actually used, and the response body. Works on draft-enabled OData V4 RAP services: V4 is auto-detected from /odata4/ paths, $metadata gets an XML Accept, and data reads use a JSON Accept without the V2-only $format option. System query options ($metadata, $top, $filter, $select, $expand, $count) are preserved literally.',
555
571
  isMutating: false,
572
+ requiresSap: true,
556
573
  input_schema: {
557
574
  type: 'object',
558
575
  properties: {
@@ -593,6 +610,7 @@ registerTool({
593
610
  name: 'sap_badi_list',
594
611
  description: 'Search for BAdI definitions and enhancement spots by name pattern (supports * wildcard), with optional enhancement-spot drill-down.',
595
612
  isMutating: false,
613
+ requiresSap: true,
596
614
  input_schema: {
597
615
  type: 'object',
598
616
  properties: {
@@ -89,6 +89,7 @@ registerTool({
89
89
  + 'a single method body. For method-body-only edits use sap_update_method (Rule 7a). '
90
90
  + 'The transport auto-resolves to the owning request if the object is already locked.',
91
91
  isMutating: true,
92
+ requiresSap: true,
92
93
  input_schema: {
93
94
  type: 'object',
94
95
  properties: {
@@ -252,6 +253,7 @@ registerTool({
252
253
  + 'method_source must be the lines between METHOD x. and ENDMETHOD. (no wrappers). '
253
254
  + 'The transport auto-resolves to the owning request if the class is already locked.',
254
255
  isMutating: true,
256
+ requiresSap: true,
255
257
  input_schema: {
256
258
  type: 'object',
257
259
  properties: {
@@ -441,6 +443,7 @@ registerTool({
441
443
  + 'Post-check: confirms the object no longer exists. '
442
444
  + 'The transport auto-resolves to the owning request if the object is already locked.',
443
445
  isMutating: true,
446
+ requiresSap: true,
444
447
  input_schema: {
445
448
  type: 'object',
446
449
  properties: {
@@ -563,6 +566,7 @@ registerTool({
563
566
  + 'Requires approval_id. No snapshot needed (new object). '
564
567
  + 'Write source separately via sap_set_source, then call sap_activate.',
565
568
  isMutating: true,
569
+ requiresSap: true,
566
570
  input_schema: {
567
571
  type: 'object',
568
572
  properties: {
@@ -670,6 +674,7 @@ registerTool({
670
674
  + 'After writing, activate the class via sap_activate. '
671
675
  + 'The transport auto-resolves to the owning request if the class is already locked.',
672
676
  isMutating: true,
677
+ requiresSap: true,
673
678
  input_schema: {
674
679
  type: 'object',
675
680
  properties: {
@@ -792,6 +797,7 @@ registerTool({
792
797
  + 'Requires approval_id. No snapshot needed (new object). '
793
798
  + 'Use the domain in a data element via sap_create_data_element.',
794
799
  isMutating: true,
800
+ requiresSap: true,
795
801
  input_schema: {
796
802
  type: 'object',
797
803
  properties: {
@@ -926,6 +932,7 @@ registerTool({
926
932
  + 'activate and verify it. Requires approval_id. No snapshot needed (new object). '
927
933
  + 'Use the data element as a table/structure field type.',
928
934
  isMutating: true,
935
+ requiresSap: true,
929
936
  input_schema: {
930
937
  type: 'object',
931
938
  properties: {
@@ -1054,6 +1061,7 @@ registerTool({
1054
1061
  + 'sap_update_method / sap_create_object (Rule 10). '
1055
1062
  + 'Post-check: objects must no longer appear in the inactive-objects list.',
1056
1063
  isMutating: true,
1064
+ requiresSap: true,
1057
1065
  input_schema: {
1058
1066
  type: 'object',
1059
1067
  properties: {
@@ -1169,6 +1177,7 @@ registerTool({
1169
1177
  name: 'sap_lock',
1170
1178
  description: 'RARELY needed. Returns a lock handle but other write tools cannot consume it — sap_set_source / sap_update_method / sap_delete_object each acquire their OWN lock internally. Calling sap_lock as a recovery step after a write failure CREATES A STALE LOCK that blocks the next write attempt; do not do that. Only call this when you need to inspect lock state or hold a lock for a coordinated multi-step ABAP workbench operation outside of CSPeach.',
1171
1179
  isMutating: true,
1180
+ requiresSap: true,
1172
1181
  input_schema: {
1173
1182
  type: 'object',
1174
1183
  properties: {
@@ -1190,6 +1199,7 @@ registerTool({
1190
1199
  name: 'sap_unlock',
1191
1200
  description: 'Release an ADT edit lock on an ABAP object using the lockHandle from sap_lock.',
1192
1201
  isMutating: true,
1202
+ requiresSap: true,
1193
1203
  input_schema: {
1194
1204
  type: 'object',
1195
1205
  properties: {
@@ -1212,6 +1222,7 @@ registerTool({
1212
1222
  name: 'sap_service_binding_publish',
1213
1223
  description: 'Publish an ADT service binding so its OData endpoint becomes active and reachable.',
1214
1224
  isMutating: true,
1225
+ requiresSap: true,
1215
1226
  input_schema: {
1216
1227
  type: 'object',
1217
1228
  properties: {
@@ -1235,6 +1246,7 @@ registerTool({
1235
1246
  description: 'Unpublish an ADT service binding so its OData endpoint is removed. '
1236
1247
  + 'Required before deleting a published binding (SAP returns HTTP 412 "is published" otherwise).',
1237
1248
  isMutating: true,
1249
+ requiresSap: true,
1238
1250
  input_schema: {
1239
1251
  type: 'object',
1240
1252
  properties: {
@@ -1257,6 +1269,7 @@ registerTool({
1257
1269
  + 'Maintaining MSAG message-class entries via ADT requires XML message-class-format '
1258
1270
  + 'parsing not yet implemented in @cspeach/sap-client.',
1259
1271
  isMutating: true,
1272
+ requiresSap: true,
1260
1273
  input_schema: {
1261
1274
  type: 'object',
1262
1275
  properties: {
@@ -1287,6 +1300,7 @@ registerTool({
1287
1300
  + 'Writing NROB number-range intervals via ADT requires NR-object XML format '
1288
1301
  + 'not yet implemented in @cspeach/sap-client.',
1289
1302
  isMutating: true,
1303
+ requiresSap: true,
1290
1304
  input_schema: {
1291
1305
  type: 'object',
1292
1306
  properties: {
@@ -30,6 +30,9 @@ registerTool({
30
30
  name: 'sap_snapshot_take',
31
31
  description: "Take a snapshot of an object's current source before modification. Usually invoked automatically by the CLI before any write — rarely called directly by the model.",
32
32
  isMutating: false,
33
+ // Reads the live source via ctx.adt.getSource — the only snapshot tool that
34
+ // needs SAP. list / read / cleanup work purely on the local snapshot store.
35
+ requiresSap: true,
33
36
  input_schema: {
34
37
  type: 'object',
35
38
  properties: {
@@ -63,6 +63,7 @@ registerTool({
63
63
  + 'approval mismatch failure mode observed live 2026-05-07). '
64
64
  + 'Requires approval_id. Returns the transport number to use in subsequent writes.',
65
65
  isMutating: true,
66
+ requiresSap: true,
66
67
  input_schema: {
67
68
  type: 'object',
68
69
  properties: {
@@ -260,6 +261,7 @@ registerTool({
260
261
  + 'locked → use the returned owning transport; not locked → a new or '
261
262
  + 'existing transport may be used.',
262
263
  isMutating: false,
264
+ requiresSap: true,
263
265
  input_schema: {
264
266
  type: 'object',
265
267
  properties: {
@@ -330,6 +332,7 @@ registerTool({
330
332
  description: 'List SAP CTS transport requests. '
331
333
  + 'Optionally filter by owner (user) or status (modifiable | released).',
332
334
  isMutating: false,
335
+ requiresSap: true,
333
336
  input_schema: {
334
337
  type: 'object',
335
338
  properties: {
@@ -377,6 +380,7 @@ registerTool({
377
380
  + 'All objects must be syntax-clean and ATC-clean before releasing (Rule 9). '
378
381
  + 'Requires approval_id.',
379
382
  isMutating: true,
383
+ requiresSap: true,
380
384
  input_schema: {
381
385
  type: 'object',
382
386
  properties: {
package/dist/ui/header.js CHANGED
@@ -1,6 +1,7 @@
1
1
  import { jsxs as _jsxs, jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  import { Box, Text } from 'ink';
3
3
  import { useSapState } from './sap-state-store.js';
4
+ import { formatSpendSegment } from './status-line.js';
4
5
  import { CLI_VERSION } from '../lib/version.js';
5
6
  const PEACH = '#FFCBA4';
6
7
  /**
@@ -34,6 +35,7 @@ export function Header({ writeMode } = {}) {
34
35
  const tokDisplay = s.tokenUsageToday >= 1000
35
36
  ? `${(s.tokenUsageToday / 1000).toFixed(1)}k tok`
36
37
  : `${s.tokenUsageToday} tok`;
37
- const spendDisplay = `$${s.dollarSpendToday.toFixed(2)}`;
38
+ // Shared with <StatusLine /> so the credits/dollar switch has one home.
39
+ const spendDisplay = formatSpendSegment(s);
38
40
  return (_jsxs(Box, { borderStyle: "single", borderColor: "gray", paddingX: 1, children: [_jsxs(Text, { bold: true, color: PEACH, children: ["\uD83C\uDF51 CSPeach ", CLI_VERSION] }), _jsx(Text, { color: "gray", children: " \u2502 " }), _jsx(Text, { color: "cyan", children: s.system || 'no system' }), _jsx(Text, { color: "gray", children: " \u2502 " }), _jsx(Text, { color: "white", children: s.user || '—' }), _jsx(Text, { color: "gray", children: " \u2502 tr " }), _jsx(Text, { color: "yellow", children: s.transport ?? 'none' }), _jsx(Text, { color: "gray", children: " \u2502 " }), _jsx(Text, { color: "green", children: tokDisplay }), _jsx(Text, { color: "gray", children: " \u2502 " }), _jsx(Text, { color: "green", children: spendDisplay }), modeLabel && (_jsxs(_Fragment, { children: [_jsx(Text, { color: "gray", children: " \u2502 " }), _jsx(Text, { color: modeColor, bold: isAdvisory, children: modeLabel })] }))] }));
39
41
  }
@@ -15,6 +15,10 @@ const DEFAULT_STATE = {
15
15
  system: '', user: '', transport: null, locksHeld: [],
16
16
  tokenUsageToday: 0, dollarSpendToday: 0, dollarCap: 100, recentTurns: [],
17
17
  writeMode: null, lastWriteTransport: null,
18
+ // Credits default OFF: BYOK/local/ai-hub and any pre-resolution frame keep
19
+ // the dollar rendering. Only an explicit managed+metered resolution flips it.
20
+ creditsMode: false, creditsSessionTotal: 0, creditsBalance: null,
21
+ creditsUnitLabel: 'credits', creditsPending: false,
18
22
  };
19
23
  /**
20
24
  * Rate limiter: calls `fn` at most once every `minIntervalMs`. Trailing-only:
@@ -1,6 +1,21 @@
1
1
  import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { Text } from 'ink';
3
3
  import { useSapState } from './sap-state-store.js';
4
+ import { formatCredits, CREDITS_PENDING } from '../cost/credits.js';
5
+ /**
6
+ * The spend segment shared by <StatusLine /> and <Header />.
7
+ *
8
+ * Single home for the credits/dollar switch so the two chrome widgets can
9
+ * never drift apart — a drift here is exactly how our COGS would leak onto a
10
+ * managed customer's screen from one of them.
11
+ */
12
+ export function formatSpendSegment(s) {
13
+ if (!s.creditsMode)
14
+ return `$${s.dollarSpendToday.toFixed(2)}`;
15
+ if (s.creditsPending && s.creditsSessionTotal === 0)
16
+ return CREDITS_PENDING;
17
+ return formatCredits(s.creditsSessionTotal, s.creditsUnitLabel);
18
+ }
4
19
  /**
5
20
  * Persistent SAP statusline (UX Wave 1, Task 4) — Header reborn,
6
21
  * bottom-anchored. Single borderless line rendered between <TurnStatus />
@@ -25,7 +40,11 @@ const MODE_COLORS = {
25
40
  };
26
41
  export function StatusLine() {
27
42
  const s = useSapState();
28
- const spendDisplay = `$${s.dollarSpendToday.toFixed(2)}`;
43
+ // Credits mode (2026-09-16): a managed customer sees what THEY are charged.
44
+ // The segment keeps its meaning — "what this session has cost me" — so it
45
+ // carries the session credit total, not the balance (the balance has its
46
+ // own home in the post-turn receipt and `cspeach doctor`).
47
+ const spendDisplay = formatSpendSegment(s);
29
48
  // Wave1 live-fix (Bug 1) — one TRUNCATING <Text> instead of a <Box> of
30
49
  // sibling Texts. The statusline lives in the dynamic Ink frame, where a
31
50
  // row that soft-wraps in the terminal breaks log-update's logical-line
package/package.json CHANGED
@@ -1,109 +1,109 @@
1
- {
2
- "name": "@cspeach/cli",
3
- "version": "1.1.2",
4
- "description": "CSPeach — AI-assisted ABAP development CLI. Direct SAP access, 34 skills, safety gates.",
5
- "keywords": [
6
- "abap",
7
- "sap",
8
- "ai",
9
- "cli",
10
- "ai-assisted-development",
11
- "s4hana",
12
- "abap-development",
13
- "claude",
14
- "anthropic"
15
- ],
16
- "homepage": "https://cspeach.dev",
17
- "bugs": {
18
- "email": "laeeq.siddique@cremencing.com"
19
- },
20
- "author": "Laeeq Siddique (Cremencing Solutions)",
21
- "license": "SEE LICENSE IN LICENSE",
22
- "private": false,
23
- "publishConfig": {
24
- "access": "public"
25
- },
26
- "type": "module",
27
- "bin": {
28
- "cspeach": "dist/index.js"
29
- },
30
- "scripts": {
31
- "dev": "tsx src/index.ts",
32
- "prebuild": "tsx scripts/prebuild.ts",
33
- "build": "tsc && node scripts/make-bin-executable.js",
34
- "install:global": "tsx scripts/install-global.ts",
35
- "pretest": "tsx scripts/sync-signing-key.ts || node -e \"console.warn('WARN: sync-signing-key skipped — using stub')\"",
36
- "start": "node dist/index.js",
37
- "typecheck": "tsc --noEmit",
38
- "test": "vitest run",
39
- "test:watch": "vitest",
40
- "adt:smoke": "tsx scripts/adt-smoke.ts",
41
- "smoke:all": "pnpm zcspeach:smoke && pnpm adt:smoke",
42
- "zcspeach:smoke": "tsx scripts/zcspeach-smoke.ts",
43
- "bench:models": "tsx scripts/bench-models.ts",
44
- "bench:audit": "tsx scripts/bench-audit-task.ts",
45
- "fiori": "tsx src/tools/fiori/bin.ts",
46
- "prepare": "husky",
47
- "prepublishOnly": "node -e \"const d=(require('./package.json').dependencies||{})['@cspeach/sap-client']||''; if(d.startsWith('file:')||d.startsWith('link:')){console.error('publish blocked: @cspeach/sap-client is a local link ('+d+') — point it at the published version before npm publish'); process.exit(1)}\""
48
- },
49
- "engines": {
50
- "node": ">=20.0.0"
51
- },
52
- "dependencies": {
53
- "@anthropic-ai/sdk": "^0.90.0",
54
- "@cspeach/sap-client": "^0.1.11",
55
- "@iarna/toml": "^2.2.5",
56
- "@inkjs/ui": "^2.0.0",
57
- "@inquirer/prompts": "^7.0.0",
58
- "@noble/ed25519": "2.1.0",
59
- "@noble/hashes": "1.4.0",
60
- "@sap-ux/fe-fpm-writer": "0.43.7",
61
- "@sap-ux/fiori-elements-writer": "^3.0.39",
62
- "@sap-ux/fiori-freestyle-writer": "3.0.12",
63
- "chalk": "^5.3.0",
64
- "cli-highlight": "^2.1.11",
65
- "cli-table3": "^0.6.5",
66
- "clipboardy": "^5.3.1",
67
- "cross-spawn": "^7.0.6",
68
- "diff": "^9.0.0",
69
- "ejs": "3.1.10",
70
- "fuse.js": "^7.0.0",
71
- "ink": "^5.0.0",
72
- "ink-text-input": "^6.0.0",
73
- "jose": "^5.9.0",
74
- "keytar": "^7.9.0",
75
- "mammoth": "^1.8.0",
76
- "marked": "^11.2.0",
77
- "marked-terminal": "^6.2.0",
78
- "mem-fs": "2.1.0",
79
- "mem-fs-editor": "9.4.0",
80
- "node-machine-id": "^1.1.12",
81
- "openai": "4.67.3",
82
- "puppeteer-core": "24.10.2",
83
- "react": "^18.3.0",
84
- "turndown": "^7.2.0",
85
- "unpdf": "^0.12.1",
86
- "zod": "^3.23.0"
87
- },
88
- "devDependencies": {
89
- "@types/cross-spawn": "^6.0.6",
90
- "@types/diff": "^7.0.2",
91
- "@types/ejs": "^3.1.5",
92
- "@types/node": "^20.17.0",
93
- "@types/react": "^18.3.0",
94
- "@types/turndown": "^5.0.5",
95
- "docx": "^9.0.2",
96
- "husky": "^9.1.7",
97
- "ink-testing-library": "^4.0.0",
98
- "pdf-lib": "^1.17.1",
99
- "tsx": "^4.19.0",
100
- "typescript": "^5.7.0",
101
- "vitest": "^2.1.0"
102
- },
103
- "pnpm": {
104
- "onlyBuiltDependencies": [
105
- "keytar",
106
- "esbuild"
107
- ]
108
- }
109
- }
1
+ {
2
+ "name": "@cspeach/cli",
3
+ "version": "1.1.4",
4
+ "description": "CSPeach — AI-assisted ABAP development CLI. Direct SAP access, 34 skills, safety gates.",
5
+ "keywords": [
6
+ "abap",
7
+ "sap",
8
+ "ai",
9
+ "cli",
10
+ "ai-assisted-development",
11
+ "s4hana",
12
+ "abap-development",
13
+ "claude",
14
+ "anthropic"
15
+ ],
16
+ "homepage": "https://cspeach.dev",
17
+ "bugs": {
18
+ "email": "laeeq.siddique@cremencing.com"
19
+ },
20
+ "author": "Laeeq Siddique (Cremencing Solutions)",
21
+ "license": "SEE LICENSE IN LICENSE",
22
+ "private": false,
23
+ "publishConfig": {
24
+ "access": "public"
25
+ },
26
+ "type": "module",
27
+ "bin": {
28
+ "cspeach": "dist/index.js"
29
+ },
30
+ "scripts": {
31
+ "dev": "tsx src/index.ts",
32
+ "prebuild": "tsx scripts/prebuild.ts",
33
+ "build": "tsc && node scripts/make-bin-executable.js",
34
+ "install:global": "tsx scripts/install-global.ts",
35
+ "pretest": "tsx scripts/sync-signing-key.ts || node -e \"console.warn('WARN: sync-signing-key skipped — using stub')\"",
36
+ "start": "node dist/index.js",
37
+ "typecheck": "tsc --noEmit",
38
+ "test": "vitest run",
39
+ "test:watch": "vitest",
40
+ "adt:smoke": "tsx scripts/adt-smoke.ts",
41
+ "smoke:all": "pnpm zcspeach:smoke && pnpm adt:smoke",
42
+ "zcspeach:smoke": "tsx scripts/zcspeach-smoke.ts",
43
+ "bench:models": "tsx scripts/bench-models.ts",
44
+ "bench:audit": "tsx scripts/bench-audit-task.ts",
45
+ "fiori": "tsx src/tools/fiori/bin.ts",
46
+ "prepare": "husky",
47
+ "prepublishOnly": "node -e \"const d=(require('./package.json').dependencies||{})['@cspeach/sap-client']||''; if(d.startsWith('file:')||d.startsWith('link:')){console.error('publish blocked: @cspeach/sap-client is a local link ('+d+') — point it at the published version before npm publish'); process.exit(1)}\""
48
+ },
49
+ "engines": {
50
+ "node": ">=20.0.0"
51
+ },
52
+ "dependencies": {
53
+ "@anthropic-ai/sdk": "^0.90.0",
54
+ "@cspeach/sap-client": "^0.1.11",
55
+ "@iarna/toml": "^2.2.5",
56
+ "@inkjs/ui": "^2.0.0",
57
+ "@inquirer/prompts": "^7.0.0",
58
+ "@noble/ed25519": "2.1.0",
59
+ "@noble/hashes": "1.4.0",
60
+ "@sap-ux/fe-fpm-writer": "0.43.7",
61
+ "@sap-ux/fiori-elements-writer": "^3.0.39",
62
+ "@sap-ux/fiori-freestyle-writer": "3.0.12",
63
+ "chalk": "^5.3.0",
64
+ "cli-highlight": "^2.1.11",
65
+ "cli-table3": "^0.6.5",
66
+ "clipboardy": "^5.3.1",
67
+ "cross-spawn": "^7.0.6",
68
+ "diff": "^9.0.0",
69
+ "ejs": "3.1.10",
70
+ "fuse.js": "^7.0.0",
71
+ "ink": "^5.0.0",
72
+ "ink-text-input": "^6.0.0",
73
+ "jose": "^5.9.0",
74
+ "keytar": "^7.9.0",
75
+ "mammoth": "^1.8.0",
76
+ "marked": "^11.2.0",
77
+ "marked-terminal": "^6.2.0",
78
+ "mem-fs": "2.1.0",
79
+ "mem-fs-editor": "9.4.0",
80
+ "node-machine-id": "^1.1.12",
81
+ "openai": "4.67.3",
82
+ "puppeteer-core": "24.10.2",
83
+ "react": "^18.3.0",
84
+ "turndown": "^7.2.0",
85
+ "unpdf": "^0.12.1",
86
+ "zod": "^3.23.0"
87
+ },
88
+ "devDependencies": {
89
+ "@types/cross-spawn": "^6.0.6",
90
+ "@types/diff": "^7.0.2",
91
+ "@types/ejs": "^3.1.5",
92
+ "@types/node": "^20.17.0",
93
+ "@types/react": "^18.3.0",
94
+ "@types/turndown": "^5.0.5",
95
+ "docx": "^9.0.2",
96
+ "husky": "^9.1.7",
97
+ "ink-testing-library": "^4.0.0",
98
+ "pdf-lib": "^1.17.1",
99
+ "tsx": "^4.19.0",
100
+ "typescript": "^5.7.0",
101
+ "vitest": "^2.1.0"
102
+ },
103
+ "pnpm": {
104
+ "onlyBuiltDependencies": [
105
+ "keytar",
106
+ "esbuild"
107
+ ]
108
+ }
109
+ }