fix(services): guard getters, use counter for memory, deduplicate listEntities

This commit is contained in:
chahinebrini 2026-06-25 12:30:14 +02:00
parent 908a89d772
commit a0af702344
6 changed files with 12 additions and 13 deletions

View File

@ -1,6 +1,8 @@
import { loadConfig } from '../../core/config.js';
import { suggestDelegation, autoDelegate } from '../../core/services/delegateService.js';
export async function delegate(cwd: string, options: { auto?: boolean } = {}): Promise<void> {
const config = loadConfig(cwd);
const suggestion = suggestDelegation(cwd);
if (!suggestion) {
console.log('No open tasks to delegate.');
@ -12,7 +14,7 @@ export async function delegate(cwd: string, options: { auto?: boolean } = {}): P
console.log(` Role: ${suggestion.role}`);
console.log(` Preferred agent: ${suggestion.preferredAgent}`);
if (options.auto) {
if (config.delegationMode === 'auto' || options.auto) {
autoDelegate(cwd);
console.log('Handoff created automatically.');
} else {

View File

@ -46,6 +46,7 @@ export function listDecisions(cwd: string): ReturnType<Index['list']> {
}
export function getDecision(cwd: string, id: string): { decision: Decision; body: string; filePath: string } {
if (!id) throw new Error('Decision ID is required');
const filePath = join(getEntityDir(cwd, 'decisions'), `${id}.md`);
const { frontmatter, body } = readEntity(filePath);
return { decision: DecisionSchema.parse(frontmatter), body, filePath };

View File

@ -48,6 +48,7 @@ export function listHandoffs(cwd: string): ReturnType<Index['list']> {
}
export function getHandoff(cwd: string, id: string): { handoff: Handoff; body: string; filePath: string } {
if (!id) throw new Error('Handoff ID is required');
const filePath = join(getEntityDir(cwd, 'handoffs'), `${id}.md`);
const { frontmatter, body } = readEntity(filePath);
return { handoff: HandoffSchema.parse(frontmatter), body, filePath };

View File

@ -1,12 +1,13 @@
import { join } from 'path';
import { getEntityDir } from '../paths.js';
import { getNextId } from '../counter.js';
import { writeEntity } from '../files.js';
import { MemorySchema, type Memory } from '../schema.js';
import { Index } from '../index.js';
export function addMemory(cwd: string, options: Partial<Memory> = {}): Memory {
const now = new Date().toISOString();
const id = `MEM-${Date.now()}`;
const id = getNextId(cwd, 'memory');
const memory: Memory = MemorySchema.parse({
id,
title: options.title ?? 'Memory',

View File

@ -37,6 +37,7 @@ export function listTasks(cwd: string, filters?: { status?: string; role?: strin
}
export function getTask(cwd: string, id: string): { task: Task; body: string; filePath: string } {
if (!id) throw new Error('Task ID is required');
const filePath = join(getEntityDir(cwd, 'tasks'), `${id}.md`);
const { frontmatter, body } = readEntity(filePath);
return { task: TaskSchema.parse(frontmatter), body, filePath };

View File

@ -1,7 +1,7 @@
import { readFileSync, writeFileSync, mkdirSync, existsSync, readdirSync } from 'fs';
import { writeFileSync, mkdirSync, existsSync } from 'fs';
import { join } from 'path';
import { getEntityDir, getStatusPath } from './paths.js';
import { readEntity, writeEntity } from './files.js';
import { readEntity, writeEntity, listEntities } from './files.js';
import { StatusSchema } from './schema.js';
export function generateStatus(cwd: string) {
@ -13,7 +13,7 @@ export function generateStatus(cwd: string) {
const blockedTasks: string[] = [];
if (existsSync(taskDir)) {
for (const file of listMdFiles(taskDir)) {
for (const file of listEntities(taskDir)) {
const { frontmatter } = readEntity(file);
if (frontmatter.status === 'open' || frontmatter.status === 'in_progress') {
activeTasks.push(String(frontmatter.id));
@ -42,15 +42,8 @@ export function generateStatus(cwd: string) {
return status;
}
function listMdFiles(dir: string): string[] {
if (!existsSync(dir)) return [];
return readdirSync(dir)
.filter((f) => f.endsWith('.md'))
.map((f) => join(dir, f));
}
function recentIds(dir: string, limit: number): string[] {
return listMdFiles(dir)
return listEntities(dir)
.map((f) => ({ file: f, ...readEntity(f) }))
.sort((a, b) => String(b.frontmatter.createdAt).localeCompare(String(a.frontmatter.createdAt)))
.slice(0, limit)