@felan-ai/ext-codebase-memory 0.0.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/LICENSE +21 -0
- package/NOTICE +16 -0
- package/README.md +81 -0
- package/dist/cache.d.ts +13 -0
- package/dist/cache.d.ts.map +1 -0
- package/dist/cache.js +97 -0
- package/dist/cache.js.map +1 -0
- package/dist/client.d.ts +35 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +108 -0
- package/dist/client.js.map +1 -0
- package/dist/config.d.ts +4 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +15 -0
- package/dist/config.js.map +1 -0
- package/dist/grep-augmentation.d.ts +6 -0
- package/dist/grep-augmentation.d.ts.map +1 -0
- package/dist/grep-augmentation.js +103 -0
- package/dist/grep-augmentation.js.map +1 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +102 -0
- package/dist/index.js.map +1 -0
- package/dist/installer.d.ts +4 -0
- package/dist/installer.d.ts.map +1 -0
- package/dist/installer.js +50 -0
- package/dist/installer.js.map +1 -0
- package/dist/runtime-path.d.ts +3 -0
- package/dist/runtime-path.d.ts.map +1 -0
- package/dist/runtime-path.js +10 -0
- package/dist/runtime-path.js.map +1 -0
- package/dist/services.d.ts +21 -0
- package/dist/services.d.ts.map +1 -0
- package/dist/services.js +179 -0
- package/dist/services.js.map +1 -0
- package/dist/tools.d.ts +5 -0
- package/dist/tools.d.ts.map +1 -0
- package/dist/tools.js +98 -0
- package/dist/tools.js.map +1 -0
- package/package.json +45 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Felan contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, 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/NOTICE
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
@felan-ai/ext-codebase-memory
|
|
2
|
+
|
|
3
|
+
This package adapts selected MIT-licensed behavior and prompt guidance from
|
|
4
|
+
pi-cbm 1.2.1 at commit 921a749d5cea74bda8f647542627ef9518fec272
|
|
5
|
+
(https://github.com/alexykn/pi-cbm). Copyright (c) 2026 alexykn.
|
|
6
|
+
|
|
7
|
+
The runtime integration targets codebase-memory-mcp 0.10.8 at commit
|
|
8
|
+
46ae198fc11cda80e817acbc5f5908d7c2de7032
|
|
9
|
+
(https://github.com/DeusData/codebase-memory-mcp), licensed under MIT.
|
|
10
|
+
|
|
11
|
+
This package uses TypeBox 1.1.38 from https://github.com/sinclairzx81/typebox,
|
|
12
|
+
licensed under the MIT License. Copyright (c) 2017-2026 Haydn Paterson.
|
|
13
|
+
|
|
14
|
+
Felan's portable AgentRuntime implementation, binary gating, explicit installer,
|
|
15
|
+
bounded grep augmentation, cache policy, and four-tool model surface are Felan
|
|
16
|
+
changes. The optional binary is never bundled with this npm package.
|
package/README.md
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
# @felan-ai/ext-codebase-memory
|
|
2
|
+
|
|
3
|
+
Portable structural code exploration for Felan, backed by the reviewed
|
|
4
|
+
`codebase-memory-mcp` 0.10.8 native executable.
|
|
5
|
+
|
|
6
|
+
## Behavior
|
|
7
|
+
|
|
8
|
+
When the exact reviewed binary is available, the extension registers exactly
|
|
9
|
+
four model tools:
|
|
10
|
+
|
|
11
|
+
- `codebase_memory` proxies the bounded structural query surface and performs
|
|
12
|
+
an explicit `index_repository` refresh for the active git repository.
|
|
13
|
+
- `read_symbol` resolves and reads one named symbol.
|
|
14
|
+
- `search_and_read_symbols` searches symbols and reads a bounded set of likely
|
|
15
|
+
matches.
|
|
16
|
+
- `search_code` searches indexed source text.
|
|
17
|
+
|
|
18
|
+
The extension indexes once at session startup. It has no file watcher or
|
|
19
|
+
periodic refresh. After edits, the model can call
|
|
20
|
+
`codebase_memory({ command: "index_repository" })`, and local users can run
|
|
21
|
+
`/codebase-memory refresh`. Direct file reads, grep, compiler output, and tests
|
|
22
|
+
remain authoritative because an index can be stale.
|
|
23
|
+
|
|
24
|
+
Grep and ripgrep calls made through `bash` or Codex `exec_command` receive a
|
|
25
|
+
best-effort Codebase Memory appendix by default. Augmentation has its own
|
|
26
|
+
1.5-second deadline, never replaces the original command result, and emits
|
|
27
|
+
hit/error telemetry only through a host-supplied callback.
|
|
28
|
+
|
|
29
|
+
## Availability and installation
|
|
30
|
+
|
|
31
|
+
The package never bundles or installs a binary automatically. If the binary is
|
|
32
|
+
missing, it registers no tools, capability instructions, or model prompt. A
|
|
33
|
+
local interactive session shows one installation hint; a cloud host receives a
|
|
34
|
+
hard error log while session startup continues without Codebase Memory.
|
|
35
|
+
|
|
36
|
+
Local installation is always explicit through `/dependencies` or
|
|
37
|
+
`/codebase-memory install`. Felan downloads a commit-pinned upstream installer,
|
|
38
|
+
verifies its SHA-256 digest, requests the pinned 0.10.8 release, passes
|
|
39
|
+
`--skip-config`, and installs only into `AgentRuntime.storage('agent')`. It
|
|
40
|
+
never edits agent or repository configuration. Cloud hosts must place the exact
|
|
41
|
+
reviewed binary on `PATH` in the execution image.
|
|
42
|
+
|
|
43
|
+
## Cache and limits
|
|
44
|
+
|
|
45
|
+
Codebase Memory data is rooted at
|
|
46
|
+
`AgentRuntime.storage('agent')/codebase-memory/cache`, so root sessions and
|
|
47
|
+
subagents using the same runtime coordinate through one index. No tenant key is
|
|
48
|
+
added inside that already scoped runtime storage.
|
|
49
|
+
|
|
50
|
+
- Query timeout: 60 seconds
|
|
51
|
+
- Index timeout: 20 minutes
|
|
52
|
+
- Combined process output: 5 MiB
|
|
53
|
+
- Maximum symbol read: 220 lines
|
|
54
|
+
- Cache LRU: 2 GiB for host runtimes; 500 MiB for Docker and Daytona
|
|
55
|
+
|
|
56
|
+
Set `extensionConfig.codebaseMemory.maxCacheBytes` to a positive integer to
|
|
57
|
+
override the runtime cache limit. The persisted default `0` means “use the
|
|
58
|
+
runtime-specific limit”; it is not a zero-byte cache.
|
|
59
|
+
|
|
60
|
+
## Public API
|
|
61
|
+
|
|
62
|
+
The default export is the portable extension. Hosts may also use:
|
|
63
|
+
|
|
64
|
+
- `createCodebaseMemoryExtension({ telemetry, log })`
|
|
65
|
+
- `CODEBASE_MEMORY_CONFIG`
|
|
66
|
+
- `inspectCodebaseMemoryRuntime(runtime)`
|
|
67
|
+
- `installManagedCodebaseMemory(runtime, onStatus)`
|
|
68
|
+
- `MANAGED_CODEBASE_MEMORY_VERSION`
|
|
69
|
+
|
|
70
|
+
The binary client, project coordination, and symbol services are internal
|
|
71
|
+
implementation details. The package intentionally provides no LSP integration.
|
|
72
|
+
|
|
73
|
+
## Development
|
|
74
|
+
|
|
75
|
+
```sh
|
|
76
|
+
pnpm --filter @felan-ai/ext-codebase-memory build
|
|
77
|
+
pnpm --filter @felan-ai/ext-codebase-memory type-check
|
|
78
|
+
pnpm --filter @felan-ai/ext-codebase-memory test
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
See [NOTICE](NOTICE) for the immutable upstream baselines and licensing.
|
package/dist/cache.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { AgentRuntime } from '@felan-ai/agent-core';
|
|
2
|
+
export type CodebaseMemoryTelemetry = (event: string, fields: Record<string, unknown>) => void;
|
|
3
|
+
export declare class CacheManager {
|
|
4
|
+
#private;
|
|
5
|
+
private readonly runtime;
|
|
6
|
+
private readonly telemetry;
|
|
7
|
+
private readonly onEvict;
|
|
8
|
+
private readonly measureBytes?;
|
|
9
|
+
readonly maxBytes: number;
|
|
10
|
+
constructor(runtime: AgentRuntime, maxBytes?: number, telemetry?: CodebaseMemoryTelemetry, onEvict?: (project: string) => Promise<void>, measureBytes?: (() => Promise<number>) | undefined);
|
|
11
|
+
record(project: string, bytes: number, lastAccessedAt?: number): Promise<void>;
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=cache.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../src/cache.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AASzD,MAAM,MAAM,uBAAuB,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;AAK/F,qBAAa,YAAY;;IAIrB,OAAO,CAAC,QAAQ,CAAC,OAAO;IAExB,OAAO,CAAC,QAAQ,CAAC,SAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAC;IAPhC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;gBAGP,OAAO,EAAE,YAAY,EACtC,QAAQ,SAAyE,EAChE,SAAS,GAAE,uBAAkC,EAC7C,OAAO,GAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAkB,EAC5D,YAAY,CAAC,GAAE,MAAM,OAAO,CAAC,MAAM,CAAC,aAAA;IAKvD,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,cAAc,SAAa,GAAG,OAAO,CAAC,IAAI,CAAC;CA6EnF"}
|
package/dist/cache.js
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
const HOST_MAX_CACHE_BYTES = 2 * 1024 * 1024 * 1024;
|
|
3
|
+
const CLOUD_MAX_CACHE_BYTES = 500 * 1024 * 1024;
|
|
4
|
+
const encoder = new TextEncoder();
|
|
5
|
+
const decoder = new TextDecoder();
|
|
6
|
+
const MAX_MANIFEST_BYTES = 1024 * 1024;
|
|
7
|
+
const cacheControls = new Map();
|
|
8
|
+
export class CacheManager {
|
|
9
|
+
runtime;
|
|
10
|
+
telemetry;
|
|
11
|
+
onEvict;
|
|
12
|
+
measureBytes;
|
|
13
|
+
maxBytes;
|
|
14
|
+
constructor(runtime, maxBytes = runtime.kind === 'host' ? HOST_MAX_CACHE_BYTES : CLOUD_MAX_CACHE_BYTES, telemetry = () => { }, onEvict = async () => { }, measureBytes) {
|
|
15
|
+
this.runtime = runtime;
|
|
16
|
+
this.telemetry = telemetry;
|
|
17
|
+
this.onEvict = onEvict;
|
|
18
|
+
this.measureBytes = measureBytes;
|
|
19
|
+
this.maxBytes = maxBytes;
|
|
20
|
+
}
|
|
21
|
+
record(project, bytes, lastAccessedAt = Date.now()) {
|
|
22
|
+
return this.#run(async () => {
|
|
23
|
+
const manifest = await this.#readManifest();
|
|
24
|
+
const entries = manifest.entries.filter((entry) => entry.project !== project);
|
|
25
|
+
entries.push({ project, bytes: Math.max(0, bytes), lastAccessedAt });
|
|
26
|
+
entries.sort((left, right) => left.lastAccessedAt - right.lastAccessedAt);
|
|
27
|
+
let total = this.measureBytes
|
|
28
|
+
? await this.measureBytes()
|
|
29
|
+
: entries.reduce((sum, entry) => sum + entry.bytes, 0);
|
|
30
|
+
while (total > this.maxBytes && entries.length > 0) {
|
|
31
|
+
const evicted = entries.shift();
|
|
32
|
+
if (!evicted)
|
|
33
|
+
break;
|
|
34
|
+
await this.onEvict(evicted.project);
|
|
35
|
+
await this.runtime.storage('agent').remove(`codebase-memory/cache/${projectStorageKey(evicted.project)}`, { recursive: true }).catch(() => { });
|
|
36
|
+
total = this.measureBytes ? await this.measureBytes() : total - evicted.bytes;
|
|
37
|
+
this.telemetry('cache_eviction', {
|
|
38
|
+
projectKey: projectStorageKey(evicted.project),
|
|
39
|
+
bytes: evicted.bytes,
|
|
40
|
+
maxBytes: this.maxBytes,
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
await this.runtime.storage('agent').mkdir('codebase-memory', { recursive: true });
|
|
44
|
+
if (entries.some((entry) => entry.project === project)) {
|
|
45
|
+
const storageKey = projectStorageKey(project);
|
|
46
|
+
await this.runtime.storage('agent').mkdir(`codebase-memory/cache/${storageKey}`, { recursive: true });
|
|
47
|
+
await this.runtime.storage('agent').writeFile(`codebase-memory/cache/${storageKey}/.felan-lru`, encoder.encode(String(lastAccessedAt)));
|
|
48
|
+
}
|
|
49
|
+
await this.runtime.storage('agent').writeFile('codebase-memory/lru.json', encoder.encode(JSON.stringify({ version: 1, entries })));
|
|
50
|
+
this.telemetry('cache_size', { bytes: total, maxBytes: this.maxBytes, projects: entries.length });
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
async #readManifest() {
|
|
54
|
+
try {
|
|
55
|
+
const parsed = JSON.parse(decoder.decode(await this.runtime.storage('agent').readFile('codebase-memory/lru.json', { maxBytes: MAX_MANIFEST_BYTES })));
|
|
56
|
+
if (parsed.version !== 1 || !Array.isArray(parsed.entries))
|
|
57
|
+
return { version: 1, entries: [] };
|
|
58
|
+
const entries = parsed.entries.filter((value) => {
|
|
59
|
+
if (typeof value !== 'object' || value === null || Array.isArray(value))
|
|
60
|
+
return false;
|
|
61
|
+
const entry = value;
|
|
62
|
+
return typeof entry.project === 'string'
|
|
63
|
+
&& entry.project.length > 0
|
|
64
|
+
&& typeof entry.bytes === 'number'
|
|
65
|
+
&& Number.isSafeInteger(entry.bytes)
|
|
66
|
+
&& entry.bytes >= 0
|
|
67
|
+
&& typeof entry.lastAccessedAt === 'number'
|
|
68
|
+
&& Number.isSafeInteger(entry.lastAccessedAt)
|
|
69
|
+
&& entry.lastAccessedAt >= 0;
|
|
70
|
+
});
|
|
71
|
+
return { version: 1, entries };
|
|
72
|
+
}
|
|
73
|
+
catch {
|
|
74
|
+
return { version: 1, entries: [] };
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
async #run(operation) {
|
|
78
|
+
const key = this.runtime.storage('agent').root;
|
|
79
|
+
const previous = cacheControls.get(key) ?? Promise.resolve();
|
|
80
|
+
let release;
|
|
81
|
+
const current = new Promise((resolve) => { release = resolve; });
|
|
82
|
+
cacheControls.set(key, current);
|
|
83
|
+
await previous;
|
|
84
|
+
try {
|
|
85
|
+
await operation();
|
|
86
|
+
}
|
|
87
|
+
finally {
|
|
88
|
+
release();
|
|
89
|
+
if (cacheControls.get(key) === current)
|
|
90
|
+
cacheControls.delete(key);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
function projectStorageKey(project) {
|
|
95
|
+
return createHash('sha256').update(project).digest('hex');
|
|
96
|
+
}
|
|
97
|
+
//# sourceMappingURL=cache.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cache.js","sourceRoot":"","sources":["../src/cache.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAGzC,MAAM,oBAAoB,GAAG,CAAC,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;AACpD,MAAM,qBAAqB,GAAG,GAAG,GAAG,IAAI,GAAG,IAAI,CAAC;AAChD,MAAM,OAAO,GAAG,IAAI,WAAW,EAAE,CAAC;AAClC,MAAM,OAAO,GAAG,IAAI,WAAW,EAAE,CAAC;AAClC,MAAM,kBAAkB,GAAG,IAAI,GAAG,IAAI,CAAC;AACvC,MAAM,aAAa,GAAG,IAAI,GAAG,EAAyB,CAAC;AAOvD,MAAM,OAAO,YAAY;IAIJ;IAEA;IACA;IACA;IAPV,QAAQ,CAAS;IAE1B,YACmB,OAAqB,EACtC,QAAQ,GAAG,OAAO,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,oBAAoB,CAAC,CAAC,CAAC,qBAAqB,EAChE,YAAqC,GAAG,EAAE,GAAE,CAAC,EAC7C,UAA8C,KAAK,IAAI,EAAE,GAAE,CAAC,EAC5D,YAAoC;QAJpC,YAAO,GAAP,OAAO,CAAc;QAErB,cAAS,GAAT,SAAS,CAAoC;QAC7C,YAAO,GAAP,OAAO,CAAqD;QAC5D,iBAAY,GAAZ,YAAY,CAAwB;QAErD,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAC3B,CAAC;IAED,MAAM,CAAC,OAAe,EAAE,KAAa,EAAE,cAAc,GAAG,IAAI,CAAC,GAAG,EAAE;QAChE,OAAO,IAAI,CAAC,IAAI,CAAC,KAAK,IAAI,EAAE;YAC1B,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,aAAa,EAAE,CAAC;YAC5C,MAAM,OAAO,GAAG,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,OAAO,KAAK,OAAO,CAAC,CAAC;YAC9E,OAAO,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,EAAE,cAAc,EAAE,CAAC,CAAC;YACrE,OAAO,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,cAAc,GAAG,KAAK,CAAC,cAAc,CAAC,CAAC;YAC1E,IAAI,KAAK,GAAG,IAAI,CAAC,YAAY;gBAC3B,CAAC,CAAC,MAAM,IAAI,CAAC,YAAY,EAAE;gBAC3B,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE,CAAC,GAAG,GAAG,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;YACzD,OAAO,KAAK,GAAG,IAAI,CAAC,QAAQ,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACnD,MAAM,OAAO,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC;gBAChC,IAAI,CAAC,OAAO;oBAAE,MAAM;gBACpB,MAAM,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;gBACpC,MAAM,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,MAAM,CACxC,yBAAyB,iBAAiB,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,EAC7D,EAAE,SAAS,EAAE,IAAI,EAAE,CACpB,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;gBAClB,KAAK,GAAG,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,MAAM,IAAI,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC;gBAC9E,IAAI,CAAC,SAAS,CAAC,gBAAgB,EAAE;oBAC/B,UAAU,EAAE,iBAAiB,CAAC,OAAO,CAAC,OAAO,CAAC;oBAC9C,KAAK,EAAE,OAAO,CAAC,KAAK;oBACpB,QAAQ,EAAE,IAAI,CAAC,QAAQ;iBACxB,CAAC,CAAC;YACL,CAAC;YACD,MAAM,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,KAAK,CAAC,iBAAiB,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YAClF,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,OAAO,KAAK,OAAO,CAAC,EAAE,CAAC;gBACvD,MAAM,UAAU,GAAG,iBAAiB,CAAC,OAAO,CAAC,CAAC;gBAC9C,MAAM,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,KAAK,CAAC,yBAAyB,UAAU,EAAE,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;gBACtG,MAAM,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,SAAS,CAC3C,yBAAyB,UAAU,aAAa,EAChD,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC,CACvC,CAAC;YACJ,CAAC;YACD,MAAM,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,0BAA0B,EAAE,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC;YACnI,IAAI,CAAC,SAAS,CAAC,YAAY,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,QAAQ,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;QACpG,CAAC,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,aAAa;QACjB,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,QAAQ,CACnF,0BAA0B,EAC1B,EAAE,QAAQ,EAAE,kBAAkB,EAAE,CACjC,CAAC,CAA4B,CAAC;YAC/B,IAAI,MAAM,CAAC,OAAO,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC;gBAAE,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;YAC/F,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,KAAK,EAAuB,EAAE;gBACnE,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;oBAAE,OAAO,KAAK,CAAC;gBACtF,MAAM,KAAK,GAAG,KAAgC,CAAC;gBAC/C,OAAO,OAAO,KAAK,CAAC,OAAO,KAAK,QAAQ;uBACnC,KAAK,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC;uBACxB,OAAO,KAAK,CAAC,KAAK,KAAK,QAAQ;uBAC/B,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,KAAK,CAAC;uBACjC,KAAK,CAAC,KAAK,IAAI,CAAC;uBAChB,OAAO,KAAK,CAAC,cAAc,KAAK,QAAQ;uBACxC,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,cAAc,CAAC;uBAC1C,KAAK,CAAC,cAAc,IAAI,CAAC,CAAC;YACjC,CAAC,CAAC,CAAC;YACH,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC;QACjC,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;QACrC,CAAC;IACH,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,SAA8B;QACvC,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC;QAC/C,MAAM,QAAQ,GAAG,aAAa,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;QAC7D,IAAI,OAAoB,CAAC;QACzB,MAAM,OAAO,GAAG,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE,GAAG,OAAO,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;QACvE,aAAa,CAAC,GAAG,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;QAChC,MAAM,QAAQ,CAAC;QACf,IAAI,CAAC;YACH,MAAM,SAAS,EAAE,CAAC;QACpB,CAAC;gBAAS,CAAC;YACT,OAAO,EAAE,CAAC;YACV,IAAI,aAAa,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,OAAO;gBAAE,aAAa,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACpE,CAAC;IACH,CAAC;CACF;AAED,SAAS,iBAAiB,CAAC,OAAe;IACxC,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAC5D,CAAC"}
|
package/dist/client.d.ts
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { AgentRuntime } from '@felan-ai/agent-core';
|
|
2
|
+
export declare const CODEBASE_MEMORY_VERSION = "0.10.8";
|
|
3
|
+
export declare const QUERY_TIMEOUT_MS = 60000;
|
|
4
|
+
export declare const INDEX_TIMEOUT_MS: number;
|
|
5
|
+
export declare const MAX_OUTPUT_BYTES: number;
|
|
6
|
+
export interface CbmInvocation {
|
|
7
|
+
readonly command: string;
|
|
8
|
+
readonly version: string;
|
|
9
|
+
readonly source: 'managed' | 'path';
|
|
10
|
+
}
|
|
11
|
+
export type CbmDetection = {
|
|
12
|
+
readonly available: true;
|
|
13
|
+
readonly invocation: CbmInvocation;
|
|
14
|
+
} | {
|
|
15
|
+
readonly available: false;
|
|
16
|
+
readonly reason: string;
|
|
17
|
+
};
|
|
18
|
+
export interface CbmCallOptions {
|
|
19
|
+
readonly signal?: AbortSignal;
|
|
20
|
+
readonly timeoutMs?: number;
|
|
21
|
+
}
|
|
22
|
+
export interface CbmCallResult {
|
|
23
|
+
readonly data: unknown;
|
|
24
|
+
readonly stderr: string;
|
|
25
|
+
}
|
|
26
|
+
export declare class CbmClient {
|
|
27
|
+
private readonly runtime;
|
|
28
|
+
readonly invocation: CbmInvocation;
|
|
29
|
+
readonly cacheRoot: string;
|
|
30
|
+
readonly runtimeRoot: string;
|
|
31
|
+
constructor(runtime: AgentRuntime, invocation: CbmInvocation);
|
|
32
|
+
call(command: string, args: Record<string, unknown>, options?: CbmCallOptions): Promise<CbmCallResult>;
|
|
33
|
+
}
|
|
34
|
+
export declare function detectCbm(runtime: AgentRuntime): Promise<CbmDetection>;
|
|
35
|
+
//# sourceMappingURL=client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAc,MAAM,sBAAsB,CAAC;AAGrE,eAAO,MAAM,uBAAuB,WAAW,CAAC;AAChD,eAAO,MAAM,gBAAgB,QAAS,CAAC;AACvC,eAAO,MAAM,gBAAgB,QAAc,CAAC;AAC5C,eAAO,MAAM,gBAAgB,QAAkB,CAAC;AAEhD,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,MAAM,EAAE,SAAS,GAAG,MAAM,CAAC;CACrC;AAED,MAAM,MAAM,YAAY,GACpB;IAAE,QAAQ,CAAC,SAAS,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,UAAU,EAAE,aAAa,CAAA;CAAE,GAChE;IAAE,QAAQ,CAAC,SAAS,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAE3D,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,CAAC;IAC9B,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED,qBAAa,SAAS;IAKlB,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,QAAQ,CAAC,UAAU,EAAE,aAAa;IALpC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;gBAGV,OAAO,EAAE,YAAY,EAC7B,UAAU,EAAE,aAAa;IAM9B,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,GAAE,cAAmB,GAAG,OAAO,CAAC,aAAa,CAAC;CAqBjH;AAED,wBAAsB,SAAS,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC,CA2B5E"}
|
package/dist/client.js
ADDED
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { joinRuntimePath, shellQuote } from './runtime-path.js';
|
|
2
|
+
export const CODEBASE_MEMORY_VERSION = '0.10.8';
|
|
3
|
+
export const QUERY_TIMEOUT_MS = 60_000;
|
|
4
|
+
export const INDEX_TIMEOUT_MS = 20 * 60_000;
|
|
5
|
+
export const MAX_OUTPUT_BYTES = 5 * 1024 * 1024;
|
|
6
|
+
export class CbmClient {
|
|
7
|
+
runtime;
|
|
8
|
+
invocation;
|
|
9
|
+
cacheRoot;
|
|
10
|
+
runtimeRoot;
|
|
11
|
+
constructor(runtime, invocation) {
|
|
12
|
+
this.runtime = runtime;
|
|
13
|
+
this.invocation = invocation;
|
|
14
|
+
this.cacheRoot = joinRuntimePath(runtime.storage('agent').root, 'codebase-memory/cache');
|
|
15
|
+
this.runtimeRoot = joinRuntimePath(runtime.storage('agent').root, 'codebase-memory/runtime');
|
|
16
|
+
}
|
|
17
|
+
async call(command, args, options = {}) {
|
|
18
|
+
const timeout = options.timeoutMs ?? (command === 'index_repository' ? INDEX_TIMEOUT_MS : QUERY_TIMEOUT_MS);
|
|
19
|
+
await this.runtime.storage('agent').mkdir('codebase-memory/runtime', { recursive: true });
|
|
20
|
+
const encoded = JSON.stringify(args);
|
|
21
|
+
const shellCommand = [
|
|
22
|
+
shellQuote(this.invocation.command),
|
|
23
|
+
'cli',
|
|
24
|
+
'--json',
|
|
25
|
+
shellQuote(command),
|
|
26
|
+
shellQuote(encoded),
|
|
27
|
+
].join(' ');
|
|
28
|
+
const result = await this.runtime.shell(shellCommand, {
|
|
29
|
+
cwd: this.runtime.cwd,
|
|
30
|
+
env: { CBM_CACHE_DIR: this.cacheRoot, CBM_RUNTIME_DIR: this.runtimeRoot },
|
|
31
|
+
maxOutputBytes: MAX_OUTPUT_BYTES,
|
|
32
|
+
shellFlavor: 'posix',
|
|
33
|
+
...(options.signal === undefined ? {} : { signal: options.signal }),
|
|
34
|
+
timeout,
|
|
35
|
+
});
|
|
36
|
+
return parseResult(command, result);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
export async function detectCbm(runtime) {
|
|
40
|
+
const candidates = [
|
|
41
|
+
{
|
|
42
|
+
command: joinRuntimePath(runtime.storage('agent').root, 'codebase-memory/bin/codebase-memory-mcp'),
|
|
43
|
+
source: 'managed',
|
|
44
|
+
},
|
|
45
|
+
{ command: 'codebase-memory-mcp', source: 'path' },
|
|
46
|
+
];
|
|
47
|
+
for (const candidate of candidates) {
|
|
48
|
+
let result;
|
|
49
|
+
try {
|
|
50
|
+
result = await runtime.exec(candidate.command, ['--version'], {
|
|
51
|
+
cwd: runtime.cwd,
|
|
52
|
+
maxOutputBytes: 64 * 1024,
|
|
53
|
+
timeout: 5_000,
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
catch {
|
|
57
|
+
continue;
|
|
58
|
+
}
|
|
59
|
+
if (result.code !== 0 || result.killed)
|
|
60
|
+
continue;
|
|
61
|
+
const version = `${result.stdout}\n${result.stderr}`.match(/\b(\d+\.\d+\.\d+)\b/u)?.[1];
|
|
62
|
+
if (version && isCompatibleVersion(version))
|
|
63
|
+
return { available: true, invocation: { ...candidate, version } };
|
|
64
|
+
}
|
|
65
|
+
return {
|
|
66
|
+
available: false,
|
|
67
|
+
reason: `Compatible codebase-memory-mcp ${CODEBASE_MEMORY_VERSION} is not installed.`,
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
function isCompatibleVersion(version) {
|
|
71
|
+
return version === CODEBASE_MEMORY_VERSION;
|
|
72
|
+
}
|
|
73
|
+
function parseResult(command, result) {
|
|
74
|
+
if (result.killed)
|
|
75
|
+
throw new Error(`${command} timed out or was cancelled`);
|
|
76
|
+
if (result.truncated)
|
|
77
|
+
throw new Error(`${command} exceeded the ${MAX_OUTPUT_BYTES}-byte output limit`);
|
|
78
|
+
if (result.code !== 0)
|
|
79
|
+
throw new Error(sanitize(result.stderr || result.stdout || `${command} exited ${result.code}`));
|
|
80
|
+
const trimmed = result.stdout.trim();
|
|
81
|
+
if (!trimmed)
|
|
82
|
+
throw new Error(`${command} produced no JSON output`);
|
|
83
|
+
let envelope;
|
|
84
|
+
try {
|
|
85
|
+
envelope = JSON.parse(trimmed);
|
|
86
|
+
}
|
|
87
|
+
catch {
|
|
88
|
+
const candidate = trimmed.split(/\r?\n/u).reverse().find((line) => line.trim().startsWith('{'));
|
|
89
|
+
if (!candidate)
|
|
90
|
+
throw new Error(`${command} produced invalid JSON output`);
|
|
91
|
+
envelope = JSON.parse(candidate);
|
|
92
|
+
}
|
|
93
|
+
const text = envelope.content?.find((block) => block.type === 'text' && typeof block.text === 'string')?.text;
|
|
94
|
+
if (text === undefined)
|
|
95
|
+
throw new Error(`${command} returned an envelope with no text content`);
|
|
96
|
+
let data = text;
|
|
97
|
+
try {
|
|
98
|
+
data = JSON.parse(text);
|
|
99
|
+
}
|
|
100
|
+
catch { /* Preserve non-JSON upstream text. */ }
|
|
101
|
+
if (envelope.isError)
|
|
102
|
+
throw new Error(sanitize(typeof data === 'string' ? data : JSON.stringify(data)));
|
|
103
|
+
return { data, stderr: sanitize(result.stderr) };
|
|
104
|
+
}
|
|
105
|
+
function sanitize(value) {
|
|
106
|
+
return value.replace(/\u001b\[[0-?]*[ -/]*[@-~]/gu, '').replace(/[\u0000-\u001f\u007f]/gu, ' ').trim().slice(0, 1_000);
|
|
107
|
+
}
|
|
108
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
|
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,sBAAsB;;EAYjC,CAAC"}
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { configField, defineExtensionConfig } from '@felan-ai/agent-core';
|
|
2
|
+
export const CODEBASE_MEMORY_CONFIG = defineExtensionConfig({
|
|
3
|
+
id: 'codebaseMemory',
|
|
4
|
+
title: 'Codebase Memory',
|
|
5
|
+
fields: {
|
|
6
|
+
maxCacheBytes: configField.number({
|
|
7
|
+
default: 0,
|
|
8
|
+
description: 'Maximum bytes retained by the Codebase Memory LRU cache; 0 uses the runtime default',
|
|
9
|
+
validate: (value) => typeof value === 'number' && Number.isSafeInteger(value) && value >= 0
|
|
10
|
+
? undefined
|
|
11
|
+
: 'must be a non-negative integer',
|
|
12
|
+
}),
|
|
13
|
+
},
|
|
14
|
+
});
|
|
15
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAE1E,MAAM,CAAC,MAAM,sBAAsB,GAAG,qBAAqB,CAAC;IAC1D,EAAE,EAAE,gBAAgB;IACpB,KAAK,EAAE,iBAAiB;IACxB,MAAM,EAAE;QACN,aAAa,EAAE,WAAW,CAAC,MAAM,CAAC;YAChC,OAAO,EAAE,CAAC;YACV,WAAW,EAAE,qFAAqF;YAClG,QAAQ,EAAE,CAAC,KAAc,EAAE,EAAE,CAAC,OAAO,KAAK,KAAK,QAAQ,IAAI,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,IAAI,KAAK,IAAI,CAAC;gBAClG,CAAC,CAAC,SAAS;gBACX,CAAC,CAAC,gCAAgC;SACrC,CAAC;KACH;CACF,CAAC,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { FelanExtensionAPI } from '@felan-ai/agent-core';
|
|
2
|
+
import type { CodebaseMemoryTelemetry } from './cache.js';
|
|
3
|
+
import type { CbmClient } from './client.js';
|
|
4
|
+
import type { ProjectService } from './services.js';
|
|
5
|
+
export declare function registerGrepAugmentation(pi: FelanExtensionAPI, client: CbmClient, projects: ProjectService, telemetry: CodebaseMemoryTelemetry): void;
|
|
6
|
+
//# sourceMappingURL=grep-augmentation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"grep-augmentation.d.ts","sourceRoot":"","sources":["../src/grep-augmentation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAoB,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAChF,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,YAAY,CAAC;AAC1D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAKpD,wBAAgB,wBAAwB,CACtC,EAAE,EAAE,iBAAiB,EACrB,MAAM,EAAE,SAAS,EACjB,QAAQ,EAAE,cAAc,EACxB,SAAS,EAAE,uBAAuB,GACjC,IAAI,CAiDN"}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
const GREP_AUGMENT_TIMEOUT_MS = 1_500;
|
|
2
|
+
const COMMAND_TOOLS = ['bash', 'exec_command'];
|
|
3
|
+
export function registerGrepAugmentation(pi, client, projects, telemetry) {
|
|
4
|
+
const patterns = new Map();
|
|
5
|
+
pi.on('tool_call', (event) => {
|
|
6
|
+
if (!COMMAND_TOOLS.includes(event.toolName))
|
|
7
|
+
return;
|
|
8
|
+
const command = readCommand(event.toolName, event.input);
|
|
9
|
+
const pattern = command ? grepPattern(command) : undefined;
|
|
10
|
+
if (pattern)
|
|
11
|
+
patterns.set(event.toolCallId, { pattern, tool: event.toolName });
|
|
12
|
+
});
|
|
13
|
+
pi.on('tool_result', async (event, _ctx) => {
|
|
14
|
+
const pending = patterns.get(event.toolCallId);
|
|
15
|
+
if (!pending)
|
|
16
|
+
return undefined;
|
|
17
|
+
patterns.delete(event.toolCallId);
|
|
18
|
+
if (event.isError)
|
|
19
|
+
return undefined;
|
|
20
|
+
const startedAt = Date.now();
|
|
21
|
+
try {
|
|
22
|
+
const project = await projects.project(undefined, remainingMs(startedAt));
|
|
23
|
+
const result = await client.call('search_code', {
|
|
24
|
+
project,
|
|
25
|
+
pattern: pending.pattern,
|
|
26
|
+
context: 2,
|
|
27
|
+
limit: 20,
|
|
28
|
+
max_symbol_lines: 220,
|
|
29
|
+
}, { timeoutMs: remainingMs(startedAt) });
|
|
30
|
+
const text = typeof result.data === 'string' ? result.data : JSON.stringify(result.data, null, 2);
|
|
31
|
+
const hit = hasResults(result.data);
|
|
32
|
+
telemetry('grep_augmentation', {
|
|
33
|
+
tool: pending.tool,
|
|
34
|
+
hit,
|
|
35
|
+
durationMs: Date.now() - startedAt,
|
|
36
|
+
deadlineMs: GREP_AUGMENT_TIMEOUT_MS,
|
|
37
|
+
});
|
|
38
|
+
if (!hit)
|
|
39
|
+
return undefined;
|
|
40
|
+
return {
|
|
41
|
+
content: [
|
|
42
|
+
...event.content,
|
|
43
|
+
{ type: 'text', text: `Codebase Memory augmentation (possibly stale; grep remains authoritative):\n${text}` },
|
|
44
|
+
],
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
catch {
|
|
48
|
+
telemetry('grep_augmentation', {
|
|
49
|
+
tool: pending.tool,
|
|
50
|
+
hit: false,
|
|
51
|
+
error: true,
|
|
52
|
+
durationMs: Date.now() - startedAt,
|
|
53
|
+
deadlineMs: GREP_AUGMENT_TIMEOUT_MS,
|
|
54
|
+
});
|
|
55
|
+
return undefined;
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
function remainingMs(startedAt) {
|
|
60
|
+
return Math.max(1, GREP_AUGMENT_TIMEOUT_MS - (Date.now() - startedAt));
|
|
61
|
+
}
|
|
62
|
+
function readCommand(tool, input) {
|
|
63
|
+
const value = tool === 'exec_command' ? input.cmd : input.command;
|
|
64
|
+
return typeof value === 'string' ? value : undefined;
|
|
65
|
+
}
|
|
66
|
+
function grepPattern(command) {
|
|
67
|
+
const segment = command.split(/(?:&&|;|\|\|)/u).find((part) => /(?:^|\s)(?:grep|rg)(?:\s|$)/u.test(part));
|
|
68
|
+
if (!segment)
|
|
69
|
+
return undefined;
|
|
70
|
+
const tokens = segment.match(/(?:[^\s"']+|"[^"]*"|'[^']*')+/gu) ?? [];
|
|
71
|
+
const index = tokens.findIndex((token) => token === 'grep' || token === 'rg');
|
|
72
|
+
const optionsWithValues = new Set([
|
|
73
|
+
'-A', '-B', '-C', '-f', '-g', '-j', '-m', '-t', '-T',
|
|
74
|
+
'--after-context', '--before-context', '--context', '--encoding', '--engine',
|
|
75
|
+
'--file', '--glob', '--iglob', '--max-count', '--sort', '--sortr', '--threads',
|
|
76
|
+
'--type', '--type-not',
|
|
77
|
+
]);
|
|
78
|
+
for (let position = index + 1; position < tokens.length; position += 1) {
|
|
79
|
+
const token = tokens[position];
|
|
80
|
+
if (token === '-e' || token === '--regexp')
|
|
81
|
+
return unquote(tokens[position + 1]);
|
|
82
|
+
if (optionsWithValues.has(token)) {
|
|
83
|
+
position += 1;
|
|
84
|
+
continue;
|
|
85
|
+
}
|
|
86
|
+
if (token.startsWith('-'))
|
|
87
|
+
continue;
|
|
88
|
+
return unquote(token);
|
|
89
|
+
}
|
|
90
|
+
return undefined;
|
|
91
|
+
}
|
|
92
|
+
function unquote(token) {
|
|
93
|
+
return token?.replace(/^(['"])(.*)\1$/u, '$2');
|
|
94
|
+
}
|
|
95
|
+
function hasResults(value) {
|
|
96
|
+
if (typeof value === 'string')
|
|
97
|
+
return value.trim().length > 0;
|
|
98
|
+
if (!value || typeof value !== 'object')
|
|
99
|
+
return false;
|
|
100
|
+
const results = Reflect.get(value, 'results');
|
|
101
|
+
return Array.isArray(results) ? results.length > 0 : true;
|
|
102
|
+
}
|
|
103
|
+
//# sourceMappingURL=grep-augmentation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"grep-augmentation.js","sourceRoot":"","sources":["../src/grep-augmentation.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { type FelanExtension } from '@felan-ai/agent-core';
|
|
2
|
+
import { type CodebaseMemoryTelemetry } from './cache.js';
|
|
3
|
+
export declare const CODEBASE_MEMORY_CAPABILITY_INSTRUCTIONS = "Use Codebase Memory for structural code exploration before broad raw searches: read_symbol reads a known symbol, search_and_read_symbols finds and reads likely implementations, search_code searches indexed text, and codebase_memory proxies other structural queries or refreshes with {command:\"index_repository\"}. The index is built at startup and refreshed only when the model calls index_repository or the user invokes /codebase-memory. It may be stale after edits. Direct reads, grep, compiler output, and tests remain authoritative; grep output can include bounded Codebase Memory augmentation. Keep symbol reads focused and at no more than 220 lines per symbol.";
|
|
4
|
+
export interface CodebaseMemoryExtensionOptions {
|
|
5
|
+
readonly telemetry?: CodebaseMemoryTelemetry;
|
|
6
|
+
readonly log?: (level: 'error' | 'info', message: string, fields: Record<string, unknown>) => void;
|
|
7
|
+
}
|
|
8
|
+
export declare function createCodebaseMemoryExtension(options?: CodebaseMemoryExtensionOptions): FelanExtension;
|
|
9
|
+
declare const codebaseMemoryExtension: FelanExtension;
|
|
10
|
+
export default codebaseMemoryExtension;
|
|
11
|
+
export { CODEBASE_MEMORY_CONFIG } from './config.js';
|
|
12
|
+
export { CODEBASE_MEMORY_VERSION as MANAGED_CODEBASE_MEMORY_VERSION, detectCbm as inspectCodebaseMemoryRuntime, } from './client.js';
|
|
13
|
+
export { installManagedCbm as installManagedCodebaseMemory } from './installer.js';
|
|
14
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,cAAc,EACpB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,KAAK,uBAAuB,EAAE,MAAM,YAAY,CAAC;AAQ1D,eAAO,MAAM,uCAAuC,gqBAA8pB,CAAC;AAEntB,MAAM,WAAW,8BAA8B;IAC7C,QAAQ,CAAC,SAAS,CAAC,EAAE,uBAAuB,CAAC;IAC7C,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;CACpG;AAED,wBAAgB,6BAA6B,CAAC,OAAO,GAAE,8BAAmC,GAAG,cAAc,CAyE1G;AAiBD,QAAA,MAAM,uBAAuB,gBAAkC,CAAC;AAChE,eAAe,uBAAuB,CAAC;AACvC,OAAO,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC;AACrD,OAAO,EACL,uBAAuB,IAAI,+BAA+B,EAC1D,SAAS,IAAI,4BAA4B,GAC1C,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,iBAAiB,IAAI,4BAA4B,EAAE,MAAM,gBAAgB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { associateExtensionConfig, } from '@felan-ai/agent-core';
|
|
2
|
+
import {} from './cache.js';
|
|
3
|
+
import { CbmClient, detectCbm } from './client.js';
|
|
4
|
+
import { CODEBASE_MEMORY_CONFIG } from './config.js';
|
|
5
|
+
import { registerGrepAugmentation } from './grep-augmentation.js';
|
|
6
|
+
import { installManagedCbm } from './installer.js';
|
|
7
|
+
import { ProjectService, SymbolService } from './services.js';
|
|
8
|
+
import { registerTools } from './tools.js';
|
|
9
|
+
export const CODEBASE_MEMORY_CAPABILITY_INSTRUCTIONS = `Use Codebase Memory for structural code exploration before broad raw searches: read_symbol reads a known symbol, search_and_read_symbols finds and reads likely implementations, search_code searches indexed text, and codebase_memory proxies other structural queries or refreshes with {command:"index_repository"}. The index is built at startup and refreshed only when the model calls index_repository or the user invokes /codebase-memory. It may be stale after edits. Direct reads, grep, compiler output, and tests remain authoritative; grep output can include bounded Codebase Memory augmentation. Keep symbol reads focused and at no more than 220 lines per symbol.`;
|
|
10
|
+
export function createCodebaseMemoryExtension(options = {}) {
|
|
11
|
+
const log = options.log ?? ((level, message, fields) => {
|
|
12
|
+
if (level === 'error')
|
|
13
|
+
console.error(`[codebase-memory] ERROR ${message}`, fields);
|
|
14
|
+
else
|
|
15
|
+
console.info(`[codebase-memory] ${message}`, fields);
|
|
16
|
+
});
|
|
17
|
+
const extension = async (pi) => {
|
|
18
|
+
const telemetry = options.telemetry ?? ((event, fields) => {
|
|
19
|
+
if (pi.runtime.kind !== 'host')
|
|
20
|
+
log('info', `telemetry.${event}`, fields);
|
|
21
|
+
});
|
|
22
|
+
let detection = await detectCbm(pi.runtime);
|
|
23
|
+
let hintShown = false;
|
|
24
|
+
let projects;
|
|
25
|
+
const activate = (available) => {
|
|
26
|
+
const client = new CbmClient(pi.runtime, available.invocation);
|
|
27
|
+
const configured = pi.config.maxCacheBytes;
|
|
28
|
+
const maxCacheBytes = typeof configured === 'number' && configured > 0 ? configured : undefined;
|
|
29
|
+
projects = new ProjectService(pi.runtime, client, maxCacheBytes, telemetry);
|
|
30
|
+
const symbols = new SymbolService(client, projects);
|
|
31
|
+
pi.registerCapability({ id: 'codebase-memory', instructions: CODEBASE_MEMORY_CAPABILITY_INSTRUCTIONS });
|
|
32
|
+
registerTools(pi, client, projects, symbols);
|
|
33
|
+
registerGrepAugmentation(pi, client, projects, telemetry);
|
|
34
|
+
};
|
|
35
|
+
if (detection.available)
|
|
36
|
+
activate(detection);
|
|
37
|
+
else if (pi.runtime.kind !== 'host') {
|
|
38
|
+
log('error', 'Compatible codebase-memory-mcp binary is unavailable; extension disabled nonfatally.', {
|
|
39
|
+
runtimeKind: pi.runtime.kind,
|
|
40
|
+
reason: detection.reason,
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
pi.registerCommand('codebase-memory', {
|
|
44
|
+
description: 'Refresh the repository index or explicitly install Codebase Memory',
|
|
45
|
+
handler: async (args, ctx) => {
|
|
46
|
+
const action = args.trim().toLowerCase();
|
|
47
|
+
if (action && action !== 'install' && action !== 'refresh') {
|
|
48
|
+
ctx.ui.notify('Usage: /codebase-memory [refresh|install]', 'warning');
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
if (action === 'install') {
|
|
52
|
+
if (!await ctx.ui.confirm('Install Codebase Memory', 'Download the pinned reviewed installer and Codebase Memory 0.10.8 binary into Felan agent storage?'))
|
|
53
|
+
return;
|
|
54
|
+
detection = await installManagedCbm(pi.runtime, (message) => ctx.ui.setStatus('codebase-memory', `… ${message}`));
|
|
55
|
+
ctx.ui.setStatus('codebase-memory', undefined);
|
|
56
|
+
ctx.ui.notify(detectionMessage(detection), detection.available ? 'info' : 'error');
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
if (!projects) {
|
|
60
|
+
ctx.ui.notify(detection.available
|
|
61
|
+
? 'Codebase Memory was installed after this session started. Restart Felan to activate it.'
|
|
62
|
+
: `${detection.reason} Use /codebase-memory install to install it.`, 'warning');
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
await refresh(projects, ctx);
|
|
66
|
+
},
|
|
67
|
+
});
|
|
68
|
+
pi.on('session_start', async (_event, ctx) => {
|
|
69
|
+
if (!projects) {
|
|
70
|
+
if (pi.runtime.kind === 'host' && ctx.hasUI && !hintShown) {
|
|
71
|
+
hintShown = true;
|
|
72
|
+
ctx.ui.notify('Codebase Memory is unavailable. Run /codebase-memory install to install the reviewed binary.', 'info');
|
|
73
|
+
}
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
await refresh(projects, ctx);
|
|
77
|
+
});
|
|
78
|
+
};
|
|
79
|
+
associateExtensionConfig(extension, CODEBASE_MEMORY_CONFIG);
|
|
80
|
+
return extension;
|
|
81
|
+
}
|
|
82
|
+
function detectionMessage(detection) {
|
|
83
|
+
return detection.available ? 'Codebase Memory installed. Restart Felan to activate it.' : detection.reason;
|
|
84
|
+
}
|
|
85
|
+
async function refresh(projects, ctx) {
|
|
86
|
+
ctx.ui.setStatus('codebase-memory', '… Indexing repository');
|
|
87
|
+
try {
|
|
88
|
+
await projects.index(ctx.signal);
|
|
89
|
+
ctx.ui.setStatus('codebase-memory', '✓ Codebase Memory indexed');
|
|
90
|
+
}
|
|
91
|
+
catch (error) {
|
|
92
|
+
ctx.ui.setStatus('codebase-memory', undefined);
|
|
93
|
+
if (ctx.hasUI)
|
|
94
|
+
ctx.ui.notify(`Codebase Memory index failed: ${error instanceof Error ? error.message : String(error)}`, 'warning');
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
const codebaseMemoryExtension = createCodebaseMemoryExtension();
|
|
98
|
+
export default codebaseMemoryExtension;
|
|
99
|
+
export { CODEBASE_MEMORY_CONFIG } from './config.js';
|
|
100
|
+
export { CODEBASE_MEMORY_VERSION as MANAGED_CODEBASE_MEMORY_VERSION, detectCbm as inspectCodebaseMemoryRuntime, } from './client.js';
|
|
101
|
+
export { installManagedCbm as installManagedCodebaseMemory } from './installer.js';
|
|
102
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { AgentRuntime } from '@felan-ai/agent-core';
|
|
2
|
+
import { type CbmDetection } from './client.js';
|
|
3
|
+
export declare function installManagedCbm(runtime: AgentRuntime, onStatus?: (message: string) => void): Promise<CbmDetection>;
|
|
4
|
+
//# sourceMappingURL=installer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"installer.d.ts","sourceRoot":"","sources":["../src/installer.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAc,MAAM,sBAAsB,CAAC;AACrE,OAAO,EAAsC,KAAK,YAAY,EAAE,MAAM,aAAa,CAAC;AAQpF,wBAAsB,iBAAiB,CACrC,OAAO,EAAE,YAAY,EACrB,QAAQ,GAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAe,GAC7C,OAAO,CAAC,YAAY,CAAC,CAiCvB"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { createHash, randomUUID } from 'node:crypto';
|
|
2
|
+
import { CODEBASE_MEMORY_VERSION, detectCbm } from './client.js';
|
|
3
|
+
import { joinRuntimePath } from './runtime-path.js';
|
|
4
|
+
const INSTALLER_COMMIT = '46ae198fc11cda80e817acbc5f5908d7c2de7032';
|
|
5
|
+
const INSTALLER_SHA256 = '2fdd4d6563fc8e540bb32e233c5fdef22ecf05d7ebd5a80657cd4fec953b3475';
|
|
6
|
+
const INSTALLER_URL = `https://raw.githubusercontent.com/DeusData/codebase-memory-mcp/${INSTALLER_COMMIT}/install.sh`;
|
|
7
|
+
const RELEASE_URL = `https://github.com/DeusData/codebase-memory-mcp/releases/download/v${CODEBASE_MEMORY_VERSION}`;
|
|
8
|
+
export async function installManagedCbm(runtime, onStatus = () => { }) {
|
|
9
|
+
const session = runtime.storage('session');
|
|
10
|
+
const relative = `codebase-memory/install-${randomUUID()}.sh`;
|
|
11
|
+
const script = joinRuntimePath(session.root, relative);
|
|
12
|
+
const binDir = joinRuntimePath(runtime.storage('agent').root, 'codebase-memory/bin');
|
|
13
|
+
await session.mkdir('codebase-memory', { recursive: true });
|
|
14
|
+
await runtime.storage('agent').mkdir('codebase-memory/bin', { recursive: true });
|
|
15
|
+
try {
|
|
16
|
+
onStatus('Downloading the pinned Codebase Memory installer...');
|
|
17
|
+
const downloaded = await runtime.exec('curl', [
|
|
18
|
+
'--proto', '=https', '--tlsv1.2', '--fail', '--silent', '--show-error', '--location',
|
|
19
|
+
'--max-filesize', String(128 * 1024), INSTALLER_URL, '--output', script,
|
|
20
|
+
], { cwd: runtime.cwd, timeout: 30_000, maxOutputBytes: 64 * 1024 });
|
|
21
|
+
if (!successful(downloaded))
|
|
22
|
+
return unavailable(downloaded.stderr || downloaded.stdout || 'download failed');
|
|
23
|
+
const bytes = await session.readFile(relative, { maxBytes: 128 * 1024 + 1 });
|
|
24
|
+
if (createHash('sha256').update(bytes).digest('hex') !== INSTALLER_SHA256) {
|
|
25
|
+
return unavailable('Installer SHA-256 mismatch; refusing to execute it.');
|
|
26
|
+
}
|
|
27
|
+
onStatus(`Installing Codebase Memory ${CODEBASE_MEMORY_VERSION} in Felan agent storage...`);
|
|
28
|
+
const installed = await runtime.shell(`/bin/bash '${script.replaceAll("'", `'"'"'`)}' --dir '${binDir.replaceAll("'", `'"'"'`)}' --skip-config`, {
|
|
29
|
+
cwd: runtime.cwd,
|
|
30
|
+
env: { CBM_DOWNLOAD_URL: RELEASE_URL },
|
|
31
|
+
maxOutputBytes: 5 * 1024 * 1024,
|
|
32
|
+
shellFlavor: 'posix',
|
|
33
|
+
timeout: 180_000,
|
|
34
|
+
});
|
|
35
|
+
if (!successful(installed))
|
|
36
|
+
return unavailable(installed.stderr || installed.stdout || 'installer failed');
|
|
37
|
+
return detectCbm(runtime);
|
|
38
|
+
}
|
|
39
|
+
catch (error) {
|
|
40
|
+
return unavailable(error instanceof Error ? error.message : String(error));
|
|
41
|
+
}
|
|
42
|
+
finally {
|
|
43
|
+
await session.remove(relative).catch(() => { });
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
function successful(result) { return result.code === 0 && !result.killed; }
|
|
47
|
+
function unavailable(reason) {
|
|
48
|
+
return { available: false, reason: `Managed Codebase Memory installation failed: ${reason.slice(0, 500)}` };
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=installer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"installer.js","sourceRoot":"","sources":["../src/installer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime-path.d.ts","sourceRoot":"","sources":["../src/runtime-path.ts"],"names":[],"mappings":"AAAA,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,KAAK,EAAE,MAAM,EAAE,GAAG,MAAM,CAKxE;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEhD"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export function joinRuntimePath(root, ...parts) {
|
|
2
|
+
const separator = root.includes('\\') && !root.includes('/') ? '\\' : '/';
|
|
3
|
+
return [root.replace(/[\\/]+$/u, ''), ...parts.map((part) => part.replace(/^[\\/]+|[\\/]+$/gu, ''))]
|
|
4
|
+
.filter(Boolean)
|
|
5
|
+
.join(separator);
|
|
6
|
+
}
|
|
7
|
+
export function shellQuote(value) {
|
|
8
|
+
return `'${value.replaceAll("'", `'"'"'`)}'`;
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=runtime-path.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime-path.js","sourceRoot":"","sources":["../src/runtime-path.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,eAAe,CAAC,IAAY,EAAE,GAAG,KAAe;IAC9D,MAAM,SAAS,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC;IAC1E,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,EAAE,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,mBAAmB,EAAE,EAAE,CAAC,CAAC,CAAC;SACjG,MAAM,CAAC,OAAO,CAAC;SACf,IAAI,CAAC,SAAS,CAAC,CAAC;AACrB,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,KAAa;IACtC,OAAO,IAAI,KAAK,CAAC,UAAU,CAAC,GAAG,EAAE,OAAO,CAAC,GAAG,CAAC;AAC/C,CAAC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { AgentRuntime } from '@felan-ai/agent-core';
|
|
2
|
+
import { type CodebaseMemoryTelemetry } from './cache.js';
|
|
3
|
+
import { CbmClient } from './client.js';
|
|
4
|
+
export declare class ProjectService {
|
|
5
|
+
#private;
|
|
6
|
+
private readonly runtime;
|
|
7
|
+
private readonly client;
|
|
8
|
+
constructor(runtime: AgentRuntime, client: CbmClient, maxCacheBytes: number | undefined, telemetry: CodebaseMemoryTelemetry);
|
|
9
|
+
gitRoot(signal?: AbortSignal, timeout?: number): Promise<string>;
|
|
10
|
+
index(signal?: AbortSignal): Promise<unknown>;
|
|
11
|
+
project(signal?: AbortSignal, timeoutMs?: number): Promise<string>;
|
|
12
|
+
}
|
|
13
|
+
export declare class SymbolService {
|
|
14
|
+
private readonly client;
|
|
15
|
+
private readonly projects;
|
|
16
|
+
constructor(client: CbmClient, projects: ProjectService);
|
|
17
|
+
read(params: Record<string, unknown>, signal?: AbortSignal): Promise<unknown>;
|
|
18
|
+
searchAndRead(params: Record<string, unknown>, signal?: AbortSignal): Promise<unknown>;
|
|
19
|
+
}
|
|
20
|
+
export declare function asRecord(value: unknown): Record<string, unknown>;
|
|
21
|
+
//# sourceMappingURL=services.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"services.d.ts","sourceRoot":"","sources":["../src/services.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACzD,OAAO,EAAgB,KAAK,uBAAuB,EAAE,MAAM,YAAY,CAAC;AACxE,OAAO,EAAE,SAAS,EAAoB,MAAM,aAAa,CAAC;AAI1D,qBAAa,cAAc;;IAKvB,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,MAAM;gBADN,OAAO,EAAE,YAAY,EACrB,MAAM,EAAE,SAAS,EAClC,aAAa,EAAE,MAAM,GAAG,SAAS,EACjC,SAAS,EAAE,uBAAuB;IAO9B,OAAO,CAAC,MAAM,CAAC,EAAE,WAAW,EAAE,OAAO,SAAS,GAAG,OAAO,CAAC,MAAM,CAAC;IAUhE,KAAK,CAAC,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC;IAgC7C,OAAO,CAAC,MAAM,CAAC,EAAE,WAAW,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;CAYzE;AAED,qBAAa,aAAa;IACZ,OAAO,CAAC,QAAQ,CAAC,MAAM;IAAa,OAAO,CAAC,QAAQ,CAAC,QAAQ;gBAA5C,MAAM,EAAE,SAAS,EAAmB,QAAQ,EAAE,cAAc;IAEnF,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC;IAmC7E,aAAa,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC;CAoB7F;AAED,wBAAgB,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAEhE"}
|
package/dist/services.js
ADDED
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
import { CacheManager } from './cache.js';
|
|
2
|
+
import { CbmClient, INDEX_TIMEOUT_MS } from './client.js';
|
|
3
|
+
const activeIndexes = new Map();
|
|
4
|
+
export class ProjectService {
|
|
5
|
+
runtime;
|
|
6
|
+
client;
|
|
7
|
+
#cache;
|
|
8
|
+
#project;
|
|
9
|
+
constructor(runtime, client, maxCacheBytes, telemetry) {
|
|
10
|
+
this.runtime = runtime;
|
|
11
|
+
this.client = client;
|
|
12
|
+
this.#cache = new CacheManager(runtime, maxCacheBytes, telemetry, async (project) => {
|
|
13
|
+
await client.call('delete_project', { project }).catch(() => { });
|
|
14
|
+
}, () => this.#cacheSize());
|
|
15
|
+
}
|
|
16
|
+
async gitRoot(signal, timeout = 10_000) {
|
|
17
|
+
const result = await this.runtime.exec('git', ['rev-parse', '--show-toplevel'], {
|
|
18
|
+
cwd: this.runtime.cwd,
|
|
19
|
+
maxOutputBytes: 64 * 1024,
|
|
20
|
+
...(signal === undefined ? {} : { signal }),
|
|
21
|
+
timeout,
|
|
22
|
+
});
|
|
23
|
+
return result.code === 0 && !result.killed ? result.stdout.trim() || this.runtime.cwd : this.runtime.cwd;
|
|
24
|
+
}
|
|
25
|
+
async index(signal) {
|
|
26
|
+
const root = await this.gitRoot(signal);
|
|
27
|
+
const key = `${this.client.cacheRoot}\u0000${root}`;
|
|
28
|
+
const existing = activeIndexes.get(key);
|
|
29
|
+
if (existing)
|
|
30
|
+
return existing;
|
|
31
|
+
const request = this.client.call('index_repository', { repo_path: root, mode: 'full' }, {
|
|
32
|
+
...(signal === undefined ? {} : { signal }),
|
|
33
|
+
timeoutMs: INDEX_TIMEOUT_MS,
|
|
34
|
+
}).then(async ({ data }) => {
|
|
35
|
+
const record = asRecord(data);
|
|
36
|
+
const project = typeof record.project === 'string' ? record.project : projectName(root);
|
|
37
|
+
this.#project = project;
|
|
38
|
+
await this.#cache.record(project, 0);
|
|
39
|
+
return data;
|
|
40
|
+
}).finally(() => { activeIndexes.delete(key); });
|
|
41
|
+
activeIndexes.set(key, request);
|
|
42
|
+
return request;
|
|
43
|
+
}
|
|
44
|
+
async #cacheSize() {
|
|
45
|
+
try {
|
|
46
|
+
const listed = await this.client.call('list_projects', {});
|
|
47
|
+
const projects = arrayProperty(listed.data, 'projects');
|
|
48
|
+
return projects.reduce((sum, project) => {
|
|
49
|
+
const bytes = asRecord(project).size_bytes;
|
|
50
|
+
return typeof bytes === 'number' && Number.isFinite(bytes) ? sum + bytes : sum;
|
|
51
|
+
}, 0);
|
|
52
|
+
}
|
|
53
|
+
catch {
|
|
54
|
+
return this.#cache.maxBytes + 1;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
async project(signal, timeoutMs) {
|
|
58
|
+
if (this.#project)
|
|
59
|
+
return this.#project;
|
|
60
|
+
const root = await this.gitRoot(signal, timeoutMs);
|
|
61
|
+
const listed = await this.client.call('list_projects', {}, {
|
|
62
|
+
...(signal === undefined ? {} : { signal }),
|
|
63
|
+
...(timeoutMs === undefined ? {} : { timeoutMs }),
|
|
64
|
+
});
|
|
65
|
+
const projects = Array.isArray(asRecord(listed.data).projects) ? asRecord(listed.data).projects : [];
|
|
66
|
+
const match = projects.map(asRecord).find((candidate) => candidate.root_path === root);
|
|
67
|
+
this.#project = typeof match?.name === 'string' ? match.name : projectName(root);
|
|
68
|
+
return this.#project;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
export class SymbolService {
|
|
72
|
+
client;
|
|
73
|
+
projects;
|
|
74
|
+
constructor(client, projects) {
|
|
75
|
+
this.client = client;
|
|
76
|
+
this.projects = projects;
|
|
77
|
+
}
|
|
78
|
+
async read(params, signal) {
|
|
79
|
+
const project = await this.projects.project(signal);
|
|
80
|
+
const search = await this.client.call('search_graph', {
|
|
81
|
+
project,
|
|
82
|
+
...(params.qualified_name === undefined
|
|
83
|
+
? { query: params.name }
|
|
84
|
+
: { qn_pattern: params.qualified_name }),
|
|
85
|
+
format: 'json',
|
|
86
|
+
limit: 10,
|
|
87
|
+
}, signal === undefined ? {} : { signal });
|
|
88
|
+
const candidates = searchCandidates(search.data);
|
|
89
|
+
const matches = candidates.filter((item) => {
|
|
90
|
+
const candidate = asRecord(item);
|
|
91
|
+
const qualifiedName = typeof candidate.qualified_name === 'string' ? candidate.qualified_name : '';
|
|
92
|
+
const requestedName = typeof params.name === 'string' ? params.name : undefined;
|
|
93
|
+
return (!requestedName
|
|
94
|
+
|| candidate.name === requestedName
|
|
95
|
+
|| qualifiedName.split('.').at(-1) === requestedName)
|
|
96
|
+
&& (!params.qualified_name || qualifiedName === params.qualified_name)
|
|
97
|
+
&& (!params.file_path || String(candidate.file_path ?? '').includes(String(params.file_path)));
|
|
98
|
+
});
|
|
99
|
+
if (matches.length > 1) {
|
|
100
|
+
return {
|
|
101
|
+
project,
|
|
102
|
+
candidates: matches,
|
|
103
|
+
error: 'Symbol lookup is ambiguous; retry with qualified_name or file_path.',
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
const selected = matches[0];
|
|
107
|
+
const qualifiedName = asRecord(selected).qualified_name;
|
|
108
|
+
if (typeof qualifiedName !== 'string')
|
|
109
|
+
return { project, candidates, error: 'No matching symbol found' };
|
|
110
|
+
const snippet = await this.client.call('get_code_snippet', { project, qualified_name: qualifiedName }, signal === undefined ? {} : { signal });
|
|
111
|
+
return { project, symbol: selected, snippet: boundSnippet(snippet.data, params.max_symbol_lines) };
|
|
112
|
+
}
|
|
113
|
+
async searchAndRead(params, signal) {
|
|
114
|
+
const project = await this.projects.project(signal);
|
|
115
|
+
const search = await this.client.call('search_graph', {
|
|
116
|
+
project,
|
|
117
|
+
query: params.query,
|
|
118
|
+
file_pattern: params.file_pattern,
|
|
119
|
+
limit: params.limit ?? 20,
|
|
120
|
+
format: 'json',
|
|
121
|
+
}, signal === undefined ? {} : { signal });
|
|
122
|
+
const candidates = searchCandidates(search.data);
|
|
123
|
+
const readLimit = clampInt(params.read_limit, 1, 12, 6);
|
|
124
|
+
const symbols = [];
|
|
125
|
+
for (const candidate of candidates.slice(0, readLimit)) {
|
|
126
|
+
const qualifiedName = asRecord(candidate).qualified_name;
|
|
127
|
+
if (typeof qualifiedName !== 'string')
|
|
128
|
+
continue;
|
|
129
|
+
const snippet = await this.client.call('get_code_snippet', { project, qualified_name: qualifiedName }, signal === undefined ? {} : { signal });
|
|
130
|
+
symbols.push({ symbol: candidate, snippet: boundSnippet(snippet.data, params.max_symbol_lines) });
|
|
131
|
+
}
|
|
132
|
+
return { project, candidates, symbols };
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
export function asRecord(value) {
|
|
136
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value) ? value : {};
|
|
137
|
+
}
|
|
138
|
+
function arrayProperty(value, key) {
|
|
139
|
+
const candidate = asRecord(value)[key];
|
|
140
|
+
return Array.isArray(candidate) ? candidate : [];
|
|
141
|
+
}
|
|
142
|
+
function searchCandidates(value) {
|
|
143
|
+
const results = arrayProperty(value, 'results');
|
|
144
|
+
if (results.length > 0)
|
|
145
|
+
return results;
|
|
146
|
+
const record = asRecord(value);
|
|
147
|
+
if (!Array.isArray(record.cols) || !Array.isArray(record.rows))
|
|
148
|
+
return [];
|
|
149
|
+
const columns = record.cols.filter((column) => typeof column === 'string');
|
|
150
|
+
return record.rows.filter(Array.isArray).map((row) => Object.fromEntries(columns.map((column, index) => [column === 'qn' ? 'qualified_name' : column, row[index]])));
|
|
151
|
+
}
|
|
152
|
+
function projectName(path) {
|
|
153
|
+
return path.replaceAll('\\', '/').split('/').filter(Boolean).at(-1)?.replace(/[^A-Za-z0-9._-]/gu, '-') || 'project';
|
|
154
|
+
}
|
|
155
|
+
function clampInt(value, min, max, fallback) {
|
|
156
|
+
return typeof value === 'number' && Number.isSafeInteger(value) ? Math.max(min, Math.min(max, value)) : fallback;
|
|
157
|
+
}
|
|
158
|
+
function boundSnippet(value, requestedLines) {
|
|
159
|
+
const maxLines = clampInt(requestedLines, 1, 220, 220);
|
|
160
|
+
if (typeof value === 'string')
|
|
161
|
+
return boundText(value, maxLines);
|
|
162
|
+
const record = asRecord(value);
|
|
163
|
+
for (const field of ['code', 'source', 'snippet']) {
|
|
164
|
+
if (typeof record[field] !== 'string')
|
|
165
|
+
continue;
|
|
166
|
+
const bounded = boundText(record[field], maxLines);
|
|
167
|
+
if (typeof bounded === 'string')
|
|
168
|
+
return value;
|
|
169
|
+
return { ...record, [field]: bounded.text, truncated: true, original_lines: bounded.originalLines };
|
|
170
|
+
}
|
|
171
|
+
return value;
|
|
172
|
+
}
|
|
173
|
+
function boundText(value, maxLines) {
|
|
174
|
+
const lines = value.split(/\r?\n/u);
|
|
175
|
+
if (lines.length <= maxLines)
|
|
176
|
+
return value;
|
|
177
|
+
return { text: lines.slice(0, maxLines).join('\n'), originalLines: lines.length };
|
|
178
|
+
}
|
|
179
|
+
//# sourceMappingURL=services.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"services.js","sourceRoot":"","sources":["../src/services.ts"],"names":[],"mappings":"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"}
|
package/dist/tools.d.ts
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { FelanExtensionAPI } from '@felan-ai/agent-core';
|
|
2
|
+
import type { CbmClient } from './client.js';
|
|
3
|
+
import type { ProjectService, SymbolService } from './services.js';
|
|
4
|
+
export declare function registerTools(pi: FelanExtensionAPI, client: CbmClient, projects: ProjectService, symbols: SymbolService): void;
|
|
5
|
+
//# sourceMappingURL=tools.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAkB,MAAM,sBAAsB,CAAC;AAE9E,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,KAAK,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAgBnE,wBAAgB,aAAa,CAC3B,EAAE,EAAE,iBAAiB,EACrB,MAAM,EAAE,SAAS,EACjB,QAAQ,EAAE,cAAc,EACxB,OAAO,EAAE,aAAa,GACrB,IAAI,CA2EN"}
|
package/dist/tools.js
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { Type } from 'typebox';
|
|
2
|
+
const MaxSymbolLines = Type.Optional(Type.Integer({ minimum: 1, maximum: 220, default: 220 }));
|
|
3
|
+
const ProxyCommand = Type.Union([
|
|
4
|
+
Type.Literal('index_repository'),
|
|
5
|
+
Type.Literal('search_graph'),
|
|
6
|
+
Type.Literal('query_graph'),
|
|
7
|
+
Type.Literal('trace_path'),
|
|
8
|
+
Type.Literal('get_graph_schema'),
|
|
9
|
+
Type.Literal('get_architecture'),
|
|
10
|
+
Type.Literal('index_status'),
|
|
11
|
+
Type.Literal('check_index_coverage'),
|
|
12
|
+
Type.Literal('detect_changes'),
|
|
13
|
+
]);
|
|
14
|
+
const PROXY_COMMANDS = new Set(ProxyCommand.anyOf.map((entry) => entry.const));
|
|
15
|
+
export function registerTools(pi, client, projects, symbols) {
|
|
16
|
+
const tools = [
|
|
17
|
+
{
|
|
18
|
+
name: 'codebase_memory',
|
|
19
|
+
label: 'codebase_memory',
|
|
20
|
+
description: 'Proxy a Codebase Memory structural query or explicitly refresh the current repository with command index_repository.',
|
|
21
|
+
promptSnippet: 'Structural code query or explicit repository index refresh',
|
|
22
|
+
parameters: Type.Object({
|
|
23
|
+
command: ProxyCommand,
|
|
24
|
+
arguments: Type.Optional(Type.Record(Type.String(), Type.Unknown())),
|
|
25
|
+
}, { additionalProperties: false }),
|
|
26
|
+
execute: async (_id, params, signal) => {
|
|
27
|
+
const input = params;
|
|
28
|
+
if (!PROXY_COMMANDS.has(input.command)) {
|
|
29
|
+
throw new Error(`Unsupported Codebase Memory command: ${input.command}`);
|
|
30
|
+
}
|
|
31
|
+
const args = input.arguments ?? {};
|
|
32
|
+
const data = input.command === 'index_repository'
|
|
33
|
+
? await projects.index(signal)
|
|
34
|
+
: (await client.call(input.command, {
|
|
35
|
+
...args,
|
|
36
|
+
project: await projects.project(signal),
|
|
37
|
+
}, signal === undefined ? {} : { signal })).data;
|
|
38
|
+
return toolResult(data);
|
|
39
|
+
},
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
name: 'read_symbol',
|
|
43
|
+
label: 'read_symbol',
|
|
44
|
+
description: 'Resolve and read one function, method, class, type, route, or other named symbol.',
|
|
45
|
+
promptSnippet: 'Resolve and read a named code symbol',
|
|
46
|
+
parameters: Type.Object({
|
|
47
|
+
name: Type.Optional(Type.String()),
|
|
48
|
+
qualified_name: Type.Optional(Type.String()),
|
|
49
|
+
file_path: Type.Optional(Type.String()),
|
|
50
|
+
max_symbol_lines: MaxSymbolLines,
|
|
51
|
+
}, { additionalProperties: false }),
|
|
52
|
+
execute: async (_id, params, signal) => toolResult(await symbols.read(params, signal)),
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
name: 'search_and_read_symbols',
|
|
56
|
+
label: 'search_and_read_symbols',
|
|
57
|
+
description: 'Find likely symbols and return focused source for the best matches.',
|
|
58
|
+
promptSnippet: 'Search for symbols and read the best matches',
|
|
59
|
+
parameters: Type.Object({
|
|
60
|
+
query: Type.String(),
|
|
61
|
+
file_pattern: Type.Optional(Type.String()),
|
|
62
|
+
limit: Type.Optional(Type.Integer({ minimum: 1, maximum: 50, default: 20 })),
|
|
63
|
+
read_limit: Type.Optional(Type.Integer({ minimum: 1, maximum: 12, default: 6 })),
|
|
64
|
+
max_symbol_lines: MaxSymbolLines,
|
|
65
|
+
}, { additionalProperties: false }),
|
|
66
|
+
execute: async (_id, params, signal) => toolResult(await symbols.searchAndRead(params, signal)),
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
name: 'search_code',
|
|
70
|
+
label: 'search_code',
|
|
71
|
+
description: 'Search indexed code for literal or regular-expression text with graph-aware context.',
|
|
72
|
+
promptSnippet: 'Search indexed source text',
|
|
73
|
+
parameters: Type.Object({
|
|
74
|
+
pattern: Type.String(),
|
|
75
|
+
file_pattern: Type.Optional(Type.String()),
|
|
76
|
+
path_filter: Type.Optional(Type.String()),
|
|
77
|
+
regex: Type.Optional(Type.Boolean()),
|
|
78
|
+
context: Type.Optional(Type.Integer({ minimum: 0, maximum: 20, default: 2 })),
|
|
79
|
+
limit: Type.Optional(Type.Integer({ minimum: 1, maximum: 100, default: 20 })),
|
|
80
|
+
max_symbol_lines: MaxSymbolLines,
|
|
81
|
+
}, { additionalProperties: false }),
|
|
82
|
+
execute: async (_id, params, signal) => {
|
|
83
|
+
const input = params;
|
|
84
|
+
const project = await projects.project(signal);
|
|
85
|
+
return toolResult((await client.call('search_code', { ...input, project }, signal === undefined ? {} : { signal })).data);
|
|
86
|
+
},
|
|
87
|
+
},
|
|
88
|
+
];
|
|
89
|
+
for (const tool of tools)
|
|
90
|
+
pi.registerTool(tool);
|
|
91
|
+
}
|
|
92
|
+
function toolResult(data) {
|
|
93
|
+
return {
|
|
94
|
+
content: [{ type: 'text', text: typeof data === 'string' ? data : JSON.stringify(data, null, 2) }],
|
|
95
|
+
details: { data },
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
//# sourceMappingURL=tools.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tools.js","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAI/B,MAAM,cAAc,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC;AAC/F,MAAM,YAAY,GAAG,IAAI,CAAC,KAAK,CAAC;IAC9B,IAAI,CAAC,OAAO,CAAC,kBAAkB,CAAC;IAChC,IAAI,CAAC,OAAO,CAAC,cAAc,CAAC;IAC5B,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC;IAC3B,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC;IAC1B,IAAI,CAAC,OAAO,CAAC,kBAAkB,CAAC;IAChC,IAAI,CAAC,OAAO,CAAC,kBAAkB,CAAC;IAChC,IAAI,CAAC,OAAO,CAAC,cAAc,CAAC;IAC5B,IAAI,CAAC,OAAO,CAAC,sBAAsB,CAAC;IACpC,IAAI,CAAC,OAAO,CAAC,gBAAgB,CAAC;CAC/B,CAAC,CAAC;AACH,MAAM,cAAc,GAAwB,IAAI,GAAG,CAAC,YAAY,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC;AAEpG,MAAM,UAAU,aAAa,CAC3B,EAAqB,EACrB,MAAiB,EACjB,QAAwB,EACxB,OAAsB;IAEtB,MAAM,KAAK,GAAqB;QAC9B;YACE,IAAI,EAAE,iBAAiB;YACvB,KAAK,EAAE,iBAAiB;YACxB,WAAW,EAAE,sHAAsH;YACnI,aAAa,EAAE,4DAA4D;YAC3E,UAAU,EAAE,IAAI,CAAC,MAAM,CAAC;gBACtB,OAAO,EAAE,YAAY;gBACrB,SAAS,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;aACrE,EAAE,EAAE,oBAAoB,EAAE,KAAK,EAAE,CAAC;YACnC,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE;gBACrC,MAAM,KAAK,GAAG,MAAkE,CAAC;gBACjF,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC;oBACvC,MAAM,IAAI,KAAK,CAAC,wCAAwC,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;gBAC3E,CAAC;gBACD,MAAM,IAAI,GAAG,KAAK,CAAC,SAAS,IAAI,EAAE,CAAC;gBACnC,MAAM,IAAI,GAAG,KAAK,CAAC,OAAO,KAAK,kBAAkB;oBAC/C,CAAC,CAAC,MAAM,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC;oBAC9B,CAAC,CAAC,CAAC,MAAM,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE;wBAClC,GAAG,IAAI;wBACP,OAAO,EAAE,MAAM,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC;qBACxC,EAAE,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;gBACnD,OAAO,UAAU,CAAC,IAAI,CAAC,CAAC;YAC1B,CAAC;SACF;QACD;YACE,IAAI,EAAE,aAAa;YACnB,KAAK,EAAE,aAAa;YACpB,WAAW,EAAE,mFAAmF;YAChG,aAAa,EAAE,sCAAsC;YACrD,UAAU,EAAE,IAAI,CAAC,MAAM,CAAC;gBACtB,IAAI,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;gBAClC,cAAc,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;gBAC5C,SAAS,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;gBACvC,gBAAgB,EAAE,cAAc;aACjC,EAAE,EAAE,oBAAoB,EAAE,KAAK,EAAE,CAAC;YACnC,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,CAAC,UAAU,CAAC,MAAM,OAAO,CAAC,IAAI,CAAC,MAAiC,EAAE,MAAM,CAAC,CAAC;SAClH;QACD;YACE,IAAI,EAAE,yBAAyB;YAC/B,KAAK,EAAE,yBAAyB;YAChC,WAAW,EAAE,qEAAqE;YAClF,aAAa,EAAE,8CAA8C;YAC7D,UAAU,EAAE,IAAI,CAAC,MAAM,CAAC;gBACtB,KAAK,EAAE,IAAI,CAAC,MAAM,EAAE;gBACpB,YAAY,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;gBAC1C,KAAK,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,CAAC;gBAC5E,UAAU,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC,CAAC;gBAChF,gBAAgB,EAAE,cAAc;aACjC,EAAE,EAAE,oBAAoB,EAAE,KAAK,EAAE,CAAC;YACnC,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,CAAC,UAAU,CAAC,MAAM,OAAO,CAAC,aAAa,CAAC,MAAiC,EAAE,MAAM,CAAC,CAAC;SAC3H;QACD;YACE,IAAI,EAAE,aAAa;YACnB,KAAK,EAAE,aAAa;YACpB,WAAW,EAAE,sFAAsF;YACnG,aAAa,EAAE,4BAA4B;YAC3C,UAAU,EAAE,IAAI,CAAC,MAAM,CAAC;gBACtB,OAAO,EAAE,IAAI,CAAC,MAAM,EAAE;gBACtB,YAAY,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;gBAC1C,WAAW,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;gBACzC,KAAK,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;gBACpC,OAAO,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC,CAAC;gBAC7E,KAAK,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,CAAC;gBAC7E,gBAAgB,EAAE,cAAc;aACjC,EAAE,EAAE,oBAAoB,EAAE,KAAK,EAAE,CAAC;YACnC,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE;gBACrC,MAAM,KAAK,GAAG,MAAiC,CAAC;gBAChD,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;gBAC/C,OAAO,UAAU,CAAC,CAAC,MAAM,MAAM,CAAC,IAAI,CAAC,aAAa,EAAE,EAAE,GAAG,KAAK,EAAE,OAAO,EAAE,EAAE,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;YAC5H,CAAC;SACF;KACF,CAAC;IACF,KAAK,MAAM,IAAI,IAAI,KAAK;QAAE,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;AAClD,CAAC;AAED,SAAS,UAAU,CAAC,IAAa;IAC/B,OAAO;QACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC;QAC3G,OAAO,EAAE,EAAE,IAAI,EAAE;KAClB,CAAC;AACJ,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@felan-ai/ext-codebase-memory",
|
|
3
|
+
"version": "0.0.0",
|
|
4
|
+
"description": "Portable Codebase Memory tools and grep augmentation for Felan",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/felan-ai/felan.git",
|
|
10
|
+
"directory": "packages/ext-codebase-memory"
|
|
11
|
+
},
|
|
12
|
+
"engines": {
|
|
13
|
+
"node": ">=22.19.0"
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"dist",
|
|
17
|
+
"LICENSE",
|
|
18
|
+
"NOTICE",
|
|
19
|
+
"README.md"
|
|
20
|
+
],
|
|
21
|
+
"exports": {
|
|
22
|
+
".": {
|
|
23
|
+
"types": "./dist/index.d.ts",
|
|
24
|
+
"import": "./dist/index.js"
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
"dependencies": {
|
|
28
|
+
"typebox": "1.1.38"
|
|
29
|
+
},
|
|
30
|
+
"peerDependencies": {
|
|
31
|
+
"@felan-ai/agent-core": "^0.5.0"
|
|
32
|
+
},
|
|
33
|
+
"devDependencies": {
|
|
34
|
+
"@felan-ai/agent-core": "0.5.6"
|
|
35
|
+
},
|
|
36
|
+
"publishConfig": {
|
|
37
|
+
"access": "public",
|
|
38
|
+
"provenance": true
|
|
39
|
+
},
|
|
40
|
+
"scripts": {
|
|
41
|
+
"build": "rm -rf dist && tsc -p tsconfig.build.json",
|
|
42
|
+
"type-check": "tsc -p tsconfig.json --noEmit",
|
|
43
|
+
"test": "vitest run"
|
|
44
|
+
}
|
|
45
|
+
}
|