@draht/coding-agent 2026.3.11-1 → 2026.3.14
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/CHANGELOG.md +45 -0
- package/bin/draht-tools.cjs +187 -32
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +2 -2
- package/dist/config.js.map +1 -1
- package/dist/core/package-manager.d.ts.map +1 -1
- package/dist/core/package-manager.js +1 -1
- package/dist/core/package-manager.js.map +1 -1
- package/dist/gsd/domain.d.ts +5 -1
- package/dist/gsd/domain.d.ts.map +1 -1
- package/dist/gsd/domain.js +71 -1
- package/dist/gsd/domain.js.map +1 -1
- package/dist/gsd/git.d.ts.map +1 -1
- package/dist/gsd/git.js +18 -0
- package/dist/gsd/git.js.map +1 -1
- package/dist/gsd/index.d.ts +1 -0
- package/dist/gsd/index.d.ts.map +1 -1
- package/dist/gsd/index.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +2 -0
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/prompts/commands/execute-phase.md +2 -2
- package/dist/prompts/commands/fix.md +2 -2
- package/dist/prompts/commands/plan-phase.md +5 -1
- package/dist/prompts/commands/quick.md +5 -1
- package/dist/utils/changelog.d.ts +12 -0
- package/dist/utils/changelog.d.ts.map +1 -1
- package/dist/utils/changelog.js +25 -14
- package/dist/utils/changelog.js.map +1 -1
- package/dist/utils/notify.d.ts +12 -0
- package/dist/utils/notify.d.ts.map +1 -0
- package/dist/utils/notify.js +41 -0
- package/dist/utils/notify.js.map +1 -0
- package/examples/extensions/antigravity-image-gen.ts +5 -4
- package/examples/extensions/custom-provider-gitlab-duo/test.ts +2 -2
- package/examples/extensions/notify.ts +9 -2
- package/examples/extensions/preset.ts +2 -3
- package/examples/extensions/sandbox/index.ts +2 -3
- package/examples/extensions/tool-override.ts +2 -3
- package/package.json +4 -4
- package/prompts/commands/execute-phase.md +2 -2
- package/prompts/commands/fix.md +2 -2
- package/prompts/commands/plan-phase.md +5 -1
- package/prompts/commands/quick.md +5 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,50 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [2026.3.14] - 2026-03-14
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
|
|
7
|
+
- built-in terminal notification on agent turn end
|
|
8
|
+
|
|
9
|
+
### Changed
|
|
10
|
+
|
|
11
|
+
- fix(coding-agent): use getAgentDir() in example extensions (#2009)
|
|
12
|
+
- Export the structured mapping contract through the public GSD entrypoint
|
|
13
|
+
- Add typed extraction results to GSD domain mapping
|
|
14
|
+
- consolidate quality gate fixture helpers
|
|
15
|
+
- Cover strict-mode TypeScript error detection
|
|
16
|
+
- add TypeScript-error quality gate scenario
|
|
17
|
+
- Cover passing and failing test-suite outcomes
|
|
18
|
+
- add failing test-suite quality gate scenario
|
|
19
|
+
- Create a real-hook quality gate test harness
|
|
20
|
+
- add real quality gate hook harness test
|
|
21
|
+
- verify phase 21 lifecycle execution logs
|
|
22
|
+
- add failing phase 21 execution log verification test
|
|
23
|
+
- exercise phase 21 lifecycle task commit flow
|
|
24
|
+
- add failing phase 21 lifecycle commit flow test
|
|
25
|
+
- define mapCodebase structured extraction contract
|
|
26
|
+
- build phase 21 lifecycle workspace fixture
|
|
27
|
+
- add failing phase 21 lifecycle fixture test
|
|
28
|
+
- reduce duplicated domain fixture assertions
|
|
29
|
+
- Create a stable domain fixture codebase
|
|
30
|
+
- replace gsd structure checks with runtime loading coverage
|
|
31
|
+
- specify stable GSD domain fixture exports
|
|
32
|
+
- add gsd extension runtime loading spec
|
|
33
|
+
- extract reusable temp git repo setup steps
|
|
34
|
+
- Implement the shared git repo helper
|
|
35
|
+
- specify isolated temp git repo helper behavior
|
|
36
|
+
|
|
37
|
+
### Fixed
|
|
38
|
+
|
|
39
|
+
- add stdin support to all draht-tools write commands
|
|
40
|
+
- add cmux support to notify example extension
|
|
41
|
+
- add stdin support to create-quick-plan and fix plan prompts to pipe actual content
|
|
42
|
+
- use conventional commit prefixes instead of TDD annotations in prompt templates
|
|
43
|
+
- restore phase 21 verification baseline
|
|
44
|
+
- The draht-tools create-plan command now reads stdin content when piped
|
|
45
|
+
- handle date-based version suffixes in changelog parsing
|
|
46
|
+
- change default update instruction to bun add -g
|
|
47
|
+
|
|
3
48
|
## [2026.3.11] - 2026-03-11
|
|
4
49
|
|
|
5
50
|
### Added
|
package/bin/draht-tools.cjs
CHANGED
|
@@ -305,7 +305,8 @@ commands["phase-info"] = function (n) {
|
|
|
305
305
|
};
|
|
306
306
|
|
|
307
307
|
// --- save-context ---
|
|
308
|
-
|
|
308
|
+
// Supports stdin: echo "content" | draht-tools save-context N
|
|
309
|
+
commands["save-context"] = async function (n, ...rest) {
|
|
309
310
|
const num = parseInt(n, 10);
|
|
310
311
|
if (!num) { console.error("Usage: draht-tools save-context N"); process.exit(1); }
|
|
311
312
|
|
|
@@ -314,7 +315,22 @@ commands["save-context"] = function (n, ...rest) {
|
|
|
314
315
|
ensureDir(dir);
|
|
315
316
|
|
|
316
317
|
const contextPath = path.join(dir, `${padNum(num)}-CONTEXT.md`);
|
|
317
|
-
|
|
318
|
+
|
|
319
|
+
// Check for stdin content (piped input)
|
|
320
|
+
let stdinContent = "";
|
|
321
|
+
if (!process.stdin.isTTY) {
|
|
322
|
+
stdinContent = await new Promise((resolve) => {
|
|
323
|
+
let data = "";
|
|
324
|
+
process.stdin.setEncoding("utf-8");
|
|
325
|
+
process.stdin.on("data", (chunk) => { data += chunk; });
|
|
326
|
+
process.stdin.on("end", () => { resolve(data.trim()); });
|
|
327
|
+
});
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
if (stdinContent) {
|
|
331
|
+
writeMd(contextPath, stdinContent);
|
|
332
|
+
console.log(`Created: ${contextPath}`);
|
|
333
|
+
} else if (fs.existsSync(contextPath)) {
|
|
318
334
|
console.log(`Context already exists at ${contextPath}`);
|
|
319
335
|
console.log("Edit it directly or pass content via stdin.");
|
|
320
336
|
} else {
|
|
@@ -372,7 +388,8 @@ commands["load-phase-context"] = function (n) {
|
|
|
372
388
|
};
|
|
373
389
|
|
|
374
390
|
// --- create-plan ---
|
|
375
|
-
|
|
391
|
+
// Supports stdin: echo "content" | draht-tools create-plan N P [title]
|
|
392
|
+
commands["create-plan"] = async function (n, p, ...titleWords) {
|
|
376
393
|
const phaseNum = parseInt(n, 10);
|
|
377
394
|
const planNum = parseInt(p, 10);
|
|
378
395
|
if (!phaseNum || !planNum) { console.error("Usage: draht-tools create-plan N P [title]"); process.exit(1); }
|
|
@@ -384,7 +401,24 @@ commands["create-plan"] = function (n, p, ...titleWords) {
|
|
|
384
401
|
const title = titleWords.join(" ") || `Plan ${planNum}`;
|
|
385
402
|
const planPath = path.join(dir, `${padNum(phaseNum)}-${padNum(planNum)}-PLAN.md`);
|
|
386
403
|
|
|
387
|
-
|
|
404
|
+
// Check for stdin content (piped input)
|
|
405
|
+
let stdinContent = "";
|
|
406
|
+
if (!process.stdin.isTTY) {
|
|
407
|
+
stdinContent = await new Promise((resolve) => {
|
|
408
|
+
let data = "";
|
|
409
|
+
process.stdin.setEncoding("utf-8");
|
|
410
|
+
process.stdin.on("data", (chunk) => { data += chunk; });
|
|
411
|
+
process.stdin.on("end", () => { resolve(data.trim()); });
|
|
412
|
+
});
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
let content;
|
|
416
|
+
if (stdinContent) {
|
|
417
|
+
// Use stdin content directly
|
|
418
|
+
content = stdinContent;
|
|
419
|
+
} else {
|
|
420
|
+
// Generate template
|
|
421
|
+
content = `---
|
|
388
422
|
phase: ${phaseNum}
|
|
389
423
|
plan: ${planNum}
|
|
390
424
|
depends_on: []
|
|
@@ -417,7 +451,9 @@ must_haves:
|
|
|
417
451
|
---
|
|
418
452
|
Created: ${timestamp()}
|
|
419
453
|
`;
|
|
420
|
-
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
writeMd(planPath, content);
|
|
421
457
|
console.log(`Created: ${planPath}`);
|
|
422
458
|
};
|
|
423
459
|
|
|
@@ -547,7 +583,8 @@ commands["commit-task"] = function (n, p, t, ...desc) {
|
|
|
547
583
|
};
|
|
548
584
|
|
|
549
585
|
// --- write-summary ---
|
|
550
|
-
|
|
586
|
+
// Supports stdin: echo "content" | draht-tools write-summary N P
|
|
587
|
+
commands["write-summary"] = async function (n, p) {
|
|
551
588
|
const phaseNum = parseInt(n, 10);
|
|
552
589
|
const planNum = parseInt(p, 10);
|
|
553
590
|
if (!phaseNum || !planNum) { console.error("Usage: draht-tools write-summary N P"); process.exit(1); }
|
|
@@ -556,8 +593,26 @@ commands["write-summary"] = function (n, p) {
|
|
|
556
593
|
if (!phaseDir) { console.error(`Phase ${phaseNum} not found`); process.exit(1); }
|
|
557
594
|
|
|
558
595
|
const summaryPath = path.join(phaseDir, `${padNum(phaseNum)}-${padNum(planNum)}-SUMMARY.md`);
|
|
559
|
-
|
|
560
|
-
|
|
596
|
+
|
|
597
|
+
// Check for stdin content (piped input)
|
|
598
|
+
let stdinContent = "";
|
|
599
|
+
if (!process.stdin.isTTY) {
|
|
600
|
+
stdinContent = await new Promise((resolve) => {
|
|
601
|
+
let data = "";
|
|
602
|
+
process.stdin.setEncoding("utf-8");
|
|
603
|
+
process.stdin.on("data", (chunk) => { data += chunk; });
|
|
604
|
+
process.stdin.on("end", () => { resolve(data.trim()); });
|
|
605
|
+
});
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
let content;
|
|
609
|
+
if (stdinContent) {
|
|
610
|
+
content = stdinContent;
|
|
611
|
+
} else {
|
|
612
|
+
content = `# Phase ${phaseNum}, Plan ${planNum} Summary\n\n## Completed Tasks\n| # | Task | Status | Commit |\n|---|------|--------|--------|\n| 1 | [task] | ✅ Done | [hash] |\n\n## Files Changed\n- [files]\n\n## Verification Results\n- [results]\n\n## Notes\n[deviations, decisions]\n\n---\nCompleted: ${timestamp()}\n`;
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
writeMd(summaryPath, content);
|
|
561
616
|
console.log(`Created: ${summaryPath}`);
|
|
562
617
|
};
|
|
563
618
|
|
|
@@ -628,17 +683,35 @@ commands["extract-deliverables"] = function (n) {
|
|
|
628
683
|
};
|
|
629
684
|
|
|
630
685
|
// --- create-fix-plan ---
|
|
631
|
-
|
|
686
|
+
// Supports stdin: echo "content" | draht-tools create-fix-plan N P [issue]
|
|
687
|
+
commands["create-fix-plan"] = async function (n, p, ...issueWords) {
|
|
632
688
|
const phaseNum = parseInt(n, 10);
|
|
633
689
|
const planNum = parseInt(p, 10);
|
|
634
690
|
if (!phaseNum || !planNum) { console.error("Usage: draht-tools create-fix-plan N P [issue]"); process.exit(1); }
|
|
635
691
|
|
|
636
692
|
const slug = getPhaseSlug(phaseNum) || `phase-${phaseNum}`;
|
|
637
693
|
const dir = planningPath("phases", `${padNum(phaseNum)}-${slug}`);
|
|
694
|
+
ensureDir(dir);
|
|
638
695
|
const issue = issueWords.join(" ") || "Fix identified issues";
|
|
639
696
|
|
|
640
697
|
const fixPath = path.join(dir, `${padNum(phaseNum)}-${padNum(planNum)}-FIX-PLAN.md`);
|
|
641
|
-
|
|
698
|
+
|
|
699
|
+
// Check for stdin content (piped input)
|
|
700
|
+
let stdinContent = "";
|
|
701
|
+
if (!process.stdin.isTTY) {
|
|
702
|
+
stdinContent = await new Promise((resolve) => {
|
|
703
|
+
let data = "";
|
|
704
|
+
process.stdin.setEncoding("utf-8");
|
|
705
|
+
process.stdin.on("data", (chunk) => { data += chunk; });
|
|
706
|
+
process.stdin.on("end", () => { resolve(data.trim()); });
|
|
707
|
+
});
|
|
708
|
+
}
|
|
709
|
+
|
|
710
|
+
let content;
|
|
711
|
+
if (stdinContent) {
|
|
712
|
+
content = stdinContent;
|
|
713
|
+
} else {
|
|
714
|
+
content = `---
|
|
642
715
|
gap_closure: true
|
|
643
716
|
fixes_plan: ${planNum}
|
|
644
717
|
issue: "${issue}"
|
|
@@ -662,12 +735,15 @@ ${issue}
|
|
|
662
735
|
---
|
|
663
736
|
Created: ${timestamp()}
|
|
664
737
|
`;
|
|
665
|
-
|
|
738
|
+
}
|
|
739
|
+
|
|
740
|
+
writeMd(fixPath, content);
|
|
666
741
|
console.log(`Created: ${fixPath}`);
|
|
667
742
|
};
|
|
668
743
|
|
|
669
744
|
// --- write-uat ---
|
|
670
|
-
|
|
745
|
+
// Supports stdin: echo "content" | draht-tools write-uat N
|
|
746
|
+
commands["write-uat"] = async function (n) {
|
|
671
747
|
const num = parseInt(n, 10);
|
|
672
748
|
if (!num) { console.error("Usage: draht-tools write-uat N"); process.exit(1); }
|
|
673
749
|
|
|
@@ -675,8 +751,26 @@ commands["write-uat"] = function (n) {
|
|
|
675
751
|
if (!phaseDir) { console.error(`Phase ${num} not found`); process.exit(1); }
|
|
676
752
|
|
|
677
753
|
const uatPath = path.join(phaseDir, `${padNum(num)}-UAT.md`);
|
|
678
|
-
|
|
679
|
-
|
|
754
|
+
|
|
755
|
+
// Check for stdin content (piped input)
|
|
756
|
+
let stdinContent = "";
|
|
757
|
+
if (!process.stdin.isTTY) {
|
|
758
|
+
stdinContent = await new Promise((resolve) => {
|
|
759
|
+
let data = "";
|
|
760
|
+
process.stdin.setEncoding("utf-8");
|
|
761
|
+
process.stdin.on("data", (chunk) => { data += chunk; });
|
|
762
|
+
process.stdin.on("end", () => { resolve(data.trim()); });
|
|
763
|
+
});
|
|
764
|
+
}
|
|
765
|
+
|
|
766
|
+
let content;
|
|
767
|
+
if (stdinContent) {
|
|
768
|
+
content = stdinContent;
|
|
769
|
+
} else {
|
|
770
|
+
content = `# Phase ${num} User Acceptance Testing\n\n## Test Date: ${dateStamp()}\n\n## Results\n| # | Deliverable | Status | Notes |\n|---|-------------|--------|-------|\n| 1 | [description] | ✅ Pass | |\n\n## Summary\n- Passed: X/Y\n- Failed: 0/Y\n- Skipped: 0/Y\n\n## Fix Plans Created\n(none)\n`;
|
|
771
|
+
}
|
|
772
|
+
|
|
773
|
+
writeMd(uatPath, content);
|
|
680
774
|
console.log(`Created: ${uatPath}`);
|
|
681
775
|
};
|
|
682
776
|
|
|
@@ -691,7 +785,8 @@ commands["next-quick-number"] = function () {
|
|
|
691
785
|
};
|
|
692
786
|
|
|
693
787
|
// --- create-quick-plan ---
|
|
694
|
-
|
|
788
|
+
// Supports stdin: echo "content" | draht-tools create-quick-plan NNN [desc]
|
|
789
|
+
commands["create-quick-plan"] = async function (n, ...descWords) {
|
|
695
790
|
const num = padNum(parseInt(n, 10), 3);
|
|
696
791
|
const desc = descWords.join(" ") || "Quick task";
|
|
697
792
|
const slug = slugify(desc);
|
|
@@ -699,13 +794,34 @@ commands["create-quick-plan"] = function (n, ...descWords) {
|
|
|
699
794
|
ensureDir(dir);
|
|
700
795
|
|
|
701
796
|
const planPath = path.join(dir, `${num}-PLAN.md`);
|
|
702
|
-
|
|
703
|
-
|
|
797
|
+
|
|
798
|
+
// Check for stdin content (piped input)
|
|
799
|
+
let stdinContent = "";
|
|
800
|
+
if (!process.stdin.isTTY) {
|
|
801
|
+
stdinContent = await new Promise((resolve) => {
|
|
802
|
+
let data = "";
|
|
803
|
+
process.stdin.setEncoding("utf-8");
|
|
804
|
+
process.stdin.on("data", (chunk) => { data += chunk; });
|
|
805
|
+
process.stdin.on("end", () => { resolve(data.trim()); });
|
|
806
|
+
});
|
|
807
|
+
}
|
|
808
|
+
|
|
809
|
+
let content;
|
|
810
|
+
if (stdinContent) {
|
|
811
|
+
// Use stdin content directly
|
|
812
|
+
content = stdinContent;
|
|
813
|
+
} else {
|
|
814
|
+
// Generate template
|
|
815
|
+
content = `# Quick Task ${num}: ${desc}\n\n## Tasks\n\n<task type="auto">\n <n>[Task]</n>\n <files>[files]</files>\n <action>[instructions]</action>\n <verify>[verify]</verify>\n <done>[done]</done>\n</task>\n\n---\nCreated: ${timestamp()}\n`;
|
|
816
|
+
}
|
|
817
|
+
|
|
818
|
+
writeMd(planPath, content);
|
|
704
819
|
console.log(`Created: ${planPath}`);
|
|
705
820
|
};
|
|
706
821
|
|
|
707
822
|
// --- write-quick-summary ---
|
|
708
|
-
|
|
823
|
+
// Supports stdin: echo "content" | draht-tools write-quick-summary NNN
|
|
824
|
+
commands["write-quick-summary"] = async function (n) {
|
|
709
825
|
const num = padNum(parseInt(n, 10), 3);
|
|
710
826
|
const dir = planningPath("quick");
|
|
711
827
|
if (!fs.existsSync(dir)) { console.error("No quick tasks directory"); process.exit(1); }
|
|
@@ -713,8 +829,26 @@ commands["write-quick-summary"] = function (n) {
|
|
|
713
829
|
if (!match) { console.error(`Quick task ${num} not found`); process.exit(1); }
|
|
714
830
|
|
|
715
831
|
const summaryPath = path.join(dir, match, `${num}-SUMMARY.md`);
|
|
716
|
-
|
|
717
|
-
|
|
832
|
+
|
|
833
|
+
// Check for stdin content (piped input)
|
|
834
|
+
let stdinContent = "";
|
|
835
|
+
if (!process.stdin.isTTY) {
|
|
836
|
+
stdinContent = await new Promise((resolve) => {
|
|
837
|
+
let data = "";
|
|
838
|
+
process.stdin.setEncoding("utf-8");
|
|
839
|
+
process.stdin.on("data", (chunk) => { data += chunk; });
|
|
840
|
+
process.stdin.on("end", () => { resolve(data.trim()); });
|
|
841
|
+
});
|
|
842
|
+
}
|
|
843
|
+
|
|
844
|
+
let content;
|
|
845
|
+
if (stdinContent) {
|
|
846
|
+
content = stdinContent;
|
|
847
|
+
} else {
|
|
848
|
+
content = `# Quick Task ${num} Summary\n\n## Tasks Completed\n| # | Task | Status | Commit |\n|---|------|--------|--------|\n| 1 | [task] | ✅ Done | [hash] |\n\n## Files Changed\n- [files]\n\n---\nCompleted: ${timestamp()}\n`;
|
|
849
|
+
}
|
|
850
|
+
|
|
851
|
+
writeMd(summaryPath, content);
|
|
718
852
|
console.log(`Created: ${summaryPath}`);
|
|
719
853
|
};
|
|
720
854
|
|
|
@@ -826,7 +960,8 @@ commands["commit-docs"] = function (...msg) {
|
|
|
826
960
|
};
|
|
827
961
|
|
|
828
962
|
// --- research-phase ---
|
|
829
|
-
|
|
963
|
+
// Supports stdin: echo "content" | draht-tools research-phase N
|
|
964
|
+
commands["research-phase"] = async function (n) {
|
|
830
965
|
const num = parseInt(n, 10);
|
|
831
966
|
if (!num) { console.error("Usage: draht-tools research-phase N"); process.exit(1); }
|
|
832
967
|
|
|
@@ -835,10 +970,28 @@ commands["research-phase"] = function (n) {
|
|
|
835
970
|
ensureDir(dir);
|
|
836
971
|
|
|
837
972
|
const resPath = path.join(dir, `${padNum(num)}-RESEARCH.md`);
|
|
838
|
-
|
|
839
|
-
|
|
973
|
+
|
|
974
|
+
// Check for stdin content (piped input)
|
|
975
|
+
let stdinContent = "";
|
|
976
|
+
if (!process.stdin.isTTY) {
|
|
977
|
+
stdinContent = await new Promise((resolve) => {
|
|
978
|
+
let data = "";
|
|
979
|
+
process.stdin.setEncoding("utf-8");
|
|
980
|
+
process.stdin.on("data", (chunk) => { data += chunk; });
|
|
981
|
+
process.stdin.on("end", () => { resolve(data.trim()); });
|
|
982
|
+
});
|
|
983
|
+
}
|
|
984
|
+
|
|
985
|
+
let content;
|
|
986
|
+
if (stdinContent) {
|
|
987
|
+
content = stdinContent;
|
|
988
|
+
} else {
|
|
989
|
+
content = `# Phase ${num} Research\n\nGenerated: ${timestamp()}\n\n## Best Practices\n[Fill in]\n\n## Patterns & Anti-Patterns\n[Fill in]\n\n## Library Recommendations\n[Fill in]\n\n## Edge Cases & Gotchas\n[Fill in]\n`;
|
|
990
|
+
}
|
|
991
|
+
|
|
992
|
+
writeMd(resPath, content);
|
|
840
993
|
console.log(`Created: ${resPath}`);
|
|
841
|
-
console.log("→ Fill in research findings, then plan the phase.");
|
|
994
|
+
if (!stdinContent) console.log("→ Fill in research findings, then plan the phase.");
|
|
842
995
|
};
|
|
843
996
|
|
|
844
997
|
// ============================================================================
|
|
@@ -902,11 +1055,13 @@ Version: 1.0.0
|
|
|
902
1055
|
// Dispatch
|
|
903
1056
|
const [cmd, ...args] = process.argv.slice(2);
|
|
904
1057
|
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
commands[cmd]
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
1058
|
+
(async () => {
|
|
1059
|
+
if (!cmd || cmd === "help" || cmd === "--help" || cmd === "-h") {
|
|
1060
|
+
commands.help();
|
|
1061
|
+
} else if (commands[cmd]) {
|
|
1062
|
+
await commands[cmd](...args);
|
|
1063
|
+
} else {
|
|
1064
|
+
console.error(`Unknown command: ${cmd}\nRun: draht-tools help`);
|
|
1065
|
+
process.exit(1);
|
|
1066
|
+
}
|
|
1067
|
+
})();
|
package/dist/config.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAYA;;;GAGG;AACH,eAAO,MAAM,WAAW,SACqF,CAAC;AAE9G,gEAAgE;AAChE,eAAO,MAAM,YAAY,SAAyB,CAAC;AAMnD,MAAM,MAAM,aAAa,GAAG,YAAY,GAAG,KAAK,GAAG,MAAM,GAAG,MAAM,GAAG,KAAK,GAAG,SAAS,CAAC;AAEvF,wBAAgB,mBAAmB,IAAI,aAAa,CAqBnD;AAED,wBAAgB,oBAAoB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAgBhE;AAMD;;;;;GAKG;AACH,wBAAgB,aAAa,IAAI,MAAM,CAuBtC;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,IAAI,MAAM,CAQrC;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,IAAI,MAAM,CAO7C;AAED,+BAA+B;AAC/B,wBAAgB,kBAAkB,IAAI,MAAM,CAE3C;AAED,4BAA4B;AAC5B,wBAAgB,aAAa,IAAI,MAAM,CAEtC;AAED,iCAAiC;AACjC,wBAAgB,WAAW,IAAI,MAAM,CAEpC;AAED,qCAAqC;AACrC,wBAAgB,eAAe,IAAI,MAAM,CAExC;AAED,+BAA+B;AAC/B,wBAAgB,gBAAgB,IAAI,MAAM,CAEzC;AAQD,eAAO,MAAM,QAAQ,EAAE,MAAyC,CAAC;AACjE,eAAO,MAAM,eAAe,EAAE,MAA+C,CAAC;AAC9E,eAAO,MAAM,sBAAsB,QAAQ,CAAC;AAC5C,eAAO,MAAM,OAAO,EAAE,MAAwE,CAAC;AAE/F;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAMvD;AAGD,eAAO,MAAM,aAAa,QAA+C,CAAC;AAI1E,6CAA6C;AAC7C,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAGxD;AAMD,6DAA6D;AAC7D,wBAAgB,WAAW,IAAI,MAAM,CASpC;AAED,iDAAiD;AACjD,wBAAgB,kBAAkB,IAAI,MAAM,CAE3C;AAED,8BAA8B;AAC9B,wBAAgB,aAAa,IAAI,MAAM,CAEtC;AAED,4BAA4B;AAC5B,wBAAgB,WAAW,IAAI,MAAM,CAEpC;AAED,gCAAgC;AAChC,wBAAgB,eAAe,IAAI,MAAM,CAExC;AAED,kCAAkC;AAClC,wBAAgB,WAAW,IAAI,MAAM,CAEpC;AAED,sDAAsD;AACtD,wBAAgB,SAAS,IAAI,MAAM,CAElC;AAED,6CAA6C;AAC7C,wBAAgB,aAAa,IAAI,MAAM,CAEtC;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,IAAI,MAAM,CAK7C;AAED;;GAEG;AACH,wBAAgB,kBAAkB,IAAI,MAAM,CAK3C;AAED,qCAAqC;AACrC,wBAAgB,cAAc,IAAI,MAAM,CAEvC;AAED,iCAAiC;AACjC,wBAAgB,eAAe,IAAI,MAAM,CAExC","sourcesContent":["import { existsSync, readFileSync } from \"fs\";\nimport { homedir } from \"os\";\nimport { dirname, join, resolve } from \"path\";\nimport { fileURLToPath } from \"url\";\n\n// =============================================================================\n// Package Detection\n// =============================================================================\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\n\n/**\n * Detect if we're running as a Bun compiled binary.\n * Bun binaries have import.meta.url containing \"$bunfs\", \"~BUN\", or \"%7EBUN\" (Bun's virtual filesystem path)\n */\nexport const isBunBinary =\n\timport.meta.url.includes(\"$bunfs\") || import.meta.url.includes(\"~BUN\") || import.meta.url.includes(\"%7EBUN\");\n\n/** Detect if Bun is the runtime (compiled binary or bun run) */\nexport const isBunRuntime = !!process.versions.bun;\n\n// =============================================================================\n// Install Method Detection\n// =============================================================================\n\nexport type InstallMethod = \"bun-binary\" | \"npm\" | \"pnpm\" | \"yarn\" | \"bun\" | \"unknown\";\n\nexport function detectInstallMethod(): InstallMethod {\n\tif (isBunBinary) {\n\t\treturn \"bun-binary\";\n\t}\n\n\tconst resolvedPath = `${__dirname}\\0${process.execPath || \"\"}`.toLowerCase();\n\n\tif (resolvedPath.includes(\"/pnpm/\") || resolvedPath.includes(\"/.pnpm/\") || resolvedPath.includes(\"\\\\pnpm\\\\\")) {\n\t\treturn \"pnpm\";\n\t}\n\tif (resolvedPath.includes(\"/yarn/\") || resolvedPath.includes(\"/.yarn/\") || resolvedPath.includes(\"\\\\yarn\\\\\")) {\n\t\treturn \"yarn\";\n\t}\n\tif (isBunRuntime) {\n\t\treturn \"bun\";\n\t}\n\tif (resolvedPath.includes(\"/npm/\") || resolvedPath.includes(\"/node_modules/\") || resolvedPath.includes(\"\\\\npm\\\\\")) {\n\t\treturn \"npm\";\n\t}\n\n\treturn \"unknown\";\n}\n\nexport function getUpdateInstruction(packageName: string): string {\n\tconst method = detectInstallMethod();\n\tswitch (method) {\n\t\tcase \"bun-binary\":\n\t\t\treturn `Download from: https://github.com/draht-dev/draht/releases/latest`;\n\t\tcase \"pnpm\":\n\t\t\treturn `Run: pnpm install -g ${packageName}`;\n\t\tcase \"yarn\":\n\t\t\treturn `Run: yarn global add ${packageName}`;\n\t\tcase \"bun\":\n\t\t\treturn `Run: bun install -g ${packageName}`;\n\t\tcase \"npm\":\n\t\t\treturn `Run: npm install -g ${packageName}`;\n\t\tdefault:\n\t\t\treturn `Run: npm install -g ${packageName}`;\n\t}\n}\n\n// =============================================================================\n// Package Asset Paths (shipped with executable)\n// =============================================================================\n\n/**\n * Get the base directory for resolving package assets (themes, package.json, README.md, CHANGELOG.md).\n * - For Bun binary: returns the directory containing the executable\n * - For Node.js (dist/): returns __dirname (the dist/ directory)\n * - For tsx (src/): returns parent directory (the package root)\n */\nexport function getPackageDir(): string {\n\t// Allow override via environment variable (useful for Nix/Guix where store paths tokenize poorly)\n\tconst envDir = process.env.DRAHT_PACKAGE_DIR;\n\tif (envDir) {\n\t\tif (envDir === \"~\") return homedir();\n\t\tif (envDir.startsWith(\"~/\")) return homedir() + envDir.slice(1);\n\t\treturn envDir;\n\t}\n\n\tif (isBunBinary) {\n\t\t// Bun binary: process.execPath points to the compiled executable\n\t\treturn dirname(process.execPath);\n\t}\n\t// Node.js: walk up from __dirname until we find package.json\n\tlet dir = __dirname;\n\twhile (dir !== dirname(dir)) {\n\t\tif (existsSync(join(dir, \"package.json\"))) {\n\t\t\treturn dir;\n\t\t}\n\t\tdir = dirname(dir);\n\t}\n\t// Fallback (shouldn't happen)\n\treturn __dirname;\n}\n\n/**\n * Get path to built-in themes directory (shipped with package)\n * - For Bun binary: theme/ next to executable\n * - For Node.js (dist/): dist/modes/interactive/theme/\n * - For tsx (src/): src/modes/interactive/theme/\n */\nexport function getThemesDir(): string {\n\tif (isBunBinary) {\n\t\treturn join(dirname(process.execPath), \"theme\");\n\t}\n\t// Theme is in modes/interactive/theme/ relative to src/ or dist/\n\tconst packageDir = getPackageDir();\n\tconst srcOrDist = existsSync(join(packageDir, \"src\")) ? \"src\" : \"dist\";\n\treturn join(packageDir, srcOrDist, \"modes\", \"interactive\", \"theme\");\n}\n\n/**\n * Get path to HTML export template directory (shipped with package)\n * - For Bun binary: export-html/ next to executable\n * - For Node.js (dist/): dist/core/export-html/\n * - For tsx (src/): src/core/export-html/\n */\nexport function getExportTemplateDir(): string {\n\tif (isBunBinary) {\n\t\treturn join(dirname(process.execPath), \"export-html\");\n\t}\n\tconst packageDir = getPackageDir();\n\tconst srcOrDist = existsSync(join(packageDir, \"src\")) ? \"src\" : \"dist\";\n\treturn join(packageDir, srcOrDist, \"core\", \"export-html\");\n}\n\n/** Get path to package.json */\nexport function getPackageJsonPath(): string {\n\treturn join(getPackageDir(), \"package.json\");\n}\n\n/** Get path to README.md */\nexport function getReadmePath(): string {\n\treturn resolve(join(getPackageDir(), \"README.md\"));\n}\n\n/** Get path to docs directory */\nexport function getDocsPath(): string {\n\treturn resolve(join(getPackageDir(), \"docs\"));\n}\n\n/** Get path to examples directory */\nexport function getExamplesPath(): string {\n\treturn resolve(join(getPackageDir(), \"examples\"));\n}\n\n/** Get path to CHANGELOG.md */\nexport function getChangelogPath(): string {\n\treturn resolve(join(getPackageDir(), \"CHANGELOG.md\"));\n}\n\n// =============================================================================\n// App Config (from package.json drahtConfig)\n// =============================================================================\n\nconst pkg = JSON.parse(readFileSync(getPackageJsonPath(), \"utf-8\"));\n\nexport const APP_NAME: string = pkg.drahtConfig?.name || \"draht\";\nexport const CONFIG_DIR_NAME: string = pkg.drahtConfig?.configDir || \".draht\";\nexport const LEGACY_CONFIG_DIR_NAME = \".pi\";\nexport const VERSION: string = existsSync(join(getPackageDir(), \".dev\")) ? \"dev\" : pkg.version;\n\n/**\n * Resolve the project config directory. Prefers `CONFIG_DIR_NAME` (`.draht`),\n * falls back to `LEGACY_CONFIG_DIR_NAME` (`.pi`) if the primary doesn't exist\n * but the legacy one does.\n */\nexport function getProjectConfigDir(cwd: string): string {\n\tconst primary = join(cwd, CONFIG_DIR_NAME);\n\tif (existsSync(primary)) return primary;\n\tconst legacy = join(cwd, LEGACY_CONFIG_DIR_NAME);\n\tif (existsSync(legacy)) return legacy;\n\treturn primary; // default to primary even if it doesn't exist yet\n}\n\n// e.g., DRAHT_CODING_AGENT_DIR or TAU_CODING_AGENT_DIR\nexport const ENV_AGENT_DIR = `${APP_NAME.toUpperCase()}_CODING_AGENT_DIR`;\n\nconst DEFAULT_SHARE_VIEWER_URL = \"https://draht.dev/session/\";\n\n/** Get the share viewer URL for a gist ID */\nexport function getShareViewerUrl(gistId: string): string {\n\tconst baseUrl = process.env.DRAHT_SHARE_VIEWER_URL || DEFAULT_SHARE_VIEWER_URL;\n\treturn `${baseUrl}#${gistId}`;\n}\n\n// =============================================================================\n// User Config Paths (~/.draht/agent/*)\n// =============================================================================\n\n/** Get the agent config directory (e.g., ~/.draht/agent/) */\nexport function getAgentDir(): string {\n\tconst envDir = process.env[ENV_AGENT_DIR];\n\tif (envDir) {\n\t\t// Expand tilde to home directory\n\t\tif (envDir === \"~\") return homedir();\n\t\tif (envDir.startsWith(\"~/\")) return homedir() + envDir.slice(1);\n\t\treturn envDir;\n\t}\n\treturn join(homedir(), CONFIG_DIR_NAME, \"agent\");\n}\n\n/** Get path to user's custom themes directory */\nexport function getCustomThemesDir(): string {\n\treturn join(getAgentDir(), \"themes\");\n}\n\n/** Get path to models.json */\nexport function getModelsPath(): string {\n\treturn join(getAgentDir(), \"models.json\");\n}\n\n/** Get path to auth.json */\nexport function getAuthPath(): string {\n\treturn join(getAgentDir(), \"auth.json\");\n}\n\n/** Get path to settings.json */\nexport function getSettingsPath(): string {\n\treturn join(getAgentDir(), \"settings.json\");\n}\n\n/** Get path to tools directory */\nexport function getToolsDir(): string {\n\treturn join(getAgentDir(), \"tools\");\n}\n\n/** Get path to managed binaries directory (fd, rg) */\nexport function getBinDir(): string {\n\treturn join(getAgentDir(), \"bin\");\n}\n\n/** Get path to prompt templates directory */\nexport function getPromptsDir(): string {\n\treturn join(getAgentDir(), \"prompts\");\n}\n\n/**\n * Get path to shipped prompt templates (bundled with the package).\n * - For Bun binary: prompts/ next to executable\n * - For Node.js: prompts/ at package root\n */\nexport function getShippedPromptsDir(): string {\n\tif (isBunBinary) {\n\t\treturn join(dirname(process.execPath), \"prompts\");\n\t}\n\treturn join(getPackageDir(), \"prompts\");\n}\n\n/**\n * Get path to shipped hooks (bundled with the package).\n */\nexport function getShippedHooksDir(): string {\n\tif (isBunBinary) {\n\t\treturn join(dirname(process.execPath), \"hooks\");\n\t}\n\treturn join(getPackageDir(), \"hooks\");\n}\n\n/** Get path to sessions directory */\nexport function getSessionsDir(): string {\n\treturn join(getAgentDir(), \"sessions\");\n}\n\n/** Get path to debug log file */\nexport function getDebugLogPath(): string {\n\treturn join(getAgentDir(), `${APP_NAME}-debug.log`);\n}\n"]}
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAYA;;;GAGG;AACH,eAAO,MAAM,WAAW,SACqF,CAAC;AAE9G,gEAAgE;AAChE,eAAO,MAAM,YAAY,SAAyB,CAAC;AAMnD,MAAM,MAAM,aAAa,GAAG,YAAY,GAAG,KAAK,GAAG,MAAM,GAAG,MAAM,GAAG,KAAK,GAAG,SAAS,CAAC;AAEvF,wBAAgB,mBAAmB,IAAI,aAAa,CAqBnD;AAED,wBAAgB,oBAAoB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAgBhE;AAMD;;;;;GAKG;AACH,wBAAgB,aAAa,IAAI,MAAM,CAuBtC;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,IAAI,MAAM,CAQrC;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,IAAI,MAAM,CAO7C;AAED,+BAA+B;AAC/B,wBAAgB,kBAAkB,IAAI,MAAM,CAE3C;AAED,4BAA4B;AAC5B,wBAAgB,aAAa,IAAI,MAAM,CAEtC;AAED,iCAAiC;AACjC,wBAAgB,WAAW,IAAI,MAAM,CAEpC;AAED,qCAAqC;AACrC,wBAAgB,eAAe,IAAI,MAAM,CAExC;AAED,+BAA+B;AAC/B,wBAAgB,gBAAgB,IAAI,MAAM,CAEzC;AAQD,eAAO,MAAM,QAAQ,EAAE,MAAyC,CAAC;AACjE,eAAO,MAAM,eAAe,EAAE,MAA+C,CAAC;AAC9E,eAAO,MAAM,sBAAsB,QAAQ,CAAC;AAC5C,eAAO,MAAM,OAAO,EAAE,MAAwE,CAAC;AAE/F;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAMvD;AAGD,eAAO,MAAM,aAAa,QAA+C,CAAC;AAI1E,6CAA6C;AAC7C,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAGxD;AAMD,6DAA6D;AAC7D,wBAAgB,WAAW,IAAI,MAAM,CASpC;AAED,iDAAiD;AACjD,wBAAgB,kBAAkB,IAAI,MAAM,CAE3C;AAED,8BAA8B;AAC9B,wBAAgB,aAAa,IAAI,MAAM,CAEtC;AAED,4BAA4B;AAC5B,wBAAgB,WAAW,IAAI,MAAM,CAEpC;AAED,gCAAgC;AAChC,wBAAgB,eAAe,IAAI,MAAM,CAExC;AAED,kCAAkC;AAClC,wBAAgB,WAAW,IAAI,MAAM,CAEpC;AAED,sDAAsD;AACtD,wBAAgB,SAAS,IAAI,MAAM,CAElC;AAED,6CAA6C;AAC7C,wBAAgB,aAAa,IAAI,MAAM,CAEtC;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,IAAI,MAAM,CAK7C;AAED;;GAEG;AACH,wBAAgB,kBAAkB,IAAI,MAAM,CAK3C;AAED,qCAAqC;AACrC,wBAAgB,cAAc,IAAI,MAAM,CAEvC;AAED,iCAAiC;AACjC,wBAAgB,eAAe,IAAI,MAAM,CAExC","sourcesContent":["import { existsSync, readFileSync } from \"fs\";\nimport { homedir } from \"os\";\nimport { dirname, join, resolve } from \"path\";\nimport { fileURLToPath } from \"url\";\n\n// =============================================================================\n// Package Detection\n// =============================================================================\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\n\n/**\n * Detect if we're running as a Bun compiled binary.\n * Bun binaries have import.meta.url containing \"$bunfs\", \"~BUN\", or \"%7EBUN\" (Bun's virtual filesystem path)\n */\nexport const isBunBinary =\n\timport.meta.url.includes(\"$bunfs\") || import.meta.url.includes(\"~BUN\") || import.meta.url.includes(\"%7EBUN\");\n\n/** Detect if Bun is the runtime (compiled binary or bun run) */\nexport const isBunRuntime = !!process.versions.bun;\n\n// =============================================================================\n// Install Method Detection\n// =============================================================================\n\nexport type InstallMethod = \"bun-binary\" | \"npm\" | \"pnpm\" | \"yarn\" | \"bun\" | \"unknown\";\n\nexport function detectInstallMethod(): InstallMethod {\n\tif (isBunBinary) {\n\t\treturn \"bun-binary\";\n\t}\n\n\tconst resolvedPath = `${__dirname}\\0${process.execPath || \"\"}`.toLowerCase();\n\n\tif (resolvedPath.includes(\"/pnpm/\") || resolvedPath.includes(\"/.pnpm/\") || resolvedPath.includes(\"\\\\pnpm\\\\\")) {\n\t\treturn \"pnpm\";\n\t}\n\tif (resolvedPath.includes(\"/yarn/\") || resolvedPath.includes(\"/.yarn/\") || resolvedPath.includes(\"\\\\yarn\\\\\")) {\n\t\treturn \"yarn\";\n\t}\n\tif (isBunRuntime) {\n\t\treturn \"bun\";\n\t}\n\tif (resolvedPath.includes(\"/npm/\") || resolvedPath.includes(\"/node_modules/\") || resolvedPath.includes(\"\\\\npm\\\\\")) {\n\t\treturn \"npm\";\n\t}\n\n\treturn \"unknown\";\n}\n\nexport function getUpdateInstruction(packageName: string): string {\n\tconst method = detectInstallMethod();\n\tswitch (method) {\n\t\tcase \"bun-binary\":\n\t\t\treturn `Download from: https://github.com/draht-dev/draht/releases/latest`;\n\t\tcase \"pnpm\":\n\t\t\treturn `Run: pnpm install -g ${packageName}`;\n\t\tcase \"yarn\":\n\t\t\treturn `Run: yarn global add ${packageName}`;\n\t\tcase \"bun\":\n\t\t\treturn `Run: bun add -g ${packageName}`;\n\t\tcase \"npm\":\n\t\t\treturn `Run: npm install -g ${packageName}`;\n\t\tdefault:\n\t\t\treturn `Run: bun add -g ${packageName}`;\n\t}\n}\n\n// =============================================================================\n// Package Asset Paths (shipped with executable)\n// =============================================================================\n\n/**\n * Get the base directory for resolving package assets (themes, package.json, README.md, CHANGELOG.md).\n * - For Bun binary: returns the directory containing the executable\n * - For Node.js (dist/): returns __dirname (the dist/ directory)\n * - For tsx (src/): returns parent directory (the package root)\n */\nexport function getPackageDir(): string {\n\t// Allow override via environment variable (useful for Nix/Guix where store paths tokenize poorly)\n\tconst envDir = process.env.DRAHT_PACKAGE_DIR;\n\tif (envDir) {\n\t\tif (envDir === \"~\") return homedir();\n\t\tif (envDir.startsWith(\"~/\")) return homedir() + envDir.slice(1);\n\t\treturn envDir;\n\t}\n\n\tif (isBunBinary) {\n\t\t// Bun binary: process.execPath points to the compiled executable\n\t\treturn dirname(process.execPath);\n\t}\n\t// Node.js: walk up from __dirname until we find package.json\n\tlet dir = __dirname;\n\twhile (dir !== dirname(dir)) {\n\t\tif (existsSync(join(dir, \"package.json\"))) {\n\t\t\treturn dir;\n\t\t}\n\t\tdir = dirname(dir);\n\t}\n\t// Fallback (shouldn't happen)\n\treturn __dirname;\n}\n\n/**\n * Get path to built-in themes directory (shipped with package)\n * - For Bun binary: theme/ next to executable\n * - For Node.js (dist/): dist/modes/interactive/theme/\n * - For tsx (src/): src/modes/interactive/theme/\n */\nexport function getThemesDir(): string {\n\tif (isBunBinary) {\n\t\treturn join(dirname(process.execPath), \"theme\");\n\t}\n\t// Theme is in modes/interactive/theme/ relative to src/ or dist/\n\tconst packageDir = getPackageDir();\n\tconst srcOrDist = existsSync(join(packageDir, \"src\")) ? \"src\" : \"dist\";\n\treturn join(packageDir, srcOrDist, \"modes\", \"interactive\", \"theme\");\n}\n\n/**\n * Get path to HTML export template directory (shipped with package)\n * - For Bun binary: export-html/ next to executable\n * - For Node.js (dist/): dist/core/export-html/\n * - For tsx (src/): src/core/export-html/\n */\nexport function getExportTemplateDir(): string {\n\tif (isBunBinary) {\n\t\treturn join(dirname(process.execPath), \"export-html\");\n\t}\n\tconst packageDir = getPackageDir();\n\tconst srcOrDist = existsSync(join(packageDir, \"src\")) ? \"src\" : \"dist\";\n\treturn join(packageDir, srcOrDist, \"core\", \"export-html\");\n}\n\n/** Get path to package.json */\nexport function getPackageJsonPath(): string {\n\treturn join(getPackageDir(), \"package.json\");\n}\n\n/** Get path to README.md */\nexport function getReadmePath(): string {\n\treturn resolve(join(getPackageDir(), \"README.md\"));\n}\n\n/** Get path to docs directory */\nexport function getDocsPath(): string {\n\treturn resolve(join(getPackageDir(), \"docs\"));\n}\n\n/** Get path to examples directory */\nexport function getExamplesPath(): string {\n\treturn resolve(join(getPackageDir(), \"examples\"));\n}\n\n/** Get path to CHANGELOG.md */\nexport function getChangelogPath(): string {\n\treturn resolve(join(getPackageDir(), \"CHANGELOG.md\"));\n}\n\n// =============================================================================\n// App Config (from package.json drahtConfig)\n// =============================================================================\n\nconst pkg = JSON.parse(readFileSync(getPackageJsonPath(), \"utf-8\"));\n\nexport const APP_NAME: string = pkg.drahtConfig?.name || \"draht\";\nexport const CONFIG_DIR_NAME: string = pkg.drahtConfig?.configDir || \".draht\";\nexport const LEGACY_CONFIG_DIR_NAME = \".pi\";\nexport const VERSION: string = existsSync(join(getPackageDir(), \".dev\")) ? \"dev\" : pkg.version;\n\n/**\n * Resolve the project config directory. Prefers `CONFIG_DIR_NAME` (`.draht`),\n * falls back to `LEGACY_CONFIG_DIR_NAME` (`.pi`) if the primary doesn't exist\n * but the legacy one does.\n */\nexport function getProjectConfigDir(cwd: string): string {\n\tconst primary = join(cwd, CONFIG_DIR_NAME);\n\tif (existsSync(primary)) return primary;\n\tconst legacy = join(cwd, LEGACY_CONFIG_DIR_NAME);\n\tif (existsSync(legacy)) return legacy;\n\treturn primary; // default to primary even if it doesn't exist yet\n}\n\n// e.g., DRAHT_CODING_AGENT_DIR or TAU_CODING_AGENT_DIR\nexport const ENV_AGENT_DIR = `${APP_NAME.toUpperCase()}_CODING_AGENT_DIR`;\n\nconst DEFAULT_SHARE_VIEWER_URL = \"https://draht.dev/session/\";\n\n/** Get the share viewer URL for a gist ID */\nexport function getShareViewerUrl(gistId: string): string {\n\tconst baseUrl = process.env.DRAHT_SHARE_VIEWER_URL || DEFAULT_SHARE_VIEWER_URL;\n\treturn `${baseUrl}#${gistId}`;\n}\n\n// =============================================================================\n// User Config Paths (~/.draht/agent/*)\n// =============================================================================\n\n/** Get the agent config directory (e.g., ~/.draht/agent/) */\nexport function getAgentDir(): string {\n\tconst envDir = process.env[ENV_AGENT_DIR];\n\tif (envDir) {\n\t\t// Expand tilde to home directory\n\t\tif (envDir === \"~\") return homedir();\n\t\tif (envDir.startsWith(\"~/\")) return homedir() + envDir.slice(1);\n\t\treturn envDir;\n\t}\n\treturn join(homedir(), CONFIG_DIR_NAME, \"agent\");\n}\n\n/** Get path to user's custom themes directory */\nexport function getCustomThemesDir(): string {\n\treturn join(getAgentDir(), \"themes\");\n}\n\n/** Get path to models.json */\nexport function getModelsPath(): string {\n\treturn join(getAgentDir(), \"models.json\");\n}\n\n/** Get path to auth.json */\nexport function getAuthPath(): string {\n\treturn join(getAgentDir(), \"auth.json\");\n}\n\n/** Get path to settings.json */\nexport function getSettingsPath(): string {\n\treturn join(getAgentDir(), \"settings.json\");\n}\n\n/** Get path to tools directory */\nexport function getToolsDir(): string {\n\treturn join(getAgentDir(), \"tools\");\n}\n\n/** Get path to managed binaries directory (fd, rg) */\nexport function getBinDir(): string {\n\treturn join(getAgentDir(), \"bin\");\n}\n\n/** Get path to prompt templates directory */\nexport function getPromptsDir(): string {\n\treturn join(getAgentDir(), \"prompts\");\n}\n\n/**\n * Get path to shipped prompt templates (bundled with the package).\n * - For Bun binary: prompts/ next to executable\n * - For Node.js: prompts/ at package root\n */\nexport function getShippedPromptsDir(): string {\n\tif (isBunBinary) {\n\t\treturn join(dirname(process.execPath), \"prompts\");\n\t}\n\treturn join(getPackageDir(), \"prompts\");\n}\n\n/**\n * Get path to shipped hooks (bundled with the package).\n */\nexport function getShippedHooksDir(): string {\n\tif (isBunBinary) {\n\t\treturn join(dirname(process.execPath), \"hooks\");\n\t}\n\treturn join(getPackageDir(), \"hooks\");\n}\n\n/** Get path to sessions directory */\nexport function getSessionsDir(): string {\n\treturn join(getAgentDir(), \"sessions\");\n}\n\n/** Get path to debug log file */\nexport function getDebugLogPath(): string {\n\treturn join(getAgentDir(), `${APP_NAME}-debug.log`);\n}\n"]}
|
package/dist/config.js
CHANGED
|
@@ -43,11 +43,11 @@ export function getUpdateInstruction(packageName) {
|
|
|
43
43
|
case "yarn":
|
|
44
44
|
return `Run: yarn global add ${packageName}`;
|
|
45
45
|
case "bun":
|
|
46
|
-
return `Run: bun
|
|
46
|
+
return `Run: bun add -g ${packageName}`;
|
|
47
47
|
case "npm":
|
|
48
48
|
return `Run: npm install -g ${packageName}`;
|
|
49
49
|
default:
|
|
50
|
-
return `Run:
|
|
50
|
+
return `Run: bun add -g ${packageName}`;
|
|
51
51
|
}
|
|
52
52
|
}
|
|
53
53
|
// =============================================================================
|
package/dist/config.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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","sourcesContent":["import { existsSync, readFileSync } from \"fs\";\nimport { homedir } from \"os\";\nimport { dirname, join, resolve } from \"path\";\nimport { fileURLToPath } from \"url\";\n\n// =============================================================================\n// Package Detection\n// =============================================================================\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\n\n/**\n * Detect if we're running as a Bun compiled binary.\n * Bun binaries have import.meta.url containing \"$bunfs\", \"~BUN\", or \"%7EBUN\" (Bun's virtual filesystem path)\n */\nexport const isBunBinary =\n\timport.meta.url.includes(\"$bunfs\") || import.meta.url.includes(\"~BUN\") || import.meta.url.includes(\"%7EBUN\");\n\n/** Detect if Bun is the runtime (compiled binary or bun run) */\nexport const isBunRuntime = !!process.versions.bun;\n\n// =============================================================================\n// Install Method Detection\n// =============================================================================\n\nexport type InstallMethod = \"bun-binary\" | \"npm\" | \"pnpm\" | \"yarn\" | \"bun\" | \"unknown\";\n\nexport function detectInstallMethod(): InstallMethod {\n\tif (isBunBinary) {\n\t\treturn \"bun-binary\";\n\t}\n\n\tconst resolvedPath = `${__dirname}\\0${process.execPath || \"\"}`.toLowerCase();\n\n\tif (resolvedPath.includes(\"/pnpm/\") || resolvedPath.includes(\"/.pnpm/\") || resolvedPath.includes(\"\\\\pnpm\\\\\")) {\n\t\treturn \"pnpm\";\n\t}\n\tif (resolvedPath.includes(\"/yarn/\") || resolvedPath.includes(\"/.yarn/\") || resolvedPath.includes(\"\\\\yarn\\\\\")) {\n\t\treturn \"yarn\";\n\t}\n\tif (isBunRuntime) {\n\t\treturn \"bun\";\n\t}\n\tif (resolvedPath.includes(\"/npm/\") || resolvedPath.includes(\"/node_modules/\") || resolvedPath.includes(\"\\\\npm\\\\\")) {\n\t\treturn \"npm\";\n\t}\n\n\treturn \"unknown\";\n}\n\nexport function getUpdateInstruction(packageName: string): string {\n\tconst method = detectInstallMethod();\n\tswitch (method) {\n\t\tcase \"bun-binary\":\n\t\t\treturn `Download from: https://github.com/draht-dev/draht/releases/latest`;\n\t\tcase \"pnpm\":\n\t\t\treturn `Run: pnpm install -g ${packageName}`;\n\t\tcase \"yarn\":\n\t\t\treturn `Run: yarn global add ${packageName}`;\n\t\tcase \"bun\":\n\t\t\treturn `Run: bun install -g ${packageName}`;\n\t\tcase \"npm\":\n\t\t\treturn `Run: npm install -g ${packageName}`;\n\t\tdefault:\n\t\t\treturn `Run: npm install -g ${packageName}`;\n\t}\n}\n\n// =============================================================================\n// Package Asset Paths (shipped with executable)\n// =============================================================================\n\n/**\n * Get the base directory for resolving package assets (themes, package.json, README.md, CHANGELOG.md).\n * - For Bun binary: returns the directory containing the executable\n * - For Node.js (dist/): returns __dirname (the dist/ directory)\n * - For tsx (src/): returns parent directory (the package root)\n */\nexport function getPackageDir(): string {\n\t// Allow override via environment variable (useful for Nix/Guix where store paths tokenize poorly)\n\tconst envDir = process.env.DRAHT_PACKAGE_DIR;\n\tif (envDir) {\n\t\tif (envDir === \"~\") return homedir();\n\t\tif (envDir.startsWith(\"~/\")) return homedir() + envDir.slice(1);\n\t\treturn envDir;\n\t}\n\n\tif (isBunBinary) {\n\t\t// Bun binary: process.execPath points to the compiled executable\n\t\treturn dirname(process.execPath);\n\t}\n\t// Node.js: walk up from __dirname until we find package.json\n\tlet dir = __dirname;\n\twhile (dir !== dirname(dir)) {\n\t\tif (existsSync(join(dir, \"package.json\"))) {\n\t\t\treturn dir;\n\t\t}\n\t\tdir = dirname(dir);\n\t}\n\t// Fallback (shouldn't happen)\n\treturn __dirname;\n}\n\n/**\n * Get path to built-in themes directory (shipped with package)\n * - For Bun binary: theme/ next to executable\n * - For Node.js (dist/): dist/modes/interactive/theme/\n * - For tsx (src/): src/modes/interactive/theme/\n */\nexport function getThemesDir(): string {\n\tif (isBunBinary) {\n\t\treturn join(dirname(process.execPath), \"theme\");\n\t}\n\t// Theme is in modes/interactive/theme/ relative to src/ or dist/\n\tconst packageDir = getPackageDir();\n\tconst srcOrDist = existsSync(join(packageDir, \"src\")) ? \"src\" : \"dist\";\n\treturn join(packageDir, srcOrDist, \"modes\", \"interactive\", \"theme\");\n}\n\n/**\n * Get path to HTML export template directory (shipped with package)\n * - For Bun binary: export-html/ next to executable\n * - For Node.js (dist/): dist/core/export-html/\n * - For tsx (src/): src/core/export-html/\n */\nexport function getExportTemplateDir(): string {\n\tif (isBunBinary) {\n\t\treturn join(dirname(process.execPath), \"export-html\");\n\t}\n\tconst packageDir = getPackageDir();\n\tconst srcOrDist = existsSync(join(packageDir, \"src\")) ? \"src\" : \"dist\";\n\treturn join(packageDir, srcOrDist, \"core\", \"export-html\");\n}\n\n/** Get path to package.json */\nexport function getPackageJsonPath(): string {\n\treturn join(getPackageDir(), \"package.json\");\n}\n\n/** Get path to README.md */\nexport function getReadmePath(): string {\n\treturn resolve(join(getPackageDir(), \"README.md\"));\n}\n\n/** Get path to docs directory */\nexport function getDocsPath(): string {\n\treturn resolve(join(getPackageDir(), \"docs\"));\n}\n\n/** Get path to examples directory */\nexport function getExamplesPath(): string {\n\treturn resolve(join(getPackageDir(), \"examples\"));\n}\n\n/** Get path to CHANGELOG.md */\nexport function getChangelogPath(): string {\n\treturn resolve(join(getPackageDir(), \"CHANGELOG.md\"));\n}\n\n// =============================================================================\n// App Config (from package.json drahtConfig)\n// =============================================================================\n\nconst pkg = JSON.parse(readFileSync(getPackageJsonPath(), \"utf-8\"));\n\nexport const APP_NAME: string = pkg.drahtConfig?.name || \"draht\";\nexport const CONFIG_DIR_NAME: string = pkg.drahtConfig?.configDir || \".draht\";\nexport const LEGACY_CONFIG_DIR_NAME = \".pi\";\nexport const VERSION: string = existsSync(join(getPackageDir(), \".dev\")) ? \"dev\" : pkg.version;\n\n/**\n * Resolve the project config directory. Prefers `CONFIG_DIR_NAME` (`.draht`),\n * falls back to `LEGACY_CONFIG_DIR_NAME` (`.pi`) if the primary doesn't exist\n * but the legacy one does.\n */\nexport function getProjectConfigDir(cwd: string): string {\n\tconst primary = join(cwd, CONFIG_DIR_NAME);\n\tif (existsSync(primary)) return primary;\n\tconst legacy = join(cwd, LEGACY_CONFIG_DIR_NAME);\n\tif (existsSync(legacy)) return legacy;\n\treturn primary; // default to primary even if it doesn't exist yet\n}\n\n// e.g., DRAHT_CODING_AGENT_DIR or TAU_CODING_AGENT_DIR\nexport const ENV_AGENT_DIR = `${APP_NAME.toUpperCase()}_CODING_AGENT_DIR`;\n\nconst DEFAULT_SHARE_VIEWER_URL = \"https://draht.dev/session/\";\n\n/** Get the share viewer URL for a gist ID */\nexport function getShareViewerUrl(gistId: string): string {\n\tconst baseUrl = process.env.DRAHT_SHARE_VIEWER_URL || DEFAULT_SHARE_VIEWER_URL;\n\treturn `${baseUrl}#${gistId}`;\n}\n\n// =============================================================================\n// User Config Paths (~/.draht/agent/*)\n// =============================================================================\n\n/** Get the agent config directory (e.g., ~/.draht/agent/) */\nexport function getAgentDir(): string {\n\tconst envDir = process.env[ENV_AGENT_DIR];\n\tif (envDir) {\n\t\t// Expand tilde to home directory\n\t\tif (envDir === \"~\") return homedir();\n\t\tif (envDir.startsWith(\"~/\")) return homedir() + envDir.slice(1);\n\t\treturn envDir;\n\t}\n\treturn join(homedir(), CONFIG_DIR_NAME, \"agent\");\n}\n\n/** Get path to user's custom themes directory */\nexport function getCustomThemesDir(): string {\n\treturn join(getAgentDir(), \"themes\");\n}\n\n/** Get path to models.json */\nexport function getModelsPath(): string {\n\treturn join(getAgentDir(), \"models.json\");\n}\n\n/** Get path to auth.json */\nexport function getAuthPath(): string {\n\treturn join(getAgentDir(), \"auth.json\");\n}\n\n/** Get path to settings.json */\nexport function getSettingsPath(): string {\n\treturn join(getAgentDir(), \"settings.json\");\n}\n\n/** Get path to tools directory */\nexport function getToolsDir(): string {\n\treturn join(getAgentDir(), \"tools\");\n}\n\n/** Get path to managed binaries directory (fd, rg) */\nexport function getBinDir(): string {\n\treturn join(getAgentDir(), \"bin\");\n}\n\n/** Get path to prompt templates directory */\nexport function getPromptsDir(): string {\n\treturn join(getAgentDir(), \"prompts\");\n}\n\n/**\n * Get path to shipped prompt templates (bundled with the package).\n * - For Bun binary: prompts/ next to executable\n * - For Node.js: prompts/ at package root\n */\nexport function getShippedPromptsDir(): string {\n\tif (isBunBinary) {\n\t\treturn join(dirname(process.execPath), \"prompts\");\n\t}\n\treturn join(getPackageDir(), \"prompts\");\n}\n\n/**\n * Get path to shipped hooks (bundled with the package).\n */\nexport function getShippedHooksDir(): string {\n\tif (isBunBinary) {\n\t\treturn join(dirname(process.execPath), \"hooks\");\n\t}\n\treturn join(getPackageDir(), \"hooks\");\n}\n\n/** Get path to sessions directory */\nexport function getSessionsDir(): string {\n\treturn join(getAgentDir(), \"sessions\");\n}\n\n/** Get path to debug log file */\nexport function getDebugLogPath(): string {\n\treturn join(getAgentDir(), `${APP_NAME}-debug.log`);\n}\n"]}
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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","sourcesContent":["import { existsSync, readFileSync } from \"fs\";\nimport { homedir } from \"os\";\nimport { dirname, join, resolve } from \"path\";\nimport { fileURLToPath } from \"url\";\n\n// =============================================================================\n// Package Detection\n// =============================================================================\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\n\n/**\n * Detect if we're running as a Bun compiled binary.\n * Bun binaries have import.meta.url containing \"$bunfs\", \"~BUN\", or \"%7EBUN\" (Bun's virtual filesystem path)\n */\nexport const isBunBinary =\n\timport.meta.url.includes(\"$bunfs\") || import.meta.url.includes(\"~BUN\") || import.meta.url.includes(\"%7EBUN\");\n\n/** Detect if Bun is the runtime (compiled binary or bun run) */\nexport const isBunRuntime = !!process.versions.bun;\n\n// =============================================================================\n// Install Method Detection\n// =============================================================================\n\nexport type InstallMethod = \"bun-binary\" | \"npm\" | \"pnpm\" | \"yarn\" | \"bun\" | \"unknown\";\n\nexport function detectInstallMethod(): InstallMethod {\n\tif (isBunBinary) {\n\t\treturn \"bun-binary\";\n\t}\n\n\tconst resolvedPath = `${__dirname}\\0${process.execPath || \"\"}`.toLowerCase();\n\n\tif (resolvedPath.includes(\"/pnpm/\") || resolvedPath.includes(\"/.pnpm/\") || resolvedPath.includes(\"\\\\pnpm\\\\\")) {\n\t\treturn \"pnpm\";\n\t}\n\tif (resolvedPath.includes(\"/yarn/\") || resolvedPath.includes(\"/.yarn/\") || resolvedPath.includes(\"\\\\yarn\\\\\")) {\n\t\treturn \"yarn\";\n\t}\n\tif (isBunRuntime) {\n\t\treturn \"bun\";\n\t}\n\tif (resolvedPath.includes(\"/npm/\") || resolvedPath.includes(\"/node_modules/\") || resolvedPath.includes(\"\\\\npm\\\\\")) {\n\t\treturn \"npm\";\n\t}\n\n\treturn \"unknown\";\n}\n\nexport function getUpdateInstruction(packageName: string): string {\n\tconst method = detectInstallMethod();\n\tswitch (method) {\n\t\tcase \"bun-binary\":\n\t\t\treturn `Download from: https://github.com/draht-dev/draht/releases/latest`;\n\t\tcase \"pnpm\":\n\t\t\treturn `Run: pnpm install -g ${packageName}`;\n\t\tcase \"yarn\":\n\t\t\treturn `Run: yarn global add ${packageName}`;\n\t\tcase \"bun\":\n\t\t\treturn `Run: bun add -g ${packageName}`;\n\t\tcase \"npm\":\n\t\t\treturn `Run: npm install -g ${packageName}`;\n\t\tdefault:\n\t\t\treturn `Run: bun add -g ${packageName}`;\n\t}\n}\n\n// =============================================================================\n// Package Asset Paths (shipped with executable)\n// =============================================================================\n\n/**\n * Get the base directory for resolving package assets (themes, package.json, README.md, CHANGELOG.md).\n * - For Bun binary: returns the directory containing the executable\n * - For Node.js (dist/): returns __dirname (the dist/ directory)\n * - For tsx (src/): returns parent directory (the package root)\n */\nexport function getPackageDir(): string {\n\t// Allow override via environment variable (useful for Nix/Guix where store paths tokenize poorly)\n\tconst envDir = process.env.DRAHT_PACKAGE_DIR;\n\tif (envDir) {\n\t\tif (envDir === \"~\") return homedir();\n\t\tif (envDir.startsWith(\"~/\")) return homedir() + envDir.slice(1);\n\t\treturn envDir;\n\t}\n\n\tif (isBunBinary) {\n\t\t// Bun binary: process.execPath points to the compiled executable\n\t\treturn dirname(process.execPath);\n\t}\n\t// Node.js: walk up from __dirname until we find package.json\n\tlet dir = __dirname;\n\twhile (dir !== dirname(dir)) {\n\t\tif (existsSync(join(dir, \"package.json\"))) {\n\t\t\treturn dir;\n\t\t}\n\t\tdir = dirname(dir);\n\t}\n\t// Fallback (shouldn't happen)\n\treturn __dirname;\n}\n\n/**\n * Get path to built-in themes directory (shipped with package)\n * - For Bun binary: theme/ next to executable\n * - For Node.js (dist/): dist/modes/interactive/theme/\n * - For tsx (src/): src/modes/interactive/theme/\n */\nexport function getThemesDir(): string {\n\tif (isBunBinary) {\n\t\treturn join(dirname(process.execPath), \"theme\");\n\t}\n\t// Theme is in modes/interactive/theme/ relative to src/ or dist/\n\tconst packageDir = getPackageDir();\n\tconst srcOrDist = existsSync(join(packageDir, \"src\")) ? \"src\" : \"dist\";\n\treturn join(packageDir, srcOrDist, \"modes\", \"interactive\", \"theme\");\n}\n\n/**\n * Get path to HTML export template directory (shipped with package)\n * - For Bun binary: export-html/ next to executable\n * - For Node.js (dist/): dist/core/export-html/\n * - For tsx (src/): src/core/export-html/\n */\nexport function getExportTemplateDir(): string {\n\tif (isBunBinary) {\n\t\treturn join(dirname(process.execPath), \"export-html\");\n\t}\n\tconst packageDir = getPackageDir();\n\tconst srcOrDist = existsSync(join(packageDir, \"src\")) ? \"src\" : \"dist\";\n\treturn join(packageDir, srcOrDist, \"core\", \"export-html\");\n}\n\n/** Get path to package.json */\nexport function getPackageJsonPath(): string {\n\treturn join(getPackageDir(), \"package.json\");\n}\n\n/** Get path to README.md */\nexport function getReadmePath(): string {\n\treturn resolve(join(getPackageDir(), \"README.md\"));\n}\n\n/** Get path to docs directory */\nexport function getDocsPath(): string {\n\treturn resolve(join(getPackageDir(), \"docs\"));\n}\n\n/** Get path to examples directory */\nexport function getExamplesPath(): string {\n\treturn resolve(join(getPackageDir(), \"examples\"));\n}\n\n/** Get path to CHANGELOG.md */\nexport function getChangelogPath(): string {\n\treturn resolve(join(getPackageDir(), \"CHANGELOG.md\"));\n}\n\n// =============================================================================\n// App Config (from package.json drahtConfig)\n// =============================================================================\n\nconst pkg = JSON.parse(readFileSync(getPackageJsonPath(), \"utf-8\"));\n\nexport const APP_NAME: string = pkg.drahtConfig?.name || \"draht\";\nexport const CONFIG_DIR_NAME: string = pkg.drahtConfig?.configDir || \".draht\";\nexport const LEGACY_CONFIG_DIR_NAME = \".pi\";\nexport const VERSION: string = existsSync(join(getPackageDir(), \".dev\")) ? \"dev\" : pkg.version;\n\n/**\n * Resolve the project config directory. Prefers `CONFIG_DIR_NAME` (`.draht`),\n * falls back to `LEGACY_CONFIG_DIR_NAME` (`.pi`) if the primary doesn't exist\n * but the legacy one does.\n */\nexport function getProjectConfigDir(cwd: string): string {\n\tconst primary = join(cwd, CONFIG_DIR_NAME);\n\tif (existsSync(primary)) return primary;\n\tconst legacy = join(cwd, LEGACY_CONFIG_DIR_NAME);\n\tif (existsSync(legacy)) return legacy;\n\treturn primary; // default to primary even if it doesn't exist yet\n}\n\n// e.g., DRAHT_CODING_AGENT_DIR or TAU_CODING_AGENT_DIR\nexport const ENV_AGENT_DIR = `${APP_NAME.toUpperCase()}_CODING_AGENT_DIR`;\n\nconst DEFAULT_SHARE_VIEWER_URL = \"https://draht.dev/session/\";\n\n/** Get the share viewer URL for a gist ID */\nexport function getShareViewerUrl(gistId: string): string {\n\tconst baseUrl = process.env.DRAHT_SHARE_VIEWER_URL || DEFAULT_SHARE_VIEWER_URL;\n\treturn `${baseUrl}#${gistId}`;\n}\n\n// =============================================================================\n// User Config Paths (~/.draht/agent/*)\n// =============================================================================\n\n/** Get the agent config directory (e.g., ~/.draht/agent/) */\nexport function getAgentDir(): string {\n\tconst envDir = process.env[ENV_AGENT_DIR];\n\tif (envDir) {\n\t\t// Expand tilde to home directory\n\t\tif (envDir === \"~\") return homedir();\n\t\tif (envDir.startsWith(\"~/\")) return homedir() + envDir.slice(1);\n\t\treturn envDir;\n\t}\n\treturn join(homedir(), CONFIG_DIR_NAME, \"agent\");\n}\n\n/** Get path to user's custom themes directory */\nexport function getCustomThemesDir(): string {\n\treturn join(getAgentDir(), \"themes\");\n}\n\n/** Get path to models.json */\nexport function getModelsPath(): string {\n\treturn join(getAgentDir(), \"models.json\");\n}\n\n/** Get path to auth.json */\nexport function getAuthPath(): string {\n\treturn join(getAgentDir(), \"auth.json\");\n}\n\n/** Get path to settings.json */\nexport function getSettingsPath(): string {\n\treturn join(getAgentDir(), \"settings.json\");\n}\n\n/** Get path to tools directory */\nexport function getToolsDir(): string {\n\treturn join(getAgentDir(), \"tools\");\n}\n\n/** Get path to managed binaries directory (fd, rg) */\nexport function getBinDir(): string {\n\treturn join(getAgentDir(), \"bin\");\n}\n\n/** Get path to prompt templates directory */\nexport function getPromptsDir(): string {\n\treturn join(getAgentDir(), \"prompts\");\n}\n\n/**\n * Get path to shipped prompt templates (bundled with the package).\n * - For Bun binary: prompts/ next to executable\n * - For Node.js: prompts/ at package root\n */\nexport function getShippedPromptsDir(): string {\n\tif (isBunBinary) {\n\t\treturn join(dirname(process.execPath), \"prompts\");\n\t}\n\treturn join(getPackageDir(), \"prompts\");\n}\n\n/**\n * Get path to shipped hooks (bundled with the package).\n */\nexport function getShippedHooksDir(): string {\n\tif (isBunBinary) {\n\t\treturn join(dirname(process.execPath), \"hooks\");\n\t}\n\treturn join(getPackageDir(), \"hooks\");\n}\n\n/** Get path to sessions directory */\nexport function getSessionsDir(): string {\n\treturn join(getAgentDir(), \"sessions\");\n}\n\n/** Get path to debug log file */\nexport function getDebugLogPath(): string {\n\treturn join(getAgentDir(), `${APP_NAME}-debug.log`);\n}\n"]}
|