balchemy 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/README.md +59 -0
- package/assets/bcrow.png +0 -0
- package/dist/agent-store.d.ts +40 -0
- package/dist/agent-store.d.ts.map +1 -0
- package/dist/agent-store.js +206 -0
- package/dist/agent-store.js.map +1 -0
- package/dist/config-loader.d.ts +8 -0
- package/dist/config-loader.d.ts.map +1 -0
- package/dist/config-loader.js +106 -0
- package/dist/config-loader.js.map +1 -0
- package/dist/docker-gen.d.ts +6 -0
- package/dist/docker-gen.d.ts.map +1 -0
- package/dist/docker-gen.js +40 -0
- package/dist/docker-gen.js.map +1 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +143 -0
- package/dist/index.js.map +1 -0
- package/dist/openai-oauth.d.ts +28 -0
- package/dist/openai-oauth.d.ts.map +1 -0
- package/dist/openai-oauth.js +215 -0
- package/dist/openai-oauth.js.map +1 -0
- package/dist/runner.d.ts +6 -0
- package/dist/runner.d.ts.map +1 -0
- package/dist/runner.js +63 -0
- package/dist/runner.js.map +1 -0
- package/dist/terminal-logo.d.ts +15 -0
- package/dist/terminal-logo.d.ts.map +1 -0
- package/dist/terminal-logo.js +121 -0
- package/dist/terminal-logo.js.map +1 -0
- package/dist/tui/AgentBridge.d.ts +35 -0
- package/dist/tui/AgentBridge.d.ts.map +1 -0
- package/dist/tui/AgentBridge.js +235 -0
- package/dist/tui/AgentBridge.js.map +1 -0
- package/dist/tui/App.d.ts +8 -0
- package/dist/tui/App.d.ts.map +1 -0
- package/dist/tui/App.js +118 -0
- package/dist/tui/App.js.map +1 -0
- package/dist/tui/ChatAgent.d.ts +41 -0
- package/dist/tui/ChatAgent.d.ts.map +1 -0
- package/dist/tui/ChatAgent.js +312 -0
- package/dist/tui/ChatAgent.js.map +1 -0
- package/dist/tui/ChatPanel.d.ts +10 -0
- package/dist/tui/ChatPanel.d.ts.map +1 -0
- package/dist/tui/ChatPanel.js +43 -0
- package/dist/tui/ChatPanel.js.map +1 -0
- package/dist/tui/StatusPanel.d.ts +8 -0
- package/dist/tui/StatusPanel.d.ts.map +1 -0
- package/dist/tui/StatusPanel.js +25 -0
- package/dist/tui/StatusPanel.js.map +1 -0
- package/dist/tui/start.d.ts +3 -0
- package/dist/tui/start.d.ts.map +1 -0
- package/dist/tui/start.js +14 -0
- package/dist/tui/start.js.map +1 -0
- package/dist/tui/types.d.ts +61 -0
- package/dist/tui/types.d.ts.map +1 -0
- package/dist/tui/types.js +3 -0
- package/dist/tui/types.js.map +1 -0
- package/dist/wizard.d.ts +16 -0
- package/dist/wizard.d.ts.map +1 -0
- package/dist/wizard.js +716 -0
- package/dist/wizard.js.map +1 -0
- package/package.json +57 -0
- package/templates/.env.example +19 -0
- package/templates/Dockerfile +20 -0
- package/templates/agent.config.yaml +71 -0
- package/templates/docker-compose.yml +27 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* create-balchemy-agent CLI entry point.
|
|
4
|
+
*
|
|
5
|
+
* On launch:
|
|
6
|
+
* - If ~/.balchemy/agent.json exists → offer to resume or start fresh
|
|
7
|
+
* - If no cached agent → run wizard
|
|
8
|
+
*
|
|
9
|
+
* Sub-commands:
|
|
10
|
+
* (no args) Resume cached agent or run wizard
|
|
11
|
+
* init / --init Force run wizard (ignore cache)
|
|
12
|
+
* start [config] Start from agent.config.yaml
|
|
13
|
+
* docker [outDir] Generate Docker files
|
|
14
|
+
*/
|
|
15
|
+
import * as path from "path";
|
|
16
|
+
import * as readline from "readline";
|
|
17
|
+
import { loadAgent, clearAgent } from "./agent-store.js";
|
|
18
|
+
const [, , cmd, ...args] = process.argv;
|
|
19
|
+
const T = "\x1b[38;2;0;172;176m";
|
|
20
|
+
const G = "\x1b[38;2;186;115;6m";
|
|
21
|
+
const W = "\x1b[1;37m";
|
|
22
|
+
const D = "\x1b[38;5;245m";
|
|
23
|
+
const R = "\x1b[0m";
|
|
24
|
+
function ask(rl, question, defaultVal = "") {
|
|
25
|
+
return new Promise((resolve) => {
|
|
26
|
+
const hint = defaultVal ? ` ${D}[${defaultVal}]${R}` : "";
|
|
27
|
+
rl.question(` ${question}${hint}: `, (answer) => {
|
|
28
|
+
resolve(answer.trim() || defaultVal);
|
|
29
|
+
});
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
async function main() {
|
|
33
|
+
switch (cmd) {
|
|
34
|
+
case "--init":
|
|
35
|
+
case "init": {
|
|
36
|
+
// Force wizard — ignore cache
|
|
37
|
+
const { runWizard } = await import("./wizard.js");
|
|
38
|
+
await runWizard(process.cwd());
|
|
39
|
+
break;
|
|
40
|
+
}
|
|
41
|
+
case "start": {
|
|
42
|
+
const configPath = args[0] ?? path.join(process.cwd(), "agent.config.yaml");
|
|
43
|
+
const resolvedPath = path.resolve(configPath);
|
|
44
|
+
const dotenv = await import("dotenv");
|
|
45
|
+
const envPath = path.join(path.dirname(resolvedPath), ".env");
|
|
46
|
+
const fs = await import("fs");
|
|
47
|
+
if (fs.existsSync(envPath)) {
|
|
48
|
+
dotenv.config({ path: envPath });
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
dotenv.config();
|
|
52
|
+
}
|
|
53
|
+
const { loadConfig } = await import("./config-loader.js");
|
|
54
|
+
const config = loadConfig(resolvedPath);
|
|
55
|
+
const publicId = config.mcpEndpoint.split("/").filter(Boolean).pop() ?? "unknown";
|
|
56
|
+
const { startTui } = await import("./tui/start.js");
|
|
57
|
+
await startTui({
|
|
58
|
+
mcpEndpoint: config.mcpEndpoint,
|
|
59
|
+
apiKey: config.apiKey,
|
|
60
|
+
llmProvider: config.llmProvider,
|
|
61
|
+
llmApiKey: config.llmApiKey,
|
|
62
|
+
llmModel: config.llmModel,
|
|
63
|
+
llmBaseUrl: config.llmBaseUrl,
|
|
64
|
+
maxDailyLlmCost: config.maxDailyLlmCost,
|
|
65
|
+
llmTimeoutMs: config.llmTimeoutMs,
|
|
66
|
+
publicId,
|
|
67
|
+
strategy: "custom",
|
|
68
|
+
shadowMode: false,
|
|
69
|
+
});
|
|
70
|
+
break;
|
|
71
|
+
}
|
|
72
|
+
case "docker": {
|
|
73
|
+
const outDir = args[0] ?? process.cwd();
|
|
74
|
+
const { generateDocker } = await import("./docker-gen.js");
|
|
75
|
+
await generateDocker(outDir);
|
|
76
|
+
process.stdout.write(`Docker files written to ${outDir}\n`);
|
|
77
|
+
break;
|
|
78
|
+
}
|
|
79
|
+
case undefined: {
|
|
80
|
+
// Default: check for cached agent
|
|
81
|
+
const cached = loadAgent();
|
|
82
|
+
if (cached) {
|
|
83
|
+
// Show cached agent info and ask what to do
|
|
84
|
+
const { renderLogo } = await import("./terminal-logo.js");
|
|
85
|
+
process.stdout.write(renderLogo(20));
|
|
86
|
+
process.stdout.write(`\n ${G}B${T}alchemy ${W}Agent${R}\n\n`);
|
|
87
|
+
process.stdout.write(` ${D}Cached agent found:${R}\n`);
|
|
88
|
+
process.stdout.write(` ${T}Agent:${R} ${cached.publicId}\n`);
|
|
89
|
+
process.stdout.write(` ${T}Endpoint:${R} ${cached.mcpEndpoint}\n`);
|
|
90
|
+
process.stdout.write(` ${T}Model:${R} ${cached.llmModel ?? "default"}\n`);
|
|
91
|
+
process.stdout.write(` ${T}Strategy:${R} ${cached.strategy}\n`);
|
|
92
|
+
process.stdout.write(` ${T}Mode:${R} ${cached.shadowMode ? "Shadow" : "LIVE"}\n`);
|
|
93
|
+
process.stdout.write(` ${D}Saved:${R} ${cached.createdAt}\n\n`);
|
|
94
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
95
|
+
const choice = await ask(rl, `${W}Resume this agent?${R} (y/n/new)`, "y");
|
|
96
|
+
rl.close();
|
|
97
|
+
if (choice === "y" || choice === "yes") {
|
|
98
|
+
// Resume — go straight to TUI
|
|
99
|
+
const { startTui } = await import("./tui/start.js");
|
|
100
|
+
await startTui({
|
|
101
|
+
mcpEndpoint: cached.mcpEndpoint,
|
|
102
|
+
apiKey: cached.apiKey,
|
|
103
|
+
llmProvider: cached.llmProvider,
|
|
104
|
+
llmApiKey: cached.llmApiKey,
|
|
105
|
+
llmModel: cached.llmModel,
|
|
106
|
+
llmBaseUrl: cached.llmBaseUrl,
|
|
107
|
+
maxDailyLlmCost: cached.maxDailyLlmCost,
|
|
108
|
+
publicId: cached.publicId,
|
|
109
|
+
strategy: cached.strategy,
|
|
110
|
+
shadowMode: cached.shadowMode,
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
else if (choice === "new" || choice === "n") {
|
|
114
|
+
// New agent — clear cache and run wizard
|
|
115
|
+
if (choice === "new")
|
|
116
|
+
clearAgent();
|
|
117
|
+
const { runWizard } = await import("./wizard.js");
|
|
118
|
+
await runWizard(process.cwd());
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
else {
|
|
122
|
+
// No cached agent — run wizard
|
|
123
|
+
const { runWizard } = await import("./wizard.js");
|
|
124
|
+
await runWizard(process.cwd());
|
|
125
|
+
}
|
|
126
|
+
break;
|
|
127
|
+
}
|
|
128
|
+
default: {
|
|
129
|
+
process.stdout.write(`${T}Balchemy Agent CLI${R}\n\n` +
|
|
130
|
+
"Usage:\n" +
|
|
131
|
+
" npx create-balchemy-agent Resume agent or setup wizard\n" +
|
|
132
|
+
" npx create-balchemy-agent init Force new setup wizard\n" +
|
|
133
|
+
" balchemy-agent start [config] Start from config file\n" +
|
|
134
|
+
" balchemy-agent docker [outDir] Generate Docker files\n\n");
|
|
135
|
+
break;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
main().catch((err) => {
|
|
140
|
+
process.stderr.write(`Error: ${err instanceof Error ? err.message : String(err)}\n`);
|
|
141
|
+
process.exit(1);
|
|
142
|
+
});
|
|
143
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenAI OAuth 2.0 + PKCE authentication for ChatGPT Plus/Pro subscriptions.
|
|
3
|
+
*
|
|
4
|
+
* Uses the same flow as the official Codex CLI:
|
|
5
|
+
* 1. Generate PKCE code_verifier + code_challenge
|
|
6
|
+
* 2. Start localhost callback server
|
|
7
|
+
* 3. Open browser → user logs in with ChatGPT account
|
|
8
|
+
* 4. Exchange auth code for access_token + refresh_token
|
|
9
|
+
* 5. Auto-refresh before expiry
|
|
10
|
+
*
|
|
11
|
+
* Reference: https://developers.openai.com/codex/auth
|
|
12
|
+
*/
|
|
13
|
+
export interface OAuthTokens {
|
|
14
|
+
accessToken: string;
|
|
15
|
+
refreshToken: string;
|
|
16
|
+
expiresAt: number;
|
|
17
|
+
accountId?: string;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Run the full OAuth PKCE flow. Opens browser, waits for callback, returns tokens.
|
|
21
|
+
* Rejects after timeoutMs (default 120s).
|
|
22
|
+
*/
|
|
23
|
+
export declare function loginWithOpenAI(timeoutMs?: number): Promise<OAuthTokens>;
|
|
24
|
+
/**
|
|
25
|
+
* Refresh an expired access token using the refresh token.
|
|
26
|
+
*/
|
|
27
|
+
export declare function refreshAccessToken(refreshToken: string): Promise<OAuthTokens>;
|
|
28
|
+
//# sourceMappingURL=openai-oauth.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openai-oauth.d.ts","sourceRoot":"","sources":["../src/openai-oauth.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAiBH,MAAM,WAAW,WAAW;IAC1B,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AA8BD;;;GAGG;AACH,wBAAgB,eAAe,CAAC,SAAS,SAAU,GAAG,OAAO,CAAC,WAAW,CAAC,CAwFzE;AAkDD;;GAEG;AACH,wBAAsB,kBAAkB,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CA6BnF"}
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenAI OAuth 2.0 + PKCE authentication for ChatGPT Plus/Pro subscriptions.
|
|
3
|
+
*
|
|
4
|
+
* Uses the same flow as the official Codex CLI:
|
|
5
|
+
* 1. Generate PKCE code_verifier + code_challenge
|
|
6
|
+
* 2. Start localhost callback server
|
|
7
|
+
* 3. Open browser → user logs in with ChatGPT account
|
|
8
|
+
* 4. Exchange auth code for access_token + refresh_token
|
|
9
|
+
* 5. Auto-refresh before expiry
|
|
10
|
+
*
|
|
11
|
+
* Reference: https://developers.openai.com/codex/auth
|
|
12
|
+
*/
|
|
13
|
+
import * as http from "http";
|
|
14
|
+
import * as crypto from "crypto";
|
|
15
|
+
import { exec } from "child_process";
|
|
16
|
+
// ── Constants ─────────────────────────────────────────────────────────────────
|
|
17
|
+
const CLIENT_ID = "app_EMoamEEZ73f0CkXaXp7hrann";
|
|
18
|
+
const AUTH_URL = "https://auth.openai.com/oauth/authorize";
|
|
19
|
+
const TOKEN_URL = "https://auth.openai.com/oauth/token";
|
|
20
|
+
const CALLBACK_PORT = 1455;
|
|
21
|
+
const REDIRECT_URI = `http://localhost:${CALLBACK_PORT}/auth/callback`;
|
|
22
|
+
const SCOPES = "openid profile email offline_access";
|
|
23
|
+
// ── PKCE Helpers ──────────────────────────────────────────────────────────────
|
|
24
|
+
function generateCodeVerifier() {
|
|
25
|
+
return crypto.randomBytes(32).toString("base64url");
|
|
26
|
+
}
|
|
27
|
+
function generateCodeChallenge(verifier) {
|
|
28
|
+
return crypto.createHash("sha256").update(verifier).digest("base64url");
|
|
29
|
+
}
|
|
30
|
+
function generateState() {
|
|
31
|
+
return crypto.randomBytes(16).toString("hex");
|
|
32
|
+
}
|
|
33
|
+
// ── Browser ───────────────────────────────────────────────────────────────────
|
|
34
|
+
function openBrowser(url) {
|
|
35
|
+
const cmd = process.platform === "darwin"
|
|
36
|
+
? `open "${url}"`
|
|
37
|
+
: process.platform === "win32"
|
|
38
|
+
? `start "${url}"`
|
|
39
|
+
: `xdg-open "${url}"`;
|
|
40
|
+
exec(cmd, () => { });
|
|
41
|
+
}
|
|
42
|
+
// ── OAuth Flow ────────────────────────────────────────────────────────────────
|
|
43
|
+
/**
|
|
44
|
+
* Run the full OAuth PKCE flow. Opens browser, waits for callback, returns tokens.
|
|
45
|
+
* Rejects after timeoutMs (default 120s).
|
|
46
|
+
*/
|
|
47
|
+
export function loginWithOpenAI(timeoutMs = 120_000) {
|
|
48
|
+
return new Promise((resolve, reject) => {
|
|
49
|
+
const codeVerifier = generateCodeVerifier();
|
|
50
|
+
const codeChallenge = generateCodeChallenge(codeVerifier);
|
|
51
|
+
const state = generateState();
|
|
52
|
+
let server = null;
|
|
53
|
+
let timer = null;
|
|
54
|
+
const cleanup = () => {
|
|
55
|
+
if (timer)
|
|
56
|
+
clearTimeout(timer);
|
|
57
|
+
if (server)
|
|
58
|
+
server.close();
|
|
59
|
+
};
|
|
60
|
+
timer = setTimeout(() => {
|
|
61
|
+
cleanup();
|
|
62
|
+
reject(new Error("OAuth login timed out (120s). Try again."));
|
|
63
|
+
}, timeoutMs);
|
|
64
|
+
server = http.createServer(async (req, res) => {
|
|
65
|
+
const url = new URL(req.url ?? "/", `http://localhost:${CALLBACK_PORT}`);
|
|
66
|
+
if (url.pathname !== "/auth/callback") {
|
|
67
|
+
res.writeHead(404);
|
|
68
|
+
res.end("Not found");
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
const code = url.searchParams.get("code");
|
|
72
|
+
const returnedState = url.searchParams.get("state");
|
|
73
|
+
const error = url.searchParams.get("error");
|
|
74
|
+
if (error) {
|
|
75
|
+
res.writeHead(200, { "Content-Type": "text/html" });
|
|
76
|
+
res.end(errorPage(error));
|
|
77
|
+
cleanup();
|
|
78
|
+
reject(new Error(`OAuth error: ${error}`));
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
if (!code || returnedState !== state) {
|
|
82
|
+
res.writeHead(400, { "Content-Type": "text/html" });
|
|
83
|
+
res.end(errorPage("Invalid callback — state mismatch or missing code."));
|
|
84
|
+
cleanup();
|
|
85
|
+
reject(new Error("OAuth state mismatch"));
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
// Exchange code for tokens
|
|
89
|
+
try {
|
|
90
|
+
const tokens = await exchangeCode(code, codeVerifier);
|
|
91
|
+
res.writeHead(200, { "Content-Type": "text/html" });
|
|
92
|
+
res.end(successPage());
|
|
93
|
+
cleanup();
|
|
94
|
+
resolve(tokens);
|
|
95
|
+
}
|
|
96
|
+
catch (err) {
|
|
97
|
+
res.writeHead(500, { "Content-Type": "text/html" });
|
|
98
|
+
res.end(errorPage(err instanceof Error ? err.message : "Token exchange failed"));
|
|
99
|
+
cleanup();
|
|
100
|
+
reject(err);
|
|
101
|
+
}
|
|
102
|
+
});
|
|
103
|
+
server.listen(CALLBACK_PORT, () => {
|
|
104
|
+
// Build auth URL
|
|
105
|
+
const params = new URLSearchParams({
|
|
106
|
+
client_id: CLIENT_ID,
|
|
107
|
+
redirect_uri: REDIRECT_URI,
|
|
108
|
+
response_type: "code",
|
|
109
|
+
scope: SCOPES,
|
|
110
|
+
state,
|
|
111
|
+
code_challenge: codeChallenge,
|
|
112
|
+
code_challenge_method: "S256",
|
|
113
|
+
});
|
|
114
|
+
const authUrl = `${AUTH_URL}?${params.toString()}`;
|
|
115
|
+
openBrowser(authUrl);
|
|
116
|
+
});
|
|
117
|
+
server.on("error", (err) => {
|
|
118
|
+
cleanup();
|
|
119
|
+
if (err.code === "EADDRINUSE") {
|
|
120
|
+
reject(new Error(`Port ${CALLBACK_PORT} is in use. Close other apps and try again.`));
|
|
121
|
+
}
|
|
122
|
+
else {
|
|
123
|
+
reject(err);
|
|
124
|
+
}
|
|
125
|
+
});
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
// ── Token Exchange ────────────────────────────────────────────────────────────
|
|
129
|
+
async function exchangeCode(code, codeVerifier) {
|
|
130
|
+
const body = new URLSearchParams({
|
|
131
|
+
grant_type: "authorization_code",
|
|
132
|
+
client_id: CLIENT_ID,
|
|
133
|
+
code,
|
|
134
|
+
redirect_uri: REDIRECT_URI,
|
|
135
|
+
code_verifier: codeVerifier,
|
|
136
|
+
});
|
|
137
|
+
const res = await fetch(TOKEN_URL, {
|
|
138
|
+
method: "POST",
|
|
139
|
+
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
140
|
+
body: body.toString(),
|
|
141
|
+
});
|
|
142
|
+
if (!res.ok) {
|
|
143
|
+
const text = await res.text();
|
|
144
|
+
throw new Error(`Token exchange failed: ${res.status} ${text}`);
|
|
145
|
+
}
|
|
146
|
+
const data = (await res.json());
|
|
147
|
+
// Extract accountId from access token (JWT payload)
|
|
148
|
+
let accountId;
|
|
149
|
+
try {
|
|
150
|
+
const payload = JSON.parse(Buffer.from(data.access_token.split(".")[1], "base64").toString());
|
|
151
|
+
accountId = payload.sub ?? payload.account_id;
|
|
152
|
+
}
|
|
153
|
+
catch {
|
|
154
|
+
// non-critical
|
|
155
|
+
}
|
|
156
|
+
return {
|
|
157
|
+
accessToken: data.access_token,
|
|
158
|
+
refreshToken: data.refresh_token,
|
|
159
|
+
expiresAt: Date.now() + data.expires_in * 1000,
|
|
160
|
+
accountId,
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Refresh an expired access token using the refresh token.
|
|
165
|
+
*/
|
|
166
|
+
export async function refreshAccessToken(refreshToken) {
|
|
167
|
+
const body = new URLSearchParams({
|
|
168
|
+
grant_type: "refresh_token",
|
|
169
|
+
client_id: CLIENT_ID,
|
|
170
|
+
refresh_token: refreshToken,
|
|
171
|
+
});
|
|
172
|
+
const res = await fetch(TOKEN_URL, {
|
|
173
|
+
method: "POST",
|
|
174
|
+
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
175
|
+
body: body.toString(),
|
|
176
|
+
});
|
|
177
|
+
if (!res.ok) {
|
|
178
|
+
const text = await res.text();
|
|
179
|
+
throw new Error(`Token refresh failed: ${res.status} ${text}`);
|
|
180
|
+
}
|
|
181
|
+
const data = (await res.json());
|
|
182
|
+
return {
|
|
183
|
+
accessToken: data.access_token,
|
|
184
|
+
refreshToken: data.refresh_token,
|
|
185
|
+
expiresAt: Date.now() + data.expires_in * 1000,
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
// ── HTML Pages ────────────────────────────────────────────────────────────────
|
|
189
|
+
/**
|
|
190
|
+
* Escape HTML special characters to prevent XSS when interpolating
|
|
191
|
+
* untrusted strings (e.g. OAuth error parameters) into HTML responses.
|
|
192
|
+
*/
|
|
193
|
+
function escapeHtml(s) {
|
|
194
|
+
return s
|
|
195
|
+
.replace(/&/g, "&")
|
|
196
|
+
.replace(/</g, "<")
|
|
197
|
+
.replace(/>/g, ">")
|
|
198
|
+
.replace(/"/g, """)
|
|
199
|
+
.replace(/'/g, "'");
|
|
200
|
+
}
|
|
201
|
+
function successPage() {
|
|
202
|
+
return `<!DOCTYPE html><html><body style="font-family:system-ui;display:flex;justify-content:center;align-items:center;height:100vh;background:#0a0a0a;color:#00acb0">
|
|
203
|
+
<div style="text-align:center">
|
|
204
|
+
<h1>Logged in</h1>
|
|
205
|
+
<p style="color:#888">You can close this tab and return to the terminal.</p>
|
|
206
|
+
</div></body></html>`;
|
|
207
|
+
}
|
|
208
|
+
function errorPage(msg) {
|
|
209
|
+
return `<!DOCTYPE html><html><body style="font-family:system-ui;display:flex;justify-content:center;align-items:center;height:100vh;background:#0a0a0a;color:#e55">
|
|
210
|
+
<div style="text-align:center">
|
|
211
|
+
<h1>Login failed</h1>
|
|
212
|
+
<p style="color:#888">${escapeHtml(msg)}</p>
|
|
213
|
+
</div></body></html>`;
|
|
214
|
+
}
|
|
215
|
+
//# sourceMappingURL=openai-oauth.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openai-oauth.js","sourceRoot":"","sources":["../src/openai-oauth.ts"],"names":[],"mappings":"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"}
|
package/dist/runner.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../src/runner.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAmBH,wBAAsB,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAoDhE"}
|
package/dist/runner.js
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Starts the AgentLoop from a config file path.
|
|
3
|
+
* Handles process signals (SIGINT, SIGTERM) for graceful shutdown.
|
|
4
|
+
*/
|
|
5
|
+
import * as dotenv from 'dotenv';
|
|
6
|
+
import * as path from 'path';
|
|
7
|
+
import * as fs from 'fs';
|
|
8
|
+
import { AgentLoop } from '@balchemyai/agent-sdk';
|
|
9
|
+
import { loadConfig } from './config-loader.js';
|
|
10
|
+
function loadDotEnv(configPath) {
|
|
11
|
+
// Look for .env relative to the config file directory
|
|
12
|
+
const envPath = path.join(path.dirname(configPath), '.env');
|
|
13
|
+
if (fs.existsSync(envPath)) {
|
|
14
|
+
dotenv.config({ path: envPath });
|
|
15
|
+
}
|
|
16
|
+
else {
|
|
17
|
+
// Fall back to cwd
|
|
18
|
+
dotenv.config();
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
export async function runAgent(configPath) {
|
|
22
|
+
const resolvedPath = path.resolve(configPath);
|
|
23
|
+
// Load .env before parsing config (config may reference env vars)
|
|
24
|
+
loadDotEnv(resolvedPath);
|
|
25
|
+
process.stdout.write(`Starting Balchemy agent from: ${resolvedPath}\n`);
|
|
26
|
+
const config = loadConfig(resolvedPath);
|
|
27
|
+
const loop = new AgentLoop({
|
|
28
|
+
...config,
|
|
29
|
+
onStatusChange: (status) => {
|
|
30
|
+
process.stdout.write(`[agent] status=${status.status} events=${status.eventsReceived} ` +
|
|
31
|
+
`decisions=${status.decisionsExecuted} trades=${status.tradesExecuted} ` +
|
|
32
|
+
`llmCost=$${status.llmCostToday.toFixed(4)}/${status.maxDailyLlmCost}\n`);
|
|
33
|
+
},
|
|
34
|
+
onDecision: (decision) => {
|
|
35
|
+
process.stdout.write(`[agent] decision action=${decision.action}` +
|
|
36
|
+
(decision.token ? ` token=${decision.token}` : '') +
|
|
37
|
+
(decision.amount ? ` amount=${decision.amount}` : '') +
|
|
38
|
+
(decision.confidence !== undefined ? ` confidence=${decision.confidence}` : '') +
|
|
39
|
+
'\n');
|
|
40
|
+
},
|
|
41
|
+
onError: (err) => {
|
|
42
|
+
process.stderr.write(`[agent] error: ${err.message}\n`);
|
|
43
|
+
},
|
|
44
|
+
});
|
|
45
|
+
// Graceful shutdown
|
|
46
|
+
let stopping = false;
|
|
47
|
+
const shutdown = async () => {
|
|
48
|
+
if (stopping)
|
|
49
|
+
return;
|
|
50
|
+
stopping = true;
|
|
51
|
+
process.stdout.write('\n[agent] Shutting down...\n');
|
|
52
|
+
await loop.stop();
|
|
53
|
+
process.stdout.write('[agent] Stopped.\n');
|
|
54
|
+
process.exit(0);
|
|
55
|
+
};
|
|
56
|
+
process.on('SIGINT', () => { void shutdown(); });
|
|
57
|
+
process.on('SIGTERM', () => { void shutdown(); });
|
|
58
|
+
await loop.start();
|
|
59
|
+
process.stdout.write('[agent] Running. Press Ctrl+C to stop.\n');
|
|
60
|
+
// Keep process alive
|
|
61
|
+
await new Promise(() => { });
|
|
62
|
+
}
|
|
63
|
+
//# sourceMappingURL=runner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runner.js","sourceRoot":"","sources":["../src/runner.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Terminal image rendering for BCrow logo.
|
|
3
|
+
*
|
|
4
|
+
* Terminal emulators do not share one universal "render this SVG" API, so we
|
|
5
|
+
* ship a bundled PNG and use native image protocols when the terminal supports
|
|
6
|
+
* them. Everyone else gets the ANSI art fallback.
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Render the BCrow logo. Uses native terminal image protocol when available,
|
|
10
|
+
* falls back to ANSI block art.
|
|
11
|
+
*
|
|
12
|
+
* @param widthCols — terminal columns to use for the image (default 20)
|
|
13
|
+
*/
|
|
14
|
+
export declare function renderLogo(widthCols?: number): string;
|
|
15
|
+
//# sourceMappingURL=terminal-logo.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"terminal-logo.d.ts","sourceRoot":"","sources":["../src/terminal-logo.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AA+FH;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,SAAS,SAAK,GAAG,MAAM,CAsBjD"}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Terminal image rendering for BCrow logo.
|
|
3
|
+
*
|
|
4
|
+
* Terminal emulators do not share one universal "render this SVG" API, so we
|
|
5
|
+
* ship a bundled PNG and use native image protocols when the terminal supports
|
|
6
|
+
* them. Everyone else gets the ANSI art fallback.
|
|
7
|
+
*/
|
|
8
|
+
import * as fs from "fs";
|
|
9
|
+
import * as path from "path";
|
|
10
|
+
import { fileURLToPath } from "url";
|
|
11
|
+
const __filename_esm = fileURLToPath(import.meta.url);
|
|
12
|
+
const __dirname_esm = path.dirname(__filename_esm);
|
|
13
|
+
// ── Brand colors ──────────────────────────────────────────────────────────────
|
|
14
|
+
const T = "\x1b[38;2;0;172;176m"; // teal
|
|
15
|
+
const DT = "\x1b[38;2;0;120;124m"; // dark teal
|
|
16
|
+
const G = "\x1b[38;2;186;115;6m"; // gold
|
|
17
|
+
const R = "\x1b[0m"; // reset
|
|
18
|
+
// ── ANSI fallback logo ────────────────────────────────────────────────────────
|
|
19
|
+
// Per-letter gradient colors matching the Balchemy brand logo
|
|
20
|
+
// Generated via figlet -f small, then colorized per-letter
|
|
21
|
+
const C1 = "\x1b[38;2;0;172;176m"; // B — teal
|
|
22
|
+
const C2 = "\x1b[38;2;0;152;160m"; // A — teal-blue
|
|
23
|
+
const C3 = "\x1b[38;2;180;100;140m"; // L — rose
|
|
24
|
+
const C4 = "\x1b[38;2;186;155;6m"; // C — gold
|
|
25
|
+
const C5 = "\x1b[38;2;0;160;170m"; // H — teal
|
|
26
|
+
const C6 = "\x1b[38;2;80;130;200m"; // E — blue
|
|
27
|
+
const C7 = "\x1b[38;2;170;90;150m"; // M — magenta
|
|
28
|
+
const C8 = "\x1b[38;2;90;140;190m"; // Y — slate blue
|
|
29
|
+
const D = "\x1b[38;5;245m"; // dim gray
|
|
30
|
+
const ANSI_LOGO = [
|
|
31
|
+
``,
|
|
32
|
+
` ${C1} ___ ${R}${C2} _ ${R}${C3} _ ${R}${C4} ___ ${R}${C5} _ _ ${R}${C6} ___ ${R}${C7} __ __ ${R}${C8}__ __${R}`,
|
|
33
|
+
` ${C1}| _ )${R}${C2} /_\\ ${R}${C3}| | ${R}${C4} / __|${R}${C5}| || |${R}${C6}| __|${R}${C7}| \\/ |${R}${C8}\\ \\ / /${R}`,
|
|
34
|
+
` ${C1}| _ \\${R}${C2} / _ \\ ${R}${C3}| |__ ${R}${C4}| (__ ${R}${C5}| __ |${R}${C6}| _| ${R}${C7}| |\\/| |${R}${C8} \\ V / ${R}`,
|
|
35
|
+
` ${C1}|___/${R}${C2}/_/ \\_\\${R}${C3}|____|${R}${C4} \\___|${R}${C5}|_||_|${R}${C6}|___|${R}${C7}|_| |_|${R}${C8} |_| ${R}`,
|
|
36
|
+
` ${D}${"─".repeat(52)}${R}`,
|
|
37
|
+
``,
|
|
38
|
+
].join("\n");
|
|
39
|
+
function detectProtocol() {
|
|
40
|
+
const term = process.env.TERM_PROGRAM ?? "";
|
|
41
|
+
const termInfo = process.env.TERM ?? "";
|
|
42
|
+
// iTerm2 inline image protocol
|
|
43
|
+
if (term === "iTerm.app" ||
|
|
44
|
+
term === "WezTerm" ||
|
|
45
|
+
process.env.WEZTERM_EXECUTABLE) {
|
|
46
|
+
return "iterm2";
|
|
47
|
+
}
|
|
48
|
+
// Kitty graphics protocol
|
|
49
|
+
if (process.env.KITTY_WINDOW_ID || termInfo.includes("kitty")) {
|
|
50
|
+
return "kitty";
|
|
51
|
+
}
|
|
52
|
+
return "none";
|
|
53
|
+
}
|
|
54
|
+
// ── iTerm2 inline image rendering ─────────────────────────────────────────────
|
|
55
|
+
function renderIterm2(image, widthCols) {
|
|
56
|
+
return `\x1b]1337;File=size=${image.byteSize};inline=1;width=${widthCols};preserveAspectRatio=1:${image.base64}\x07`;
|
|
57
|
+
}
|
|
58
|
+
// ── Kitty graphics protocol rendering ─────────────────────────────────────────
|
|
59
|
+
function renderKitty(image, widthCols) {
|
|
60
|
+
const chunks = [];
|
|
61
|
+
const chunkSize = 4096;
|
|
62
|
+
for (let i = 0; i < image.base64.length; i += chunkSize) {
|
|
63
|
+
const chunk = image.base64.slice(i, i + chunkSize);
|
|
64
|
+
const isLast = i + chunkSize >= image.base64.length;
|
|
65
|
+
if (i === 0) {
|
|
66
|
+
chunks.push(`\x1b_Gq=2,f=100,a=T,c=${widthCols},m=${isLast ? 0 : 1};${chunk}\x1b\\`);
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
chunks.push(`\x1b_Gm=${isLast ? 0 : 1};${chunk}\x1b\\`);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
return chunks.join("");
|
|
73
|
+
}
|
|
74
|
+
// ── Public API ────────────────────────────────────────────────────────────────
|
|
75
|
+
/**
|
|
76
|
+
* Render the BCrow logo. Uses native terminal image protocol when available,
|
|
77
|
+
* falls back to ANSI block art.
|
|
78
|
+
*
|
|
79
|
+
* @param widthCols — terminal columns to use for the image (default 20)
|
|
80
|
+
*/
|
|
81
|
+
export function renderLogo(widthCols = 20) {
|
|
82
|
+
const protocol = detectProtocol();
|
|
83
|
+
if (protocol === "none") {
|
|
84
|
+
return ANSI_LOGO;
|
|
85
|
+
}
|
|
86
|
+
// Try to load the bundled image
|
|
87
|
+
const image = loadBundledImage();
|
|
88
|
+
if (!image) {
|
|
89
|
+
return ANSI_LOGO;
|
|
90
|
+
}
|
|
91
|
+
if (protocol === "iterm2") {
|
|
92
|
+
return "\n" + renderIterm2(image, widthCols) + "\n";
|
|
93
|
+
}
|
|
94
|
+
if (protocol === "kitty") {
|
|
95
|
+
return "\n" + renderKitty(image, widthCols) + "\n";
|
|
96
|
+
}
|
|
97
|
+
return ANSI_LOGO;
|
|
98
|
+
}
|
|
99
|
+
function loadBundledImage() {
|
|
100
|
+
const candidates = [
|
|
101
|
+
path.join(__dirname_esm, "..", "assets", "bcrow.png"),
|
|
102
|
+
path.join(__dirname_esm, "assets", "bcrow.png"),
|
|
103
|
+
path.join(process.cwd(), "create-balchemy-agent", "assets", "bcrow.png"),
|
|
104
|
+
];
|
|
105
|
+
for (const candidate of candidates) {
|
|
106
|
+
try {
|
|
107
|
+
if (fs.existsSync(candidate)) {
|
|
108
|
+
const buf = fs.readFileSync(candidate);
|
|
109
|
+
return {
|
|
110
|
+
base64: buf.toString("base64"),
|
|
111
|
+
byteSize: buf.byteLength,
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
catch {
|
|
116
|
+
// continue
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
return null;
|
|
120
|
+
}
|
|
121
|
+
//# sourceMappingURL=terminal-logo.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"terminal-logo.js","sourceRoot":"","sources":["../src/terminal-logo.ts"],"names":[],"mappings":"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"}
|