mindvest-atlas 0.68.3 → 0.68.4
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 +1 -1
- package/src/commands/computer-use.js +63 -1
package/package.json
CHANGED
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
// ONE IMPLEMENTATION, NOT TWO: every subcommand runs the SAME atlas_env function
|
|
22
22
|
// a project's script would call, inside the project, so the switch, the claim,
|
|
23
23
|
// the action log and standing back for a person are identically the same rules.
|
|
24
|
-
import { spawnSync } from 'node:child_process';
|
|
24
|
+
import { spawn, spawnSync } from 'node:child_process';
|
|
25
25
|
import crypto from 'node:crypto';
|
|
26
26
|
import fs from 'node:fs';
|
|
27
27
|
import path from 'node:path';
|
|
@@ -285,6 +285,63 @@ export function runInProject(job, code, root) {
|
|
|
285
285
|
return out.status === null ? 1 : out.status;
|
|
286
286
|
}
|
|
287
287
|
|
|
288
|
+
/**
|
|
289
|
+
* Start a watch that OUTLIVES this command.
|
|
290
|
+
*
|
|
291
|
+
* A watch runs for hours by design: it looks, decides how long to wait, and
|
|
292
|
+
* looks again. Run in the foreground, a shell agent that started one would sit
|
|
293
|
+
* there until it finished — one turn, held open, with nothing to show for it.
|
|
294
|
+
* The Python CLI has detached it since 2026-09-06; this runtime ran it inline,
|
|
295
|
+
* and this runtime is the one Atlas Studio bundles, so the blocking version is
|
|
296
|
+
* the one a chat actually got (owner, 2026-09-15).
|
|
297
|
+
*
|
|
298
|
+
* Detached, with no console and no pipes: what it does is visible in the watch
|
|
299
|
+
* window and the action log, which is where somebody watching already is.
|
|
300
|
+
*/
|
|
301
|
+
function startWatch(job, instruction, flags) {
|
|
302
|
+
if (!String(instruction || '').trim()) {
|
|
303
|
+
eprintln(color.red('Say what to watch for.'));
|
|
304
|
+
eprintln(color.dim(' atlas computer-use watch "when SPY breaks the opening range high, buy 1 call"'));
|
|
305
|
+
return 1;
|
|
306
|
+
}
|
|
307
|
+
const { dir } = workspace(job, undefined);
|
|
308
|
+
if (!fs.existsSync(dir)) {
|
|
309
|
+
eprintln(color.red(`There is no project called ${job} on this computer.`));
|
|
310
|
+
return 1;
|
|
311
|
+
}
|
|
312
|
+
try { ensureProjectFiles(dir); } catch { /* it may already be right */ }
|
|
313
|
+
const venv = venvPython(dir);
|
|
314
|
+
const python = venv ? [String(venv)] : [...ambientPython()];
|
|
315
|
+
const env = { ...process.env, ...jobEnv(dir), ATLAS_JOB: path.basename(dir) };
|
|
316
|
+
if (!env.ATLAS_ASK_URL || !env.ATLAS_ASK_TOKEN) {
|
|
317
|
+
const at = askAddress(undefined);
|
|
318
|
+
if (at) { env.ATLAS_ASK_URL = at.url; env.ATLAS_ASK_TOKEN = at.token; }
|
|
319
|
+
}
|
|
320
|
+
if (!env.ATLAS_COMPUTER_SESSION) env.ATLAS_COMPUTER_SESSION = shellSession(undefined);
|
|
321
|
+
env.PYTHONPATH = [dir, process.env.PYTHONPATH].filter(Boolean).join(path.delimiter);
|
|
322
|
+
ensureDeps(python, dir, env);
|
|
323
|
+
const kw = { every: Number(flags.every || 5) };
|
|
324
|
+
if (flags.most) kw.most = Number(flags.most);
|
|
325
|
+
if (flags.hours) kw.hours = Number(flags.hours);
|
|
326
|
+
const code = 'import atlas_env as e, json, sys\n'
|
|
327
|
+
+ 'e.watch(json.loads(sys.argv[1]), **json.loads(sys.argv[2]))\n';
|
|
328
|
+
try {
|
|
329
|
+
const child = spawn(
|
|
330
|
+
python[0],
|
|
331
|
+
[...python.slice(1), '-c', code, JSON.stringify(String(instruction)), JSON.stringify(kw)],
|
|
332
|
+
{ cwd: dir, env, stdio: 'ignore', detached: true, ...HIDDEN },
|
|
333
|
+
);
|
|
334
|
+
child.unref();
|
|
335
|
+
} catch (err) {
|
|
336
|
+
eprintln(color.red(`Could not start watching: ${err && err.message ? err.message : err}`));
|
|
337
|
+
return 1;
|
|
338
|
+
}
|
|
339
|
+
println(color.dim('Watching started. It looks, decides how long to wait, and looks again.'));
|
|
340
|
+
println(color.dim(' Follow it in the watch window, or: atlas computer-use screen'));
|
|
341
|
+
println(color.dim(' Stop ends it — the whole thing, wait included.'));
|
|
342
|
+
return 0;
|
|
343
|
+
}
|
|
344
|
+
|
|
288
345
|
export function computerUseCommand(args) {
|
|
289
346
|
const flags = args.flags || {};
|
|
290
347
|
const rest = [...(args.positional || args._ || [])];
|
|
@@ -351,6 +408,11 @@ export function computerUseCommand(args) {
|
|
|
351
408
|
return out;
|
|
352
409
|
}
|
|
353
410
|
|
|
411
|
+
// A WATCH FROM A CHAT MUST COME BACK: detached unless told otherwise.
|
|
412
|
+
if (sub === 'watch' && flags.background !== false) {
|
|
413
|
+
return startWatch(job, rest[0] || '', flags);
|
|
414
|
+
}
|
|
415
|
+
|
|
354
416
|
// SEVERAL ACTIONS AND ONE PICTURE, in one process. The slow part was never
|
|
355
417
|
// the clicking: it was a command and a look for every step, when four of them
|
|
356
418
|
// were visible in the picture you already had.
|