docdex 0.2.16 → 0.2.17
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 +117 -0
- package/bin/docdex-mcp-server.js +66 -0
- package/bin/docdex.js +32 -2
- package/lib/install.js +310 -8
- package/lib/playwright_fetch.js +174 -0
- package/lib/playwright_install.js +302 -0
- package/lib/postinstall_setup.js +318 -5
- package/package.json +5 -2
package/lib/postinstall_setup.js
CHANGED
|
@@ -19,6 +19,7 @@ const DEFAULT_OLLAMA_MODEL = "nomic-embed-text";
|
|
|
19
19
|
const DEFAULT_OLLAMA_CHAT_MODEL = "phi3.5:3.8b";
|
|
20
20
|
const DEFAULT_OLLAMA_CHAT_MODEL_SIZE_GIB = 2.2;
|
|
21
21
|
const SETUP_PENDING_MARKER = "setup_pending.json";
|
|
22
|
+
const AGENTS_DOC_FILENAME = "agents.md";
|
|
22
23
|
|
|
23
24
|
function defaultConfigPath() {
|
|
24
25
|
return path.join(os.homedir(), ".docdex", "config.toml");
|
|
@@ -153,6 +154,126 @@ function writeJson(pathname, value) {
|
|
|
153
154
|
fs.writeFileSync(pathname, JSON.stringify(value, null, 2) + "\n");
|
|
154
155
|
}
|
|
155
156
|
|
|
157
|
+
function agentsDocSourcePath() {
|
|
158
|
+
return path.join(__dirname, "..", "assets", AGENTS_DOC_FILENAME);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
function loadAgentInstructions() {
|
|
162
|
+
const sourcePath = agentsDocSourcePath();
|
|
163
|
+
if (!fs.existsSync(sourcePath)) return "";
|
|
164
|
+
try {
|
|
165
|
+
return fs.readFileSync(sourcePath, "utf8");
|
|
166
|
+
} catch {
|
|
167
|
+
return "";
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
function normalizeInstructionText(value) {
|
|
172
|
+
return String(value || "").trim();
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
function mergeInstructionText(existing, instructions) {
|
|
176
|
+
const next = normalizeInstructionText(instructions);
|
|
177
|
+
if (!next) return normalizeInstructionText(existing);
|
|
178
|
+
const current = normalizeInstructionText(existing);
|
|
179
|
+
if (!current) return next;
|
|
180
|
+
if (current.includes(next)) return current;
|
|
181
|
+
return `${current}\n\n${next}`;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
function writeTextFile(pathname, contents) {
|
|
185
|
+
const next = contents.endsWith("\n") ? contents : `${contents}\n`;
|
|
186
|
+
let current = "";
|
|
187
|
+
if (fs.existsSync(pathname)) {
|
|
188
|
+
current = fs.readFileSync(pathname, "utf8");
|
|
189
|
+
if (current === next) return false;
|
|
190
|
+
}
|
|
191
|
+
fs.mkdirSync(path.dirname(pathname), { recursive: true });
|
|
192
|
+
fs.writeFileSync(pathname, next);
|
|
193
|
+
return true;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
function upsertPromptFile(pathname, instructions, { prepend = false } = {}) {
|
|
197
|
+
const next = normalizeInstructionText(instructions);
|
|
198
|
+
if (!next) return false;
|
|
199
|
+
let current = "";
|
|
200
|
+
if (fs.existsSync(pathname)) {
|
|
201
|
+
current = fs.readFileSync(pathname, "utf8");
|
|
202
|
+
if (current.includes(next)) return false;
|
|
203
|
+
}
|
|
204
|
+
const currentTrimmed = normalizeInstructionText(current);
|
|
205
|
+
let merged = next;
|
|
206
|
+
if (currentTrimmed) {
|
|
207
|
+
merged = prepend ? `${next}\n\n${currentTrimmed}` : `${currentTrimmed}\n\n${next}`;
|
|
208
|
+
}
|
|
209
|
+
return writeTextFile(pathname, merged);
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
function escapeRegExp(value) {
|
|
213
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
function upsertYamlInstruction(pathname, key, instructions) {
|
|
217
|
+
const next = normalizeInstructionText(instructions);
|
|
218
|
+
if (!next) return false;
|
|
219
|
+
let current = "";
|
|
220
|
+
if (fs.existsSync(pathname)) {
|
|
221
|
+
current = fs.readFileSync(pathname, "utf8");
|
|
222
|
+
}
|
|
223
|
+
const keyRe = new RegExp(`^\\s*${escapeRegExp(key)}\\s*:`, "m");
|
|
224
|
+
if (keyRe.test(current)) {
|
|
225
|
+
if (current.includes(next)) return false;
|
|
226
|
+
return false;
|
|
227
|
+
}
|
|
228
|
+
const lines = next.split(/\r?\n/).map((line) => ` ${line}`);
|
|
229
|
+
const block = `${key}: |\n${lines.join("\n")}`;
|
|
230
|
+
const merged = current.trim() ? `${current.trim()}\n\n${block}` : block;
|
|
231
|
+
return writeTextFile(pathname, merged);
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
function upsertClaudeInstructions(pathname, instructions) {
|
|
235
|
+
const { value } = readJson(pathname);
|
|
236
|
+
if (typeof value !== "object" || value == null || Array.isArray(value)) return false;
|
|
237
|
+
const merged = mergeInstructionText(value.instructions, instructions);
|
|
238
|
+
if (!merged || merged === value.instructions) return false;
|
|
239
|
+
value.instructions = merged;
|
|
240
|
+
writeJson(pathname, value);
|
|
241
|
+
return true;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
function upsertContinueInstructions(pathname, instructions) {
|
|
245
|
+
const { value } = readJson(pathname);
|
|
246
|
+
if (typeof value !== "object" || value == null || Array.isArray(value)) return false;
|
|
247
|
+
const merged = mergeInstructionText(value.systemMessage, instructions);
|
|
248
|
+
if (!merged || merged === value.systemMessage) return false;
|
|
249
|
+
value.systemMessage = merged;
|
|
250
|
+
writeJson(pathname, value);
|
|
251
|
+
return true;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
function upsertZedInstructions(pathname, instructions) {
|
|
255
|
+
const { value } = readJson(pathname);
|
|
256
|
+
if (typeof value !== "object" || value == null || Array.isArray(value)) return false;
|
|
257
|
+
if (!value.assistant || typeof value.assistant !== "object" || Array.isArray(value.assistant)) {
|
|
258
|
+
value.assistant = {};
|
|
259
|
+
}
|
|
260
|
+
const merged = mergeInstructionText(value.assistant.system_prompt, instructions);
|
|
261
|
+
if (!merged || merged === value.assistant.system_prompt) return false;
|
|
262
|
+
value.assistant.system_prompt = merged;
|
|
263
|
+
writeJson(pathname, value);
|
|
264
|
+
return true;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
function upsertVsCodeInstructions(pathname, instructionsPath) {
|
|
268
|
+
const { value } = readJson(pathname);
|
|
269
|
+
if (typeof value !== "object" || value == null || Array.isArray(value)) return false;
|
|
270
|
+
const key = "copilot.chat.codeGeneration.instructions";
|
|
271
|
+
if (value[key] === instructionsPath) return false;
|
|
272
|
+
value[key] = instructionsPath;
|
|
273
|
+
writeJson(pathname, value);
|
|
274
|
+
return true;
|
|
275
|
+
}
|
|
276
|
+
|
|
156
277
|
function upsertMcpServerJson(pathname, url) {
|
|
157
278
|
const { value } = readJson(pathname);
|
|
158
279
|
if (typeof value !== "object" || value == null || Array.isArray(value)) return false;
|
|
@@ -210,6 +331,7 @@ function upsertCodexConfig(pathname, url) {
|
|
|
210
331
|
new RegExp(`^\\s*\\[${section}\\]\\s*$`, "m").test(contents);
|
|
211
332
|
const hasNestedMcpServers = (contents) =>
|
|
212
333
|
/^\s*\[mcp_servers\.[^\]]+\]\s*$/m.test(contents);
|
|
334
|
+
const legacyInstructionPath = "~/.docdex/agents.md";
|
|
213
335
|
const parseTomlString = (value) => {
|
|
214
336
|
const trimmed = value.trim();
|
|
215
337
|
const quoted = trimmed.match(/^"(.*)"$/) || trimmed.match(/^'(.*)'$/);
|
|
@@ -336,6 +458,52 @@ function upsertCodexConfig(pathname, url) {
|
|
|
336
458
|
return { contents: lines.join("\n"), updated };
|
|
337
459
|
};
|
|
338
460
|
|
|
461
|
+
const removeLegacyInstructions = (text) => {
|
|
462
|
+
const lines = text.split(/\r?\n/);
|
|
463
|
+
const output = [];
|
|
464
|
+
let inFeatures = false;
|
|
465
|
+
let featuresHasEntries = false;
|
|
466
|
+
let buffer = [];
|
|
467
|
+
let updated = false;
|
|
468
|
+
|
|
469
|
+
const flushFeatures = () => {
|
|
470
|
+
if (!inFeatures) return;
|
|
471
|
+
if (featuresHasEntries) output.push(...buffer);
|
|
472
|
+
inFeatures = false;
|
|
473
|
+
featuresHasEntries = false;
|
|
474
|
+
buffer = [];
|
|
475
|
+
};
|
|
476
|
+
|
|
477
|
+
for (const line of lines) {
|
|
478
|
+
const section = line.match(/^\s*\[([^\]]+)\]\s*$/);
|
|
479
|
+
if (section) {
|
|
480
|
+
flushFeatures();
|
|
481
|
+
if (section[1].trim() === "features") {
|
|
482
|
+
inFeatures = true;
|
|
483
|
+
buffer = [line];
|
|
484
|
+
continue;
|
|
485
|
+
}
|
|
486
|
+
output.push(line);
|
|
487
|
+
continue;
|
|
488
|
+
}
|
|
489
|
+
if (inFeatures) {
|
|
490
|
+
const match = line.match(/^\s*experimental_instructions_file\s*=\s*(.+?)\s*$/);
|
|
491
|
+
if (match && parseTomlString(match[1]) === legacyInstructionPath) {
|
|
492
|
+
updated = true;
|
|
493
|
+
continue;
|
|
494
|
+
}
|
|
495
|
+
if (line.trim() && !line.trim().startsWith("#") && /=/.test(line)) {
|
|
496
|
+
featuresHasEntries = true;
|
|
497
|
+
}
|
|
498
|
+
buffer.push(line);
|
|
499
|
+
continue;
|
|
500
|
+
}
|
|
501
|
+
output.push(line);
|
|
502
|
+
}
|
|
503
|
+
flushFeatures();
|
|
504
|
+
return { contents: output.join("\n"), updated };
|
|
505
|
+
};
|
|
506
|
+
|
|
339
507
|
let contents = "";
|
|
340
508
|
if (fs.existsSync(pathname)) {
|
|
341
509
|
contents = fs.readFileSync(pathname, "utf8");
|
|
@@ -347,6 +515,10 @@ function upsertCodexConfig(pathname, url) {
|
|
|
347
515
|
updated = updated || migrated.migrated;
|
|
348
516
|
}
|
|
349
517
|
|
|
518
|
+
const cleaned = removeLegacyInstructions(contents);
|
|
519
|
+
contents = cleaned.contents;
|
|
520
|
+
updated = updated || cleaned.updated;
|
|
521
|
+
|
|
350
522
|
if (hasNestedMcpServers(contents)) {
|
|
351
523
|
const nested = upsertDocdexNested(contents, url);
|
|
352
524
|
contents = nested.contents;
|
|
@@ -422,6 +594,67 @@ function clientConfigPaths() {
|
|
|
422
594
|
}
|
|
423
595
|
}
|
|
424
596
|
|
|
597
|
+
function clientInstructionPaths() {
|
|
598
|
+
const home = os.homedir();
|
|
599
|
+
const appData = process.env.APPDATA || path.join(home, "AppData", "Roaming");
|
|
600
|
+
const userProfile = process.env.USERPROFILE || home;
|
|
601
|
+
const vscodeGlobalInstructions = path.join(home, ".vscode", "global_instructions.md");
|
|
602
|
+
const windsurfGlobalRules = path.join(userProfile, ".codeium", "windsurf", "memories", "global_rules.md");
|
|
603
|
+
const rooRules = path.join(home, ".roo", "rules", "docdex.md");
|
|
604
|
+
const pearaiAgent = path.join(home, ".config", "pearai", "agent.md");
|
|
605
|
+
const aiderConfig = path.join(home, ".aider.conf.yml");
|
|
606
|
+
const gooseConfig = path.join(home, ".config", "goose", "config.yaml");
|
|
607
|
+
const openInterpreterConfig = path.join(home, ".openinterpreter", "profiles", "default.yaml");
|
|
608
|
+
const codexAgents = path.join(userProfile, ".codex", "AGENTS.md");
|
|
609
|
+
switch (process.platform) {
|
|
610
|
+
case "win32":
|
|
611
|
+
return {
|
|
612
|
+
claude: path.join(appData, "Claude", "claude_desktop_config.json"),
|
|
613
|
+
continue: path.join(userProfile, ".continue", "config.json"),
|
|
614
|
+
zed: path.join(appData, "Zed", "settings.json"),
|
|
615
|
+
vscodeSettings: path.join(appData, "Code", "User", "settings.json"),
|
|
616
|
+
vscodeGlobalInstructions,
|
|
617
|
+
windsurfGlobalRules,
|
|
618
|
+
rooRules,
|
|
619
|
+
pearaiAgent,
|
|
620
|
+
aiderConfig,
|
|
621
|
+
gooseConfig,
|
|
622
|
+
openInterpreterConfig,
|
|
623
|
+
codexAgents
|
|
624
|
+
};
|
|
625
|
+
case "darwin":
|
|
626
|
+
return {
|
|
627
|
+
claude: path.join(home, "Library", "Application Support", "Claude", "claude_desktop_config.json"),
|
|
628
|
+
continue: path.join(home, ".continue", "config.json"),
|
|
629
|
+
zed: path.join(home, ".config", "zed", "settings.json"),
|
|
630
|
+
vscodeSettings: path.join(home, "Library", "Application Support", "Code", "User", "settings.json"),
|
|
631
|
+
vscodeGlobalInstructions,
|
|
632
|
+
windsurfGlobalRules,
|
|
633
|
+
rooRules,
|
|
634
|
+
pearaiAgent,
|
|
635
|
+
aiderConfig,
|
|
636
|
+
gooseConfig,
|
|
637
|
+
openInterpreterConfig,
|
|
638
|
+
codexAgents
|
|
639
|
+
};
|
|
640
|
+
default:
|
|
641
|
+
return {
|
|
642
|
+
claude: path.join(home, ".config", "Claude", "claude_desktop_config.json"),
|
|
643
|
+
continue: path.join(home, ".continue", "config.json"),
|
|
644
|
+
zed: path.join(home, ".config", "zed", "settings.json"),
|
|
645
|
+
vscodeSettings: path.join(home, ".config", "Code", "User", "settings.json"),
|
|
646
|
+
vscodeGlobalInstructions,
|
|
647
|
+
windsurfGlobalRules,
|
|
648
|
+
rooRules,
|
|
649
|
+
pearaiAgent,
|
|
650
|
+
aiderConfig,
|
|
651
|
+
gooseConfig,
|
|
652
|
+
openInterpreterConfig,
|
|
653
|
+
codexAgents
|
|
654
|
+
};
|
|
655
|
+
}
|
|
656
|
+
}
|
|
657
|
+
|
|
425
658
|
function resolveBinaryPath({ binaryPath } = {}) {
|
|
426
659
|
if (binaryPath && fs.existsSync(binaryPath)) return binaryPath;
|
|
427
660
|
try {
|
|
@@ -434,6 +667,66 @@ function resolveBinaryPath({ binaryPath } = {}) {
|
|
|
434
667
|
return null;
|
|
435
668
|
}
|
|
436
669
|
|
|
670
|
+
function applyAgentInstructions({ logger } = {}) {
|
|
671
|
+
const instructions = loadAgentInstructions();
|
|
672
|
+
if (!normalizeInstructionText(instructions)) return { ok: false, reason: "missing_instructions" };
|
|
673
|
+
const paths = clientInstructionPaths();
|
|
674
|
+
let updated = false;
|
|
675
|
+
const safeApply = (label, fn) => {
|
|
676
|
+
try {
|
|
677
|
+
const didUpdate = fn();
|
|
678
|
+
if (didUpdate) updated = true;
|
|
679
|
+
return didUpdate;
|
|
680
|
+
} catch (err) {
|
|
681
|
+
logger?.warn?.(`[docdex] agent instructions update failed for ${label}: ${err?.message || err}`);
|
|
682
|
+
return false;
|
|
683
|
+
}
|
|
684
|
+
};
|
|
685
|
+
|
|
686
|
+
if (paths.vscodeGlobalInstructions) {
|
|
687
|
+
safeApply("vscode-global", () =>
|
|
688
|
+
upsertPromptFile(paths.vscodeGlobalInstructions, instructions, { prepend: true })
|
|
689
|
+
);
|
|
690
|
+
}
|
|
691
|
+
if (paths.vscodeSettings && paths.vscodeGlobalInstructions) {
|
|
692
|
+
safeApply("vscode-settings", () => upsertVsCodeInstructions(paths.vscodeSettings, paths.vscodeGlobalInstructions));
|
|
693
|
+
}
|
|
694
|
+
if (paths.windsurfGlobalRules) {
|
|
695
|
+
safeApply("windsurf", () => upsertPromptFile(paths.windsurfGlobalRules, instructions, { prepend: true }));
|
|
696
|
+
}
|
|
697
|
+
if (paths.rooRules) {
|
|
698
|
+
safeApply("roo", () => upsertPromptFile(paths.rooRules, instructions));
|
|
699
|
+
}
|
|
700
|
+
if (paths.pearaiAgent) {
|
|
701
|
+
safeApply("pearai", () => upsertPromptFile(paths.pearaiAgent, instructions, { prepend: true }));
|
|
702
|
+
}
|
|
703
|
+
if (paths.claude) {
|
|
704
|
+
safeApply("claude", () => upsertClaudeInstructions(paths.claude, instructions));
|
|
705
|
+
}
|
|
706
|
+
if (paths.continue) {
|
|
707
|
+
safeApply("continue", () => upsertContinueInstructions(paths.continue, instructions));
|
|
708
|
+
}
|
|
709
|
+
if (paths.zed) {
|
|
710
|
+
safeApply("zed", () => upsertZedInstructions(paths.zed, instructions));
|
|
711
|
+
}
|
|
712
|
+
if (paths.aiderConfig) {
|
|
713
|
+
safeApply("aider", () => upsertYamlInstruction(paths.aiderConfig, "system-prompt", instructions));
|
|
714
|
+
}
|
|
715
|
+
if (paths.gooseConfig) {
|
|
716
|
+
safeApply("goose", () => upsertYamlInstruction(paths.gooseConfig, "instructions", instructions));
|
|
717
|
+
}
|
|
718
|
+
if (paths.openInterpreterConfig) {
|
|
719
|
+
safeApply("open-interpreter", () =>
|
|
720
|
+
upsertYamlInstruction(paths.openInterpreterConfig, "system_message", instructions)
|
|
721
|
+
);
|
|
722
|
+
}
|
|
723
|
+
if (paths.codexAgents) {
|
|
724
|
+
safeApply("codex", () => upsertPromptFile(paths.codexAgents, instructions));
|
|
725
|
+
}
|
|
726
|
+
|
|
727
|
+
return { ok: true, updated };
|
|
728
|
+
}
|
|
729
|
+
|
|
437
730
|
function resolveMcpBinaryPath(binaryPath) {
|
|
438
731
|
if (!binaryPath) return null;
|
|
439
732
|
const dir = path.dirname(binaryPath);
|
|
@@ -604,6 +897,14 @@ function normalizeModelName(name) {
|
|
|
604
897
|
return String(name || "").trim();
|
|
605
898
|
}
|
|
606
899
|
|
|
900
|
+
function isEmbeddingModelName(name) {
|
|
901
|
+
const normalized = normalizeModelName(name).toLowerCase();
|
|
902
|
+
if (!normalized) return false;
|
|
903
|
+
const base = normalized.split(":")[0];
|
|
904
|
+
const embed = DEFAULT_OLLAMA_MODEL.toLowerCase();
|
|
905
|
+
return base === embed || base.startsWith(`${embed}-`);
|
|
906
|
+
}
|
|
907
|
+
|
|
607
908
|
function readLlmDefaultModel(contents) {
|
|
608
909
|
let inLlm = false;
|
|
609
910
|
const lines = String(contents || "").split(/\r?\n/);
|
|
@@ -861,6 +1162,10 @@ async function maybePromptOllamaModel({
|
|
|
861
1162
|
|
|
862
1163
|
const forced = normalizeModelName(env.DOCDEX_OLLAMA_MODEL);
|
|
863
1164
|
if (forced) {
|
|
1165
|
+
if (isEmbeddingModelName(forced)) {
|
|
1166
|
+
logger?.warn?.(`[docdex] ${forced} is an embedding-only model; choose a chat model.`);
|
|
1167
|
+
return { status: "skipped", reason: "embedding_only" };
|
|
1168
|
+
}
|
|
864
1169
|
const installed = listOllamaModels() || [];
|
|
865
1170
|
const forcedLower = forced.toLowerCase();
|
|
866
1171
|
const hasForced = installed.some((model) => normalizeModelName(model).toLowerCase() === forcedLower);
|
|
@@ -915,7 +1220,7 @@ async function maybePromptOllamaModel({
|
|
|
915
1220
|
|
|
916
1221
|
const normalizedInstalled = installed.map(normalizeModelName);
|
|
917
1222
|
const displayModels = normalizedInstalled.map((model) => {
|
|
918
|
-
const selectable = model
|
|
1223
|
+
const selectable = !isEmbeddingModelName(model);
|
|
919
1224
|
return {
|
|
920
1225
|
model,
|
|
921
1226
|
label: selectable ? model : `${model} (embedding only)`,
|
|
@@ -971,6 +1276,11 @@ async function maybePromptOllamaModel({
|
|
|
971
1276
|
updateDefaultModelConfig(configPath, phiModel, logger);
|
|
972
1277
|
return { status: "installed", model: phiModel };
|
|
973
1278
|
}
|
|
1279
|
+
if (isEmbeddingModelName(normalizedAnswer)) {
|
|
1280
|
+
const modelName = normalizedAnswer || DEFAULT_OLLAMA_MODEL;
|
|
1281
|
+
logger?.warn?.(`[docdex] ${modelName} is an embedding-only model; choose a chat model.`);
|
|
1282
|
+
return { status: "skipped", reason: "embedding_only" };
|
|
1283
|
+
}
|
|
974
1284
|
const numeric = Number.parseInt(answerLower, 10);
|
|
975
1285
|
if (Number.isFinite(numeric) && numeric >= 1 && numeric <= displayModels.length) {
|
|
976
1286
|
const selected = displayModels[numeric - 1];
|
|
@@ -1189,6 +1499,7 @@ function commandExists(cmd, spawnSyncFn) {
|
|
|
1189
1499
|
function launchMacTerminal({ binaryPath, args, spawnSyncFn, logger }) {
|
|
1190
1500
|
const command = [
|
|
1191
1501
|
"DOCDEX_SETUP_AUTO=1",
|
|
1502
|
+
"DOCDEX_SETUP_MODE=auto",
|
|
1192
1503
|
`"${binaryPath}"`,
|
|
1193
1504
|
...args.map((arg) => `"${arg}"`)
|
|
1194
1505
|
].join(" ");
|
|
@@ -1209,7 +1520,7 @@ function launchMacTerminal({ binaryPath, args, spawnSyncFn, logger }) {
|
|
|
1209
1520
|
}
|
|
1210
1521
|
|
|
1211
1522
|
function launchLinuxTerminal({ binaryPath, args, spawnFn, spawnSyncFn }) {
|
|
1212
|
-
const envArgs = ["env", "DOCDEX_SETUP_AUTO=1", binaryPath, ...args];
|
|
1523
|
+
const envArgs = ["env", "DOCDEX_SETUP_AUTO=1", "DOCDEX_SETUP_MODE=auto", binaryPath, ...args];
|
|
1213
1524
|
const candidates = [
|
|
1214
1525
|
{ cmd: "x-terminal-emulator", args: ["-e", ...envArgs] },
|
|
1215
1526
|
{ cmd: "gnome-terminal", args: ["--", ...envArgs] },
|
|
@@ -1248,7 +1559,7 @@ function launchSetupWizard({
|
|
|
1248
1559
|
if (!binaryPath) return { ok: false, reason: "missing_binary" };
|
|
1249
1560
|
if (shouldSkipSetup(env)) return { ok: false, reason: "skipped" };
|
|
1250
1561
|
|
|
1251
|
-
const args = ["setup"];
|
|
1562
|
+
const args = ["setup", "--auto"];
|
|
1252
1563
|
if (platform === "linux" || platform === "darwin") {
|
|
1253
1564
|
if (!canPrompt(stdin, stdout)) {
|
|
1254
1565
|
return { ok: false, reason: "non_interactive" };
|
|
@@ -1265,7 +1576,7 @@ function launchSetupWizard({
|
|
|
1265
1576
|
|
|
1266
1577
|
if (platform === "win32") {
|
|
1267
1578
|
const quoted = `"${binaryPath}" ${args.map((arg) => `"${arg}"`).join(" ")}`;
|
|
1268
|
-
const cmdline = `set DOCDEX_SETUP_AUTO=1 && ${quoted}`;
|
|
1579
|
+
const cmdline = `set DOCDEX_SETUP_AUTO=1 && set DOCDEX_SETUP_MODE=auto && ${quoted}`;
|
|
1269
1580
|
const result = spawnSyncFn("cmd", ["/c", "start", "", "cmd", "/c", cmdline]);
|
|
1270
1581
|
if (result.status === 0) return { ok: true };
|
|
1271
1582
|
logger?.warn?.(`[docdex] cmd start failed: ${result.stderr || "unknown error"}`);
|
|
@@ -1323,6 +1634,7 @@ async function runPostInstallSetup({ binaryPath, logger } = {}) {
|
|
|
1323
1634
|
upsertZedConfig(paths.zed, url);
|
|
1324
1635
|
}
|
|
1325
1636
|
upsertCodexConfig(paths.codex, codexUrl);
|
|
1637
|
+
applyAgentInstructions({ logger: log });
|
|
1326
1638
|
|
|
1327
1639
|
const daemonRoot = ensureDaemonRoot();
|
|
1328
1640
|
const resolvedBinary = resolveBinaryPath({ binaryPath });
|
|
@@ -1375,5 +1687,6 @@ module.exports = {
|
|
|
1375
1687
|
hasInteractiveTty,
|
|
1376
1688
|
canPromptWithTty,
|
|
1377
1689
|
shouldSkipSetup,
|
|
1378
|
-
launchSetupWizard
|
|
1690
|
+
launchSetupWizard,
|
|
1691
|
+
applyAgentInstructions
|
|
1379
1692
|
};
|
package/package.json
CHANGED
|
@@ -1,15 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "docdex",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.17",
|
|
4
4
|
"mcpName": "io.github.bekirdag/docdex",
|
|
5
5
|
"description": "Local-first documentation and code indexer with HTTP/MCP search, AST, and agent memory.",
|
|
6
6
|
"bin": {
|
|
7
7
|
"docdex": "bin/docdex.js",
|
|
8
|
-
"docdexd": "bin/docdex.js"
|
|
8
|
+
"docdexd": "bin/docdex.js",
|
|
9
|
+
"docdex-mcp-server": "bin/docdex-mcp-server.js"
|
|
9
10
|
},
|
|
10
11
|
"files": [
|
|
11
12
|
"bin",
|
|
12
13
|
"lib",
|
|
14
|
+
"assets",
|
|
13
15
|
"README.md",
|
|
14
16
|
"CHANGELOG.md",
|
|
15
17
|
"LICENSE"
|
|
@@ -60,6 +62,7 @@
|
|
|
60
62
|
"access": "public"
|
|
61
63
|
},
|
|
62
64
|
"dependencies": {
|
|
65
|
+
"playwright": "^1.49.0",
|
|
63
66
|
"tar": "^6.2.1"
|
|
64
67
|
}
|
|
65
68
|
}
|