Files
aiturk-hermes-ide/apps/desktop/electron/is-hatti-settings.ts
T
yilsem 557e619499
Server CI and Windows package / verify (push) Successful in 2m42s
Server CI and Windows package / windows-package (push) Successful in 6m21s
feat(codex-link): AITURK work routing setting and beta.40
- Default routing rule (user decision, 15 Oct 2026): repeating/scheduled work goes to the AITURK IDE bot as a cron job; coding stays in Codex (itself or its subagents); 'Codex' or 'sen yap' keeps everything in Codex.
- Settings > Codex Bağlama: choice (recommended / send large work / never / custom text) with a text box and restore-default; written to bridge.json aiturk_hat.
- Bridge re-reads aiturk_hat when bridge.json changes: no restart. IDE apply keeps aiturk_hat instead of wiping it.
- Bridge version 20, IDE 1.0.0-beta.40. Jev untouched.
2026-10-15 02:18:18 +03:00

83 lines
2.7 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import fs from 'node:fs'
import path from 'node:path'
/** "AITURK iş hattı" choice, stored in the Codex bridge's `bridge.json` under `aiturk_hat`.
* The bridge re-reads the field when the file changes, so no restart is needed. */
export type IsHattiSecim = 'onerilen' | 'buyuk' | 'kapali' | 'ozel'
export interface IsHattiSettings {
secim: IsHattiSecim
talimat: string
}
const SECIMLER: IsHattiSecim[] = ['onerilen', 'buyuk', 'kapali', 'ozel']
const MAX_TALIMAT = 20000
export function readIsHatti(raw: null | string): IsHattiSettings {
try {
const hat = raw ? JSON.parse(raw)?.aiturk_hat : null
if (!hat || typeof hat !== 'object') {
return { secim: 'onerilen', talimat: '' }
}
const talimat = typeof hat.talimat === 'string' ? hat.talimat : ''
if (SECIMLER.includes(hat.secim)) {
return { secim: hat.secim, talimat }
}
// Written before this screen existed: same meaning the bridge gives it.
return { secim: hat.enabled === false ? 'kapali' : talimat.trim() ? 'ozel' : 'onerilen', talimat }
} catch {
return { secim: 'onerilen', talimat: '' }
}
}
export function writeIsHatti(raw: null | string, value: unknown): string {
const v = value as Partial<IsHattiSettings> | null
if (!v || !SECIMLER.includes(v.secim as IsHattiSecim)) throw new Error('Invalid choice')
const talimat = typeof v.talimat === 'string' ? v.talimat : ''
if (talimat.length > MAX_TALIMAT) throw new Error('Instruction too long')
if (v.secim === 'ozel' && !talimat.trim()) throw new Error('Custom instruction is empty')
let config: Record<string, unknown> = {}
try {
const parsed = raw ? JSON.parse(raw) : {}
config = parsed && typeof parsed === 'object' && !Array.isArray(parsed) ? parsed : {}
} catch {
throw new Error('bridge.json is not valid JSON')
}
const old = config.aiturk_hat && typeof config.aiturk_hat === 'object' ? (config.aiturk_hat as Record<string, unknown>) : {}
const hat: Record<string, unknown> = { ...old, secim: v.secim, talimat }
delete hat.enabled
return `${JSON.stringify({ ...config, aiturk_hat: hat }, null, 2)}\n`
}
export function createIsHattiStore(directory: string) {
const file = path.join(directory, 'bridge.json')
const read = () => (fs.existsSync(file) ? fs.readFileSync(file, 'utf8') : null)
return {
get: (): IsHattiSettings => readIsHatti(read()),
save(value: unknown): IsHattiSettings {
const text = writeIsHatti(read(), value)
fs.mkdirSync(directory, { recursive: true })
const tmp = `${file}.${process.pid}.tmp`
try {
fs.writeFileSync(tmp, text, 'utf8')
fs.renameSync(tmp, file)
} finally {
if (fs.existsSync(tmp)) fs.unlinkSync(tmp)
}
return readIsHatti(text)
}
}
}