@boole-digital/cli 0.2.5 → 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.
Files changed (2) hide show
  1. package/dist/index.js +62 -1
  2. package/package.json +28 -8
package/dist/index.js CHANGED
@@ -685,6 +685,28 @@ function open(s) {
685
685
  });
686
686
  });
687
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
+ }
688
710
  async function runRemoteInherit(command) {
689
711
  const s = requireSession();
690
712
  const conn = await open(s);
@@ -765,8 +787,43 @@ function init(opts = {}) {
765
787
  log(` Your agent reads these rules and operates your trading computer through ${c.cyan("boole")}.`);
766
788
  }
767
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
+
768
825
  // src/index.ts
769
- var VERSION = "0.2.5";
826
+ var VERSION = "0.3.0";
770
827
  function parse(argv) {
771
828
  const _ = [];
772
829
  const flags = {};
@@ -803,6 +860,7 @@ ${c.bold("Getting started")}
803
860
  logout Sign out and clear the cached session
804
861
 
805
862
  ${c.bold("Operate the box")}
863
+ plan "<goal>" Ask the box's harness how to build something (returns an implementation plan)
806
864
  ssh "<command>" Run a command on the connected box (this is how you operate it)
807
865
  logs [name] Tail a strategy's logs
808
866
  balances [--venue <v>] Equity + open positions
@@ -858,6 +916,9 @@ async function main() {
858
916
  case "init":
859
917
  init({ dir: _[1], force: !!flags.force });
860
918
  break;
919
+ case "plan":
920
+ await plan({ request: _.slice(1).join(" ") });
921
+ break;
861
922
  case "ssh": {
862
923
  const command = _.slice(1).join(" ");
863
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.2.5",
4
- "description": "Boole install, sign in, and operate your trading computer from the terminal (Claude Code, Codex, Gemini).",
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": { "boole": "dist/index.js" },
6
+ "bin": {
7
+ "boole": "dist/index.js"
8
+ },
7
9
  "main": "dist/index.js",
8
- "files": ["dist/index.js", "README.md", "LICENSE"],
10
+ "files": [
11
+ "dist/index.js",
12
+ "README.md",
13
+ "LICENSE"
14
+ ],
9
15
  "license": "SEE LICENSE IN LICENSE",
10
- "engines": { "node": ">=18" },
11
- "repository": { "type": "git", "url": "git+https://github.com/Boole-Digital/portara-desktop.git" },
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": { "access": "public" },
14
- "keywords": ["boole", "trading", "cli", "claude-code", "codex", "gemini"],
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
  },