mindvest-atlas 0.44.0 → 0.45.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.44.0",
3
+ "version": "0.45.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": {
@@ -155,6 +155,37 @@ export function askServer(job, op, args, root) {
155
155
  }
156
156
 
157
157
  /** Run one atlas_env call inside the project, and hand back what it said. */
158
+ /** What using the computer needs, and what it is called when you import it. */
159
+ const NEEDED = [['pyautogui', 'pyautogui'], ['mss', 'mss'], ['Pillow', 'PIL']];
160
+
161
+ /**
162
+ * Put what is missing into the interpreter that is ABOUT TO BE USED.
163
+ *
164
+ * Atlas installs these when the switch goes on, but into the ambient python,
165
+ * and a project with a venv of its own runs on that instead: the switch said
166
+ * ready and the run then found nothing. The interpreter here is the one the
167
+ * work will happen in, which is the only one worth checking.
168
+ *
169
+ * Best effort and quiet: a machine with no network or no pip is one that runs
170
+ * without it, and every call site already says what it cannot do.
171
+ */
172
+ export function ensureDeps(python, cwd, env) {
173
+ const check = `import ${NEEDED.map(([, mod]) => mod).join(', ')}`;
174
+ const has = () => spawnSync(python[0], [...python.slice(1), '-c', check],
175
+ { cwd, env, stdio: 'ignore' }).status === 0;
176
+ if (has()) return true;
177
+ println(color.dim(' Getting this computer ready (one time)…'));
178
+ // --user is wrong inside a venv and right outside one, so ask the interpreter
179
+ // which it is in rather than guessing.
180
+ const inVenv = spawnSync(python[0],
181
+ [...python.slice(1), '-c', 'import sys; sys.exit(0 if sys.prefix != sys.base_prefix else 1)'],
182
+ { cwd, env, stdio: 'ignore' }).status === 0;
183
+ const args = ['-m', 'pip', 'install', '--quiet', ...(inVenv ? [] : ['--user'])];
184
+ spawnSync(python[0], [...python.slice(1), ...args, ...NEEDED.map(([name]) => name)],
185
+ { cwd, env, stdio: 'ignore', timeout: 300000 });
186
+ return has();
187
+ }
188
+
158
189
  export function runInProject(job, code, root) {
159
190
  const { dir } = workspace(job, root);
160
191
  if (!fs.existsSync(dir)) {
@@ -165,6 +196,10 @@ export function runInProject(job, code, root) {
165
196
  const venv = venvPython(dir);
166
197
  const python = venv ? [String(venv)] : [...ambientPython()];
167
198
  const env = { ...process.env, ...jobEnv(dir), ATLAS_JOB: path.basename(dir) };
199
+ // BEFORE ANYTHING TRIES TO IMPORT THEM. Checked every time and installed only
200
+ // when something is missing, so the cost is one python start on a machine
201
+ // that is already set up.
202
+ ensureDeps(python, dir, env);
168
203
  // THE SAME HOLDER FOR EVERY COMMAND in this shell, and no process behind the
169
204
  // claim: each of these exits, and a claim needing a live process would be
170
205
  // gone before the next one ran.
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.44.0';
5
+ export const VERSION = '0.45.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';