repowise 0.1.88 → 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 +106 -13
- 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) {
|
|
@@ -3241,6 +3322,7 @@ async function create() {
|
|
|
3241
3322
|
let repoRoot;
|
|
3242
3323
|
let repoPlatform;
|
|
3243
3324
|
let repoExternalId;
|
|
3325
|
+
let repoLookupError;
|
|
3244
3326
|
spinner.start("Checking for pending repository...");
|
|
3245
3327
|
try {
|
|
3246
3328
|
const pending = await apiRequest("/v1/onboarding/pending");
|
|
@@ -3276,7 +3358,8 @@ async function create() {
|
|
|
3276
3358
|
repoPlatform = match.platform;
|
|
3277
3359
|
repoExternalId = match.externalId;
|
|
3278
3360
|
}
|
|
3279
|
-
} catch {
|
|
3361
|
+
} catch (err) {
|
|
3362
|
+
repoLookupError = err instanceof Error ? err.message : String(err);
|
|
3280
3363
|
}
|
|
3281
3364
|
} else {
|
|
3282
3365
|
try {
|
|
@@ -3285,11 +3368,15 @@ async function create() {
|
|
|
3285
3368
|
}
|
|
3286
3369
|
}
|
|
3287
3370
|
if (!repoId) {
|
|
3288
|
-
|
|
3289
|
-
chalk5.red(
|
|
3290
|
-
|
|
3291
|
-
|
|
3292
|
-
|
|
3371
|
+
if (repoLookupError) {
|
|
3372
|
+
spinner.fail(chalk5.red(`Failed to look up repositories: ${repoLookupError}`));
|
|
3373
|
+
} else {
|
|
3374
|
+
spinner.fail(
|
|
3375
|
+
chalk5.red(
|
|
3376
|
+
"Could not find this repository in your RepoWise account. Connect it on the dashboard first."
|
|
3377
|
+
)
|
|
3378
|
+
);
|
|
3379
|
+
}
|
|
3293
3380
|
process.exitCode = 1;
|
|
3294
3381
|
return;
|
|
3295
3382
|
}
|
|
@@ -4044,6 +4131,7 @@ async function sync() {
|
|
|
4044
4131
|
let repoId;
|
|
4045
4132
|
let repoPlatform;
|
|
4046
4133
|
let repoExternalId;
|
|
4134
|
+
let repoLookupError;
|
|
4047
4135
|
spinner.start("Resolving repository...");
|
|
4048
4136
|
try {
|
|
4049
4137
|
const repos = await apiRequest("/v1/repos");
|
|
@@ -4053,14 +4141,19 @@ async function sync() {
|
|
|
4053
4141
|
repoPlatform = match.platform;
|
|
4054
4142
|
repoExternalId = match.externalId;
|
|
4055
4143
|
}
|
|
4056
|
-
} catch {
|
|
4144
|
+
} catch (err) {
|
|
4145
|
+
repoLookupError = err instanceof Error ? err.message : String(err);
|
|
4057
4146
|
}
|
|
4058
4147
|
if (!repoId) {
|
|
4059
|
-
|
|
4060
|
-
chalk9.red(
|
|
4061
|
-
|
|
4062
|
-
|
|
4063
|
-
|
|
4148
|
+
if (repoLookupError) {
|
|
4149
|
+
spinner.fail(chalk9.red(`Failed to look up repositories: ${repoLookupError}`));
|
|
4150
|
+
} else {
|
|
4151
|
+
spinner.fail(
|
|
4152
|
+
chalk9.red(
|
|
4153
|
+
"Could not find this repository in your RepoWise account. Run `repowise create` first."
|
|
4154
|
+
)
|
|
4155
|
+
);
|
|
4156
|
+
}
|
|
4064
4157
|
process.exitCode = 1;
|
|
4065
4158
|
return;
|
|
4066
4159
|
}
|