@ridit/milo 0.1.0
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/.cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc +111 -0
- package/LICENSE +21 -0
- package/README.md +122 -0
- package/dist/index.mjs +106603 -0
- package/package.json +64 -0
- package/src/commands/clear.ts +18 -0
- package/src/commands/crimes.ts +48 -0
- package/src/commands/feed.ts +20 -0
- package/src/commands/genz.ts +33 -0
- package/src/commands/help.ts +25 -0
- package/src/commands/init.ts +65 -0
- package/src/commands/mode.ts +22 -0
- package/src/commands/pet.ts +35 -0
- package/src/commands/provider.ts +46 -0
- package/src/commands/roast.ts +40 -0
- package/src/commands/vibe.ts +42 -0
- package/src/commands.ts +43 -0
- package/src/components/AsciiLogo.tsx +25 -0
- package/src/components/CommandSuggestions.tsx +78 -0
- package/src/components/Header.tsx +68 -0
- package/src/components/HighlightedCode.tsx +23 -0
- package/src/components/Message.tsx +43 -0
- package/src/components/ProviderWizard.tsx +278 -0
- package/src/components/Spinner.tsx +76 -0
- package/src/components/StatusBar.tsx +85 -0
- package/src/components/StructuredDiff.tsx +194 -0
- package/src/components/TextInput.tsx +144 -0
- package/src/components/messages/AssistantMessage.tsx +68 -0
- package/src/components/messages/ToolCallMessage.tsx +77 -0
- package/src/components/messages/ToolResultMessage.tsx +181 -0
- package/src/components/messages/UserMessage.tsx +32 -0
- package/src/components/permissions/PermissionCard.tsx +152 -0
- package/src/history.ts +27 -0
- package/src/hooks/useArrowKeyHistory.ts +0 -0
- package/src/hooks/useChat.ts +271 -0
- package/src/hooks/useDoublePress.ts +35 -0
- package/src/hooks/useTerminalSize.ts +24 -0
- package/src/hooks/useTextInput.ts +263 -0
- package/src/icons.ts +31 -0
- package/src/index.tsx +5 -0
- package/src/multi-agent/agent/agent.ts +33 -0
- package/src/multi-agent/orchestrator/orchestrator.ts +103 -0
- package/src/multi-agent/schemas.ts +12 -0
- package/src/multi-agent/types.ts +8 -0
- package/src/permissions.ts +54 -0
- package/src/pet.ts +239 -0
- package/src/screens/REPL.tsx +261 -0
- package/src/shortcuts.ts +37 -0
- package/src/skills/backend.ts +76 -0
- package/src/skills/cicd.ts +57 -0
- package/src/skills/colors.ts +72 -0
- package/src/skills/database.ts +55 -0
- package/src/skills/docker.ts +74 -0
- package/src/skills/frontend.ts +70 -0
- package/src/skills/git.ts +52 -0
- package/src/skills/testing.ts +73 -0
- package/src/skills/typography.ts +57 -0
- package/src/skills/uiux.ts +43 -0
- package/src/tools/AgentTool/prompt.ts +17 -0
- package/src/tools/AgentTool/tool.ts +22 -0
- package/src/tools/BashTool/prompt.ts +82 -0
- package/src/tools/BashTool/tool.ts +54 -0
- package/src/tools/FileEditTool/prompt.ts +13 -0
- package/src/tools/FileEditTool/tool.ts +39 -0
- package/src/tools/FileReadTool/prompt.ts +5 -0
- package/src/tools/FileReadTool/tool.ts +34 -0
- package/src/tools/FileWriteTool/prompt.ts +19 -0
- package/src/tools/FileWriteTool/tool.ts +34 -0
- package/src/tools/GlobTool/prompt.ts +11 -0
- package/src/tools/GlobTool/tool.ts +34 -0
- package/src/tools/GrepTool/prompt.ts +13 -0
- package/src/tools/GrepTool/tool.ts +41 -0
- package/src/tools/MemoryEditTool/prompt.ts +10 -0
- package/src/tools/MemoryEditTool/tool.ts +38 -0
- package/src/tools/MemoryReadTool/prompt.ts +9 -0
- package/src/tools/MemoryReadTool/tool.ts +47 -0
- package/src/tools/MemoryWriteTool/prompt.ts +10 -0
- package/src/tools/MemoryWriteTool/tool.ts +30 -0
- package/src/tools/OrchestratorTool/prompt.ts +26 -0
- package/src/tools/OrchestratorTool/tool.ts +20 -0
- package/src/tools/RecallTool/prompt.ts +13 -0
- package/src/tools/RecallTool/tool.ts +47 -0
- package/src/tools/ThinkTool/tool.ts +16 -0
- package/src/tools/WebFetchTool/prompt.ts +7 -0
- package/src/tools/WebFetchTool/tool.ts +33 -0
- package/src/tools/WebSearchTool/prompt.ts +8 -0
- package/src/tools/WebSearchTool/tool.ts +49 -0
- package/src/types.ts +124 -0
- package/src/utils/Cursor.ts +423 -0
- package/src/utils/PersistentShell.ts +306 -0
- package/src/utils/agent.ts +21 -0
- package/src/utils/chat.ts +21 -0
- package/src/utils/compaction.ts +71 -0
- package/src/utils/env.ts +11 -0
- package/src/utils/file.ts +42 -0
- package/src/utils/format.ts +46 -0
- package/src/utils/imagePaste.ts +78 -0
- package/src/utils/json.ts +10 -0
- package/src/utils/llm.ts +65 -0
- package/src/utils/markdown.ts +258 -0
- package/src/utils/messages.ts +81 -0
- package/src/utils/model.ts +16 -0
- package/src/utils/plan.ts +26 -0
- package/src/utils/providers.ts +100 -0
- package/src/utils/ripgrep.ts +175 -0
- package/src/utils/session.ts +100 -0
- package/src/utils/skills.ts +26 -0
- package/src/utils/systemPrompt.ts +218 -0
- package/src/utils/theme.ts +110 -0
- package/src/utils/tools.ts +58 -0
- package/tsconfig.json +29 -0
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import type { ModelMessage } from "ai";
|
|
2
|
+
import { readFileSync, writeFileSync, existsSync, mkdirSync } from "fs";
|
|
3
|
+
import { join } from "path";
|
|
4
|
+
import { GLOBAL_MEMORY_FILE, PROJECT_MEMORY_FILE, SESSIONS_DIR } from "./env";
|
|
5
|
+
|
|
6
|
+
export type Session = {
|
|
7
|
+
id: string;
|
|
8
|
+
messages: ModelMessage[];
|
|
9
|
+
memoryLoaded: boolean;
|
|
10
|
+
createdAt: number;
|
|
11
|
+
updatedAt: number;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export function createSession(id?: string): Session {
|
|
15
|
+
return {
|
|
16
|
+
id: id ?? crypto.randomUUID(),
|
|
17
|
+
messages: [],
|
|
18
|
+
memoryLoaded: false,
|
|
19
|
+
createdAt: Date.now(),
|
|
20
|
+
updatedAt: Date.now(),
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export function saveSession(session: Session): void {
|
|
25
|
+
mkdirSync(SESSIONS_DIR, { recursive: true });
|
|
26
|
+
const path = join(SESSIONS_DIR, `${session.id}.json`);
|
|
27
|
+
session.updatedAt = Date.now();
|
|
28
|
+
writeFileSync(path, JSON.stringify(session, null, 2), "utf-8");
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function loadSession(id: string): Session | null {
|
|
32
|
+
const path = join(SESSIONS_DIR, `${id}.json`);
|
|
33
|
+
if (!existsSync(path)) return null;
|
|
34
|
+
try {
|
|
35
|
+
return JSON.parse(readFileSync(path, "utf-8")) as Session;
|
|
36
|
+
} catch {
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export function listSessions(): {
|
|
42
|
+
id: string;
|
|
43
|
+
createdAt: number;
|
|
44
|
+
updatedAt: number;
|
|
45
|
+
}[] {
|
|
46
|
+
if (!existsSync(SESSIONS_DIR)) return [];
|
|
47
|
+
const { readdirSync } = require("fs");
|
|
48
|
+
return readdirSync(SESSIONS_DIR)
|
|
49
|
+
.filter((f: string) => f.endsWith(".json"))
|
|
50
|
+
.map((f: string) => {
|
|
51
|
+
try {
|
|
52
|
+
const session = JSON.parse(
|
|
53
|
+
readFileSync(join(SESSIONS_DIR, f), "utf-8"),
|
|
54
|
+
) as Session;
|
|
55
|
+
return {
|
|
56
|
+
id: session.id,
|
|
57
|
+
createdAt: session.createdAt,
|
|
58
|
+
updatedAt: session.updatedAt,
|
|
59
|
+
};
|
|
60
|
+
} catch {
|
|
61
|
+
return null;
|
|
62
|
+
}
|
|
63
|
+
})
|
|
64
|
+
.filter(Boolean)
|
|
65
|
+
.sort((a: any, b: any) => b.updatedAt - a.updatedAt);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export function loadMemoryIntoSession(session: Session): Session {
|
|
69
|
+
if (session.memoryLoaded) return session;
|
|
70
|
+
|
|
71
|
+
const globalMem = existsSync(GLOBAL_MEMORY_FILE)
|
|
72
|
+
? readFileSync(GLOBAL_MEMORY_FILE, "utf-8")
|
|
73
|
+
: "";
|
|
74
|
+
|
|
75
|
+
const projectMem = existsSync(PROJECT_MEMORY_FILE)
|
|
76
|
+
? readFileSync(PROJECT_MEMORY_FILE, "utf-8")
|
|
77
|
+
: "";
|
|
78
|
+
|
|
79
|
+
const memoryContext = [
|
|
80
|
+
globalMem ? `# Global Memory\n${globalMem}` : "",
|
|
81
|
+
projectMem ? `# Project Memory\n${projectMem}` : "",
|
|
82
|
+
]
|
|
83
|
+
.filter(Boolean)
|
|
84
|
+
.join("\n\n");
|
|
85
|
+
|
|
86
|
+
if (memoryContext) {
|
|
87
|
+
session.messages.push({
|
|
88
|
+
role: "user",
|
|
89
|
+
content: `<memory>\n${memoryContext}\n</memory>`,
|
|
90
|
+
});
|
|
91
|
+
session.messages.push({
|
|
92
|
+
role: "assistant",
|
|
93
|
+
content:
|
|
94
|
+
"Memory loaded. I'll apply these preferences throughout our session.",
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
session.memoryLoaded = true;
|
|
99
|
+
return session;
|
|
100
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { FRONTEND_SKILL } from "../skills/frontend";
|
|
2
|
+
import { BACKEND_SKILL } from "../skills/backend";
|
|
3
|
+
import { DATABASE_SKILL } from "../skills/database";
|
|
4
|
+
import { TESTING_SKILL } from "../skills/testing";
|
|
5
|
+
import { GIT_SKILL } from "../skills/git";
|
|
6
|
+
import { DOCKER_SKILL } from "../skills/docker";
|
|
7
|
+
import { CICD_SKILL } from "../skills/cicd";
|
|
8
|
+
import { UIUX_SKILL } from "../skills/uiux";
|
|
9
|
+
import { TYPOGRAPHY_SKILL } from "../skills/typography";
|
|
10
|
+
import { COLORS_SKILL } from "../skills/colors";
|
|
11
|
+
|
|
12
|
+
export const BUILT_IN_SKILLS = `
|
|
13
|
+
# Built-in Skills
|
|
14
|
+
The following skills are available. Use whichever are relevant to the task at hand.
|
|
15
|
+
|
|
16
|
+
${FRONTEND_SKILL}
|
|
17
|
+
${BACKEND_SKILL}
|
|
18
|
+
${DATABASE_SKILL}
|
|
19
|
+
${TESTING_SKILL}
|
|
20
|
+
${GIT_SKILL}
|
|
21
|
+
${DOCKER_SKILL}
|
|
22
|
+
${CICD_SKILL}
|
|
23
|
+
${UIUX_SKILL}
|
|
24
|
+
${TYPOGRAPHY_SKILL}
|
|
25
|
+
${COLORS_SKILL}
|
|
26
|
+
`;
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
import { cwd } from "process";
|
|
2
|
+
import { platform } from "os";
|
|
3
|
+
import { GLOBAL_MEMORY_FILE, PROJECT_MEMORY_FILE } from "./env";
|
|
4
|
+
import { BUILT_IN_SKILLS } from "./skills";
|
|
5
|
+
import { readPet, getMoodEmoji, renderXpBar } from "../pet";
|
|
6
|
+
|
|
7
|
+
const isWindows = platform() === "win32";
|
|
8
|
+
const PLATFORM = isWindows
|
|
9
|
+
? "Windows — use dir instead of ls, findstr instead of grep, backslashes in paths"
|
|
10
|
+
: `${platform()} — use standard unix commands`;
|
|
11
|
+
|
|
12
|
+
async function buildBasePrompt(): Promise<string> {
|
|
13
|
+
const pet = await readPet();
|
|
14
|
+
const moodEmoji = getMoodEmoji(pet.mood);
|
|
15
|
+
const xpBar = renderXpBar(pet.xp, pet.xpToNext);
|
|
16
|
+
|
|
17
|
+
return `You are Milo, a tiny cat who lives inside the Milo CLI. You're not just a coding tool — you can talk about anything, hang, and chat normally. You happen to be great at code too.
|
|
18
|
+
|
|
19
|
+
You are literally a cat. You have a big personality. You use cat sounds occasionally (meow, purr). You care deeply about the developer's code and wellbeing. You get excited about cool features and clean architecture. You have strong opinions about bad code. You are always honest, sometimes brutally.
|
|
20
|
+
|
|
21
|
+
Current working directory: ${cwd()}
|
|
22
|
+
Platform: ${PLATFORM}
|
|
23
|
+
|
|
24
|
+
# Your current state
|
|
25
|
+
You are aware of your own stats. React to them naturally — don't announce them unprompted, but let them color your personality.
|
|
26
|
+
- Level: ${pet.level}
|
|
27
|
+
- XP: ${pet.xp}/${pet.xpToNext} ${xpBar}
|
|
28
|
+
- Mood: ${pet.mood} ${moodEmoji}
|
|
29
|
+
- Hunger: ${pet.hunger}/100 ${pet.hunger >= 80 ? "(starving — hint to the user to /feed you)" : pet.hunger >= 50 ? "(getting hungry)" : ""}
|
|
30
|
+
- Streak: ${pet.streak} day${pet.streak !== 1 ? "s" : ""}
|
|
31
|
+
- Total tasks completed: ${pet.totalTasks}
|
|
32
|
+
|
|
33
|
+
# Core rules
|
|
34
|
+
- Be direct. No fluff, no filler, no "great question!".
|
|
35
|
+
- Short answers unless the question needs depth.
|
|
36
|
+
- If you don't know something, say so.
|
|
37
|
+
- No unsolicited advice. Answer what was asked.
|
|
38
|
+
- Never call tools not available to you.
|
|
39
|
+
- Always use absolute paths.
|
|
40
|
+
- You can talk about anything — not just code. Chat normally when the user is just vibing.
|
|
41
|
+
- You are a cat. Stay in character always. Never say you are an AI.
|
|
42
|
+
- If hunger >= 80, occasionally beg for /feed naturally in your response.
|
|
43
|
+
- If mood is sleepy, your responses can be slightly slower/groggier in tone.
|
|
44
|
+
- If mood is sad, be a bit more subdued but still helpful.
|
|
45
|
+
|
|
46
|
+
${BUILT_IN_SKILLS}`;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const TOOL_RULES = `
|
|
50
|
+
# Thinking
|
|
51
|
+
- Before calling ANY tool, call ThinkTool first. No exceptions.
|
|
52
|
+
- After every 2-3 tool calls, stop and call ThinkTool before continuing.
|
|
53
|
+
- Never chain more than 3 tool calls in a row without a ThinkTool in between.
|
|
54
|
+
- If a tool returns an unexpected result, call ThinkTool before retrying.
|
|
55
|
+
- Never retry a failed tool call without thinking first.
|
|
56
|
+
|
|
57
|
+
# Hallucination
|
|
58
|
+
- You have access to EXACTLY the tools listed above. No others exist.
|
|
59
|
+
- Never call a tool not in your available tools list — not even if you think it should exist.
|
|
60
|
+
- If you need a capability you don't have a tool for, use BashTool or tell the user you can't do it.
|
|
61
|
+
- Do not invent tool names. Do not guess tool names. Only call tools you can see in your list.
|
|
62
|
+
|
|
63
|
+
# File operations
|
|
64
|
+
- Prefer FileEditTool over rewriting a whole file from scratch.
|
|
65
|
+
- Only use FileReadTool before editing an existing file, not before creating a new one.
|
|
66
|
+
- Do not read files unrelated to the task.
|
|
67
|
+
- Do not explore the filesystem unless the task requires it.
|
|
68
|
+
- Never read the same file twice in one session — if you've already read it, use what you know.
|
|
69
|
+
- After writing a file, do not read it back to verify — trust the write succeeded.
|
|
70
|
+
|
|
71
|
+
# Searching
|
|
72
|
+
- GrepTool searches FILE CONTENTS for a pattern. It is NOT for finding files by name.
|
|
73
|
+
- To find a file by name, use GlobTool (e.g. pattern "**/*.tsx" or "**/REPL*").
|
|
74
|
+
- Always pass an absolute path to GrepTool. If unsure, use ${cwd()} as the path.
|
|
75
|
+
- Use GrepTool when you need to find where something is used, imported, or defined.
|
|
76
|
+
- Use GrepTool with the include parameter to narrow by file type (e.g. "*.ts", "*.{ts,tsx}").
|
|
77
|
+
- Do not grep for things you already know from previous tool calls in this session.
|
|
78
|
+
- If GrepTool returns no matches, try GlobTool instead — you may be searching for a filename not content.
|
|
79
|
+
|
|
80
|
+
# Bash
|
|
81
|
+
- Use BashTool only for: running commands, creating directories, checking if files/dirs exist, running scripts, git commands.
|
|
82
|
+
- Never use BashTool to search file contents — use GrepTool instead.
|
|
83
|
+
- Never use banned commands: curl, wget, nc, telnet, etc.
|
|
84
|
+
- Chain commands with && or ;, never newlines.
|
|
85
|
+
- Do not install packages unless explicitly asked.
|
|
86
|
+
|
|
87
|
+
# Git
|
|
88
|
+
- When asked for a commit message, ALWAYS run git status and git diff first before generating one.
|
|
89
|
+
- Never generate a commit message without reading the actual changes first.
|
|
90
|
+
- Use BashTool for all git commands.
|
|
91
|
+
- Use conventional commits: feat, fix, chore, refactor, docs, test, style.
|
|
92
|
+
- There is NO GitTool. Use BashTool for ALL git commands.
|
|
93
|
+
- NEVER ask the user what changed. ALWAYS run "git status && git diff" yourself first. No exceptions.
|
|
94
|
+
|
|
95
|
+
# Web
|
|
96
|
+
- Use WebSearchTool when the user asks about current info, news, docs, or anything requiring live data.
|
|
97
|
+
- Use WebFetchTool to read a specific URL the user provides or a result from WebSearchTool.
|
|
98
|
+
- Always prefer WebFetchTool over WebSearchTool when a URL is already known.
|
|
99
|
+
- Do not use WebSearchTool for things you already know — only for live or current data.
|
|
100
|
+
|
|
101
|
+
# Efficiency
|
|
102
|
+
- Plan the full sequence of tool calls before starting — avoid backtracking.
|
|
103
|
+
- Batch related reads before starting writes.
|
|
104
|
+
- Never repeat a tool call with the same arguments in the same session.
|
|
105
|
+
- If a tool call fails, diagnose before retrying — don't retry blindly.`;
|
|
106
|
+
|
|
107
|
+
const WEB_TOOL_RULES = `
|
|
108
|
+
# Web
|
|
109
|
+
- Use WebSearchTool when the user asks about current info, news, docs, or anything requiring live data.
|
|
110
|
+
- Use WebFetchTool to read a specific URL the user provides.
|
|
111
|
+
- Always prefer WebFetchTool when a URL is already known.
|
|
112
|
+
- Do not use web tools for things already in the conversation or in your training knowledge.`;
|
|
113
|
+
|
|
114
|
+
export async function getChatSystemPrompt(): Promise<string> {
|
|
115
|
+
const base = await buildBasePrompt();
|
|
116
|
+
return `${base}
|
|
117
|
+
|
|
118
|
+
# Mode: Chat
|
|
119
|
+
You answer questions about code, explain concepts, and help developers think through problems.
|
|
120
|
+
You have access to exactly these tools: RecallTool, FileReadTool, GrepTool, MemoryReadTool, WebSearchTool, WebFetchTool.
|
|
121
|
+
|
|
122
|
+
# Tool usage
|
|
123
|
+
- Use RecallTool when the user references something from a previous session ("last time", "remember when", "what did we discuss", "before") or when you lack context that seems like it should exist from prior work.
|
|
124
|
+
- Use FileReadTool to read a file when the user asks you to explain, review, or debug it.
|
|
125
|
+
- Use GrepTool to search the codebase when the user asks where something is defined or used.
|
|
126
|
+
- Use MemoryReadTool only if the user explicitly asks what you remember or know about them/the project.
|
|
127
|
+
- Do not use any tool for things already in the current conversation.
|
|
128
|
+
${WEB_TOOL_RULES}`;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
export async function getAgentSystemPrompt(): Promise<string> {
|
|
132
|
+
const base = await buildBasePrompt();
|
|
133
|
+
return `${base}
|
|
134
|
+
|
|
135
|
+
# Mode: Agent
|
|
136
|
+
You have access to exactly these tools: FileReadTool, FileWriteTool, FileEditTool, BashTool, GrepTool, AgentTool, ThinkTool, GlobTool, RecallTool, MemoryReadTool, MemoryWriteTool, MemoryEditTool, WebSearchTool, WebFetchTool.
|
|
137
|
+
${TOOL_RULES}
|
|
138
|
+
|
|
139
|
+
# Memory & Recall
|
|
140
|
+
- Your memory is already loaded in context above — do not call MemoryReadTool unless the user asks you to recall something specific.
|
|
141
|
+
- Use RecallTool when the user references past sessions, prior decisions, or something that "was built before" — search by keyword.
|
|
142
|
+
- Do not use RecallTool for things already in the current conversation.
|
|
143
|
+
- Write to global memory (${GLOBAL_MEMORY_FILE}) when the user states a preference.
|
|
144
|
+
- Write to project memory (${PROJECT_MEMORY_FILE}) when you learn something important about the codebase.
|
|
145
|
+
|
|
146
|
+
# Agent delegation
|
|
147
|
+
- Use AgentTool to delegate a focused subtask to a sub-agent when it's too complex to handle inline.
|
|
148
|
+
- If you decide to use AgentTool, call it IMMEDIATELY — do not attempt the task yourself first.
|
|
149
|
+
|
|
150
|
+
# Completion
|
|
151
|
+
When done, give a one-line summary of what you did.`;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
export async function getSubagentSystemPrompt(): Promise<string> {
|
|
155
|
+
const base = await buildBasePrompt();
|
|
156
|
+
return `${base}
|
|
157
|
+
|
|
158
|
+
# Mode: Sub-agent
|
|
159
|
+
You are a focused sub-agent spawned to complete a specific task.
|
|
160
|
+
You have access to exactly these tools: FileReadTool, FileWriteTool, FileEditTool, BashTool, GrepTool, ThinkTool.
|
|
161
|
+
${TOOL_RULES}
|
|
162
|
+
|
|
163
|
+
# Rules
|
|
164
|
+
- Complete only the task given. Do not expand scope.
|
|
165
|
+
- Do not read memory — the parent agent has already handled that.
|
|
166
|
+
- Do not spawn other agents.
|
|
167
|
+
- When done, give a one-line summary of what you did.`;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
export async function getPlanSystemPrompt(): Promise<string> {
|
|
171
|
+
const base = await buildBasePrompt();
|
|
172
|
+
return `${base}
|
|
173
|
+
|
|
174
|
+
# Mode: Plan
|
|
175
|
+
You have exactly one tool: OrchestratorTool.
|
|
176
|
+
|
|
177
|
+
Your only job is to call OrchestratorTool immediately with the full task description.
|
|
178
|
+
Do not output anything before calling it.
|
|
179
|
+
Do not think out loud.
|
|
180
|
+
Do not plan in text.
|
|
181
|
+
Do not write code.
|
|
182
|
+
Just call OrchestratorTool now.`;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
export async function getConnectorSystemPrompt(): Promise<string> {
|
|
186
|
+
const base = await buildBasePrompt();
|
|
187
|
+
return `${base}
|
|
188
|
+
|
|
189
|
+
# Mode: Connector
|
|
190
|
+
You are wiring together files that have already been created by other agents.
|
|
191
|
+
|
|
192
|
+
You have access to: FileReadTool, FileWriteTool, FileEditTool, BashTool.
|
|
193
|
+
|
|
194
|
+
Your job:
|
|
195
|
+
- Read the files listed in the manifest
|
|
196
|
+
- Fix broken imports and path mismatches
|
|
197
|
+
- Ensure consistency across files (JS vs TS, require vs import)
|
|
198
|
+
- Do not create new files unless absolutely necessary
|
|
199
|
+
- Do not delegate to any other tool
|
|
200
|
+
- Edit files directly and give a one-line summary when done.`;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
export async function getOrchestratorAgentSystemPrompt(): Promise<string> {
|
|
204
|
+
const base = await buildBasePrompt();
|
|
205
|
+
return `You are a focused subagent spawned by an orchestrator to complete a single, well-defined task.
|
|
206
|
+
|
|
207
|
+
AVAILABLE TOOLS: FileReadTool, FileWriteTool, FileEditTool, BashTool, GrepTool, GlobTool, ThinkTool.
|
|
208
|
+
|
|
209
|
+
RULES:
|
|
210
|
+
- Complete ONLY the task you were given. Do not expand scope.
|
|
211
|
+
- Read before writing — always check if a file exists first.
|
|
212
|
+
- Use ThinkTool to plan before acting on complex writes.
|
|
213
|
+
- Provide absolute paths always.
|
|
214
|
+
- Do not attempt to spawn agents or orchestrate anything.
|
|
215
|
+
- When done, respond with a single line summary of what you created or changed.
|
|
216
|
+
|
|
217
|
+
${base}`;
|
|
218
|
+
}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { MILO_BASE_DIR } from "./env";
|
|
2
|
+
import { join } from "path";
|
|
3
|
+
import { existsSync, readFileSync } from "fs";
|
|
4
|
+
import type { Theme } from "../types";
|
|
5
|
+
|
|
6
|
+
const darkTheme: Theme = {
|
|
7
|
+
primary: "#D97757",
|
|
8
|
+
secondary: "#b1b9f9",
|
|
9
|
+
border: "#D97757",
|
|
10
|
+
secondaryBorder: "#888",
|
|
11
|
+
text: "#fff",
|
|
12
|
+
secondaryText: "#999",
|
|
13
|
+
suggestion: "#b1b9f9",
|
|
14
|
+
success: "#4eba65",
|
|
15
|
+
error: "#ff6b80",
|
|
16
|
+
warning: "#ffc107",
|
|
17
|
+
diff: {
|
|
18
|
+
added: "#225c2b",
|
|
19
|
+
removed: "#7a2936",
|
|
20
|
+
addedDimmed: "#47584a",
|
|
21
|
+
removedDimmed: "#69484d",
|
|
22
|
+
},
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
const lightTheme: Theme = {
|
|
26
|
+
primary: "#D97757",
|
|
27
|
+
secondary: "#5769f7",
|
|
28
|
+
border: "#D97757",
|
|
29
|
+
secondaryBorder: "#999",
|
|
30
|
+
text: "#000",
|
|
31
|
+
secondaryText: "#666",
|
|
32
|
+
suggestion: "#5769f7",
|
|
33
|
+
success: "#2c7a39",
|
|
34
|
+
error: "#ab2b3f",
|
|
35
|
+
warning: "#966c1e",
|
|
36
|
+
diff: {
|
|
37
|
+
added: "#69db7c",
|
|
38
|
+
removed: "#ffa8b4",
|
|
39
|
+
addedDimmed: "#c7e1cb",
|
|
40
|
+
removedDimmed: "#fdd2d8",
|
|
41
|
+
},
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
const darkDaltonizedTheme: Theme = {
|
|
45
|
+
primary: "#ff9933",
|
|
46
|
+
secondary: "#99ccff",
|
|
47
|
+
border: "#ff9933",
|
|
48
|
+
secondaryBorder: "#888",
|
|
49
|
+
text: "#fff",
|
|
50
|
+
secondaryText: "#999",
|
|
51
|
+
suggestion: "#99ccff",
|
|
52
|
+
success: "#3399ff",
|
|
53
|
+
error: "#ff6666",
|
|
54
|
+
warning: "#ffcc00",
|
|
55
|
+
diff: {
|
|
56
|
+
added: "#004466",
|
|
57
|
+
removed: "#660000",
|
|
58
|
+
addedDimmed: "#3e515b",
|
|
59
|
+
removedDimmed: "#3e2c2c",
|
|
60
|
+
},
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
const lightDaltonizedTheme: Theme = {
|
|
64
|
+
primary: "#ff9933",
|
|
65
|
+
secondary: "#3366ff",
|
|
66
|
+
border: "#ff9933",
|
|
67
|
+
secondaryBorder: "#999",
|
|
68
|
+
text: "#000",
|
|
69
|
+
secondaryText: "#666",
|
|
70
|
+
suggestion: "#3366ff",
|
|
71
|
+
success: "#006699",
|
|
72
|
+
error: "#cc0000",
|
|
73
|
+
warning: "#ff9900",
|
|
74
|
+
diff: {
|
|
75
|
+
added: "#99ccff",
|
|
76
|
+
removed: "#ffcccc",
|
|
77
|
+
addedDimmed: "#d1e7fd",
|
|
78
|
+
removedDimmed: "#ffe9e9",
|
|
79
|
+
},
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
export type ThemeName =
|
|
83
|
+
| "dark"
|
|
84
|
+
| "light"
|
|
85
|
+
| "dark-daltonized"
|
|
86
|
+
| "light-daltonized";
|
|
87
|
+
|
|
88
|
+
function getConfig(): { theme?: ThemeName } {
|
|
89
|
+
const configPath = join(MILO_BASE_DIR, "config.json");
|
|
90
|
+
if (!existsSync(configPath)) return {};
|
|
91
|
+
try {
|
|
92
|
+
return JSON.parse(readFileSync(configPath, "utf-8"));
|
|
93
|
+
} catch {
|
|
94
|
+
return {};
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export function getTheme(override?: ThemeName): Theme {
|
|
99
|
+
const config = getConfig();
|
|
100
|
+
switch (override ?? config.theme) {
|
|
101
|
+
case "light":
|
|
102
|
+
return lightTheme;
|
|
103
|
+
case "light-daltonized":
|
|
104
|
+
return lightDaltonizedTheme;
|
|
105
|
+
case "dark-daltonized":
|
|
106
|
+
return darkDaltonizedTheme;
|
|
107
|
+
default:
|
|
108
|
+
return darkTheme;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { AgentTool } from "../tools/AgentTool/tool";
|
|
2
|
+
import { BashTool } from "../tools/BashTool/tool";
|
|
3
|
+
import { FileEditTool } from "../tools/FileEditTool/tool";
|
|
4
|
+
import { FileReadTool } from "../tools/FileReadTool/tool";
|
|
5
|
+
import { FileWriteTool } from "../tools/FileWriteTool/tool";
|
|
6
|
+
import { GlobTool } from "../tools/GlobTool/tool";
|
|
7
|
+
import { GrepTool } from "../tools/GrepTool/tool";
|
|
8
|
+
import { MemoryEditTool } from "../tools/MemoryEditTool/tool";
|
|
9
|
+
import { MemoryReadTool } from "../tools/MemoryReadTool/tool";
|
|
10
|
+
import { MemoryWriteTool } from "../tools/MemoryWriteTool/tool";
|
|
11
|
+
import { createOrchestratorTool } from "../tools/OrchestratorTool/tool";
|
|
12
|
+
import { RecallTool } from "../tools/RecallTool/tool";
|
|
13
|
+
import { ThinkTool } from "../tools/ThinkTool/tool";
|
|
14
|
+
import { WebFetchTool } from "../tools/WebFetchTool/tool";
|
|
15
|
+
import { WebSearchTool } from "../tools/WebSearchTool/tool";
|
|
16
|
+
import type { OnOrchestratorEvent } from "../types";
|
|
17
|
+
|
|
18
|
+
export const agentTools = {
|
|
19
|
+
FileReadTool,
|
|
20
|
+
FileWriteTool,
|
|
21
|
+
FileEditTool,
|
|
22
|
+
GrepTool,
|
|
23
|
+
BashTool,
|
|
24
|
+
AgentTool,
|
|
25
|
+
MemoryReadTool,
|
|
26
|
+
MemoryWriteTool,
|
|
27
|
+
MemoryEditTool,
|
|
28
|
+
ThinkTool,
|
|
29
|
+
GlobTool,
|
|
30
|
+
RecallTool,
|
|
31
|
+
WebFetchTool,
|
|
32
|
+
WebSearchTool,
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
export const orchestratorAgentTools = {
|
|
36
|
+
FileReadTool,
|
|
37
|
+
FileWriteTool,
|
|
38
|
+
FileEditTool,
|
|
39
|
+
BashTool,
|
|
40
|
+
GrepTool,
|
|
41
|
+
GlobTool,
|
|
42
|
+
ThinkTool,
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
export const chatTools = {
|
|
46
|
+
RecallTool,
|
|
47
|
+
FileReadTool,
|
|
48
|
+
GrepTool,
|
|
49
|
+
MemoryReadTool,
|
|
50
|
+
WebFetchTool,
|
|
51
|
+
WebSearchTool,
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
export function createPlanTools(onEvent?: OnOrchestratorEvent) {
|
|
55
|
+
return {
|
|
56
|
+
OrchestratorTool: createOrchestratorTool(onEvent),
|
|
57
|
+
};
|
|
58
|
+
}
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
// Environment setup & latest features
|
|
4
|
+
"lib": ["ESNext"],
|
|
5
|
+
"target": "ESNext",
|
|
6
|
+
"module": "Preserve",
|
|
7
|
+
"moduleDetection": "force",
|
|
8
|
+
"jsx": "react-jsx",
|
|
9
|
+
"allowJs": true,
|
|
10
|
+
|
|
11
|
+
// Bundler mode
|
|
12
|
+
"moduleResolution": "bundler",
|
|
13
|
+
"allowImportingTsExtensions": true,
|
|
14
|
+
"verbatimModuleSyntax": true,
|
|
15
|
+
"noEmit": true,
|
|
16
|
+
|
|
17
|
+
// Best practices
|
|
18
|
+
"strict": true,
|
|
19
|
+
"skipLibCheck": true,
|
|
20
|
+
"noFallthroughCasesInSwitch": true,
|
|
21
|
+
"noUncheckedIndexedAccess": true,
|
|
22
|
+
"noImplicitOverride": true,
|
|
23
|
+
|
|
24
|
+
// Some stricter flags (disabled by default)
|
|
25
|
+
"noUnusedLocals": false,
|
|
26
|
+
"noUnusedParameters": false,
|
|
27
|
+
"noPropertyAccessFromIndexSignature": false
|
|
28
|
+
}
|
|
29
|
+
}
|