docdex 0.2.23 → 0.2.25
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 +142 -17
- package/lib/postinstall_setup.js +340 -40
- package/package.json +1 -1
package/assets/agents.md
CHANGED
|
@@ -1,3 +1,16 @@
|
|
|
1
|
+
---- START OF DOCDEX INFO V0.2.25 ----
|
|
2
|
+
Docdex URL: http://127.0.0.1:28491
|
|
3
|
+
Use this base URL for Docdex HTTP endpoints.
|
|
4
|
+
|
|
5
|
+
## Priority Directives (Mandatory)
|
|
6
|
+
|
|
7
|
+
- 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.
|
|
8
|
+
- Maintain agent-specific profile memory: use your agent_id with docdex_get_profile/docdex_save_preference; store generic self-knowledge (role, tooling, preferences).
|
|
9
|
+
- 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.
|
|
10
|
+
- Apply DAG reasoning for planning: prefer dependency graph facts (impact results and /v1/dag/export) to choose the right change order and scope.
|
|
11
|
+
- Use Docdex tools intentionally: docdex_search/symbols/ast for repo truth; docdex_stats/files/repo_inspect/index for index health.
|
|
12
|
+
- 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.
|
|
13
|
+
|
|
1
14
|
# Docdex Agent Usage Instructions
|
|
2
15
|
|
|
3
16
|
> 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 +46,7 @@ Docdex v2.1 introduces a strict separation between "facts" and "preferences." Us
|
|
|
33
46
|
- Content: Your persona, user preferences, coding style, tooling constraints.
|
|
34
47
|
- Example: "Always use Zod for validation," or "User prefers strict TypeScript types."
|
|
35
48
|
- Tools: docdex_save_preference, docdex_get_profile
|
|
49
|
+
- Agent-specific: Each agent should use its own agent_id and store generic self-knowledge (role, tooling, preferences).
|
|
36
50
|
- 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
51
|
|
|
38
52
|
## Tool Capabilities (MCP & HTTP)
|
|
@@ -46,20 +60,6 @@ Standard retrieval. The daemon automatically handles the waterfall (Local -> Web
|
|
|
46
60
|
| docdex_search | Search code, docs, and ingested libraries. Returns ranked snippets. |
|
|
47
61
|
| docdex_web_research | Explicitly trigger Tier 2 web discovery (DDG + Headless Chrome). Use when you need external docs not present locally. |
|
|
48
62
|
|
|
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
63
|
### B. Code Intelligence (AST & Graph)
|
|
64
64
|
|
|
65
65
|
Precision tools for structural analysis. Do not rely on text search for definitions or dependencies.
|
|
@@ -70,6 +70,7 @@ Precision tools for structural analysis. Do not rely on text search for definiti
|
|
|
70
70
|
| docdex_ast | Specific AST nodes (e.g., "Find all class definitions"). |
|
|
71
71
|
| docdex_impact_diagnostics | Check for broken/dynamic imports. |
|
|
72
72
|
| HTTP /v1/graph/impact | Impact Analysis: "What breaks if I change this?" Returns inbound/outbound dependencies. |
|
|
73
|
+
| HTTP /v1/dag/export | Export the dependency DAG for change ordering and scope. |
|
|
73
74
|
|
|
74
75
|
### C. Memory Operations
|
|
75
76
|
|
|
@@ -80,6 +81,47 @@ Precision tools for structural analysis. Do not rely on text search for definiti
|
|
|
80
81
|
| docdex_save_preference | Store a global user preference (Style, Tooling, Constraint). |
|
|
81
82
|
| docdex_get_profile | Retrieve global preferences. |
|
|
82
83
|
|
|
84
|
+
### D. Local Delegation (Cheap Models)
|
|
85
|
+
|
|
86
|
+
Use local delegation for low-complexity, code-generation-oriented tasks to reduce paid-model usage.
|
|
87
|
+
|
|
88
|
+
| MCP Tool / HTTP | Purpose |
|
|
89
|
+
| --- | --- |
|
|
90
|
+
| docdex_local_completion | Delegate small tasks to a local model with strict output formats. |
|
|
91
|
+
| HTTP /v1/delegate | HTTP endpoint for delegated completions with structured responses. |
|
|
92
|
+
|
|
93
|
+
Required fields: `task_type`, `instruction`, `context`. Optional: `max_tokens`, `timeout_ms`, `mode` (`draft_only` or `draft_then_refine`), `agent` (local agent id/slug).
|
|
94
|
+
Expensive model library: `docs/expensive_models.json` (match by `agent_id`, `agent_slug`, `model`, or adapter type; case-insensitive).
|
|
95
|
+
|
|
96
|
+
### E. Index Health + File Access
|
|
97
|
+
|
|
98
|
+
Use these to verify index coverage, repo binding, and to read precise file slices.
|
|
99
|
+
|
|
100
|
+
| MCP Tool | Purpose |
|
|
101
|
+
| --- | --- |
|
|
102
|
+
| docdex_repo_inspect | Confirm normalized repo root/identity (resolve missing_repo). |
|
|
103
|
+
| docdex_stats | Index size/last update; detect stale indexes. |
|
|
104
|
+
| docdex_files | Indexed file coverage; confirm a file is in the index. |
|
|
105
|
+
| docdex_index | Reindex full repo or ingest specific files when stale/missing. |
|
|
106
|
+
| docdex_open | Read exact file slices after you identify targets. |
|
|
107
|
+
|
|
108
|
+
## Quick Tool Map (Often Missed)
|
|
109
|
+
|
|
110
|
+
- docdex_files: List indexed docs with rel_path/doc_id/token_estimate; use to verify indexing coverage.
|
|
111
|
+
- docdex_stats: Show index size, state dir, and last update time.
|
|
112
|
+
- docdex_repo_inspect: Confirm normalized repo root and repo identity mapping.
|
|
113
|
+
- docdex_index: Reindex the full repo or ingest specific files when stale.
|
|
114
|
+
- docdex_search diff: Limit search to working tree, staged, or ref ranges; filter by paths.
|
|
115
|
+
- docdex_web_research knobs: force_web, skip_local_search, repo_only, no_cache, web_limit, llm_filter_local_results, llm_model.
|
|
116
|
+
- docdex_open: Read narrow file slices after targets are identified.
|
|
117
|
+
- docdex_impact_diagnostics: Scan dynamic imports when imports are unclear or failing.
|
|
118
|
+
- docdex_local_completion: Delegate low-complexity codegen tasks (tests, docstrings, boilerplate, simple refactors).
|
|
119
|
+
- docdex_ast: Use AST queries for precise structure (class/function definitions, call sites, imports).
|
|
120
|
+
- docdex_symbols: Use symbols to confirm exact signatures/locations before edits.
|
|
121
|
+
- HTTP /v1/graph/impact: Mandatory before code changes to review inbound/outbound deps.
|
|
122
|
+
- HTTP /v1/dag/export: Export dependency graph to plan change order.
|
|
123
|
+
- HTTP /v1/initialize: Bind a default repo root for MCP when clients omit project_root.
|
|
124
|
+
|
|
83
125
|
## Interaction Patterns
|
|
84
126
|
|
|
85
127
|
### 1. Reasoning Workflow
|
|
@@ -89,9 +131,76 @@ When answering a complex coding query, follow this "Reasoning Trace":
|
|
|
89
131
|
1. Retrieve Profile: Call docdex_get_profile to load user style/constraints (e.g., "Use functional components").
|
|
90
132
|
2. Search Code: Call docdex_search or docdex_symbols to find the relevant code.
|
|
91
133
|
3. Check Memory: Call docdex_memory_recall for project-specific caveats (e.g., "Auth logic was refactored last week").
|
|
92
|
-
4.
|
|
134
|
+
4. Validate structure: Use docdex_ast/docdex_symbols to confirm targets before editing.
|
|
135
|
+
5. Read context: Use docdex_open to fetch minimal file slices after locating targets.
|
|
136
|
+
6. Plan with DAG: Use /v1/dag/export or /v1/graph/impact to order changes by dependencies.
|
|
137
|
+
7. Synthesize: Generate code that matches the Repo Truth while adhering to the Profile Style.
|
|
138
|
+
|
|
139
|
+
### 2. Memory Capture (Mandatory)
|
|
140
|
+
|
|
141
|
+
Save more memories for both lobes during the task, not just at the end.
|
|
142
|
+
|
|
143
|
+
1. Repo memory: After each meaningful discovery or code change, save at least one durable fact (file location, behavior, config, gotcha) via `docdex_memory_save`.
|
|
144
|
+
2. Profile memory: When the user expresses a preference, constraint, or workflow correction, call `docdex_save_preference` immediately with the right category.
|
|
145
|
+
3. Keep it crisp: 1-3 short sentences, include file paths when relevant, avoid raw code blobs.
|
|
146
|
+
4. Safety: Never store secrets, tokens, or sensitive user data. Skip transient or speculative info.
|
|
147
|
+
|
|
148
|
+
### 3. Index Health + Diff-Aware Search (Mandatory)
|
|
93
149
|
|
|
94
|
-
|
|
150
|
+
Use these when results look incomplete or when the task is about recent changes.
|
|
151
|
+
|
|
152
|
+
1. Confirm repo binding: Use docdex_repo_inspect or /v1/initialize when repo_id is missing/ambiguous.
|
|
153
|
+
2. Check index coverage: Use docdex_stats + docdex_files before assuming code is missing.
|
|
154
|
+
3. Reindex if needed: Run docdex_index (or advise it) when stale_index/missing files appear.
|
|
155
|
+
4. Use diff search: For change-specific tasks, use docdex_search with diff mode (working tree/staged/range).
|
|
156
|
+
|
|
157
|
+
### 4. Local Delegation Workflow (Cheap Models)
|
|
158
|
+
|
|
159
|
+
When you are an expensive/paid model, delegate eligible low-complexity tasks first unless the user opts out.
|
|
160
|
+
Delegation is mandatory for eligible tasks. If you are expensive and delegation is enabled (explicitly or auto-enabled with local candidates), you MUST attempt local delegation before doing the work yourself. Only skip when delegation is disabled, no local candidate exists, or local output fails validation after a retry/fallback.
|
|
161
|
+
|
|
162
|
+
#### Mandatory Delegation Triggers
|
|
163
|
+
|
|
164
|
+
- The work fits a delegation task type or can be split into sub-tasks that do.
|
|
165
|
+
- The change is small, localized, or mechanical (boilerplate, formatting, docstrings, small refactors).
|
|
166
|
+
- The task can be fully expressed in a capsule with explicit context and output rules.
|
|
167
|
+
|
|
168
|
+
#### Reasons to Delegate (Non-Optional)
|
|
169
|
+
|
|
170
|
+
- Cuts paid-token usage and cost.
|
|
171
|
+
- Lowers latency and avoids rate-limit pressure on premium models.
|
|
172
|
+
- Keeps expensive models focused on complex reasoning and multi-step planning.
|
|
173
|
+
- Uses tuned prompts that reduce drift for repetitive edits.
|
|
174
|
+
- Enforces the product's cost-control policy; skipping delegation is a regression.
|
|
175
|
+
|
|
176
|
+
1. Determine if you are expensive: load `docs/expensive_models.json` and match your `agent_id`, `agent_slug`, `model`, or adapter type. If you match, continue; if not and you are clearly local/cheap, skip delegation. If unsure, default to expensive.
|
|
177
|
+
2. Check config: Only delegate when `[llm.delegation].enabled` is true or `auto_enable` is true with an eligible local model/agent (and `task_type` is allowed). If uncertain, attempt delegation and handle the error.
|
|
178
|
+
3. Choose task type: Use one of `GENERATE_TESTS`, `WRITE_DOCSTRING`, `SCAFFOLD_BOILERPLATE`, `REFACTOR_SIMPLE`, `FORMAT_CODE`.
|
|
179
|
+
4. Call the tool: `docdex_local_completion` with `task_type`, `instruction`, and minimal `context` (smallest necessary snippet).
|
|
180
|
+
5. Validate output: If the local output is invalid or empty, fall back to the primary agent or handle with the paid model.
|
|
181
|
+
6. Optional refine: If mode is `draft_then_refine`, refine the draft with the primary agent and return a final result.
|
|
182
|
+
|
|
183
|
+
#### Delegation Handoff Package (Required)
|
|
184
|
+
|
|
185
|
+
Local models cannot call tools. The leading agent must provide a complete, minimal capsule.
|
|
186
|
+
|
|
187
|
+
1. Task capsule: `task_type`, goal, success criteria, output format, and constraints (tests to update, style rules).
|
|
188
|
+
2. Context payload: file paths plus the exact snippets from docdex_open; include symbol signatures/AST findings.
|
|
189
|
+
3. Dependency notes: summarize impact analysis and any DAG ordering that affects the change.
|
|
190
|
+
4. Boundaries: explicit files allowed to edit vs read-only; no new dependencies unless allowed.
|
|
191
|
+
5. Guardrails: ask for clarification if context is insufficient; do not invent missing APIs; return only the requested format.
|
|
192
|
+
|
|
193
|
+
### 5. Graph + AST Usage (Mandatory for Code Changes)
|
|
194
|
+
|
|
195
|
+
For any code change, use both AST and graph tools to reduce drift and hidden coupling.
|
|
196
|
+
|
|
197
|
+
1. Use `docdex_ast` or `docdex_symbols` to locate exact definitions and call sites.
|
|
198
|
+
2. Call HTTP `/v1/graph/impact?file=...` before edits and summarize inbound/outbound deps.
|
|
199
|
+
3. For multi-file changes, export the DAG (`/v1/dag/export`) and order edits by dependency direction.
|
|
200
|
+
4. Use docdex_impact_diagnostics when imports are dynamic or unresolved.
|
|
201
|
+
5. If graph endpoints are unavailable, state it and proceed cautiously with extra local search.
|
|
202
|
+
|
|
203
|
+
### 6. Handling Corrections (Learning)
|
|
95
204
|
|
|
96
205
|
If the user says: "I told you, we do not use Moment.js here, use date-fns!"
|
|
97
206
|
|
|
@@ -100,13 +209,28 @@ If the user says: "I told you, we do not use Moment.js here, use date-fns!"
|
|
|
100
209
|
- content: "Do not use Moment.js; prefer date-fns."
|
|
101
210
|
- agent_id: "default" (or active agent ID)
|
|
102
211
|
|
|
103
|
-
###
|
|
212
|
+
### 7. Impact Analysis
|
|
104
213
|
|
|
105
214
|
If the user asks: "Safe to delete getUser?"
|
|
106
215
|
|
|
107
216
|
- Action: Call GET /v1/graph/impact?file=src/user.ts
|
|
108
217
|
- Output: Analyze the inbound edges. If the list is not empty, it is unsafe.
|
|
109
218
|
|
|
219
|
+
### 8. Non-Repo Real-World Queries (Web First)
|
|
220
|
+
|
|
221
|
+
If the user asks a non-repo, real-world question (weather, news, general facts), immediately call docdex_web_research with force_web=true.
|
|
222
|
+
- Resolve relative dates ("yesterday", "last week") using system time by default.
|
|
223
|
+
- Do not run docdex_search unless the user explicitly wants repo-local context.
|
|
224
|
+
- 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.
|
|
225
|
+
|
|
226
|
+
### 9. Failure Handling (Missing Results or Errors)
|
|
227
|
+
|
|
228
|
+
- Ensure project_root or repo_path is set, or call /v1/initialize to bind a default root.
|
|
229
|
+
- Use docdex_repo_inspect to confirm repo identity and normalized root.
|
|
230
|
+
- Use docdex_stats and docdex_files to check whether the index exists and contains files.
|
|
231
|
+
- Reindex with docdex_index (or docdexd index) if the index is stale or empty.
|
|
232
|
+
- Add a repo-local .docdexignore for large generated artifacts or local caches when indexing is slow.
|
|
233
|
+
|
|
110
234
|
## Operational Context
|
|
111
235
|
|
|
112
236
|
### Repository Identification
|
|
@@ -129,3 +253,4 @@ Docdex adapts to the host.
|
|
|
129
253
|
|
|
130
254
|
- Project Mapping: On constrained hardware, docdex uses a "Spotlight Heuristic" to show you only a skeletal file tree based on your role keywords, rather than the full file system.
|
|
131
255
|
- LLM: It may be running a quantized model (e.g., phi3.5) or a heavy model (llama3.1:70b) depending on VRAM. Trust the daemon's token limits; it handles truncation.
|
|
256
|
+
---- END OF DOCDEX INFO -----
|
package/lib/postinstall_setup.js
CHANGED
|
@@ -26,6 +26,7 @@ const SETUP_PENDING_MARKER = "setup_pending.json";
|
|
|
26
26
|
const AGENTS_DOC_FILENAME = "agents.md";
|
|
27
27
|
const DOCDEX_INFO_START_PREFIX = "---- START OF DOCDEX INFO V";
|
|
28
28
|
const DOCDEX_INFO_END = "---- END OF DOCDEX INFO -----";
|
|
29
|
+
const DOCDEX_INFO_END_LEGACY = "---- END OF DOCDEX INFO ----";
|
|
29
30
|
|
|
30
31
|
function defaultConfigPath() {
|
|
31
32
|
return path.join(os.homedir(), ".docdex", "config.toml");
|
|
@@ -353,9 +354,14 @@ function docdexBlockStart(version) {
|
|
|
353
354
|
return `${DOCDEX_INFO_START_PREFIX}${version} ----`;
|
|
354
355
|
}
|
|
355
356
|
|
|
357
|
+
function docdexInfoEndPattern() {
|
|
358
|
+
return `(?:${escapeRegExp(DOCDEX_INFO_END)}|${escapeRegExp(DOCDEX_INFO_END_LEGACY)})`;
|
|
359
|
+
}
|
|
360
|
+
|
|
356
361
|
function buildDocdexInstructionBlock(instructions) {
|
|
357
362
|
const next = normalizeInstructionText(instructions);
|
|
358
363
|
if (!next) return "";
|
|
364
|
+
if (hasDocdexBlock(next)) return next;
|
|
359
365
|
const version = resolvePackageVersion();
|
|
360
366
|
return `${docdexBlockStart(version)}\n${next}\n${DOCDEX_INFO_END}`;
|
|
361
367
|
}
|
|
@@ -363,9 +369,7 @@ function buildDocdexInstructionBlock(instructions) {
|
|
|
363
369
|
function extractDocdexBlockBody(text) {
|
|
364
370
|
const match = String(text || "").match(
|
|
365
371
|
new RegExp(
|
|
366
|
-
`${escapeRegExp(DOCDEX_INFO_START_PREFIX)}[^\\r\\n]* ----\\r?\\n([\\s\\S]*?)\\r?\\n${
|
|
367
|
-
DOCDEX_INFO_END
|
|
368
|
-
)}`
|
|
372
|
+
`${escapeRegExp(DOCDEX_INFO_START_PREFIX)}[^\\r\\n]* ----\\r?\\n([\\s\\S]*?)\\r?\\n${docdexInfoEndPattern()}`
|
|
369
373
|
)
|
|
370
374
|
);
|
|
371
375
|
return match ? normalizeInstructionText(match[1]) : "";
|
|
@@ -383,11 +387,17 @@ function hasDocdexBlockVersion(text, version) {
|
|
|
383
387
|
return String(text || "").includes(docdexBlockStart(version));
|
|
384
388
|
}
|
|
385
389
|
|
|
390
|
+
function hasDocdexBlock(text) {
|
|
391
|
+
const source = String(text || "");
|
|
392
|
+
return (
|
|
393
|
+
source.includes(DOCDEX_INFO_START_PREFIX) &&
|
|
394
|
+
(source.includes(DOCDEX_INFO_END) || source.includes(DOCDEX_INFO_END_LEGACY))
|
|
395
|
+
);
|
|
396
|
+
}
|
|
397
|
+
|
|
386
398
|
function stripDocdexBlocks(text) {
|
|
387
399
|
const re = new RegExp(
|
|
388
|
-
`${escapeRegExp(DOCDEX_INFO_START_PREFIX)}[^\\r\\n]* ----\\r?\\n[\\s\\S]*?\\r?\\n${
|
|
389
|
-
DOCDEX_INFO_END
|
|
390
|
-
)}\\r?\\n?`,
|
|
400
|
+
`${escapeRegExp(DOCDEX_INFO_START_PREFIX)}[^\\r\\n]* ----\\r?\\n[\\s\\S]*?\\r?\\n${docdexInfoEndPattern()}\\r?\\n?`,
|
|
391
401
|
"g"
|
|
392
402
|
);
|
|
393
403
|
return String(text || "").replace(re, "").trim();
|
|
@@ -397,9 +407,7 @@ function stripDocdexBlocksExcept(text, version) {
|
|
|
397
407
|
if (!version) return stripDocdexBlocks(text);
|
|
398
408
|
const source = String(text || "");
|
|
399
409
|
const re = new RegExp(
|
|
400
|
-
`${escapeRegExp(DOCDEX_INFO_START_PREFIX)}[^\\r\\n]* ----\\r?\\n[\\s\\S]*?\\r?\\n${
|
|
401
|
-
DOCDEX_INFO_END
|
|
402
|
-
)}\\r?\\n?`,
|
|
410
|
+
`${escapeRegExp(DOCDEX_INFO_START_PREFIX)}[^\\r\\n]* ----\\r?\\n[\\s\\S]*?\\r?\\n${docdexInfoEndPattern()}\\r?\\n?`,
|
|
403
411
|
"g"
|
|
404
412
|
);
|
|
405
413
|
let result = "";
|
|
@@ -432,7 +440,7 @@ function stripLegacyDocdexBody(text, body) {
|
|
|
432
440
|
if (!body) return String(text || "");
|
|
433
441
|
const source = String(text || "").replace(/\r\n/g, "\n");
|
|
434
442
|
const re = new RegExp(
|
|
435
|
-
`${escapeRegExp(DOCDEX_INFO_START_PREFIX)}[^\\n]* ----\\n[\\s\\S]*?\\n${
|
|
443
|
+
`${escapeRegExp(DOCDEX_INFO_START_PREFIX)}[^\\n]* ----\\n[\\s\\S]*?\\n${docdexInfoEndPattern()}\\n?`,
|
|
436
444
|
"g"
|
|
437
445
|
);
|
|
438
446
|
let result = "";
|
|
@@ -493,6 +501,18 @@ function upsertPromptFile(pathname, instructions, { prepend = false } = {}) {
|
|
|
493
501
|
return writeTextFile(pathname, merged);
|
|
494
502
|
}
|
|
495
503
|
|
|
504
|
+
function removePromptFile(pathname) {
|
|
505
|
+
if (!fs.existsSync(pathname)) return false;
|
|
506
|
+
const current = fs.readFileSync(pathname, "utf8");
|
|
507
|
+
const stripped = stripDocdexBlocks(current);
|
|
508
|
+
if (normalizeInstructionText(stripped) === normalizeInstructionText(current)) return false;
|
|
509
|
+
if (!stripped) {
|
|
510
|
+
fs.unlinkSync(pathname);
|
|
511
|
+
return true;
|
|
512
|
+
}
|
|
513
|
+
return writeTextFile(pathname, stripped);
|
|
514
|
+
}
|
|
515
|
+
|
|
496
516
|
function escapeRegExp(value) {
|
|
497
517
|
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
498
518
|
}
|
|
@@ -554,16 +574,10 @@ function upsertYamlInstruction(pathname, key, instructions) {
|
|
|
554
574
|
}
|
|
555
575
|
|
|
556
576
|
function upsertClaudeInstructions(pathname, instructions) {
|
|
557
|
-
|
|
558
|
-
if (typeof value !== "object" || value == null || Array.isArray(value)) return false;
|
|
559
|
-
const merged = mergeInstructionText(value.instructions, instructions);
|
|
560
|
-
if (!merged || merged === value.instructions) return false;
|
|
561
|
-
value.instructions = merged;
|
|
562
|
-
writeJson(pathname, value);
|
|
563
|
-
return true;
|
|
577
|
+
return upsertPromptFile(pathname, instructions);
|
|
564
578
|
}
|
|
565
579
|
|
|
566
|
-
function
|
|
580
|
+
function upsertContinueJsonInstructions(pathname, instructions) {
|
|
567
581
|
const { value } = readJson(pathname);
|
|
568
582
|
if (typeof value !== "object" || value == null || Array.isArray(value)) return false;
|
|
569
583
|
const merged = mergeInstructionText(value.systemMessage, instructions);
|
|
@@ -573,6 +587,198 @@ function upsertContinueInstructions(pathname, instructions) {
|
|
|
573
587
|
return true;
|
|
574
588
|
}
|
|
575
589
|
|
|
590
|
+
function countLeadingWhitespace(line) {
|
|
591
|
+
const match = line.match(/^\s*/);
|
|
592
|
+
return match ? match[0].length : 0;
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
function isYamlTopLevelKey(line, baseIndent) {
|
|
596
|
+
const indent = countLeadingWhitespace(line);
|
|
597
|
+
if (indent > baseIndent) return false;
|
|
598
|
+
const trimmed = line.trimStart();
|
|
599
|
+
if (!trimmed || trimmed.startsWith("#") || trimmed.startsWith("-")) return false;
|
|
600
|
+
return trimmed.includes(":");
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
function hasYamlContent(lines) {
|
|
604
|
+
return lines.some((line) => {
|
|
605
|
+
const trimmed = line.trim();
|
|
606
|
+
return trimmed && !trimmed.startsWith("#");
|
|
607
|
+
});
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
function splitInlineYamlList(value) {
|
|
611
|
+
const trimmed = String(value || "").trim();
|
|
612
|
+
if (trimmed === "[]") return [];
|
|
613
|
+
if (!trimmed.startsWith("[") || !trimmed.endsWith("]")) return null;
|
|
614
|
+
const inner = trimmed.slice(1, -1);
|
|
615
|
+
const items = [];
|
|
616
|
+
let current = "";
|
|
617
|
+
let inSingle = false;
|
|
618
|
+
let inDouble = false;
|
|
619
|
+
let escaped = false;
|
|
620
|
+
for (const ch of inner) {
|
|
621
|
+
if (escaped) {
|
|
622
|
+
current += ch;
|
|
623
|
+
escaped = false;
|
|
624
|
+
continue;
|
|
625
|
+
}
|
|
626
|
+
if (ch === "\\\\") {
|
|
627
|
+
escaped = true;
|
|
628
|
+
current += ch;
|
|
629
|
+
continue;
|
|
630
|
+
}
|
|
631
|
+
if (ch === "'" && !inDouble) {
|
|
632
|
+
inSingle = !inSingle;
|
|
633
|
+
current += ch;
|
|
634
|
+
continue;
|
|
635
|
+
}
|
|
636
|
+
if (ch === '"' && !inSingle) {
|
|
637
|
+
inDouble = !inDouble;
|
|
638
|
+
current += ch;
|
|
639
|
+
continue;
|
|
640
|
+
}
|
|
641
|
+
if (ch === "," && !inSingle && !inDouble) {
|
|
642
|
+
const next = current.trim();
|
|
643
|
+
if (next) items.push(next);
|
|
644
|
+
current = "";
|
|
645
|
+
continue;
|
|
646
|
+
}
|
|
647
|
+
current += ch;
|
|
648
|
+
}
|
|
649
|
+
const next = current.trim();
|
|
650
|
+
if (next) items.push(next);
|
|
651
|
+
return items;
|
|
652
|
+
}
|
|
653
|
+
|
|
654
|
+
function inlineRulesToItems(value, itemIndent) {
|
|
655
|
+
const trimmed = String(value || "").trim();
|
|
656
|
+
if (!trimmed) return [];
|
|
657
|
+
const prefix = " ".repeat(itemIndent);
|
|
658
|
+
const split = splitInlineYamlList(trimmed);
|
|
659
|
+
if (split) {
|
|
660
|
+
return split.map((item) => [`${prefix}- ${item}`]).filter((item) => item[0].trim() !== `${prefix}-`);
|
|
661
|
+
}
|
|
662
|
+
return [[`${prefix}- ${trimmed}`]];
|
|
663
|
+
}
|
|
664
|
+
|
|
665
|
+
function buildYamlRuleBlock(itemIndent, instructions) {
|
|
666
|
+
const prefix = " ".repeat(itemIndent);
|
|
667
|
+
const contentPrefix = " ".repeat(itemIndent + 2);
|
|
668
|
+
const lines = [`${prefix}- |`];
|
|
669
|
+
for (const line of String(instructions).split(/\r?\n/)) {
|
|
670
|
+
lines.push(`${contentPrefix}${line}`);
|
|
671
|
+
}
|
|
672
|
+
return lines;
|
|
673
|
+
}
|
|
674
|
+
|
|
675
|
+
function rewriteContinueYamlRules(source, instructions, addDocdex) {
|
|
676
|
+
const lines = String(source || "").split(/\r?\n/);
|
|
677
|
+
const ruleLineRe = /^(\s*)rules\s*:(.*)$/;
|
|
678
|
+
let rulesIndex = -1;
|
|
679
|
+
let rulesIndent = 0;
|
|
680
|
+
let rulesInline = "";
|
|
681
|
+
for (let i = 0; i < lines.length; i += 1) {
|
|
682
|
+
const match = lines[i].match(ruleLineRe);
|
|
683
|
+
if (!match) continue;
|
|
684
|
+
rulesIndex = i;
|
|
685
|
+
rulesIndent = match[1]?.length || 0;
|
|
686
|
+
rulesInline = (match[2] || "").trim();
|
|
687
|
+
if (rulesInline.includes("#")) {
|
|
688
|
+
rulesInline = rulesInline.split("#")[0].trim();
|
|
689
|
+
}
|
|
690
|
+
if (rulesInline.startsWith("#")) rulesInline = "";
|
|
691
|
+
break;
|
|
692
|
+
}
|
|
693
|
+
|
|
694
|
+
if (rulesIndex === -1) {
|
|
695
|
+
if (!addDocdex) return null;
|
|
696
|
+
const trimmed = String(source || "").trimEnd();
|
|
697
|
+
const docdexBlock = buildYamlRuleBlock(2, instructions);
|
|
698
|
+
const prefix = trimmed ? `${trimmed}\n\n` : "";
|
|
699
|
+
return `${prefix}rules:\n${docdexBlock.join("\n")}`;
|
|
700
|
+
}
|
|
701
|
+
|
|
702
|
+
let endIndex = lines.length;
|
|
703
|
+
for (let i = rulesIndex + 1; i < lines.length; i += 1) {
|
|
704
|
+
if (isYamlTopLevelKey(lines[i], rulesIndent)) {
|
|
705
|
+
endIndex = i;
|
|
706
|
+
break;
|
|
707
|
+
}
|
|
708
|
+
}
|
|
709
|
+
const blockLines = lines.slice(rulesIndex + 1, endIndex);
|
|
710
|
+
const preLines = [];
|
|
711
|
+
const items = [];
|
|
712
|
+
let currentItem = [];
|
|
713
|
+
let itemIndent = null;
|
|
714
|
+
let startedItems = false;
|
|
715
|
+
|
|
716
|
+
for (const line of blockLines) {
|
|
717
|
+
const trimmed = line.trimStart();
|
|
718
|
+
const indent = countLeadingWhitespace(line);
|
|
719
|
+
const isItem = trimmed.startsWith("-") && indent > rulesIndent;
|
|
720
|
+
if (isItem) {
|
|
721
|
+
if (itemIndent == null) itemIndent = indent;
|
|
722
|
+
if (indent === itemIndent) {
|
|
723
|
+
if (startedItems && currentItem.length) {
|
|
724
|
+
items.push(currentItem);
|
|
725
|
+
currentItem = [];
|
|
726
|
+
}
|
|
727
|
+
startedItems = true;
|
|
728
|
+
}
|
|
729
|
+
currentItem.push(line);
|
|
730
|
+
continue;
|
|
731
|
+
}
|
|
732
|
+
if (startedItems) {
|
|
733
|
+
currentItem.push(line);
|
|
734
|
+
} else {
|
|
735
|
+
preLines.push(line);
|
|
736
|
+
}
|
|
737
|
+
}
|
|
738
|
+
if (currentItem.length) items.push(currentItem);
|
|
739
|
+
|
|
740
|
+
const inferredIndent = itemIndent == null ? rulesIndent + 2 : itemIndent;
|
|
741
|
+
if (!items.length && rulesInline) {
|
|
742
|
+
items.push(...inlineRulesToItems(rulesInline, inferredIndent));
|
|
743
|
+
rulesInline = "";
|
|
744
|
+
}
|
|
745
|
+
|
|
746
|
+
const keptItems = items.filter((item) => {
|
|
747
|
+
const text = item.join("\n");
|
|
748
|
+
return !hasDocdexBlock(text);
|
|
749
|
+
});
|
|
750
|
+
|
|
751
|
+
if (addDocdex) {
|
|
752
|
+
keptItems.push(buildYamlRuleBlock(inferredIndent, instructions));
|
|
753
|
+
}
|
|
754
|
+
|
|
755
|
+
const removeRulesBlock =
|
|
756
|
+
!addDocdex && !keptItems.length && !hasYamlContent(preLines) && !rulesInline;
|
|
757
|
+
|
|
758
|
+
const output = [];
|
|
759
|
+
output.push(...lines.slice(0, rulesIndex));
|
|
760
|
+
if (!removeRulesBlock) {
|
|
761
|
+
output.push(`${" ".repeat(rulesIndent)}rules:`);
|
|
762
|
+
output.push(...preLines);
|
|
763
|
+
for (const item of keptItems) {
|
|
764
|
+
output.push(...item);
|
|
765
|
+
}
|
|
766
|
+
}
|
|
767
|
+
output.push(...lines.slice(endIndex));
|
|
768
|
+
const next = output.join("\n");
|
|
769
|
+
return next === source ? null : next;
|
|
770
|
+
}
|
|
771
|
+
|
|
772
|
+
function upsertContinueYamlRules(pathname, instructions) {
|
|
773
|
+
if (!fs.existsSync(pathname)) return false;
|
|
774
|
+
const normalized = normalizeInstructionText(instructions);
|
|
775
|
+
if (!normalized) return false;
|
|
776
|
+
const current = fs.readFileSync(pathname, "utf8");
|
|
777
|
+
const updated = rewriteContinueYamlRules(current, normalized, true);
|
|
778
|
+
if (!updated) return false;
|
|
779
|
+
return writeTextFile(pathname, updated);
|
|
780
|
+
}
|
|
781
|
+
|
|
576
782
|
function upsertZedInstructions(pathname, instructions) {
|
|
577
783
|
const { value } = readJson(pathname);
|
|
578
784
|
if (typeof value !== "object" || value == null || Array.isArray(value)) return false;
|
|
@@ -586,12 +792,54 @@ function upsertZedInstructions(pathname, instructions) {
|
|
|
586
792
|
return true;
|
|
587
793
|
}
|
|
588
794
|
|
|
589
|
-
function
|
|
795
|
+
function upsertVsCodeInstructionKey(value, key, instructions) {
|
|
796
|
+
const existing = typeof value[key] === "string" ? value[key] : "";
|
|
797
|
+
const merged = mergeInstructionText(existing, instructions);
|
|
798
|
+
if (!merged || merged === existing) return false;
|
|
799
|
+
value[key] = merged;
|
|
800
|
+
return true;
|
|
801
|
+
}
|
|
802
|
+
|
|
803
|
+
function removeVsCodeInstructionKey(value, key, instructions, { legacyPath } = {}) {
|
|
804
|
+
if (typeof value[key] !== "string") return false;
|
|
805
|
+
const current = value[key];
|
|
806
|
+
const stripped = stripDocdexBlocks(current);
|
|
807
|
+
if (normalizeInstructionText(stripped) !== normalizeInstructionText(current)) {
|
|
808
|
+
if (!stripped) {
|
|
809
|
+
delete value[key];
|
|
810
|
+
} else {
|
|
811
|
+
value[key] = stripped;
|
|
812
|
+
}
|
|
813
|
+
return true;
|
|
814
|
+
}
|
|
815
|
+
const normalized = normalizeInstructionText(instructions);
|
|
816
|
+
if (current === normalized || (legacyPath && current === legacyPath)) {
|
|
817
|
+
delete value[key];
|
|
818
|
+
return true;
|
|
819
|
+
}
|
|
820
|
+
return false;
|
|
821
|
+
}
|
|
822
|
+
|
|
823
|
+
function upsertVsCodeInstructions(pathname, instructions, legacyPath) {
|
|
590
824
|
const { value } = readJson(pathname);
|
|
591
825
|
if (typeof value !== "object" || value == null || Array.isArray(value)) return false;
|
|
592
|
-
const
|
|
593
|
-
if (
|
|
594
|
-
|
|
826
|
+
const normalized = normalizeInstructionText(instructions);
|
|
827
|
+
if (!normalized) return false;
|
|
828
|
+
let updated = false;
|
|
829
|
+
if (upsertVsCodeInstructionKey(value, "chat.instructions", instructions)) {
|
|
830
|
+
updated = true;
|
|
831
|
+
}
|
|
832
|
+
if (removeVsCodeInstructionKey(value, "github.copilot.chat.codeGeneration.instructions", instructions)) {
|
|
833
|
+
updated = true;
|
|
834
|
+
}
|
|
835
|
+
if (
|
|
836
|
+
removeVsCodeInstructionKey(value, "copilot.chat.codeGeneration.instructions", instructions, {
|
|
837
|
+
legacyPath
|
|
838
|
+
})
|
|
839
|
+
) {
|
|
840
|
+
updated = true;
|
|
841
|
+
}
|
|
842
|
+
if (!updated) return false;
|
|
595
843
|
writeJson(pathname, value);
|
|
596
844
|
return true;
|
|
597
845
|
}
|
|
@@ -921,21 +1169,38 @@ function clientInstructionPaths() {
|
|
|
921
1169
|
const appData = process.env.APPDATA || path.join(home, "AppData", "Roaming");
|
|
922
1170
|
const userProfile = process.env.USERPROFILE || home;
|
|
923
1171
|
const vscodeGlobalInstructions = path.join(home, ".vscode", "global_instructions.md");
|
|
1172
|
+
const vscodeInstructionsDir = path.join(home, ".vscode", "instructions");
|
|
1173
|
+
const vscodeInstructionsFile = path.join(vscodeInstructionsDir, "docdex.md");
|
|
1174
|
+
const continueRoot = path.join(userProfile, ".continue");
|
|
1175
|
+
const continueJson = path.join(continueRoot, "config.json");
|
|
1176
|
+
const continueYaml = path.join(continueRoot, "config.yaml");
|
|
1177
|
+
const continueYml = path.join(continueRoot, "config.yml");
|
|
924
1178
|
const windsurfGlobalRules = path.join(userProfile, ".codeium", "windsurf", "memories", "global_rules.md");
|
|
925
1179
|
const rooRules = path.join(home, ".roo", "rules", "docdex.md");
|
|
926
1180
|
const pearaiAgent = path.join(home, ".config", "pearai", "agent.md");
|
|
927
1181
|
const aiderConfig = path.join(home, ".aider.conf.yml");
|
|
928
1182
|
const gooseConfig = path.join(home, ".config", "goose", "config.yaml");
|
|
929
1183
|
const openInterpreterConfig = path.join(home, ".openinterpreter", "profiles", "default.yaml");
|
|
1184
|
+
const geminiInstructions = path.join(userProfile, ".gemini", "GEMINI.md");
|
|
1185
|
+
const claudeInstructions = path.join(userProfile, ".claude", "CLAUDE.md");
|
|
1186
|
+
const cursorAgents = path.join(userProfile, ".cursor", "agents.md");
|
|
1187
|
+
const cursorAgentsUpper = path.join(userProfile, ".cursor", "AGENTS.md");
|
|
930
1188
|
const codexAgents = path.join(userProfile, ".codex", "AGENTS.md");
|
|
931
1189
|
switch (process.platform) {
|
|
932
1190
|
case "win32":
|
|
933
1191
|
return {
|
|
934
|
-
|
|
935
|
-
|
|
1192
|
+
gemini: geminiInstructions,
|
|
1193
|
+
claude: claudeInstructions,
|
|
1194
|
+
cursorAgents,
|
|
1195
|
+
cursorAgentsUpper,
|
|
1196
|
+
continue: continueJson,
|
|
1197
|
+
continueYaml,
|
|
1198
|
+
continueYml,
|
|
936
1199
|
zed: path.join(appData, "Zed", "settings.json"),
|
|
937
1200
|
vscodeSettings: path.join(appData, "Code", "User", "settings.json"),
|
|
938
1201
|
vscodeGlobalInstructions,
|
|
1202
|
+
vscodeInstructionsDir,
|
|
1203
|
+
vscodeInstructionsFile,
|
|
939
1204
|
windsurfGlobalRules,
|
|
940
1205
|
rooRules,
|
|
941
1206
|
pearaiAgent,
|
|
@@ -946,11 +1211,18 @@ function clientInstructionPaths() {
|
|
|
946
1211
|
};
|
|
947
1212
|
case "darwin":
|
|
948
1213
|
return {
|
|
949
|
-
|
|
950
|
-
|
|
1214
|
+
gemini: geminiInstructions,
|
|
1215
|
+
claude: claudeInstructions,
|
|
1216
|
+
cursorAgents,
|
|
1217
|
+
cursorAgentsUpper,
|
|
1218
|
+
continue: continueJson,
|
|
1219
|
+
continueYaml,
|
|
1220
|
+
continueYml,
|
|
951
1221
|
zed: path.join(home, ".config", "zed", "settings.json"),
|
|
952
1222
|
vscodeSettings: path.join(home, "Library", "Application Support", "Code", "User", "settings.json"),
|
|
953
1223
|
vscodeGlobalInstructions,
|
|
1224
|
+
vscodeInstructionsDir,
|
|
1225
|
+
vscodeInstructionsFile,
|
|
954
1226
|
windsurfGlobalRules,
|
|
955
1227
|
rooRules,
|
|
956
1228
|
pearaiAgent,
|
|
@@ -961,11 +1233,18 @@ function clientInstructionPaths() {
|
|
|
961
1233
|
};
|
|
962
1234
|
default:
|
|
963
1235
|
return {
|
|
964
|
-
|
|
965
|
-
|
|
1236
|
+
gemini: geminiInstructions,
|
|
1237
|
+
claude: claudeInstructions,
|
|
1238
|
+
cursorAgents,
|
|
1239
|
+
cursorAgentsUpper,
|
|
1240
|
+
continue: continueJson,
|
|
1241
|
+
continueYaml,
|
|
1242
|
+
continueYml,
|
|
966
1243
|
zed: path.join(home, ".config", "zed", "settings.json"),
|
|
967
1244
|
vscodeSettings: path.join(home, ".config", "Code", "User", "settings.json"),
|
|
968
1245
|
vscodeGlobalInstructions,
|
|
1246
|
+
vscodeInstructionsDir,
|
|
1247
|
+
vscodeInstructionsFile,
|
|
969
1248
|
windsurfGlobalRules,
|
|
970
1249
|
rooRules,
|
|
971
1250
|
pearaiAgent,
|
|
@@ -1041,12 +1320,23 @@ function applyAgentInstructions({ logger } = {}) {
|
|
|
1041
1320
|
};
|
|
1042
1321
|
|
|
1043
1322
|
if (paths.vscodeGlobalInstructions) {
|
|
1044
|
-
safeApply("vscode-global", () =>
|
|
1045
|
-
|
|
1323
|
+
safeApply("vscode-global-cleanup", () => removePromptFile(paths.vscodeGlobalInstructions));
|
|
1324
|
+
}
|
|
1325
|
+
if (paths.vscodeInstructionsFile) {
|
|
1326
|
+
safeApply("vscode-instructions-file-cleanup", () =>
|
|
1327
|
+
removePromptFile(paths.vscodeInstructionsFile)
|
|
1046
1328
|
);
|
|
1047
1329
|
}
|
|
1048
|
-
if (paths.
|
|
1049
|
-
safeApply("
|
|
1330
|
+
if (paths.cursorAgents) {
|
|
1331
|
+
safeApply("cursor-legacy-cleanup", () => removePromptFile(paths.cursorAgents));
|
|
1332
|
+
}
|
|
1333
|
+
if (paths.cursorAgentsUpper) {
|
|
1334
|
+
safeApply("cursor-legacy-upper-cleanup", () => removePromptFile(paths.cursorAgentsUpper));
|
|
1335
|
+
}
|
|
1336
|
+
if (paths.vscodeSettings) {
|
|
1337
|
+
safeApply("vscode-settings", () =>
|
|
1338
|
+
upsertVsCodeInstructions(paths.vscodeSettings, instructions, paths.vscodeGlobalInstructions)
|
|
1339
|
+
);
|
|
1050
1340
|
}
|
|
1051
1341
|
if (paths.windsurfGlobalRules) {
|
|
1052
1342
|
safeApply("windsurf", () => upsertPromptFile(paths.windsurfGlobalRules, instructions, { prepend: true }));
|
|
@@ -1060,18 +1350,28 @@ function applyAgentInstructions({ logger } = {}) {
|
|
|
1060
1350
|
if (paths.claude) {
|
|
1061
1351
|
safeApply("claude", () => upsertClaudeInstructions(paths.claude, instructions));
|
|
1062
1352
|
}
|
|
1063
|
-
if (paths.
|
|
1064
|
-
safeApply("
|
|
1353
|
+
if (paths.gemini) {
|
|
1354
|
+
safeApply("gemini", () => upsertPromptFile(paths.gemini, instructions));
|
|
1355
|
+
}
|
|
1356
|
+
const continueYamlExists =
|
|
1357
|
+
(paths.continueYaml && fs.existsSync(paths.continueYaml)) ||
|
|
1358
|
+
(paths.continueYml && fs.existsSync(paths.continueYml));
|
|
1359
|
+
if (continueYamlExists) {
|
|
1360
|
+
if (paths.continueYaml && fs.existsSync(paths.continueYaml)) {
|
|
1361
|
+
safeApply("continue-yaml", () => upsertContinueYamlRules(paths.continueYaml, instructions));
|
|
1362
|
+
}
|
|
1363
|
+
if (paths.continueYml && fs.existsSync(paths.continueYml)) {
|
|
1364
|
+
safeApply("continue-yml", () => upsertContinueYamlRules(paths.continueYml, instructions));
|
|
1365
|
+
}
|
|
1366
|
+
if (paths.continue && fs.existsSync(paths.continue)) {
|
|
1367
|
+
safeApply("continue-json", () => upsertContinueJsonInstructions(paths.continue, instructions));
|
|
1368
|
+
}
|
|
1369
|
+
} else if (paths.continue) {
|
|
1370
|
+
safeApply("continue-json", () => upsertContinueJsonInstructions(paths.continue, instructions));
|
|
1065
1371
|
}
|
|
1066
1372
|
if (paths.zed) {
|
|
1067
1373
|
safeApply("zed", () => upsertZedInstructions(paths.zed, instructions));
|
|
1068
1374
|
}
|
|
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
1375
|
if (paths.openInterpreterConfig) {
|
|
1076
1376
|
safeApply("open-interpreter", () =>
|
|
1077
1377
|
upsertYamlInstruction(paths.openInterpreterConfig, "system_message", instructions)
|