mindvest-atlas 0.93.0 → 0.94.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/README.md CHANGED
@@ -56,3 +56,28 @@ npm test
56
56
  Runs PKCE/arg/SSE/storage unit tests plus integration tests that drive the real
57
57
  OAuth client and loopback server against in-process mock servers — no network
58
58
  required.
59
+
60
+ ## Trade settings, paused workflows, sharing, the marketplace
61
+
62
+ Everything below was only on the website before 0.93.1.
63
+
64
+ ```bash
65
+ atlas signal-trade-settings # your defaults, accounts, and every group's settings
66
+ atlas signal-trade-settings --max-per-trade 230 # your budget for one trade
67
+ atlas signal-trade-settings --group-id <id> --accept-mode auto --max-per-trade 150
68
+ atlas signal-take --signal-id <id> --late true --max-per-trade 230
69
+ atlas signal-my-order --signal-id <id> --contracts 2 # or --cancel true
70
+ atlas signal-pending # plays waiting for your yes or no
71
+ atlas signal-answer --signal-id <id> --accept true
72
+
73
+ atlas workflow-restore --workflow-id <id> # turn a paused workflow back on
74
+ atlas workflow-review --workflow-id <id> # the run held for review; then --action place|discard --review-id <id>
75
+ atlas workflow-abort --workflow-id <id> # stop a run in progress
76
+ atlas workflow-follow --workflow-id <id> --follow false # make an imported copy your own
77
+ atlas workflow-history --workflow-id <id> # earlier versions; --version-id <id> --restore true goes back
78
+
79
+ atlas workflow-collab-find --query ada
80
+ atlas workflow-collab-set --workflow-id <id> --user-id <id> --roles '["writer","operator"]'
81
+ atlas marketplace-mine # what you sell and what you pay for
82
+ atlas marketplace-listing-update --kind signal_group --ref-id <id> --price 20 --status live
83
+ ```
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mindvest-atlas",
3
- "version": "0.93.0",
3
+ "version": "0.94.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": {
@@ -29,6 +29,7 @@ import {
29
29
  SCRIPTS_DIR, projectsForAlert, readMode,
30
30
  streamStudioFrames,
31
31
  localBrokers, localBrokerCall,
32
+ studioVoice,
32
33
  } from '../remote-control.js';
33
34
  import fs from 'node:fs';
34
35
  import os from 'node:os';
@@ -486,6 +487,14 @@ async function handleAsk(ask, root) {
486
487
  .catch((err) => answer(ask.request_id, { ok: false, error: String(err.message || err) }));
487
488
  return undefined;
488
489
  }
490
+ if (ask.op === 'voice') {
491
+ // A voice the person is talking to on their phone, working Atlas Studio
492
+ // on this computer: one screen tool, carried out by the app itself.
493
+ void studioVoice(ask.name, ask.args, ask.allowed === true, root)
494
+ .then((out) => answer(ask.request_id, out))
495
+ .catch((err) => answer(ask.request_id, { ok: false, error: String(err.message || err) }));
496
+ return undefined;
497
+ }
489
498
  if (ask.op === 'build') {
490
499
  // THE POINT OF ALL OF THIS. Words in, working script out: the owner says
491
500
  // what they want in one sentence and their own model writes it, runs it,
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.93.0';
5
+ export const VERSION = '0.94.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';
@@ -2018,6 +2018,52 @@ export async function localBrokerCall(connector, tool, args, root, timeoutMs = 1
2018
2018
  return out;
2019
2019
  }
2020
2020
 
2021
+ /**
2022
+ * A VOICE THE PERSON IS TALKING TO SOMEWHERE ELSE, WORKING ATLAS STUDIO HERE
2023
+ * (owner, 2026-10-06: "when I switch to local, where is the voice ... it
2024
+ * controls atlas studio remotely and the user will approve too").
2025
+ *
2026
+ * The voice is on their phone or in their browser. One of its screen tools
2027
+ * (look, go_to, point_at, press, type_into) is carried out in the app's own
2028
+ * window on this computer, by the app's own rules. This only passes the
2029
+ * question to the app and the answer back; a press that needs a yes comes
2030
+ * back as `ask`, to be asked where the person is.
2031
+ *
2032
+ * There is nothing to press without the app, so a runner started by hand in a
2033
+ * terminal says so.
2034
+ */
2035
+ export const STUDIO_VOICE_TOOLS = ['look', 'go_to', 'point_at', 'press', 'type_into'];
2036
+ export async function studioVoice(name, args, allowed, root, opts = {}) {
2037
+ const fetchImpl = opts.fetch || fetch;
2038
+ if (!STUDIO_VOICE_TOOLS.includes(String(name || ''))) {
2039
+ return { ok: false, error: 'That cannot be done on the computer from here.' };
2040
+ }
2041
+ const at = (opts.address || askAddress)(root);
2042
+ if (!at) return { ok: false, error: 'Atlas Studio is not open on that computer.' };
2043
+ try {
2044
+ const res = await fetchImpl(at.url.replace('/ask', '/voice'), {
2045
+ method: 'POST',
2046
+ headers: { 'Content-Type': 'application/json', 'X-Atlas-Token': at.token },
2047
+ body: JSON.stringify({
2048
+ name: String(name),
2049
+ args: args && typeof args === 'object' && !Array.isArray(args) ? args : {},
2050
+ // Only `true` is a yes.
2051
+ allowed: allowed === true,
2052
+ }),
2053
+ signal: AbortSignal.timeout(opts.timeoutMs ?? 25000),
2054
+ });
2055
+ const out = await res.json().catch(() => ({}));
2056
+ // An app from before this door existed answers 404 or its own refusal.
2057
+ if (res.status === 404 || res.status === 405) {
2058
+ return { ok: false, error: 'Atlas Studio on that computer needs updating before a voice can work it from here.' };
2059
+ }
2060
+ if (!res.ok || !out || out.ok === false) return { ok: false, error: (out && out.error) || `Atlas Studio answered ${res.status}.` };
2061
+ return { ok: true, result: out.result && typeof out.result === 'object' ? out.result : {} };
2062
+ } catch (err) {
2063
+ return { ok: false, error: 'Atlas Studio on that computer did not answer.' };
2064
+ }
2065
+ }
2066
+
2021
2067
  /**
2022
2068
  * Stream a chat turn from the model on THIS computer.
2023
2069
  *