Skip to content

Commit 494a998

Browse files
author
linyuan.yang
committed
todo service
1 parent 6c6c721 commit 494a998

6 files changed

Lines changed: 30 additions & 14 deletions

File tree

0 Bytes
Binary file not shown.

packages/sbot/src/Core/Config.ts

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -515,17 +515,14 @@ class Config {
515515
getAgentSkillsPath(agentName: string) {
516516
return this.getConfigPath(`agents/${agentName}/skills`, true)
517517
}
518-
getSessionSkillsPath(dbSessionId: string) {
519-
return this.getConfigPath(`sessions/${dbSessionId}/skills`, true)
520-
}
521518
getAgentInsightsPath(agentName: string) {
522519
return this.getConfigPath(`agents/${agentName}/insights`, true)
523520
}
524-
getSessionInsightsPath(dbSessionId: string) {
525-
return this.getConfigPath(`sessions/${dbSessionId}/insights`, true)
521+
getSessionInsightsPath(sessionId: string) {
522+
return this.getConfigPath(`sessions/${sessionId}/insights`, true)
526523
}
527-
getSessionTodoPath(dbSessionId: string) {
528-
return this.getConfigPath(`sessions/${dbSessionId}/todos.json`)
524+
getSessionTodoPath(sessionId: string) {
525+
return this.getConfigPath(`sessions/${sessionId}/todos.json`)
529526
}
530527
getAgentMcpServers(agentName: string): MCPServers {
531528
const mcpConfigPath = this.getConfigPath(`agents/${agentName}/mcp.json`);

packages/scorpio.ai/src/Insight/Extractor/InsightExtractor.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,8 @@ export class InsightExtractor implements IInsightExtractor {
4545
const { results } = await this.modelService.invokeStructured<{ results: ExtractedInsight[] }>(InsightExtractionSchema, messages);
4646
return results;
4747
} catch (error: any) {
48-
this.logger?.warn(`Insight extraction failed: ${error.message}`);
48+
const detail = error?.response?.data ? ` body=${JSON.stringify(error.response.data)}` : '';
49+
this.logger?.warn(`Insight extraction failed: ${error.message}${detail}`);
4950
return [];
5051
}
5152
}

packages/scorpio.ai/src/Model/OpenAIModelService.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,8 @@ export class OpenAIModelService implements IModelService {
5353

5454
async invokeStructured<T = any>(schema: any, prompt: string | ChatMessage[], options?: { signal?: AbortSignal }): Promise<T> {
5555
const input = typeof prompt === 'string' ? prompt : toBaseMessages(prompt);
56-
return this.model!.withStructuredOutput(schema).invoke(input, options?.signal ? { signal: options.signal } : undefined) as Promise<T>;
56+
const structured = this.model!.withStructuredOutput(schema, { method: "functionCalling" });
57+
return structured.invoke(input, options?.signal ? { signal: options.signal } : undefined) as Promise<T>;
5758
}
5859

5960
async stream(messages: string | ChatMessage[], options?: { signal?: AbortSignal }): Promise<AsyncIterable<ChatMessage>> {

packages/scorpio.ai/src/Todo/Extractor/TodoExtractor.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,8 @@ export class TodoExtractor implements ITodoExtractor {
5454
);
5555
return actions;
5656
} catch (error: any) {
57-
this.logger?.warn(`Todo extraction failed: ${error.message}`);
57+
const detail = error?.response?.data ? ` body=${JSON.stringify(error.response.data)}` : '';
58+
this.logger?.warn(`Todo extraction failed: ${error.message}${detail}`);
5859
return [];
5960
}
6061
}

packages/scorpio.ai/src/Todo/TodoService.ts

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,23 +25,27 @@ export class TodoService implements ITodoService {
2525
@inject(ILoggerService, { optional: true }) loggerService?: ILoggerService,
2626
) {
2727
this.logger = loggerService?.getLogger("TodoService");
28+
this.logger?.debug(`TodoService initialized: filePath=${filePath}, extractor=${!!extractor}`);
2829
}
2930

3031
getToolDescs(): TodoToolDescs {
3132
return this.toolDescs;
3233
}
3334

3435
async list(filter?: TodoListFilter): Promise<Todo[]> {
36+
this.logger?.debug(`list called: filter=${JSON.stringify(filter ?? {})}`);
3537
const data = await this.read();
3638
const status = filter?.status ?? TodoStatus.Pending;
3739
let items = data.todos;
3840
if (status !== 'all') items = items.filter(t => t.status === status);
3941
if (filter?.priority) items = items.filter(t => t.priority === filter.priority);
40-
return items.sort((a, b) => {
42+
const result = items.sort((a, b) => {
4143
const dp = PRIORITY_ORDER[a.priority] - PRIORITY_ORDER[b.priority];
4244
if (dp !== 0) return dp;
4345
return a.createdAt.localeCompare(b.createdAt);
4446
});
47+
this.logger?.debug(`list result: total=${data.todos.length}, filtered=${result.length}`);
48+
return result;
4549
}
4650

4751
async formatForLLM(filter?: TodoListFilter): Promise<string> {
@@ -59,14 +63,19 @@ export class TodoService implements ITodoService {
5963
}
6064

6165
async extractFromConversation(userMessage: string, assistantMessages?: string[]): Promise<void> {
62-
if (!this.extractor) return;
66+
if (!this.extractor) {
67+
this.logger?.debug(`extractFromConversation skipped: no extractor configured`);
68+
return;
69+
}
70+
this.logger?.debug(`extractFromConversation start: userMsgLen=${userMessage.length}, assistantMsgs=${assistantMessages?.length ?? 0}`);
6371
try {
6472
const data = await this.read();
6573
const actions = await this.extractor.extract(
6674
userMessage,
6775
assistantMessages ?? [],
6876
data.todos,
6977
);
78+
this.logger?.debug(`extractor returned ${actions.length} action(s)`);
7079
if (actions.length === 0) return;
7180

7281
for (const a of actions) {
@@ -106,6 +115,7 @@ export class TodoService implements ITodoService {
106115
}
107116

108117
await this.write(data);
118+
this.logger?.debug(`extractFromConversation done: applied ${actions.length} action(s)`);
109119
} catch (error: any) {
110120
this.logger?.error(`Todo extraction failed: ${error.message}`);
111121
}
@@ -115,12 +125,17 @@ export class TodoService implements ITodoService {
115125
try {
116126
const buf = await fsp.readFile(this.filePath, 'utf-8');
117127
const parsed = JSON.parse(buf) as Partial<TodoFile>;
118-
return {
128+
const file = {
119129
todos: Array.isArray(parsed.todos) ? parsed.todos : [],
120130
nextId: typeof parsed.nextId === 'number' ? parsed.nextId : 1,
121131
};
132+
this.logger?.debug(`read: ${file.todos.length} todo(s), nextId=${file.nextId}`);
133+
return file;
122134
} catch (e: any) {
123-
if (e.code === 'ENOENT') return { todos: [], nextId: 1 };
135+
if (e.code === 'ENOENT') {
136+
this.logger?.debug(`read: file not found at ${this.filePath}, returning empty`);
137+
return { todos: [], nextId: 1 };
138+
}
124139
this.logger?.warn(`Failed to read todos at ${this.filePath}: ${e.message}; returning empty`);
125140
return { todos: [], nextId: 1 };
126141
}
@@ -133,6 +148,7 @@ export class TodoService implements ITodoService {
133148
try {
134149
await fsp.writeFile(tmp, JSON.stringify(data, null, 2), 'utf-8');
135150
await fsp.rename(tmp, this.filePath);
151+
this.logger?.debug(`write: ${data.todos.length} todo(s), nextId=${data.nextId} -> ${this.filePath}`);
136152
} catch (e) {
137153
await fsp.unlink(tmp).catch(() => {});
138154
throw e;

0 commit comments

Comments
 (0)