opena2a-cli 0.1.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 (150) hide show
  1. package/dist/adapters/docker.d.ts +8 -0
  2. package/dist/adapters/docker.d.ts.map +1 -0
  3. package/dist/adapters/docker.js +60 -0
  4. package/dist/adapters/docker.js.map +1 -0
  5. package/dist/adapters/import.d.ts +12 -0
  6. package/dist/adapters/import.d.ts.map +1 -0
  7. package/dist/adapters/import.js +76 -0
  8. package/dist/adapters/import.js.map +1 -0
  9. package/dist/adapters/index.d.ts +9 -0
  10. package/dist/adapters/index.d.ts.map +1 -0
  11. package/dist/adapters/index.js +40 -0
  12. package/dist/adapters/index.js.map +1 -0
  13. package/dist/adapters/python.d.ts +9 -0
  14. package/dist/adapters/python.d.ts.map +1 -0
  15. package/dist/adapters/python.js +73 -0
  16. package/dist/adapters/python.js.map +1 -0
  17. package/dist/adapters/registry.d.ts +6 -0
  18. package/dist/adapters/registry.d.ts.map +1 -0
  19. package/dist/adapters/registry.js +86 -0
  20. package/dist/adapters/registry.js.map +1 -0
  21. package/dist/adapters/spawn.d.ts +9 -0
  22. package/dist/adapters/spawn.d.ts.map +1 -0
  23. package/dist/adapters/spawn.js +63 -0
  24. package/dist/adapters/spawn.js.map +1 -0
  25. package/dist/adapters/types.d.ts +35 -0
  26. package/dist/adapters/types.d.ts.map +1 -0
  27. package/dist/adapters/types.js +3 -0
  28. package/dist/adapters/types.js.map +1 -0
  29. package/dist/branding.d.ts +3 -0
  30. package/dist/branding.d.ts.map +1 -0
  31. package/dist/branding.js +21 -0
  32. package/dist/branding.js.map +1 -0
  33. package/dist/commands/baselines.d.ts +14 -0
  34. package/dist/commands/baselines.d.ts.map +1 -0
  35. package/dist/commands/baselines.js +269 -0
  36. package/dist/commands/baselines.js.map +1 -0
  37. package/dist/commands/guard.d.ts +38 -0
  38. package/dist/commands/guard.d.ts.map +1 -0
  39. package/dist/commands/guard.js +307 -0
  40. package/dist/commands/guard.js.map +1 -0
  41. package/dist/commands/init.d.ts +14 -0
  42. package/dist/commands/init.d.ts.map +1 -0
  43. package/dist/commands/init.js +356 -0
  44. package/dist/commands/init.js.map +1 -0
  45. package/dist/commands/onepassword-migration.d.ts +23 -0
  46. package/dist/commands/onepassword-migration.d.ts.map +1 -0
  47. package/dist/commands/onepassword-migration.js +179 -0
  48. package/dist/commands/onepassword-migration.js.map +1 -0
  49. package/dist/commands/protect.d.ts +34 -0
  50. package/dist/commands/protect.d.ts.map +1 -0
  51. package/dist/commands/protect.js +642 -0
  52. package/dist/commands/protect.js.map +1 -0
  53. package/dist/commands/runtime.d.ts +28 -0
  54. package/dist/commands/runtime.d.ts.map +1 -0
  55. package/dist/commands/runtime.js +309 -0
  56. package/dist/commands/runtime.js.map +1 -0
  57. package/dist/commands/self-register.d.ts +39 -0
  58. package/dist/commands/self-register.d.ts.map +1 -0
  59. package/dist/commands/self-register.js +528 -0
  60. package/dist/commands/self-register.js.map +1 -0
  61. package/dist/commands/verify.d.ts +25 -0
  62. package/dist/commands/verify.d.ts.map +1 -0
  63. package/dist/commands/verify.js +300 -0
  64. package/dist/commands/verify.js.map +1 -0
  65. package/dist/contextual/advisor.d.ts +12 -0
  66. package/dist/contextual/advisor.d.ts.map +1 -0
  67. package/dist/contextual/advisor.js +94 -0
  68. package/dist/contextual/advisor.js.map +1 -0
  69. package/dist/contextual/index.d.ts +3 -0
  70. package/dist/contextual/index.d.ts.map +1 -0
  71. package/dist/contextual/index.js +7 -0
  72. package/dist/contextual/index.js.map +1 -0
  73. package/dist/guided/attack-walkthrough.d.ts +13 -0
  74. package/dist/guided/attack-walkthrough.d.ts.map +1 -0
  75. package/dist/guided/attack-walkthrough.js +113 -0
  76. package/dist/guided/attack-walkthrough.js.map +1 -0
  77. package/dist/guided/wizard.d.ts +2 -0
  78. package/dist/guided/wizard.d.ts.map +1 -0
  79. package/dist/guided/wizard.js +108 -0
  80. package/dist/guided/wizard.js.map +1 -0
  81. package/dist/index.d.ts +3 -0
  82. package/dist/index.d.ts.map +1 -0
  83. package/dist/index.js +326 -0
  84. package/dist/index.js.map +1 -0
  85. package/dist/natural/index.d.ts +4 -0
  86. package/dist/natural/index.d.ts.map +1 -0
  87. package/dist/natural/index.js +9 -0
  88. package/dist/natural/index.js.map +1 -0
  89. package/dist/natural/intent-map.d.ts +7 -0
  90. package/dist/natural/intent-map.d.ts.map +1 -0
  91. package/dist/natural/intent-map.js +145 -0
  92. package/dist/natural/intent-map.js.map +1 -0
  93. package/dist/natural/llm-fallback.d.ts +8 -0
  94. package/dist/natural/llm-fallback.d.ts.map +1 -0
  95. package/dist/natural/llm-fallback.js +143 -0
  96. package/dist/natural/llm-fallback.js.map +1 -0
  97. package/dist/report/interactive-html.d.ts +51 -0
  98. package/dist/report/interactive-html.d.ts.map +1 -0
  99. package/dist/report/interactive-html.js +508 -0
  100. package/dist/report/interactive-html.js.map +1 -0
  101. package/dist/router.d.ts +23 -0
  102. package/dist/router.d.ts.map +1 -0
  103. package/dist/router.js +132 -0
  104. package/dist/router.js.map +1 -0
  105. package/dist/semantic/command-index.json +182 -0
  106. package/dist/semantic/index.d.ts +3 -0
  107. package/dist/semantic/index.d.ts.map +1 -0
  108. package/dist/semantic/index.js +28 -0
  109. package/dist/semantic/index.js.map +1 -0
  110. package/dist/semantic/search.d.ts +17 -0
  111. package/dist/semantic/search.d.ts.map +1 -0
  112. package/dist/semantic/search.js +123 -0
  113. package/dist/semantic/search.js.map +1 -0
  114. package/dist/util/action-prompt.d.ts +29 -0
  115. package/dist/util/action-prompt.d.ts.map +1 -0
  116. package/dist/util/action-prompt.js +126 -0
  117. package/dist/util/action-prompt.js.map +1 -0
  118. package/dist/util/advisories.d.ts +43 -0
  119. package/dist/util/advisories.d.ts.map +1 -0
  120. package/dist/util/advisories.js +229 -0
  121. package/dist/util/advisories.js.map +1 -0
  122. package/dist/util/colors.d.ts +9 -0
  123. package/dist/util/colors.d.ts.map +1 -0
  124. package/dist/util/colors.js +18 -0
  125. package/dist/util/colors.js.map +1 -0
  126. package/dist/util/credential-patterns.d.ts +38 -0
  127. package/dist/util/credential-patterns.d.ts.map +1 -0
  128. package/dist/util/credential-patterns.js +203 -0
  129. package/dist/util/credential-patterns.js.map +1 -0
  130. package/dist/util/detect.d.ts +11 -0
  131. package/dist/util/detect.d.ts.map +1 -0
  132. package/dist/util/detect.js +49 -0
  133. package/dist/util/detect.js.map +1 -0
  134. package/dist/util/format.d.ts +6 -0
  135. package/dist/util/format.d.ts.map +1 -0
  136. package/dist/util/format.js +49 -0
  137. package/dist/util/format.js.map +1 -0
  138. package/dist/util/report-submission.d.ts +64 -0
  139. package/dist/util/report-submission.d.ts.map +1 -0
  140. package/dist/util/report-submission.js +109 -0
  141. package/dist/util/report-submission.js.map +1 -0
  142. package/dist/util/spinner.d.ts +10 -0
  143. package/dist/util/spinner.d.ts.map +1 -0
  144. package/dist/util/spinner.js +38 -0
  145. package/dist/util/spinner.js.map +1 -0
  146. package/dist/util/version.d.ts +5 -0
  147. package/dist/util/version.d.ts.map +1 -0
  148. package/dist/util/version.js +24 -0
  149. package/dist/util/version.js.map +1 -0
  150. package/package.json +47 -0
@@ -0,0 +1,49 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.severityColor = severityColor;
4
+ exports.severityLabel = severityLabel;
5
+ exports.formatCount = formatCount;
6
+ exports.formatDuration = formatDuration;
7
+ exports.table = table;
8
+ const colors_js_1 = require("./colors.js");
9
+ function severityColor(severity) {
10
+ switch (severity) {
11
+ case 'critical': return colors_js_1.red;
12
+ case 'high': return colors_js_1.red;
13
+ case 'medium': return colors_js_1.yellow;
14
+ case 'low': return colors_js_1.cyan;
15
+ default: return colors_js_1.gray;
16
+ }
17
+ }
18
+ function severityLabel(severity) {
19
+ return severityColor(severity)(severity.toUpperCase());
20
+ }
21
+ function formatCount(count, label) {
22
+ if (count === 0)
23
+ return (0, colors_js_1.green)(`0 ${label}`);
24
+ return (0, colors_js_1.bold)(`${count} ${label}`);
25
+ }
26
+ function formatDuration(ms) {
27
+ if (ms < 1000)
28
+ return `${ms}ms`;
29
+ if (ms < 60000)
30
+ return `${(ms / 1000).toFixed(1)}s`;
31
+ const mins = Math.floor(ms / 60000);
32
+ const secs = Math.floor((ms % 60000) / 1000);
33
+ return `${mins}m ${secs}s`;
34
+ }
35
+ function table(rows, headers) {
36
+ const allRows = headers ? [headers, ...rows] : rows;
37
+ const colWidths = allRows[0].map((_, i) => Math.max(...allRows.map(row => (row[i] ?? '').length)));
38
+ const lines = [];
39
+ for (let r = 0; r < allRows.length; r++) {
40
+ const row = allRows[r];
41
+ const cells = row.map((cell, i) => cell.padEnd(colWidths[i]));
42
+ lines.push(cells.join(' '));
43
+ if (r === 0 && headers) {
44
+ lines.push(colWidths.map(w => '-'.repeat(w)).join(' '));
45
+ }
46
+ }
47
+ return lines.join('\n');
48
+ }
49
+ //# sourceMappingURL=format.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"format.js","sourceRoot":"","sources":["../../src/util/format.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,64 @@
1
+ /**
2
+ * Scan report submission -- shares detailed scan findings with the OpenA2A Registry
3
+ * when the user has opted in via `opena2a config contribute on`.
4
+ *
5
+ * This enables the community intelligence loop:
6
+ * 1. User scans a tool with HMA
7
+ * 2. Findings are shared (opt-in) with the registry
8
+ * 3. Registry aggregates data and generates advisories
9
+ * 4. Other users see advisories via `opena2a init` and `opena2a verify`
10
+ *
11
+ * Contribution prompting is delayed until after the user has run 3+ scans,
12
+ * so they see value before being asked to share.
13
+ */
14
+ export interface ScanFinding {
15
+ findingId: string;
16
+ severity: string;
17
+ category: string;
18
+ title: string;
19
+ description?: string;
20
+ cweId?: number;
21
+ filePath?: string;
22
+ lineNumber?: number;
23
+ autoFixable?: boolean;
24
+ }
25
+ export interface ScanReport {
26
+ /** Package name being scanned */
27
+ packageName: string;
28
+ /** Package version */
29
+ packageVersion?: string;
30
+ /** Package type (npm, pypi, go, mcp_server, a2a_agent) */
31
+ packageType?: string;
32
+ /** Scanner name */
33
+ scannerName: string;
34
+ /** Scanner version */
35
+ scannerVersion: string;
36
+ /** Overall score (0-100) */
37
+ overallScore: number;
38
+ /** Scan duration in ms */
39
+ scanDurationMs: number;
40
+ /** Finding counts by severity */
41
+ criticalCount: number;
42
+ highCount: number;
43
+ mediumCount: number;
44
+ lowCount: number;
45
+ infoCount: number;
46
+ /** Overall verdict */
47
+ verdict: string;
48
+ /** Detailed findings */
49
+ findings: ScanFinding[];
50
+ /** MCP tool names detected */
51
+ mcpTools?: string[];
52
+ /** A2A agent card fields detected */
53
+ a2aCapabilities?: string[];
54
+ }
55
+ export declare function submitScanReport(registryUrl: string, report: ScanReport, verbose?: boolean): Promise<boolean>;
56
+ export declare function isContributeEnabled(): Promise<boolean>;
57
+ export declare function getRegistryUrl(): Promise<string>;
58
+ /**
59
+ * Record that a scan was completed and conditionally show the contribute prompt.
60
+ * Only prompts after 3+ scans, and not if the user already opted in or recently
61
+ * dismissed the prompt. This lets us demonstrate value first.
62
+ */
63
+ export declare function recordScanAndMaybePrompt(): Promise<void>;
64
+ //# sourceMappingURL=report-submission.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"report-submission.d.ts","sourceRoot":"","sources":["../../src/util/report-submission.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAMH,MAAM,WAAW,WAAW;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,MAAM,WAAW,UAAU;IACzB,iCAAiC;IACjC,WAAW,EAAE,MAAM,CAAC;IACpB,sBAAsB;IACtB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,0DAA0D;IAC1D,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,mBAAmB;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,sBAAsB;IACtB,cAAc,EAAE,MAAM,CAAC;IACvB,4BAA4B;IAC5B,YAAY,EAAE,MAAM,CAAC;IACrB,0BAA0B;IAC1B,cAAc,EAAE,MAAM,CAAC;IACvB,iCAAiC;IACjC,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,sBAAsB;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,wBAAwB;IACxB,QAAQ,EAAE,WAAW,EAAE,CAAC;IACxB,8BAA8B;IAC9B,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,qCAAqC;IACrC,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;CAC5B;AAID,wBAAsB,gBAAgB,CACpC,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,UAAU,EAClB,OAAO,CAAC,EAAE,OAAO,GAChB,OAAO,CAAC,OAAO,CAAC,CAqClB;AASD,wBAAsB,mBAAmB,IAAI,OAAO,CAAC,OAAO,CAAC,CAO5D;AAED,wBAAsB,cAAc,IAAI,OAAO,CAAC,MAAM,CAAC,CAQtD;AAED;;;;GAIG;AACH,wBAAsB,wBAAwB,IAAI,OAAO,CAAC,IAAI,CAAC,CAa9D"}
@@ -0,0 +1,109 @@
1
+ "use strict";
2
+ /**
3
+ * Scan report submission -- shares detailed scan findings with the OpenA2A Registry
4
+ * when the user has opted in via `opena2a config contribute on`.
5
+ *
6
+ * This enables the community intelligence loop:
7
+ * 1. User scans a tool with HMA
8
+ * 2. Findings are shared (opt-in) with the registry
9
+ * 3. Registry aggregates data and generates advisories
10
+ * 4. Other users see advisories via `opena2a init` and `opena2a verify`
11
+ *
12
+ * Contribution prompting is delayed until after the user has run 3+ scans,
13
+ * so they see value before being asked to share.
14
+ */
15
+ Object.defineProperty(exports, "__esModule", { value: true });
16
+ exports.submitScanReport = submitScanReport;
17
+ exports.isContributeEnabled = isContributeEnabled;
18
+ exports.getRegistryUrl = getRegistryUrl;
19
+ exports.recordScanAndMaybePrompt = recordScanAndMaybePrompt;
20
+ const colors_js_1 = require("./colors.js");
21
+ // --- Submission ---
22
+ async function submitScanReport(registryUrl, report, verbose) {
23
+ try {
24
+ const url = `${registryUrl}/api/v1/trust/scan-report`;
25
+ const response = await fetch(url, {
26
+ method: 'POST',
27
+ headers: {
28
+ 'Content-Type': 'application/json',
29
+ 'Accept': 'application/json',
30
+ },
31
+ body: JSON.stringify({
32
+ ...report,
33
+ submittedAt: new Date().toISOString(),
34
+ clientVersion: '0.1.0',
35
+ }),
36
+ signal: AbortSignal.timeout(10_000),
37
+ });
38
+ if (response.ok) {
39
+ if (verbose) {
40
+ process.stderr.write((0, colors_js_1.dim)('Scan report shared with OpenA2A community.\n'));
41
+ }
42
+ return true;
43
+ }
44
+ // If the endpoint doesn't exist yet (404), that's fine
45
+ if (response.status === 404) {
46
+ if (verbose) {
47
+ process.stderr.write((0, colors_js_1.dim)('Registry scan-report endpoint not available yet.\n'));
48
+ }
49
+ return false;
50
+ }
51
+ return false;
52
+ }
53
+ catch {
54
+ // Network errors are non-critical
55
+ return false;
56
+ }
57
+ }
58
+ // --- Config helpers (dynamic import to avoid circular deps) ---
59
+ async function loadShared() {
60
+ const shared = await Function('return import("@opena2a/shared")')();
61
+ return 'default' in shared ? shared.default : shared;
62
+ }
63
+ async function isContributeEnabled() {
64
+ try {
65
+ const mod = await loadShared();
66
+ return mod.isContributeEnabled();
67
+ }
68
+ catch {
69
+ return false;
70
+ }
71
+ }
72
+ async function getRegistryUrl() {
73
+ try {
74
+ const mod = await loadShared();
75
+ const config = mod.loadUserConfig();
76
+ return config.registry?.url ?? 'https://registry.opena2a.org';
77
+ }
78
+ catch {
79
+ return 'https://registry.opena2a.org';
80
+ }
81
+ }
82
+ /**
83
+ * Record that a scan was completed and conditionally show the contribute prompt.
84
+ * Only prompts after 3+ scans, and not if the user already opted in or recently
85
+ * dismissed the prompt. This lets us demonstrate value first.
86
+ */
87
+ async function recordScanAndMaybePrompt() {
88
+ try {
89
+ const mod = await loadShared();
90
+ mod.incrementScanCount();
91
+ if (mod.shouldPromptContribute()) {
92
+ printContributePrompt();
93
+ // Mark as shown so it doesn't repeat every scan
94
+ mod.dismissContributePrompt();
95
+ }
96
+ }
97
+ catch {
98
+ // Non-critical
99
+ }
100
+ }
101
+ function printContributePrompt() {
102
+ process.stderr.write('\n');
103
+ process.stderr.write((0, colors_js_1.cyan)(' Your scans help the community detect unsafe tools.\n'));
104
+ process.stderr.write((0, colors_js_1.dim)(' Share anonymized scan reports with the OpenA2A registry?\n'));
105
+ process.stderr.write((0, colors_js_1.dim)(' Enable: ') + (0, colors_js_1.yellow)('opena2a config contribute on') + '\n');
106
+ process.stderr.write((0, colors_js_1.dim)(' Details: https://opena2a.org/telemetry\n'));
107
+ process.stderr.write('\n');
108
+ }
109
+ //# sourceMappingURL=report-submission.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"report-submission.js","sourceRoot":"","sources":["../../src/util/report-submission.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ export declare class Spinner {
2
+ private intervalId;
3
+ private frameIndex;
4
+ private message;
5
+ constructor(message: string);
6
+ start(): void;
7
+ stop(finalMessage?: string): void;
8
+ update(message: string): void;
9
+ }
10
+ //# sourceMappingURL=spinner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spinner.d.ts","sourceRoot":"","sources":["../../src/util/spinner.ts"],"names":[],"mappings":"AAEA,qBAAa,OAAO;IAClB,OAAO,CAAC,UAAU,CAA+C;IACjE,OAAO,CAAC,UAAU,CAAK;IACvB,OAAO,CAAC,OAAO,CAAS;gBAEZ,OAAO,EAAE,MAAM;IAI3B,KAAK,IAAI,IAAI;IASb,IAAI,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI;IAajC,MAAM,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;CAG9B"}
@@ -0,0 +1,38 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Spinner = void 0;
4
+ const FRAMES = ['|', '/', '-', '\\'];
5
+ class Spinner {
6
+ intervalId = null;
7
+ frameIndex = 0;
8
+ message;
9
+ constructor(message) {
10
+ this.message = message;
11
+ }
12
+ start() {
13
+ if (!process.stderr.isTTY)
14
+ return;
15
+ this.intervalId = setInterval(() => {
16
+ const frame = FRAMES[this.frameIndex % FRAMES.length];
17
+ process.stderr.write(`\r${frame} ${this.message}`);
18
+ this.frameIndex++;
19
+ }, 100);
20
+ }
21
+ stop(finalMessage) {
22
+ if (this.intervalId) {
23
+ clearInterval(this.intervalId);
24
+ this.intervalId = null;
25
+ }
26
+ if (process.stderr.isTTY) {
27
+ process.stderr.write('\r' + ' '.repeat(this.message.length + 4) + '\r');
28
+ }
29
+ if (finalMessage) {
30
+ process.stderr.write(finalMessage + '\n');
31
+ }
32
+ }
33
+ update(message) {
34
+ this.message = message;
35
+ }
36
+ }
37
+ exports.Spinner = Spinner;
38
+ //# sourceMappingURL=spinner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spinner.js","sourceRoot":"","sources":["../../src/util/spinner.ts"],"names":[],"mappings":";;;AAAA,MAAM,MAAM,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC;AAErC,MAAa,OAAO;IACV,UAAU,GAA0C,IAAI,CAAC;IACzD,UAAU,GAAG,CAAC,CAAC;IACf,OAAO,CAAS;IAExB,YAAY,OAAe;QACzB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IACzB,CAAC;IAED,KAAK;QACH,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK;YAAE,OAAO;QAClC,IAAI,CAAC,UAAU,GAAG,WAAW,CAAC,GAAG,EAAE;YACjC,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,UAAU,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;YACtD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,KAAK,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;YACnD,IAAI,CAAC,UAAU,EAAE,CAAC;QACpB,CAAC,EAAE,GAAG,CAAC,CAAC;IACV,CAAC;IAED,IAAI,CAAC,YAAqB;QACxB,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;YACpB,aAAa,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YAC/B,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC;QACzB,CAAC;QACD,IAAI,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;YACzB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,GAAG,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;QAC1E,CAAC;QACD,IAAI,YAAY,EAAE,CAAC;YACjB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,YAAY,GAAG,IAAI,CAAC,CAAC;QAC5C,CAAC;IACH,CAAC;IAED,MAAM,CAAC,OAAe;QACpB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IACzB,CAAC;CACF;AAlCD,0BAkCC"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Read the CLI version from package.json. Result is cached after first call.
3
+ */
4
+ export declare function getVersion(): string;
5
+ //# sourceMappingURL=version.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../../src/util/version.ts"],"names":[],"mappings":"AAKA;;GAEG;AACH,wBAAgB,UAAU,IAAI,MAAM,CAWnC"}
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getVersion = getVersion;
4
+ const node_fs_1 = require("node:fs");
5
+ const node_path_1 = require("node:path");
6
+ let cached = null;
7
+ /**
8
+ * Read the CLI version from package.json. Result is cached after first call.
9
+ */
10
+ function getVersion() {
11
+ if (cached)
12
+ return cached;
13
+ try {
14
+ // From dist/util/ or src/util/, walk up to the package root
15
+ const pkgPath = (0, node_path_1.resolve)(__dirname, '..', '..', 'package.json');
16
+ const pkg = JSON.parse((0, node_fs_1.readFileSync)(pkgPath, 'utf-8'));
17
+ cached = pkg.version ?? '0.0.0';
18
+ }
19
+ catch {
20
+ cached = '0.0.0';
21
+ }
22
+ return cached;
23
+ }
24
+ //# sourceMappingURL=version.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"version.js","sourceRoot":"","sources":["../../src/util/version.ts"],"names":[],"mappings":";;AAQA,gCAWC;AAnBD,qCAAuC;AACvC,yCAAoC;AAEpC,IAAI,MAAM,GAAkB,IAAI,CAAC;AAEjC;;GAEG;AACH,SAAgB,UAAU;IACxB,IAAI,MAAM;QAAE,OAAO,MAAM,CAAC;IAC1B,IAAI,CAAC;QACH,4DAA4D;QAC5D,MAAM,OAAO,GAAG,IAAA,mBAAO,EAAC,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,cAAc,CAAC,CAAC;QAC/D,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,IAAA,sBAAY,EAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC;QACvD,MAAM,GAAG,GAAG,CAAC,OAAO,IAAI,OAAO,CAAC;IAClC,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,GAAG,OAAO,CAAC;IACnB,CAAC;IACD,OAAO,MAAO,CAAC;AACjB,CAAC"}
package/package.json ADDED
@@ -0,0 +1,47 @@
1
+ {
2
+ "name": "opena2a-cli",
3
+ "version": "0.1.0",
4
+ "description": "Unified CLI for the OpenA2A security platform",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "bin": {
8
+ "opena2a": "dist/index.js"
9
+ },
10
+ "scripts": {
11
+ "build": "tsc && cp src/semantic/command-index.json dist/semantic/",
12
+ "test": "vitest run",
13
+ "lint": "tsc --noEmit",
14
+ "typecheck": "tsc --noEmit",
15
+ "clean": "rm -rf dist",
16
+ "dev": "tsc --watch"
17
+ },
18
+ "dependencies": {
19
+ "@opena2a/shared": "0.1.0",
20
+ "commander": "^13.1.0",
21
+ "@inquirer/prompts": "^7.0.0"
22
+ },
23
+ "devDependencies": {
24
+ "typescript": "^5.7.0",
25
+ "vitest": "^3.0.0",
26
+ "@types/node": "^22.0.0"
27
+ },
28
+ "files": ["dist"],
29
+ "engines": {
30
+ "node": ">=18.0.0"
31
+ },
32
+ "license": "Apache-2.0",
33
+ "repository": {
34
+ "type": "git",
35
+ "url": "https://github.com/opena2a-org/opena2a.git",
36
+ "directory": "packages/cli"
37
+ },
38
+ "keywords": [
39
+ "ai",
40
+ "agent",
41
+ "security",
42
+ "scanner",
43
+ "mcp",
44
+ "credentials",
45
+ "identity"
46
+ ]
47
+ }