@tradingboy/cli 0.3.8

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 (142) hide show
  1. package/README.md +8 -0
  2. package/dist/api-client.d.ts +35 -0
  3. package/dist/api-client.d.ts.map +1 -0
  4. package/dist/api-client.js +165 -0
  5. package/dist/api-client.js.map +1 -0
  6. package/dist/cli.d.ts +5 -0
  7. package/dist/cli.d.ts.map +1 -0
  8. package/dist/cli.js +143 -0
  9. package/dist/cli.js.map +1 -0
  10. package/dist/commands/audit.d.ts +18 -0
  11. package/dist/commands/audit.d.ts.map +1 -0
  12. package/dist/commands/audit.js +73 -0
  13. package/dist/commands/audit.js.map +1 -0
  14. package/dist/commands/behavioral.d.ts +73 -0
  15. package/dist/commands/behavioral.d.ts.map +1 -0
  16. package/dist/commands/behavioral.js +349 -0
  17. package/dist/commands/behavioral.js.map +1 -0
  18. package/dist/commands/benchmark-cmd.d.ts +3 -0
  19. package/dist/commands/benchmark-cmd.d.ts.map +1 -0
  20. package/dist/commands/benchmark-cmd.js +196 -0
  21. package/dist/commands/benchmark-cmd.js.map +1 -0
  22. package/dist/commands/billing.d.ts +12 -0
  23. package/dist/commands/billing.d.ts.map +1 -0
  24. package/dist/commands/billing.js +117 -0
  25. package/dist/commands/billing.js.map +1 -0
  26. package/dist/commands/catalysts.d.ts +17 -0
  27. package/dist/commands/catalysts.d.ts.map +1 -0
  28. package/dist/commands/catalysts.js +151 -0
  29. package/dist/commands/catalysts.js.map +1 -0
  30. package/dist/commands/coaching-cmd.d.ts +16 -0
  31. package/dist/commands/coaching-cmd.d.ts.map +1 -0
  32. package/dist/commands/coaching-cmd.js +231 -0
  33. package/dist/commands/coaching-cmd.js.map +1 -0
  34. package/dist/commands/config-cmd.d.ts +30 -0
  35. package/dist/commands/config-cmd.d.ts.map +1 -0
  36. package/dist/commands/config-cmd.js +378 -0
  37. package/dist/commands/config-cmd.js.map +1 -0
  38. package/dist/commands/context.d.ts +41 -0
  39. package/dist/commands/context.d.ts.map +1 -0
  40. package/dist/commands/context.js +391 -0
  41. package/dist/commands/context.js.map +1 -0
  42. package/dist/commands/decisions.d.ts +57 -0
  43. package/dist/commands/decisions.d.ts.map +1 -0
  44. package/dist/commands/decisions.js +352 -0
  45. package/dist/commands/decisions.js.map +1 -0
  46. package/dist/commands/edge-cmd.d.ts +78 -0
  47. package/dist/commands/edge-cmd.d.ts.map +1 -0
  48. package/dist/commands/edge-cmd.js +185 -0
  49. package/dist/commands/edge-cmd.js.map +1 -0
  50. package/dist/commands/edge-guard-cmd.d.ts +36 -0
  51. package/dist/commands/edge-guard-cmd.d.ts.map +1 -0
  52. package/dist/commands/edge-guard-cmd.js +174 -0
  53. package/dist/commands/edge-guard-cmd.js.map +1 -0
  54. package/dist/commands/events.d.ts +3 -0
  55. package/dist/commands/events.d.ts.map +1 -0
  56. package/dist/commands/events.js +117 -0
  57. package/dist/commands/events.js.map +1 -0
  58. package/dist/commands/infra.d.ts +20 -0
  59. package/dist/commands/infra.d.ts.map +1 -0
  60. package/dist/commands/infra.js +130 -0
  61. package/dist/commands/infra.js.map +1 -0
  62. package/dist/commands/journal.d.ts +3 -0
  63. package/dist/commands/journal.d.ts.map +1 -0
  64. package/dist/commands/journal.js +281 -0
  65. package/dist/commands/journal.js.map +1 -0
  66. package/dist/commands/login.d.ts +18 -0
  67. package/dist/commands/login.d.ts.map +1 -0
  68. package/dist/commands/login.js +121 -0
  69. package/dist/commands/login.js.map +1 -0
  70. package/dist/commands/logout.d.ts +7 -0
  71. package/dist/commands/logout.d.ts.map +1 -0
  72. package/dist/commands/logout.js +39 -0
  73. package/dist/commands/logout.js.map +1 -0
  74. package/dist/commands/narratives.d.ts +3 -0
  75. package/dist/commands/narratives.d.ts.map +1 -0
  76. package/dist/commands/narratives.js +259 -0
  77. package/dist/commands/narratives.js.map +1 -0
  78. package/dist/commands/onboarding.d.ts +7 -0
  79. package/dist/commands/onboarding.d.ts.map +1 -0
  80. package/dist/commands/onboarding.js +126 -0
  81. package/dist/commands/onboarding.js.map +1 -0
  82. package/dist/commands/query.d.ts +32 -0
  83. package/dist/commands/query.d.ts.map +1 -0
  84. package/dist/commands/query.js +132 -0
  85. package/dist/commands/query.js.map +1 -0
  86. package/dist/commands/replay-cmd.d.ts +43 -0
  87. package/dist/commands/replay-cmd.d.ts.map +1 -0
  88. package/dist/commands/replay-cmd.js +215 -0
  89. package/dist/commands/replay-cmd.js.map +1 -0
  90. package/dist/commands/review.d.ts +3 -0
  91. package/dist/commands/review.d.ts.map +1 -0
  92. package/dist/commands/review.js +443 -0
  93. package/dist/commands/review.js.map +1 -0
  94. package/dist/commands/risk.d.ts +47 -0
  95. package/dist/commands/risk.d.ts.map +1 -0
  96. package/dist/commands/risk.js +156 -0
  97. package/dist/commands/risk.js.map +1 -0
  98. package/dist/commands/social.d.ts +43 -0
  99. package/dist/commands/social.d.ts.map +1 -0
  100. package/dist/commands/social.js +318 -0
  101. package/dist/commands/social.js.map +1 -0
  102. package/dist/commands/strategy-cmd.d.ts +44 -0
  103. package/dist/commands/strategy-cmd.d.ts.map +1 -0
  104. package/dist/commands/strategy-cmd.js +367 -0
  105. package/dist/commands/strategy-cmd.js.map +1 -0
  106. package/dist/commands/subscribe.d.ts +72 -0
  107. package/dist/commands/subscribe.d.ts.map +1 -0
  108. package/dist/commands/subscribe.js +480 -0
  109. package/dist/commands/subscribe.js.map +1 -0
  110. package/dist/commands/suggestions-cmd.d.ts +24 -0
  111. package/dist/commands/suggestions-cmd.d.ts.map +1 -0
  112. package/dist/commands/suggestions-cmd.js +142 -0
  113. package/dist/commands/suggestions-cmd.js.map +1 -0
  114. package/dist/commands/thesis-cmd.d.ts +3 -0
  115. package/dist/commands/thesis-cmd.d.ts.map +1 -0
  116. package/dist/commands/thesis-cmd.js +132 -0
  117. package/dist/commands/thesis-cmd.js.map +1 -0
  118. package/dist/commands/trader.d.ts +29 -0
  119. package/dist/commands/trader.d.ts.map +1 -0
  120. package/dist/commands/trader.js +292 -0
  121. package/dist/commands/trader.js.map +1 -0
  122. package/dist/commands/watch.d.ts +16 -0
  123. package/dist/commands/watch.d.ts.map +1 -0
  124. package/dist/commands/watch.js +88 -0
  125. package/dist/commands/watch.js.map +1 -0
  126. package/dist/commands/whoami.d.ts +14 -0
  127. package/dist/commands/whoami.d.ts.map +1 -0
  128. package/dist/commands/whoami.js +89 -0
  129. package/dist/commands/whoami.js.map +1 -0
  130. package/dist/credentials.d.ts +18 -0
  131. package/dist/credentials.d.ts.map +1 -0
  132. package/dist/credentials.js +168 -0
  133. package/dist/credentials.js.map +1 -0
  134. package/dist/index.d.ts +33 -0
  135. package/dist/index.d.ts.map +1 -0
  136. package/dist/index.js +28 -0
  137. package/dist/index.js.map +1 -0
  138. package/dist/utils.d.ts +51 -0
  139. package/dist/utils.d.ts.map +1 -0
  140. package/dist/utils.js +118 -0
  141. package/dist/utils.js.map +1 -0
  142. package/package.json +38 -0
package/README.md ADDED
@@ -0,0 +1,8 @@
1
+ # @trading-boy/cli
2
+
3
+ Command-line interface for Trading Boy, built with Commander.js.
4
+
5
+ ## Structure
6
+
7
+ - **index.ts** — CLI entry point and command registration
8
+ - **commands/** — Individual command implementations
@@ -0,0 +1,35 @@
1
+ import { redactApiKey } from './credentials.js';
2
+ export interface ApiResponse<T> {
3
+ data: T;
4
+ status: number;
5
+ }
6
+ export declare class ApiError extends Error {
7
+ readonly status: number;
8
+ readonly body?: unknown | undefined;
9
+ constructor(message: string, status: number, body?: unknown | undefined);
10
+ }
11
+ /**
12
+ * Dev mode: TRADING_BOY_API_URL points to localhost AND NODE_ENV=development.
13
+ * In dev mode, auth is not required (local API server runs without API keys).
14
+ */
15
+ export declare function isDevMode(): boolean;
16
+ export declare function resolveApiKey(flagKey?: string): Promise<string>;
17
+ export declare function getApiBase(): string;
18
+ export declare function apiRequest<T>(path: string, options?: {
19
+ method?: string;
20
+ body?: unknown;
21
+ apiKey?: string;
22
+ headers?: Record<string, string>;
23
+ }): Promise<T>;
24
+ /**
25
+ * Check if the CLI should use remote API mode.
26
+ *
27
+ * Remote mode activates when the user has an API key (from `login` or env var).
28
+ * In remote mode, commands route through the REST API instead of direct DB connections.
29
+ *
30
+ * Local/dev mode: direct DB connections (requires NEO4J_URI, TIMESCALE_HOST, etc.)
31
+ * Remote mode: HTTP requests to TRADING_BOY_API_URL (defaults to https://api.cabal.ventures)
32
+ */
33
+ export declare function isRemoteMode(): Promise<boolean>;
34
+ export { redactApiKey };
35
+ //# sourceMappingURL=api-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api-client.d.ts","sourceRoot":"","sources":["../src/api-client.ts"],"names":[],"mappings":"AACA,OAAO,EAAmB,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAUjE,MAAM,WAAW,WAAW,CAAC,CAAC;IAC5B,IAAI,EAAE,CAAC,CAAC;IACR,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,qBAAa,QAAS,SAAQ,KAAK;aAGf,MAAM,EAAE,MAAM;aACd,IAAI,CAAC,EAAE,OAAO;gBAF9B,OAAO,EAAE,MAAM,EACC,MAAM,EAAE,MAAM,EACd,IAAI,CAAC,EAAE,OAAO,YAAA;CAKjC;AAID;;;GAGG;AACH,wBAAgB,SAAS,IAAI,OAAO,CAUnC;AAID,wBAAsB,aAAa,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAoBrE;AAwBD,wBAAgB,UAAU,IAAI,MAAM,CAInC;AAID,wBAAsB,UAAU,CAAC,CAAC,EAChC,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE;IACP,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC7B,GACL,OAAO,CAAC,CAAC,CAAC,CA6EZ;AAID;;;;;;;;GAQG;AACH,wBAAsB,YAAY,IAAI,OAAO,CAAC,OAAO,CAAC,CAerD;AAED,OAAO,EAAE,YAAY,EAAE,CAAC"}
@@ -0,0 +1,165 @@
1
+ import { createLogger } from '@trading-boy/core';
2
+ import { loadCredentials, redactApiKey } from './credentials.js';
3
+ const logger = createLogger('cli-api-client');
4
+ // ─── Constants ───
5
+ const DEFAULT_API_BASE = 'https://api.cabal.ventures';
6
+ export class ApiError extends Error {
7
+ status;
8
+ body;
9
+ constructor(message, status, body) {
10
+ super(message);
11
+ this.status = status;
12
+ this.body = body;
13
+ this.name = 'ApiError';
14
+ }
15
+ }
16
+ // ─── Dev Mode Detection ───
17
+ /**
18
+ * Dev mode: TRADING_BOY_API_URL points to localhost AND NODE_ENV=development.
19
+ * In dev mode, auth is not required (local API server runs without API keys).
20
+ */
21
+ export function isDevMode() {
22
+ if (process.env.NODE_ENV !== 'development')
23
+ return false;
24
+ const url = process.env.TRADING_BOY_API_URL;
25
+ if (!url)
26
+ return false;
27
+ try {
28
+ const parsed = new URL(url);
29
+ return parsed.hostname === 'localhost' || parsed.hostname === '127.0.0.1' || parsed.hostname === '::1';
30
+ }
31
+ catch {
32
+ return false;
33
+ }
34
+ }
35
+ // ─── API Key Resolution ───
36
+ export async function resolveApiKey(flagKey) {
37
+ // Priority: env var > flag > stored key
38
+ const envKey = process.env.TRADING_BOY_API_KEY;
39
+ if (envKey) {
40
+ logger.debug('Using API key from TRADING_BOY_API_KEY env var');
41
+ return envKey;
42
+ }
43
+ if (flagKey) {
44
+ logger.debug('Using API key from --api-key flag');
45
+ return flagKey;
46
+ }
47
+ const stored = await loadCredentials();
48
+ if (stored?.apiKey) {
49
+ logger.debug('Using stored API key');
50
+ return stored.apiKey;
51
+ }
52
+ throw new Error('Not authenticated. Run `trading-boy login` to set up your API key.');
53
+ }
54
+ // ─── HTTPS Warning ───
55
+ let httpsWarningShown = false;
56
+ function warnIfInsecure(url) {
57
+ if (httpsWarningShown)
58
+ return;
59
+ try {
60
+ const parsed = new URL(url);
61
+ const isLocalhost = parsed.hostname === 'localhost' || parsed.hostname === '127.0.0.1' || parsed.hostname === '::1';
62
+ if (parsed.protocol === 'http:' && !isLocalhost) {
63
+ httpsWarningShown = true;
64
+ logger.warn({ url: parsed.origin }, 'API connection is not using HTTPS — credentials may be transmitted in plaintext');
65
+ // Also print to stderr so CLI users see it
66
+ process.stderr.write(`\x1b[33mWarning: API URL ${parsed.origin} is not using HTTPS. Your API key may be sent in plaintext.\nSet TRADING_BOY_API_URL to an https:// endpoint for production use.\x1b[0m\n`);
67
+ }
68
+ }
69
+ catch {
70
+ // Invalid URL — will fail at fetch time
71
+ }
72
+ }
73
+ // ─── API Base URL ───
74
+ export function getApiBase() {
75
+ const base = process.env.TRADING_BOY_API_URL || DEFAULT_API_BASE;
76
+ warnIfInsecure(base);
77
+ return base;
78
+ }
79
+ // ─── API Request ───
80
+ export async function apiRequest(path, options = {}) {
81
+ const dev = isDevMode();
82
+ const apiKey = dev ? undefined : (options.apiKey ?? (await resolveApiKey()));
83
+ const apiBase = getApiBase();
84
+ const url = `${apiBase}${path}`;
85
+ const headers = {
86
+ ...(apiKey ? { 'X-API-Key': apiKey } : {}),
87
+ ...(options.body ? { 'Content-Type': 'application/json' } : {}),
88
+ ...options.headers,
89
+ };
90
+ const fetchOptions = {
91
+ method: options.method ?? 'GET',
92
+ headers,
93
+ };
94
+ if (options.body) {
95
+ fetchOptions.body = JSON.stringify(options.body);
96
+ }
97
+ logger.debug({ url, method: fetchOptions.method }, 'API request');
98
+ let response;
99
+ try {
100
+ response = await fetch(url, fetchOptions);
101
+ }
102
+ catch (error) {
103
+ // Network-level failures (connection refused, DNS errors, timeouts)
104
+ const msg = error instanceof Error ? error.message : String(error);
105
+ const lower = msg.toLowerCase();
106
+ if (lower.includes('econnrefused') || lower.includes('fetch failed') || lower.includes('enotfound') || lower.includes('connection refused')) {
107
+ throw new ApiError(`Cannot connect to API at ${apiBase}. The server may be offline or unreachable.\n` +
108
+ ' → Check your connection or try again later.\n' +
109
+ ' → If self-hosting, ensure the API is running: pnpm start:api', 0);
110
+ }
111
+ throw new ApiError(`Network error: ${msg}`, 0);
112
+ }
113
+ if (response.status === 401) {
114
+ throw new ApiError('API key invalid or expired. Run `trading-boy login` to re-authenticate.', 401);
115
+ }
116
+ if (response.status === 403) {
117
+ throw new ApiError('Subscription inactive. Run `trading-boy billing manage` to update your billing.', 403);
118
+ }
119
+ if (response.status === 429) {
120
+ const retryAfter = response.headers.get('Retry-After');
121
+ throw new ApiError(`Rate limited. Retry after ${retryAfter ?? '60'}s.`, 429);
122
+ }
123
+ if (!response.ok) {
124
+ let body;
125
+ try {
126
+ body = await response.json();
127
+ }
128
+ catch {
129
+ body = await response.text().catch(() => null);
130
+ }
131
+ const errorMessage = (body && typeof body === 'object' && 'error' in body && typeof body.error === 'string')
132
+ ? body.error
133
+ : `API error: ${response.status}`;
134
+ throw new ApiError(errorMessage, response.status, body);
135
+ }
136
+ return (await response.json());
137
+ }
138
+ // ─── Remote Mode Detection ───
139
+ /**
140
+ * Check if the CLI should use remote API mode.
141
+ *
142
+ * Remote mode activates when the user has an API key (from `login` or env var).
143
+ * In remote mode, commands route through the REST API instead of direct DB connections.
144
+ *
145
+ * Local/dev mode: direct DB connections (requires NEO4J_URI, TIMESCALE_HOST, etc.)
146
+ * Remote mode: HTTP requests to TRADING_BOY_API_URL (defaults to https://api.cabal.ventures)
147
+ */
148
+ export async function isRemoteMode() {
149
+ // Explicit env var override
150
+ if (process.env.TRADING_BOY_LOCAL === 'true')
151
+ return false;
152
+ // Tests always run in local mode
153
+ if (process.env.NODE_ENV === 'test')
154
+ return false;
155
+ // If API URL is explicitly set, use remote mode
156
+ if (process.env.TRADING_BOY_API_URL)
157
+ return true;
158
+ // If API key is available (env or stored), use remote mode
159
+ if (process.env.TRADING_BOY_API_KEY)
160
+ return true;
161
+ const stored = await loadCredentials();
162
+ return !!stored?.apiKey;
163
+ }
164
+ export { redactApiKey };
165
+ //# sourceMappingURL=api-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api-client.js","sourceRoot":"","sources":["../src/api-client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAEjE,MAAM,MAAM,GAAG,YAAY,CAAC,gBAAgB,CAAC,CAAC;AAE9C,oBAAoB;AAEpB,MAAM,gBAAgB,GAAG,4BAA4B,CAAC;AAStD,MAAM,OAAO,QAAS,SAAQ,KAAK;IAGf;IACA;IAHlB,YACE,OAAe,EACC,MAAc,EACd,IAAc;QAE9B,KAAK,CAAC,OAAO,CAAC,CAAC;QAHC,WAAM,GAAN,MAAM,CAAQ;QACd,SAAI,GAAJ,IAAI,CAAU;QAG9B,IAAI,CAAC,IAAI,GAAG,UAAU,CAAC;IACzB,CAAC;CACF;AAED,6BAA6B;AAE7B;;;GAGG;AACH,MAAM,UAAU,SAAS;IACvB,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,aAAa;QAAE,OAAO,KAAK,CAAC;IACzD,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC;IAC5C,IAAI,CAAC,GAAG;QAAE,OAAO,KAAK,CAAC;IACvB,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC;QAC5B,OAAO,MAAM,CAAC,QAAQ,KAAK,WAAW,IAAI,MAAM,CAAC,QAAQ,KAAK,WAAW,IAAI,MAAM,CAAC,QAAQ,KAAK,KAAK,CAAC;IACzG,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,6BAA6B;AAE7B,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,OAAgB;IAClD,wCAAwC;IACxC,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC;IAC/C,IAAI,MAAM,EAAE,CAAC;QACX,MAAM,CAAC,KAAK,CAAC,gDAAgD,CAAC,CAAC;QAC/D,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,IAAI,OAAO,EAAE,CAAC;QACZ,MAAM,CAAC,KAAK,CAAC,mCAAmC,CAAC,CAAC;QAClD,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,eAAe,EAAE,CAAC;IACvC,IAAI,MAAM,EAAE,MAAM,EAAE,CAAC;QACnB,MAAM,CAAC,KAAK,CAAC,sBAAsB,CAAC,CAAC;QACrC,OAAO,MAAM,CAAC,MAAM,CAAC;IACvB,CAAC;IAED,MAAM,IAAI,KAAK,CAAC,oEAAoE,CAAC,CAAC;AACxF,CAAC;AAED,wBAAwB;AAExB,IAAI,iBAAiB,GAAG,KAAK,CAAC;AAE9B,SAAS,cAAc,CAAC,GAAW;IACjC,IAAI,iBAAiB;QAAE,OAAO;IAC9B,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC;QAC5B,MAAM,WAAW,GAAG,MAAM,CAAC,QAAQ,KAAK,WAAW,IAAI,MAAM,CAAC,QAAQ,KAAK,WAAW,IAAI,MAAM,CAAC,QAAQ,KAAK,KAAK,CAAC;QACpH,IAAI,MAAM,CAAC,QAAQ,KAAK,OAAO,IAAI,CAAC,WAAW,EAAE,CAAC;YAChD,iBAAiB,GAAG,IAAI,CAAC;YACzB,MAAM,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,EAAE,iFAAiF,CAAC,CAAC;YACvH,2CAA2C;YAC3C,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,4BAA4B,MAAM,CAAC,MAAM,2IAA2I,CAAC,CAAC;QAC7M,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,wCAAwC;IAC1C,CAAC;AACH,CAAC;AAED,uBAAuB;AAEvB,MAAM,UAAU,UAAU;IACxB,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,mBAAmB,IAAI,gBAAgB,CAAC;IACjE,cAAc,CAAC,IAAI,CAAC,CAAC;IACrB,OAAO,IAAI,CAAC;AACd,CAAC;AAED,sBAAsB;AAEtB,MAAM,CAAC,KAAK,UAAU,UAAU,CAC9B,IAAY,EACZ,UAKI,EAAE;IAEN,MAAM,GAAG,GAAG,SAAS,EAAE,CAAC;IACxB,MAAM,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,IAAI,CAAC,MAAM,aAAa,EAAE,CAAC,CAAC,CAAC;IAC7E,MAAM,OAAO,GAAG,UAAU,EAAE,CAAC;IAC7B,MAAM,GAAG,GAAG,GAAG,OAAO,GAAG,IAAI,EAAE,CAAC;IAEhC,MAAM,OAAO,GAA2B;QACtC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC1C,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,cAAc,EAAE,kBAAkB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC/D,GAAG,OAAO,CAAC,OAAO;KACnB,CAAC;IAEF,MAAM,YAAY,GAAgB;QAChC,MAAM,EAAE,OAAO,CAAC,MAAM,IAAI,KAAK;QAC/B,OAAO;KACR,CAAC;IAEF,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;QACjB,YAAY,CAAC,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IACnD,CAAC;IAED,MAAM,CAAC,KAAK,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,YAAY,CAAC,MAAM,EAAE,EAAE,aAAa,CAAC,CAAC;IAElE,IAAI,QAAkB,CAAC;IACvB,IAAI,CAAC;QACH,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE,YAAY,CAAC,CAAC;IAC5C,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,oEAAoE;QACpE,MAAM,GAAG,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACnE,MAAM,KAAK,GAAG,GAAG,CAAC,WAAW,EAAE,CAAC;QAChC,IAAI,KAAK,CAAC,QAAQ,CAAC,cAAc,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,cAAc,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,WAAW,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,oBAAoB,CAAC,EAAE,CAAC;YAC5I,MAAM,IAAI,QAAQ,CAChB,4BAA4B,OAAO,+CAA+C;gBAClF,iDAAiD;gBACjD,gEAAgE,EAChE,CAAC,CACF,CAAC;QACJ,CAAC;QACD,MAAM,IAAI,QAAQ,CAAC,kBAAkB,GAAG,EAAE,EAAE,CAAC,CAAC,CAAC;IACjD,CAAC;IAED,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;QAC5B,MAAM,IAAI,QAAQ,CAChB,yEAAyE,EACzE,GAAG,CACJ,CAAC;IACJ,CAAC;IAED,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;QAC5B,MAAM,IAAI,QAAQ,CAChB,iFAAiF,EACjF,GAAG,CACJ,CAAC;IACJ,CAAC;IAED,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;QAC5B,MAAM,UAAU,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;QACvD,MAAM,IAAI,QAAQ,CAChB,6BAA6B,UAAU,IAAI,IAAI,IAAI,EACnD,GAAG,CACJ,CAAC;IACJ,CAAC;IAED,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,IAAI,IAAa,CAAC;QAClB,IAAI,CAAC;YACH,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;QAC/B,CAAC;QAAC,MAAM,CAAC;YACP,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC;QACjD,CAAC;QACD,MAAM,YAAY,GAAG,CAAC,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,OAAO,IAAI,IAAI,IAAI,OAAQ,IAAgC,CAAC,KAAK,KAAK,QAAQ,CAAC;YACvI,CAAC,CAAE,IAA+B,CAAC,KAAK;YACxC,CAAC,CAAC,cAAc,QAAQ,CAAC,MAAM,EAAE,CAAC;QACpC,MAAM,IAAI,QAAQ,CAAC,YAAY,EAAE,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IAC1D,CAAC;IAED,OAAO,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAM,CAAC;AACtC,CAAC;AAED,gCAAgC;AAEhC;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY;IAChC,4BAA4B;IAC5B,IAAI,OAAO,CAAC,GAAG,CAAC,iBAAiB,KAAK,MAAM;QAAE,OAAO,KAAK,CAAC;IAE3D,iCAAiC;IACjC,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,MAAM;QAAE,OAAO,KAAK,CAAC;IAElD,gDAAgD;IAChD,IAAI,OAAO,CAAC,GAAG,CAAC,mBAAmB;QAAE,OAAO,IAAI,CAAC;IAEjD,2DAA2D;IAC3D,IAAI,OAAO,CAAC,GAAG,CAAC,mBAAmB;QAAE,OAAO,IAAI,CAAC;IAEjD,MAAM,MAAM,GAAG,MAAM,eAAe,EAAE,CAAC;IACvC,OAAO,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC;AAC1B,CAAC;AAED,OAAO,EAAE,YAAY,EAAE,CAAC"}
package/dist/cli.d.ts ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env node
2
+ import { Command } from 'commander';
3
+ export declare function createCli(): Command;
4
+ export declare function main(): Promise<void>;
5
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAgBA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA0CpC,wBAAgB,SAAS,IAAI,OAAO,CA0FnC;AAID,wBAAsB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAG1C"}
package/dist/cli.js ADDED
@@ -0,0 +1,143 @@
1
+ #!/usr/bin/env node
2
+ // Suppress pino INFO logs in CLI — only show warnings and errors
3
+ if (!process.env.LOG_LEVEL) {
4
+ process.env.LOG_LEVEL = 'warn';
5
+ }
6
+ // Tell the logger to write to stderr so stdout stays clean for piping
7
+ process.env.TRADING_BOY_CLI = '1';
8
+ // TTY detection: when piped, disable colors and spinners for machine-parseable output
9
+ if (!process.stdout.isTTY) {
10
+ process.env.FORCE_COLOR = '0'; // Ensure chalk strips ANSI codes
11
+ process.env.NO_COLOR = '1'; // Standard no-color convention (https://no-color.org)
12
+ }
13
+ import { Command } from 'commander';
14
+ import { registerQueryCommand } from './commands/query.js';
15
+ import { registerWatchCommand } from './commands/watch.js';
16
+ import { registerCatalystsCommand } from './commands/catalysts.js';
17
+ import { registerRiskCommand } from './commands/risk.js';
18
+ import { registerDecisionsCommand } from './commands/decisions.js';
19
+ import { registerTraderCommand } from './commands/trader.js';
20
+ import { registerBehavioralCommand } from './commands/behavioral.js';
21
+ import { registerSocialCommand } from './commands/social.js';
22
+ import { registerNarrativeCommand } from './commands/narratives.js';
23
+ import { registerEventsCommand } from './commands/events.js';
24
+ import { registerJournalCommand } from './commands/journal.js';
25
+ import { registerAuditCommand } from './commands/audit.js';
26
+ import { registerContextCommand } from './commands/context.js';
27
+ import { registerConfigCommand } from './commands/config-cmd.js';
28
+ import { registerInfraCommand } from './commands/infra.js';
29
+ import { registerLoginCommand } from './commands/login.js';
30
+ import { registerLogoutCommand } from './commands/logout.js';
31
+ import { registerWhoamiCommand } from './commands/whoami.js';
32
+ import { registerBillingCommand } from './commands/billing.js';
33
+ import { registerSubscribeCommand } from './commands/subscribe.js';
34
+ import { registerEdgeCommand } from './commands/edge-cmd.js';
35
+ import { registerEdgeGuardCommand } from './commands/edge-guard-cmd.js';
36
+ import { registerCoachingCommand } from './commands/coaching-cmd.js';
37
+ import { registerThesisCommand } from './commands/thesis-cmd.js';
38
+ import { registerStrategyCommand } from './commands/strategy-cmd.js';
39
+ import { registerReplayCommand } from './commands/replay-cmd.js';
40
+ import { registerBenchmarkCommand } from './commands/benchmark-cmd.js';
41
+ import { registerSuggestionsCommand } from './commands/suggestions-cmd.js';
42
+ import { readFileSync } from 'node:fs';
43
+ import { fileURLToPath } from 'node:url';
44
+ import { dirname, resolve } from 'node:path';
45
+ // ─── CLI Setup ───
46
+ function getVersion() {
47
+ const __dirname = dirname(fileURLToPath(import.meta.url));
48
+ const pkgPath = resolve(__dirname, '..', 'package.json');
49
+ const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8'));
50
+ return pkg.version;
51
+ }
52
+ export function createCli() {
53
+ const program = new Command();
54
+ program
55
+ .name('trading-boy')
56
+ .description('Trading Boy — Crypto context graph system for traders and agentic trading systems')
57
+ .version(getVersion());
58
+ // ─── Register all commands ───
59
+ // Primary: context assembly
60
+ registerContextCommand(program);
61
+ // Data queries
62
+ registerQueryCommand(program);
63
+ registerWatchCommand(program);
64
+ registerCatalystsCommand(program);
65
+ registerRiskCommand(program);
66
+ registerSocialCommand(program);
67
+ registerNarrativeCommand(program);
68
+ // Trading journal & decisions
69
+ registerJournalCommand(program);
70
+ registerDecisionsCommand(program);
71
+ registerTraderCommand(program);
72
+ registerBehavioralCommand(program);
73
+ registerAuditCommand(program);
74
+ registerEventsCommand(program);
75
+ // Edge analysis & safety
76
+ registerEdgeCommand(program);
77
+ registerEdgeGuardCommand(program);
78
+ // Authentication & billing
79
+ registerLoginCommand(program);
80
+ registerLogoutCommand(program);
81
+ registerWhoamiCommand(program);
82
+ registerBillingCommand(program);
83
+ registerSubscribeCommand(program);
84
+ // Learning & coaching
85
+ registerCoachingCommand(program);
86
+ registerThesisCommand(program);
87
+ // Strategy, replay & benchmark
88
+ registerStrategyCommand(program);
89
+ registerReplayCommand(program);
90
+ registerBenchmarkCommand(program);
91
+ registerSuggestionsCommand(program);
92
+ // System management
93
+ registerConfigCommand(program);
94
+ registerInfraCommand(program);
95
+ // ─── Custom grouped help display (P1-5) ───
96
+ const GROUPS = {
97
+ 'Core': ['context', 'query', 'watch'],
98
+ 'Data & Analysis': ['catalysts', 'risk', 'social', 'narrative', 'events'],
99
+ 'Trading Journal': ['journal', 'decisions', 'stats', 'trader', 'behavioral', 'audit'],
100
+ 'Edge & Safety': ['edge', 'edge-guard', 'coaching', 'thesis'],
101
+ 'Strategy & Benchmarking': ['strategy', 'replay', 'benchmark', 'suggestions'],
102
+ 'Account': ['login', 'logout', 'whoami', 'billing', 'subscribe'],
103
+ 'System': ['config', 'infra'],
104
+ };
105
+ program.addHelpText('before', '');
106
+ program.addHelpText('after', () => {
107
+ const commands = program.commands;
108
+ const cmdMap = new Map(commands.map((c) => [c.name(), c]));
109
+ const pad = 18;
110
+ const lines = ['', 'Command Groups:'];
111
+ const grouped = new Set();
112
+ for (const [groupName, cmdNames] of Object.entries(GROUPS)) {
113
+ const groupCmds = cmdNames.filter((n) => cmdMap.has(n));
114
+ if (groupCmds.length === 0)
115
+ continue;
116
+ lines.push(`\n ${groupName}:`);
117
+ for (const name of groupCmds) {
118
+ const c = cmdMap.get(name);
119
+ lines.push(` ${name.padEnd(pad)}${c.description() || ''}`);
120
+ grouped.add(name);
121
+ }
122
+ }
123
+ return lines.join('\n');
124
+ });
125
+ return program;
126
+ }
127
+ // ─── Main Entry Point ───
128
+ export async function main() {
129
+ const program = createCli();
130
+ await program.parseAsync(process.argv);
131
+ }
132
+ // Auto-execute when run directly (not during test imports)
133
+ const scriptName = process.argv[1] ?? '';
134
+ const isDirectRun = scriptName.endsWith('cli.js') ||
135
+ scriptName.endsWith('cli.ts') ||
136
+ scriptName.endsWith('/trading-boy');
137
+ if (isDirectRun) {
138
+ main().catch((err) => {
139
+ console.error(err);
140
+ process.exit(1);
141
+ });
142
+ }
143
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ import { Command } from 'commander';
2
+ export interface AuditVerifyResult {
3
+ valid: boolean;
4
+ chainLength: number;
5
+ verifiedCount: number;
6
+ breakPoint?: {
7
+ index: number;
8
+ decisionId: string;
9
+ decisionType: string;
10
+ eventTime: string;
11
+ };
12
+ }
13
+ /**
14
+ * Format audit verification output with chalk styling.
15
+ */
16
+ export declare function formatAuditVerifyOutput(result: AuditVerifyResult, elapsedMs: number): string;
17
+ export declare function registerAuditCommand(program: Command): void;
18
+ //# sourceMappingURL=audit.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audit.d.ts","sourceRoot":"","sources":["../../src/commands/audit.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAU,MAAM,WAAW,CAAC;AAgB5C,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,OAAO,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE;QACX,KAAK,EAAE,MAAM,CAAC;QACd,UAAU,EAAE,MAAM,CAAC;QACnB,YAAY,EAAE,MAAM,CAAC;QACrB,SAAS,EAAE,MAAM,CAAC;KACnB,CAAC;CACH;AAID;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,iBAAiB,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAwB5F;AAID,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAwC3D"}
@@ -0,0 +1,73 @@
1
+ import { Option } from 'commander';
2
+ import chalk from 'chalk';
3
+ import { createLogger } from '@trading-boy/core';
4
+ import { formatConnectionError } from '../utils.js';
5
+ import { apiRequest, ApiError } from '../api-client.js';
6
+ // ─── Logger ───
7
+ const logger = createLogger('cli-audit');
8
+ // ─── Default Trader ───
9
+ const DEFAULT_TRADER_ID = 'default';
10
+ // ─── Formatter ───
11
+ /**
12
+ * Format audit verification output with chalk styling.
13
+ */
14
+ export function formatAuditVerifyOutput(result, elapsedMs) {
15
+ const lines = [];
16
+ lines.push('');
17
+ lines.push(chalk.bold.cyan(' Audit Verification'));
18
+ lines.push(chalk.gray(' ' + '\u2500'.repeat(50)));
19
+ lines.push('');
20
+ if (result.valid) {
21
+ lines.push(` ${chalk.green('\u2713')} ${chalk.green('Chain integrity verified')}`);
22
+ lines.push(` ${chalk.gray('Decisions verified:')} ${chalk.white(String(result.verifiedCount))}`);
23
+ lines.push(` ${chalk.gray('Chain length:')} ${chalk.white(String(result.chainLength))}`);
24
+ }
25
+ else {
26
+ lines.push(` ${chalk.red('\u2717')} ${chalk.red(`Chain integrity BROKEN at decision ${result.breakPoint.index}`)}`);
27
+ lines.push(` ${chalk.gray('Decision ID:')} ${chalk.white(result.breakPoint.decisionId)}`);
28
+ lines.push(` ${chalk.gray('Type:')} ${chalk.white(result.breakPoint.decisionType)}`);
29
+ lines.push(` ${chalk.gray('Event time:')} ${chalk.white(result.breakPoint.eventTime)}`);
30
+ lines.push(` ${chalk.gray('Verified:')} ${chalk.yellow(`${result.verifiedCount} of ${result.chainLength}`)} decisions`);
31
+ }
32
+ lines.push(` ${chalk.dim(`Elapsed: ${elapsedMs.toFixed(2)}ms`)}`);
33
+ lines.push('');
34
+ return lines.join('\n');
35
+ }
36
+ // ─── Command Registration ───
37
+ export function registerAuditCommand(program) {
38
+ const audit = program
39
+ .command('audit')
40
+ .description('Audit and integrity verification commands');
41
+ // ─── audit verify ───
42
+ audit
43
+ .command('verify')
44
+ .description('Verify the integrity of the decision hash chain')
45
+ .option('--trader <traderId>', 'Trader ID', DEFAULT_TRADER_ID)
46
+ .addOption(new Option('--format <format>', 'Output format').choices(['text', 'json']).default('text'))
47
+ .action(async (options) => {
48
+ try {
49
+ const startTime = performance.now();
50
+ const result = await apiRequest(`/api/v1/audit/verify?traderId=${encodeURIComponent(options.trader)}`);
51
+ const elapsed = performance.now() - startTime;
52
+ if (options.format === 'json') {
53
+ console.log(JSON.stringify({ ...result, elapsedMs: Number(elapsed.toFixed(2)) }, null, 2));
54
+ }
55
+ else {
56
+ console.log(formatAuditVerifyOutput(result, elapsed));
57
+ }
58
+ logger.debug({ elapsed: elapsed.toFixed(2) + 'ms' }, 'Chain verification complete');
59
+ }
60
+ catch (error) {
61
+ const message = error instanceof Error ? error.message : String(error);
62
+ logger.error({ error: message }, 'Failed to verify chain');
63
+ console.error(`Error: ${message}`);
64
+ if (!(error instanceof ApiError)) {
65
+ const guidance = formatConnectionError(message);
66
+ if (guidance)
67
+ console.error(guidance);
68
+ }
69
+ process.exitCode = error instanceof ApiError ? 2 : 1;
70
+ }
71
+ });
72
+ }
73
+ //# sourceMappingURL=audit.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audit.js","sourceRoot":"","sources":["../../src/commands/audit.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,73 @@
1
+ import { Command } from 'commander';
2
+ /**
3
+ * Parse a period string like "30d", "7d", "90d" into days.
4
+ * Returns default 30 if the string cannot be parsed.
5
+ */
6
+ export declare function parsePeriodDays(period: string): number;
7
+ /** Behavioral pattern enum values (kept local to avoid context-engine dep) */
8
+ declare const BehavioralPatternValues: {
9
+ readonly REVENGE_TRADING: "REVENGE_TRADING";
10
+ readonly FOMO_ENTRY: "FOMO_ENTRY";
11
+ readonly OVERTRADING: "OVERTRADING";
12
+ readonly STOP_VIOLATION: "STOP_VIOLATION";
13
+ readonly TILT_CASCADE: "TILT_CASCADE";
14
+ };
15
+ type BehavioralPatternValue = (typeof BehavioralPatternValues)[keyof typeof BehavioralPatternValues];
16
+ interface BehavioralProfile {
17
+ traderId: string;
18
+ period: string;
19
+ revengeTradeCount: number;
20
+ fomoEntryCount: number;
21
+ overtradingDays: number;
22
+ stopViolationCount: number;
23
+ tiltCascadeCount: number;
24
+ commitmentHonorRate: number;
25
+ overallScore: number;
26
+ }
27
+ interface PatternCostEntry {
28
+ pattern: BehavioralPatternValue;
29
+ occurrences: number;
30
+ totalCost: number;
31
+ winRate: number;
32
+ }
33
+ interface PatternCostAnalysis {
34
+ entries: PatternCostEntry[];
35
+ totalBehavioralCost: number;
36
+ baselineWinRate: number;
37
+ totalPnl: number;
38
+ pnlWithoutBehavioralTrades: number;
39
+ }
40
+ /**
41
+ * Color-code a behavioral health score.
42
+ * 0-30: green (healthy), 31-60: yellow (watch), 61+: red (concerning)
43
+ */
44
+ export declare function colorScore(score: number): string;
45
+ /**
46
+ * Format a commitment honor rate as a colored percentage.
47
+ */
48
+ export declare function colorHonorRate(rate: number): string;
49
+ /**
50
+ * Return the label for a behavioral health score.
51
+ */
52
+ export declare function scoreLabel(score: number): string;
53
+ /**
54
+ * Format a full behavioral profile as a human-readable string.
55
+ */
56
+ export declare function formatBehavioralProfile(profile: BehavioralProfile): string;
57
+ /**
58
+ * Format a list of decisions with behavioral flags.
59
+ */
60
+ export declare function formatBehavioralFlags(decisions: Array<{
61
+ id: string;
62
+ eventTime: string;
63
+ tokenSymbol: string;
64
+ decisionType: string;
65
+ behavioralFlags: string[];
66
+ }>): string;
67
+ /**
68
+ * Format a pattern cost analysis as a human-readable table.
69
+ */
70
+ export declare function formatCostAnalysis(analysis: PatternCostAnalysis, period: string): string;
71
+ export declare function registerBehavioralCommand(program: Command): void;
72
+ export {};
73
+ //# sourceMappingURL=behavioral.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"behavioral.d.ts","sourceRoot":"","sources":["../../src/commands/behavioral.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAU,MAAM,WAAW,CAAC;AAgB5C;;;GAGG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAMtD;AAID,8EAA8E;AAC9E,QAAA,MAAM,uBAAuB;;;;;;CAMnB,CAAC;AAEX,KAAK,sBAAsB,GAAG,CAAC,OAAO,uBAAuB,CAAC,CAAC,MAAM,OAAO,uBAAuB,CAAC,CAAC;AAErG,UAAU,iBAAiB;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,iBAAiB,EAAE,MAAM,CAAC;IAC1B,cAAc,EAAE,MAAM,CAAC;IACvB,eAAe,EAAE,MAAM,CAAC;IACxB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,gBAAgB,EAAE,MAAM,CAAC;IACzB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,UAAU,gBAAgB;IACxB,OAAO,EAAE,sBAAsB,CAAC;IAChC,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,UAAU,mBAAmB;IAC3B,OAAO,EAAE,gBAAgB,EAAE,CAAC;IAC5B,mBAAmB,EAAE,MAAM,CAAC;IAC5B,eAAe,EAAE,MAAM,CAAC;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,0BAA0B,EAAE,MAAM,CAAC;CACpC;AAID;;;GAGG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAKhD;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAKnD;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAIhD;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,iBAAiB,GAAG,MAAM,CAoD1E;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CACnC,SAAS,EAAE,KAAK,CAAC;IACf,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,eAAe,EAAE,MAAM,EAAE,CAAC;CAC3B,CAAC,GACD,MAAM,CA0CR;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,mBAAmB,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CA6DxF;AA8CD,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CA8HhE"}