@remnic/core 9.3.687 → 9.3.688
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/dist/access-cli.js +3 -3
- package/dist/active-recall.js +3 -3
- package/dist/{chunk-MCQDSY4G.js → chunk-3K37VPM3.js} +2 -2
- package/dist/{chunk-6GJS4BFH.js → chunk-A7UZR6RA.js} +2 -2
- package/dist/{chunk-QVMXQGT7.js → chunk-CCWHPGT4.js} +4 -4
- package/dist/{chunk-U7D7NP4J.js → chunk-ED35D32I.js} +2 -2
- package/dist/chunk-K6MV3TRQ.js +56 -0
- package/dist/chunk-K6MV3TRQ.js.map +1 -0
- package/dist/{chunk-QO3AILZN.js → chunk-OO42R444.js} +2 -2
- package/dist/{chunk-FE6DQUNJ.js → chunk-RVYD6LR3.js} +2 -2
- package/dist/cli.js +6 -6
- package/dist/config.js +3 -3
- package/dist/connectors/index.d.ts +10 -2
- package/dist/connectors/index.js +2 -2
- package/dist/emit-legacy-tools.js +2 -2
- package/dist/index.d.ts +11 -0
- package/dist/index.js +10 -7
- package/dist/index.js.map +1 -1
- package/dist/operator-toolkit.js +4 -4
- package/dist/resume-bundles.js +4 -4
- package/package.json +2 -2
- package/src/connectors/paths.test.ts +192 -0
- package/src/connectors/paths.ts +106 -20
- package/src/memory-extension/claude-code-publisher.ts +1 -0
- package/src/memory-extension/codex-publisher.ts +1 -0
- package/src/memory-extension/hermes-publisher.ts +1 -0
- package/src/memory-extension/types.ts +11 -0
- package/dist/chunk-3BQOQYRB.js +0 -33
- package/dist/chunk-3BQOQYRB.js.map +0 -1
- /package/dist/{chunk-MCQDSY4G.js.map → chunk-3K37VPM3.js.map} +0 -0
- /package/dist/{chunk-6GJS4BFH.js.map → chunk-A7UZR6RA.js.map} +0 -0
- /package/dist/{chunk-QVMXQGT7.js.map → chunk-CCWHPGT4.js.map} +0 -0
- /package/dist/{chunk-U7D7NP4J.js.map → chunk-ED35D32I.js.map} +0 -0
- /package/dist/{chunk-QO3AILZN.js.map → chunk-OO42R444.js.map} +0 -0
- /package/dist/{chunk-FE6DQUNJ.js.map → chunk-RVYD6LR3.js.map} +0 -0
package/dist/operator-toolkit.js
CHANGED
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
summarizeMemoryWorthLegacyCounters,
|
|
12
12
|
summarizeObservationThroughput,
|
|
13
13
|
summarizeTierDistribution
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-RVYD6LR3.js";
|
|
15
15
|
import "./chunk-2SJCWLQD.js";
|
|
16
16
|
import "./chunk-7XH7VJN4.js";
|
|
17
17
|
import "./chunk-YBPYIAA5.js";
|
|
@@ -21,11 +21,11 @@ import "./chunk-CMTINOFS.js";
|
|
|
21
21
|
import "./chunk-BVKCV2ZY.js";
|
|
22
22
|
import "./chunk-ZCWIH4LH.js";
|
|
23
23
|
import "./chunk-3PY7VHV7.js";
|
|
24
|
-
import "./chunk-
|
|
24
|
+
import "./chunk-A7UZR6RA.js";
|
|
25
25
|
import "./chunk-NDAH7BJ5.js";
|
|
26
26
|
import "./chunk-Z5LAYHGJ.js";
|
|
27
|
-
import "./chunk-
|
|
28
|
-
import "./chunk-
|
|
27
|
+
import "./chunk-OO42R444.js";
|
|
28
|
+
import "./chunk-K6MV3TRQ.js";
|
|
29
29
|
import "./chunk-4N3TFFPH.js";
|
|
30
30
|
import "./chunk-CTOQEZSN.js";
|
|
31
31
|
import "./chunk-2KAYTPPT.js";
|
package/dist/resume-bundles.js
CHANGED
|
@@ -4,17 +4,17 @@ import {
|
|
|
4
4
|
recordResumeBundle,
|
|
5
5
|
resolveResumeBundleDir,
|
|
6
6
|
validateResumeBundle
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-3K37VPM3.js";
|
|
8
8
|
import "./chunk-ZRWB5D4H.js";
|
|
9
9
|
import "./chunk-PONNZ54D.js";
|
|
10
10
|
import "./chunk-S4DDLTPX.js";
|
|
11
11
|
import "./chunk-KFY3SGN7.js";
|
|
12
12
|
import "./chunk-LMDRGRJ2.js";
|
|
13
|
-
import "./chunk-
|
|
13
|
+
import "./chunk-A7UZR6RA.js";
|
|
14
14
|
import "./chunk-NDAH7BJ5.js";
|
|
15
15
|
import "./chunk-Z5LAYHGJ.js";
|
|
16
|
-
import "./chunk-
|
|
17
|
-
import "./chunk-
|
|
16
|
+
import "./chunk-OO42R444.js";
|
|
17
|
+
import "./chunk-K6MV3TRQ.js";
|
|
18
18
|
import "./chunk-FF4KLI5W.js";
|
|
19
19
|
import "./chunk-6HMYUWXR.js";
|
|
20
20
|
import "./chunk-ZPQVJEVQ.js";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@remnic/core",
|
|
3
|
-
"version": "9.3.
|
|
3
|
+
"version": "9.3.688",
|
|
4
4
|
"description": "Framework-agnostic Remnic memory engine — orchestrator, storage, extraction, search, trust zones",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -2931,7 +2931,7 @@
|
|
|
2931
2931
|
"core"
|
|
2932
2932
|
],
|
|
2933
2933
|
"peerDependencies": {
|
|
2934
|
-
"@remnic/coding-graph": "^9.3.
|
|
2934
|
+
"@remnic/coding-graph": "^9.3.688"
|
|
2935
2935
|
},
|
|
2936
2936
|
"peerDependenciesMeta": {
|
|
2937
2937
|
"@remnic/coding-graph": {
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import fs from "node:fs";
|
|
3
|
+
import os from "node:os";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
import test from "node:test";
|
|
6
|
+
|
|
7
|
+
import {
|
|
8
|
+
getConnectorsConfigRoot,
|
|
9
|
+
getLegacyConnectorsConfigRoot,
|
|
10
|
+
getActiveConnectorsConfigRoot,
|
|
11
|
+
getRegistryPath,
|
|
12
|
+
getConnectorsDir,
|
|
13
|
+
hasLegacyConnectorEntries,
|
|
14
|
+
REGISTRY_DIR_NAME,
|
|
15
|
+
LEGACY_REGISTRY_DIR_NAME,
|
|
16
|
+
} from "./paths.js";
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Issue #1518 — the connector registry path moved from
|
|
20
|
+
* `~/.config/engram/.engram-connectors/` to `~/.config/remnic/.remnic-connectors/`,
|
|
21
|
+
* with a read-fallback so existing engram-era installs keep resolving until
|
|
22
|
+
* the user migrates. These tests lock in that contract.
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
function withXdgHome<T>(body: (xdg: string) => T): T {
|
|
26
|
+
const xdg = fs.mkdtempSync(path.join(os.tmpdir(), "remnic-paths-test-"));
|
|
27
|
+
const prev = process.env.XDG_CONFIG_HOME;
|
|
28
|
+
process.env.XDG_CONFIG_HOME = xdg;
|
|
29
|
+
try {
|
|
30
|
+
return body(xdg);
|
|
31
|
+
} finally {
|
|
32
|
+
if (prev === undefined) delete process.env.XDG_CONFIG_HOME;
|
|
33
|
+
else process.env.XDG_CONFIG_HOME = prev;
|
|
34
|
+
fs.rmSync(xdg, { recursive: true, force: true });
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
test("getConnectorsConfigRoot: canonical root is remnic/, not engram/ (#1518)", () => {
|
|
39
|
+
withXdgHome((xdg) => {
|
|
40
|
+
const root = getConnectorsConfigRoot();
|
|
41
|
+
assert.equal(root, path.join(xdg, "remnic"));
|
|
42
|
+
assert.notEqual(root, path.join(xdg, "engram"));
|
|
43
|
+
});
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
test("getLegacyConnectorsConfigRoot: legacy root is still engram/ (read-fallback)", () => {
|
|
47
|
+
withXdgHome((xdg) => {
|
|
48
|
+
assert.equal(getLegacyConnectorsConfigRoot(), path.join(xdg, "engram"));
|
|
49
|
+
});
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
test("REGISTRY_DIR_NAME: canonical subdir is .remnic-connectors", () => {
|
|
53
|
+
assert.equal(REGISTRY_DIR_NAME, ".remnic-connectors");
|
|
54
|
+
assert.equal(LEGACY_REGISTRY_DIR_NAME, ".engram-connectors");
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
test("getConnectorsDir: fresh install writes to remnic/.remnic-connectors/connectors", () => {
|
|
58
|
+
withXdgHome((xdg) => {
|
|
59
|
+
// Neither remnic nor engram exists → canonical remnic wins.
|
|
60
|
+
const dir = getConnectorsDir();
|
|
61
|
+
assert.equal(
|
|
62
|
+
dir,
|
|
63
|
+
path.join(xdg, "remnic", ".remnic-connectors", "connectors"),
|
|
64
|
+
"fresh install must resolve to the canonical remnic path",
|
|
65
|
+
);
|
|
66
|
+
});
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
test("getRegistryPath: fresh install writes registry.json under remnic/.remnic-connectors", () => {
|
|
70
|
+
withXdgHome((xdg) => {
|
|
71
|
+
const reg = getRegistryPath();
|
|
72
|
+
assert.equal(
|
|
73
|
+
reg,
|
|
74
|
+
path.join(xdg, "remnic", ".remnic-connectors", "registry.json"),
|
|
75
|
+
);
|
|
76
|
+
});
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
test("read-fallback: when ONLY engram/ exists, active root resolves to engram (#1518 back-compat)", () => {
|
|
80
|
+
withXdgHome((xdg) => {
|
|
81
|
+
// Seed the legacy engram tree — no remnic dir.
|
|
82
|
+
fs.mkdirSync(path.join(xdg, "engram", ".engram-connectors", "connectors"), {
|
|
83
|
+
recursive: true,
|
|
84
|
+
});
|
|
85
|
+
assert.equal(getActiveConnectorsConfigRoot(), path.join(xdg, "engram"));
|
|
86
|
+
assert.equal(
|
|
87
|
+
getConnectorsDir(),
|
|
88
|
+
path.join(xdg, "engram", ".engram-connectors", "connectors"),
|
|
89
|
+
);
|
|
90
|
+
assert.equal(
|
|
91
|
+
getRegistryPath(),
|
|
92
|
+
path.join(xdg, "engram", ".engram-connectors", "registry.json"),
|
|
93
|
+
);
|
|
94
|
+
});
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
test("read-fallback: once remnic/ exists, it wins over engram (post-migration)", () => {
|
|
98
|
+
withXdgHome((xdg) => {
|
|
99
|
+
// Seed BOTH trees — the user has started migrating.
|
|
100
|
+
fs.mkdirSync(path.join(xdg, "engram", ".engram-connectors", "connectors"), {
|
|
101
|
+
recursive: true,
|
|
102
|
+
});
|
|
103
|
+
fs.mkdirSync(path.join(xdg, "remnic", ".remnic-connectors", "connectors"), {
|
|
104
|
+
recursive: true,
|
|
105
|
+
});
|
|
106
|
+
assert.equal(getActiveConnectorsConfigRoot(), path.join(xdg, "remnic"));
|
|
107
|
+
assert.equal(
|
|
108
|
+
getConnectorsDir(),
|
|
109
|
+
path.join(xdg, "remnic", ".remnic-connectors", "connectors"),
|
|
110
|
+
);
|
|
111
|
+
});
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
test("read-fallback: a bare config-root dir without its registry subdir does NOT trigger fallback (#1620 round 1)", () => {
|
|
115
|
+
withXdgHome((xdg) => {
|
|
116
|
+
// A stray engram/ dir (no .engram-connectors inside) is NOT evidence of a
|
|
117
|
+
// connector install. The probe targets the registry subdir, so this falls
|
|
118
|
+
// through to the canonical remnic root.
|
|
119
|
+
fs.mkdirSync(path.join(xdg, "engram"), { recursive: true });
|
|
120
|
+
assert.equal(
|
|
121
|
+
getActiveConnectorsConfigRoot(),
|
|
122
|
+
path.join(xdg, "remnic"),
|
|
123
|
+
"bare engram/ without .engram-connectors must not trigger the legacy fallback",
|
|
124
|
+
);
|
|
125
|
+
});
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
test("read-fallback: stray remnic/config.json must not hide legacy engram connector data (#1620 round 1 regression)", () => {
|
|
129
|
+
// The cursor-reported bug: the daemon creates ~/.config/remnic/config.json
|
|
130
|
+
// for its own setup, so the bare remnic/ config root exists on a machine
|
|
131
|
+
// that has NEVER installed a connector under remnic. The active root must
|
|
132
|
+
// still resolve to engram when connector data lives there, otherwise
|
|
133
|
+
// loadRegistry would read an empty remnic tree and legacy installs would
|
|
134
|
+
// look uninstalled.
|
|
135
|
+
withXdgHome((xdg) => {
|
|
136
|
+
// Daemon setup created remnic/config.json (no .remnic-connectors).
|
|
137
|
+
fs.mkdirSync(path.join(xdg, "remnic"), { recursive: true });
|
|
138
|
+
fs.writeFileSync(path.join(xdg, "remnic", "config.json"), "{}\n");
|
|
139
|
+
// Real connector data still lives under the legacy engram tree.
|
|
140
|
+
fs.mkdirSync(path.join(xdg, "engram", ".engram-connectors", "connectors"), {
|
|
141
|
+
recursive: true,
|
|
142
|
+
});
|
|
143
|
+
assert.equal(getActiveConnectorsConfigRoot(), path.join(xdg, "engram"));
|
|
144
|
+
assert.equal(
|
|
145
|
+
getConnectorsDir(),
|
|
146
|
+
path.join(xdg, "engram", ".engram-connectors", "connectors"),
|
|
147
|
+
);
|
|
148
|
+
});
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
test("hasLegacyConnectorEntries: fresh canonical install is NOT legacy evidence (#1620 review)", () => {
|
|
152
|
+
// The codex P2 concern: a fresh post-rename install writes its first
|
|
153
|
+
// connector under remnic/.remnic-connectors/. That must NOT flip
|
|
154
|
+
// resolveEmitLegacyTools, because the user never had engram.* aliases.
|
|
155
|
+
withXdgHome((xdg) => {
|
|
156
|
+
fs.mkdirSync(
|
|
157
|
+
path.join(xdg, "remnic", ".remnic-connectors", "connectors"),
|
|
158
|
+
{ recursive: true },
|
|
159
|
+
);
|
|
160
|
+
fs.writeFileSync(
|
|
161
|
+
path.join(xdg, "remnic", ".remnic-connectors", "connectors", "claude-code.json"),
|
|
162
|
+
"{}\n",
|
|
163
|
+
);
|
|
164
|
+
assert.equal(
|
|
165
|
+
hasLegacyConnectorEntries(),
|
|
166
|
+
false,
|
|
167
|
+
"canonical remnic/ connector entries are not legacy evidence",
|
|
168
|
+
);
|
|
169
|
+
});
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
test("hasLegacyConnectorEntries: legacy engram entries ARE sticky-legacy evidence (#1550)", () => {
|
|
173
|
+
// An unmigrated install with connector data under engram/.engram-connectors
|
|
174
|
+
// must still report legacy evidence so its clients keep seeing engram_* aliases.
|
|
175
|
+
withXdgHome((xdg) => {
|
|
176
|
+
fs.mkdirSync(
|
|
177
|
+
path.join(xdg, "engram", ".engram-connectors", "connectors"),
|
|
178
|
+
{ recursive: true },
|
|
179
|
+
);
|
|
180
|
+
fs.writeFileSync(
|
|
181
|
+
path.join(xdg, "engram", ".engram-connectors", "connectors", "claude-code.json"),
|
|
182
|
+
"{}\n",
|
|
183
|
+
);
|
|
184
|
+
assert.equal(hasLegacyConnectorEntries(), true);
|
|
185
|
+
});
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
test("hasLegacyConnectorEntries: missing legacy dir is not legacy evidence (fresh install)", () => {
|
|
189
|
+
withXdgHome(() => {
|
|
190
|
+
assert.equal(hasLegacyConnectorEntries(), false);
|
|
191
|
+
});
|
|
192
|
+
});
|
package/src/connectors/paths.ts
CHANGED
|
@@ -4,46 +4,132 @@ import path from "node:path";
|
|
|
4
4
|
import { readEnvVar, resolveHomeDir } from "../runtime/env.js";
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
|
-
* Connector registry directory name. Kept under the
|
|
8
|
-
* root for
|
|
9
|
-
*
|
|
7
|
+
* Connector registry directory name. Kept under the canonical `remnic` config
|
|
8
|
+
* root for new installs; legacy installs that still live under `engram` are
|
|
9
|
+
* read-transparent via {@link getActiveConnectorsConfigRoot} (issue #1518).
|
|
10
10
|
*/
|
|
11
|
-
export const REGISTRY_DIR_NAME = ".
|
|
11
|
+
export const REGISTRY_DIR_NAME = ".remnic-connectors";
|
|
12
12
|
|
|
13
13
|
/**
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
|
|
17
|
-
|
|
14
|
+
* Legacy registry directory name from the engram era. Used only for the
|
|
15
|
+
* read-fallback so existing installs keep resolving until the user migrates.
|
|
16
|
+
*/
|
|
17
|
+
export const LEGACY_REGISTRY_DIR_NAME = ".engram-connectors";
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Config-root segment for the canonical (post-rename) layout. Issue #1518
|
|
21
|
+
* point 6: the path `~/.config/engram/...` is confusing when the product is
|
|
22
|
+
* called Remnic, so new writes land under `remnic/`.
|
|
23
|
+
*/
|
|
24
|
+
const CONFIG_ROOT_SEGMENT = "remnic";
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Config-root segment for the legacy engram-era layout. Read-fallback only.
|
|
28
|
+
*/
|
|
29
|
+
const LEGACY_CONFIG_ROOT_SEGMENT = "engram";
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Single source of truth for the canonical connectors config root
|
|
33
|
+
* (`$XDG_CONFIG_HOME/remnic` or `~/.config/remnic`). New writes ALWAYS go
|
|
34
|
+
* here. Issue #1527 flagged this derivation as previously duplicated across
|
|
35
|
+
* call sites — add new callers here, never re-derive the path inline.
|
|
18
36
|
*/
|
|
19
37
|
export function getConnectorsConfigRoot(): string {
|
|
20
38
|
const xdgConfigHome = readEnvVar("XDG_CONFIG_HOME");
|
|
21
39
|
return xdgConfigHome
|
|
22
|
-
? path.join(xdgConfigHome,
|
|
23
|
-
: path.join(resolveHomeDir(), ".config",
|
|
40
|
+
? path.join(xdgConfigHome, CONFIG_ROOT_SEGMENT)
|
|
41
|
+
: path.join(resolveHomeDir(), ".config", CONFIG_ROOT_SEGMENT);
|
|
24
42
|
}
|
|
25
43
|
|
|
26
|
-
/**
|
|
44
|
+
/**
|
|
45
|
+
* Legacy config root from the engram era (`$XDG_CONFIG_HOME/engram` or
|
|
46
|
+
* `~/.config/engram`). Exposed for tests and the migration path only —
|
|
47
|
+
* production code should call {@link getActiveConnectorsConfigRoot} so the
|
|
48
|
+
* read-fallback is applied uniformly.
|
|
49
|
+
*/
|
|
50
|
+
export function getLegacyConnectorsConfigRoot(): string {
|
|
51
|
+
const xdgConfigHome = readEnvVar("XDG_CONFIG_HOME");
|
|
52
|
+
return xdgConfigHome
|
|
53
|
+
? path.join(xdgConfigHome, LEGACY_CONFIG_ROOT_SEGMENT)
|
|
54
|
+
: path.join(resolveHomeDir(), ".config", LEGACY_CONFIG_ROOT_SEGMENT);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Read-time fallback: pick the config root that actually holds (or will hold)
|
|
59
|
+
* the connector registry.
|
|
60
|
+
*
|
|
61
|
+
* 1. Canonical `remnic/` root when its `.remnic-connectors` registry dir
|
|
62
|
+
* already exists (post-migration, or a fresh install that has already
|
|
63
|
+
* written its first connector).
|
|
64
|
+
* 2. Legacy `engram/` root when ONLY its `.engram-connectors` registry dir
|
|
65
|
+
* exists — an existing install we keep reading in place until the user
|
|
66
|
+
* runs `remnic migrate`.
|
|
67
|
+
* 3. Canonical `remnic/` root otherwise (fresh install with no registry on
|
|
68
|
+
* disk yet) so the first write lands at the new path.
|
|
69
|
+
*
|
|
70
|
+
* The probe looks for the REGISTRY SUBDIR (`.remnic-connectors` /
|
|
71
|
+
* `.engram-connectors`), not the bare config root. The config root
|
|
72
|
+
* `~/.config/remnic/` is created by unrelated daemon setup (e.g. the daemon's
|
|
73
|
+
* own `config.json`), so probing the bare root would falsely resolve to
|
|
74
|
+
* remnic and hide connector data that still lives under
|
|
75
|
+
* `~/.config/engram/.engram-connectors/` (cursor review round 1, #1620).
|
|
76
|
+
*
|
|
77
|
+
* This is a READ-time fallback. Writes go to whichever root this returns, so
|
|
78
|
+
* a legacy install keeps its data colocated for the active session; a fresh
|
|
79
|
+
* install writes straight to `remnic/`.
|
|
80
|
+
*/
|
|
81
|
+
export function getActiveConnectorsConfigRoot(): string {
|
|
82
|
+
const canonical = getConnectorsConfigRoot();
|
|
83
|
+
if (fs.existsSync(path.join(canonical, REGISTRY_DIR_NAME))) return canonical;
|
|
84
|
+
const legacy = getLegacyConnectorsConfigRoot();
|
|
85
|
+
if (fs.existsSync(path.join(legacy, LEGACY_REGISTRY_DIR_NAME))) return legacy;
|
|
86
|
+
return canonical;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Path of the connector registry manifest file. The registry subdir name
|
|
91
|
+
* (`.remnic-connectors` vs the legacy `.engram-connectors`) is chosen from the
|
|
92
|
+
* active root so a pre-rename install reads its existing files without a
|
|
93
|
+
* rename-side migration step (#1518).
|
|
94
|
+
*/
|
|
27
95
|
export function getRegistryPath(): string {
|
|
28
|
-
|
|
96
|
+
const root = getActiveConnectorsConfigRoot();
|
|
97
|
+
const dirName = root === getConnectorsConfigRoot() ? REGISTRY_DIR_NAME : LEGACY_REGISTRY_DIR_NAME;
|
|
98
|
+
return path.join(root, dirName, "registry.json");
|
|
29
99
|
}
|
|
30
100
|
|
|
31
|
-
/**
|
|
101
|
+
/**
|
|
102
|
+
* Directory holding one `<connector-id>.json` per installed connector. The
|
|
103
|
+
* registry subdir name follows the active root (see {@link getRegistryPath}).
|
|
104
|
+
*/
|
|
32
105
|
export function getConnectorsDir(): string {
|
|
33
|
-
|
|
106
|
+
const root = getActiveConnectorsConfigRoot();
|
|
107
|
+
const dirName = root === getConnectorsConfigRoot() ? REGISTRY_DIR_NAME : LEGACY_REGISTRY_DIR_NAME;
|
|
108
|
+
return path.join(root, dirName, "connectors");
|
|
34
109
|
}
|
|
35
110
|
|
|
36
111
|
/**
|
|
37
112
|
* Sticky-legacy evidence for `emitLegacyTools` (issue #1550): any persisted
|
|
38
|
-
* connector entry under the
|
|
39
|
-
*
|
|
40
|
-
*
|
|
113
|
+
* connector entry under the LEGACY engram registry means an existing install
|
|
114
|
+
* whose clients may still address engram_* aliases. Missing or unreadable
|
|
115
|
+
* legacy dir means fresh install — no evidence, no aliases.
|
|
116
|
+
*
|
|
117
|
+
* Probes ONLY the legacy engram registry (`$XDG_CONFIG_HOME/engram/.engram-connectors`),
|
|
118
|
+
* never the active/canonical root. A fresh post-rename install that just
|
|
119
|
+
* wrote its first connector under `remnic/.remnic-connectors/` is NOT legacy
|
|
120
|
+
* evidence — counting it would flip `resolveEmitLegacyTools` to true and
|
|
121
|
+
* advertise deprecated `engram.*` aliases to users who never had them
|
|
122
|
+
* (#1620 review, codex P2). An unmigrated install still reports its entries
|
|
123
|
+
* here because its data lives under the engram tree.
|
|
41
124
|
*/
|
|
42
125
|
export function hasLegacyConnectorEntries(): boolean {
|
|
43
126
|
try {
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
127
|
+
const legacyDir = path.join(
|
|
128
|
+
getLegacyConnectorsConfigRoot(),
|
|
129
|
+
LEGACY_REGISTRY_DIR_NAME,
|
|
130
|
+
"connectors",
|
|
131
|
+
);
|
|
132
|
+
return fs.readdirSync(legacyDir).some((name) => name.endsWith(".json"));
|
|
47
133
|
} catch {
|
|
48
134
|
return false;
|
|
49
135
|
}
|
|
@@ -17,6 +17,7 @@ export class ClaudeCodeMemoryExtensionPublisher implements MemoryExtensionPublis
|
|
|
17
17
|
readonly hostId = "claude-code";
|
|
18
18
|
|
|
19
19
|
static readonly capabilities: PublisherCapabilities = {
|
|
20
|
+
isStub: true,
|
|
20
21
|
instructionsMd: false,
|
|
21
22
|
skillsFolder: false,
|
|
22
23
|
citationFormat: false,
|
|
@@ -53,6 +53,7 @@ export class CodexMemoryExtensionPublisher implements MemoryExtensionPublisher {
|
|
|
53
53
|
readonly hostId = "codex";
|
|
54
54
|
|
|
55
55
|
static readonly capabilities: PublisherCapabilities = {
|
|
56
|
+
isStub: false,
|
|
56
57
|
instructionsMd: true,
|
|
57
58
|
skillsFolder: false,
|
|
58
59
|
citationFormat: true,
|
|
@@ -17,6 +17,7 @@ export class HermesMemoryExtensionPublisher implements MemoryExtensionPublisher
|
|
|
17
17
|
readonly hostId = "hermes";
|
|
18
18
|
|
|
19
19
|
static readonly capabilities: PublisherCapabilities = {
|
|
20
|
+
isStub: true,
|
|
20
21
|
instructionsMd: false,
|
|
21
22
|
skillsFolder: false,
|
|
22
23
|
citationFormat: false,
|
|
@@ -73,8 +73,19 @@ export interface PublishResult {
|
|
|
73
73
|
* Declarative capability flags that describe what a given publisher
|
|
74
74
|
* can produce. Useful for feature-gating UI or doctor output without
|
|
75
75
|
* instantiating the publisher.
|
|
76
|
+
*
|
|
77
|
+
* `isStub` is the explicit declaration required by #1518: when true, the
|
|
78
|
+
* docs-code parity gate (`scripts/check-docs-parity.mjs`) refuses any
|
|
79
|
+
* automation claim ("installs the plugin", "configures mcp",
|
|
80
|
+
* "automatically …") in the publisher's mapped install docs, because a stub
|
|
81
|
+
* publisher writes nothing to disk. A publisher that implements any real
|
|
82
|
+
* artefact writes MUST set this false. The inferred "all flags false ⇒ stub"
|
|
83
|
+
* detection in the parity script remains as a backstop, but the explicit
|
|
84
|
+
* flag is now the source of truth.
|
|
76
85
|
*/
|
|
77
86
|
export interface PublisherCapabilities {
|
|
87
|
+
/** Whether the publisher is an intentional no-op stub (writes nothing). */
|
|
88
|
+
readonly isStub: boolean;
|
|
78
89
|
/** Whether the publisher writes an instructions.md file. */
|
|
79
90
|
readonly instructionsMd: boolean;
|
|
80
91
|
/** Whether the publisher populates a skills folder. */
|
package/dist/chunk-3BQOQYRB.js
DELETED
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
readEnvVar,
|
|
3
|
-
resolveHomeDir
|
|
4
|
-
} from "./chunk-JUC24CTX.js";
|
|
5
|
-
|
|
6
|
-
// src/connectors/paths.ts
|
|
7
|
-
import fs from "fs";
|
|
8
|
-
import path from "path";
|
|
9
|
-
var REGISTRY_DIR_NAME = ".engram-connectors";
|
|
10
|
-
function getConnectorsConfigRoot() {
|
|
11
|
-
const xdgConfigHome = readEnvVar("XDG_CONFIG_HOME");
|
|
12
|
-
return xdgConfigHome ? path.join(xdgConfigHome, "engram") : path.join(resolveHomeDir(), ".config", "engram");
|
|
13
|
-
}
|
|
14
|
-
function getRegistryPath() {
|
|
15
|
-
return path.join(getConnectorsConfigRoot(), REGISTRY_DIR_NAME, "registry.json");
|
|
16
|
-
}
|
|
17
|
-
function getConnectorsDir() {
|
|
18
|
-
return path.join(getConnectorsConfigRoot(), REGISTRY_DIR_NAME, "connectors");
|
|
19
|
-
}
|
|
20
|
-
function hasLegacyConnectorEntries() {
|
|
21
|
-
try {
|
|
22
|
-
return fs.readdirSync(getConnectorsDir()).some((name) => name.endsWith(".json"));
|
|
23
|
-
} catch {
|
|
24
|
-
return false;
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
export {
|
|
29
|
-
getRegistryPath,
|
|
30
|
-
getConnectorsDir,
|
|
31
|
-
hasLegacyConnectorEntries
|
|
32
|
-
};
|
|
33
|
-
//# sourceMappingURL=chunk-3BQOQYRB.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/connectors/paths.ts"],"sourcesContent":["import fs from \"node:fs\";\nimport path from \"node:path\";\n\nimport { readEnvVar, resolveHomeDir } from \"../runtime/env.js\";\n\n/**\n * Connector registry directory name. Kept under the legacy `engram` config\n * root for backward compatibility with existing installs; the rename to a\n * `remnic` path (with a legacy read-fallback) is tracked in #1518.\n */\nexport const REGISTRY_DIR_NAME = \".engram-connectors\";\n\n/**\n * Single source of truth for the connectors config root\n * (`$XDG_CONFIG_HOME/engram` or `~/.config/engram`). Issue #1527 flagged this\n * derivation as previously duplicated across call sites — add new callers\n * here, never re-derive the path inline.\n */\nexport function getConnectorsConfigRoot(): string {\n const xdgConfigHome = readEnvVar(\"XDG_CONFIG_HOME\");\n return xdgConfigHome\n ? path.join(xdgConfigHome, \"engram\")\n : path.join(resolveHomeDir(), \".config\", \"engram\");\n}\n\n/** Path of the connector registry manifest file. */\nexport function getRegistryPath(): string {\n return path.join(getConnectorsConfigRoot(), REGISTRY_DIR_NAME, \"registry.json\");\n}\n\n/** Directory holding one `<connector-id>.json` per installed connector. */\nexport function getConnectorsDir(): string {\n return path.join(getConnectorsConfigRoot(), REGISTRY_DIR_NAME, \"connectors\");\n}\n\n/**\n * Sticky-legacy evidence for `emitLegacyTools` (issue #1550): any persisted\n * connector entry under the legacy engram connectors dir means an existing\n * install whose clients may still address engram_* aliases. Missing or\n * unreadable dir means fresh install — no evidence, no aliases.\n */\nexport function hasLegacyConnectorEntries(): boolean {\n try {\n return fs\n .readdirSync(getConnectorsDir())\n .some((name) => name.endsWith(\".json\"));\n } catch {\n return false;\n }\n}\n"],"mappings":";;;;;;AAAA,OAAO,QAAQ;AACf,OAAO,UAAU;AASV,IAAM,oBAAoB;AAQ1B,SAAS,0BAAkC;AAChD,QAAM,gBAAgB,WAAW,iBAAiB;AAClD,SAAO,gBACH,KAAK,KAAK,eAAe,QAAQ,IACjC,KAAK,KAAK,eAAe,GAAG,WAAW,QAAQ;AACrD;AAGO,SAAS,kBAA0B;AACxC,SAAO,KAAK,KAAK,wBAAwB,GAAG,mBAAmB,eAAe;AAChF;AAGO,SAAS,mBAA2B;AACzC,SAAO,KAAK,KAAK,wBAAwB,GAAG,mBAAmB,YAAY;AAC7E;AAQO,SAAS,4BAAqC;AACnD,MAAI;AACF,WAAO,GACJ,YAAY,iBAAiB,CAAC,EAC9B,KAAK,CAAC,SAAS,KAAK,SAAS,OAAO,CAAC;AAAA,EAC1C,QAAQ;AACN,WAAO;AAAA,EACT;AACF;","names":[]}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|