repowise 0.1.89 → 0.1.90
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/bin/repowise.js +82 -1
- package/package.json +1 -1
package/dist/bin/repowise.js
CHANGED
|
@@ -321,6 +321,51 @@ async function scanLocalContextFiles(repoRoot, contextFolder) {
|
|
|
321
321
|
}
|
|
322
322
|
}
|
|
323
323
|
|
|
324
|
+
// ../../packages/shared/dist/lib/project-overview-injection.js
|
|
325
|
+
var START_MARKER = "<!-- repowise:agent-instructions:start -->";
|
|
326
|
+
var END_MARKER = "<!-- repowise:agent-instructions:end -->";
|
|
327
|
+
var AI_AGENT_USAGE_INSTRUCTIONS = `${START_MARKER}
|
|
328
|
+
## How AI Agents Should Use This Context
|
|
329
|
+
|
|
330
|
+
This document is the **entry point** for RepoWise's pre-analyzed codebase context. The \`repowise-context/\` folder contains architecture, API contracts, data models, coding patterns, user flows, and domain knowledge \u2014 pre-extracted so AI agents can answer most questions without searching the codebase.
|
|
331
|
+
|
|
332
|
+
**Rules for using this context:**
|
|
333
|
+
|
|
334
|
+
1. **Route first.** Use the *Context File Routing Map* below to identify which file(s) cover the domain of the current task. Files are organized by scope (root = cross-cutting, \`apps/<name>/\` = app-specific) and by concern (architecture, data models, API contracts, coding patterns, etc.).
|
|
335
|
+
|
|
336
|
+
2. **Read before searching.** Consult the matching context file(s) before running grep/glob or reading source files. These files are the authoritative source for architecture, patterns, and conventions in this project.
|
|
337
|
+
|
|
338
|
+
3. **Fall back when needed.** If the context files don't cover the question \u2014 or if the question is about ephemeral state (recent commits, branch status, in-flight work) \u2014 then use code search.
|
|
339
|
+
|
|
340
|
+
4. **Propagate to subagents.** When delegating work to a sub-task or spawning another agent, explicitly instruct it to read \`repowise-context/project-overview.md\` first. Subagents do not inherit the parent agent's instructions automatically.
|
|
341
|
+
|
|
342
|
+
5. **Don't edit these files manually.** The \`repowise-context/\` folder is regenerated by RepoWise on every sync. Manual edits will be overwritten. Update the source code and let the next sync regenerate the context.
|
|
343
|
+
${END_MARKER}`;
|
|
344
|
+
function injectAgentInstructions(content) {
|
|
345
|
+
const lineEnding = content.includes("\r\n") ? "\r\n" : "\n";
|
|
346
|
+
const canonicalBlock = AI_AGENT_USAGE_INSTRUCTIONS.replace(/\n/g, lineEnding);
|
|
347
|
+
const startIdx = content.indexOf(START_MARKER);
|
|
348
|
+
const endIdx = content.indexOf(END_MARKER);
|
|
349
|
+
if (startIdx >= 0 && endIdx > startIdx) {
|
|
350
|
+
const currentBlock = content.slice(startIdx, endIdx + END_MARKER.length);
|
|
351
|
+
if (currentBlock === canonicalBlock) {
|
|
352
|
+
return content;
|
|
353
|
+
}
|
|
354
|
+
return content.slice(0, startIdx) + canonicalBlock + content.slice(endIdx + END_MARKER.length);
|
|
355
|
+
}
|
|
356
|
+
const h1Match = content.match(/^# Project Overview\s*$/m);
|
|
357
|
+
if (h1Match && h1Match.index !== void 0) {
|
|
358
|
+
const insertAt = h1Match.index + h1Match[0].length;
|
|
359
|
+
return content.slice(0, insertAt) + lineEnding + lineEnding + canonicalBlock + content.slice(insertAt);
|
|
360
|
+
}
|
|
361
|
+
const h2Match = content.match(/^## Summary\s*$/m);
|
|
362
|
+
if (h2Match && h2Match.index !== void 0) {
|
|
363
|
+
const insertAt = h2Match.index + h2Match[0].length;
|
|
364
|
+
return content.slice(0, insertAt) + lineEnding + lineEnding + canonicalBlock + content.slice(insertAt);
|
|
365
|
+
}
|
|
366
|
+
return canonicalBlock + lineEnding + lineEnding + content;
|
|
367
|
+
}
|
|
368
|
+
|
|
324
369
|
// ../listener/dist/lib/config.js
|
|
325
370
|
import { readFile as readFile2, writeFile as writeFile2, rename, unlink as unlink2, mkdir as mkdir2, chmod } from "fs/promises";
|
|
326
371
|
import { join as join3 } from "path";
|
|
@@ -912,7 +957,8 @@ async function fetchContextFromServer(repoId, localPath, apiUrl) {
|
|
|
912
957
|
const content = await contentRes.text();
|
|
913
958
|
const filePath = join8(contextDir, file.fileName);
|
|
914
959
|
await mkdir5(dirname3(filePath), { recursive: true });
|
|
915
|
-
|
|
960
|
+
const finalContent = file.fileName === "project-overview.md" ? injectAgentInstructions(content) : content;
|
|
961
|
+
await writeFile5(filePath, finalContent, "utf-8");
|
|
916
962
|
updatedFiles.push(file.fileName);
|
|
917
963
|
}
|
|
918
964
|
console.log(`Context fetch for ${repoId}: downloaded ${updatedFiles.length}/${files.length} file(s)`);
|
|
@@ -1674,6 +1720,31 @@ async function checkStaleContext(repos, state, groups) {
|
|
|
1674
1720
|
}
|
|
1675
1721
|
return dirty;
|
|
1676
1722
|
}
|
|
1723
|
+
async function reconcileAgentInstructions(repos) {
|
|
1724
|
+
for (const repo of repos) {
|
|
1725
|
+
const path = join13(repo.localPath, "repowise-context", "project-overview.md");
|
|
1726
|
+
let content;
|
|
1727
|
+
try {
|
|
1728
|
+
content = await readFile6(path, "utf-8");
|
|
1729
|
+
} catch (err) {
|
|
1730
|
+
const code = err?.code;
|
|
1731
|
+
if (code === "ENOENT" || code === "ENOTDIR" || code === "EACCES" || code === "EPERM" || code === "EISDIR") {
|
|
1732
|
+
continue;
|
|
1733
|
+
}
|
|
1734
|
+
console.warn(`[reconcile] read failed for ${repo.repoId}:`, err instanceof Error ? err.message : String(err));
|
|
1735
|
+
continue;
|
|
1736
|
+
}
|
|
1737
|
+
const injected = injectAgentInstructions(content);
|
|
1738
|
+
if (injected === content)
|
|
1739
|
+
continue;
|
|
1740
|
+
try {
|
|
1741
|
+
await writeFile8(path, injected, "utf-8");
|
|
1742
|
+
console.log(`[reconcile] Reconciled agent instructions for ${repo.repoId}`);
|
|
1743
|
+
} catch (err) {
|
|
1744
|
+
console.warn(`[reconcile] write failed for ${repo.repoId}:`, err instanceof Error ? err.message : String(err));
|
|
1745
|
+
}
|
|
1746
|
+
}
|
|
1747
|
+
}
|
|
1677
1748
|
async function startListener() {
|
|
1678
1749
|
running = true;
|
|
1679
1750
|
const configDir = getConfigDir();
|
|
@@ -1810,6 +1881,11 @@ async function startListener() {
|
|
|
1810
1881
|
console.error = (...args) => origError(`[${ts()}]`, ...args);
|
|
1811
1882
|
console.warn = (...args) => origWarn(`[${ts()}]`, ...args);
|
|
1812
1883
|
console.log(`RepoWise Listener started \u2014 watching ${allRepoIds.length} repo(s)`);
|
|
1884
|
+
try {
|
|
1885
|
+
await reconcileAgentInstructions(config2.repos);
|
|
1886
|
+
} catch (err) {
|
|
1887
|
+
console.warn("[reconcile] Initial agent instructions reconciliation failed:", err instanceof Error ? err.message : String(err));
|
|
1888
|
+
}
|
|
1813
1889
|
const shutdown = async () => {
|
|
1814
1890
|
console.log("Shutting down...");
|
|
1815
1891
|
stop();
|
|
@@ -1946,6 +2022,11 @@ async function startListener() {
|
|
|
1946
2022
|
} catch (err) {
|
|
1947
2023
|
console.warn("[self-heal] Stale context check failed:", err instanceof Error ? err.message : String(err));
|
|
1948
2024
|
}
|
|
2025
|
+
try {
|
|
2026
|
+
await reconcileAgentInstructions(config2.repos);
|
|
2027
|
+
} catch (err) {
|
|
2028
|
+
console.warn("[reconcile] Agent instructions reconciliation failed:", err instanceof Error ? err.message : String(err));
|
|
2029
|
+
}
|
|
1949
2030
|
}
|
|
1950
2031
|
if (latestCliVersion && currentVersion && !config2.noAutoUpdate && (state.crashCount ?? 0) < CRASH_LOOP_THRESHOLD) {
|
|
1951
2032
|
if (latestCliVersion !== state.lastUpdateTargetVersion) {
|