@cspeach/cli 1.1.31 → 1.1.33
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/agent/loop.js +16 -6
- package/dist/cli.js +13 -4
- package/dist/commands/cost.js +6 -2
- package/dist/commands/help.js +18 -2
- package/dist/commands/plan-chain.js +3 -0
- package/dist/commands/plan-gate.js +10 -1
- package/dist/commands/plan-resume.js +4 -0
- package/dist/commands/team-rules.js +187 -0
- package/dist/commands/team.js +632 -90
- package/dist/commands/usage.js +106 -0
- package/dist/cost/month-usage.js +45 -0
- package/dist/journey/chain.js +265 -15
- package/dist/journey/clean-core.js +25 -3
- package/dist/journey/flow.js +51 -1
- package/dist/journey/rebuild.js +464 -0
- package/dist/journey/run.js +213 -20
- package/dist/journey/session-deps.js +5 -1
- package/dist/lane/app-chain.js +12 -2
- package/dist/one-shot.js +24 -17
- package/dist/projects/clean-core-confirm.js +38 -5
- package/dist/projects/save-command.js +20 -3
- package/dist/register/baseline.js +39 -2
- package/dist/register/decision-rules.js +35 -0
- package/dist/register/discover.js +49 -19
- package/dist/register/export-files.js +58 -0
- package/dist/register/measure.js +191 -9
- package/dist/register/plan-import.js +6 -3
- package/dist/register/records.js +15 -3
- package/dist/register/rule-proposal.js +4 -0
- package/dist/register/rules-edit.js +257 -0
- package/dist/register/status-file/register-status-file.js +106 -108
- package/dist/register/status-file/report-model.js +569 -0
- package/dist/register/status-file/team-css.js +1 -1
- package/dist/register/status-file-sync.js +1 -0
- package/dist/register/status-html.js +25 -6
- package/dist/register/store.js +4 -3
- package/dist/register/variant.js +65 -0
- package/dist/register/workbooks.js +22 -56
- package/dist/register/write-whole.js +30 -2
- package/dist/renderer/tool-labels.js +2 -1
- package/dist/repl/builtin-commands.js +7 -0
- package/dist/repl/journey-entry.js +4 -2
- package/dist/repl/plan-hop.js +2 -9
- package/dist/repl/rules-menu.js +177 -0
- package/dist/repl/slash-completer.js +2 -0
- package/dist/repl/slash-picker.js +5 -4
- package/dist/repl.js +157 -86
- package/dist/router/classifier.js +8 -4
- package/dist/router/router-core.js +43 -7
- package/dist/router/routing-decision.js +1 -1
- package/dist/runs/bundled-runs.js +100 -0
- package/dist/runs/front-door.js +19 -0
- package/dist/runs/manifest-runs.js +50 -0
- package/dist/runs/run-command.js +24 -0
- package/dist/runs/runs.js +27 -0
- package/dist/runs/shadow.js +100 -0
- package/dist/runs/types.js +1 -0
- package/dist/session/queued-step.js +45 -0
- package/dist/skills/bundled-skills.js +53 -53
- package/dist/tools/dispatch-skill.js +8 -4
- package/dist/tools/lane/app-lane-resolve.js +1 -1
- package/dist/tools/project/rules_propose.js +59 -0
- package/dist/tools/project/team_findings.js +13 -2
- package/dist/upgrade-check.js +49 -4
- package/package.json +120 -120
- package/.cspeach/project.json +0 -4
|
@@ -15,8 +15,9 @@
|
|
|
15
15
|
* user's keypress to make.
|
|
16
16
|
* - The command argument MUST start with a known slash route. Free
|
|
17
17
|
* text without a leading `/` is rejected.
|
|
18
|
-
* - Set the slot via ctx.pendingDispatch.set(command).
|
|
19
|
-
* it after runTurn and routes as the next submission
|
|
18
|
+
* - Set the slot via ctx.pendingDispatch.set(command, { by: 'switch', … }).
|
|
19
|
+
* repl.tsx reads it after runTurn and routes it as the next submission,
|
|
20
|
+
* shown as "Auto-routed: <command>" — never as the person's own line.
|
|
20
21
|
* - Skill ends the turn naturally after this tool call. Do not also
|
|
21
22
|
* emit a "Type X at the next prompt" hint — the dispatch supersedes it.
|
|
22
23
|
*
|
|
@@ -32,7 +33,7 @@
|
|
|
32
33
|
* for every other dispatch (e.g. /abap-generate → /abap-rap switch).
|
|
33
34
|
*/
|
|
34
35
|
import { registerTool } from './index.js';
|
|
35
|
-
import { isPlanResumeCommand } from '../commands/plan-resume.js';
|
|
36
|
+
import { autoRoutedNotice, isPlanResumeCommand } from '../commands/plan-resume.js';
|
|
36
37
|
export const PLAN_RESUME_DISPATCH_REASON = 'Do not dispatch /abap-plan --resume. When your plan manifest is saved, CSPeach runs the next step itself with the exact saved file. Simply end the turn now.';
|
|
37
38
|
registerTool({
|
|
38
39
|
name: 'dispatch_skill',
|
|
@@ -91,7 +92,10 @@ registerTool({
|
|
|
91
92
|
}),
|
|
92
93
|
};
|
|
93
94
|
}
|
|
94
|
-
|
|
95
|
+
// Must-fix follow-up (b): the person agreed to the switch, but the model
|
|
96
|
+
// wrote the command, so it is never shown as theirs ("You › …"). Tagged
|
|
97
|
+
// `switch`, both REPLs show its one "Auto-routed:" line (queuedStepView).
|
|
98
|
+
ctx.pendingDispatch.set(command, { by: 'switch', line: autoRoutedNotice(command) ?? `Auto-routed: ${command}` });
|
|
95
99
|
return {
|
|
96
100
|
content: JSON.stringify({
|
|
97
101
|
ok: true,
|
|
@@ -284,7 +284,7 @@ export async function appLaneResolveHandler(args, ctx, deps = {}) {
|
|
|
284
284
|
ctx.chunkEmitter?.emit('info', `Lane chosen by the rules (no confirm card in this terminal): ${shown}.`);
|
|
285
285
|
}
|
|
286
286
|
if (flow?.specGapPath && planCmd) {
|
|
287
|
-
ctx.pendingDispatch?.set(planCmd);
|
|
287
|
+
ctx.pendingDispatch?.set(planCmd, { by: 'app' }); // audit M-2: CSPeach's step, never shown as typed
|
|
288
288
|
lines.push('Next: the plan is being created.');
|
|
289
289
|
}
|
|
290
290
|
else if (flow?.specGapPath && headless) {
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* rules_propose — read-only (step 2, Task 10, optional step; spec 2026-10-08 §7 D7).
|
|
3
|
+
*
|
|
4
|
+
* "Rule from words": the person says a rule in words, the model turns it into
|
|
5
|
+
* the decision-rule shape and calls this. Code checks it with register-core's
|
|
6
|
+
* strict reader against the team project's rules and says it back in plain
|
|
7
|
+
* words. Nothing is written: the proposal is kept in this process, and the
|
|
8
|
+
* person saves it from `/rules` (Add the proposed rule → card → Save), lead
|
|
9
|
+
* only. The model never writes the rules.
|
|
10
|
+
*/
|
|
11
|
+
import { readDecisionRules } from '@cspeach/register-core';
|
|
12
|
+
import { registerTool } from '../index.js';
|
|
13
|
+
import { activeProject, readProjectFile, RegisterError } from '../../register/store.js';
|
|
14
|
+
import { addProposed, ruleWords } from '../../register/rules-edit.js';
|
|
15
|
+
import { setRuleProposal } from '../../register/rule-proposal.js';
|
|
16
|
+
export async function rulesProposeHandler(args, _ctx) {
|
|
17
|
+
const joined = activeProject();
|
|
18
|
+
if (!joined)
|
|
19
|
+
return { content: 'This laptop has not joined a team project. The developer runs: cspeach team join <folder>', is_error: true };
|
|
20
|
+
try {
|
|
21
|
+
const project = readProjectFile(joined.projectDir);
|
|
22
|
+
const current = readDecisionRules(project);
|
|
23
|
+
if (current.warning)
|
|
24
|
+
return { content: `${current.warning} Nothing can be added until the file is fixed or the rules are restored (/rules → Restore defaults).`, is_error: true };
|
|
25
|
+
const edit = addProposed(current.rules, args.rule, { by: 'proposed', at: new Date(0).toISOString() });
|
|
26
|
+
const rule = edit.after;
|
|
27
|
+
const { id: _id, on: _on, changedBy: _by, changedAt: _at, ...proposal } = rule;
|
|
28
|
+
setRuleProposal({ projectId: joined.projectId, proposal, words: ruleWords(rule) });
|
|
29
|
+
return {
|
|
30
|
+
content: JSON.stringify({
|
|
31
|
+
ok: true, id: rule.id, words: ruleWords(rule), note: rule.note, saved: false,
|
|
32
|
+
next: 'Nothing is saved. Tell the person: open /rules and pick "Add the proposed rule"; it is saved only when they press Save (the lead only). New rules go last: the first rule that is on and holds decides.',
|
|
33
|
+
}),
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
catch (e) {
|
|
37
|
+
if (e instanceof RegisterError)
|
|
38
|
+
return { content: e.message, is_error: true };
|
|
39
|
+
throw e;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
registerTool({
|
|
43
|
+
name: 'rules_propose',
|
|
44
|
+
description: 'Read-only. Check a decision rule the person described in words, for the team project this laptop joined. '
|
|
45
|
+
+ 'Give it as { when: { types?, levelNow?, targetAtMost?, minFindings?, maxFindings?, findingClasses?, onlyClasses?, findingRules? (rule-id prefixes, e.g. SEARCH_PROBLEMATIC_STATEMENTS_FOR_ALV_CALLS), callers?, noOpenForTarget? }, '
|
|
46
|
+
+ 'then: { disposition: keep|fix|rebuild|retire-candidate, target? }, note }. Returns the rule in plain words or why it cannot be read. '
|
|
47
|
+
+ 'Never saves: the person saves it from /rules. No SAP call.',
|
|
48
|
+
isMutating: false,
|
|
49
|
+
category: 'project',
|
|
50
|
+
requiresSap: false,
|
|
51
|
+
input_schema: {
|
|
52
|
+
type: 'object',
|
|
53
|
+
properties: {
|
|
54
|
+
rule: { type: 'object', description: 'The proposed rule: { when, then, note }. Any id, on or changedBy given is ignored.' },
|
|
55
|
+
},
|
|
56
|
+
required: ['rule'],
|
|
57
|
+
},
|
|
58
|
+
handler: (args, ctx) => rulesProposeHandler(args, ctx),
|
|
59
|
+
});
|
|
@@ -12,11 +12,17 @@
|
|
|
12
12
|
* While a journey triage is queued in the session, only the page the journey
|
|
13
13
|
* handed out (journey/flow.ts, at most 40 keys) is shown: the skill needs no
|
|
14
14
|
* change to work in pages.
|
|
15
|
+
*
|
|
16
|
+
* Decision rules (step 2, D6): every row carries `ruleProposal` — the first
|
|
17
|
+
* rule of the team project (or the defaults) that decides it, or null when no
|
|
18
|
+
* rule does and the row is CSPeach's judgement. Rules the file names but this
|
|
19
|
+
* build cannot read give `rulesWarning` (one line) and the defaults.
|
|
15
20
|
*/
|
|
16
|
-
import { dispositionOf, DISPOSITION_WORD, inLane } from '@cspeach/register-core';
|
|
21
|
+
import { dispositionOf, DISPOSITION_WORD, inLane, readDecisionRules, } from '@cspeach/register-core';
|
|
17
22
|
import { registerTool } from '../index.js';
|
|
18
23
|
import { findingsByObject, shownUpTo } from '../../register/findings.js';
|
|
19
24
|
import { registerFor } from '../../register/picture.js';
|
|
25
|
+
import { ruleProposalOf } from '../../register/decision-rules.js';
|
|
20
26
|
import { activeProject, readProjectFile } from '../../register/store.js';
|
|
21
27
|
import { shown } from '../../register/atc-file.js';
|
|
22
28
|
import { journeyPage } from '../../journey/flow.js';
|
|
@@ -93,6 +99,7 @@ export async function teamFindingsHandler(args, ctx) {
|
|
|
93
99
|
const slice = objects.slice(start, start + limit);
|
|
94
100
|
const more = objects.length - start - slice.length;
|
|
95
101
|
const findings = findingsByObject(joined.projectDir, joined.outboxDir);
|
|
102
|
+
const rules = readDecisionRules(project);
|
|
96
103
|
const list = slice.map((o) => {
|
|
97
104
|
const f = findings.get(o.key);
|
|
98
105
|
const d = dispositionOf(o.decision);
|
|
@@ -108,12 +115,15 @@ export async function teamFindingsHandler(args, ctx) {
|
|
|
108
115
|
lastChanged: o.evidence.changed?.at ? shownUpTo(o.evidence.changed.at, 30) : null,
|
|
109
116
|
retireCandidate: o.retireCandidate,
|
|
110
117
|
priority: { band: o.priority.effective.band, source: o.priority.effective.source },
|
|
118
|
+
// The rule that decides this row, from the latest counted run's findings; null = no rule decides.
|
|
119
|
+
ruleProposal: ruleProposalOf(o, f, rules.rules),
|
|
111
120
|
};
|
|
112
121
|
});
|
|
113
122
|
return {
|
|
114
123
|
content: JSON.stringify({
|
|
115
124
|
teamProject: project.name, scope, objects: list,
|
|
116
125
|
...(page ? { journey: JOURNEY_NOTE } : {}),
|
|
126
|
+
...(rules.warning ? { rulesWarning: rules.warning } : {}),
|
|
117
127
|
...(more > 0 ? { more } : {}),
|
|
118
128
|
...(paged && more > 0 && slice.length ? { next: slice[slice.length - 1].key } : {}),
|
|
119
129
|
}),
|
|
@@ -127,7 +137,8 @@ registerTool({
|
|
|
127
137
|
name: 'team_findings',
|
|
128
138
|
description: 'Read-only. The objects of a lane (or package patterns) in the team project this laptop joined, with the findings '
|
|
129
139
|
+ 'measurement zero recorded for each, any decision already recorded, and per object: usage (state and source), callers from the '
|
|
130
|
-
+ 'index (or why they were not read), last change (a change, not use), whether it is a retire candidate,
|
|
140
|
+
+ 'index (or why they were not read), last change (a change, not use), whether it is a retire candidate, its priority, and '
|
|
141
|
+
+ 'ruleProposal: the decision rule that decides the row (null = no rule decides; your judgement). '
|
|
131
142
|
+ 'Use it for a /abap-clean-core triage. No SAP call.',
|
|
132
143
|
isMutating: false,
|
|
133
144
|
category: 'project',
|
package/dist/upgrade-check.js
CHANGED
|
@@ -3,7 +3,9 @@ import { loadConfig } from './config/loader.js';
|
|
|
3
3
|
import { CLI_VERSION } from './lib/version.js';
|
|
4
4
|
import { getStore } from './auth/api-key.js';
|
|
5
5
|
import { brandSettled } from './renderer/brand-settled.js';
|
|
6
|
-
|
|
6
|
+
import { ManifestClient, DEFAULT_MANIFEST_URL } from './skills/manifest-client.js';
|
|
7
|
+
import { asRunEntries, runsFloor } from './runs/manifest-runs.js';
|
|
8
|
+
export function compareVersions(a, b) {
|
|
7
9
|
const pa = a.split('.').map(Number);
|
|
8
10
|
const pb = b.split('.').map(Number);
|
|
9
11
|
for (let i = 0; i < 3; i++) {
|
|
@@ -24,19 +26,20 @@ function compareVersions(a, b) {
|
|
|
24
26
|
* GET with the bearer and read the body field (the header is still honoured
|
|
25
27
|
* should the proxy add it); not signed in → skip (a 401 tells us nothing).
|
|
26
28
|
* The warning goes to stderr so one-shot stdout stays the answer only.
|
|
29
|
+
* Returns true when it printed.
|
|
27
30
|
*/
|
|
28
|
-
|
|
31
|
+
async function checkSkillFloor() {
|
|
29
32
|
try {
|
|
30
33
|
const cfg = await loadConfig();
|
|
31
34
|
const key = await (await getStore()).get();
|
|
32
35
|
if (!key)
|
|
33
|
-
return;
|
|
36
|
+
return false;
|
|
34
37
|
const r = await fetch(`${cfg.proxy_url}/v1/skills/abap-radar`, {
|
|
35
38
|
headers: { Authorization: `Bearer ${key}` },
|
|
36
39
|
signal: AbortSignal.timeout(3000),
|
|
37
40
|
});
|
|
38
41
|
if (!r.ok)
|
|
39
|
-
return;
|
|
42
|
+
return false;
|
|
40
43
|
let minCli = r.headers.get('x-skill-min-cli-version');
|
|
41
44
|
if (!minCli) {
|
|
42
45
|
const body = (await r.json().catch(() => null));
|
|
@@ -52,7 +55,49 @@ export async function checkForUpgrade() {
|
|
|
52
55
|
text: `This CSPeach (${current}) is older than the minimum (${minCli})`,
|
|
53
56
|
next: 'cspeach --upgrade',
|
|
54
57
|
}).trimEnd());
|
|
58
|
+
return true;
|
|
55
59
|
}
|
|
60
|
+
return false;
|
|
61
|
+
}
|
|
62
|
+
catch {
|
|
63
|
+
// Offline, keychain unavailable or proxy down — never block startup.
|
|
64
|
+
return false;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Guided runs (2026-10-09, spec §3.2): a run's min_cli_version comes from the
|
|
69
|
+
* signed manifest's runs[]; an older CLI gets the same "!" line a skill gives.
|
|
70
|
+
* Returns true when it printed. Any failure (offline, unsigned, malformed) is silent.
|
|
71
|
+
*/
|
|
72
|
+
async function checkRunsFloor(deps) {
|
|
73
|
+
try {
|
|
74
|
+
const read = deps.fetchManifest ?? (() => new ManifestClient(DEFAULT_MANIFEST_URL).fetchAndVerifyManifest());
|
|
75
|
+
// The race caps the WAIT at 3 s; the underlying fetch keeps its own 10 s
|
|
76
|
+
// timeout (manifest-client.ts:32) and may outlive this call — harmless:
|
|
77
|
+
// nothing awaits it, and the process exit path does not wait for it (M-9).
|
|
78
|
+
const m = await Promise.race([read(), new Promise((_, rej) => { const t = setTimeout(() => rej(new Error('manifest timeout')), 3000); t.unref?.(); })]);
|
|
79
|
+
const floor = runsFloor(asRunEntries(m.runs), CLI_VERSION);
|
|
80
|
+
if (!floor)
|
|
81
|
+
return false;
|
|
82
|
+
await brandSettled();
|
|
83
|
+
console.error('\n' + formatAttention({
|
|
84
|
+
text: `This CSPeach (${CLI_VERSION}) is older than the guided run '${floor.name.replace(/^run-/, '')}' needs (${floor.min})`,
|
|
85
|
+
next: 'cspeach --upgrade',
|
|
86
|
+
}).trimEnd());
|
|
87
|
+
return true;
|
|
88
|
+
}
|
|
89
|
+
catch {
|
|
90
|
+
return false;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
export async function checkForUpgrade(deps = {}) {
|
|
94
|
+
try {
|
|
95
|
+
const key = await (await getStore()).get();
|
|
96
|
+
if (!key)
|
|
97
|
+
return;
|
|
98
|
+
const printed = await checkSkillFloor();
|
|
99
|
+
if (!printed)
|
|
100
|
+
await checkRunsFloor(deps);
|
|
56
101
|
}
|
|
57
102
|
catch {
|
|
58
103
|
// Offline, keychain unavailable or proxy down — never block startup.
|
package/package.json
CHANGED
|
@@ -1,120 +1,120 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@cspeach/cli",
|
|
3
|
-
"version": "1.1.
|
|
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
|
-
"test:smoke-e2e": "vitest run --config vitest.smoke-e2e.config.ts",
|
|
41
|
-
"adt:smoke": "tsx scripts/adt-smoke.ts",
|
|
42
|
-
"smoke:all": "pnpm adt:smoke",
|
|
43
|
-
"bench:models": "tsx scripts/bench-models.ts",
|
|
44
|
-
"bench:audit": "tsx scripts/bench-audit-task.ts",
|
|
45
|
-
"bench:replay": "tsx bench/replay/run.ts",
|
|
46
|
-
"fiori": "tsx src/tools/fiori/bin.ts",
|
|
47
|
-
"prepare": "husky",
|
|
48
|
-
"prepublishOnly": "node -e \"const deps=require('./package.json').dependencies||{}; for (const n of ['@cspeach/sap-client','@cspeach/register-core']) { const d=deps[n]||''; if(d.startsWith('file:')||d.startsWith('link:')){console.error('publish blocked: '+n+' is a local link ('+d+') — point it at the published version before npm publish'); process.exit(1)} }\""
|
|
49
|
-
},
|
|
50
|
-
"engines": {
|
|
51
|
-
"node": ">=20.0.0"
|
|
52
|
-
},
|
|
53
|
-
"dependencies": {
|
|
54
|
-
"@anthropic-ai/sdk": "^0.90.0",
|
|
55
|
-
"@cspeach/register-core": "0.
|
|
56
|
-
"@cspeach/sap-client": "0.1.
|
|
57
|
-
"@iarna/toml": "^2.2.5",
|
|
58
|
-
"@inkjs/ui": "^2.0.0",
|
|
59
|
-
"@inquirer/prompts": "^7.0.0",
|
|
60
|
-
"@napi-rs/keyring": "2.1.0",
|
|
61
|
-
"@noble/ed25519": "2.1.0",
|
|
62
|
-
"@noble/hashes": "1.4.0",
|
|
63
|
-
"@sap-ux/annotation-converter": "0.10.21",
|
|
64
|
-
"@sap-ux/edmx-parser": "0.10.0",
|
|
65
|
-
"@sap-ux/fe-fpm-writer": "0.43.7",
|
|
66
|
-
"@sap-ux/fiori-elements-writer": "^3.0.39",
|
|
67
|
-
"@sap-ux/fiori-freestyle-writer": "3.0.12",
|
|
68
|
-
"@sap-ux/vocabularies-types": "0.15.0",
|
|
69
|
-
"adm-zip": "0.5.17",
|
|
70
|
-
"chalk": "^5.3.0",
|
|
71
|
-
"cli-highlight": "^2.1.11",
|
|
72
|
-
"cli-table3": "^0.6.5",
|
|
73
|
-
"clipboardy": "^5.3.1",
|
|
74
|
-
"cross-spawn": "^7.0.6",
|
|
75
|
-
"diff": "^9.0.0",
|
|
76
|
-
"ejs": "3.1.10",
|
|
77
|
-
"fuse.js": "^7.0.0",
|
|
78
|
-
"ink": "^5.0.0",
|
|
79
|
-
"ink-text-input": "^6.0.0",
|
|
80
|
-
"jose": "^5.9.0",
|
|
81
|
-
"mammoth": "^1.8.0",
|
|
82
|
-
"marked": "^11.2.0",
|
|
83
|
-
"marked-terminal": "^6.2.0",
|
|
84
|
-
"mem-fs": "2.1.0",
|
|
85
|
-
"mem-fs-editor": "9.4.0",
|
|
86
|
-
"node-machine-id": "^1.1.12",
|
|
87
|
-
"openai": "^6.49.0",
|
|
88
|
-
"puppeteer-core": "24.10.2",
|
|
89
|
-
"react": "^18.3.0",
|
|
90
|
-
"string-width": "^7.2.0",
|
|
91
|
-
"turndown": "^7.2.0",
|
|
92
|
-
"unpdf": "1.7.0",
|
|
93
|
-
"zod": "^3.23.0"
|
|
94
|
-
},
|
|
95
|
-
"devDependencies": {
|
|
96
|
-
"@sap-ux/ui5-middleware-fe-mockserver": "2.4.17",
|
|
97
|
-
"@types/adm-zip": "0.5.8",
|
|
98
|
-
"@types/cross-spawn": "^6.0.6",
|
|
99
|
-
"@types/diff": "^7.0.2",
|
|
100
|
-
"@types/ejs": "^3.1.5",
|
|
101
|
-
"@types/node": "^20.17.0",
|
|
102
|
-
"@types/react": "^18.3.0",
|
|
103
|
-
"@types/turndown": "^5.0.5",
|
|
104
|
-
"@ui5/builder": "4.3.2",
|
|
105
|
-
"@ui5/fs": "4.0.6",
|
|
106
|
-
"docx": "^9.0.2",
|
|
107
|
-
"husky": "^9.1.7",
|
|
108
|
-
"ink-testing-library": "^4.0.0",
|
|
109
|
-
"pdf-lib": "^1.17.1",
|
|
110
|
-
"strip-ansi": "6.0.1",
|
|
111
|
-
"tsx": "^4.19.0",
|
|
112
|
-
"typescript": "^5.7.0",
|
|
113
|
-
"vitest": "^2.1.0"
|
|
114
|
-
},
|
|
115
|
-
"pnpm": {
|
|
116
|
-
"onlyBuiltDependencies": [
|
|
117
|
-
"esbuild"
|
|
118
|
-
]
|
|
119
|
-
}
|
|
120
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@cspeach/cli",
|
|
3
|
+
"version": "1.1.33",
|
|
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
|
+
"test:smoke-e2e": "vitest run --config vitest.smoke-e2e.config.ts",
|
|
41
|
+
"adt:smoke": "tsx scripts/adt-smoke.ts",
|
|
42
|
+
"smoke:all": "pnpm adt:smoke",
|
|
43
|
+
"bench:models": "tsx scripts/bench-models.ts",
|
|
44
|
+
"bench:audit": "tsx scripts/bench-audit-task.ts",
|
|
45
|
+
"bench:replay": "tsx bench/replay/run.ts",
|
|
46
|
+
"fiori": "tsx src/tools/fiori/bin.ts",
|
|
47
|
+
"prepare": "husky",
|
|
48
|
+
"prepublishOnly": "node -e \"const deps=require('./package.json').dependencies||{}; for (const n of ['@cspeach/sap-client','@cspeach/register-core']) { const d=deps[n]||''; if(d.startsWith('file:')||d.startsWith('link:')){console.error('publish blocked: '+n+' is a local link ('+d+') — point it at the published version before npm publish'); process.exit(1)} }\""
|
|
49
|
+
},
|
|
50
|
+
"engines": {
|
|
51
|
+
"node": ">=20.0.0"
|
|
52
|
+
},
|
|
53
|
+
"dependencies": {
|
|
54
|
+
"@anthropic-ai/sdk": "^0.90.0",
|
|
55
|
+
"@cspeach/register-core": "0.4.0",
|
|
56
|
+
"@cspeach/sap-client": "0.1.18",
|
|
57
|
+
"@iarna/toml": "^2.2.5",
|
|
58
|
+
"@inkjs/ui": "^2.0.0",
|
|
59
|
+
"@inquirer/prompts": "^7.0.0",
|
|
60
|
+
"@napi-rs/keyring": "2.1.0",
|
|
61
|
+
"@noble/ed25519": "2.1.0",
|
|
62
|
+
"@noble/hashes": "1.4.0",
|
|
63
|
+
"@sap-ux/annotation-converter": "0.10.21",
|
|
64
|
+
"@sap-ux/edmx-parser": "0.10.0",
|
|
65
|
+
"@sap-ux/fe-fpm-writer": "0.43.7",
|
|
66
|
+
"@sap-ux/fiori-elements-writer": "^3.0.39",
|
|
67
|
+
"@sap-ux/fiori-freestyle-writer": "3.0.12",
|
|
68
|
+
"@sap-ux/vocabularies-types": "0.15.0",
|
|
69
|
+
"adm-zip": "0.5.17",
|
|
70
|
+
"chalk": "^5.3.0",
|
|
71
|
+
"cli-highlight": "^2.1.11",
|
|
72
|
+
"cli-table3": "^0.6.5",
|
|
73
|
+
"clipboardy": "^5.3.1",
|
|
74
|
+
"cross-spawn": "^7.0.6",
|
|
75
|
+
"diff": "^9.0.0",
|
|
76
|
+
"ejs": "3.1.10",
|
|
77
|
+
"fuse.js": "^7.0.0",
|
|
78
|
+
"ink": "^5.0.0",
|
|
79
|
+
"ink-text-input": "^6.0.0",
|
|
80
|
+
"jose": "^5.9.0",
|
|
81
|
+
"mammoth": "^1.8.0",
|
|
82
|
+
"marked": "^11.2.0",
|
|
83
|
+
"marked-terminal": "^6.2.0",
|
|
84
|
+
"mem-fs": "2.1.0",
|
|
85
|
+
"mem-fs-editor": "9.4.0",
|
|
86
|
+
"node-machine-id": "^1.1.12",
|
|
87
|
+
"openai": "^6.49.0",
|
|
88
|
+
"puppeteer-core": "24.10.2",
|
|
89
|
+
"react": "^18.3.0",
|
|
90
|
+
"string-width": "^7.2.0",
|
|
91
|
+
"turndown": "^7.2.0",
|
|
92
|
+
"unpdf": "1.7.0",
|
|
93
|
+
"zod": "^3.23.0"
|
|
94
|
+
},
|
|
95
|
+
"devDependencies": {
|
|
96
|
+
"@sap-ux/ui5-middleware-fe-mockserver": "2.4.17",
|
|
97
|
+
"@types/adm-zip": "0.5.8",
|
|
98
|
+
"@types/cross-spawn": "^6.0.6",
|
|
99
|
+
"@types/diff": "^7.0.2",
|
|
100
|
+
"@types/ejs": "^3.1.5",
|
|
101
|
+
"@types/node": "^20.17.0",
|
|
102
|
+
"@types/react": "^18.3.0",
|
|
103
|
+
"@types/turndown": "^5.0.5",
|
|
104
|
+
"@ui5/builder": "4.3.2",
|
|
105
|
+
"@ui5/fs": "4.0.6",
|
|
106
|
+
"docx": "^9.0.2",
|
|
107
|
+
"husky": "^9.1.7",
|
|
108
|
+
"ink-testing-library": "^4.0.0",
|
|
109
|
+
"pdf-lib": "^1.17.1",
|
|
110
|
+
"strip-ansi": "6.0.1",
|
|
111
|
+
"tsx": "^4.19.0",
|
|
112
|
+
"typescript": "^5.7.0",
|
|
113
|
+
"vitest": "^2.1.0"
|
|
114
|
+
},
|
|
115
|
+
"pnpm": {
|
|
116
|
+
"onlyBuiltDependencies": [
|
|
117
|
+
"esbuild"
|
|
118
|
+
]
|
|
119
|
+
}
|
|
120
|
+
}
|
package/.cspeach/project.json
DELETED