mindvest-atlas 0.45.0 → 0.47.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mindvest-atlas",
3
- "version": "0.45.0",
3
+ "version": "0.47.0",
4
4
  "description": "Atlas CLI \u2014 OAuth login, tool calls, and live alert/flow streaming for the Atlas trading API",
5
5
  "type": "module",
6
6
  "bin": {
package/src/config.js CHANGED
@@ -2,7 +2,7 @@
2
2
  import path from 'node:path';
3
3
  import os from 'node:os';
4
4
 
5
- export const VERSION = '0.45.0';
5
+ export const VERSION = '0.47.0';
6
6
  export const DEFAULT_BASE_URL = 'https://atlasmcp.finmanagerai.com';
7
7
  export const DEFAULT_SCOPE = 'atlas broker';
8
8
  export const CLIENT_NAME = 'Atlas CLI';
@@ -843,6 +843,27 @@ def _do(action, fn, detail=None, points=()):
843
843
  if holder:
844
844
  _log_action(action, detail, ok=False, error="in use by %s" % (holder.get("job") or "another project"))
845
845
  raise RuntimeError(_busy(holder))
846
+ # AND NEVER ON ATLAS'S OWN STRIP. It is excluded from screen capture, so it
847
+ # is never in a picture, and it is still a window that takes clicks: a
848
+ # position read off a picture that happens to be under it presses Stop and
849
+ # ends the run, which then has no idea what it pressed (owner, 2026-09-06:
850
+ # "the agent should be careful so it does not stop itself").
851
+ #
852
+ # Atlas keeps the strip off the screen a run is working on where it can, and
853
+ # puts none up at all on a single screen. This is the second line: a refusal
854
+ # that holds whatever the placement decided, and on any machine whose window
855
+ # titles cannot be read.
856
+ if action in _ACTS_ON_A_WINDOW:
857
+ for point in points:
858
+ if _on_the_strip(*point):
859
+ _log_action(action, detail, ok=False, error="on the Atlas strip")
860
+ raise RuntimeError(
861
+ "(%s, %s) is under the Atlas strip, which is the bar showing "
862
+ "what this run is doing. It is not in the picture because it "
863
+ "is excluded from capture, and pressing it would stop this "
864
+ "run. Whatever you meant to click is elsewhere: look again."
865
+ % (point[0], point[1])
866
+ )
846
867
  # NOT INSIDE ATLAS UNLESS SOMEBODY SAID SO. Checked at the moment of acting
847
868
  # rather than when the window was focused: what matters is where the click
848
869
  # lands, and the front window can change between the two.
@@ -1413,8 +1434,23 @@ def do(*steps, **kw):
1413
1434
  try:
1414
1435
  fn(*args)
1415
1436
  except Exception as err:
1416
- raise RuntimeError("stopped at %s: %s (already did: %s)"
1417
- % (name, err, ", ".join(did) or "nothing"))
1437
+ # A LONG RUN HAS TO BE SAFE TO ATTEMPT, or caution is the right
1438
+ # answer and nobody will attempt one. So a sequence that stops
1439
+ # halfway hands back a PICTURE of where it stopped, not just the
1440
+ # name of the step: the whole reason to fear a six-step run is not
1441
+ # knowing what state it left behind, and this answers that in the
1442
+ # same breath as the failure.
1443
+ where = None
1444
+ try:
1445
+ shot = screen()
1446
+ where = shot if isinstance(shot, str) else shot.get("path")
1447
+ except Exception:
1448
+ pass
1449
+ raise RuntimeError(
1450
+ "stopped at %s (step %d of %d): %s. Already did: %s.%s"
1451
+ % (name, len(did) + 1, len(steps), err, ", ".join(did) or "nothing",
1452
+ (" The screen at that moment: %s" % where) if where else "")
1453
+ )
1418
1454
  did.append(str(name))
1419
1455
  if not look:
1420
1456
  return {"did": did}
@@ -1653,6 +1689,31 @@ def _front_window():
1653
1689
  return ""
1654
1690
 
1655
1691
 
1692
+ def _on_the_strip(x, y):
1693
+ """Is this point under Atlas's own driving strip?
1694
+
1695
+ The strip writes where it is, because nothing else can see it: it is
1696
+ excluded from capture, so a picture never shows it and no amount of looking
1697
+ would find it.
1698
+ """
1699
+ import json as _json
1700
+ root = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
1701
+ try:
1702
+ with open(os.path.join(root, ".studio", "strip.json"), encoding="utf-8") as fh:
1703
+ box = _json.load(fh)
1704
+ # A note left by a strip that has gone is not a no-go area for ever.
1705
+ import time as _time
1706
+ if _time.time() - float(box.get("at") or 0) > 120:
1707
+ return False
1708
+ # A little margin: a click at the very edge of it is still a click
1709
+ # somebody did not mean to make there.
1710
+ pad = 6
1711
+ return (int(box["x"]) - pad <= int(x) <= int(box["x"]) + int(box["width"]) + pad
1712
+ and int(box["y"]) - pad <= int(y) <= int(box["y"]) + int(box["height"]) + pad)
1713
+ except Exception:
1714
+ return False
1715
+
1716
+
1656
1717
  def _in_the_atlas_window():
1657
1718
  front = _front_window().lower()
1658
1719
  return any(name in front for name in _ATLAS_WINDOWS) if front else False