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>
49 lines
2.3 KiB
JSON
49 lines
2.3 KiB
JSON
{
|
|
"name": "@boocode/server",
|
|
"version": "0.0.0",
|
|
"private": true,
|
|
"type": "module",
|
|
"main": "dist/index.js",
|
|
"exports": {
|
|
".": { "types": "./dist/index.d.ts", "default": "./dist/index.js" },
|
|
"./inference": { "types": "./dist/services/inference/index.d.ts", "default": "./dist/services/inference/index.js" },
|
|
"./tools": { "types": "./dist/services/tools.d.ts", "default": "./dist/services/tools.js" },
|
|
"./broker": { "types": "./dist/services/broker.d.ts", "default": "./dist/services/broker.js" },
|
|
"./compaction": { "types": "./dist/services/compaction.d.ts", "default": "./dist/services/compaction.js" },
|
|
"./model-context": { "types": "./dist/services/model-context.d.ts", "default": "./dist/services/model-context.js" },
|
|
"./system-prompt": { "types": "./dist/services/system-prompt.d.ts", "default": "./dist/services/system-prompt.js" },
|
|
"./agents": { "types": "./dist/services/agents.d.ts", "default": "./dist/services/agents.js" },
|
|
"./truncate": { "types": "./dist/services/truncate.d.ts", "default": "./dist/services/truncate.js" },
|
|
"./path-guard": { "types": "./dist/services/path_guard.d.ts", "default": "./dist/services/path_guard.js" },
|
|
"./file-ops": { "types": "./dist/services/file_ops.d.ts", "default": "./dist/services/file_ops.js" },
|
|
"./types": { "types": "./dist/types/api.d.ts", "default": "./dist/types/api.js" },
|
|
"./ws-frames": { "types": "./dist/types/ws-frames.d.ts", "default": "./dist/types/ws-frames.js" },
|
|
"./db": { "types": "./dist/db.d.ts", "default": "./dist/db.js" },
|
|
"./config": { "types": "./dist/config.d.ts", "default": "./dist/config.js" }
|
|
},
|
|
"scripts": {
|
|
"dev": "tsx watch src/index.ts",
|
|
"build": "tsc && node -e \"import('node:fs').then(fs=>fs.copyFileSync('src/schema.sql','dist/schema.sql'))\"",
|
|
"typecheck": "tsc --noEmit",
|
|
"test": "vitest run"
|
|
},
|
|
"dependencies": {
|
|
"@ai-sdk/openai-compatible": "^2.0.47",
|
|
"@fastify/static": "^7.0.4",
|
|
"@fastify/websocket": "^10.0.1",
|
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
"ai": "^6.0.190",
|
|
"fastify": "^4.28.1",
|
|
"postgres": "^3.4.4",
|
|
"ws": "^8.18.0",
|
|
"zod": "^3.23.8"
|
|
},
|
|
"devDependencies": {
|
|
"@types/node": "^20.14.10",
|
|
"@types/ws": "^8.5.10",
|
|
"tsx": "^4.16.2",
|
|
"typescript": "^5.5.0",
|
|
"vitest": "^3.2.4"
|
|
}
|
|
}
|