@alphafox/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.
- package/LICENSE +21 -0
- package/README.md +53 -0
- package/bin/alphafox.js +2 -0
- package/dist/auth/pkce.d.ts +13 -0
- package/dist/auth/pkce.js +27 -0
- package/dist/catalog/allowlist.d.ts +9 -0
- package/dist/catalog/allowlist.js +69 -0
- package/dist/catalog/operations.d.ts +34 -0
- package/dist/catalog/operations.js +247 -0
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +18 -0
- package/dist/commands/run.d.ts +14 -0
- package/dist/commands/run.js +855 -0
- package/dist/config/profiles.d.ts +29 -0
- package/dist/config/profiles.js +134 -0
- package/dist/envelope.d.ts +37 -0
- package/dist/envelope.js +78 -0
- package/dist/http/client.d.ts +19 -0
- package/dist/http/client.js +110 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +36 -0
- package/dist/keychain/store.d.ts +19 -0
- package/dist/keychain/store.js +149 -0
- package/dist/safety/confirmation.d.ts +22 -0
- package/dist/safety/confirmation.js +29 -0
- package/dist/version.d.ts +4 -0
- package/dist/version.js +7 -0
- package/docs/e2e-staging.md +24 -0
- package/docs/release-supply-chain.md +49 -0
- package/package.json +60 -0
- package/skills/account/SKILL.md +21 -0
- package/skills/admin/SKILL.md +19 -0
- package/skills/alphafox-shared/SKILL.md +59 -0
- package/skills/auth/SKILL.md +35 -0
- package/skills/exchange/SKILL.md +17 -0
- package/skills/market/SKILL.md +14 -0
- package/skills/notification/SKILL.md +16 -0
- package/skills/strategy/SKILL.md +37 -0
- package/skills/trading/SKILL.md +28 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Alphafox AI
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# @alphafox/cli
|
|
2
|
+
|
|
3
|
+
Alphafox CLI (`alphafox`) — Agent and human entry for the versioned Public Application API on alphafox-web.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install -g @alphafox/cli
|
|
9
|
+
# or
|
|
10
|
+
npx @alphafox/cli version
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Quick start
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
alphafox version
|
|
17
|
+
alphafox doctor
|
|
18
|
+
alphafox auth login --no-wait # Device Flow (headless-friendly)
|
|
19
|
+
alphafox auth login --device-code <code>
|
|
20
|
+
alphafox whoami
|
|
21
|
+
alphafox schema me.whoami
|
|
22
|
+
alphafox api GET /api/v1/me
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Security
|
|
26
|
+
|
|
27
|
+
- Tokens live in the OS keychain (or controlled test injection). **Never** in config files or `--token` argv.
|
|
28
|
+
- Profiles: `production` (default), `staging`, `local` — isolated issuer/audience/client (ADR 0003).
|
|
29
|
+
- High-risk writes require `--yes`. Automation tokens are **deferred** (ADR 0004).
|
|
30
|
+
- Raw `api` only hits allowlisted `/api/v1/*` facade paths.
|
|
31
|
+
|
|
32
|
+
## Skills
|
|
33
|
+
|
|
34
|
+
Co-versioned Agent Skills live under `skills/`. They route intent to public `operationId`s only.
|
|
35
|
+
|
|
36
|
+
## Docs
|
|
37
|
+
|
|
38
|
+
- [Release / supply chain](docs/release-supply-chain.md)
|
|
39
|
+
- [Staging E2E checklist](docs/e2e-staging.md)
|
|
40
|
+
- Related ADRs and parity matrix live in the alphafox-web repository
|
|
41
|
+
|
|
42
|
+
## Development
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
pnpm install
|
|
46
|
+
pnpm build
|
|
47
|
+
pnpm test
|
|
48
|
+
node dist/cli.js version
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## License
|
|
52
|
+
|
|
53
|
+
MIT
|
package/bin/alphafox.js
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export declare function generatePkcePair(): {
|
|
2
|
+
readonly codeVerifier: string;
|
|
3
|
+
readonly codeChallenge: string;
|
|
4
|
+
readonly codeChallengeMethod: "S256";
|
|
5
|
+
};
|
|
6
|
+
export declare function buildAuthorizeUrl(input: {
|
|
7
|
+
readonly issuer: string;
|
|
8
|
+
readonly clientId: string;
|
|
9
|
+
readonly redirectUri: string;
|
|
10
|
+
readonly codeChallenge: string;
|
|
11
|
+
readonly state: string;
|
|
12
|
+
readonly scope?: string;
|
|
13
|
+
}): string;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.generatePkcePair = generatePkcePair;
|
|
4
|
+
exports.buildAuthorizeUrl = buildAuthorizeUrl;
|
|
5
|
+
const node_crypto_1 = require("node:crypto");
|
|
6
|
+
function generatePkcePair() {
|
|
7
|
+
const codeVerifier = (0, node_crypto_1.randomBytes)(32).toString("base64url");
|
|
8
|
+
const codeChallenge = (0, node_crypto_1.createHash)("sha256")
|
|
9
|
+
.update(codeVerifier, "utf8")
|
|
10
|
+
.digest("base64url");
|
|
11
|
+
return {
|
|
12
|
+
codeVerifier,
|
|
13
|
+
codeChallenge,
|
|
14
|
+
codeChallengeMethod: "S256",
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
function buildAuthorizeUrl(input) {
|
|
18
|
+
const authorize = new URL(`${input.issuer.replace(/\/$/, "")}/oauth/authorize`);
|
|
19
|
+
authorize.searchParams.set("response_type", "code");
|
|
20
|
+
authorize.searchParams.set("client_id", input.clientId);
|
|
21
|
+
authorize.searchParams.set("redirect_uri", input.redirectUri);
|
|
22
|
+
authorize.searchParams.set("code_challenge", input.codeChallenge);
|
|
23
|
+
authorize.searchParams.set("code_challenge_method", "S256");
|
|
24
|
+
authorize.searchParams.set("state", input.state);
|
|
25
|
+
authorize.searchParams.set("scope", input.scope ?? "openid profile offline_access");
|
|
26
|
+
return authorize.toString();
|
|
27
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Raw API allowlist + internal path rejection.
|
|
3
|
+
* Mirrors alphafox-contracts public-api allowlist rules.
|
|
4
|
+
*/
|
|
5
|
+
/** MVP + core facade paths always allowed; full registry embedded for drift tests. */
|
|
6
|
+
export declare const FACILITY_ALWAYS_ALLOW: readonly ["/api/v1/meta", "/api/v1/me", "/api/v1/operations", "/api/v1/openapi.json", "/api/v1/trading/strategy-definitions", "/api/v1/exchange-connectors", "/api/v1/trading/traders", "/api/v1/chats", "/api/v1/backtests"];
|
|
7
|
+
export declare function normalizeApiPath(path: string): string;
|
|
8
|
+
export declare function isInternalDisallowedPath(path: string): boolean;
|
|
9
|
+
export declare function isFacadeAllowlistedPath(path: string, extraAllow?: readonly string[]): boolean;
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Raw API allowlist + internal path rejection.
|
|
4
|
+
* Mirrors alphafox-contracts public-api allowlist rules.
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.FACILITY_ALWAYS_ALLOW = void 0;
|
|
8
|
+
exports.normalizeApiPath = normalizeApiPath;
|
|
9
|
+
exports.isInternalDisallowedPath = isInternalDisallowedPath;
|
|
10
|
+
exports.isFacadeAllowlistedPath = isFacadeAllowlistedPath;
|
|
11
|
+
const INTERNAL_PREFIXES = [
|
|
12
|
+
"/backend",
|
|
13
|
+
"/control-plane",
|
|
14
|
+
"/signal-center",
|
|
15
|
+
"/api/backend",
|
|
16
|
+
"/api/control-plane",
|
|
17
|
+
"/api/signal-center",
|
|
18
|
+
];
|
|
19
|
+
/** MVP + core facade paths always allowed; full registry embedded for drift tests. */
|
|
20
|
+
exports.FACILITY_ALWAYS_ALLOW = [
|
|
21
|
+
"/api/v1/meta",
|
|
22
|
+
"/api/v1/me",
|
|
23
|
+
"/api/v1/operations",
|
|
24
|
+
"/api/v1/openapi.json",
|
|
25
|
+
"/api/v1/trading/strategy-definitions",
|
|
26
|
+
"/api/v1/exchange-connectors",
|
|
27
|
+
"/api/v1/trading/traders",
|
|
28
|
+
"/api/v1/chats",
|
|
29
|
+
"/api/v1/backtests",
|
|
30
|
+
];
|
|
31
|
+
function normalizeApiPath(path) {
|
|
32
|
+
const trimmed = path.trim();
|
|
33
|
+
if (!trimmed)
|
|
34
|
+
return "/";
|
|
35
|
+
const withSlash = trimmed.startsWith("/") ? trimmed : `/${trimmed}`;
|
|
36
|
+
return (withSlash.split("?")[0] ?? withSlash).split("#")[0].replace(/\/{2,}/g, "/");
|
|
37
|
+
}
|
|
38
|
+
function isInternalDisallowedPath(path) {
|
|
39
|
+
const n = normalizeApiPath(path);
|
|
40
|
+
return INTERNAL_PREFIXES.some((p) => n === p || n.startsWith(`${p}/`) || n.includes(`${p}/`));
|
|
41
|
+
}
|
|
42
|
+
function isFacadeAllowlistedPath(path, extraAllow = []) {
|
|
43
|
+
const n = normalizeApiPath(path);
|
|
44
|
+
if (isInternalDisallowedPath(n)) {
|
|
45
|
+
return false;
|
|
46
|
+
}
|
|
47
|
+
if (!n.startsWith("/api/v1")) {
|
|
48
|
+
return false;
|
|
49
|
+
}
|
|
50
|
+
const allow = [...exports.FACILITY_ALWAYS_ALLOW, ...extraAllow];
|
|
51
|
+
for (const a of allow) {
|
|
52
|
+
if (n === a || n.startsWith(`${a}/`)) {
|
|
53
|
+
return true;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
// templated backtests etc.
|
|
57
|
+
if (/^\/api\/v1\/backtests\/[^/]+(\/.*)?$/.test(n)) {
|
|
58
|
+
return true;
|
|
59
|
+
}
|
|
60
|
+
if (/^\/api\/v1\/trading\/traders\/[^/]+(\/.*)?$/.test(n)) {
|
|
61
|
+
return true;
|
|
62
|
+
}
|
|
63
|
+
if (/^\/api\/v1\//.test(n)) {
|
|
64
|
+
// Allow any /api/v1/* that is not internal — facade is the allowlist boundary.
|
|
65
|
+
// Internal services are never mounted under /api/v1.
|
|
66
|
+
return true;
|
|
67
|
+
}
|
|
68
|
+
return false;
|
|
69
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Embedded capability catalog (co-versioned with CLI).
|
|
3
|
+
* Source of truth for full matrix lives in alphafox-contracts + parity-matrix-m0.md.
|
|
4
|
+
*/
|
|
5
|
+
export interface CatalogOperation {
|
|
6
|
+
readonly operationId: string;
|
|
7
|
+
readonly method: string;
|
|
8
|
+
readonly path: string;
|
|
9
|
+
readonly role: string;
|
|
10
|
+
readonly risk: "read" | "write" | "high-risk-write" | string;
|
|
11
|
+
readonly scopes: readonly string[];
|
|
12
|
+
readonly stream?: boolean;
|
|
13
|
+
readonly mvp?: boolean;
|
|
14
|
+
readonly description?: string;
|
|
15
|
+
}
|
|
16
|
+
export declare const CATALOG_VERSION = "2026-08-11";
|
|
17
|
+
export declare const CATALOG_OPERATIONS: readonly CatalogOperation[];
|
|
18
|
+
export declare function findCatalogOperation(operationId: string): CatalogOperation | undefined;
|
|
19
|
+
export declare function buildCapabilityManifest(): {
|
|
20
|
+
contractVersion: string;
|
|
21
|
+
registryVersion: string;
|
|
22
|
+
operations: {
|
|
23
|
+
operationId: string;
|
|
24
|
+
method: string;
|
|
25
|
+
path: string;
|
|
26
|
+
role: string;
|
|
27
|
+
risk: string;
|
|
28
|
+
scopes: readonly string[];
|
|
29
|
+
stream: boolean;
|
|
30
|
+
mvp: boolean;
|
|
31
|
+
}[];
|
|
32
|
+
};
|
|
33
|
+
/** Resolve path templates like /api/v1/backtests/{backtestId}. */
|
|
34
|
+
export declare function resolveOperationPath(template: string, params: Record<string, string>): string;
|
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Embedded capability catalog (co-versioned with CLI).
|
|
4
|
+
* Source of truth for full matrix lives in alphafox-contracts + parity-matrix-m0.md.
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.CATALOG_OPERATIONS = exports.CATALOG_VERSION = void 0;
|
|
8
|
+
exports.findCatalogOperation = findCatalogOperation;
|
|
9
|
+
exports.buildCapabilityManifest = buildCapabilityManifest;
|
|
10
|
+
exports.resolveOperationPath = resolveOperationPath;
|
|
11
|
+
exports.CATALOG_VERSION = "2026-08-11";
|
|
12
|
+
exports.CATALOG_OPERATIONS = [
|
|
13
|
+
{
|
|
14
|
+
operationId: "meta.get",
|
|
15
|
+
method: "GET",
|
|
16
|
+
path: "/api/v1/meta",
|
|
17
|
+
role: "public",
|
|
18
|
+
risk: "read",
|
|
19
|
+
scopes: [],
|
|
20
|
+
mvp: true,
|
|
21
|
+
description: "Environment, commit SHA, contract version",
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
operationId: "me.whoami",
|
|
25
|
+
method: "GET",
|
|
26
|
+
path: "/api/v1/me",
|
|
27
|
+
role: "user",
|
|
28
|
+
risk: "read",
|
|
29
|
+
scopes: ["openid", "profile"],
|
|
30
|
+
mvp: true,
|
|
31
|
+
description: "Authenticated user identity",
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
operationId: "trading.strategy_definitions.list",
|
|
35
|
+
method: "GET",
|
|
36
|
+
path: "/api/v1/trading/strategy-definitions",
|
|
37
|
+
role: "user",
|
|
38
|
+
risk: "read",
|
|
39
|
+
scopes: ["openid", "profile", "trading:read"],
|
|
40
|
+
mvp: true,
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
operationId: "exchange_connectors.list",
|
|
44
|
+
method: "GET",
|
|
45
|
+
path: "/api/v1/exchange-connectors",
|
|
46
|
+
role: "user",
|
|
47
|
+
risk: "read",
|
|
48
|
+
scopes: ["openid", "profile", "exchange-connectors:read"],
|
|
49
|
+
mvp: true,
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
operationId: "trading.traders.list",
|
|
53
|
+
method: "GET",
|
|
54
|
+
path: "/api/v1/trading/traders",
|
|
55
|
+
role: "user",
|
|
56
|
+
risk: "read",
|
|
57
|
+
scopes: ["openid", "profile", "trading:read"],
|
|
58
|
+
mvp: true,
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
operationId: "chats.create",
|
|
62
|
+
method: "POST",
|
|
63
|
+
path: "/api/v1/chats",
|
|
64
|
+
role: "user",
|
|
65
|
+
risk: "write",
|
|
66
|
+
scopes: ["openid", "profile", "chats:write"],
|
|
67
|
+
mvp: true,
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
operationId: "backtests.create",
|
|
71
|
+
method: "POST",
|
|
72
|
+
path: "/api/v1/backtests",
|
|
73
|
+
role: "user",
|
|
74
|
+
risk: "write",
|
|
75
|
+
scopes: ["openid", "profile", "backtests:write"],
|
|
76
|
+
mvp: true,
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
operationId: "backtests.byId.get",
|
|
80
|
+
method: "GET",
|
|
81
|
+
path: "/api/v1/backtests/{backtestId}",
|
|
82
|
+
role: "user",
|
|
83
|
+
risk: "read",
|
|
84
|
+
scopes: ["openid", "profile", "backtests:read"],
|
|
85
|
+
mvp: true,
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
operationId: "backtests.byId.stream",
|
|
89
|
+
method: "GET",
|
|
90
|
+
path: "/api/v1/backtests/{backtestId}/stream",
|
|
91
|
+
role: "user",
|
|
92
|
+
risk: "read",
|
|
93
|
+
scopes: ["openid", "profile", "backtests:read"],
|
|
94
|
+
stream: true,
|
|
95
|
+
mvp: true,
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
operationId: "backtests.byId.cancel",
|
|
99
|
+
method: "POST",
|
|
100
|
+
path: "/api/v1/backtests/{backtestId}/cancel",
|
|
101
|
+
role: "user",
|
|
102
|
+
risk: "write",
|
|
103
|
+
scopes: ["openid", "profile", "backtests:write"],
|
|
104
|
+
mvp: true,
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
operationId: "trading.traders.byId.start",
|
|
108
|
+
method: "POST",
|
|
109
|
+
path: "/api/v1/trading/traders/{traderId}/start",
|
|
110
|
+
role: "user",
|
|
111
|
+
risk: "high-risk-write",
|
|
112
|
+
scopes: ["openid", "profile", "trading:write", "trading:high-risk"],
|
|
113
|
+
},
|
|
114
|
+
{
|
|
115
|
+
operationId: "trading.traders.byId.stop",
|
|
116
|
+
method: "POST",
|
|
117
|
+
path: "/api/v1/trading/traders/{traderId}/stop",
|
|
118
|
+
role: "user",
|
|
119
|
+
risk: "high-risk-write",
|
|
120
|
+
scopes: ["openid", "profile", "trading:write", "trading:high-risk"],
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
operationId: "wallet.get",
|
|
124
|
+
method: "GET",
|
|
125
|
+
path: "/api/v1/wallet",
|
|
126
|
+
role: "user",
|
|
127
|
+
risk: "read",
|
|
128
|
+
scopes: ["openid", "profile", "wallet:read"],
|
|
129
|
+
},
|
|
130
|
+
{
|
|
131
|
+
operationId: "notification.channels.list",
|
|
132
|
+
method: "GET",
|
|
133
|
+
path: "/api/v1/notification/channels",
|
|
134
|
+
role: "user",
|
|
135
|
+
risk: "read",
|
|
136
|
+
scopes: ["openid", "profile", "notification:read"],
|
|
137
|
+
},
|
|
138
|
+
{
|
|
139
|
+
operationId: "account.exchange_uids.list",
|
|
140
|
+
method: "GET",
|
|
141
|
+
path: "/api/v1/account/exchange-uids",
|
|
142
|
+
role: "user",
|
|
143
|
+
risk: "read",
|
|
144
|
+
scopes: ["openid", "profile", "account:read"],
|
|
145
|
+
},
|
|
146
|
+
{
|
|
147
|
+
operationId: "subscriptions.me.get",
|
|
148
|
+
method: "GET",
|
|
149
|
+
path: "/api/v1/subscriptions/me",
|
|
150
|
+
role: "user",
|
|
151
|
+
risk: "read",
|
|
152
|
+
scopes: ["openid", "profile", "subscriptions:read"],
|
|
153
|
+
},
|
|
154
|
+
{
|
|
155
|
+
operationId: "managed_wallets.list",
|
|
156
|
+
method: "GET",
|
|
157
|
+
path: "/api/v1/managed-wallets",
|
|
158
|
+
role: "user",
|
|
159
|
+
risk: "read",
|
|
160
|
+
scopes: ["openid", "profile", "managed-wallets:read"],
|
|
161
|
+
},
|
|
162
|
+
{
|
|
163
|
+
operationId: "strategy_plaza.publications.list",
|
|
164
|
+
method: "GET",
|
|
165
|
+
path: "/api/v1/strategy-plaza/publications",
|
|
166
|
+
role: "user",
|
|
167
|
+
risk: "read",
|
|
168
|
+
scopes: ["openid", "profile", "strategy-plaza:read"],
|
|
169
|
+
},
|
|
170
|
+
{
|
|
171
|
+
operationId: "spread_radar.pairs.list",
|
|
172
|
+
method: "GET",
|
|
173
|
+
path: "/api/v1/spread-radar/pairs",
|
|
174
|
+
role: "user",
|
|
175
|
+
risk: "read",
|
|
176
|
+
scopes: ["openid", "profile", "spread-radar:read"],
|
|
177
|
+
},
|
|
178
|
+
{
|
|
179
|
+
operationId: "trader_dna.report.get",
|
|
180
|
+
method: "GET",
|
|
181
|
+
path: "/api/v1/trader-dna/report",
|
|
182
|
+
role: "user",
|
|
183
|
+
risk: "read",
|
|
184
|
+
scopes: ["openid", "profile", "trader-dna:read"],
|
|
185
|
+
},
|
|
186
|
+
{
|
|
187
|
+
operationId: "platform_statistics.get",
|
|
188
|
+
method: "GET",
|
|
189
|
+
path: "/api/v1/platform-statistics",
|
|
190
|
+
role: "user",
|
|
191
|
+
risk: "read",
|
|
192
|
+
scopes: ["openid", "profile", "platform-statistics:read"],
|
|
193
|
+
},
|
|
194
|
+
{
|
|
195
|
+
operationId: "asr.transcribe",
|
|
196
|
+
method: "POST",
|
|
197
|
+
path: "/api/v1/asr/transcribe",
|
|
198
|
+
role: "user",
|
|
199
|
+
risk: "write",
|
|
200
|
+
scopes: ["openid", "profile", "asr:write"],
|
|
201
|
+
},
|
|
202
|
+
{
|
|
203
|
+
operationId: "lite.catalog_config.get",
|
|
204
|
+
method: "GET",
|
|
205
|
+
path: "/api/v1/lite/catalog-config",
|
|
206
|
+
role: "user",
|
|
207
|
+
risk: "read",
|
|
208
|
+
scopes: ["openid", "profile", "lite:read"],
|
|
209
|
+
},
|
|
210
|
+
{
|
|
211
|
+
operationId: "admin.users.list",
|
|
212
|
+
method: "GET",
|
|
213
|
+
path: "/api/v1/admin/users",
|
|
214
|
+
role: "admin",
|
|
215
|
+
risk: "read",
|
|
216
|
+
scopes: ["openid", "profile", "admin:read"],
|
|
217
|
+
},
|
|
218
|
+
];
|
|
219
|
+
function findCatalogOperation(operationId) {
|
|
220
|
+
return exports.CATALOG_OPERATIONS.find((op) => op.operationId === operationId);
|
|
221
|
+
}
|
|
222
|
+
function buildCapabilityManifest() {
|
|
223
|
+
return {
|
|
224
|
+
contractVersion: exports.CATALOG_VERSION,
|
|
225
|
+
registryVersion: "1.0.0",
|
|
226
|
+
operations: exports.CATALOG_OPERATIONS.map((op) => ({
|
|
227
|
+
operationId: op.operationId,
|
|
228
|
+
method: op.method,
|
|
229
|
+
path: op.path,
|
|
230
|
+
role: op.role,
|
|
231
|
+
risk: op.risk,
|
|
232
|
+
scopes: op.scopes,
|
|
233
|
+
stream: Boolean(op.stream),
|
|
234
|
+
mvp: Boolean(op.mvp),
|
|
235
|
+
})),
|
|
236
|
+
};
|
|
237
|
+
}
|
|
238
|
+
/** Resolve path templates like /api/v1/backtests/{backtestId}. */
|
|
239
|
+
function resolveOperationPath(template, params) {
|
|
240
|
+
return template.replace(/\{([a-zA-Z0-9_]+)\}/g, (_, key) => {
|
|
241
|
+
const value = params[key];
|
|
242
|
+
if (!value) {
|
|
243
|
+
throw new Error(`Missing path parameter: ${key}`);
|
|
244
|
+
}
|
|
245
|
+
return encodeURIComponent(value);
|
|
246
|
+
});
|
|
247
|
+
}
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
const run_1 = require("./commands/run");
|
|
5
|
+
async function main() {
|
|
6
|
+
const code = await (0, run_1.runCli)(process.argv.slice(2), process.env);
|
|
7
|
+
if (typeof code === "number") {
|
|
8
|
+
process.exit(code);
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
main().catch((err) => {
|
|
12
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
13
|
+
process.stderr.write(`${JSON.stringify({
|
|
14
|
+
ok: false,
|
|
15
|
+
error: { type: "runtime", message },
|
|
16
|
+
})}\n`);
|
|
17
|
+
process.exit(1);
|
|
18
|
+
});
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export interface GlobalFlags {
|
|
2
|
+
profile?: string;
|
|
3
|
+
format: "json" | "jsonl" | "text";
|
|
4
|
+
yes: boolean;
|
|
5
|
+
dryRun: boolean;
|
|
6
|
+
noInput: boolean;
|
|
7
|
+
unsafeCustomEndpoint?: string;
|
|
8
|
+
jq?: string;
|
|
9
|
+
}
|
|
10
|
+
export declare function parseGlobalFlags(argv: string[]): {
|
|
11
|
+
flags: GlobalFlags;
|
|
12
|
+
rest: string[];
|
|
13
|
+
};
|
|
14
|
+
export declare function runCli(argv: string[], env?: NodeJS.ProcessEnv): Promise<number>;
|