final gaps: .gitattributes, .dockerignore, structured logger, clean stray files
This commit is contained in:
parent
be7354ee38
commit
e92eaeaefc
|
|
@ -0,0 +1,13 @@
|
|||
node_modules/
|
||||
.git/
|
||||
.gitignore
|
||||
.gitattributes
|
||||
*.md
|
||||
src/
|
||||
tsconfig.json
|
||||
vitest.config.ts
|
||||
.env
|
||||
.env.local
|
||||
LOGS/
|
||||
TEMP/
|
||||
.familiar-test
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
# Auto-detect text files and normalize to LF
|
||||
* text=auto
|
||||
42
CLAUDE.md
42
CLAUDE.md
|
|
@ -1,42 +0,0 @@
|
|||
# fable-agent — Project Instructions
|
||||
|
||||
## Project
|
||||
TypeScript self-improving agent system implementing the Fable 5 compound stack. All model calls route through the local proxy at `localhost:18901`.
|
||||
|
||||
## Build / Test
|
||||
- `npm run build`
|
||||
- `node dist/index.js demo`
|
||||
- `npx tsc --noEmit`
|
||||
|
||||
## Model Routing
|
||||
|
||||
All model calls route through `http://localhost:18901/v1`.
|
||||
|
||||
### Working verified routes
|
||||
| Alias | Provider | Notes |
|
||||
|-------|----------|-------|
|
||||
| `go-dsv4-flash` | Go API | Primary cheap/fast route |
|
||||
| `claude-sonnet-4-6` | Zen API | Code review, bounded subtasks |
|
||||
| `fi-gemini` | Free provider | Gemini free tier |
|
||||
| `fi-mistral` | Free provider | Mistral free tier |
|
||||
| `nemotron-3-ultra-free` | Free provider | Nvidia free tier |
|
||||
|
||||
### Provider groups
|
||||
- **Go API**: `go-*` models (12 models, $10/mo flat)
|
||||
- **Zen API**: `claude-*`, `gpt-*`, `gemini-*`, etc.
|
||||
- **CrofAI**: fallback provider on 429
|
||||
- **Free providers (`fi-*`)**: free-tier models
|
||||
|
||||
The proxy currently exposes 58 model aliases across these providers. The model router tracks 35 models with real pricing.
|
||||
|
||||
## Proxy Configuration
|
||||
- Proxy config: `~/.config/grok-proxy.cjs`
|
||||
- Provider keys: `~/.config/infer/keys.env`, `~/.config/fi/keys.env`
|
||||
- Restart proxy after config changes.
|
||||
|
||||
## Project Structure
|
||||
- CLI: `dist/index.js`
|
||||
- Source: `src/`
|
||||
- State: `~/.fable-agent/`
|
||||
- Skills: `SKILLS/`
|
||||
- Phases: `PHASES/`
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
/**
|
||||
* Structured logger — replaces console.log across the system.
|
||||
* Writes JSONL logs for machine parsing + human-readable terminal output.
|
||||
*/
|
||||
|
||||
import * as fs from "node:fs";
|
||||
import * as path from "node:path";
|
||||
|
||||
export type LogLevel = "debug" | "info" | "warn" | "error";
|
||||
|
||||
const LOG_DIR = path.join(
|
||||
process.env.FABLE_DATA_DIR || process.env.HOME || process.env.USERPROFILE || ".", ".fable-agent", "logs"
|
||||
);
|
||||
|
||||
const COLORS: Record<LogLevel, string> = {
|
||||
debug: "\x1b[90m", // gray
|
||||
info: "\x1b[36m", // cyan
|
||||
warn: "\x1b[33m", // yellow
|
||||
error: "\x1b[31m", // red
|
||||
};
|
||||
const RESET = "\x1b[0m";
|
||||
|
||||
class Logger {
|
||||
private logFile: string;
|
||||
|
||||
constructor() {
|
||||
try {
|
||||
if (!fs.existsSync(LOG_DIR)) fs.mkdirSync(LOG_DIR, { recursive: true });
|
||||
} catch {}
|
||||
this.logFile = path.join(LOG_DIR, `${new Date().toISOString().slice(0, 10)}.jsonl`);
|
||||
}
|
||||
|
||||
private write(level: LogLevel, message: string, data?: Record<string, unknown>): void {
|
||||
const entry = {
|
||||
timestamp: new Date().toISOString(),
|
||||
level,
|
||||
message,
|
||||
...data,
|
||||
};
|
||||
|
||||
// JSONL for machine parsing
|
||||
try {
|
||||
fs.appendFileSync(this.logFile, JSON.stringify(entry) + "\n", "utf-8");
|
||||
} catch {}
|
||||
|
||||
// Colored terminal output
|
||||
const prefix = level === "error" ? "✗" : level === "warn" ? "⚠" : level === "debug" ? "·" : "✓";
|
||||
if (level !== "debug" || process.env.FABLE_DEBUG) {
|
||||
process.stdout.write(`${COLORS[level]}${prefix}${RESET} ${message}\n`);
|
||||
}
|
||||
}
|
||||
|
||||
info(message: string, data?: Record<string, unknown>): void { this.write("info", message, data); }
|
||||
warn(message: string, data?: Record<string, unknown>): void { this.write("warn", message, data); }
|
||||
error(message: string, data?: Record<string, unknown>): void { this.write("error", message, data); }
|
||||
debug(message: string, data?: Record<string, unknown>): void { this.write("debug", message, data); }
|
||||
}
|
||||
|
||||
export const logger = new Logger();
|
||||
Loading…
Reference in New Issue