@futdevpro/fdp-agent-memory 0.1.0 → 1.1.12
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/LICENSE +21 -0
- package/README.md +7 -7
- package/build/package.json +6 -5
- package/build/src/_cli/_collections/fam-arg.util.js +48 -0
- package/build/src/_cli/_collections/fam-cli.const.js +40 -0
- package/build/src/_cli/_collections/fam-output.util.js +86 -0
- package/build/src/_cli/_collections/fam-project-discovery.util.js +98 -0
- package/build/src/_cli/_commands/capture.command.js +73 -0
- package/build/src/_cli/_commands/config.command.js +93 -0
- package/build/src/_cli/_commands/doctor.command.js +124 -0
- package/build/src/_cli/_commands/errors.command.js +66 -0
- package/build/src/_cli/_commands/export.command.js +65 -0
- package/build/src/_cli/_commands/find-duplicates.command.js +97 -0
- package/build/src/_cli/_commands/import.command.js +136 -0
- package/build/src/_cli/_commands/init.command.js +147 -0
- package/build/src/_cli/_commands/read.command.js +109 -0
- package/build/src/_cli/_commands/scan-projects.command.js +138 -0
- package/build/src/_cli/_commands/scan.command.js +98 -0
- package/build/src/_cli/_commands/seed.command.js +40 -0
- package/build/src/_cli/_commands/serve.command.js +350 -0
- package/build/src/_cli/_commands/start.command.js +134 -0
- package/build/src/_cli/_commands/stats.command.js +54 -0
- package/build/src/_cli/_commands/write.command.js +103 -0
- package/build/src/_cli/_models/interfaces/fam-cli-global-options.interface.js +2 -0
- package/build/src/_cli/_models/interfaces/fam-cli-output.interface.js +9 -0
- package/build/src/_cli/_models/interfaces/fam-client-result.interface.js +2 -0
- package/build/src/_cli/_services/fam-client.service.js +140 -0
- package/build/src/_cli/register-commands.js +86 -0
- package/build/src/_collections/config-catalog.const.js +67 -1
- package/build/src/_collections/fam-console.util.js +367 -0
- package/build/src/_collections/fam-entry-bootstrap.util.js +158 -4
- package/build/src/_collections/fam-error-factory.util.js +0 -9
- package/build/src/_collections/fam-mcp-bridge.util.js +49 -0
- package/build/src/_collections/fam-reference-code.util.js +105 -0
- package/build/src/_collections/fam-version.const.js +10 -0
- package/build/src/_models/data-models/fam-entry-base-properties.const.js +1 -0
- package/build/src/_models/data-models/fam-entry.data-model.js +6 -0
- package/build/src/_models/data-models/fam-ingest-run.data-model.js +3 -1
- package/build/src/_models/data-models/fam-reference.data-model.js +7 -0
- package/build/src/_modules/capture/_collections/fam-capture.const.js +11 -0
- package/build/src/_modules/capture/_services/fam-auto-capture.control-service.js +87 -0
- package/build/src/_modules/capture/index.js +8 -0
- package/build/src/_modules/embedding/_collections/fam-embedding-prefix.util.js +77 -0
- package/build/src/_modules/embedding/_services/fam-duplicate-scan.control-service.js +202 -0
- package/build/src/_modules/embedding/_services/fam-embedding-pipeline.control-service.js +33 -9
- package/build/src/_modules/embedding/_services/fam-embedding.control-service.js +21 -2
- package/build/src/_modules/embedding/_services/fam-entry.data-service.js +135 -0
- package/build/src/_modules/embedding/_services/fam-vector-search.control-service.js +42 -32
- package/build/src/_modules/embedding/index.js +4 -1
- package/build/src/_modules/export/_collections/fam-export.const.js +22 -0
- package/build/src/_modules/export/_services/fam-export.control-service.js +64 -0
- package/build/src/_modules/export/index.js +8 -0
- package/build/src/_modules/ingest/_collections/fam-famignore.util.js +83 -0
- package/build/src/_modules/ingest/_collections/fam-file-routing.util.js +59 -48
- package/build/src/_modules/ingest/_collections/fam-project-identity.util.js +134 -0
- package/build/src/_modules/ingest/_collections/fam-scan-progress.util.js +57 -0
- package/build/src/_modules/ingest/_collections/fam-scan-summary.util.js +60 -0
- package/build/src/_modules/ingest/_collections/fam-scan-weight.util.js +53 -0
- package/build/src/_modules/ingest/_collections/fam-secret-exclude.util.js +37 -14
- package/build/src/_modules/ingest/_collections/fam-sliding-chunker.util.js +34 -0
- package/build/src/_modules/ingest/_collections/fam-ts-chunker.util.js +200 -14
- package/build/src/_modules/ingest/_services/fam-delta-compare.util.js +4 -1
- package/build/src/_modules/ingest/_services/fam-ingest-run.data-service.js +7 -4
- package/build/src/_modules/ingest/_services/fam-ingest.control-service.js +346 -17
- package/build/src/_modules/ingest/_services/fam-scan.control-service.js +25 -2
- package/build/src/_modules/ingest/index.js +3 -1
- package/build/src/_modules/mcp/_collections/fam-active-rules.util.js +56 -0
- package/build/src/_modules/mcp/_collections/fam-core-tools.const.js +47 -6
- package/build/src/_modules/mcp/_services/fam-capabilities-tool.service.js +4 -4
- package/build/src/_modules/mcp/_services/fam-capability-registry.service.js +224 -18
- package/build/src/_modules/mcp/_services/fam-mcp-adapter.service.js +4 -4
- package/build/src/_modules/mcp/_services/fam-mcp-server.service.js +4 -4
- package/build/src/_modules/mcp/_services/fam-read-tool.service.js +53 -1
- package/build/src/_modules/mcp/_services/fam-write-tool.service.js +104 -8
- package/build/src/_modules/mcp/index.js +4 -4
- package/build/src/_modules/migration/_collections/fam-claude-mem-normalize.util.js +66 -3
- package/build/src/_modules/migration/_collections/fam-prompt-aggregate.util.js +143 -0
- package/build/src/_modules/migration/_collections/fam-target-mapping.util.js +19 -0
- package/build/src/_modules/migration/_enums/fam-claude-mem-source.type-enum.js +6 -0
- package/build/src/_modules/migration/_models/interfaces/fam-claude-mem.interface.js +5 -0
- package/build/src/_modules/migration/_services/fam-agent-memory-reader.service.js +125 -0
- package/build/src/_modules/migration/_services/fam-claude-mem-import.control-service.js +101 -18
- package/build/src/_modules/migration/_services/fam-import-dedup.data-service.js +53 -0
- package/build/src/_modules/migration/index.js +3 -1
- package/build/src/_modules/retrieval/_services/fam-retrieval-candidate.data-service.js +78 -4
- package/build/src/_modules/retrieval/_services/fam-retrieval.control-service.js +293 -50
- package/build/src/_modules/scope-reference/_collections/fam-scope-normalize.util.js +6 -3
- package/build/src/_modules/scope-reference/_services/fam-reference.data-service.js +18 -0
- package/build/src/_modules/scope-reference/_services/fam-scope-resolver.control-service.js +79 -20
- package/build/src/_routes/server/api/api.controller.js +34 -2
- package/build/src/_routes/server/client-app/client-app.control-service.js +1 -1
- package/build/src/_routes/server/server-status/server-status.controller.js +2 -1
- package/build/src/app.server.js +13 -1
- package/build/src/environments/environment.js +1 -1
- package/build/src/index.js +1 -1
- package/client-dist/{chunk-GHKRM4SM.js → chunk-I77GXVAQ.js} +1 -1
- package/client-dist/{chunk-LMTL7GA3.js → chunk-YXHWCJ5O.js} +1 -1
- package/client-dist/index.html +1 -1
- package/client-dist/{main-2KWB3QYK.js → main-PJPEDVJT.js} +1 -1
- package/package.json +6 -5
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
FDP License
|
|
2
|
+
|
|
3
|
+
Copyright (c) Future Development Program Ltd. (HU)
|
|
4
|
+
|
|
5
|
+
Permission is not granted, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE
|
package/README.md
CHANGED
|
@@ -22,7 +22,7 @@ in-memory pool-ba hidratálódnak — **NINCS Atlas-dependencia**.
|
|
|
22
22
|
|
|
23
23
|
> **Boundary:** **nincs auth / jogosultságkezelés** (lokális, single-user); FDP Templates package
|
|
24
24
|
> nélkül (Pure Dynamo). Az MCP-transport MVP1-ben **stdio** (nincs hálózati port az MCP-felületnek;
|
|
25
|
-
> a `
|
|
25
|
+
> a `39265`-ös port a REST/UI réteghez tartozik). HTTP/SSE transport későbbi fázis (BACKLOG).
|
|
26
26
|
|
|
27
27
|
## 2. Install
|
|
28
28
|
|
|
@@ -66,8 +66,8 @@ LMSTUDIO_EMBEDDING_MODEL=nomic-embed-text-v1.5
|
|
|
66
66
|
# OPENAI_EMBEDDING_MODEL=text-embedding-3-large
|
|
67
67
|
|
|
68
68
|
# Portok (a REST/UI réteg; NEM az MCP-stdio)
|
|
69
|
-
FAM_SERVER_PORT=
|
|
70
|
-
FAM_CLIENT_PORT=
|
|
69
|
+
FAM_SERVER_PORT=39265
|
|
70
|
+
FAM_CLIENT_PORT=4226
|
|
71
71
|
```
|
|
72
72
|
|
|
73
73
|
### Teljes env-var referencia
|
|
@@ -81,8 +81,8 @@ FAM_CLIENT_PORT=4205
|
|
|
81
81
|
| `OPENAI_EMBEDDING_MODEL` | nem | `text-embedding-3-large` | OpenAI embedding-modell. |
|
|
82
82
|
| `LMSTUDIO_BASE_URL` | ha `provider=lmstudio` | `http://127.0.0.1:1234/v1` | LM Studio OpenAI-kompatibilis endpoint. |
|
|
83
83
|
| `LMSTUDIO_EMBEDDING_MODEL` | ha `provider=lmstudio` | — | A betöltött embedding-modell neve. |
|
|
84
|
-
| `FAM_SERVER_PORT` | nem | `
|
|
85
|
-
| `FAM_CLIENT_PORT` | nem | `
|
|
84
|
+
| `FAM_SERVER_PORT` | nem | `39265` | REST/UI szerver-port (NEM az MCP-stdio). |
|
|
85
|
+
| `FAM_CLIENT_PORT` | nem | `4226` | Angular UI dev-port (külön kliens-app). |
|
|
86
86
|
| `FAM_CONFIG_OVERRIDE` | nem | — | Opcionális boot-time config-override JSON-path (a DB-backed config-on felül). |
|
|
87
87
|
|
|
88
88
|
> **A futás-idejű minőségi paraméterek (`topK` / `minScore` / chunk-méret / overlap / dense-küszöb /
|
|
@@ -197,8 +197,8 @@ fam create-config # DB-backed config seedelése reasonable default-okkal
|
|
|
197
197
|
fam start # az MCP-szerver indítása stdio-n (CSAK a szerver)
|
|
198
198
|
```
|
|
199
199
|
|
|
200
|
-
> `fam start` az **MCP-szervert stdio-n** ÉS a **REST/UI réteget** indítja (port `
|
|
201
|
-
> **admin UI a <http://localhost:
|
|
200
|
+
> `fam start` az **MCP-szervert stdio-n** ÉS a **REST/UI réteget** indítja (port `39265`). A beépített
|
|
201
|
+
> **admin UI a <http://localhost:39265/api/app>** alatt érhető el — a **szerver szolgálja ki**, nincs
|
|
202
202
|
> külön kliens-process (egy `fam start` = teljes lokál felület). Ez az a parancs, amit az MCP-kliens
|
|
203
203
|
> config `command`-ja is meghív. (Alternatíva: `docker compose -f docker-compose.local.yml up` —
|
|
204
204
|
> ugyanez konténerből, lokál Mongo-val.)
|
package/build/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@futdevpro/fdp-agent-memory",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "1.1.12",
|
|
4
4
|
"description": "Local-first, vector-backed multi-table agent memory exposed as an MCP server (read/write/capabilities). Public, FDP-Templates-free, no auth.",
|
|
5
5
|
"private": false,
|
|
6
6
|
"publishConfig": {
|
|
@@ -17,9 +17,9 @@
|
|
|
17
17
|
},
|
|
18
18
|
"files": [
|
|
19
19
|
"build",
|
|
20
|
-
"bin",
|
|
21
20
|
"client-dist",
|
|
22
|
-
"README.md"
|
|
21
|
+
"README.md",
|
|
22
|
+
"LICENSE"
|
|
23
23
|
],
|
|
24
24
|
"engines": {
|
|
25
25
|
"node": ">=20"
|
|
@@ -54,11 +54,12 @@
|
|
|
54
54
|
"author": "FutDevPro",
|
|
55
55
|
"license": "FDP",
|
|
56
56
|
"dependencies": {
|
|
57
|
-
"@futdevpro/fsm-dynamo": "^1.16",
|
|
58
|
-
"@futdevpro/nts-dynamo": "^1.15",
|
|
57
|
+
"@futdevpro/fsm-dynamo": "^1.16.7",
|
|
58
|
+
"@futdevpro/nts-dynamo": "^1.15.72",
|
|
59
59
|
"@modelcontextprotocol/sdk": "^1.12.0",
|
|
60
60
|
"axios": "~1.8.1",
|
|
61
61
|
"better-sqlite3": "^12.4.1",
|
|
62
|
+
"commander": "^12.1.0",
|
|
62
63
|
"crypto-js": "~4.2.0",
|
|
63
64
|
"dotenv": "^16.4.7",
|
|
64
65
|
"express": "4.21.2",
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.FAM_Arg_Util = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* `FAM_Arg_Util` — közös flag-parserek a CLI-parancsokhoz (dsgn-010 §7). A `--scope` `layer=name,...`
|
|
6
|
+
* párokká → a server `scopePath`/`scopeFilter` wire-shape-jévé (`{ layer, rawName }[]`), a `--tags`/
|
|
7
|
+
* comma-listák tömbbé, és a commander **ismételhető** opcióinak collector-függvényei (`--query`/`--tables`).
|
|
8
|
+
*
|
|
9
|
+
* Statikus util (nincs állapot) — a CLI csak flag→server-input map, NEM domain-logika (a scope-feloldás a
|
|
10
|
+
* server-réteg felelőssége; itt csak a nyers `{ layer, rawName }` shape-re alakítunk).
|
|
11
|
+
*/
|
|
12
|
+
class FAM_Arg_Util {
|
|
13
|
+
/**
|
|
14
|
+
* Egy `--scope "organization=FutDevPro,project=Adventor"` string → a server `FAM_RawScopeLayer[]`
|
|
15
|
+
* wire-shape-je (`{ layer, rawName }[]`). Üres / hiányzó → `undefined` (nincs scope-prefilter).
|
|
16
|
+
*/
|
|
17
|
+
static parseScope(raw) {
|
|
18
|
+
if (!raw) {
|
|
19
|
+
return undefined;
|
|
20
|
+
}
|
|
21
|
+
const pairs = [];
|
|
22
|
+
for (const segment of raw.split(',')) {
|
|
23
|
+
const trimmed = segment.trim();
|
|
24
|
+
if (!trimmed) {
|
|
25
|
+
continue;
|
|
26
|
+
}
|
|
27
|
+
const eq = trimmed.indexOf('=');
|
|
28
|
+
if (eq < 0) {
|
|
29
|
+
continue;
|
|
30
|
+
}
|
|
31
|
+
pairs.push({ layer: trimmed.slice(0, eq).trim(), rawName: trimmed.slice(eq + 1).trim() });
|
|
32
|
+
}
|
|
33
|
+
return pairs.length ? pairs : undefined;
|
|
34
|
+
}
|
|
35
|
+
/** Egy comma-lista (`"a,b,c"`) → trimmelt, nem-üres tömb (vagy `undefined`). */
|
|
36
|
+
static parseList(raw) {
|
|
37
|
+
if (!raw) {
|
|
38
|
+
return undefined;
|
|
39
|
+
}
|
|
40
|
+
const items = raw.split(',').map((item) => item.trim()).filter((item) => item.length > 0);
|
|
41
|
+
return items.length ? items : undefined;
|
|
42
|
+
}
|
|
43
|
+
/** A commander ismételhető-opció collector-e (minden megjelenés a tömbbe gyűlik). */
|
|
44
|
+
static collect(value, previous) {
|
|
45
|
+
return [...previous, value];
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
exports.FAM_Arg_Util = FAM_Arg_Util;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* FAM CLI globális konstansok (dsgn-010 §3/§9). Egy fájlban a szorosan összetartozó CLI-szintű
|
|
4
|
+
* konstansok (exit-kód-térkép, default szerver-URL, CCAP retrieval-defaultok) — ezek NEM
|
|
5
|
+
* domain-konstansok (azok a szerver-réteg SSOT-jai), csak a CLI-front-end keretértékei.
|
|
6
|
+
*/
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.FAM_SCAN_SECRET_GUARD = exports.FAM_DEFAULT_TOP_K = exports.FAM_DEFAULT_SERVER_URL = exports.FAM_CliExitCode = void 0;
|
|
9
|
+
/**
|
|
10
|
+
* Egységes CLI exit-kódok (dsgn-010 §3). A `--json` mód a nem-`2` hibákra is `ok:false` burkot ír,
|
|
11
|
+
* így a hívó scriptek egységesen kezelhetik a kimenetet.
|
|
12
|
+
*/
|
|
13
|
+
var FAM_CliExitCode;
|
|
14
|
+
(function (FAM_CliExitCode) {
|
|
15
|
+
/** Siker (`ok:true`). */
|
|
16
|
+
FAM_CliExitCode[FAM_CliExitCode["ok"] = 0] = "ok";
|
|
17
|
+
/** Művelet-hiba (`ok:false` + strukturált `error`). */
|
|
18
|
+
FAM_CliExitCode[FAM_CliExitCode["operationError"] = 1] = "operationError";
|
|
19
|
+
/** Használati / argument-hiba (a commander adja). */
|
|
20
|
+
FAM_CliExitCode[FAM_CliExitCode["usageError"] = 2] = "usageError";
|
|
21
|
+
/** A remote szerver elérhetetlen (`FAM_SERVER_URL`/`--server-url`). */
|
|
22
|
+
FAM_CliExitCode[FAM_CliExitCode["serverUnreachable"] = 3] = "serverUnreachable";
|
|
23
|
+
})(FAM_CliExitCode || (exports.FAM_CliExitCode = FAM_CliExitCode = {}));
|
|
24
|
+
/** A CLI remote default szerver-URL-je (dsgn-010 §9; `FAM_SERVER_URL` env felülírja). */
|
|
25
|
+
exports.FAM_DEFAULT_SERVER_URL = 'http://127.0.0.1:39265';
|
|
26
|
+
/** A retrieval top-K CCAP-örökség default-ja (dsgn-007 `read.topK`). */
|
|
27
|
+
exports.FAM_DEFAULT_TOP_K = 5;
|
|
28
|
+
/**
|
|
29
|
+
* A `scan` alap secret-guard exclude-mintái (dsgn-004 §security). Ezek MINDIG hozzáadódnak a
|
|
30
|
+
* felhasználói `--exclude`-hoz; opt-out NEM megengedett titok-mintákra.
|
|
31
|
+
*/
|
|
32
|
+
exports.FAM_SCAN_SECRET_GUARD = [
|
|
33
|
+
'**/.env',
|
|
34
|
+
'**/.env.*',
|
|
35
|
+
'**/*.pem',
|
|
36
|
+
'**/*.key',
|
|
37
|
+
'**/id_rsa*',
|
|
38
|
+
'**/node_modules/**',
|
|
39
|
+
'**/.git/**',
|
|
40
|
+
];
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.FAM_Output_Util = void 0;
|
|
4
|
+
const fam_cli_const_1 = require("./fam-cli.const");
|
|
5
|
+
/**
|
|
6
|
+
* `FAM_Output_Util` — a CLI egységes kimenet- és exit-kód-rétege (dsgn-010 §3/§12). MINDEN parancs ezen
|
|
7
|
+
* át ír: a `--json` mód a stdout-ra KIZÁRÓLAG egyetlen JSON-burkot tesz (a `… --json | jq` pipe-tisztaság
|
|
8
|
+
* invariáns), minden log/diag a stderr-re megy. Néma hiba TILOS (dsgn-008): a hibák strukturált
|
|
9
|
+
* `FAM_CliError`-rá fordulnak és mindig megjelennek (default- és `--json`-kimeneten is).
|
|
10
|
+
*
|
|
11
|
+
* Statikus util (nincs állapot, nincs függőség) — a workspace-konvenció szerinti util-service.
|
|
12
|
+
*/
|
|
13
|
+
class FAM_Output_Util {
|
|
14
|
+
/** Egy nem-blokkoló diag-sor a stderr-re (a `--quiet` elnyomja). */
|
|
15
|
+
static logInfo(options, line) {
|
|
16
|
+
if (!options.quiet) {
|
|
17
|
+
process.stderr.write(`${line}\n`);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
/** Egy hiba-sor a stderr-re (a `--quiet` NEM nyomja el — hibák mindig láthatók). */
|
|
21
|
+
static logError(line) {
|
|
22
|
+
process.stderr.write(`${line}\n`);
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Siker-kimenet: a parancs-payload + opcionális warning/uncertainty. `--json` → egyetlen burok a
|
|
26
|
+
* stdout-ra; különben a `humanFormatter`-rel formázott szöveg (ha nincs formatter, a payload pretty-JSON).
|
|
27
|
+
* Visszatérési exit-kód: `0`.
|
|
28
|
+
*/
|
|
29
|
+
static success(input) {
|
|
30
|
+
const envelope = {
|
|
31
|
+
ok: true,
|
|
32
|
+
command: input.command,
|
|
33
|
+
data: input.data,
|
|
34
|
+
warnings: input.warnings ?? [],
|
|
35
|
+
uncertaintyNotes: input.uncertaintyNotes ?? [],
|
|
36
|
+
error: null,
|
|
37
|
+
};
|
|
38
|
+
if (input.options.json) {
|
|
39
|
+
process.stdout.write(`${JSON.stringify(envelope)}\n`);
|
|
40
|
+
}
|
|
41
|
+
else {
|
|
42
|
+
const text = input.humanFormatter
|
|
43
|
+
? input.humanFormatter(input.data)
|
|
44
|
+
: JSON.stringify(input.data, null, 2);
|
|
45
|
+
process.stdout.write(`${text}\n`);
|
|
46
|
+
for (const warning of envelope.warnings) {
|
|
47
|
+
FAM_Output_Util.logInfo(input.options, `⚠ ${warning}`);
|
|
48
|
+
}
|
|
49
|
+
for (const note of envelope.uncertaintyNotes) {
|
|
50
|
+
FAM_Output_Util.logInfo(input.options, `~ ${note}`);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
return fam_cli_const_1.FAM_CliExitCode.ok;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Hiba-kimenet: a strukturált `FAM_CliError` + a kapott exit-kód (default `1` művelet-hiba; `3`
|
|
57
|
+
* szerver-elérhetetlen). `--json` → `ok:false` burok a stdout-ra; különben a hiba a stderr-re
|
|
58
|
+
* (és a `fixHint`, ha van). A `2` (argument-hiba) a commander saját útja — ide NEM jut.
|
|
59
|
+
*/
|
|
60
|
+
static failure(input) {
|
|
61
|
+
const code = input.exitCode ?? fam_cli_const_1.FAM_CliExitCode.operationError;
|
|
62
|
+
const envelope = {
|
|
63
|
+
ok: false,
|
|
64
|
+
command: input.command,
|
|
65
|
+
data: null,
|
|
66
|
+
warnings: [],
|
|
67
|
+
uncertaintyNotes: [],
|
|
68
|
+
error: input.error,
|
|
69
|
+
};
|
|
70
|
+
if (input.options.json) {
|
|
71
|
+
process.stdout.write(`${JSON.stringify(envelope)}\n`);
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
FAM_Output_Util.logError(`✗ [${input.error.errorCode}] ${input.error.message}`);
|
|
75
|
+
if (input.error.fixHint) {
|
|
76
|
+
FAM_Output_Util.logError(` → ${input.error.fixHint}`);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
return code;
|
|
80
|
+
}
|
|
81
|
+
/** A kapott exit-kóddal lép ki (a handler-ek visszatérési értéke ezen át fut a process-exit-re). */
|
|
82
|
+
static exit(code) {
|
|
83
|
+
process.exitCode = code;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
exports.FAM_Output_Util = FAM_Output_Util;
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.FAM_ProjectDiscovery_Util = void 0;
|
|
4
|
+
const fs_1 = require("fs");
|
|
5
|
+
const path_1 = require("path");
|
|
6
|
+
/**
|
|
7
|
+
* `FAM_ProjectDiscovery_Util` (a `fam scan-projects` magja) — projekt-gyökerek **auto-felderítése** egy mappa
|
|
8
|
+
* alatt + a `--config` JSON-lista parse-je. PURE (fs-olvasás, nincs hálózat). A scope-nevet a `package.json`
|
|
9
|
+
* `name`-jéből deriválja (a user-kérte „package.json-ből olvas projekt-elnevezéseket"), fallback a dir-név.
|
|
10
|
+
*
|
|
11
|
+
* **Felderítés-szabály:** egy könyvtár PROJEKT-GYÖKÉR, ha van `package.json` VAGY `.git`. Ott MEGÁLLUNK (nem
|
|
12
|
+
* megyünk beljebb — egy monorepo gyökere egy projektnek számít). A `node_modules` + rejtett mappák kihagyva.
|
|
13
|
+
*/
|
|
14
|
+
class FAM_ProjectDiscovery_Util {
|
|
15
|
+
/** A projekt-gyökér markerek (bármelyik megléte → projekt). */
|
|
16
|
+
static MARKERS = ['package.json', '.git'];
|
|
17
|
+
/** Projekt-gyökér-e a könyvtár (van `package.json` vagy `.git`). */
|
|
18
|
+
static isProjectRoot(dir) {
|
|
19
|
+
return FAM_ProjectDiscovery_Util.MARKERS.some((marker) => (0, fs_1.existsSync)((0, path_1.join)(dir, marker)));
|
|
20
|
+
}
|
|
21
|
+
/** A scope leaf-név: a `package.json` `name` bare alakja (`@scope/x` → `x`), vagy a dir-név. */
|
|
22
|
+
static projectName(dir) {
|
|
23
|
+
try {
|
|
24
|
+
const pkgPath = (0, path_1.join)(dir, 'package.json');
|
|
25
|
+
if ((0, fs_1.existsSync)(pkgPath)) {
|
|
26
|
+
const name = JSON.parse((0, fs_1.readFileSync)(pkgPath, 'utf-8')).name;
|
|
27
|
+
if (typeof name === 'string' && name.trim()) {
|
|
28
|
+
return name.trim().replace(/^@[^/]+\//, '');
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
catch {
|
|
33
|
+
// fallback a dir-névre
|
|
34
|
+
}
|
|
35
|
+
return (0, path_1.basename)(dir);
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Projekt-gyökerek felderítése `root` alatt `maxDepth`-ig. Ha a `root` maga projekt → csak az. Egyébként
|
|
39
|
+
* rekurzívan a nem-rejtett alkönyvtárakban (egy projekt-gyökérnél MEGÁLL). Determinisztikus (név szerint rendezett).
|
|
40
|
+
*/
|
|
41
|
+
static discover(root, maxDepth, defaults) {
|
|
42
|
+
const result = [];
|
|
43
|
+
const visit = (dir, depth) => {
|
|
44
|
+
if (depth > maxDepth) {
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
if (FAM_ProjectDiscovery_Util.isProjectRoot(dir)) {
|
|
48
|
+
result.push({
|
|
49
|
+
path: dir, project: FAM_ProjectDiscovery_Util.projectName(dir),
|
|
50
|
+
org: defaults?.org, table: defaults?.table,
|
|
51
|
+
});
|
|
52
|
+
return; // egy projektbe NEM megyünk beljebb
|
|
53
|
+
}
|
|
54
|
+
let entries;
|
|
55
|
+
try {
|
|
56
|
+
entries = (0, fs_1.readdirSync)(dir).sort();
|
|
57
|
+
}
|
|
58
|
+
catch {
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
for (const name of entries) {
|
|
62
|
+
if (name.startsWith('.') || name === 'node_modules') {
|
|
63
|
+
continue;
|
|
64
|
+
}
|
|
65
|
+
const child = (0, path_1.join)(dir, name);
|
|
66
|
+
try {
|
|
67
|
+
if ((0, fs_1.statSync)(child).isDirectory()) {
|
|
68
|
+
visit(child, depth + 1);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
catch {
|
|
72
|
+
// olvashatatlan bejegyzés → kihagyjuk
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
visit(root, 0);
|
|
77
|
+
return result;
|
|
78
|
+
}
|
|
79
|
+
/** A `--config` JSON-lista → projekt-spec-ek (validálva: `path` + `project` kötelező soronként). */
|
|
80
|
+
static parseConfig(content) {
|
|
81
|
+
const parsed = JSON.parse(content);
|
|
82
|
+
if (!Array.isArray(parsed)) {
|
|
83
|
+
throw new Error('A scan-projects config egy JSON-tömb legyen: [{ "path": "...", "project": "..." }, ...]');
|
|
84
|
+
}
|
|
85
|
+
return parsed.map((raw, index) => {
|
|
86
|
+
const entry = (raw && typeof raw === 'object') ? raw : {};
|
|
87
|
+
if (typeof entry.path !== 'string' || typeof entry.project !== 'string') {
|
|
88
|
+
throw new Error(`A config[${index}] hiányos: a 'path' és a 'project' (string) kötelező.`);
|
|
89
|
+
}
|
|
90
|
+
return {
|
|
91
|
+
path: entry.path, project: entry.project,
|
|
92
|
+
org: typeof entry.org === 'string' ? entry.org : undefined,
|
|
93
|
+
table: typeof entry.table === 'string' ? entry.table : undefined,
|
|
94
|
+
};
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
exports.FAM_ProjectDiscovery_Util = FAM_ProjectDiscovery_Util;
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.FAM_Capture_Util = void 0;
|
|
4
|
+
const commander_1 = require("commander");
|
|
5
|
+
const fam_output_util_1 = require("../_collections/fam-output.util");
|
|
6
|
+
const fam_client_service_1 = require("../_services/fam-client.service");
|
|
7
|
+
const fam_cli_const_1 = require("../_collections/fam-cli.const");
|
|
8
|
+
/**
|
|
9
|
+
* `fam capture` — FEAT-006 thin-wrapper: egy session-observation auto-capture-je a `memory`-tárba. A szerver
|
|
10
|
+
* `auto_capture` capability-jére delegál (content-hash dedup → idempotens, agent-provenance + auto-embed). A
|
|
11
|
+
* `content` pozícionális argumentumként VAGY stdin-en (pipe) — a hook-használat (`echo "..." | fam capture`)
|
|
12
|
+
* természetes útja. Az opciók: `--session` (provenance), `--tag` (ismételhető), `--kind`.
|
|
13
|
+
*/
|
|
14
|
+
class FAM_Capture_Util {
|
|
15
|
+
/** A `capture` parancs-deszkriptor. */
|
|
16
|
+
static command() {
|
|
17
|
+
const command = new commander_1.Command('capture');
|
|
18
|
+
command
|
|
19
|
+
.description('Session-observation auto-capture a memory-tárba (content-hash dedup, FEAT-006)')
|
|
20
|
+
.argument('[content]', 'a megfigyelés szövege (elhagyva: stdin-ről olvas)')
|
|
21
|
+
.option('--session <id>', 'opcionális session-azonosító (provenance a source.path-ban)')
|
|
22
|
+
.option('--tag <tag...>', 'opcionális tag (ismételhető)')
|
|
23
|
+
.option('--kind <kind>', 'opcionális kind (default: observation)')
|
|
24
|
+
.action(async (content) => {
|
|
25
|
+
fam_output_util_1.FAM_Output_Util.exit(await FAM_Capture_Util.run(command, content));
|
|
26
|
+
});
|
|
27
|
+
return command;
|
|
28
|
+
}
|
|
29
|
+
/** A flow: content (arg VAGY stdin) → `auto_capture` capability invoke → render. */
|
|
30
|
+
static async run(command, contentArg) {
|
|
31
|
+
const globals = command.optsWithGlobals();
|
|
32
|
+
const local = command.opts();
|
|
33
|
+
const content = (contentArg ?? await FAM_Capture_Util.readStdin()).trim();
|
|
34
|
+
if (!content) {
|
|
35
|
+
return fam_output_util_1.FAM_Output_Util.failure({
|
|
36
|
+
options: globals,
|
|
37
|
+
command: 'capture',
|
|
38
|
+
error: {
|
|
39
|
+
errorCode: 'FAM-CLI-CAPTURE-001',
|
|
40
|
+
message: 'A `content` kötelező (pozícionális argumentum VAGY stdin-pipe).',
|
|
41
|
+
fixHint: 'Pl.: fam capture "megfigyelés" — vagy: echo "megfigyelés" | fam capture',
|
|
42
|
+
},
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
const client = new fam_client_service_1.FAM_CliClient_Service(globals.serverUrl);
|
|
46
|
+
const result = await client.post('/api/capabilities', {
|
|
47
|
+
action: 'invoke',
|
|
48
|
+
name: 'auto_capture',
|
|
49
|
+
arguments: { content: content, sessionId: local.session, tags: local.tag, kind: local.kind },
|
|
50
|
+
});
|
|
51
|
+
if (!result.ok) {
|
|
52
|
+
return fam_output_util_1.FAM_Output_Util.failure({
|
|
53
|
+
options: globals,
|
|
54
|
+
command: 'capture',
|
|
55
|
+
error: result.error ?? { errorCode: 'FAM-CLI-CAPTURE-002', message: 'Ismeretlen capture-hiba.' },
|
|
56
|
+
exitCode: result.unreachable ? fam_cli_const_1.FAM_CliExitCode.serverUnreachable : fam_cli_const_1.FAM_CliExitCode.operationError,
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
return fam_output_util_1.FAM_Output_Util.success({ options: globals, command: 'capture', data: result.data });
|
|
60
|
+
}
|
|
61
|
+
/** A stdin teljes beolvasása (pipe-használat). TTY (interaktív, nincs pipe) → üres string. */
|
|
62
|
+
static async readStdin() {
|
|
63
|
+
if (process.stdin.isTTY) {
|
|
64
|
+
return '';
|
|
65
|
+
}
|
|
66
|
+
const chunks = [];
|
|
67
|
+
for await (const chunk of process.stdin) {
|
|
68
|
+
chunks.push(chunk);
|
|
69
|
+
}
|
|
70
|
+
return Buffer.concat(chunks).toString('utf8');
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
exports.FAM_Capture_Util = FAM_Capture_Util;
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.FAM_Config_Util = void 0;
|
|
4
|
+
const commander_1 = require("commander");
|
|
5
|
+
const fam_output_util_1 = require("../_collections/fam-output.util");
|
|
6
|
+
const fam_client_service_1 = require("../_services/fam-client.service");
|
|
7
|
+
const fam_cli_const_1 = require("../_collections/fam-cli.const");
|
|
8
|
+
/**
|
|
9
|
+
* `fam config get|set` — a DB-backed scoped config CLI-tükre (dsgn-010 §11.1, dsgn-007). A `get`
|
|
10
|
+
* (`GET /api/config?table=`) a teljes effektív (merge-elt) configot adja a precedencia-forrással; a `set`
|
|
11
|
+
* (`PUT /api/config`) egy értéket ír a megadott szinten (global < table < scope). A kulcsok a dsgn-007
|
|
12
|
+
* `CONFIG_CATALOG` dotted nevei (a CLI nem vezet be saját config-névteret).
|
|
13
|
+
*/
|
|
14
|
+
class FAM_Config_Util {
|
|
15
|
+
/** A `config` parancs-deszkriptor (get/set alparanccsal). */
|
|
16
|
+
static command() {
|
|
17
|
+
const command = new commander_1.Command('config');
|
|
18
|
+
command.description('Scoped config olvasás/írás (dsgn-007 dotted kulcsok)');
|
|
19
|
+
command.addCommand(FAM_Config_Util.getCommand());
|
|
20
|
+
command.addCommand(FAM_Config_Util.setCommand());
|
|
21
|
+
return command;
|
|
22
|
+
}
|
|
23
|
+
/** `config get` — effektív (merge-elt) config az adott szinten. */
|
|
24
|
+
static getCommand() {
|
|
25
|
+
const command = new commander_1.Command('get');
|
|
26
|
+
command
|
|
27
|
+
.description('Az effektív (merge-elt) config az adott kontextusra')
|
|
28
|
+
.option('--key <key>', 'egy konkrét kulcs (dsgn-007 dotted)')
|
|
29
|
+
.option('--table <table>', 'table-szintű kontextus')
|
|
30
|
+
.option('--scope <layer=name,...>', 'scope-szintű kontextus')
|
|
31
|
+
.action(async () => {
|
|
32
|
+
fam_output_util_1.FAM_Output_Util.exit(await FAM_Config_Util.runGet(command));
|
|
33
|
+
});
|
|
34
|
+
return command;
|
|
35
|
+
}
|
|
36
|
+
/** `config set` — egy config-érték írása egy szinten. */
|
|
37
|
+
static setCommand() {
|
|
38
|
+
const command = new commander_1.Command('set');
|
|
39
|
+
command
|
|
40
|
+
.description('Egy config-érték beállítása egy szinten (global<table<scope)')
|
|
41
|
+
.requiredOption('--key <key>', 'a CONFIG_CATALOG dotted kulcsa')
|
|
42
|
+
.requiredOption('--value <value>', 'az új érték')
|
|
43
|
+
.option('--table <table>', 'table-szint')
|
|
44
|
+
.option('--scope <layer=name,...>', 'scope-szint')
|
|
45
|
+
.action(async () => {
|
|
46
|
+
fam_output_util_1.FAM_Output_Util.exit(await FAM_Config_Util.runSet(command));
|
|
47
|
+
});
|
|
48
|
+
return command;
|
|
49
|
+
}
|
|
50
|
+
/** A `config get` futtatása. */
|
|
51
|
+
static async runGet(command) {
|
|
52
|
+
const globals = command.optsWithGlobals();
|
|
53
|
+
const local = command.opts();
|
|
54
|
+
const query = local.table ? `?table=${encodeURIComponent(local.table)}` : '';
|
|
55
|
+
const client = new fam_client_service_1.FAM_CliClient_Service(globals.serverUrl);
|
|
56
|
+
const result = await client.get(`/api/config${query}`);
|
|
57
|
+
if (!result.ok) {
|
|
58
|
+
return FAM_Config_Util.fail(globals, 'config get', result, 'FAM-CLI-CONFIG-001');
|
|
59
|
+
}
|
|
60
|
+
// Egy konkrét kulcs szűrése (a server a teljes effektívet adja).
|
|
61
|
+
const data = local.key && result.data?.effective
|
|
62
|
+
? { key: local.key, value: result.data.effective[local.key] }
|
|
63
|
+
: result.data;
|
|
64
|
+
return fam_output_util_1.FAM_Output_Util.success({ options: globals, command: 'config get', data: data });
|
|
65
|
+
}
|
|
66
|
+
/** A `config set` futtatása. */
|
|
67
|
+
static async runSet(command) {
|
|
68
|
+
const globals = command.optsWithGlobals();
|
|
69
|
+
const local = command.opts();
|
|
70
|
+
const body = {
|
|
71
|
+
key: local.key,
|
|
72
|
+
value: local.value,
|
|
73
|
+
table: local.table,
|
|
74
|
+
scopeId: local.scope,
|
|
75
|
+
};
|
|
76
|
+
const client = new fam_client_service_1.FAM_CliClient_Service(globals.serverUrl);
|
|
77
|
+
const result = await client.put('/api/config', body);
|
|
78
|
+
if (!result.ok) {
|
|
79
|
+
return FAM_Config_Util.fail(globals, 'config set', result, 'FAM-CLI-CONFIG-002');
|
|
80
|
+
}
|
|
81
|
+
return fam_output_util_1.FAM_Output_Util.success({ options: globals, command: 'config set', data: result.data });
|
|
82
|
+
}
|
|
83
|
+
/** Közös hiba-render a config-parancsokhoz (unreachable → 3, egyébként 1). */
|
|
84
|
+
static fail(globals, command, result, fallbackCode) {
|
|
85
|
+
return fam_output_util_1.FAM_Output_Util.failure({
|
|
86
|
+
options: globals,
|
|
87
|
+
command: command,
|
|
88
|
+
error: result.error ?? { errorCode: fallbackCode, message: 'Ismeretlen config-hiba.' },
|
|
89
|
+
exitCode: result.unreachable ? fam_cli_const_1.FAM_CliExitCode.serverUnreachable : fam_cli_const_1.FAM_CliExitCode.operationError,
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
exports.FAM_Config_Util = FAM_Config_Util;
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.FAM_Doctor_Util = void 0;
|
|
4
|
+
const commander_1 = require("commander");
|
|
5
|
+
const fam_output_util_1 = require("../_collections/fam-output.util");
|
|
6
|
+
const fam_client_service_1 = require("../_services/fam-client.service");
|
|
7
|
+
const fam_cli_const_1 = require("../_collections/fam-cli.const");
|
|
8
|
+
/** A 6 doctor al-check ↔ capability-eszköz mátrix (dsgn-010 §5.2). */
|
|
9
|
+
const CHECK_MATRIX = [
|
|
10
|
+
{ name: 'env', capability: 'validate_environment', fixHint: 'Hiányzó env (pl. MONGODB_URI) → `fam init` vagy állítsd be a `.env`-ben.' },
|
|
11
|
+
{ name: 'mongodb', capability: 'test_mongodb_connection', fixHint: 'Mongo nem elérhető → indítsd a Mongo-t, ellenőrizd a portot / MONGODB_URI-t.' },
|
|
12
|
+
{ name: 'config', capability: 'get_config_status', fixHint: 'Nincs fam_config global rekord → `fam init` vagy `fam config set …`.' },
|
|
13
|
+
{ name: 'embedding', capability: 'test_embedding_provider', fixHint: 'OpenAI 401 → ellenőrizd OPENAI_API_KEY-t; LM Studio: indítsd a szervert + tölts be modellt.' },
|
|
14
|
+
{ name: 'vector', capability: 'test_vector_search', fixHint: 'Vektor-pool üres/nem-hidratált → `fam write … re-embed` vagy ellenőrizd a Mongo-persist réteget.' },
|
|
15
|
+
{ name: 'collections', capability: 'get_table_stats', fixHint: 'Hiányzó collection → indítsd a szervert egyszer (auto-create), majd `fam doctor`.' },
|
|
16
|
+
];
|
|
17
|
+
/**
|
|
18
|
+
* `fam doctor` — a setup/diag al-checkek aggregátora (dsgn-010 §5). Lefuttatja mind a 6 al-checket a
|
|
19
|
+
* dsgn-003 capability-diagnostics eszközökön át (`POST /api/capabilities {action:invoke}`), és minden
|
|
20
|
+
* FAIL/WARN mellé KONKRÉT fix-tippet ad — néma hiba TILOS (dsgn-008). Szerver hiányában a checkek
|
|
21
|
+
* `WARN`-ot adnak "szerver szükséges" tippel (az `env` is a server-capabilityn megy MVP1-ben).
|
|
22
|
+
*
|
|
23
|
+
* A 3 diagnosztikai setup-alias (`validate-env`/`test-db`/`test-embedding`) a `doctor` EGYETLEN
|
|
24
|
+
* al-checkjére delegál — nincs külön implementáció (dsgn-010 §10).
|
|
25
|
+
*/
|
|
26
|
+
class FAM_Doctor_Util {
|
|
27
|
+
/** A `doctor` parancs-deszkriptor (mind a 6 al-check). */
|
|
28
|
+
static command() {
|
|
29
|
+
const command = new commander_1.Command('doctor');
|
|
30
|
+
command
|
|
31
|
+
.description('Health-report: env/mongodb/config/embedding/vector/collections (dsgn-010 §5)')
|
|
32
|
+
.option('--fix-hints', 'fix-tipp minden FAIL/WARN mellé (default be)', true)
|
|
33
|
+
.option('--skip <check,...>', 'check-ek kihagyása (pl. embedding,vector)')
|
|
34
|
+
.action(async () => {
|
|
35
|
+
const globals = command.optsWithGlobals();
|
|
36
|
+
const skip = (command.opts().skip ?? '')
|
|
37
|
+
.split(',').map((entry) => entry.trim()).filter((entry) => entry.length > 0);
|
|
38
|
+
const names = CHECK_MATRIX.map((descriptor) => descriptor.name).filter((name) => !skip.includes(name));
|
|
39
|
+
fam_output_util_1.FAM_Output_Util.exit(await FAM_Doctor_Util.runChecks(globals, names));
|
|
40
|
+
});
|
|
41
|
+
return command;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Egy delegáló alias-parancs, ami a `doctor` EGYETLEN al-checkjére fut (dsgn-010 §2/§10). Nincs külön
|
|
45
|
+
* logika — ugyanazt a capability-invoke-ot hívja, mint a `doctor` az adott checkre.
|
|
46
|
+
*/
|
|
47
|
+
static aliasCommand(aliasName, checks) {
|
|
48
|
+
const descriptor = CHECK_MATRIX.find((entry) => entry.name === checks[0]);
|
|
49
|
+
const command = new commander_1.Command(aliasName);
|
|
50
|
+
command
|
|
51
|
+
.description(`(alias) a \`fam doctor\` '${checks.join(',')}' al-checkje`)
|
|
52
|
+
.action(async () => {
|
|
53
|
+
const globals = command.optsWithGlobals();
|
|
54
|
+
fam_output_util_1.FAM_Output_Util.exit(await FAM_Doctor_Util.runChecks(globals, descriptor ? checks : []));
|
|
55
|
+
});
|
|
56
|
+
return command;
|
|
57
|
+
}
|
|
58
|
+
/** A megadott al-checkek lefuttatása + aggregált health-report (exit 0 ha nincs FAIL, különben 1). */
|
|
59
|
+
static async runChecks(globals, names) {
|
|
60
|
+
const client = new fam_client_service_1.FAM_CliClient_Service(globals.serverUrl);
|
|
61
|
+
const reachable = await client.isReachable();
|
|
62
|
+
const checks = [];
|
|
63
|
+
for (const name of names) {
|
|
64
|
+
const descriptor = CHECK_MATRIX.find((entry) => entry.name === name);
|
|
65
|
+
if (!descriptor) {
|
|
66
|
+
continue;
|
|
67
|
+
}
|
|
68
|
+
checks.push(reachable
|
|
69
|
+
? await FAM_Doctor_Util.runCapabilityCheck(client, descriptor)
|
|
70
|
+
: FAM_Doctor_Util.serverlessWarn(descriptor, client.getBaseUrl()));
|
|
71
|
+
}
|
|
72
|
+
const summary = { ok: 0, warn: 0, fail: 0 };
|
|
73
|
+
for (const check of checks) {
|
|
74
|
+
summary[check.status] += 1;
|
|
75
|
+
}
|
|
76
|
+
const health = summary.fail ? 'fail' : summary.warn ? 'warn' : 'ok';
|
|
77
|
+
const exitCode = summary.fail ? fam_cli_const_1.FAM_CliExitCode.operationError : fam_cli_const_1.FAM_CliExitCode.ok;
|
|
78
|
+
fam_output_util_1.FAM_Output_Util.success({
|
|
79
|
+
options: globals,
|
|
80
|
+
command: 'doctor',
|
|
81
|
+
data: { health: health, checks: checks, summary: summary },
|
|
82
|
+
humanFormatter: () => FAM_Doctor_Util.formatHuman(checks, summary),
|
|
83
|
+
});
|
|
84
|
+
return exitCode;
|
|
85
|
+
}
|
|
86
|
+
/** Egy capability-invoke-on át futtatott check → `FAM_DoctorCheck`. */
|
|
87
|
+
static async runCapabilityCheck(client, descriptor) {
|
|
88
|
+
const result = await client.post('/api/capabilities', { action: 'invoke', name: descriptor.capability });
|
|
89
|
+
if (result.ok) {
|
|
90
|
+
return { name: descriptor.name, status: 'ok' };
|
|
91
|
+
}
|
|
92
|
+
// A late-bind eszközök (pl. MP-12) clear "pending MP-X" hibát adnak → WARN (nem FAIL, nem néma).
|
|
93
|
+
const isPending = (result.error?.message ?? '').toLowerCase().includes('pending');
|
|
94
|
+
return {
|
|
95
|
+
name: descriptor.name,
|
|
96
|
+
status: isPending ? 'warn' : 'fail',
|
|
97
|
+
detail: result.error?.message,
|
|
98
|
+
fixHint: descriptor.fixHint,
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
/** Szerver-hiányos WARN (a check a server-réteget igényli; dsgn-010 §5.3 kockázat). */
|
|
102
|
+
static serverlessWarn(descriptor, baseUrl) {
|
|
103
|
+
return {
|
|
104
|
+
name: descriptor.name,
|
|
105
|
+
status: 'warn',
|
|
106
|
+
detail: `A '${descriptor.name}' check a futó szervert igényli (${baseUrl} elérhetetlen).`,
|
|
107
|
+
fixHint: `Indítsd a szervert (\`fam start\`), vagy adj \`--server-url\`-t. (Default: ${fam_cli_const_1.FAM_DEFAULT_SERVER_URL})`,
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
/** Ember-olvasható health-banner (`✓`/`⚠`/`✗` soronként + záró Health). */
|
|
111
|
+
static formatHuman(checks, summary) {
|
|
112
|
+
const glyph = { ok: '✓', warn: '⚠', fail: '✗' };
|
|
113
|
+
const lines = [];
|
|
114
|
+
for (const check of checks) {
|
|
115
|
+
lines.push(`${glyph[check.status]} ${check.name}${check.detail ? ` — ${check.detail}` : ''}`);
|
|
116
|
+
if (check.status !== 'ok' && check.fixHint) {
|
|
117
|
+
lines.push(` → ${check.fixHint}`);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
lines.push(`\nHealth: ${summary.ok}/${checks.length} OK, ${summary.warn} WARN, ${summary.fail} FAIL`);
|
|
121
|
+
return lines.join('\n');
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
exports.FAM_Doctor_Util = FAM_Doctor_Util;
|