@devness/useai-cli 0.3.4 → 0.3.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +101 -21
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -395,7 +395,7 @@ import chalk6 from "chalk";
|
|
|
395
395
|
|
|
396
396
|
// src/services/tools.ts
|
|
397
397
|
import { execSync } from "child_process";
|
|
398
|
-
import { existsSync as existsSync4, readFileSync as readFileSync2, writeFileSync as writeFileSync2, mkdirSync as mkdirSync2 } from "fs";
|
|
398
|
+
import { existsSync as existsSync4, readFileSync as readFileSync2, writeFileSync as writeFileSync2, mkdirSync as mkdirSync2, unlinkSync } from "fs";
|
|
399
399
|
import { dirname, join as join2 } from "path";
|
|
400
400
|
import { homedir as homedir2 } from "os";
|
|
401
401
|
import { parse as parseToml, stringify as stringifyToml } from "smol-toml";
|
|
@@ -589,6 +589,65 @@ function removeYaml(configPath) {
|
|
|
589
589
|
writeYamlFile(configPath, config);
|
|
590
590
|
}
|
|
591
591
|
}
|
|
592
|
+
var INSTRUCTIONS_START = "<!-- useai:start -->";
|
|
593
|
+
var INSTRUCTIONS_END = "<!-- useai:end -->";
|
|
594
|
+
var USEAI_INSTRUCTIONS = [
|
|
595
|
+
"## UseAI Session Tracking",
|
|
596
|
+
"- At the START of every conversation, call `useai_session_start` with the appropriate task_type.",
|
|
597
|
+
"- For LONG sessions (15+ min), call `useai_heartbeat` periodically.",
|
|
598
|
+
"- At the END of every conversation, call `useai_session_end` with languages used, files_touched_count, and milestones (generic descriptions only \u2014 no project names, file paths, or company names)."
|
|
599
|
+
].join("\n");
|
|
600
|
+
var USEAI_INSTRUCTIONS_BLOCK = `${INSTRUCTIONS_START}
|
|
601
|
+
${USEAI_INSTRUCTIONS}
|
|
602
|
+
${INSTRUCTIONS_END}`;
|
|
603
|
+
function hasInstructionsBlock(filePath) {
|
|
604
|
+
if (!existsSync4(filePath)) return false;
|
|
605
|
+
try {
|
|
606
|
+
return readFileSync2(filePath, "utf-8").includes(INSTRUCTIONS_START);
|
|
607
|
+
} catch {
|
|
608
|
+
return false;
|
|
609
|
+
}
|
|
610
|
+
}
|
|
611
|
+
function injectInstructions(config) {
|
|
612
|
+
mkdirSync2(dirname(config.path), { recursive: true });
|
|
613
|
+
if (config.method === "create") {
|
|
614
|
+
writeFileSync2(config.path, USEAI_INSTRUCTIONS + "\n");
|
|
615
|
+
return;
|
|
616
|
+
}
|
|
617
|
+
if (hasInstructionsBlock(config.path)) return;
|
|
618
|
+
let existing = "";
|
|
619
|
+
if (existsSync4(config.path)) {
|
|
620
|
+
existing = readFileSync2(config.path, "utf-8");
|
|
621
|
+
}
|
|
622
|
+
const separator = existing && !existing.endsWith("\n") ? "\n\n" : existing ? "\n" : "";
|
|
623
|
+
writeFileSync2(config.path, existing + separator + USEAI_INSTRUCTIONS_BLOCK + "\n");
|
|
624
|
+
}
|
|
625
|
+
function removeInstructions(config) {
|
|
626
|
+
if (config.method === "create") {
|
|
627
|
+
if (existsSync4(config.path)) {
|
|
628
|
+
try {
|
|
629
|
+
unlinkSync(config.path);
|
|
630
|
+
} catch {
|
|
631
|
+
}
|
|
632
|
+
}
|
|
633
|
+
return;
|
|
634
|
+
}
|
|
635
|
+
if (!existsSync4(config.path)) return;
|
|
636
|
+
try {
|
|
637
|
+
const content = readFileSync2(config.path, "utf-8");
|
|
638
|
+
const escaped = (s) => s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
639
|
+
const regex = new RegExp(
|
|
640
|
+
`\\n?${escaped(INSTRUCTIONS_START)}[\\s\\S]*?${escaped(INSTRUCTIONS_END)}\\n?`
|
|
641
|
+
);
|
|
642
|
+
const cleaned = content.replace(regex, "").trim();
|
|
643
|
+
if (cleaned) {
|
|
644
|
+
writeFileSync2(config.path, cleaned + "\n");
|
|
645
|
+
} else {
|
|
646
|
+
unlinkSync(config.path);
|
|
647
|
+
}
|
|
648
|
+
} catch {
|
|
649
|
+
}
|
|
650
|
+
}
|
|
592
651
|
var formatHandlers = {
|
|
593
652
|
standard: { isConfigured: isConfiguredStandard, install: installStandard, remove: removeStandard },
|
|
594
653
|
vscode: { isConfigured: isConfiguredVscode, install: installVscode, remove: removeVscode },
|
|
@@ -605,8 +664,14 @@ function createTool(def) {
|
|
|
605
664
|
getConfigPath: () => def.configPath,
|
|
606
665
|
detect: def.detect,
|
|
607
666
|
isConfigured: () => handler.isConfigured(def.configPath),
|
|
608
|
-
install: () =>
|
|
609
|
-
|
|
667
|
+
install: () => {
|
|
668
|
+
handler.install(def.configPath);
|
|
669
|
+
if (def.instructions) injectInstructions(def.instructions);
|
|
670
|
+
},
|
|
671
|
+
remove: () => {
|
|
672
|
+
handler.remove(def.configPath);
|
|
673
|
+
if (def.instructions) removeInstructions(def.instructions);
|
|
674
|
+
}
|
|
610
675
|
};
|
|
611
676
|
}
|
|
612
677
|
var appSupport = join2(home, "Library", "Application Support");
|
|
@@ -637,7 +702,8 @@ var AI_TOOLS = [
|
|
|
637
702
|
name: "Claude Code",
|
|
638
703
|
configFormat: "standard",
|
|
639
704
|
configPath: join2(home, ".claude.json"),
|
|
640
|
-
detect: () => hasBinary("claude") || existsSync4(join2(home, ".claude.json"))
|
|
705
|
+
detect: () => hasBinary("claude") || existsSync4(join2(home, ".claude.json")),
|
|
706
|
+
instructions: { method: "append", path: join2(home, ".claude", "CLAUDE.md") }
|
|
641
707
|
}),
|
|
642
708
|
createTool({
|
|
643
709
|
id: "claude-desktop",
|
|
@@ -658,28 +724,32 @@ var AI_TOOLS = [
|
|
|
658
724
|
name: "Windsurf",
|
|
659
725
|
configFormat: "standard",
|
|
660
726
|
configPath: join2(home, ".codeium", "windsurf", "mcp_config.json"),
|
|
661
|
-
detect: () => existsSync4(join2(home, ".codeium", "windsurf"))
|
|
727
|
+
detect: () => existsSync4(join2(home, ".codeium", "windsurf")),
|
|
728
|
+
instructions: { method: "append", path: join2(home, ".codeium", "windsurf", "memories", "global_rules.md") }
|
|
662
729
|
}),
|
|
663
730
|
createTool({
|
|
664
731
|
id: "vscode",
|
|
665
732
|
name: "VS Code",
|
|
666
733
|
configFormat: "vscode",
|
|
667
734
|
configPath: join2(appSupport, "Code", "User", "mcp.json"),
|
|
668
|
-
detect: () => existsSync4(join2(appSupport, "Code"))
|
|
735
|
+
detect: () => existsSync4(join2(appSupport, "Code")),
|
|
736
|
+
instructions: { method: "create", path: join2(appSupport, "Code", "User", "prompts", "useai.instructions.md") }
|
|
669
737
|
}),
|
|
670
738
|
createTool({
|
|
671
739
|
id: "vscode-insiders",
|
|
672
740
|
name: "VS Code Insiders",
|
|
673
741
|
configFormat: "vscode",
|
|
674
742
|
configPath: join2(appSupport, "Code - Insiders", "User", "mcp.json"),
|
|
675
|
-
detect: () => existsSync4(join2(appSupport, "Code - Insiders"))
|
|
743
|
+
detect: () => existsSync4(join2(appSupport, "Code - Insiders")),
|
|
744
|
+
instructions: { method: "create", path: join2(appSupport, "Code - Insiders", "User", "prompts", "useai.instructions.md") }
|
|
676
745
|
}),
|
|
677
746
|
createTool({
|
|
678
747
|
id: "gemini-cli",
|
|
679
748
|
name: "Gemini CLI",
|
|
680
749
|
configFormat: "standard",
|
|
681
750
|
configPath: join2(home, ".gemini", "settings.json"),
|
|
682
|
-
detect: () => hasBinary("gemini")
|
|
751
|
+
detect: () => hasBinary("gemini"),
|
|
752
|
+
instructions: { method: "append", path: join2(home, ".gemini", "GEMINI.md") }
|
|
683
753
|
}),
|
|
684
754
|
createTool({
|
|
685
755
|
id: "zed",
|
|
@@ -703,7 +773,8 @@ var AI_TOOLS = [
|
|
|
703
773
|
),
|
|
704
774
|
detect: () => existsSync4(
|
|
705
775
|
join2(appSupport, "Code", "User", "globalStorage", "saoudrizwan.claude-dev")
|
|
706
|
-
)
|
|
776
|
+
),
|
|
777
|
+
instructions: { method: "create", path: join2(home, "Documents", "Cline", "Rules", "useai.md") }
|
|
707
778
|
}),
|
|
708
779
|
createTool({
|
|
709
780
|
id: "roo-code",
|
|
@@ -720,7 +791,8 @@ var AI_TOOLS = [
|
|
|
720
791
|
),
|
|
721
792
|
detect: () => existsSync4(
|
|
722
793
|
join2(appSupport, "Code", "User", "globalStorage", "rooveterinaryinc.roo-cline")
|
|
723
|
-
)
|
|
794
|
+
),
|
|
795
|
+
instructions: { method: "create", path: join2(home, ".roo", "rules", "useai.md") }
|
|
724
796
|
}),
|
|
725
797
|
createTool({
|
|
726
798
|
id: "amazon-q-cli",
|
|
@@ -741,21 +813,24 @@ var AI_TOOLS = [
|
|
|
741
813
|
name: "Codex",
|
|
742
814
|
configFormat: "toml",
|
|
743
815
|
configPath: join2(home, ".codex", "config.toml"),
|
|
744
|
-
detect: () => hasBinary("codex") || existsSync4(join2(home, ".codex")) || existsSync4("/Applications/Codex.app")
|
|
816
|
+
detect: () => hasBinary("codex") || existsSync4(join2(home, ".codex")) || existsSync4("/Applications/Codex.app"),
|
|
817
|
+
instructions: { method: "append", path: join2(home, ".codex", "AGENTS.md") }
|
|
745
818
|
}),
|
|
746
819
|
createTool({
|
|
747
820
|
id: "goose",
|
|
748
821
|
name: "Goose",
|
|
749
822
|
configFormat: "yaml",
|
|
750
823
|
configPath: join2(home, ".config", "goose", "config.yaml"),
|
|
751
|
-
detect: () => existsSync4(join2(home, ".config", "goose"))
|
|
824
|
+
detect: () => existsSync4(join2(home, ".config", "goose")),
|
|
825
|
+
instructions: { method: "append", path: join2(home, ".config", "goose", ".goosehints") }
|
|
752
826
|
}),
|
|
753
827
|
createTool({
|
|
754
828
|
id: "opencode",
|
|
755
829
|
name: "OpenCode",
|
|
756
830
|
configFormat: "standard",
|
|
757
831
|
configPath: join2(home, ".config", "opencode", "opencode.json"),
|
|
758
|
-
detect: () => hasBinary("opencode") || existsSync4(join2(home, ".config", "opencode"))
|
|
832
|
+
detect: () => hasBinary("opencode") || existsSync4(join2(home, ".config", "opencode")),
|
|
833
|
+
instructions: { method: "append", path: join2(home, ".config", "opencode", "AGENTS.md") }
|
|
759
834
|
}),
|
|
760
835
|
createTool({
|
|
761
836
|
id: "junie",
|
|
@@ -796,17 +871,16 @@ function showStatus(tools) {
|
|
|
796
871
|
}
|
|
797
872
|
async function installFlow(tools, autoYes, explicit) {
|
|
798
873
|
if (explicit) {
|
|
799
|
-
const toInstall2 = tools.filter((t) => !t.isConfigured());
|
|
800
|
-
const alreadyDone = tools.filter((t) => t.isConfigured());
|
|
801
|
-
for (const tool of alreadyDone) {
|
|
802
|
-
console.log(info(`${tool.name} is already configured.`));
|
|
803
|
-
}
|
|
804
|
-
if (toInstall2.length === 0) return;
|
|
805
874
|
console.log();
|
|
806
|
-
for (const tool of
|
|
875
|
+
for (const tool of tools) {
|
|
807
876
|
try {
|
|
877
|
+
const wasConfigured = tool.isConfigured();
|
|
808
878
|
tool.install();
|
|
809
|
-
|
|
879
|
+
if (wasConfigured) {
|
|
880
|
+
console.log(success(`\u2713 ${tool.name.padEnd(18)} ${chalk6.dim("(updated)")}`));
|
|
881
|
+
} else {
|
|
882
|
+
console.log(success(`\u2713 ${tool.name.padEnd(18)} \u2192 ${chalk6.dim(shortenPath(tool.getConfigPath()))}`));
|
|
883
|
+
}
|
|
810
884
|
} catch (err) {
|
|
811
885
|
console.log(error(`\u2717 ${tool.name.padEnd(18)} \u2014 ${err.message}`));
|
|
812
886
|
}
|
|
@@ -870,6 +944,12 @@ async function installFlow(tools, autoYes, explicit) {
|
|
|
870
944
|
console.log(error(`\u2717 ${tool.name.padEnd(18)} \u2014 ${err.message}`));
|
|
871
945
|
}
|
|
872
946
|
}
|
|
947
|
+
for (const tool of alreadyConfigured) {
|
|
948
|
+
try {
|
|
949
|
+
tool.install();
|
|
950
|
+
} catch {
|
|
951
|
+
}
|
|
952
|
+
}
|
|
873
953
|
console.log(`
|
|
874
954
|
Done! UseAI MCP server configured in ${chalk6.bold(String(toInstall.length))} tool${toInstall.length === 1 ? "" : "s"}.
|
|
875
955
|
`);
|