@hiveai/core 0.1.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/dist/index.d.ts +249 -0
- package/dist/index.js +462 -0
- package/dist/index.js.map +1 -0
- package/package.json +45 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 hAIve 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/dist/index.d.ts
ADDED
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
|
|
3
|
+
declare const MemoryScopeSchema: z.ZodEnum<["personal", "team", "module"]>;
|
|
4
|
+
declare const MemoryStatusSchema: z.ZodEnum<["draft", "proposed", "validated", "deprecated", "stale"]>;
|
|
5
|
+
declare const MemoryTypeSchema: z.ZodEnum<["convention", "decision", "gotcha", "architecture", "glossary"]>;
|
|
6
|
+
declare const AnchorSchema: z.ZodObject<{
|
|
7
|
+
commit: z.ZodOptional<z.ZodString>;
|
|
8
|
+
paths: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
|
|
9
|
+
symbols: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
|
|
10
|
+
}, "strip", z.ZodTypeAny, {
|
|
11
|
+
paths: string[];
|
|
12
|
+
symbols: string[];
|
|
13
|
+
commit?: string | undefined;
|
|
14
|
+
}, {
|
|
15
|
+
commit?: string | undefined;
|
|
16
|
+
paths?: string[] | undefined;
|
|
17
|
+
symbols?: string[] | undefined;
|
|
18
|
+
}>;
|
|
19
|
+
declare const MemoryFrontmatterSchema: z.ZodEffects<z.ZodObject<{
|
|
20
|
+
id: z.ZodString;
|
|
21
|
+
scope: z.ZodDefault<z.ZodEnum<["personal", "team", "module"]>>;
|
|
22
|
+
module: z.ZodOptional<z.ZodString>;
|
|
23
|
+
type: z.ZodEnum<["convention", "decision", "gotcha", "architecture", "glossary"]>;
|
|
24
|
+
status: z.ZodDefault<z.ZodEnum<["draft", "proposed", "validated", "deprecated", "stale"]>>;
|
|
25
|
+
anchor: z.ZodDefault<z.ZodObject<{
|
|
26
|
+
commit: z.ZodOptional<z.ZodString>;
|
|
27
|
+
paths: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
|
|
28
|
+
symbols: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
|
|
29
|
+
}, "strip", z.ZodTypeAny, {
|
|
30
|
+
paths: string[];
|
|
31
|
+
symbols: string[];
|
|
32
|
+
commit?: string | undefined;
|
|
33
|
+
}, {
|
|
34
|
+
commit?: string | undefined;
|
|
35
|
+
paths?: string[] | undefined;
|
|
36
|
+
symbols?: string[] | undefined;
|
|
37
|
+
}>>;
|
|
38
|
+
tags: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
|
|
39
|
+
domain: z.ZodOptional<z.ZodString>;
|
|
40
|
+
author: z.ZodOptional<z.ZodString>;
|
|
41
|
+
created_at: z.ZodPipeline<z.ZodEffects<z.ZodUnion<[z.ZodString, z.ZodDate]>, string, string | Date>, z.ZodString>;
|
|
42
|
+
expires_when: z.ZodDefault<z.ZodNullable<z.ZodString>>;
|
|
43
|
+
verified_at: z.ZodDefault<z.ZodNullable<z.ZodString>>;
|
|
44
|
+
stale_reason: z.ZodDefault<z.ZodNullable<z.ZodString>>;
|
|
45
|
+
}, "strip", z.ZodTypeAny, {
|
|
46
|
+
type: "convention" | "decision" | "gotcha" | "architecture" | "glossary";
|
|
47
|
+
status: "draft" | "proposed" | "validated" | "deprecated" | "stale";
|
|
48
|
+
id: string;
|
|
49
|
+
scope: "personal" | "team" | "module";
|
|
50
|
+
anchor: {
|
|
51
|
+
paths: string[];
|
|
52
|
+
symbols: string[];
|
|
53
|
+
commit?: string | undefined;
|
|
54
|
+
};
|
|
55
|
+
tags: string[];
|
|
56
|
+
created_at: string;
|
|
57
|
+
expires_when: string | null;
|
|
58
|
+
verified_at: string | null;
|
|
59
|
+
stale_reason: string | null;
|
|
60
|
+
module?: string | undefined;
|
|
61
|
+
domain?: string | undefined;
|
|
62
|
+
author?: string | undefined;
|
|
63
|
+
}, {
|
|
64
|
+
type: "convention" | "decision" | "gotcha" | "architecture" | "glossary";
|
|
65
|
+
id: string;
|
|
66
|
+
created_at: string | Date;
|
|
67
|
+
module?: string | undefined;
|
|
68
|
+
status?: "draft" | "proposed" | "validated" | "deprecated" | "stale" | undefined;
|
|
69
|
+
scope?: "personal" | "team" | "module" | undefined;
|
|
70
|
+
anchor?: {
|
|
71
|
+
commit?: string | undefined;
|
|
72
|
+
paths?: string[] | undefined;
|
|
73
|
+
symbols?: string[] | undefined;
|
|
74
|
+
} | undefined;
|
|
75
|
+
tags?: string[] | undefined;
|
|
76
|
+
domain?: string | undefined;
|
|
77
|
+
author?: string | undefined;
|
|
78
|
+
expires_when?: string | null | undefined;
|
|
79
|
+
verified_at?: string | null | undefined;
|
|
80
|
+
stale_reason?: string | null | undefined;
|
|
81
|
+
}>, {
|
|
82
|
+
type: "convention" | "decision" | "gotcha" | "architecture" | "glossary";
|
|
83
|
+
status: "draft" | "proposed" | "validated" | "deprecated" | "stale";
|
|
84
|
+
id: string;
|
|
85
|
+
scope: "personal" | "team" | "module";
|
|
86
|
+
anchor: {
|
|
87
|
+
paths: string[];
|
|
88
|
+
symbols: string[];
|
|
89
|
+
commit?: string | undefined;
|
|
90
|
+
};
|
|
91
|
+
tags: string[];
|
|
92
|
+
created_at: string;
|
|
93
|
+
expires_when: string | null;
|
|
94
|
+
verified_at: string | null;
|
|
95
|
+
stale_reason: string | null;
|
|
96
|
+
module?: string | undefined;
|
|
97
|
+
domain?: string | undefined;
|
|
98
|
+
author?: string | undefined;
|
|
99
|
+
}, {
|
|
100
|
+
type: "convention" | "decision" | "gotcha" | "architecture" | "glossary";
|
|
101
|
+
id: string;
|
|
102
|
+
created_at: string | Date;
|
|
103
|
+
module?: string | undefined;
|
|
104
|
+
status?: "draft" | "proposed" | "validated" | "deprecated" | "stale" | undefined;
|
|
105
|
+
scope?: "personal" | "team" | "module" | undefined;
|
|
106
|
+
anchor?: {
|
|
107
|
+
commit?: string | undefined;
|
|
108
|
+
paths?: string[] | undefined;
|
|
109
|
+
symbols?: string[] | undefined;
|
|
110
|
+
} | undefined;
|
|
111
|
+
tags?: string[] | undefined;
|
|
112
|
+
domain?: string | undefined;
|
|
113
|
+
author?: string | undefined;
|
|
114
|
+
expires_when?: string | null | undefined;
|
|
115
|
+
verified_at?: string | null | undefined;
|
|
116
|
+
stale_reason?: string | null | undefined;
|
|
117
|
+
}>;
|
|
118
|
+
|
|
119
|
+
type MemoryScope = z.infer<typeof MemoryScopeSchema>;
|
|
120
|
+
type MemoryStatus = z.infer<typeof MemoryStatusSchema>;
|
|
121
|
+
type MemoryType = z.infer<typeof MemoryTypeSchema>;
|
|
122
|
+
type Anchor = z.infer<typeof AnchorSchema>;
|
|
123
|
+
type MemoryFrontmatter = z.infer<typeof MemoryFrontmatterSchema>;
|
|
124
|
+
interface Memory {
|
|
125
|
+
frontmatter: MemoryFrontmatter;
|
|
126
|
+
body: string;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
declare function stripPrivate(body: string): string;
|
|
130
|
+
declare function parseMemory(raw: string): Memory;
|
|
131
|
+
declare function serializeMemory(memory: Memory): string;
|
|
132
|
+
declare function newMemoryId(type: string, slug: string, date?: Date): string;
|
|
133
|
+
declare function buildFrontmatter(input: {
|
|
134
|
+
type: MemoryFrontmatter["type"];
|
|
135
|
+
slug: string;
|
|
136
|
+
scope?: MemoryFrontmatter["scope"];
|
|
137
|
+
module?: string;
|
|
138
|
+
tags?: string[];
|
|
139
|
+
domain?: string;
|
|
140
|
+
author?: string;
|
|
141
|
+
paths?: string[];
|
|
142
|
+
symbols?: string[];
|
|
143
|
+
commit?: string;
|
|
144
|
+
}): MemoryFrontmatter;
|
|
145
|
+
|
|
146
|
+
declare const HAIVE_DIR = ".ai";
|
|
147
|
+
declare function findProjectRoot(startDir?: string): string;
|
|
148
|
+
declare const PROJECT_CONTEXT_FILE = "project-context.md";
|
|
149
|
+
declare const MEMORIES_DIR = "memories";
|
|
150
|
+
interface HaivePaths {
|
|
151
|
+
root: string;
|
|
152
|
+
haiveDir: string;
|
|
153
|
+
projectContext: string;
|
|
154
|
+
memoriesDir: string;
|
|
155
|
+
personalDir: string;
|
|
156
|
+
teamDir: string;
|
|
157
|
+
moduleDir: string;
|
|
158
|
+
modulesContextDir: string;
|
|
159
|
+
}
|
|
160
|
+
declare function resolveHaivePaths(projectRoot: string): HaivePaths;
|
|
161
|
+
declare function memoryFilePath(paths: HaivePaths, scope: "personal" | "team" | "module", id: string, module?: string): string;
|
|
162
|
+
|
|
163
|
+
interface LoadedMemory {
|
|
164
|
+
memory: Memory;
|
|
165
|
+
filePath: string;
|
|
166
|
+
}
|
|
167
|
+
declare function listMarkdownFilesRecursive(dir: string): Promise<string[]>;
|
|
168
|
+
declare function loadMemory(filePath: string): Promise<LoadedMemory>;
|
|
169
|
+
declare function loadMemoriesFromDir(dir: string): Promise<LoadedMemory[]>;
|
|
170
|
+
|
|
171
|
+
declare function tokenizeQuery(query: string): string[];
|
|
172
|
+
declare function literalMatchesAllTokens(memory: Memory, tokens: string[]): boolean;
|
|
173
|
+
declare function pickSnippetNeedle(query: string): string;
|
|
174
|
+
declare function extractSnippet(body: string, needle: string, radius?: number): string;
|
|
175
|
+
|
|
176
|
+
interface VerifyResult {
|
|
177
|
+
stale: boolean;
|
|
178
|
+
reason: string | null;
|
|
179
|
+
checkedPaths: string[];
|
|
180
|
+
checkedSymbols: string[];
|
|
181
|
+
}
|
|
182
|
+
interface VerifyOptions {
|
|
183
|
+
/** Project root used to resolve relative anchor paths. */
|
|
184
|
+
projectRoot: string;
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Verify that a memory's anchor still matches the current code.
|
|
188
|
+
* - Every anchor.paths entry must exist on disk
|
|
189
|
+
* - Every anchor.symbols entry must appear at least once across the anchor.paths
|
|
190
|
+
* files (or any tracked file if no paths are recorded)
|
|
191
|
+
*
|
|
192
|
+
* Anchorless memories (no paths and no symbols) are always considered fresh —
|
|
193
|
+
* staleness only applies to memories that opted into anchoring.
|
|
194
|
+
*/
|
|
195
|
+
declare function verifyAnchor(memory: Memory, options: VerifyOptions): Promise<VerifyResult>;
|
|
196
|
+
|
|
197
|
+
interface MemoryUsage {
|
|
198
|
+
read_count: number;
|
|
199
|
+
last_read_at: string | null;
|
|
200
|
+
rejected_count: number;
|
|
201
|
+
last_rejected_at: string | null;
|
|
202
|
+
rejection_reason: string | null;
|
|
203
|
+
}
|
|
204
|
+
interface UsageIndex {
|
|
205
|
+
version: 1;
|
|
206
|
+
updated_at: string;
|
|
207
|
+
by_id: Record<string, MemoryUsage>;
|
|
208
|
+
}
|
|
209
|
+
declare const USAGE_FILE = "usage.json";
|
|
210
|
+
declare function emptyUsage(): MemoryUsage;
|
|
211
|
+
declare function emptyUsageIndex(): UsageIndex;
|
|
212
|
+
declare function usagePath(paths: HaivePaths): string;
|
|
213
|
+
declare function loadUsageIndex(paths: HaivePaths): Promise<UsageIndex>;
|
|
214
|
+
declare function saveUsageIndex(paths: HaivePaths, index: UsageIndex): Promise<void>;
|
|
215
|
+
declare function getUsage(index: UsageIndex, id: string): MemoryUsage;
|
|
216
|
+
declare function bumpRead(index: UsageIndex, ids: string[]): UsageIndex;
|
|
217
|
+
declare function recordRejection(index: UsageIndex, id: string, reason: string | null): UsageIndex;
|
|
218
|
+
declare function trackReads(paths: HaivePaths, ids: string[]): Promise<UsageIndex>;
|
|
219
|
+
|
|
220
|
+
type ConfidenceLevel = "unverified" | "low" | "trusted" | "authoritative" | "stale";
|
|
221
|
+
interface ConfidenceThresholds {
|
|
222
|
+
trustedReads: number;
|
|
223
|
+
authoritativeReads: number;
|
|
224
|
+
}
|
|
225
|
+
declare const DEFAULT_CONFIDENCE_THRESHOLDS: ConfidenceThresholds;
|
|
226
|
+
declare function deriveConfidence(fm: MemoryFrontmatter, usage: MemoryUsage, thresholds?: ConfidenceThresholds): ConfidenceLevel;
|
|
227
|
+
interface AutoPromoteRule {
|
|
228
|
+
/** Minimum read_count to promote proposed → validated. */
|
|
229
|
+
minReads: number;
|
|
230
|
+
/** Maximum rejected_count tolerated (memories with more rejections never auto-promote). */
|
|
231
|
+
maxRejections: number;
|
|
232
|
+
}
|
|
233
|
+
declare const DEFAULT_AUTO_PROMOTE_RULE: AutoPromoteRule;
|
|
234
|
+
declare function isAutoPromoteEligible(fm: MemoryFrontmatter, usage: MemoryUsage, rule?: AutoPromoteRule): boolean;
|
|
235
|
+
|
|
236
|
+
/**
|
|
237
|
+
* Best-effort inference: given a list of file paths, infer module names from
|
|
238
|
+
* conventional layouts (packages/X/, apps/X/, modules/X/, src/X/).
|
|
239
|
+
*/
|
|
240
|
+
declare function inferModulesFromPaths(filePaths: string[]): string[];
|
|
241
|
+
/**
|
|
242
|
+
* Path overlap: returns true if `a` and `b` refer to the same path or one is a
|
|
243
|
+
* parent of the other. Both inputs are treated as POSIX-style relative paths.
|
|
244
|
+
*/
|
|
245
|
+
declare function pathsOverlap(a: string, b: string): boolean;
|
|
246
|
+
declare function memoryMatchesAnchorPaths(memory: LoadedMemory["memory"], inputPaths: string[]): boolean;
|
|
247
|
+
declare function relPathFrom(root: string, abs: string): string;
|
|
248
|
+
|
|
249
|
+
export { type Anchor, AnchorSchema, type AutoPromoteRule, type ConfidenceLevel, type ConfidenceThresholds, DEFAULT_AUTO_PROMOTE_RULE, DEFAULT_CONFIDENCE_THRESHOLDS, HAIVE_DIR, type HaivePaths, type LoadedMemory, MEMORIES_DIR, type Memory, type MemoryFrontmatter, MemoryFrontmatterSchema, type MemoryScope, MemoryScopeSchema, type MemoryStatus, MemoryStatusSchema, type MemoryType, MemoryTypeSchema, type MemoryUsage, PROJECT_CONTEXT_FILE, USAGE_FILE, type UsageIndex, type VerifyOptions, type VerifyResult, buildFrontmatter, bumpRead, deriveConfidence, emptyUsage, emptyUsageIndex, extractSnippet, findProjectRoot, getUsage, inferModulesFromPaths, isAutoPromoteEligible, listMarkdownFilesRecursive, literalMatchesAllTokens, loadMemoriesFromDir, loadMemory, loadUsageIndex, memoryFilePath, memoryMatchesAnchorPaths, newMemoryId, parseMemory, pathsOverlap, pickSnippetNeedle, recordRejection, relPathFrom, resolveHaivePaths, saveUsageIndex, serializeMemory, stripPrivate, tokenizeQuery, trackReads, usagePath, verifyAnchor };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,462 @@
|
|
|
1
|
+
// src/schema.ts
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
var MemoryScopeSchema = z.enum(["personal", "team", "module"]);
|
|
4
|
+
var MemoryStatusSchema = z.enum([
|
|
5
|
+
"draft",
|
|
6
|
+
"proposed",
|
|
7
|
+
"validated",
|
|
8
|
+
"deprecated",
|
|
9
|
+
"stale"
|
|
10
|
+
]);
|
|
11
|
+
var MemoryTypeSchema = z.enum([
|
|
12
|
+
"convention",
|
|
13
|
+
"decision",
|
|
14
|
+
"gotcha",
|
|
15
|
+
"architecture",
|
|
16
|
+
"glossary"
|
|
17
|
+
]);
|
|
18
|
+
var AnchorSchema = z.object({
|
|
19
|
+
commit: z.string().optional(),
|
|
20
|
+
paths: z.array(z.string()).default([]),
|
|
21
|
+
symbols: z.array(z.string()).default([])
|
|
22
|
+
});
|
|
23
|
+
var IsoDateString = z.union([z.string(), z.date()]).transform((v) => v instanceof Date ? v.toISOString() : v).pipe(z.string().datetime());
|
|
24
|
+
var MemoryFrontmatterSchema = z.object({
|
|
25
|
+
id: z.string().min(1),
|
|
26
|
+
scope: MemoryScopeSchema.default("personal"),
|
|
27
|
+
module: z.string().optional(),
|
|
28
|
+
type: MemoryTypeSchema,
|
|
29
|
+
status: MemoryStatusSchema.default("draft"),
|
|
30
|
+
anchor: AnchorSchema.default({ paths: [], symbols: [] }),
|
|
31
|
+
tags: z.array(z.string()).default([]),
|
|
32
|
+
domain: z.string().optional(),
|
|
33
|
+
author: z.string().optional(),
|
|
34
|
+
created_at: IsoDateString,
|
|
35
|
+
expires_when: z.string().nullable().default(null),
|
|
36
|
+
verified_at: z.string().nullable().default(null),
|
|
37
|
+
stale_reason: z.string().nullable().default(null)
|
|
38
|
+
}).refine(
|
|
39
|
+
(data) => data.scope !== "module" || !!data.module,
|
|
40
|
+
{ message: "module name is required when scope is 'module'", path: ["module"] }
|
|
41
|
+
);
|
|
42
|
+
|
|
43
|
+
// src/parser.ts
|
|
44
|
+
import matter from "gray-matter";
|
|
45
|
+
var PRIVATE_BLOCK_RE = /<private>[\s\S]*?<\/private>/g;
|
|
46
|
+
function stripPrivate(body) {
|
|
47
|
+
return body.replace(PRIVATE_BLOCK_RE, "").trimEnd();
|
|
48
|
+
}
|
|
49
|
+
function parseMemory(raw) {
|
|
50
|
+
const parsed = matter(raw);
|
|
51
|
+
const frontmatter = MemoryFrontmatterSchema.parse(parsed.data);
|
|
52
|
+
return {
|
|
53
|
+
frontmatter,
|
|
54
|
+
body: stripPrivate(parsed.content.trim())
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
function stripUndefined(value) {
|
|
58
|
+
if (Array.isArray(value)) {
|
|
59
|
+
return value.map((v) => stripUndefined(v));
|
|
60
|
+
}
|
|
61
|
+
if (value && typeof value === "object") {
|
|
62
|
+
const out = {};
|
|
63
|
+
for (const [k, v] of Object.entries(value)) {
|
|
64
|
+
if (v === void 0) continue;
|
|
65
|
+
out[k] = stripUndefined(v);
|
|
66
|
+
}
|
|
67
|
+
return out;
|
|
68
|
+
}
|
|
69
|
+
return value;
|
|
70
|
+
}
|
|
71
|
+
function serializeMemory(memory) {
|
|
72
|
+
const clean = stripUndefined(memory.frontmatter);
|
|
73
|
+
return matter.stringify(memory.body, clean);
|
|
74
|
+
}
|
|
75
|
+
function newMemoryId(type, slug, date = /* @__PURE__ */ new Date()) {
|
|
76
|
+
const isoDate = date.toISOString().slice(0, 10);
|
|
77
|
+
const safeSlug = slug.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "").slice(0, 60);
|
|
78
|
+
return `${isoDate}-${type}-${safeSlug}`;
|
|
79
|
+
}
|
|
80
|
+
function buildFrontmatter(input) {
|
|
81
|
+
const now = /* @__PURE__ */ new Date();
|
|
82
|
+
const id = newMemoryId(input.type, input.slug, now);
|
|
83
|
+
return MemoryFrontmatterSchema.parse({
|
|
84
|
+
id,
|
|
85
|
+
scope: input.scope ?? "personal",
|
|
86
|
+
module: input.module,
|
|
87
|
+
type: input.type,
|
|
88
|
+
status: "draft",
|
|
89
|
+
anchor: {
|
|
90
|
+
commit: input.commit,
|
|
91
|
+
paths: input.paths ?? [],
|
|
92
|
+
symbols: input.symbols ?? []
|
|
93
|
+
},
|
|
94
|
+
tags: input.tags ?? [],
|
|
95
|
+
domain: input.domain,
|
|
96
|
+
author: input.author,
|
|
97
|
+
created_at: now.toISOString(),
|
|
98
|
+
expires_when: null
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// src/paths.ts
|
|
103
|
+
import { existsSync } from "fs";
|
|
104
|
+
import path from "path";
|
|
105
|
+
var HAIVE_DIR = ".ai";
|
|
106
|
+
var ROOT_MARKERS = [".ai", ".git", "package.json"];
|
|
107
|
+
function findProjectRoot(startDir = process.cwd()) {
|
|
108
|
+
let current = path.resolve(startDir);
|
|
109
|
+
const fsRoot = path.parse(current).root;
|
|
110
|
+
while (current !== fsRoot) {
|
|
111
|
+
for (const marker of ROOT_MARKERS) {
|
|
112
|
+
if (existsSync(path.join(current, marker))) return current;
|
|
113
|
+
}
|
|
114
|
+
current = path.dirname(current);
|
|
115
|
+
}
|
|
116
|
+
return path.resolve(startDir);
|
|
117
|
+
}
|
|
118
|
+
var PROJECT_CONTEXT_FILE = "project-context.md";
|
|
119
|
+
var MEMORIES_DIR = "memories";
|
|
120
|
+
function resolveHaivePaths(projectRoot) {
|
|
121
|
+
const haiveDir = path.join(projectRoot, HAIVE_DIR);
|
|
122
|
+
const memoriesDir = path.join(haiveDir, MEMORIES_DIR);
|
|
123
|
+
return {
|
|
124
|
+
root: projectRoot,
|
|
125
|
+
haiveDir,
|
|
126
|
+
projectContext: path.join(haiveDir, PROJECT_CONTEXT_FILE),
|
|
127
|
+
memoriesDir,
|
|
128
|
+
personalDir: path.join(memoriesDir, "personal"),
|
|
129
|
+
teamDir: path.join(memoriesDir, "team"),
|
|
130
|
+
moduleDir: path.join(memoriesDir, "module"),
|
|
131
|
+
modulesContextDir: path.join(haiveDir, "modules")
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
function memoryFilePath(paths, scope, id, module) {
|
|
135
|
+
const base = scope === "personal" ? paths.personalDir : scope === "team" ? paths.teamDir : path.join(paths.moduleDir, module ?? "_unscoped");
|
|
136
|
+
return path.join(base, `${id}.md`);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// src/loader.ts
|
|
140
|
+
import { readdir, readFile } from "fs/promises";
|
|
141
|
+
import path2 from "path";
|
|
142
|
+
async function listMarkdownFilesRecursive(dir) {
|
|
143
|
+
const out = [];
|
|
144
|
+
let entries;
|
|
145
|
+
try {
|
|
146
|
+
entries = await readdir(dir, { withFileTypes: true });
|
|
147
|
+
} catch {
|
|
148
|
+
return out;
|
|
149
|
+
}
|
|
150
|
+
for (const entry of entries) {
|
|
151
|
+
const full = path2.join(dir, entry.name);
|
|
152
|
+
if (entry.isDirectory()) {
|
|
153
|
+
out.push(...await listMarkdownFilesRecursive(full));
|
|
154
|
+
} else if (entry.isFile() && entry.name.endsWith(".md")) {
|
|
155
|
+
out.push(full);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
return out;
|
|
159
|
+
}
|
|
160
|
+
async function loadMemory(filePath) {
|
|
161
|
+
const raw = await readFile(filePath, "utf8");
|
|
162
|
+
return { memory: parseMemory(raw), filePath };
|
|
163
|
+
}
|
|
164
|
+
async function loadMemoriesFromDir(dir) {
|
|
165
|
+
const files = await listMarkdownFilesRecursive(dir);
|
|
166
|
+
const out = [];
|
|
167
|
+
for (const file of files) {
|
|
168
|
+
try {
|
|
169
|
+
out.push(await loadMemory(file));
|
|
170
|
+
} catch {
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
return out;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// src/search.ts
|
|
177
|
+
function tokenizeQuery(query) {
|
|
178
|
+
return query.toLowerCase().split(/\s+/).map((t) => t.trim()).filter(Boolean);
|
|
179
|
+
}
|
|
180
|
+
function literalMatchesAllTokens(memory, tokens) {
|
|
181
|
+
if (tokens.length === 0) return true;
|
|
182
|
+
const fm = memory.frontmatter;
|
|
183
|
+
const idLower = fm.id.toLowerCase();
|
|
184
|
+
const tagsLower = fm.tags.map((t) => t.toLowerCase());
|
|
185
|
+
const bodyLower = memory.body.toLowerCase();
|
|
186
|
+
return tokens.every((rawTok) => {
|
|
187
|
+
const tok = rawTok.toLowerCase();
|
|
188
|
+
return idLower.includes(tok) || tagsLower.some((t) => t.includes(tok)) || bodyLower.includes(tok);
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
function pickSnippetNeedle(query) {
|
|
192
|
+
const tokens = tokenizeQuery(query);
|
|
193
|
+
if (tokens.length === 0) return query.toLowerCase();
|
|
194
|
+
return [...tokens].sort((a, b) => b.length - a.length)[0];
|
|
195
|
+
}
|
|
196
|
+
function extractSnippet(body, needle, radius = 40) {
|
|
197
|
+
const lower = body.toLowerCase();
|
|
198
|
+
const idx = needle ? lower.indexOf(needle) : -1;
|
|
199
|
+
if (idx < 0) {
|
|
200
|
+
return body.slice(0, radius * 3).replace(/\s+/g, " ").trim();
|
|
201
|
+
}
|
|
202
|
+
const start = Math.max(0, idx - radius);
|
|
203
|
+
const end = Math.min(body.length, idx + needle.length + radius);
|
|
204
|
+
const snippet = body.slice(start, end).replace(/\s+/g, " ").trim();
|
|
205
|
+
return (start > 0 ? "\u2026" : "") + snippet + (end < body.length ? "\u2026" : "");
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
// src/verifier.ts
|
|
209
|
+
import { readFile as readFile2 } from "fs/promises";
|
|
210
|
+
import { existsSync as existsSync2 } from "fs";
|
|
211
|
+
import path3 from "path";
|
|
212
|
+
async function verifyAnchor(memory, options) {
|
|
213
|
+
const anchor = memory.frontmatter.anchor;
|
|
214
|
+
const checkedPaths = anchor.paths;
|
|
215
|
+
const checkedSymbols = anchor.symbols;
|
|
216
|
+
if (checkedPaths.length === 0 && checkedSymbols.length === 0) {
|
|
217
|
+
return { stale: false, reason: null, checkedPaths, checkedSymbols };
|
|
218
|
+
}
|
|
219
|
+
const missingPaths = [];
|
|
220
|
+
const existingAbsPaths = [];
|
|
221
|
+
for (const rel of checkedPaths) {
|
|
222
|
+
const abs = path3.isAbsolute(rel) ? rel : path3.join(options.projectRoot, rel);
|
|
223
|
+
if (existsSync2(abs)) {
|
|
224
|
+
existingAbsPaths.push(abs);
|
|
225
|
+
} else {
|
|
226
|
+
missingPaths.push(rel);
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
if (missingPaths.length > 0) {
|
|
230
|
+
return {
|
|
231
|
+
stale: true,
|
|
232
|
+
reason: `anchor path(s) no longer exist: ${missingPaths.join(", ")}`,
|
|
233
|
+
checkedPaths,
|
|
234
|
+
checkedSymbols
|
|
235
|
+
};
|
|
236
|
+
}
|
|
237
|
+
if (checkedSymbols.length > 0) {
|
|
238
|
+
if (existingAbsPaths.length === 0) {
|
|
239
|
+
return {
|
|
240
|
+
stale: true,
|
|
241
|
+
reason: `cannot verify symbols (${checkedSymbols.join(", ")}): no anchor paths recorded`,
|
|
242
|
+
checkedPaths,
|
|
243
|
+
checkedSymbols
|
|
244
|
+
};
|
|
245
|
+
}
|
|
246
|
+
const missingSymbols = [];
|
|
247
|
+
for (const sym of checkedSymbols) {
|
|
248
|
+
let found = false;
|
|
249
|
+
for (const file of existingAbsPaths) {
|
|
250
|
+
try {
|
|
251
|
+
const contents = await readFile2(file, "utf8");
|
|
252
|
+
if (contents.includes(sym)) {
|
|
253
|
+
found = true;
|
|
254
|
+
break;
|
|
255
|
+
}
|
|
256
|
+
} catch {
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
if (!found) missingSymbols.push(sym);
|
|
260
|
+
}
|
|
261
|
+
if (missingSymbols.length > 0) {
|
|
262
|
+
return {
|
|
263
|
+
stale: true,
|
|
264
|
+
reason: `anchor symbol(s) not found in any anchor path: ${missingSymbols.join(", ")}`,
|
|
265
|
+
checkedPaths,
|
|
266
|
+
checkedSymbols
|
|
267
|
+
};
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
return { stale: false, reason: null, checkedPaths, checkedSymbols };
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
// src/usage.ts
|
|
274
|
+
import { mkdir, readFile as readFile3, writeFile } from "fs/promises";
|
|
275
|
+
import { existsSync as existsSync3 } from "fs";
|
|
276
|
+
import path4 from "path";
|
|
277
|
+
var USAGE_FILE = "usage.json";
|
|
278
|
+
function emptyUsage() {
|
|
279
|
+
return {
|
|
280
|
+
read_count: 0,
|
|
281
|
+
last_read_at: null,
|
|
282
|
+
rejected_count: 0,
|
|
283
|
+
last_rejected_at: null,
|
|
284
|
+
rejection_reason: null
|
|
285
|
+
};
|
|
286
|
+
}
|
|
287
|
+
function emptyUsageIndex() {
|
|
288
|
+
return {
|
|
289
|
+
version: 1,
|
|
290
|
+
updated_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
291
|
+
by_id: {}
|
|
292
|
+
};
|
|
293
|
+
}
|
|
294
|
+
function usagePath(paths) {
|
|
295
|
+
return path4.join(paths.haiveDir, ".cache", USAGE_FILE);
|
|
296
|
+
}
|
|
297
|
+
async function loadUsageIndex(paths) {
|
|
298
|
+
const file = usagePath(paths);
|
|
299
|
+
if (!existsSync3(file)) return emptyUsageIndex();
|
|
300
|
+
const raw = await readFile3(file, "utf8");
|
|
301
|
+
try {
|
|
302
|
+
const parsed = JSON.parse(raw);
|
|
303
|
+
if (parsed.version !== 1) return emptyUsageIndex();
|
|
304
|
+
return parsed;
|
|
305
|
+
} catch {
|
|
306
|
+
return emptyUsageIndex();
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
async function saveUsageIndex(paths, index) {
|
|
310
|
+
const file = usagePath(paths);
|
|
311
|
+
await mkdir(path4.dirname(file), { recursive: true });
|
|
312
|
+
index.updated_at = (/* @__PURE__ */ new Date()).toISOString();
|
|
313
|
+
await writeFile(file, JSON.stringify(index, null, 2), "utf8");
|
|
314
|
+
}
|
|
315
|
+
function getUsage(index, id) {
|
|
316
|
+
return index.by_id[id] ?? emptyUsage();
|
|
317
|
+
}
|
|
318
|
+
function bumpRead(index, ids) {
|
|
319
|
+
if (ids.length === 0) return index;
|
|
320
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
321
|
+
for (const id of ids) {
|
|
322
|
+
const current = index.by_id[id] ?? emptyUsage();
|
|
323
|
+
index.by_id[id] = {
|
|
324
|
+
...current,
|
|
325
|
+
read_count: current.read_count + 1,
|
|
326
|
+
last_read_at: now
|
|
327
|
+
};
|
|
328
|
+
}
|
|
329
|
+
return index;
|
|
330
|
+
}
|
|
331
|
+
function recordRejection(index, id, reason) {
|
|
332
|
+
const current = index.by_id[id] ?? emptyUsage();
|
|
333
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
334
|
+
index.by_id[id] = {
|
|
335
|
+
...current,
|
|
336
|
+
rejected_count: current.rejected_count + 1,
|
|
337
|
+
last_rejected_at: now,
|
|
338
|
+
rejection_reason: reason
|
|
339
|
+
};
|
|
340
|
+
return index;
|
|
341
|
+
}
|
|
342
|
+
async function trackReads(paths, ids) {
|
|
343
|
+
if (ids.length === 0) {
|
|
344
|
+
return await loadUsageIndex(paths);
|
|
345
|
+
}
|
|
346
|
+
const index = await loadUsageIndex(paths);
|
|
347
|
+
bumpRead(index, ids);
|
|
348
|
+
await saveUsageIndex(paths, index);
|
|
349
|
+
return index;
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
// src/confidence.ts
|
|
353
|
+
var DEFAULT_CONFIDENCE_THRESHOLDS = {
|
|
354
|
+
trustedReads: 3,
|
|
355
|
+
authoritativeReads: 10
|
|
356
|
+
};
|
|
357
|
+
function deriveConfidence(fm, usage, thresholds = DEFAULT_CONFIDENCE_THRESHOLDS) {
|
|
358
|
+
if (fm.status === "stale" || fm.status === "deprecated") return "stale";
|
|
359
|
+
if (fm.status === "validated") {
|
|
360
|
+
return usage.read_count >= thresholds.authoritativeReads ? "authoritative" : "trusted";
|
|
361
|
+
}
|
|
362
|
+
if (fm.status === "proposed") {
|
|
363
|
+
return usage.read_count >= thresholds.trustedReads ? "trusted" : "low";
|
|
364
|
+
}
|
|
365
|
+
return "unverified";
|
|
366
|
+
}
|
|
367
|
+
var DEFAULT_AUTO_PROMOTE_RULE = {
|
|
368
|
+
minReads: 5,
|
|
369
|
+
maxRejections: 0
|
|
370
|
+
};
|
|
371
|
+
function isAutoPromoteEligible(fm, usage, rule = DEFAULT_AUTO_PROMOTE_RULE) {
|
|
372
|
+
if (fm.status !== "proposed") return false;
|
|
373
|
+
if (usage.rejected_count > rule.maxRejections) return false;
|
|
374
|
+
return usage.read_count >= rule.minReads;
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
// src/relevance.ts
|
|
378
|
+
import path5 from "path";
|
|
379
|
+
var MODULE_PATTERNS = [
|
|
380
|
+
/^packages\/([^/]+)\//,
|
|
381
|
+
/^apps\/([^/]+)\//,
|
|
382
|
+
/^modules\/([^/]+)\//,
|
|
383
|
+
/^src\/([^/]+)\//
|
|
384
|
+
];
|
|
385
|
+
function inferModulesFromPaths(filePaths) {
|
|
386
|
+
const out = /* @__PURE__ */ new Set();
|
|
387
|
+
for (const p of filePaths) {
|
|
388
|
+
const norm = normalize(p);
|
|
389
|
+
for (const re of MODULE_PATTERNS) {
|
|
390
|
+
const m = norm.match(re);
|
|
391
|
+
if (m && m[1]) out.add(m[1]);
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
return [...out].sort();
|
|
395
|
+
}
|
|
396
|
+
function pathsOverlap(a, b) {
|
|
397
|
+
const na = normalize(a);
|
|
398
|
+
const nb = normalize(b);
|
|
399
|
+
if (na === nb) return true;
|
|
400
|
+
return na.startsWith(nb + "/") || nb.startsWith(na + "/");
|
|
401
|
+
}
|
|
402
|
+
function memoryMatchesAnchorPaths(memory, inputPaths) {
|
|
403
|
+
const anchorPaths = memory.frontmatter.anchor.paths;
|
|
404
|
+
if (anchorPaths.length === 0) return false;
|
|
405
|
+
for (const ap of anchorPaths) {
|
|
406
|
+
for (const ip of inputPaths) {
|
|
407
|
+
if (pathsOverlap(ap, ip)) return true;
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
return false;
|
|
411
|
+
}
|
|
412
|
+
function normalize(p) {
|
|
413
|
+
return p.replace(/\\/g, "/").replace(/^\.\//, "").replace(/\/+$/, "");
|
|
414
|
+
}
|
|
415
|
+
function relPathFrom(root, abs) {
|
|
416
|
+
return path5.relative(root, abs).replace(/\\/g, "/");
|
|
417
|
+
}
|
|
418
|
+
export {
|
|
419
|
+
AnchorSchema,
|
|
420
|
+
DEFAULT_AUTO_PROMOTE_RULE,
|
|
421
|
+
DEFAULT_CONFIDENCE_THRESHOLDS,
|
|
422
|
+
HAIVE_DIR,
|
|
423
|
+
MEMORIES_DIR,
|
|
424
|
+
MemoryFrontmatterSchema,
|
|
425
|
+
MemoryScopeSchema,
|
|
426
|
+
MemoryStatusSchema,
|
|
427
|
+
MemoryTypeSchema,
|
|
428
|
+
PROJECT_CONTEXT_FILE,
|
|
429
|
+
USAGE_FILE,
|
|
430
|
+
buildFrontmatter,
|
|
431
|
+
bumpRead,
|
|
432
|
+
deriveConfidence,
|
|
433
|
+
emptyUsage,
|
|
434
|
+
emptyUsageIndex,
|
|
435
|
+
extractSnippet,
|
|
436
|
+
findProjectRoot,
|
|
437
|
+
getUsage,
|
|
438
|
+
inferModulesFromPaths,
|
|
439
|
+
isAutoPromoteEligible,
|
|
440
|
+
listMarkdownFilesRecursive,
|
|
441
|
+
literalMatchesAllTokens,
|
|
442
|
+
loadMemoriesFromDir,
|
|
443
|
+
loadMemory,
|
|
444
|
+
loadUsageIndex,
|
|
445
|
+
memoryFilePath,
|
|
446
|
+
memoryMatchesAnchorPaths,
|
|
447
|
+
newMemoryId,
|
|
448
|
+
parseMemory,
|
|
449
|
+
pathsOverlap,
|
|
450
|
+
pickSnippetNeedle,
|
|
451
|
+
recordRejection,
|
|
452
|
+
relPathFrom,
|
|
453
|
+
resolveHaivePaths,
|
|
454
|
+
saveUsageIndex,
|
|
455
|
+
serializeMemory,
|
|
456
|
+
stripPrivate,
|
|
457
|
+
tokenizeQuery,
|
|
458
|
+
trackReads,
|
|
459
|
+
usagePath,
|
|
460
|
+
verifyAnchor
|
|
461
|
+
};
|
|
462
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/schema.ts","../src/parser.ts","../src/paths.ts","../src/loader.ts","../src/search.ts","../src/verifier.ts","../src/usage.ts","../src/confidence.ts","../src/relevance.ts"],"sourcesContent":["import { z } from \"zod\";\n\nexport const MemoryScopeSchema = z.enum([\"personal\", \"team\", \"module\"]);\n\nexport const MemoryStatusSchema = z.enum([\n \"draft\",\n \"proposed\",\n \"validated\",\n \"deprecated\",\n \"stale\",\n]);\n\nexport const MemoryTypeSchema = z.enum([\n \"convention\",\n \"decision\",\n \"gotcha\",\n \"architecture\",\n \"glossary\",\n]);\n\nexport const AnchorSchema = z.object({\n commit: z.string().optional(),\n paths: z.array(z.string()).default([]),\n symbols: z.array(z.string()).default([]),\n});\n\nconst IsoDateString = z\n .union([z.string(), z.date()])\n .transform((v) => (v instanceof Date ? v.toISOString() : v))\n .pipe(z.string().datetime());\n\nexport const MemoryFrontmatterSchema = z\n .object({\n id: z.string().min(1),\n scope: MemoryScopeSchema.default(\"personal\"),\n module: z.string().optional(),\n type: MemoryTypeSchema,\n status: MemoryStatusSchema.default(\"draft\"),\n anchor: AnchorSchema.default({ paths: [], symbols: [] }),\n tags: z.array(z.string()).default([]),\n domain: z.string().optional(),\n author: z.string().optional(),\n created_at: IsoDateString,\n expires_when: z.string().nullable().default(null),\n verified_at: z.string().nullable().default(null),\n stale_reason: z.string().nullable().default(null),\n })\n .refine(\n (data) => data.scope !== \"module\" || !!data.module,\n { message: \"module name is required when scope is 'module'\", path: [\"module\"] },\n );\n","import matter from \"gray-matter\";\nimport { MemoryFrontmatterSchema } from \"./schema.js\";\nimport type { Memory, MemoryFrontmatter } from \"./types.js\";\n\nconst PRIVATE_BLOCK_RE = /<private>[\\s\\S]*?<\\/private>/g;\n\nexport function stripPrivate(body: string): string {\n return body.replace(PRIVATE_BLOCK_RE, \"\").trimEnd();\n}\n\nexport function parseMemory(raw: string): Memory {\n const parsed = matter(raw);\n const frontmatter = MemoryFrontmatterSchema.parse(parsed.data);\n return {\n frontmatter,\n body: stripPrivate(parsed.content.trim()),\n };\n}\n\nfunction stripUndefined<T>(value: T): T {\n if (Array.isArray(value)) {\n return value.map((v) => stripUndefined(v)) as unknown as T;\n }\n if (value && typeof value === \"object\") {\n const out: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(value as Record<string, unknown>)) {\n if (v === undefined) continue;\n out[k] = stripUndefined(v);\n }\n return out as T;\n }\n return value;\n}\n\nexport function serializeMemory(memory: Memory): string {\n const clean = stripUndefined(memory.frontmatter) as Record<string, unknown>;\n return matter.stringify(memory.body, clean);\n}\n\nexport function newMemoryId(type: string, slug: string, date = new Date()): string {\n const isoDate = date.toISOString().slice(0, 10);\n const safeSlug = slug\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \"-\")\n .replace(/^-|-$/g, \"\")\n .slice(0, 60);\n return `${isoDate}-${type}-${safeSlug}`;\n}\n\nexport function buildFrontmatter(input: {\n type: MemoryFrontmatter[\"type\"];\n slug: string;\n scope?: MemoryFrontmatter[\"scope\"];\n module?: string;\n tags?: string[];\n domain?: string;\n author?: string;\n paths?: string[];\n symbols?: string[];\n commit?: string;\n}): MemoryFrontmatter {\n const now = new Date();\n const id = newMemoryId(input.type, input.slug, now);\n return MemoryFrontmatterSchema.parse({\n id,\n scope: input.scope ?? \"personal\",\n module: input.module,\n type: input.type,\n status: \"draft\",\n anchor: {\n commit: input.commit,\n paths: input.paths ?? [],\n symbols: input.symbols ?? [],\n },\n tags: input.tags ?? [],\n domain: input.domain,\n author: input.author,\n created_at: now.toISOString(),\n expires_when: null,\n });\n}\n","import { existsSync } from \"node:fs\";\nimport path from \"node:path\";\n\nexport const HAIVE_DIR = \".ai\";\n\nconst ROOT_MARKERS = [\".ai\", \".git\", \"package.json\"];\n\nexport function findProjectRoot(startDir: string = process.cwd()): string {\n let current = path.resolve(startDir);\n const fsRoot = path.parse(current).root;\n while (current !== fsRoot) {\n for (const marker of ROOT_MARKERS) {\n if (existsSync(path.join(current, marker))) return current;\n }\n current = path.dirname(current);\n }\n return path.resolve(startDir);\n}\n\nexport const PROJECT_CONTEXT_FILE = \"project-context.md\";\nexport const MEMORIES_DIR = \"memories\";\n\nexport interface HaivePaths {\n root: string;\n haiveDir: string;\n projectContext: string;\n memoriesDir: string;\n personalDir: string;\n teamDir: string;\n moduleDir: string;\n modulesContextDir: string;\n}\n\nexport function resolveHaivePaths(projectRoot: string): HaivePaths {\n const haiveDir = path.join(projectRoot, HAIVE_DIR);\n const memoriesDir = path.join(haiveDir, MEMORIES_DIR);\n return {\n root: projectRoot,\n haiveDir,\n projectContext: path.join(haiveDir, PROJECT_CONTEXT_FILE),\n memoriesDir,\n personalDir: path.join(memoriesDir, \"personal\"),\n teamDir: path.join(memoriesDir, \"team\"),\n moduleDir: path.join(memoriesDir, \"module\"),\n modulesContextDir: path.join(haiveDir, \"modules\"),\n };\n}\n\nexport function memoryFilePath(\n paths: HaivePaths,\n scope: \"personal\" | \"team\" | \"module\",\n id: string,\n module?: string,\n): string {\n const base =\n scope === \"personal\"\n ? paths.personalDir\n : scope === \"team\"\n ? paths.teamDir\n : path.join(paths.moduleDir, module ?? \"_unscoped\");\n return path.join(base, `${id}.md`);\n}\n","import { readdir, readFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { parseMemory } from \"./parser.js\";\nimport type { Memory } from \"./types.js\";\n\nexport interface LoadedMemory {\n memory: Memory;\n filePath: string;\n}\n\nexport async function listMarkdownFilesRecursive(dir: string): Promise<string[]> {\n const out: string[] = [];\n let entries;\n try {\n entries = await readdir(dir, { withFileTypes: true });\n } catch {\n return out;\n }\n for (const entry of entries) {\n const full = path.join(dir, entry.name);\n if (entry.isDirectory()) {\n out.push(...(await listMarkdownFilesRecursive(full)));\n } else if (entry.isFile() && entry.name.endsWith(\".md\")) {\n out.push(full);\n }\n }\n return out;\n}\n\nexport async function loadMemory(filePath: string): Promise<LoadedMemory> {\n const raw = await readFile(filePath, \"utf8\");\n return { memory: parseMemory(raw), filePath };\n}\n\nexport async function loadMemoriesFromDir(dir: string): Promise<LoadedMemory[]> {\n const files = await listMarkdownFilesRecursive(dir);\n const out: LoadedMemory[] = [];\n for (const file of files) {\n try {\n out.push(await loadMemory(file));\n } catch {\n // Skip unparseable files in v0.1; future: surface a warning channel.\n }\n }\n return out;\n}\n","import type { Memory } from \"./types.js\";\n\nexport function tokenizeQuery(query: string): string[] {\n return query\n .toLowerCase()\n .split(/\\s+/)\n .map((t) => t.trim())\n .filter(Boolean);\n}\n\nexport function literalMatchesAllTokens(memory: Memory, tokens: string[]): boolean {\n if (tokens.length === 0) return true;\n const fm = memory.frontmatter;\n const idLower = fm.id.toLowerCase();\n const tagsLower = fm.tags.map((t) => t.toLowerCase());\n const bodyLower = memory.body.toLowerCase();\n return tokens.every((rawTok) => {\n const tok = rawTok.toLowerCase();\n return (\n idLower.includes(tok) ||\n tagsLower.some((t) => t.includes(tok)) ||\n bodyLower.includes(tok)\n );\n });\n}\n\nexport function pickSnippetNeedle(query: string): string {\n const tokens = tokenizeQuery(query);\n if (tokens.length === 0) return query.toLowerCase();\n return [...tokens].sort((a, b) => b.length - a.length)[0]!;\n}\n\nexport function extractSnippet(body: string, needle: string, radius = 40): string {\n const lower = body.toLowerCase();\n const idx = needle ? lower.indexOf(needle) : -1;\n if (idx < 0) {\n return body.slice(0, radius * 3).replace(/\\s+/g, \" \").trim();\n }\n const start = Math.max(0, idx - radius);\n const end = Math.min(body.length, idx + needle.length + radius);\n const snippet = body.slice(start, end).replace(/\\s+/g, \" \").trim();\n return (start > 0 ? \"…\" : \"\") + snippet + (end < body.length ? \"…\" : \"\");\n}\n","import { readFile } from \"node:fs/promises\";\nimport { existsSync } from \"node:fs\";\nimport path from \"node:path\";\nimport type { Memory } from \"./types.js\";\n\nexport interface VerifyResult {\n stale: boolean;\n reason: string | null;\n checkedPaths: string[];\n checkedSymbols: string[];\n}\n\nexport interface VerifyOptions {\n /** Project root used to resolve relative anchor paths. */\n projectRoot: string;\n}\n\n/**\n * Verify that a memory's anchor still matches the current code.\n * - Every anchor.paths entry must exist on disk\n * - Every anchor.symbols entry must appear at least once across the anchor.paths\n * files (or any tracked file if no paths are recorded)\n *\n * Anchorless memories (no paths and no symbols) are always considered fresh —\n * staleness only applies to memories that opted into anchoring.\n */\nexport async function verifyAnchor(\n memory: Memory,\n options: VerifyOptions,\n): Promise<VerifyResult> {\n const anchor = memory.frontmatter.anchor;\n const checkedPaths = anchor.paths;\n const checkedSymbols = anchor.symbols;\n\n if (checkedPaths.length === 0 && checkedSymbols.length === 0) {\n return { stale: false, reason: null, checkedPaths, checkedSymbols };\n }\n\n const missingPaths: string[] = [];\n const existingAbsPaths: string[] = [];\n for (const rel of checkedPaths) {\n const abs = path.isAbsolute(rel) ? rel : path.join(options.projectRoot, rel);\n if (existsSync(abs)) {\n existingAbsPaths.push(abs);\n } else {\n missingPaths.push(rel);\n }\n }\n\n if (missingPaths.length > 0) {\n return {\n stale: true,\n reason: `anchor path(s) no longer exist: ${missingPaths.join(\", \")}`,\n checkedPaths,\n checkedSymbols,\n };\n }\n\n if (checkedSymbols.length > 0) {\n if (existingAbsPaths.length === 0) {\n return {\n stale: true,\n reason: `cannot verify symbols (${checkedSymbols.join(\", \")}): no anchor paths recorded`,\n checkedPaths,\n checkedSymbols,\n };\n }\n const missingSymbols: string[] = [];\n for (const sym of checkedSymbols) {\n let found = false;\n for (const file of existingAbsPaths) {\n try {\n const contents = await readFile(file, \"utf8\");\n if (contents.includes(sym)) {\n found = true;\n break;\n }\n } catch {\n // unreadable file; treat as not finding the symbol here\n }\n }\n if (!found) missingSymbols.push(sym);\n }\n if (missingSymbols.length > 0) {\n return {\n stale: true,\n reason: `anchor symbol(s) not found in any anchor path: ${missingSymbols.join(\", \")}`,\n checkedPaths,\n checkedSymbols,\n };\n }\n }\n\n return { stale: false, reason: null, checkedPaths, checkedSymbols };\n}\n","import { mkdir, readFile, writeFile } from \"node:fs/promises\";\nimport { existsSync } from \"node:fs\";\nimport path from \"node:path\";\nimport type { HaivePaths } from \"./paths.js\";\n\nexport interface MemoryUsage {\n read_count: number;\n last_read_at: string | null;\n rejected_count: number;\n last_rejected_at: string | null;\n rejection_reason: string | null;\n}\n\nexport interface UsageIndex {\n version: 1;\n updated_at: string;\n by_id: Record<string, MemoryUsage>;\n}\n\nexport const USAGE_FILE = \"usage.json\";\n\nexport function emptyUsage(): MemoryUsage {\n return {\n read_count: 0,\n last_read_at: null,\n rejected_count: 0,\n last_rejected_at: null,\n rejection_reason: null,\n };\n}\n\nexport function emptyUsageIndex(): UsageIndex {\n return {\n version: 1,\n updated_at: new Date().toISOString(),\n by_id: {},\n };\n}\n\nexport function usagePath(paths: HaivePaths): string {\n return path.join(paths.haiveDir, \".cache\", USAGE_FILE);\n}\n\nexport async function loadUsageIndex(paths: HaivePaths): Promise<UsageIndex> {\n const file = usagePath(paths);\n if (!existsSync(file)) return emptyUsageIndex();\n const raw = await readFile(file, \"utf8\");\n try {\n const parsed = JSON.parse(raw) as UsageIndex;\n if (parsed.version !== 1) return emptyUsageIndex();\n return parsed;\n } catch {\n return emptyUsageIndex();\n }\n}\n\nexport async function saveUsageIndex(paths: HaivePaths, index: UsageIndex): Promise<void> {\n const file = usagePath(paths);\n await mkdir(path.dirname(file), { recursive: true });\n index.updated_at = new Date().toISOString();\n await writeFile(file, JSON.stringify(index, null, 2), \"utf8\");\n}\n\nexport function getUsage(index: UsageIndex, id: string): MemoryUsage {\n return index.by_id[id] ?? emptyUsage();\n}\n\nexport function bumpRead(index: UsageIndex, ids: string[]): UsageIndex {\n if (ids.length === 0) return index;\n const now = new Date().toISOString();\n for (const id of ids) {\n const current = index.by_id[id] ?? emptyUsage();\n index.by_id[id] = {\n ...current,\n read_count: current.read_count + 1,\n last_read_at: now,\n };\n }\n return index;\n}\n\nexport function recordRejection(\n index: UsageIndex,\n id: string,\n reason: string | null,\n): UsageIndex {\n const current = index.by_id[id] ?? emptyUsage();\n const now = new Date().toISOString();\n index.by_id[id] = {\n ...current,\n rejected_count: current.rejected_count + 1,\n last_rejected_at: now,\n rejection_reason: reason,\n };\n return index;\n}\n\nexport async function trackReads(\n paths: HaivePaths,\n ids: string[],\n): Promise<UsageIndex> {\n if (ids.length === 0) {\n return await loadUsageIndex(paths);\n }\n const index = await loadUsageIndex(paths);\n bumpRead(index, ids);\n await saveUsageIndex(paths, index);\n return index;\n}\n","import type { MemoryFrontmatter } from \"./types.js\";\nimport type { MemoryUsage } from \"./usage.js\";\n\nexport type ConfidenceLevel =\n | \"unverified\"\n | \"low\"\n | \"trusted\"\n | \"authoritative\"\n | \"stale\";\n\nexport interface ConfidenceThresholds {\n trustedReads: number;\n authoritativeReads: number;\n}\n\nexport const DEFAULT_CONFIDENCE_THRESHOLDS: ConfidenceThresholds = {\n trustedReads: 3,\n authoritativeReads: 10,\n};\n\nexport function deriveConfidence(\n fm: MemoryFrontmatter,\n usage: MemoryUsage,\n thresholds: ConfidenceThresholds = DEFAULT_CONFIDENCE_THRESHOLDS,\n): ConfidenceLevel {\n if (fm.status === \"stale\" || fm.status === \"deprecated\") return \"stale\";\n if (fm.status === \"validated\") {\n return usage.read_count >= thresholds.authoritativeReads\n ? \"authoritative\"\n : \"trusted\";\n }\n if (fm.status === \"proposed\") {\n return usage.read_count >= thresholds.trustedReads ? \"trusted\" : \"low\";\n }\n // draft\n return \"unverified\";\n}\n\nexport interface AutoPromoteRule {\n /** Minimum read_count to promote proposed → validated. */\n minReads: number;\n /** Maximum rejected_count tolerated (memories with more rejections never auto-promote). */\n maxRejections: number;\n}\n\nexport const DEFAULT_AUTO_PROMOTE_RULE: AutoPromoteRule = {\n minReads: 5,\n maxRejections: 0,\n};\n\nexport function isAutoPromoteEligible(\n fm: MemoryFrontmatter,\n usage: MemoryUsage,\n rule: AutoPromoteRule = DEFAULT_AUTO_PROMOTE_RULE,\n): boolean {\n if (fm.status !== \"proposed\") return false;\n if (usage.rejected_count > rule.maxRejections) return false;\n return usage.read_count >= rule.minReads;\n}\n","import path from \"node:path\";\nimport type { LoadedMemory } from \"./loader.js\";\n\nconst MODULE_PATTERNS = [\n /^packages\\/([^/]+)\\//,\n /^apps\\/([^/]+)\\//,\n /^modules\\/([^/]+)\\//,\n /^src\\/([^/]+)\\//,\n];\n\n/**\n * Best-effort inference: given a list of file paths, infer module names from\n * conventional layouts (packages/X/, apps/X/, modules/X/, src/X/).\n */\nexport function inferModulesFromPaths(filePaths: string[]): string[] {\n const out = new Set<string>();\n for (const p of filePaths) {\n const norm = normalize(p);\n for (const re of MODULE_PATTERNS) {\n const m = norm.match(re);\n if (m && m[1]) out.add(m[1]);\n }\n }\n return [...out].sort();\n}\n\n/**\n * Path overlap: returns true if `a` and `b` refer to the same path or one is a\n * parent of the other. Both inputs are treated as POSIX-style relative paths.\n */\nexport function pathsOverlap(a: string, b: string): boolean {\n const na = normalize(a);\n const nb = normalize(b);\n if (na === nb) return true;\n return na.startsWith(nb + \"/\") || nb.startsWith(na + \"/\");\n}\n\nexport function memoryMatchesAnchorPaths(\n memory: LoadedMemory[\"memory\"],\n inputPaths: string[],\n): boolean {\n const anchorPaths = memory.frontmatter.anchor.paths;\n if (anchorPaths.length === 0) return false;\n for (const ap of anchorPaths) {\n for (const ip of inputPaths) {\n if (pathsOverlap(ap, ip)) return true;\n }\n }\n return false;\n}\n\nfunction normalize(p: string): string {\n // Strip leading \"./\" and trailing \"/\", normalize separators.\n return p.replace(/\\\\/g, \"/\").replace(/^\\.\\//, \"\").replace(/\\/+$/, \"\");\n}\n\nexport function relPathFrom(root: string, abs: string): string {\n return path.relative(root, abs).replace(/\\\\/g, \"/\");\n}\n"],"mappings":"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","names":["path","path","readFile","existsSync","path","readFile","existsSync","path","path"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@hiveai/core",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "hAIve core — memory types, schema, parser, validator",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+https://github.com/Doucs91/hAIve.git",
|
|
9
|
+
"directory": "packages/core"
|
|
10
|
+
},
|
|
11
|
+
"bugs": "https://github.com/Doucs91/hAIve/issues",
|
|
12
|
+
"homepage": "https://github.com/Doucs91/hAIve#readme",
|
|
13
|
+
"keywords": [
|
|
14
|
+
"ai",
|
|
15
|
+
"memory",
|
|
16
|
+
"mcp",
|
|
17
|
+
"haive",
|
|
18
|
+
"agent",
|
|
19
|
+
"team"
|
|
20
|
+
],
|
|
21
|
+
"type": "module",
|
|
22
|
+
"main": "./dist/index.js",
|
|
23
|
+
"types": "./dist/index.d.ts",
|
|
24
|
+
"exports": {
|
|
25
|
+
".": {
|
|
26
|
+
"types": "./dist/index.d.ts",
|
|
27
|
+
"import": "./dist/index.js"
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
"files": [
|
|
31
|
+
"dist",
|
|
32
|
+
"LICENSE"
|
|
33
|
+
],
|
|
34
|
+
"dependencies": {
|
|
35
|
+
"gray-matter": "^4.0.3",
|
|
36
|
+
"zod": "^3.23.8"
|
|
37
|
+
},
|
|
38
|
+
"scripts": {
|
|
39
|
+
"build": "tsup",
|
|
40
|
+
"test": "vitest run",
|
|
41
|
+
"test:watch": "vitest",
|
|
42
|
+
"typecheck": "tsc --noEmit",
|
|
43
|
+
"clean": "rm -rf dist .tsbuildinfo"
|
|
44
|
+
}
|
|
45
|
+
}
|