@boole-digital/cli 0.2.4 → 0.3.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/dist/index.js +79 -3
- package/package.json +28 -8
package/dist/index.js
CHANGED
|
@@ -356,8 +356,23 @@ var BooleApi = class {
|
|
|
356
356
|
method: "POST",
|
|
357
357
|
body: JSON.stringify({ accessCode: (accessCode || "").trim() })
|
|
358
358
|
});
|
|
359
|
-
const
|
|
360
|
-
|
|
359
|
+
const cand = [
|
|
360
|
+
body?.data?.droplet_password,
|
|
361
|
+
body?.data?.password,
|
|
362
|
+
body?.data?.ssh_password,
|
|
363
|
+
body?.data?.sshPassword,
|
|
364
|
+
body?.droplet_password,
|
|
365
|
+
body?.password,
|
|
366
|
+
body?.ssh_password,
|
|
367
|
+
body?.sshPassword,
|
|
368
|
+
body?.result?.password
|
|
369
|
+
];
|
|
370
|
+
const pw = cand.find((v) => typeof v === "string" && v.length > 0);
|
|
371
|
+
if (!pw) {
|
|
372
|
+
throw new Error(
|
|
373
|
+
"SSH password not present. topKeys=" + JSON.stringify(Object.keys(body || {})) + " dataKeys=" + JSON.stringify(Object.keys(body?.data || {}))
|
|
374
|
+
);
|
|
375
|
+
}
|
|
361
376
|
return String(pw);
|
|
362
377
|
}
|
|
363
378
|
// ---- talk to the gateway on the box (via the ownership-checked proxy) ---
|
|
@@ -670,6 +685,28 @@ function open(s) {
|
|
|
670
685
|
});
|
|
671
686
|
});
|
|
672
687
|
}
|
|
688
|
+
async function runRemote(command) {
|
|
689
|
+
const s = requireSession();
|
|
690
|
+
const conn = await open(s);
|
|
691
|
+
try {
|
|
692
|
+
return await new Promise((resolve2, reject) => {
|
|
693
|
+
conn.exec(command, (err2, stream) => {
|
|
694
|
+
if (err2) return reject(new Error(friendly(err2)));
|
|
695
|
+
let stdout = "";
|
|
696
|
+
let stderr = "";
|
|
697
|
+
stream.on("close", (code) => resolve2({ code: code ?? 0, stdout, stderr }));
|
|
698
|
+
stream.on("data", (d) => {
|
|
699
|
+
stdout += d.toString();
|
|
700
|
+
});
|
|
701
|
+
stream.stderr.on("data", (d) => {
|
|
702
|
+
stderr += d.toString();
|
|
703
|
+
});
|
|
704
|
+
});
|
|
705
|
+
});
|
|
706
|
+
} finally {
|
|
707
|
+
conn.end();
|
|
708
|
+
}
|
|
709
|
+
}
|
|
673
710
|
async function runRemoteInherit(command) {
|
|
674
711
|
const s = requireSession();
|
|
675
712
|
const conn = await open(s);
|
|
@@ -750,8 +787,43 @@ function init(opts = {}) {
|
|
|
750
787
|
log(` Your agent reads these rules and operates your trading computer through ${c.cyan("boole")}.`);
|
|
751
788
|
}
|
|
752
789
|
|
|
790
|
+
// src/plan.ts
|
|
791
|
+
async function plan({ request }) {
|
|
792
|
+
const req = (request || "").trim();
|
|
793
|
+
if (!req) die('Usage: boole plan "<what you want to build>"');
|
|
794
|
+
if (req.length > 4e3) die("Request too long (max 4000 chars). Trim it down.");
|
|
795
|
+
info("Asking your box how to build this \u2014 the harness has the full picture (this can take up to a minute)\u2026");
|
|
796
|
+
const payload = Buffer.from(JSON.stringify({ request: req })).toString("base64");
|
|
797
|
+
const cmd = `printf %s '${payload}' | base64 -d | curl -s --max-time 175 -X POST http://localhost:3000/api/plan -H 'content-type: application/json' -d @-`;
|
|
798
|
+
const { code, stdout, stderr } = await runRemote(cmd);
|
|
799
|
+
if (!stdout) die(`Could not reach the planner on your box${code ? ` (exit ${code})` : ""}. ${stderr || ""}`.trim());
|
|
800
|
+
let res;
|
|
801
|
+
try {
|
|
802
|
+
res = JSON.parse(stdout);
|
|
803
|
+
} catch {
|
|
804
|
+
die(`Planner returned an unexpected response: ${stdout.slice(0, 300) || stderr || "empty"}`);
|
|
805
|
+
}
|
|
806
|
+
if (res?.error) die(`Planner error: ${res.error}`);
|
|
807
|
+
const planText = String(res?.plan || "").trim();
|
|
808
|
+
if (!planText) die("Planner returned no plan. Try again in a moment.");
|
|
809
|
+
if (res?.degraded) {
|
|
810
|
+
log();
|
|
811
|
+
warn(c.bold("Your Boole account is out of credit \u2014 this plan came from a fallback model."));
|
|
812
|
+
log(c.yellow(" Boole does not consider this model capable of this planning task; treat the plan below with caution."));
|
|
813
|
+
log(c.yellow(" To restore full-quality planning, either:"));
|
|
814
|
+
log(c.yellow(" \u2022 top up a small amount of credit, or"));
|
|
815
|
+
log(c.yellow(" \u2022 connect your GPT account for subscription-based usage."));
|
|
816
|
+
log(c.yellow(` Do this in the Boole web app under ${c.bold("Usage & model settings")} (/usage).`));
|
|
817
|
+
}
|
|
818
|
+
log();
|
|
819
|
+
log(planText);
|
|
820
|
+
log();
|
|
821
|
+
info("Build it over SSH exactly as above \u2014 the paths + calls are the ones your box actually exposes.");
|
|
822
|
+
if (res?.model) log(c.dim(` planner model: ${res.model}${res?.degraded ? " (fallback)" : ""}`));
|
|
823
|
+
}
|
|
824
|
+
|
|
753
825
|
// src/index.ts
|
|
754
|
-
var VERSION = "0.
|
|
826
|
+
var VERSION = "0.3.0";
|
|
755
827
|
function parse(argv) {
|
|
756
828
|
const _ = [];
|
|
757
829
|
const flags = {};
|
|
@@ -788,6 +860,7 @@ ${c.bold("Getting started")}
|
|
|
788
860
|
logout Sign out and clear the cached session
|
|
789
861
|
|
|
790
862
|
${c.bold("Operate the box")}
|
|
863
|
+
plan "<goal>" Ask the box's harness how to build something (returns an implementation plan)
|
|
791
864
|
ssh "<command>" Run a command on the connected box (this is how you operate it)
|
|
792
865
|
logs [name] Tail a strategy's logs
|
|
793
866
|
balances [--venue <v>] Equity + open positions
|
|
@@ -843,6 +916,9 @@ async function main() {
|
|
|
843
916
|
case "init":
|
|
844
917
|
init({ dir: _[1], force: !!flags.force });
|
|
845
918
|
break;
|
|
919
|
+
case "plan":
|
|
920
|
+
await plan({ request: _.slice(1).join(" ") });
|
|
921
|
+
break;
|
|
846
922
|
case "ssh": {
|
|
847
923
|
const command = _.slice(1).join(" ");
|
|
848
924
|
if (!command) die('Usage: boole ssh "<command>"');
|
package/package.json
CHANGED
|
@@ -1,17 +1,37 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@boole-digital/cli",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Boole
|
|
3
|
+
"version": "0.3.0",
|
|
4
|
+
"description": "Boole \u2014 install, sign in, and operate your trading computer from the terminal (Claude Code, Codex, Gemini).",
|
|
5
5
|
"type": "module",
|
|
6
|
-
"bin": {
|
|
6
|
+
"bin": {
|
|
7
|
+
"boole": "dist/index.js"
|
|
8
|
+
},
|
|
7
9
|
"main": "dist/index.js",
|
|
8
|
-
"files": [
|
|
10
|
+
"files": [
|
|
11
|
+
"dist/index.js",
|
|
12
|
+
"README.md",
|
|
13
|
+
"LICENSE"
|
|
14
|
+
],
|
|
9
15
|
"license": "SEE LICENSE IN LICENSE",
|
|
10
|
-
"engines": {
|
|
11
|
-
|
|
16
|
+
"engines": {
|
|
17
|
+
"node": ">=18"
|
|
18
|
+
},
|
|
19
|
+
"repository": {
|
|
20
|
+
"type": "git",
|
|
21
|
+
"url": "git+https://github.com/Boole-Digital/portara-desktop.git"
|
|
22
|
+
},
|
|
12
23
|
"homepage": "https://trade.boole.markets",
|
|
13
|
-
"publishConfig": {
|
|
14
|
-
|
|
24
|
+
"publishConfig": {
|
|
25
|
+
"access": "public"
|
|
26
|
+
},
|
|
27
|
+
"keywords": [
|
|
28
|
+
"boole",
|
|
29
|
+
"trading",
|
|
30
|
+
"cli",
|
|
31
|
+
"claude-code",
|
|
32
|
+
"codex",
|
|
33
|
+
"gemini"
|
|
34
|
+
],
|
|
15
35
|
"dependencies": {
|
|
16
36
|
"ssh2": "^1.16.0"
|
|
17
37
|
},
|