wendkeep 0.70.0 → 0.72.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/CHANGELOG.md +57 -0
- package/README.en.md +7 -3
- package/README.md +7 -3
- package/docs/en/commands/observer.md +80 -35
- package/docs/pt-BR/commands/observer.md +82 -37
- package/hooks/observer-publish.mjs +1 -0
- package/package.json +3 -2
- package/packages/integrations/src/host-hooks.mjs +2 -0
- package/schema/observer/001-authority.sql +107 -0
- package/schema/observer/002-usage.sql +72 -0
- package/schema/observer/003-transcripts.sql +21 -0
- package/src/observer-memory-publish.mjs +335 -0
- package/src/observer-memory.mjs +308 -0
- package/src/observer-publish.mjs +23 -9
- package/src/observer-server.mjs +335 -22
- package/src/observer-sql-migrate.mjs +335 -0
- package/src/observer-sql-publish.mjs +398 -0
- package/src/observer-sql-store.mjs +542 -0
- package/src/observer-transcript-store.mjs +49 -0
- package/src/observer.mjs +72 -16
- package/web/observer/app.mjs +858 -0
- package/web/observer/favicon.svg +5 -0
- package/web/observer/index.html +126 -0
- package/web/observer/styles.css +262 -0
package/src/observer.mjs
CHANGED
|
@@ -2,20 +2,24 @@ import { homedir } from 'node:os';
|
|
|
2
2
|
import { isAbsolute, resolve } from 'node:path';
|
|
3
3
|
import { appendObserverEvent, readObserverIndex, registerObserverProject } from './observer-store.mjs';
|
|
4
4
|
import { buildProjectSnapshot } from './observer-snapshot.mjs';
|
|
5
|
+
import { compareMemoryParity } from './observer-memory-publish.mjs';
|
|
6
|
+
import { publishObserverSql } from './observer-sql-publish.mjs';
|
|
5
7
|
import { startObserverServer } from './observer-server.mjs';
|
|
8
|
+
import { ensureObserverDatabase, migrateObserverDatabase, listSqlProjects, OBSERVER_SQL_FILE, OBSERVER_SQL_SCHEMA_VERSION } from './observer-sql-store.mjs';
|
|
6
9
|
import { resolveProjectVault } from '../packages/vault/src/project-vault.mjs';
|
|
7
10
|
|
|
8
11
|
export const OBSERVER_HELP = `wendkeep observer — Observer local multi-projeto
|
|
9
12
|
|
|
10
13
|
Uso:
|
|
11
|
-
wendkeep observer serve [--data-dir P] [--host 127.0.0.1] [--port 8787]
|
|
14
|
+
wendkeep observer serve [--data-dir P] [--host 127.0.0.1] [--port 8787]
|
|
12
15
|
[--allow-non-loopback]
|
|
13
16
|
wendkeep observer register --project P [--vault V] [--data-dir D] [--json]
|
|
14
17
|
wendkeep observer publish --project P [--vault V] [--data-dir D] [--json]
|
|
18
|
+
wendkeep observer memory import --project P [--vault V] [--url U] [--json]
|
|
15
19
|
wendkeep observer status [--data-dir D] [--json]
|
|
16
20
|
|
|
17
|
-
O
|
|
18
|
-
|
|
21
|
+
O Observer local pode manter snapshots operacionais e uma cópia completa da memória em volume
|
|
22
|
+
Docker. O comando memory import faz a primeira migração de um vault para o container.
|
|
19
23
|
`;
|
|
20
24
|
|
|
21
25
|
function optionValue(argv, name) {
|
|
@@ -41,8 +45,8 @@ function vaultBase(argv, root) {
|
|
|
41
45
|
return resolveProjectVault({ startDir: root }).base;
|
|
42
46
|
}
|
|
43
47
|
|
|
44
|
-
function print(value, asJson) {
|
|
45
|
-
|
|
48
|
+
function print(value, asJson, write = (chunk) => process.stdout.write(chunk)) {
|
|
49
|
+
write((asJson ? JSON.stringify(value, null, 2) : String(value)) + '\n');
|
|
46
50
|
}
|
|
47
51
|
|
|
48
52
|
function summary(index) {
|
|
@@ -52,7 +56,22 @@ function summary(index) {
|
|
|
52
56
|
};
|
|
53
57
|
}
|
|
54
58
|
|
|
55
|
-
|
|
59
|
+
function databaseSummary(dir) {
|
|
60
|
+
const db = ensureObserverDatabase(dir);
|
|
61
|
+
try {
|
|
62
|
+
const migrations = migrateObserverDatabase(db);
|
|
63
|
+
return {
|
|
64
|
+
engine: 'sqlite',
|
|
65
|
+
file: OBSERVER_SQL_FILE,
|
|
66
|
+
schema_version: OBSERVER_SQL_SCHEMA_VERSION,
|
|
67
|
+
migrations: migrations.applied.length,
|
|
68
|
+
projects: listSqlProjects(db).length,
|
|
69
|
+
ready: true,
|
|
70
|
+
};
|
|
71
|
+
} finally { db.close(); }
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export async function runObserver(argv = [], { write = (chunk) => process.stdout.write(chunk) } = {}) {
|
|
56
75
|
const [sub] = argv;
|
|
57
76
|
const asJson = argv.includes('--json');
|
|
58
77
|
if (!sub || sub === 'help') {
|
|
@@ -62,30 +81,67 @@ export async function runObserver(argv = []) {
|
|
|
62
81
|
const dir = dataDir(argv);
|
|
63
82
|
|
|
64
83
|
if (sub === 'status') {
|
|
65
|
-
print(summary(readObserverIndex(dir)), asJson);
|
|
84
|
+
print({ ...summary(readObserverIndex(dir)), database: databaseSummary(dir) }, asJson, write);
|
|
66
85
|
return 0;
|
|
67
86
|
}
|
|
68
87
|
|
|
69
88
|
if (sub === 'serve') {
|
|
70
|
-
const token = optionValue(argv, '--token') || process.env.WENDKEEP_OBSERVER_TOKEN || '';
|
|
71
89
|
const host = optionValue(argv, '--host') || '127.0.0.1';
|
|
72
90
|
const server = await startObserverServer({
|
|
73
91
|
dataDir: dir,
|
|
74
92
|
host,
|
|
75
93
|
port: Number(optionValue(argv, '--port') || 8787),
|
|
76
|
-
token,
|
|
77
94
|
allowNonLoopback: argv.includes('--allow-non-loopback'),
|
|
78
95
|
});
|
|
79
|
-
if (!token) {
|
|
80
|
-
await server.close();
|
|
81
|
-
throw new Error('Observer exige --token ou WENDKEEP_OBSERVER_TOKEN.');
|
|
82
|
-
}
|
|
83
96
|
const address = server.address();
|
|
84
97
|
process.stdout.write(`wendkeep observer listening: http://${address.address}:${address.port}\n`);
|
|
85
98
|
return 0;
|
|
86
99
|
}
|
|
87
100
|
|
|
88
|
-
if (
|
|
101
|
+
if (sub === 'memory') {
|
|
102
|
+
const action = argv[1] || '';
|
|
103
|
+
if (action !== 'import') throw new Error('observer memory: use memory import.');
|
|
104
|
+
const root = projectRoot(argv);
|
|
105
|
+
const vault = vaultBase(argv, root);
|
|
106
|
+
const snapshot = buildProjectSnapshot({ vaultBase: vault, projectRoot: root });
|
|
107
|
+
const url = optionValue(argv, '--url') || process.env.WENDKEEP_OBSERVER_URL || '';
|
|
108
|
+
if (!url) throw new Error('observer memory import: --url ou WENDKEEP_OBSERVER_URL é obrigatório.');
|
|
109
|
+
const headers = { 'content-type': 'application/json', accept: 'application/json' };
|
|
110
|
+
const registration = await fetch(
|
|
111
|
+
String(url).replace(/\/$/, '') + '/v1/projects/' + encodeURIComponent(snapshot.project_id),
|
|
112
|
+
{
|
|
113
|
+
method: 'PUT',
|
|
114
|
+
headers,
|
|
115
|
+
body: JSON.stringify({
|
|
116
|
+
project_id: snapshot.project_id,
|
|
117
|
+
project_name: snapshot.project_name,
|
|
118
|
+
wendkeep_version: snapshot.wendkeep_version,
|
|
119
|
+
}),
|
|
120
|
+
},
|
|
121
|
+
);
|
|
122
|
+
if (!registration.ok) throw new Error('Observer não registrou o projeto: HTTP ' + registration.status + '.');
|
|
123
|
+
const sql = await publishObserverSql({
|
|
124
|
+
vaultBase: vault,
|
|
125
|
+
projectId: snapshot.project_id,
|
|
126
|
+
url,
|
|
127
|
+
});
|
|
128
|
+
const parity = await compareMemoryParity({
|
|
129
|
+
vaultBase: vault,
|
|
130
|
+
projectId: snapshot.project_id,
|
|
131
|
+
url,
|
|
132
|
+
});
|
|
133
|
+
const result = {
|
|
134
|
+
ok: sql.ok && parity.missing === 0 && parity.mismatched === 0,
|
|
135
|
+
project_id: snapshot.project_id,
|
|
136
|
+
sql,
|
|
137
|
+
memory: { ...sql, authority: 'sqlite' },
|
|
138
|
+
parity,
|
|
139
|
+
};
|
|
140
|
+
print(result, asJson, write);
|
|
141
|
+
return result.ok ? 0 : 1;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
if (!['register', 'publish'].includes(sub)) throw new Error('observer: subcomando desconhecido: ' + sub);
|
|
89
145
|
const root = projectRoot(argv);
|
|
90
146
|
const vault = vaultBase(argv, root);
|
|
91
147
|
const snapshot = buildProjectSnapshot({ vaultBase: vault, projectRoot: root });
|
|
@@ -97,12 +153,12 @@ export async function runObserver(argv = []) {
|
|
|
97
153
|
wendkeepVersion: snapshot.wendkeep_version,
|
|
98
154
|
});
|
|
99
155
|
if (!result.registered) throw new Error(result.errors.join(' '));
|
|
100
|
-
print(result, asJson);
|
|
156
|
+
print(result, asJson, write);
|
|
101
157
|
return 0;
|
|
102
158
|
}
|
|
103
159
|
|
|
104
160
|
const result = appendObserverEvent(dir, snapshot);
|
|
105
161
|
if (!result.accepted && !result.duplicate) throw new Error(result.errors.join(' '));
|
|
106
|
-
print({ ok: true, ...result }, asJson);
|
|
162
|
+
print({ ok: true, ...result }, asJson, write);
|
|
107
163
|
return 0;
|
|
108
164
|
}
|