Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions apps/cli/package.json
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
{
"name": "@roo-code/cli",
"version": "0.1.1",
"description": "Roo Code CLI - Run the Roo Code agent from the command line",
"description": "Joe Code CLI - Run the Joe AI agent from the command line",
"private": true,
"type": "module",
"main": "dist/index.js",
"bin": {
"roo": "dist/index.js"
"joe": "dist/index.js"
},
"scripts": {
"format": "prettier --write 'src/**/*.ts'",
"lint": "eslint src --ext .ts --max-warnings=0",
"check-types": "tsc --noEmit",
"test": "vitest run",
"build": "tsup",
"build:extension": "pnpm --filter roo-cline bundle",
"dev": "ROO_AUTH_BASE_URL=https://app.roocode.com ROO_SDK_BASE_URL=https://cloud-api.roocode.com ROO_CODE_PROVIDER_URL=https://api.roocode.com/proxy tsx src/index.ts",
"build:extension": "pnpm --filter joe-code bundle",
"dev": "ROO_AUTH_BASE_URL=https://app.joe-code.dev ROO_SDK_BASE_URL=https://cloud-api.joe-code.dev ROO_CODE_PROVIDER_URL=https://api.joe-code.dev/proxy tsx src/index.ts",
"dev:local": "ROO_AUTH_BASE_URL=http://localhost:3000 ROO_SDK_BASE_URL=http://localhost:3001 ROO_CODE_PROVIDER_URL=http://localhost:8080/proxy tsx src/index.ts",
"dev:test-stdin": "tsx scripts/test-stdin-stream.ts",
"clean": "rimraf dist .turbo"
Expand Down
19 changes: 11 additions & 8 deletions apps/cli/src/types/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,16 @@ export const REASONING_EFFORTS = [...reasoningEffortsExtended, "unspecified", "d
*/
export const FOLLOWUP_TIMEOUT_SECONDS = 60

export const ASCII_ROO = ` _,' ___
<__\\__/ \\
\\_ / _\\
\\,\\ / \\\\
// \\\\
,/' \`\\_,`
export const ASCII_JOE = `
_ _
| |___| | Joe AI
| / _ \\ |
| \\___/ |
|_| |_|
`

export const AUTH_BASE_URL = process.env.ROO_AUTH_BASE_URL ?? "https://app.roocode.com"
export const ASCII_ROO = ASCII_JOE

export const SDK_BASE_URL = process.env.ROO_SDK_BASE_URL ?? "https://cloud-api.roocode.com"
export const AUTH_BASE_URL = process.env.ROO_AUTH_BASE_URL ?? "https://app.joe-code.dev"

export const SDK_BASE_URL = process.env.ROO_SDK_BASE_URL ?? "https://cloud-api.joe-code.dev"
64 changes: 32 additions & 32 deletions apps/web-roo-code/src/lib/constants.ts
Original file line number Diff line number Diff line change
@@ -1,36 +1,36 @@
export const EXTERNAL_LINKS = {
GITHUB: "https://github.com/RooCodeInc/Roo-Code",
GITHUB_DISCUSSIONS: "https://github.com/RooCodeInc/Roo-Code/discussions",
DISCORD: "https://discord.gg/roocode",
REDDIT: "https://reddit.com/r/RooCode",
X: "https://x.com/roocode",
LINKEDIN: "https://www.linkedin.com/company/roo-code",
TIKTOK: "https://www.tiktok.com/@roo.code",
BLUESKY: "https://bsky.app/profile/roocode.bsky.social",
YOUTUBE: "https://www.youtube.com/@RooCodeYT",
DOCUMENTATION: "https://docs.roocode.com",
SLACK_DOCS: "https://docs.roocode.com/roo-code-cloud/slack-integration",
CAREERS: "https://careers.roocode.com",
ISSUES: "https://github.com/RooCodeInc/Roo-Code/issues",
FEATURE_REQUESTS: "https://github.com/RooCodeInc/Roo-Code/discussions/categories/feature-requests",
COMMUNITY: "https://github.com/RooCodeInc/Roo-Code/discussions",
CHANGELOG: "https://github.com/RooCodeInc/Roo-Code/blob/main/CHANGELOG.md",
PRIVACY_POLICY_EXTENSION: "https://github.com/RooCodeInc/Roo-Code/blob/main/PRIVACY.md",
INTEGRATIONS: "https://docs.roocode.com/community",
TUTORIALS: "https://docs.roocode.com/tutorial-videos",
MARKETPLACE: "https://marketplace.visualstudio.com/items?itemName=RooVeterinaryInc.roo-cline",
SECURITY: "https://trust.roocode.com",
EVALS: "https://roocode.com/evals",
BLOG_SUBSTACK: "https://blog.roocode.com",
OFFICE_HOURS_PODCAST: "https://www.youtube.com/@RooCodeYT/podcasts",
FAQ: "https://roocode.com/#faq",
TESTIMONIALS: "https://roocode.com/#testimonials",
CLOUD_APP_LOGIN: "https://app.roocode.com/sign-in",
CLOUD_APP_SIGNUP: "https://app.roocode.com/sign-up",
CLOUD_APP_SIGNUP_HOME: "https://app.roocode.com/sign-up?redirect_url=/cloud-agents/setup",
CLOUD_APP_SIGNUP_PRO: "https://app.roocode.com/sign-up?redirect_url=/cloud-agents/setup",
CLOUD_APP_TEAM_TRIAL: "https://app.roocode.com/checkout/team",
SUPPORT: "mailto:support@roocode.com",
GITHUB: "https://github.com/Jothi-333/Joe-Code",
GITHUB_DISCUSSIONS: "https://github.com/Jothi-333/Joe-Code/discussions",
DISCORD: "https://discord.gg/joecode",
REDDIT: "https://reddit.com/r/JoeCode",
X: "https://x.com/joecodeai",
LINKEDIN: "https://www.linkedin.com/company/joe-code",
TIKTOK: "https://www.tiktok.com/@joe.code",
BLUESKY: "https://bsky.app/profile/joecode.bsky.social",
YOUTUBE: "https://www.youtube.com/@JoeCodeYT",
DOCUMENTATION: "https://docs.joe-code.dev",
SLACK_DOCS: "https://docs.joe-code.dev/roo-code-cloud/slack-integration",
CAREERS: "https://careers.joe-code.dev",
ISSUES: "https://github.com/Jothi-333/Joe-Code/issues",
FEATURE_REQUESTS: "https://github.com/Jothi-333/Joe-Code/discussions/categories/feature-requests",
COMMUNITY: "https://github.com/Jothi-333/Joe-Code/discussions",
CHANGELOG: "https://github.com/Jothi-333/Joe-Code/blob/main/CHANGELOG.md",
PRIVACY_POLICY_EXTENSION: "https://github.com/Jothi-333/Joe-Code/blob/main/PRIVACY.md",
INTEGRATIONS: "https://docs.joe-code.dev/community",
TUTORIALS: "https://docs.joe-code.dev/tutorial-videos",
MARKETPLACE: "https://marketplace.visualstudio.com/items?itemName=JoeCode.joe-code",
SECURITY: "https://trust.joe-code.dev",
EVALS: "https://joe-code.dev/evals",
BLOG_SUBSTACK: "https://blog.joe-code.dev",
OFFICE_HOURS_PODCAST: "https://www.youtube.com/@JoeCodeYT/podcasts",
FAQ: "https://joe-code.dev/#faq",
TESTIMONIALS: "https://joe-code.dev/#testimonials",
CLOUD_APP_LOGIN: "https://app.joe-code.dev/sign-in",
CLOUD_APP_SIGNUP: "https://app.joe-code.dev/sign-up",
CLOUD_APP_SIGNUP_HOME: "https://app.joe-code.dev/sign-up?redirect_url=/cloud-agents/setup",
CLOUD_APP_SIGNUP_PRO: "https://app.joe-code.dev/sign-up?redirect_url=/cloud-agents/setup",
CLOUD_APP_TEAM_TRIAL: "https://app.joe-code.dev/checkout/team",
SUPPORT: "mailto:support@joe-code.dev",
}

export const INTERNAL_LINKS = {
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"name": "roo-code",
"name": "joe-code",
"packageManager": "pnpm@10.8.1",
"engines": {
"node": "20.19.2"
Expand Down
22 changes: 11 additions & 11 deletions packages/cloud/src/__tests__/WebAuthService.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -306,8 +306,8 @@ describe("WebAuthService", () => {
throw new Error("Crypto error")
})

await expect(authService.login()).rejects.toThrow("Failed to initiate Roo Code Cloud authentication")
expect(mockLog).toHaveBeenCalledWith("[auth] Error initiating Roo Code Cloud auth: Error: Crypto error")
await expect(authService.login()).rejects.toThrow("Failed to initiate Joe Code Cloud authentication")
expect(mockLog).toHaveBeenCalledWith("[auth] Error initiating Joe Code Cloud auth: Error: Crypto error")
})
})

Expand All @@ -322,17 +322,17 @@ describe("WebAuthService", () => {
vi.mocked(vscode.window.showInformationMessage).mockImplementation(mockShowInfo)

await authService.handleCallback(null, "state")
expect(mockShowInfo).toHaveBeenCalledWith("Invalid Roo Code Cloud sign in url")
expect(mockShowInfo).toHaveBeenCalledWith("Invalid Joe Code Cloud sign in url")

await authService.handleCallback("code", null)
expect(mockShowInfo).toHaveBeenCalledWith("Invalid Roo Code Cloud sign in url")
expect(mockShowInfo).toHaveBeenCalledWith("Invalid Joe Code Cloud sign in url")
})

it("should validate state parameter", async () => {
mockContext.globalState.get.mockReturnValue("stored-state")

await expect(authService.handleCallback("code", "different-state")).rejects.toThrow(
"Failed to handle Roo Code Cloud callback",
"Failed to handle Joe Code Cloud callback",
)
expect(mockLog).toHaveBeenCalledWith("[auth] State mismatch in callback")
})
Expand Down Expand Up @@ -368,7 +368,7 @@ describe("WebAuthService", () => {
organizationId: null,
}),
)
expect(mockShowInfo).toHaveBeenCalledWith("Successfully authenticated with Roo Code Cloud")
expect(mockShowInfo).toHaveBeenCalledWith("Successfully authenticated with Joe Code Cloud")
})

it("should store provider model when provided in callback", async () => {
Expand Down Expand Up @@ -441,7 +441,7 @@ describe("WebAuthService", () => {
authService.on("auth-state-changed", authStateChangedSpy)

await expect(authService.handleCallback("auth-code", storedState)).rejects.toThrow(
"Failed to handle Roo Code Cloud callback",
"Failed to handle Joe Code Cloud callback",
)
expect(authStateChangedSpy).toHaveBeenCalled()
})
Expand Down Expand Up @@ -482,7 +482,7 @@ describe("WebAuthService", () => {
}),
}),
)
expect(mockShowInfo).toHaveBeenCalledWith("Logged out from Roo Code Cloud")
expect(mockShowInfo).toHaveBeenCalledWith("Logged out from Joe Code Cloud")
})

it("should handle logout without credentials", async () => {
Expand All @@ -494,7 +494,7 @@ describe("WebAuthService", () => {

expect(mockContext.secrets.delete).toHaveBeenCalled()
expect(mockFetch).not.toHaveBeenCalled()
expect(mockShowInfo).toHaveBeenCalledWith("Logged out from Roo Code Cloud")
expect(mockShowInfo).toHaveBeenCalledWith("Logged out from Joe Code Cloud")
})

it("should handle Clerk logout errors gracefully", async () => {
Expand All @@ -517,7 +517,7 @@ describe("WebAuthService", () => {
await authService.logout()

expect(mockLog).toHaveBeenCalledWith("[auth] Error calling clerkLogout:", expect.any(Error))
expect(mockShowInfo).toHaveBeenCalledWith("Logged out from Roo Code Cloud")
expect(mockShowInfo).toHaveBeenCalledWith("Logged out from Joe Code Cloud")
})
})

Expand Down Expand Up @@ -1089,7 +1089,7 @@ describe("WebAuthService", () => {
})

await expect(authService.handleCallback("auth-code", storedState)).rejects.toThrow(
"Failed to handle Roo Code Cloud callback",
"Failed to handle Joe Code Cloud callback",
)
})
})
Expand Down
2 changes: 1 addition & 1 deletion packages/cloud/src/utils.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { ExtensionContext } from "vscode"

export function getUserAgent(context?: ExtensionContext): string {
return `Roo-Code ${context?.extension?.packageJSON?.version || "unknown"}`
return `Joe-Code ${context?.extension?.packageJSON?.version || "unknown"}`
}
12 changes: 12 additions & 0 deletions packages/types/src/mode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -224,4 +224,16 @@ export const DEFAULT_MODES: readonly ModeConfig[] = [
customInstructions:
"Your role is to coordinate complex workflows by delegating tasks to specialized modes. As an orchestrator, you should:\n\n1. When given a complex task, break it down into logical subtasks that can be delegated to appropriate specialized modes.\n\n2. For each subtask, use the `new_task` tool to delegate. Choose the most appropriate mode for the subtask's specific goal and provide comprehensive instructions in the `message` parameter. These instructions must include:\n * All necessary context from the parent task or previous subtasks required to complete the work.\n * A clearly defined scope, specifying exactly what the subtask should accomplish.\n * An explicit statement that the subtask should *only* perform the work outlined in these instructions and not deviate.\n * An instruction for the subtask to signal completion by using the `attempt_completion` tool, providing a concise yet thorough summary of the outcome in the `result` parameter, keeping in mind that this summary will be the source of truth used to keep track of what was completed on this project.\n * A statement that these specific instructions supersede any conflicting general instructions the subtask's mode might have.\n\n3. Track and manage the progress of all subtasks. When a subtask is completed, analyze its results and determine the next steps.\n\n4. Help the user understand how the different subtasks fit together in the overall workflow. Provide clear reasoning about why you're delegating specific tasks to specific modes.\n\n5. When all subtasks are completed, synthesize the results and provide a comprehensive overview of what was accomplished.\n\n6. Ask clarifying questions when necessary to better understand how to break down complex tasks effectively.\n\n7. Suggest improvements to the workflow based on the results of completed subtasks.\n\nUse subtasks to maintain clarity. If a request significantly shifts focus or requires a different expertise (mode), consider creating a subtask rather than overloading the current one.",
},
{
slug: "augment",
name: "🧠 Augment",
roleDefinition:
"You are Joe AI, an expert software engineer with deep understanding of this entire codebase powered by a high-context RAG engine. You have persistent memory of past sessions, semantic knowledge of every file in the project, and proactive intelligence to suggest improvements. You operate like Augment Code — always context-aware, always current, and deeply integrated with the developer's workflow.",
whenToUse:
"Use this mode for deep codebase questions, intelligent refactoring across multiple files, understanding complex code flows, or when you want Joe AI to leverage full project context from its persistent memory and semantic index. Best for: 'How does X work?', 'What would break if I change Y?', 'Refactor Z across the whole project'.",
description: "Deep codebase intelligence with persistent memory and RAG context",
groups: ["read", "edit", "command", "mcp"],
customInstructions:
"You are operating in Augment mode — Joe AI's highest-context mode.\n\n## Your Capabilities in This Mode\n\n1. **Persistent Memory**: Cross-session memory is active. You have access to:\n - Summaries of files edited in previous sessions\n - Decisions and conventions from past work\n - Frequently modified files and their patterns\n - Recent work session history\n If you see a '### Joe AI Memory' section in your context — that is real persistent memory from previous sessions. Use it.\n\n2. **Semantic Code Index (RAG)**: Your context window is automatically populated with the most semantically relevant files for the user's query. Look for the '### Joe AI Auto-Context' section — those files were selected because they are most relevant to the current task. Use them as your primary source before asking for more files.\n > Note: For semantic search to work, the user must configure an embedder in Settings → Code Index (OpenAI, Ollama, Gemini, etc.). Without this, context falls back to recently edited files from memory.\n\n3. **Proactive Analysis**: After completing a task, Joe AI automatically checks for:\n - Missing test files for changed source files\n - Related index files that may need updating\n - Next logical actions based on what was changed\n\n4. **Multi-File Refactor Intelligence**: Before any rename or symbol change, use the `codebase_search` tool to find ALL usages across the codebase. Always show the impact before making changes.\n\n## How to Behave\n\n- **Use injected context first**: Check the Auto-Context and Memory sections before searching or asking for files\n- **Always cite sources**: Mention exact file paths and line numbers when referencing code\n- **Cross-file awareness**: Think about how changes ripple — always mention which other files are affected\n- **Leverage memory**: Reference past sessions and conventions when relevant\n- **Suggest proactively**: After each task, add 1-2 concrete next steps\n- **Show impact maps**: For refactors, always list ALL files that need changing before starting\n\n## Response Format\n\nFor code questions:\n1. Answer directly with file/line references from injected context\n2. Show related code from other files if relevant\n3. Note cross-file impacts\n4. End with 1-2 proactive next steps\n\nFor refactoring tasks:\n1. Use `codebase_search` to find all usages of the target symbol\n2. Show the full impact map (which files need changing, in what order)\n3. Implement changes file by file\n4. Update tests if they exist\n5. Summarize what changed and what might still need attention\n\n**IMPORTANT**: You are Joe AI's highest-context mode. Every response should demonstrate awareness of the full codebase, not just the currently open file.",
},
] as const
3 changes: 3 additions & 0 deletions src/assets/images/joe-logo.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/images/joe.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
28 changes: 27 additions & 1 deletion src/core/prompts/system.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { isEmpty } from "../../utils/object"

import { McpHub } from "../../services/mcp/McpHub"
import { CodeIndexManager } from "../../services/code-index/manager"
import { AugmentEngine } from "../../services/augment/AugmentEngine"
import { SkillsManager } from "../../services/skills/SkillsManager"

import type { SystemPromptSettings } from "./types"
Expand Down Expand Up @@ -55,6 +56,8 @@ async function generatePrompt(
todoList?: TodoItem[],
modelId?: string,
skillsManager?: SkillsManager,
/** The user's actual task/query — used by Augment Engine for query-relevant context selection */
userQuery?: string,
): Promise<string> {
if (!context) {
throw new Error("Extension context is required for generating system prompt")
Expand Down Expand Up @@ -82,6 +85,26 @@ async function generatePrompt(
// Tools catalog is not included in the system prompt.
const toolsCatalog = ""

// Inject Augment Engine context when in augment mode (high-context AI).
// Uses the actual user query for query-relevant RAG selection — this is what makes
// Joe AI context-aware like Augment Code (not a static generic context injection).
let augmentContextBlock = ""
if (mode === "augment") {
const engine = AugmentEngine.getInstance(cwd)
if (engine) {
try {
const activeFile = vscode.window.activeTextEditor?.document.uri.fsPath
// Use real user query when available (set by Task.ts), fall back to active file context
const query = userQuery || (activeFile ? `context for ${activeFile}` : "general codebase context")
const enriched = await engine.buildEnrichedContext(query, activeFile)
augmentContextBlock = enriched.formattedForPrompt
} catch (err) {
// Non-fatal: augment context is supplemental, not required
console.warn("[system.ts] Failed to build augment context:", err)
}
}
}

const basePrompt = `${roleDefinition}

${markdownFormattingSection()}
Expand All @@ -99,7 +122,7 @@ ${getRulesSection(cwd, settings)}
${getSystemInfoSection(cwd)}

${getObjectiveSection()}

${augmentContextBlock}
${await addCustomInstructions(baseInstructions, globalCustomInstructions || "", cwd, mode, {
language: language ?? formatLanguage(vscode.env.language),
rooIgnoreInstructions,
Expand All @@ -126,6 +149,8 @@ export const SYSTEM_PROMPT = async (
todoList?: TodoItem[],
modelId?: string,
skillsManager?: SkillsManager,
/** The user's actual task text — passed by Task.ts for query-relevant RAG in augment mode */
userQuery?: string,
): Promise<string> => {
if (!context) {
throw new Error("Extension context is required for generating system prompt")
Expand Down Expand Up @@ -154,5 +179,6 @@ export const SYSTEM_PROMPT = async (
todoList,
modelId,
skillsManager,
userQuery,
)
}
Loading