Skip to content
Merged
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
7 changes: 7 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,13 @@

Every agent working on this Commander project MUST follow these standards. No exceptions.

We use bun run tauri dev to run the app.

You always work on features that are configurable via the Settings Panel in the app. Every feature must be toggleable or adjustable through user preferences.
Before you write any code, you will write the PRD and save in the docs/ directory.

You write the TDD and then write the feature implementation.

## Architecture Pattern - STRICT COMPLIANCE

### Modular Structure (REQUIRED)
Expand Down
15 changes: 11 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
"test:watch": "vitest --watch"
},
"dependencies": {
"@openai/codex": "^0.44.0",
"@openai/codex-sdk": "^0.44.0",
"@phosphor-icons/react": "^2.1.10",
"@radix-ui/react-accordion": "^1.2.12",
"@radix-ui/react-alert-dialog": "^1.1.15",
Expand All @@ -30,31 +32,36 @@
"@radix-ui/react-switch": "^1.2.6",
"@radix-ui/react-toggle": "^1.1.10",
"@radix-ui/react-tooltip": "^1.2.8",
"@radix-ui/react-use-controllable-state": "^1.2.2",
"@tanstack/react-table": "^8.21.3",
"@tauri-apps/api": "^2",
"@tauri-apps/plugin-opener": "^2",
"@types/react-syntax-highlighter": "^15.5.13",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"lucide-react": "^0.541.0",
"prism-react-renderer": "^2.3.1",
"react": "^19.1.0",
"react-dom": "^19.1.0",
"react-file-icon": "^1.5.0",
"react-markdown": "^10.1.0",
"react-syntax-highlighter": "^15.6.6",
"remark-gfm": "^4.0.1",
"vscode-icons-js": "^11.6.1"
},
"devDependencies": {
"@tauri-apps/cli": "^2",
"@testing-library/jest-dom": "^6.6.3",
"@testing-library/react": "^16.0.1",
"@types/react": "^19.1.8",
"@types/react-dom": "^19.1.6",
"@vitejs/plugin-react": "^4.6.0",
"autoprefixer": "^10.4.21",
"@testing-library/react": "^16.0.1",
"@testing-library/jest-dom": "^6.6.3",
"jsdom": "^26.0.0",
"vitest": "^2.0.5",
"postcss": "^8.5.6",
"tailwindcss": "^3.4.0",
"typescript": "~5.8.3",
"vite": "^7.0.4"
"vite": "^7.0.4",
"vitest": "^2.0.5"
}
}
109 changes: 109 additions & 0 deletions scripts/codex-sdk-runner.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
#!/usr/bin/env node
import fs from 'fs'
import { pathToFileURL, fileURLToPath } from 'url'

export async function runCodex(options = {}, io = defaultIO) {
const {
sessionId,
prompt = '',
workingDirectory,
sandboxMode,
model,
skipGitRepoCheck,
} = options

let CodexModule
const distPath = process.env.CODEX_SDK_DIST_PATH
if (distPath && fs.existsSync(distPath)) {
CodexModule = await import(pathToFileURL(distPath).href)
} else {
CodexModule = await import('@openai/codex-sdk')
}
const { Codex } = CodexModule

const codexOptions = workingDirectory ? { workingDirectory } : {}
const codex = new Codex(codexOptions)

const threadOptions = {
...(model ? { model } : {}),
...(sandboxMode ? { sandboxMode } : {}),
...(workingDirectory ? { workingDirectory } : {}),
skipGitRepoCheck: skipGitRepoCheck !== false,
}

const thread = codex.startThread(threadOptions)

try {
const { events } = await thread.runStreamed(prompt)
for await (const event of events) {
await io.write(
JSON.stringify({
sessionId,
content: JSON.stringify(event),
finished: false,
})
)
}

await io.write(
JSON.stringify({
sessionId,
content: '',
finished: true,
})
)
} catch (error) {
const message = error instanceof Error ? error.message : String(error)
const payload = JSON.stringify({ sessionId, error: message, finished: true })
if (io.writeError) {
await io.writeError(payload)
} else {
await io.write(payload)
}
}
}

async function readStdin() {
const chunks = []
for await (const chunk of process.stdin) {
chunks.push(chunk)
}
if (!chunks.length) return ''
return Buffer.concat(chunks.map((c) => (typeof c === 'string' ? Buffer.from(c) : c))).toString('utf8')
}

async function main() {
const stdin = await readStdin()
const argInput = process.argv[2]
const rawInput = stdin && stdin.trim().length > 0 ? stdin : argInput

if (!rawInput) {
throw new Error('Missing input payload for Codex SDK runner')
}

const payload = JSON.parse(rawInput)
await runCodex(payload)
}

const defaultIO = {
write: async (msg) => {
process.stdout.write(msg + '\n')
},
writeError: async (msg) => {
process.stderr.write(msg + '\n')
},
}

// Check if this script is being run directly
// Use fs.realpathSync to resolve symlinks (like /var -> /private/var on macOS)
const scriptPath = process.argv[1] ? fs.realpathSync(process.argv[1]) : null
const currentPath = import.meta.url ? fs.realpathSync(fileURLToPath(import.meta.url)) : null
const isMainModule = scriptPath && currentPath && scriptPath === currentPath

if (isMainModule) {
main().catch((err) => {
const message = err instanceof Error ? err.message : String(err)
process.stderr.write(JSON.stringify({ error: message }) + '\n')
process.exit(1)
})
}
2 changes: 2 additions & 0 deletions src-tauri/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions src-tauri/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ portable-pty = "0.8"
which = "6"
uuid = { version = "1.0", features = ["v4", "serde"] }
regex = "1.10"
async-trait = "0.1"
semver = "1"

[dev-dependencies]
tokio-test = "0.4"
Expand Down
Loading
Loading