mindvest-atlas 0.95.0 → 0.96.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 +1 -1
- package/src/commands/memory.js +17 -7
- package/src/commands/remote-control.js +11 -0
- package/src/config.js +1 -1
- package/src/remote-control.js +30 -0
package/package.json
CHANGED
package/src/commands/memory.js
CHANGED
|
@@ -43,9 +43,19 @@ function printCard(card) {
|
|
|
43
43
|
println(` ${color.bold(lines[0])}`);
|
|
44
44
|
for (const l of lines.slice(1)) println(` ${l}`);
|
|
45
45
|
const project = card.project || card.source?.project;
|
|
46
|
-
|
|
46
|
+
const by = card.by || card.source?.by;
|
|
47
|
+
println(color.dim(` ${card.kind}${project ? ` · ${project}` : ''} · w${card.weight} · used ${card.score} · ${fade(card)} · stored ${stored(card)}${by ? ` by ${by}` : ''} · ${card.id.slice(0, 8)}`));
|
|
47
48
|
}
|
|
48
49
|
|
|
50
|
+
// WHO IS WRITING (owner, 2026-10-08: "they say claude gpt etc. To say who
|
|
51
|
+
// stored this"). A model running this from a chat passes its own name with
|
|
52
|
+
// `--by claude`; the app keeps it on the memory. A person at a terminal says
|
|
53
|
+
// nothing and is the CLI. A name is a short plain word, never free text.
|
|
54
|
+
const whoSays = (flags) => {
|
|
55
|
+
const said = String(flags?.by ?? '').trim().toLowerCase().replace(/\s+/g, '-').replace(/[^a-z0-9._+-]/g, '').slice(0, 40);
|
|
56
|
+
return said || 'cli';
|
|
57
|
+
};
|
|
58
|
+
|
|
49
59
|
export async function memoryCommand(args) {
|
|
50
60
|
const flags = args.flags || {};
|
|
51
61
|
const at = askAddress(flags.root);
|
|
@@ -97,7 +107,7 @@ export async function memoryCommand(args) {
|
|
|
97
107
|
project: flags.project === undefined
|
|
98
108
|
? (process.env.ATLAS_JOB || undefined)
|
|
99
109
|
: (typeof flags.project === 'string' ? flags.project : ''),
|
|
100
|
-
by:
|
|
110
|
+
by: whoSays(flags),
|
|
101
111
|
});
|
|
102
112
|
println('Remembered.');
|
|
103
113
|
printCard(out.memory);
|
|
@@ -111,7 +121,7 @@ export async function memoryCommand(args) {
|
|
|
111
121
|
const id = String(rest[0] || flags.id || '');
|
|
112
122
|
const weight = Number(flags.weight ?? rest[1]);
|
|
113
123
|
if (!id || !weight) { eprintln(color.red('`atlas memory weight <id> <1-10>`')); return 1; }
|
|
114
|
-
const out = await post(at, '/memory/update', { id, weight, by:
|
|
124
|
+
const out = await post(at, '/memory/update', { id, weight, by: whoSays(flags) });
|
|
115
125
|
printCard(out.memory);
|
|
116
126
|
return 0;
|
|
117
127
|
}
|
|
@@ -119,7 +129,7 @@ export async function memoryCommand(args) {
|
|
|
119
129
|
case 'demote': {
|
|
120
130
|
const id = String(rest[0] || flags.id || '');
|
|
121
131
|
if (!id) { eprintln(color.red(`\`atlas memory ${sub} <id> [--tier long|permanent|short]\``)); return 1; }
|
|
122
|
-
const out = await post(at, '/memory/update', { id, tier: flags.tier || (sub === 'promote' ? 'long' : 'short'), by:
|
|
132
|
+
const out = await post(at, '/memory/update', { id, tier: flags.tier || (sub === 'promote' ? 'long' : 'short'), by: whoSays(flags) });
|
|
123
133
|
printCard(out.memory);
|
|
124
134
|
return 0;
|
|
125
135
|
}
|
|
@@ -127,7 +137,7 @@ export async function memoryCommand(args) {
|
|
|
127
137
|
case 'unpin': {
|
|
128
138
|
const id = String(rest[0] || flags.id || '');
|
|
129
139
|
if (!id) { eprintln(color.red(`\`atlas memory ${sub} <id>\``)); return 1; }
|
|
130
|
-
const out = await post(at, '/memory/update', { id, pinned: sub === 'pin', by:
|
|
140
|
+
const out = await post(at, '/memory/update', { id, pinned: sub === 'pin', by: whoSays(flags) });
|
|
131
141
|
printCard(out.memory);
|
|
132
142
|
return 0;
|
|
133
143
|
}
|
|
@@ -138,7 +148,7 @@ export async function memoryCommand(args) {
|
|
|
138
148
|
// came back, so forgetting by the 8-character id it shows (which forget
|
|
139
149
|
// did not accept) said Forgotten and removed nothing. A miss is an
|
|
140
150
|
// error from the app now; this reports only what it was told.
|
|
141
|
-
const out = await post(at, '/memory/forget', { id, why: flags.why || 'removed from the CLI', by:
|
|
151
|
+
const out = await post(at, '/memory/forget', { id, why: flags.why || 'removed from the CLI', by: whoSays(flags) });
|
|
142
152
|
if (!out.forgotten) { eprintln(color.red(`Nothing was forgotten: no memory matched "${id}".`)); return 1; }
|
|
143
153
|
println(`Forgotten (${out.id || id}). It is in the trash for 30 days: \`atlas memory restore ${String(out.id || id).slice(0, 8)}\`.`);
|
|
144
154
|
return 0;
|
|
@@ -246,7 +256,7 @@ export async function memoryCommand(args) {
|
|
|
246
256
|
const out = await post(at, '/memory/list', {});
|
|
247
257
|
const verdict = out.queue.find((v) => v.id === id || v.id.startsWith(id));
|
|
248
258
|
if (!verdict) { eprintln(color.red('No proposal by that id. `atlas memory review` lists them.')); return 1; }
|
|
249
|
-
await post(at, '/memory/decide', { verdict, accept: sub === 'accept', by:
|
|
259
|
+
await post(at, '/memory/decide', { verdict, accept: sub === 'accept', by: whoSays(flags) });
|
|
250
260
|
println(sub === 'accept' ? 'Done.' : 'Kept as it was.');
|
|
251
261
|
return 0;
|
|
252
262
|
}
|
|
@@ -29,6 +29,7 @@ import {
|
|
|
29
29
|
SCRIPTS_DIR, projectsForAlert, readMode,
|
|
30
30
|
streamStudioFrames,
|
|
31
31
|
localBrokers, localBrokerCall,
|
|
32
|
+
localMemory,
|
|
32
33
|
studioVoice,
|
|
33
34
|
appendSaid,
|
|
34
35
|
} from '../remote-control.js';
|
|
@@ -490,6 +491,16 @@ async function handleAsk(ask, root) {
|
|
|
490
491
|
.catch((err) => answer(ask.request_id, { ok: false, error: String(err.message || err) }));
|
|
491
492
|
return undefined;
|
|
492
493
|
}
|
|
494
|
+
// MEMORY SHARING (owner, 2026-10-08): what Atlas Studio remembers on this
|
|
495
|
+
// computer, read or changed from the web, the phone or a tool. Not awaited:
|
|
496
|
+
// a write checks the new memory against the old ones with a model, which
|
|
497
|
+
// can take a minute, and the stream must keep serving everyone else.
|
|
498
|
+
if (ask.op === 'memory') {
|
|
499
|
+
void localMemory(ask.what, ask.data, root)
|
|
500
|
+
.then((out) => answer(ask.request_id, out && typeof out === 'object' ? out : { ok: false, error: 'No answer.' }))
|
|
501
|
+
.catch((err) => answer(ask.request_id, { ok: false, error: String(err.message || err) }));
|
|
502
|
+
return undefined;
|
|
503
|
+
}
|
|
493
504
|
if (ask.op === 'voice') {
|
|
494
505
|
// A voice the person is talking to on their phone, working Atlas Studio
|
|
495
506
|
// on this computer: one screen tool, carried out by the app itself.
|
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.
|
|
5
|
+
export const VERSION = '0.96.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';
|
package/src/remote-control.js
CHANGED
|
@@ -2018,6 +2018,36 @@ export async function localBrokerCall(connector, tool, args, root, timeoutMs = 1
|
|
|
2018
2018
|
return out;
|
|
2019
2019
|
}
|
|
2020
2020
|
|
|
2021
|
+
// What a person's computer answers about its memory when the web, the phone or
|
|
2022
|
+
// an assistant asks (the server's `op: 'memory'`): the endpoints Atlas Studio's
|
|
2023
|
+
// own memory already has, by name. Anything else is refused here, before the
|
|
2024
|
+
// app is asked.
|
|
2025
|
+
export const MEMORY_OPS = ['list', 'recall', 'tension', 'write', 'update', 'forget', 'restore'];
|
|
2026
|
+
|
|
2027
|
+
/**
|
|
2028
|
+
* One memory request, answered by Atlas Studio on THIS computer.
|
|
2029
|
+
*
|
|
2030
|
+
* The store is the app's (`.studio/memory`); this only passes the question to
|
|
2031
|
+
* it and the answer back, the way `atlas memory` does from a terminal. Memory
|
|
2032
|
+
* sharing is the person's own switch on the web (Profile, Memory): the server
|
|
2033
|
+
* asks nothing of a computer while it is off.
|
|
2034
|
+
*/
|
|
2035
|
+
export async function localMemory(what, data, root, timeoutMs = 150000) {
|
|
2036
|
+
const op = String(what || '').trim().toLowerCase();
|
|
2037
|
+
if (!MEMORY_OPS.includes(op)) return { ok: false, error: `unknown memory request ${op || '(none)'}` };
|
|
2038
|
+
const at = askAddress(root);
|
|
2039
|
+
if (!at) return { ok: false, error: 'Atlas Studio is not open on this computer. It holds the memory.' };
|
|
2040
|
+
const res = await fetch(at.url.replace('/ask', `/memory/${op}`), {
|
|
2041
|
+
method: 'POST',
|
|
2042
|
+
headers: { 'Content-Type': 'application/json', 'X-Atlas-Token': at.token },
|
|
2043
|
+
body: JSON.stringify(data && typeof data === 'object' && !Array.isArray(data) ? data : {}),
|
|
2044
|
+
signal: AbortSignal.timeout(timeoutMs),
|
|
2045
|
+
});
|
|
2046
|
+
const out = await res.json().catch(() => ({}));
|
|
2047
|
+
if (!res.ok) return { ok: false, error: out.error || `The memory request failed (${res.status}).` };
|
|
2048
|
+
return out && typeof out === 'object' ? out : { ok: false, error: 'No answer.' };
|
|
2049
|
+
}
|
|
2050
|
+
|
|
2021
2051
|
/**
|
|
2022
2052
|
* A VOICE THE PERSON IS TALKING TO SOMEWHERE ELSE, WORKING ATLAS STUDIO HERE
|
|
2023
2053
|
* (owner, 2026-10-06: "when I switch to local, where is the voice ... it
|