Phase 2 of v2.0. BooCoder is now a functional write-capable chatbot.
Write-path guard: resolveWritePath() uses resolve() (no realpath — files may
not exist for creates) + prefix-check + secret-file deny list (.env, *.pem,
id_rsa*, etc.). 23 unit tests cover traversal attacks.
Pending-changes service: queueEdit/Create/Delete → applyOne/All →
rejectOne/All → rewindOne. Edit diffs stored as JSON {old, new}. All writes
queue before touching disk; apply re-validates the path guard.
5 write tools: edit_file, create_file, delete_file, apply_pending, rewind.
Registered alongside 25 read-only tools from BooChat (30 total, alpha-sorted).
Write tools use a module-level inference context for sql+sessionId injection.
Inference loop via workspace dependency: apps/coder imports
createInferenceRunner, createBroker, ALL_TOOLS from @boocode/server (dist/).
apps/server gains declaration: true + exports map with typed subpath entries.
No code duplication — one inference engine shared by both apps.
API routes: POST /api/sessions/:id/messages (user msg → inference), POST stop,
GET/POST pending-changes CRUD (5 endpoints), WebSocket session streaming.
Dockerfile updated to build apps/server first (coder depends on its .d.ts).
Health endpoint reports tool count: {"ok":true,"db":true,"tools":30}.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
37 lines
985 B
TypeScript
37 lines
985 B
TypeScript
import type { Sql } from '../../db.js';
|
|
|
|
/**
|
|
* Module-level inference context for write tools.
|
|
*
|
|
* Set via `setInferenceContext()` before each inference run starts.
|
|
* Write tools read it via `getInferenceContext()` during execute.
|
|
* Same pattern as BooChat's `loadConfig()` singleton — tools need
|
|
* ambient state that can't be threaded through the tool-phase execute
|
|
* signature (which is `execute(input, projectRoot, extraRoots?)`).
|
|
*/
|
|
|
|
export interface InferenceContext {
|
|
sql: Sql;
|
|
sessionId: string;
|
|
taskId: string | null;
|
|
}
|
|
|
|
let current: InferenceContext | null = null;
|
|
|
|
export function setInferenceContext(ctx: InferenceContext): void {
|
|
current = ctx;
|
|
}
|
|
|
|
export function clearInferenceContext(): void {
|
|
current = null;
|
|
}
|
|
|
|
export function getInferenceContext(): InferenceContext {
|
|
if (!current) {
|
|
throw new Error(
|
|
'Write tool called outside inference context — setInferenceContext() was not called before this run',
|
|
);
|
|
}
|
|
return current;
|
|
}
|