@hiveai/cli 0.2.16 → 0.3.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/dist/Dashboard-HVELRRC7.js +336 -0
- package/dist/Dashboard-HVELRRC7.js.map +1 -0
- package/dist/index.js +158 -20
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/Dashboard-SRPCHP7Z.js +0 -194
- package/dist/Dashboard-SRPCHP7Z.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
// src/index.ts
|
|
4
|
-
import { Command as
|
|
4
|
+
import { Command as Command29 } from "commander";
|
|
5
5
|
|
|
6
6
|
// src/commands/briefing.ts
|
|
7
7
|
import { existsSync } from "fs";
|
|
@@ -11,8 +11,10 @@ import {
|
|
|
11
11
|
findProjectRoot,
|
|
12
12
|
literalMatchesAllTokens,
|
|
13
13
|
literalMatchesAnyToken,
|
|
14
|
+
loadCodeMap,
|
|
14
15
|
loadMemoriesFromDir,
|
|
15
16
|
memoryMatchesAnchorPaths,
|
|
17
|
+
queryCodeMap,
|
|
16
18
|
resolveHaivePaths,
|
|
17
19
|
tokenizeQuery,
|
|
18
20
|
trackReads
|
|
@@ -52,7 +54,7 @@ var ui = {
|
|
|
52
54
|
function registerBriefing(program2) {
|
|
53
55
|
program2.command("briefing").description(
|
|
54
56
|
"Print project context + relevant memories in one shot \u2014 ideal for agent onboarding"
|
|
55
|
-
).option("--task <text>", "what you are about to do \u2014 filters memories by relevance").option("--files <csv>", "comma-separated file paths being worked on (anchors memories)").option("--max-memories <n>", "cap on memories surfaced", "10").option(
|
|
57
|
+
).option("--task <text>", "what you are about to do \u2014 filters memories by relevance").option("--files <csv>", "comma-separated file paths being worked on (anchors memories)").option("--symbols <csv>", "symbol names to look up in the code-map (e.g. PaymentService,TenantFilter)").option("--max-memories <n>", "cap on memories surfaced", "10").option(
|
|
56
58
|
"--scope <scope>",
|
|
57
59
|
"personal | team | module | all (default: team)",
|
|
58
60
|
"team"
|
|
@@ -163,6 +165,34 @@ function registerBriefing(program2) {
|
|
|
163
165
|
await trackReads(paths, ids).catch(() => {
|
|
164
166
|
});
|
|
165
167
|
}
|
|
168
|
+
const requestedSymbols = (opts.symbols ?? "").split(",").map((s) => s.trim()).filter(Boolean);
|
|
169
|
+
if (requestedSymbols.length > 0) {
|
|
170
|
+
const codeMap = await loadCodeMap(paths);
|
|
171
|
+
if (!codeMap) {
|
|
172
|
+
ui.warn("No code-map found. Run `haive index code` first to enable symbol lookup.");
|
|
173
|
+
} else {
|
|
174
|
+
console.log(`
|
|
175
|
+
${ui.bold("=== Symbol Locations ===")}
|
|
176
|
+
`);
|
|
177
|
+
for (const sym of requestedSymbols) {
|
|
178
|
+
const { files } = queryCodeMap(codeMap, { symbol: sym });
|
|
179
|
+
if (files.length === 0) {
|
|
180
|
+
console.log(`${ui.dim(sym)} (not found in code-map)`);
|
|
181
|
+
} else {
|
|
182
|
+
for (const f of files) {
|
|
183
|
+
const exports = f.entry.exports.filter(
|
|
184
|
+
(e) => e.name.toLowerCase().includes(sym.toLowerCase())
|
|
185
|
+
);
|
|
186
|
+
for (const e of exports) {
|
|
187
|
+
const desc = e.description ? ` \u2014 ${e.description}` : "";
|
|
188
|
+
console.log(`${ui.bold(e.name)} ${ui.dim(f.path + ":" + e.line)} [${e.kind}]${desc}`);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
console.log();
|
|
194
|
+
}
|
|
195
|
+
}
|
|
166
196
|
});
|
|
167
197
|
}
|
|
168
198
|
function parseCsv(value) {
|
|
@@ -183,7 +213,7 @@ function registerTui(program2) {
|
|
|
183
213
|
const root = findProjectRoot2(opts.dir);
|
|
184
214
|
const { render } = await import("ink");
|
|
185
215
|
const { createElement } = await import("react");
|
|
186
|
-
const { Dashboard } = await import("./Dashboard-
|
|
216
|
+
const { Dashboard } = await import("./Dashboard-HVELRRC7.js");
|
|
187
217
|
const { waitUntilExit } = render(createElement(Dashboard, { root }));
|
|
188
218
|
await waitUntilExit();
|
|
189
219
|
});
|
|
@@ -2129,17 +2159,124 @@ function registerMemoryImport(memory2) {
|
|
|
2129
2159
|
});
|
|
2130
2160
|
}
|
|
2131
2161
|
|
|
2132
|
-
// src/commands/
|
|
2133
|
-
import { writeFile as writeFile12, mkdir as mkdir6 } from "fs/promises";
|
|
2162
|
+
// src/commands/memory-digest.ts
|
|
2134
2163
|
import { existsSync as existsSync25 } from "fs";
|
|
2164
|
+
import { writeFile as writeFile12 } from "fs/promises";
|
|
2135
2165
|
import path23 from "path";
|
|
2136
2166
|
import "commander";
|
|
2137
2167
|
import {
|
|
2138
|
-
|
|
2168
|
+
deriveConfidence as deriveConfidence4,
|
|
2139
2169
|
findProjectRoot as findProjectRoot27,
|
|
2170
|
+
getUsage as getUsage8,
|
|
2140
2171
|
loadMemoriesFromDir as loadMemoriesFromDir5,
|
|
2172
|
+
loadUsageIndex as loadUsageIndex10,
|
|
2173
|
+
resolveHaivePaths as resolveHaivePaths24
|
|
2174
|
+
} from "@hiveai/core";
|
|
2175
|
+
var CONFIDENCE_EMOJI = {
|
|
2176
|
+
unverified: "\u2B1C",
|
|
2177
|
+
low: "\u{1F7E1}",
|
|
2178
|
+
trusted: "\u{1F7E2}",
|
|
2179
|
+
authoritative: "\u2B50",
|
|
2180
|
+
stale: "\u{1F534}"
|
|
2181
|
+
};
|
|
2182
|
+
function registerMemoryDigest(program2) {
|
|
2183
|
+
program2.command("digest").description(
|
|
2184
|
+
"Generate a Markdown review digest of recently added/updated memories (default: last 7 days)"
|
|
2185
|
+
).option("--days <n>", "look-back window in days", "7").option("--scope <scope>", "personal | team | module | all", "team").option("--out <file>", "write digest to a file instead of stdout").option("-d, --dir <dir>", "project root").action(async (opts) => {
|
|
2186
|
+
const root = findProjectRoot27(opts.dir);
|
|
2187
|
+
const paths = resolveHaivePaths24(root);
|
|
2188
|
+
if (!existsSync25(paths.memoriesDir)) {
|
|
2189
|
+
ui.error("No .ai/memories found. Run `haive init` first.");
|
|
2190
|
+
process.exitCode = 1;
|
|
2191
|
+
return;
|
|
2192
|
+
}
|
|
2193
|
+
const days = Math.max(1, Number(opts.days ?? 7));
|
|
2194
|
+
const scopeFilter = opts.scope ?? "team";
|
|
2195
|
+
const cutoff = new Date(Date.now() - days * 24 * 60 * 60 * 1e3);
|
|
2196
|
+
const all = await loadMemoriesFromDir5(paths.memoriesDir);
|
|
2197
|
+
const usage = await loadUsageIndex10(paths);
|
|
2198
|
+
const recent = all.filter(({ memory: mem }) => {
|
|
2199
|
+
const fm = mem.frontmatter;
|
|
2200
|
+
if (fm.type === "session_recap") return false;
|
|
2201
|
+
if (fm.status === "rejected" || fm.status === "deprecated") return false;
|
|
2202
|
+
if (scopeFilter !== "all" && fm.scope !== scopeFilter) return false;
|
|
2203
|
+
return new Date(fm.created_at) >= cutoff;
|
|
2204
|
+
});
|
|
2205
|
+
const now = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
2206
|
+
const lines = [
|
|
2207
|
+
`# hAIve Memory Digest \u2014 ${now}`,
|
|
2208
|
+
``,
|
|
2209
|
+
`> **Period:** last ${days} day${days > 1 ? "s" : ""} | **Scope:** ${scopeFilter} | **Total:** ${recent.length} memor${recent.length === 1 ? "y" : "ies"}`,
|
|
2210
|
+
``,
|
|
2211
|
+
`---`,
|
|
2212
|
+
``
|
|
2213
|
+
];
|
|
2214
|
+
if (recent.length === 0) {
|
|
2215
|
+
lines.push(`_No new memories in the last ${days} days._`);
|
|
2216
|
+
} else {
|
|
2217
|
+
const byType = /* @__PURE__ */ new Map();
|
|
2218
|
+
for (const m of recent) {
|
|
2219
|
+
const t = m.memory.frontmatter.type;
|
|
2220
|
+
if (!byType.has(t)) byType.set(t, []);
|
|
2221
|
+
byType.get(t).push(m);
|
|
2222
|
+
}
|
|
2223
|
+
for (const [type, mems] of byType) {
|
|
2224
|
+
lines.push(`## ${type.charAt(0).toUpperCase() + type.slice(1)} (${mems.length})`);
|
|
2225
|
+
lines.push(``);
|
|
2226
|
+
for (const { memory: mem } of mems) {
|
|
2227
|
+
const fm = mem.frontmatter;
|
|
2228
|
+
const u = getUsage8(usage, fm.id);
|
|
2229
|
+
const confidence = deriveConfidence4(fm, u);
|
|
2230
|
+
const emoji = CONFIDENCE_EMOJI[confidence] ?? "\u2B1C";
|
|
2231
|
+
const anchor = fm.anchor.paths.length > 0 ? `\`${fm.anchor.paths[0]}\`` + (fm.anchor.paths.length > 1 ? ` +${fm.anchor.paths.length - 1}` : "") : "_no anchor_";
|
|
2232
|
+
lines.push(`### ${emoji} \`${fm.id}\``);
|
|
2233
|
+
lines.push(``);
|
|
2234
|
+
lines.push(`| Field | Value |`);
|
|
2235
|
+
lines.push(`|---|---|`);
|
|
2236
|
+
lines.push(`| **Status** | \`${fm.status}\` |`);
|
|
2237
|
+
lines.push(`| **Confidence** | ${confidence} |`);
|
|
2238
|
+
lines.push(`| **Scope** | ${fm.scope}${fm.module ? `/${fm.module}` : ""} |`);
|
|
2239
|
+
lines.push(`| **Tags** | ${fm.tags.length > 0 ? fm.tags.map((t) => `\`${t}\``).join(", ") : "_none_"} |`);
|
|
2240
|
+
lines.push(`| **Anchor** | ${anchor} |`);
|
|
2241
|
+
lines.push(`| **Reads** | ${u.read_count} |`);
|
|
2242
|
+
lines.push(`| **Created** | ${fm.created_at.slice(0, 10)} |`);
|
|
2243
|
+
lines.push(``);
|
|
2244
|
+
const bodyPreview = mem.body.split("\n").slice(0, 6).join("\n").trim();
|
|
2245
|
+
lines.push(bodyPreview);
|
|
2246
|
+
lines.push(``);
|
|
2247
|
+
lines.push(`**Action:** [ ] approve [ ] reject [ ] keep as-is`);
|
|
2248
|
+
lines.push(``);
|
|
2249
|
+
lines.push(`---`);
|
|
2250
|
+
lines.push(``);
|
|
2251
|
+
}
|
|
2252
|
+
}
|
|
2253
|
+
}
|
|
2254
|
+
lines.push(``);
|
|
2255
|
+
lines.push(
|
|
2256
|
+
`> _To take action: \`haive memory approve <id>\`, \`haive memory reject <id>\`, or open \`haive tui\` for interactive review._`
|
|
2257
|
+
);
|
|
2258
|
+
const digest = lines.join("\n");
|
|
2259
|
+
if (opts.out) {
|
|
2260
|
+
const outPath = path23.resolve(process.cwd(), opts.out);
|
|
2261
|
+
await writeFile12(outPath, digest, "utf8");
|
|
2262
|
+
ui.success(`Digest written to ${opts.out} (${recent.length} memor${recent.length === 1 ? "y" : "ies"})`);
|
|
2263
|
+
} else {
|
|
2264
|
+
console.log(digest);
|
|
2265
|
+
}
|
|
2266
|
+
});
|
|
2267
|
+
}
|
|
2268
|
+
|
|
2269
|
+
// src/commands/session-end.ts
|
|
2270
|
+
import { writeFile as writeFile13, mkdir as mkdir6 } from "fs/promises";
|
|
2271
|
+
import { existsSync as existsSync26 } from "fs";
|
|
2272
|
+
import path24 from "path";
|
|
2273
|
+
import "commander";
|
|
2274
|
+
import {
|
|
2275
|
+
buildFrontmatter as buildFrontmatter3,
|
|
2276
|
+
findProjectRoot as findProjectRoot28,
|
|
2277
|
+
loadMemoriesFromDir as loadMemoriesFromDir6,
|
|
2141
2278
|
memoryFilePath as memoryFilePath4,
|
|
2142
|
-
resolveHaivePaths as
|
|
2279
|
+
resolveHaivePaths as resolveHaivePaths25,
|
|
2143
2280
|
serializeMemory as serializeMemory10
|
|
2144
2281
|
} from "@hiveai/core";
|
|
2145
2282
|
function buildRecapBody(opts) {
|
|
@@ -2172,9 +2309,9 @@ function recapTopic(scope, module) {
|
|
|
2172
2309
|
}
|
|
2173
2310
|
function registerSessionEnd(session2) {
|
|
2174
2311
|
session2.command("end").description("Save a structured end-of-session recap (goal / accomplished / discoveries / next steps)").requiredOption("--goal <text>", "What you were trying to accomplish (1\u20132 sentences)").requiredOption("--accomplished <text>", "What was actually done (bullet list recommended)").option("--discoveries <text>", "Bugs, surprises, or inconsistencies found during this session").option("--files <csv>", "Key files touched, comma-separated").option("--next <text>", "What should happen next (for the next session or a teammate)").option("--scope <scope>", "personal | team | module", "personal").option("--module <name>", "module name (required when scope=module)").option("-d, --dir <dir>", "project root").action(async (opts) => {
|
|
2175
|
-
const root =
|
|
2176
|
-
const paths =
|
|
2177
|
-
if (!
|
|
2312
|
+
const root = findProjectRoot28(opts.dir);
|
|
2313
|
+
const paths = resolveHaivePaths25(root);
|
|
2314
|
+
if (!existsSync26(paths.haiveDir)) {
|
|
2178
2315
|
ui.error(`No .ai/ found at ${root}. Run \`haive init\` first.`);
|
|
2179
2316
|
process.exitCode = 1;
|
|
2180
2317
|
return;
|
|
@@ -2183,13 +2320,13 @@ function registerSessionEnd(session2) {
|
|
|
2183
2320
|
const body = buildRecapBody(opts);
|
|
2184
2321
|
const topic = recapTopic(scope, opts.module);
|
|
2185
2322
|
const filesTouched = parseCsv5(opts.files);
|
|
2186
|
-
const missingPaths = filesTouched.filter((p) => !
|
|
2323
|
+
const missingPaths = filesTouched.filter((p) => !existsSync26(path24.resolve(root, p)));
|
|
2187
2324
|
if (missingPaths.length > 0) {
|
|
2188
2325
|
ui.warn(`Anchor path${missingPaths.length > 1 ? "s" : ""} not found in project (will be stale):`);
|
|
2189
2326
|
for (const p of missingPaths) ui.warn(` \u2717 ${p}`);
|
|
2190
2327
|
}
|
|
2191
|
-
if (
|
|
2192
|
-
const existing = await
|
|
2328
|
+
if (existsSync26(paths.memoriesDir)) {
|
|
2329
|
+
const existing = await loadMemoriesFromDir6(paths.memoriesDir);
|
|
2193
2330
|
const topicMatch = existing.find(
|
|
2194
2331
|
({ memory: memory2 }) => memory2.frontmatter.topic === topic && memory2.frontmatter.scope === scope && (!opts.module || memory2.frontmatter.module === opts.module)
|
|
2195
2332
|
);
|
|
@@ -2204,9 +2341,9 @@ function registerSessionEnd(session2) {
|
|
|
2204
2341
|
paths: filesTouched.length ? filesTouched : fm.anchor.paths
|
|
2205
2342
|
}
|
|
2206
2343
|
};
|
|
2207
|
-
await
|
|
2344
|
+
await writeFile13(topicMatch.filePath, serializeMemory10({ frontmatter: newFrontmatter, body }), "utf8");
|
|
2208
2345
|
ui.success(`Session recap updated (revision #${revisionCount})`);
|
|
2209
|
-
ui.info(`id=${fm.id} file=${
|
|
2346
|
+
ui.info(`id=${fm.id} file=${path24.relative(root, topicMatch.filePath)}`);
|
|
2210
2347
|
return;
|
|
2211
2348
|
}
|
|
2212
2349
|
}
|
|
@@ -2221,10 +2358,10 @@ function registerSessionEnd(session2) {
|
|
|
2221
2358
|
status: "validated"
|
|
2222
2359
|
});
|
|
2223
2360
|
const file = memoryFilePath4(paths, frontmatter.scope, frontmatter.id, frontmatter.module);
|
|
2224
|
-
await mkdir6(
|
|
2225
|
-
await
|
|
2361
|
+
await mkdir6(path24.dirname(file), { recursive: true });
|
|
2362
|
+
await writeFile13(file, serializeMemory10({ frontmatter, body }), "utf8");
|
|
2226
2363
|
ui.success(`Session recap created`);
|
|
2227
|
-
ui.info(`id=${frontmatter.id} scope=${scope} file=${
|
|
2364
|
+
ui.info(`id=${frontmatter.id} scope=${scope} file=${path24.relative(root, file)}`);
|
|
2228
2365
|
ui.info("Next session: call `get_briefing` \u2014 the recap will be surfaced automatically.");
|
|
2229
2366
|
});
|
|
2230
2367
|
}
|
|
@@ -2234,8 +2371,8 @@ function parseCsv5(value) {
|
|
|
2234
2371
|
}
|
|
2235
2372
|
|
|
2236
2373
|
// src/index.ts
|
|
2237
|
-
var program = new
|
|
2238
|
-
program.name("haive").description("hAIve \u2014 team-first persistent memory layer for AI coding agents").version("0.
|
|
2374
|
+
var program = new Command29();
|
|
2375
|
+
program.name("haive").description("hAIve \u2014 team-first persistent memory layer for AI coding agents").version("0.3.0");
|
|
2239
2376
|
registerInit(program);
|
|
2240
2377
|
registerMcp(program);
|
|
2241
2378
|
registerBriefing(program);
|
|
@@ -2263,6 +2400,7 @@ registerMemoryUpdate(memory);
|
|
|
2263
2400
|
registerMemoryHot(memory);
|
|
2264
2401
|
registerMemoryTried(memory);
|
|
2265
2402
|
registerMemoryImport(memory);
|
|
2403
|
+
registerMemoryDigest(memory);
|
|
2266
2404
|
var session = program.command("session").description("Manage session lifecycle");
|
|
2267
2405
|
registerSessionEnd(session);
|
|
2268
2406
|
program.parseAsync(process.argv).catch((err) => {
|