docdex 0.2.23 → 0.2.24
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/assets/agents.md +36 -14
- package/lib/postinstall_setup.js +286 -18
- package/package.json +1 -1
package/assets/agents.md
CHANGED
|
@@ -1,3 +1,12 @@
|
|
|
1
|
+
## Priority Directives (Mandatory)
|
|
2
|
+
|
|
3
|
+
- Always use both memory lobes early: docdex_get_profile + docdex_memory_recall; save new facts via docdex_memory_save and new preferences via docdex_save_preference.
|
|
4
|
+
- Maintain agent-specific profile memory: use your agent_id with docdex_get_profile/docdex_save_preference; store generic self-knowledge (role, tooling, preferences).
|
|
5
|
+
- Use impact analysis for every code change: call HTTP /v1/graph/impact?file=... and account for inbound/outbound deps; if unavailable, state it and proceed cautiously.
|
|
6
|
+
- Apply DAG reasoning for planning: prefer dependency graph facts (impact results and /v1/dag/export) to choose the right change order and scope.
|
|
7
|
+
- Use Docdex tools intentionally: docdex_search/symbols/ast for repo truth; docdex_stats/files/repo_inspect/index for index health.
|
|
8
|
+
- When you do not know something, run docdex_web_research (force_web=true). Web research is encouraged by default for non-repo facts and external APIs.
|
|
9
|
+
|
|
1
10
|
# Docdex Agent Usage Instructions
|
|
2
11
|
|
|
3
12
|
> Context for AI Agents: Docdex is your local-first Dual-Lobe Memory and Code Intelligence daemon. Unlike simple vector stores, it provides structural understanding of code (AST/Graph), persistent behavioral profiles (Agent Memory), and gated web enrichment, all strictly scoped to the local machine.
|
|
@@ -33,6 +42,7 @@ Docdex v2.1 introduces a strict separation between "facts" and "preferences." Us
|
|
|
33
42
|
- Content: Your persona, user preferences, coding style, tooling constraints.
|
|
34
43
|
- Example: "Always use Zod for validation," or "User prefers strict TypeScript types."
|
|
35
44
|
- Tools: docdex_save_preference, docdex_get_profile
|
|
45
|
+
- Agent-specific: Each agent should use its own agent_id and store generic self-knowledge (role, tooling, preferences).
|
|
36
46
|
- Usage: Use this to "learn" from corrections. If a user corrects your style, save it here so you do not repeat the mistake in a different repo.
|
|
37
47
|
|
|
38
48
|
## Tool Capabilities (MCP & HTTP)
|
|
@@ -46,20 +56,6 @@ Standard retrieval. The daemon automatically handles the waterfall (Local -> Web
|
|
|
46
56
|
| docdex_search | Search code, docs, and ingested libraries. Returns ranked snippets. |
|
|
47
57
|
| docdex_web_research | Explicitly trigger Tier 2 web discovery (DDG + Headless Chrome). Use when you need external docs not present locally. |
|
|
48
58
|
|
|
49
|
-
Tier 2 discovery providers (in fallback order when DDG HTML fails or is blocked):
|
|
50
|
-
- DuckDuckGo Lite
|
|
51
|
-
- SearXNG JSON (public instance or self-hosted)
|
|
52
|
-
- Google Mobile
|
|
53
|
-
- Brave Search API (requires DOCDEX_BRAVE_API_KEY)
|
|
54
|
-
- Google Custom Search JSON API (requires DOCDEX_GOOGLE_CSE_API_KEY + DOCDEX_GOOGLE_CSE_CX)
|
|
55
|
-
- Bing Web Search API (requires DOCDEX_BING_API_KEY)
|
|
56
|
-
- Tavily API (requires DOCDEX_TAVILY_API_KEY)
|
|
57
|
-
- Exa API (requires DOCDEX_EXA_API_KEY)
|
|
58
|
-
|
|
59
|
-
Defaults and overrides:
|
|
60
|
-
- Default endpoints: `https://html.duckduckgo.com/html/`, `https://lite.duckduckgo.com/lite/`, `https://searx.be/search` (built-in fallback list), `https://www.google.com/m`, `https://api.search.brave.com/res/v1/web/search`, `https://www.googleapis.com/customsearch/v1`, `https://api.bing.microsoft.com/v7.0/search`, `https://api.tavily.com/search`, `https://api.exa.ai/search`
|
|
61
|
-
- Override envs: `DOCDEX_DDG_BASE_URL`, `DOCDEX_WEB_SEARXNG_URLS` (comma list, or `DOCDEX_SEARXNG_URLS`), `DOCDEX_WEB_GOOGLE_MOBILE_URL`, `DOCDEX_BRAVE_API_KEY` + `DOCDEX_BRAVE_API_URL`, `DOCDEX_GOOGLE_CSE_API_KEY` + `DOCDEX_GOOGLE_CSE_CX` + `DOCDEX_GOOGLE_CSE_API_URL`, `DOCDEX_BING_API_KEY` + `DOCDEX_BING_API_URL`, `DOCDEX_TAVILY_API_KEY` + `DOCDEX_TAVILY_API_URL`, `DOCDEX_EXA_API_KEY` + `DOCDEX_EXA_API_URL`
|
|
62
|
-
|
|
63
59
|
### B. Code Intelligence (AST & Graph)
|
|
64
60
|
|
|
65
61
|
Precision tools for structural analysis. Do not rely on text search for definitions or dependencies.
|
|
@@ -80,6 +76,17 @@ Precision tools for structural analysis. Do not rely on text search for definiti
|
|
|
80
76
|
| docdex_save_preference | Store a global user preference (Style, Tooling, Constraint). |
|
|
81
77
|
| docdex_get_profile | Retrieve global preferences. |
|
|
82
78
|
|
|
79
|
+
## Quick Tool Map (Often Missed)
|
|
80
|
+
|
|
81
|
+
- docdex_files: List indexed docs with rel_path/doc_id/token_estimate; use to verify indexing coverage.
|
|
82
|
+
- docdex_stats: Show index size, state dir, and last update time.
|
|
83
|
+
- docdex_repo_inspect: Confirm normalized repo root and repo identity mapping.
|
|
84
|
+
- docdex_index: Reindex the full repo or ingest specific files when stale.
|
|
85
|
+
- docdex_search diff: Limit search to working tree, staged, or ref ranges; filter by paths.
|
|
86
|
+
- docdex_web_research knobs: force_web, skip_local_search, repo_only, no_cache, web_limit, llm_filter_local_results, llm_model.
|
|
87
|
+
- HTTP /v1/initialize: Bind a default repo root for MCP when clients omit project_root.
|
|
88
|
+
- HTTP /v1/dag/export: Export the dependency graph for external analysis.
|
|
89
|
+
|
|
83
90
|
## Interaction Patterns
|
|
84
91
|
|
|
85
92
|
### 1. Reasoning Workflow
|
|
@@ -107,6 +114,21 @@ If the user asks: "Safe to delete getUser?"
|
|
|
107
114
|
- Action: Call GET /v1/graph/impact?file=src/user.ts
|
|
108
115
|
- Output: Analyze the inbound edges. If the list is not empty, it is unsafe.
|
|
109
116
|
|
|
117
|
+
### 4. Non-Repo Real-World Queries (Web First)
|
|
118
|
+
|
|
119
|
+
If the user asks a non-repo, real-world question (weather, news, general facts), immediately call docdex_web_research with force_web=true.
|
|
120
|
+
- Resolve relative dates ("yesterday", "last week") using system time by default.
|
|
121
|
+
- Do not run docdex_search unless the user explicitly wants repo-local context.
|
|
122
|
+
- Assume web access is allowed unless the user forbids it; if the web call fails, report the failure and ask for a source or permission.
|
|
123
|
+
|
|
124
|
+
### 5. Failure Handling (Missing Results or Errors)
|
|
125
|
+
|
|
126
|
+
- Ensure project_root or repo_path is set, or call /v1/initialize to bind a default root.
|
|
127
|
+
- Use docdex_repo_inspect to confirm repo identity and normalized root.
|
|
128
|
+
- Use docdex_stats and docdex_files to check whether the index exists and contains files.
|
|
129
|
+
- Reindex with docdex_index (or docdexd index) if the index is stale or empty.
|
|
130
|
+
- Add a repo-local .docdexignore for large generated artifacts or local caches when indexing is slow.
|
|
131
|
+
|
|
110
132
|
## Operational Context
|
|
111
133
|
|
|
112
134
|
### Repository Identification
|
package/lib/postinstall_setup.js
CHANGED
|
@@ -563,7 +563,7 @@ function upsertClaudeInstructions(pathname, instructions) {
|
|
|
563
563
|
return true;
|
|
564
564
|
}
|
|
565
565
|
|
|
566
|
-
function
|
|
566
|
+
function upsertContinueJsonInstructions(pathname, instructions) {
|
|
567
567
|
const { value } = readJson(pathname);
|
|
568
568
|
if (typeof value !== "object" || value == null || Array.isArray(value)) return false;
|
|
569
569
|
const merged = mergeInstructionText(value.systemMessage, instructions);
|
|
@@ -573,6 +573,198 @@ function upsertContinueInstructions(pathname, instructions) {
|
|
|
573
573
|
return true;
|
|
574
574
|
}
|
|
575
575
|
|
|
576
|
+
function countLeadingWhitespace(line) {
|
|
577
|
+
const match = line.match(/^\s*/);
|
|
578
|
+
return match ? match[0].length : 0;
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
function isYamlTopLevelKey(line, baseIndent) {
|
|
582
|
+
const indent = countLeadingWhitespace(line);
|
|
583
|
+
if (indent > baseIndent) return false;
|
|
584
|
+
const trimmed = line.trimStart();
|
|
585
|
+
if (!trimmed || trimmed.startsWith("#") || trimmed.startsWith("-")) return false;
|
|
586
|
+
return trimmed.includes(":");
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
function hasYamlContent(lines) {
|
|
590
|
+
return lines.some((line) => {
|
|
591
|
+
const trimmed = line.trim();
|
|
592
|
+
return trimmed && !trimmed.startsWith("#");
|
|
593
|
+
});
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
function splitInlineYamlList(value) {
|
|
597
|
+
const trimmed = String(value || "").trim();
|
|
598
|
+
if (trimmed === "[]") return [];
|
|
599
|
+
if (!trimmed.startsWith("[") || !trimmed.endsWith("]")) return null;
|
|
600
|
+
const inner = trimmed.slice(1, -1);
|
|
601
|
+
const items = [];
|
|
602
|
+
let current = "";
|
|
603
|
+
let inSingle = false;
|
|
604
|
+
let inDouble = false;
|
|
605
|
+
let escaped = false;
|
|
606
|
+
for (const ch of inner) {
|
|
607
|
+
if (escaped) {
|
|
608
|
+
current += ch;
|
|
609
|
+
escaped = false;
|
|
610
|
+
continue;
|
|
611
|
+
}
|
|
612
|
+
if (ch === "\\\\") {
|
|
613
|
+
escaped = true;
|
|
614
|
+
current += ch;
|
|
615
|
+
continue;
|
|
616
|
+
}
|
|
617
|
+
if (ch === "'" && !inDouble) {
|
|
618
|
+
inSingle = !inSingle;
|
|
619
|
+
current += ch;
|
|
620
|
+
continue;
|
|
621
|
+
}
|
|
622
|
+
if (ch === '"' && !inSingle) {
|
|
623
|
+
inDouble = !inDouble;
|
|
624
|
+
current += ch;
|
|
625
|
+
continue;
|
|
626
|
+
}
|
|
627
|
+
if (ch === "," && !inSingle && !inDouble) {
|
|
628
|
+
const next = current.trim();
|
|
629
|
+
if (next) items.push(next);
|
|
630
|
+
current = "";
|
|
631
|
+
continue;
|
|
632
|
+
}
|
|
633
|
+
current += ch;
|
|
634
|
+
}
|
|
635
|
+
const next = current.trim();
|
|
636
|
+
if (next) items.push(next);
|
|
637
|
+
return items;
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
function inlineRulesToItems(value, itemIndent) {
|
|
641
|
+
const trimmed = String(value || "").trim();
|
|
642
|
+
if (!trimmed) return [];
|
|
643
|
+
const prefix = " ".repeat(itemIndent);
|
|
644
|
+
const split = splitInlineYamlList(trimmed);
|
|
645
|
+
if (split) {
|
|
646
|
+
return split.map((item) => [`${prefix}- ${item}`]).filter((item) => item[0].trim() !== `${prefix}-`);
|
|
647
|
+
}
|
|
648
|
+
return [[`${prefix}- ${trimmed}`]];
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
function buildYamlRuleBlock(itemIndent, instructions) {
|
|
652
|
+
const prefix = " ".repeat(itemIndent);
|
|
653
|
+
const contentPrefix = " ".repeat(itemIndent + 2);
|
|
654
|
+
const lines = [`${prefix}- |`];
|
|
655
|
+
for (const line of String(instructions).split(/\r?\n/)) {
|
|
656
|
+
lines.push(`${contentPrefix}${line}`);
|
|
657
|
+
}
|
|
658
|
+
return lines;
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
function rewriteContinueYamlRules(source, instructions, addDocdex) {
|
|
662
|
+
const lines = String(source || "").split(/\r?\n/);
|
|
663
|
+
const ruleLineRe = /^(\s*)rules\s*:(.*)$/;
|
|
664
|
+
let rulesIndex = -1;
|
|
665
|
+
let rulesIndent = 0;
|
|
666
|
+
let rulesInline = "";
|
|
667
|
+
for (let i = 0; i < lines.length; i += 1) {
|
|
668
|
+
const match = lines[i].match(ruleLineRe);
|
|
669
|
+
if (!match) continue;
|
|
670
|
+
rulesIndex = i;
|
|
671
|
+
rulesIndent = match[1]?.length || 0;
|
|
672
|
+
rulesInline = (match[2] || "").trim();
|
|
673
|
+
if (rulesInline.includes("#")) {
|
|
674
|
+
rulesInline = rulesInline.split("#")[0].trim();
|
|
675
|
+
}
|
|
676
|
+
if (rulesInline.startsWith("#")) rulesInline = "";
|
|
677
|
+
break;
|
|
678
|
+
}
|
|
679
|
+
|
|
680
|
+
if (rulesIndex === -1) {
|
|
681
|
+
if (!addDocdex) return null;
|
|
682
|
+
const trimmed = String(source || "").trimEnd();
|
|
683
|
+
const docdexBlock = buildYamlRuleBlock(2, instructions);
|
|
684
|
+
const prefix = trimmed ? `${trimmed}\n\n` : "";
|
|
685
|
+
return `${prefix}rules:\n${docdexBlock.join("\n")}`;
|
|
686
|
+
}
|
|
687
|
+
|
|
688
|
+
let endIndex = lines.length;
|
|
689
|
+
for (let i = rulesIndex + 1; i < lines.length; i += 1) {
|
|
690
|
+
if (isYamlTopLevelKey(lines[i], rulesIndent)) {
|
|
691
|
+
endIndex = i;
|
|
692
|
+
break;
|
|
693
|
+
}
|
|
694
|
+
}
|
|
695
|
+
const blockLines = lines.slice(rulesIndex + 1, endIndex);
|
|
696
|
+
const preLines = [];
|
|
697
|
+
const items = [];
|
|
698
|
+
let currentItem = [];
|
|
699
|
+
let itemIndent = null;
|
|
700
|
+
let startedItems = false;
|
|
701
|
+
|
|
702
|
+
for (const line of blockLines) {
|
|
703
|
+
const trimmed = line.trimStart();
|
|
704
|
+
const indent = countLeadingWhitespace(line);
|
|
705
|
+
const isItem = trimmed.startsWith("-") && indent > rulesIndent;
|
|
706
|
+
if (isItem) {
|
|
707
|
+
if (itemIndent == null) itemIndent = indent;
|
|
708
|
+
if (indent === itemIndent) {
|
|
709
|
+
if (startedItems && currentItem.length) {
|
|
710
|
+
items.push(currentItem);
|
|
711
|
+
currentItem = [];
|
|
712
|
+
}
|
|
713
|
+
startedItems = true;
|
|
714
|
+
}
|
|
715
|
+
currentItem.push(line);
|
|
716
|
+
continue;
|
|
717
|
+
}
|
|
718
|
+
if (startedItems) {
|
|
719
|
+
currentItem.push(line);
|
|
720
|
+
} else {
|
|
721
|
+
preLines.push(line);
|
|
722
|
+
}
|
|
723
|
+
}
|
|
724
|
+
if (currentItem.length) items.push(currentItem);
|
|
725
|
+
|
|
726
|
+
const inferredIndent = itemIndent == null ? rulesIndent + 2 : itemIndent;
|
|
727
|
+
if (!items.length && rulesInline) {
|
|
728
|
+
items.push(...inlineRulesToItems(rulesInline, inferredIndent));
|
|
729
|
+
rulesInline = "";
|
|
730
|
+
}
|
|
731
|
+
|
|
732
|
+
const keptItems = items.filter((item) => {
|
|
733
|
+
const text = item.join("\n");
|
|
734
|
+
return !(text.includes(DOCDEX_INFO_START_PREFIX) && text.includes(DOCDEX_INFO_END));
|
|
735
|
+
});
|
|
736
|
+
|
|
737
|
+
if (addDocdex) {
|
|
738
|
+
keptItems.push(buildYamlRuleBlock(inferredIndent, instructions));
|
|
739
|
+
}
|
|
740
|
+
|
|
741
|
+
const removeRulesBlock =
|
|
742
|
+
!addDocdex && !keptItems.length && !hasYamlContent(preLines) && !rulesInline;
|
|
743
|
+
|
|
744
|
+
const output = [];
|
|
745
|
+
output.push(...lines.slice(0, rulesIndex));
|
|
746
|
+
if (!removeRulesBlock) {
|
|
747
|
+
output.push(`${" ".repeat(rulesIndent)}rules:`);
|
|
748
|
+
output.push(...preLines);
|
|
749
|
+
for (const item of keptItems) {
|
|
750
|
+
output.push(...item);
|
|
751
|
+
}
|
|
752
|
+
}
|
|
753
|
+
output.push(...lines.slice(endIndex));
|
|
754
|
+
const next = output.join("\n");
|
|
755
|
+
return next === source ? null : next;
|
|
756
|
+
}
|
|
757
|
+
|
|
758
|
+
function upsertContinueYamlRules(pathname, instructions) {
|
|
759
|
+
if (!fs.existsSync(pathname)) return false;
|
|
760
|
+
const normalized = normalizeInstructionText(instructions);
|
|
761
|
+
if (!normalized) return false;
|
|
762
|
+
const current = fs.readFileSync(pathname, "utf8");
|
|
763
|
+
const updated = rewriteContinueYamlRules(current, normalized, true);
|
|
764
|
+
if (!updated) return false;
|
|
765
|
+
return writeTextFile(pathname, updated);
|
|
766
|
+
}
|
|
767
|
+
|
|
576
768
|
function upsertZedInstructions(pathname, instructions) {
|
|
577
769
|
const { value } = readJson(pathname);
|
|
578
770
|
if (typeof value !== "object" || value == null || Array.isArray(value)) return false;
|
|
@@ -586,12 +778,56 @@ function upsertZedInstructions(pathname, instructions) {
|
|
|
586
778
|
return true;
|
|
587
779
|
}
|
|
588
780
|
|
|
589
|
-
function
|
|
781
|
+
function upsertVsCodeInstructionKey(value, key, instructions) {
|
|
782
|
+
const existing = typeof value[key] === "string" ? value[key] : "";
|
|
783
|
+
const merged = mergeInstructionText(existing, instructions);
|
|
784
|
+
if (!merged || merged === existing) return false;
|
|
785
|
+
value[key] = merged;
|
|
786
|
+
return true;
|
|
787
|
+
}
|
|
788
|
+
|
|
789
|
+
function upsertVsCodeInstructionLocations(value, instructionsDir) {
|
|
790
|
+
const key = "chat.instructionsFilesLocations";
|
|
791
|
+
const location = String(instructionsDir);
|
|
792
|
+
if (value[key] && typeof value[key] === "object" && !Array.isArray(value[key])) {
|
|
793
|
+
if (value[key][location] === true) return false;
|
|
794
|
+
value[key][location] = true;
|
|
795
|
+
return true;
|
|
796
|
+
}
|
|
797
|
+
if (Array.isArray(value[key])) {
|
|
798
|
+
if (value[key].some((entry) => entry === location)) return false;
|
|
799
|
+
value[key].push(location);
|
|
800
|
+
return true;
|
|
801
|
+
}
|
|
802
|
+
if (typeof value[key] === "string") {
|
|
803
|
+
if (value[key] === location) return false;
|
|
804
|
+
value[key] = [value[key], location];
|
|
805
|
+
return true;
|
|
806
|
+
}
|
|
807
|
+
value[key] = { [location]: true };
|
|
808
|
+
return true;
|
|
809
|
+
}
|
|
810
|
+
|
|
811
|
+
function upsertVsCodeInstructions(pathname, instructions, instructionsDir) {
|
|
590
812
|
const { value } = readJson(pathname);
|
|
591
813
|
if (typeof value !== "object" || value == null || Array.isArray(value)) return false;
|
|
592
|
-
const
|
|
593
|
-
if (
|
|
594
|
-
|
|
814
|
+
const normalized = normalizeInstructionText(instructions);
|
|
815
|
+
if (!normalized) return false;
|
|
816
|
+
let updated = false;
|
|
817
|
+
if (upsertVsCodeInstructionKey(value, "github.copilot.chat.codeGeneration.instructions", instructions)) {
|
|
818
|
+
updated = true;
|
|
819
|
+
}
|
|
820
|
+
if (upsertVsCodeInstructionKey(value, "copilot.chat.codeGeneration.instructions", instructions)) {
|
|
821
|
+
updated = true;
|
|
822
|
+
}
|
|
823
|
+
if (value["github.copilot.chat.codeGeneration.useInstructionFiles"] !== true) {
|
|
824
|
+
value["github.copilot.chat.codeGeneration.useInstructionFiles"] = true;
|
|
825
|
+
updated = true;
|
|
826
|
+
}
|
|
827
|
+
if (upsertVsCodeInstructionLocations(value, instructionsDir)) {
|
|
828
|
+
updated = true;
|
|
829
|
+
}
|
|
830
|
+
if (!updated) return false;
|
|
595
831
|
writeJson(pathname, value);
|
|
596
832
|
return true;
|
|
597
833
|
}
|
|
@@ -921,6 +1157,12 @@ function clientInstructionPaths() {
|
|
|
921
1157
|
const appData = process.env.APPDATA || path.join(home, "AppData", "Roaming");
|
|
922
1158
|
const userProfile = process.env.USERPROFILE || home;
|
|
923
1159
|
const vscodeGlobalInstructions = path.join(home, ".vscode", "global_instructions.md");
|
|
1160
|
+
const vscodeInstructionsDir = path.join(home, ".vscode", "instructions");
|
|
1161
|
+
const vscodeInstructionsFile = path.join(vscodeInstructionsDir, "docdex.md");
|
|
1162
|
+
const continueRoot = path.join(userProfile, ".continue");
|
|
1163
|
+
const continueJson = path.join(continueRoot, "config.json");
|
|
1164
|
+
const continueYaml = path.join(continueRoot, "config.yaml");
|
|
1165
|
+
const continueYml = path.join(continueRoot, "config.yml");
|
|
924
1166
|
const windsurfGlobalRules = path.join(userProfile, ".codeium", "windsurf", "memories", "global_rules.md");
|
|
925
1167
|
const rooRules = path.join(home, ".roo", "rules", "docdex.md");
|
|
926
1168
|
const pearaiAgent = path.join(home, ".config", "pearai", "agent.md");
|
|
@@ -932,10 +1174,14 @@ function clientInstructionPaths() {
|
|
|
932
1174
|
case "win32":
|
|
933
1175
|
return {
|
|
934
1176
|
claude: path.join(appData, "Claude", "claude_desktop_config.json"),
|
|
935
|
-
continue:
|
|
1177
|
+
continue: continueJson,
|
|
1178
|
+
continueYaml,
|
|
1179
|
+
continueYml,
|
|
936
1180
|
zed: path.join(appData, "Zed", "settings.json"),
|
|
937
1181
|
vscodeSettings: path.join(appData, "Code", "User", "settings.json"),
|
|
938
1182
|
vscodeGlobalInstructions,
|
|
1183
|
+
vscodeInstructionsDir,
|
|
1184
|
+
vscodeInstructionsFile,
|
|
939
1185
|
windsurfGlobalRules,
|
|
940
1186
|
rooRules,
|
|
941
1187
|
pearaiAgent,
|
|
@@ -947,10 +1193,14 @@ function clientInstructionPaths() {
|
|
|
947
1193
|
case "darwin":
|
|
948
1194
|
return {
|
|
949
1195
|
claude: path.join(home, "Library", "Application Support", "Claude", "claude_desktop_config.json"),
|
|
950
|
-
continue:
|
|
1196
|
+
continue: continueJson,
|
|
1197
|
+
continueYaml,
|
|
1198
|
+
continueYml,
|
|
951
1199
|
zed: path.join(home, ".config", "zed", "settings.json"),
|
|
952
1200
|
vscodeSettings: path.join(home, "Library", "Application Support", "Code", "User", "settings.json"),
|
|
953
1201
|
vscodeGlobalInstructions,
|
|
1202
|
+
vscodeInstructionsDir,
|
|
1203
|
+
vscodeInstructionsFile,
|
|
954
1204
|
windsurfGlobalRules,
|
|
955
1205
|
rooRules,
|
|
956
1206
|
pearaiAgent,
|
|
@@ -962,10 +1212,14 @@ function clientInstructionPaths() {
|
|
|
962
1212
|
default:
|
|
963
1213
|
return {
|
|
964
1214
|
claude: path.join(home, ".config", "Claude", "claude_desktop_config.json"),
|
|
965
|
-
continue:
|
|
1215
|
+
continue: continueJson,
|
|
1216
|
+
continueYaml,
|
|
1217
|
+
continueYml,
|
|
966
1218
|
zed: path.join(home, ".config", "zed", "settings.json"),
|
|
967
1219
|
vscodeSettings: path.join(home, ".config", "Code", "User", "settings.json"),
|
|
968
1220
|
vscodeGlobalInstructions,
|
|
1221
|
+
vscodeInstructionsDir,
|
|
1222
|
+
vscodeInstructionsFile,
|
|
969
1223
|
windsurfGlobalRules,
|
|
970
1224
|
rooRules,
|
|
971
1225
|
pearaiAgent,
|
|
@@ -1045,8 +1299,15 @@ function applyAgentInstructions({ logger } = {}) {
|
|
|
1045
1299
|
upsertPromptFile(paths.vscodeGlobalInstructions, instructions, { prepend: true })
|
|
1046
1300
|
);
|
|
1047
1301
|
}
|
|
1048
|
-
if (paths.
|
|
1049
|
-
safeApply("vscode-
|
|
1302
|
+
if (paths.vscodeInstructionsFile) {
|
|
1303
|
+
safeApply("vscode-instructions-file", () =>
|
|
1304
|
+
upsertPromptFile(paths.vscodeInstructionsFile, instructions, { prepend: true })
|
|
1305
|
+
);
|
|
1306
|
+
}
|
|
1307
|
+
if (paths.vscodeSettings && paths.vscodeInstructionsDir) {
|
|
1308
|
+
safeApply("vscode-settings", () =>
|
|
1309
|
+
upsertVsCodeInstructions(paths.vscodeSettings, instructions, paths.vscodeInstructionsDir)
|
|
1310
|
+
);
|
|
1050
1311
|
}
|
|
1051
1312
|
if (paths.windsurfGlobalRules) {
|
|
1052
1313
|
safeApply("windsurf", () => upsertPromptFile(paths.windsurfGlobalRules, instructions, { prepend: true }));
|
|
@@ -1060,18 +1321,25 @@ function applyAgentInstructions({ logger } = {}) {
|
|
|
1060
1321
|
if (paths.claude) {
|
|
1061
1322
|
safeApply("claude", () => upsertClaudeInstructions(paths.claude, instructions));
|
|
1062
1323
|
}
|
|
1063
|
-
|
|
1064
|
-
|
|
1324
|
+
const continueYamlExists =
|
|
1325
|
+
(paths.continueYaml && fs.existsSync(paths.continueYaml)) ||
|
|
1326
|
+
(paths.continueYml && fs.existsSync(paths.continueYml));
|
|
1327
|
+
if (continueYamlExists) {
|
|
1328
|
+
if (paths.continueYaml && fs.existsSync(paths.continueYaml)) {
|
|
1329
|
+
safeApply("continue-yaml", () => upsertContinueYamlRules(paths.continueYaml, instructions));
|
|
1330
|
+
}
|
|
1331
|
+
if (paths.continueYml && fs.existsSync(paths.continueYml)) {
|
|
1332
|
+
safeApply("continue-yml", () => upsertContinueYamlRules(paths.continueYml, instructions));
|
|
1333
|
+
}
|
|
1334
|
+
if (paths.continue && fs.existsSync(paths.continue)) {
|
|
1335
|
+
safeApply("continue-json", () => upsertContinueJsonInstructions(paths.continue, instructions));
|
|
1336
|
+
}
|
|
1337
|
+
} else if (paths.continue) {
|
|
1338
|
+
safeApply("continue-json", () => upsertContinueJsonInstructions(paths.continue, instructions));
|
|
1065
1339
|
}
|
|
1066
1340
|
if (paths.zed) {
|
|
1067
1341
|
safeApply("zed", () => upsertZedInstructions(paths.zed, instructions));
|
|
1068
1342
|
}
|
|
1069
|
-
if (paths.aiderConfig) {
|
|
1070
|
-
safeApply("aider", () => upsertYamlInstruction(paths.aiderConfig, "system-prompt", instructions));
|
|
1071
|
-
}
|
|
1072
|
-
if (paths.gooseConfig) {
|
|
1073
|
-
safeApply("goose", () => upsertYamlInstruction(paths.gooseConfig, "instructions", instructions));
|
|
1074
|
-
}
|
|
1075
1343
|
if (paths.openInterpreterConfig) {
|
|
1076
1344
|
safeApply("open-interpreter", () =>
|
|
1077
1345
|
upsertYamlInstruction(paths.openInterpreterConfig, "system_message", instructions)
|