feat: initial public release (MAESTRO)

This commit is contained in:
oss-sync
2026-06-03 05:08:00 +00:00
commit f5c7666f6b
823 changed files with 184150 additions and 0 deletions
+190
View File
@@ -0,0 +1,190 @@
/**
* notes.ts — SearchNotes / ReadNote / WriteNote tools
*
* Agents can search, read, and write shared knowledge notes
* stored under data/users/{userId}/notes/{folder}/{file}.md.
*/
import { ToolDef } from '../../llm/openai-compat.js';
import { NotesService } from '../../notes/notes-service.js';
import type { ToolContext, ToolResult } from './core.js';
export interface NotesToolContext {
notesService: NotesService;
user: Express.User;
}
export const TOOL_DEFS: Record<string, ToolDef> = {
SearchNotes: {
type: 'function',
function: {
name: 'SearchNotes',
description:
'購読中の knowledge notes を全文検索 (FTS5)。' +
'詳細は ReadToolDoc({ name: "SearchNotes" }) で取得可能。',
parameters: {
type: 'object',
properties: {
query: {
type: 'string',
description: '検索クエリ文字列(FTS5 構文)',
},
folder: {
type: 'string',
description: '特定フォルダーのみに絞り込む(省略可)',
},
limit: {
type: 'integer',
description: '最大取得件数(デフォルト 10、最大 100)',
},
},
required: ['query'],
},
},
},
ReadNote: {
type: 'function',
function: {
name: 'ReadNote',
description:
'特定 note の全文(frontmatter + 本文)を取得。可視性チェックあり。' +
'詳細は ReadToolDoc({ name: "ReadNote" }) で取得可能。',
parameters: {
type: 'object',
properties: {
owner_id: {
type: 'string',
description: 'note の所有者 user ID',
},
folder: {
type: 'string',
description: 'フォルダー名',
},
file_name: {
type: 'string',
description: 'ファイル名(例: foo.md)',
},
},
required: ['owner_id', 'folder', 'file_name'],
},
},
},
WriteNote: {
type: 'function',
function: {
name: 'WriteNote',
description:
'自分の notes/{folder}/{file}.md に Markdown note を書き込む(作成 / 更新)。' +
'詳細は ReadToolDoc({ name: "WriteNote" }) で取得可能。',
parameters: {
type: 'object',
properties: {
folder: {
type: 'string',
description: 'フォルダー名(英数字・. - _ のみ)',
},
file_name: {
type: 'string',
description: 'ファイル名(.md で終わる)',
},
content: {
type: 'string',
description: 'YAML frontmatter を含む完全な Markdown 内容',
},
},
required: ['folder', 'file_name', 'content'],
},
},
},
};
/**
* Execute a notes tool.
* Returns null when the tool name is not handled (allows index.ts to fall through).
*/
export async function executeNotesTools(
name: string,
args: Record<string, unknown>,
ctx: NotesToolContext | ToolContext,
): Promise<ToolResult | null> {
// Extract notes-specific context. When called via index.ts the ctx is a full
// ToolContext; when called from tests it's a minimal NotesToolContext.
const notesCtx = ctx as NotesToolContext & ToolContext;
const notesService = notesCtx.notesService;
if (!notesService) return null;
// Reconstruct a minimal Express.User from ToolContext fields if needed.
const user: Express.User = notesCtx.user ?? {
id: notesCtx.userId ?? '',
role: (notesCtx as ToolContext).notesUserRole ?? 'user',
orgIds: (notesCtx as ToolContext).notesUserOrgIds ?? [],
email: '',
name: null,
avatarUrl: null,
status: 'active',
defaultVisibility: 'private',
defaultVisibilityOrgId: null,
};
switch (name) {
case 'SearchNotes': {
const rawQuery = String(args['query'] ?? '');
// Wrap in FTS5 phrase quotes to avoid query syntax injection
const safeQuery = '"' + rawQuery.replace(/"/g, '""') + '"';
const rows = notesService.searchNotes({
user,
query: safeQuery,
folder: args['folder'] ? String(args['folder']) : undefined,
limit: args['limit'] ? Math.min(parseInt(String(args['limit']), 10), 100) : 10,
consumerSubscribed: true,
});
if (rows.length === 0) {
return { output: 'No notes found matching the query.', isError: false };
}
const lines = rows.map(
(r) =>
`- ${r.owner_id}/${r.folder}/${r.file_name}` +
(r.title ? `: ${r.title}` : '') +
(r.tags_json && r.tags_json !== '[]' ? ` [tags: ${r.tags_json}]` : '')
);
return { output: lines.join('\n'), isError: false };
}
case 'ReadNote': {
const ownerId = String(args['owner_id'] ?? '');
const folder = String(args['folder'] ?? '');
const fileName = String(args['file_name'] ?? '');
const out = notesService.getCrossUserNote({ user, ownerId, folder, fileName });
if (!out) {
return { output: 'Note not found or not accessible.', isError: true };
}
return { output: out.content, isError: false };
}
case 'WriteNote': {
try {
const result = notesService.writeNote({
ownerId: user.id,
folder: String(args['folder'] ?? ''),
fileName: String(args['file_name'] ?? ''),
content: String(args['content'] ?? ''),
});
return {
output: `Wrote ${result.row.owner_id}/${result.row.folder}/${result.row.file_name}`,
isError: false,
};
} catch (err) {
return { output: `WriteNote error: ${(err as Error).message}`, isError: true };
}
}
default:
return null;
}
}
// Re-export as executeTool for ToolModule interface compatibility
export const executeTool = executeNotesTools;