feat: initial public release (MAESTRO)
This commit is contained in:
@@ -0,0 +1,672 @@
|
||||
import { ToolDef } from '../../llm/openai-compat.js';
|
||||
import { logger } from '../../logger.js';
|
||||
import {
|
||||
ToolContext,
|
||||
ToolResult,
|
||||
ToolsConfig,
|
||||
ALL_TOOL_DEFS,
|
||||
getToolDefs as getCoreToolDefs,
|
||||
executeCoreTools,
|
||||
} from './core.js';
|
||||
import { saveRawData, logRawDownload, RAW_SAVE_TOOLS, RAW_LOG_ONLY_TOOLS } from './raw-save.js';
|
||||
import { saveStructuredBlocks } from './structured-blocks.js';
|
||||
import type { McpAggregator } from '../../mcp/aggregator.js';
|
||||
import type { McpRuntimeConfig } from '../../mcp/config.js';
|
||||
|
||||
export type { ToolContext, ToolResult, ToolsConfig };
|
||||
|
||||
let _mcpAggregator: McpAggregator | null = null;
|
||||
export function setMcpAggregator(agg: McpAggregator | null): void {
|
||||
_mcpAggregator = agg;
|
||||
}
|
||||
|
||||
type ExecuteCtxWithMcp = ToolContext & {
|
||||
ownerId?: string | null;
|
||||
jobId?: string | null;
|
||||
mcpConfig?: McpRuntimeConfig;
|
||||
mcpQuotaState?: { files: number; bytes: number };
|
||||
};
|
||||
|
||||
// 外部モジュール(他チームが実装)のインターフェース型
|
||||
interface ToolModule {
|
||||
TOOL_DEFS: Record<string, ToolDef>;
|
||||
executeTool(name: string, input: Record<string, unknown>, ctx: ToolContext): Promise<ToolResult | null>;
|
||||
}
|
||||
|
||||
// 外部モジュールを動的にロード(存在しない場合は null)
|
||||
async function tryLoadModule(specifier: string): Promise<ToolModule | null> {
|
||||
try {
|
||||
const mod = await import(specifier) as ToolModule;
|
||||
return mod;
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// 外部モジュールのキャッシュ
|
||||
let _webModule: ToolModule | null | undefined = undefined;
|
||||
let _imageModule: ToolModule | null | undefined = undefined;
|
||||
let _dataModule: ToolModule | null | undefined = undefined;
|
||||
let _officeModule: ToolModule | null | undefined = undefined;
|
||||
let _reviewModule: ToolModule | null | undefined = undefined;
|
||||
let _xModule: ToolModule | null | undefined = undefined;
|
||||
let _orchestrationModule: ToolModule | null | undefined = undefined;
|
||||
let _browserModule: ToolModule | null | undefined = undefined;
|
||||
let _mapsModule: ToolModule | null | undefined = undefined;
|
||||
let _youtubeModule: ToolModule | null | undefined = undefined;
|
||||
let _piecesModule: ToolModule | null | undefined = undefined;
|
||||
let _amazonModule: ToolModule | null | undefined = undefined;
|
||||
let _speechModule: ToolModule | null | undefined = undefined;
|
||||
let _checklistModule: ToolModule | null | undefined = undefined;
|
||||
let _knowledgeModule: ToolModule | null | undefined = undefined;
|
||||
let _msLearnModule: ToolModule | null | undefined = undefined;
|
||||
let _slideModule: ToolModule | null | undefined = undefined;
|
||||
let _userFolderModule: ToolModule | null | undefined = undefined;
|
||||
|
||||
async function getWebModule(): Promise<ToolModule | null> {
|
||||
if (_webModule === undefined) {
|
||||
_webModule = await tryLoadModule('./web.js');
|
||||
if (_webModule) logger.debug('[tools/index] web module loaded');
|
||||
}
|
||||
return _webModule;
|
||||
}
|
||||
|
||||
async function getImageModule(): Promise<ToolModule | null> {
|
||||
if (_imageModule === undefined) {
|
||||
_imageModule = await tryLoadModule('./image.js');
|
||||
if (_imageModule) logger.debug('[tools/index] image module loaded');
|
||||
}
|
||||
return _imageModule;
|
||||
}
|
||||
|
||||
async function getDataModule(): Promise<ToolModule | null> {
|
||||
if (_dataModule === undefined) {
|
||||
_dataModule = await tryLoadModule('./data.js');
|
||||
if (_dataModule) logger.debug('[tools/index] data module loaded');
|
||||
}
|
||||
return _dataModule;
|
||||
}
|
||||
|
||||
async function getOfficeModule(): Promise<ToolModule | null> {
|
||||
if (_officeModule === undefined) {
|
||||
_officeModule = await tryLoadModule('./office.js');
|
||||
if (_officeModule) logger.debug('[tools/index] office module loaded');
|
||||
}
|
||||
return _officeModule;
|
||||
}
|
||||
|
||||
async function getReviewModule(): Promise<ToolModule | null> {
|
||||
if (_reviewModule === undefined) {
|
||||
_reviewModule = await tryLoadModule('./review.js');
|
||||
if (_reviewModule) logger.debug('[tools/index] review module loaded');
|
||||
}
|
||||
return _reviewModule;
|
||||
}
|
||||
|
||||
async function getXModule(): Promise<ToolModule | null> {
|
||||
if (_xModule === undefined) {
|
||||
_xModule = await tryLoadModule('./x.js');
|
||||
if (_xModule) logger.debug('[tools/index] x module loaded');
|
||||
}
|
||||
return _xModule;
|
||||
}
|
||||
|
||||
async function getOrchestrationModule(): Promise<ToolModule | null> {
|
||||
if (_orchestrationModule === undefined) {
|
||||
_orchestrationModule = await tryLoadModule('./orchestration.js');
|
||||
if (_orchestrationModule) logger.debug('[tools/index] orchestration module loaded');
|
||||
}
|
||||
return _orchestrationModule;
|
||||
}
|
||||
|
||||
async function getBrowserModule(): Promise<ToolModule | null> {
|
||||
if (_browserModule === undefined) {
|
||||
_browserModule = await tryLoadModule('./browser.js');
|
||||
if (_browserModule) logger.debug('[tools/index] browser module loaded');
|
||||
}
|
||||
return _browserModule;
|
||||
}
|
||||
|
||||
async function getMapsModule(): Promise<ToolModule | null> {
|
||||
if (_mapsModule === undefined) {
|
||||
_mapsModule = await tryLoadModule('./maps.js');
|
||||
if (_mapsModule) logger.debug('[tools/index] maps module loaded');
|
||||
}
|
||||
return _mapsModule;
|
||||
}
|
||||
|
||||
async function getYoutubeModule(): Promise<ToolModule | null> {
|
||||
if (_youtubeModule === undefined) {
|
||||
_youtubeModule = await tryLoadModule('./youtube.js');
|
||||
if (_youtubeModule) logger.debug('[tools/index] youtube module loaded');
|
||||
}
|
||||
return _youtubeModule;
|
||||
}
|
||||
|
||||
async function getPiecesModule(): Promise<ToolModule | null> {
|
||||
if (_piecesModule === undefined) {
|
||||
_piecesModule = await tryLoadModule('./pieces.js');
|
||||
if (_piecesModule) logger.debug('[tools/index] pieces module loaded');
|
||||
}
|
||||
return _piecesModule;
|
||||
}
|
||||
|
||||
async function getAmazonModule(): Promise<ToolModule | null> {
|
||||
if (_amazonModule === undefined) {
|
||||
_amazonModule = await tryLoadModule('./amazon.js');
|
||||
if (_amazonModule) logger.debug('[tools/index] amazon module loaded');
|
||||
}
|
||||
return _amazonModule;
|
||||
}
|
||||
|
||||
async function getSpeechModule(): Promise<ToolModule | null> {
|
||||
if (_speechModule === undefined) {
|
||||
_speechModule = await tryLoadModule('./speech.js');
|
||||
if (_speechModule) logger.debug('[tools/index] speech module loaded');
|
||||
}
|
||||
return _speechModule;
|
||||
}
|
||||
|
||||
async function getChecklistModule(): Promise<ToolModule | null> {
|
||||
if (_checklistModule === undefined) {
|
||||
_checklistModule = await tryLoadModule('./checklist.js');
|
||||
if (_checklistModule) logger.debug('[tools/index] checklist module loaded');
|
||||
}
|
||||
return _checklistModule;
|
||||
}
|
||||
|
||||
async function getKnowledgeModule(): Promise<ToolModule | null> {
|
||||
if (_knowledgeModule === undefined) {
|
||||
_knowledgeModule = await tryLoadModule('./knowledge.js');
|
||||
if (_knowledgeModule) logger.debug('[tools/index] knowledge module loaded');
|
||||
}
|
||||
return _knowledgeModule;
|
||||
}
|
||||
|
||||
async function getSlideModule(): Promise<ToolModule | null> {
|
||||
if (_slideModule === undefined) {
|
||||
_slideModule = await tryLoadModule('./slide.js');
|
||||
if (_slideModule) logger.debug('[tools/index] slide module loaded');
|
||||
}
|
||||
return _slideModule;
|
||||
}
|
||||
|
||||
async function getMsLearnModule(): Promise<ToolModule | null> {
|
||||
if (_msLearnModule === undefined) {
|
||||
_msLearnModule = await tryLoadModule('./ms-learn.js');
|
||||
if (_msLearnModule) logger.debug('[tools/index] ms-learn module loaded');
|
||||
}
|
||||
return _msLearnModule;
|
||||
}
|
||||
|
||||
let _docsModule: ToolModule | null | undefined;
|
||||
async function getDocsModule(): Promise<ToolModule | null> {
|
||||
if (_docsModule === undefined) {
|
||||
_docsModule = await tryLoadModule('./docs.js');
|
||||
if (_docsModule) logger.debug('[tools/index] docs module loaded');
|
||||
}
|
||||
return _docsModule;
|
||||
}
|
||||
|
||||
let _missionModule: ToolModule | null | undefined;
|
||||
async function getMissionModule(): Promise<ToolModule | null> {
|
||||
if (_missionModule === undefined) {
|
||||
_missionModule = await tryLoadModule('./mission.js');
|
||||
if (_missionModule) logger.debug('[tools/index] mission module loaded');
|
||||
}
|
||||
return _missionModule;
|
||||
}
|
||||
|
||||
async function getUserFolderModule(): Promise<ToolModule | null> {
|
||||
if (_userFolderModule === undefined) {
|
||||
_userFolderModule = await tryLoadModule('./user-folder.js');
|
||||
if (_userFolderModule) logger.debug('[tools/index] user-folder module loaded');
|
||||
}
|
||||
return _userFolderModule;
|
||||
}
|
||||
|
||||
let _brainstormModule: ToolModule | null | undefined;
|
||||
async function getBrainstormModule(): Promise<ToolModule | null> {
|
||||
if (_brainstormModule === undefined) {
|
||||
_brainstormModule = await tryLoadModule('./brainstorm.js');
|
||||
if (_brainstormModule) logger.debug('[tools/index] brainstorm module loaded');
|
||||
}
|
||||
return _brainstormModule;
|
||||
}
|
||||
|
||||
let _appDocsModule: ToolModule | null | undefined;
|
||||
async function getAppDocsModule(): Promise<ToolModule | null> {
|
||||
if (_appDocsModule === undefined) {
|
||||
_appDocsModule = await tryLoadModule('./app-docs.js');
|
||||
if (_appDocsModule) logger.debug('[tools/index] app-docs module loaded');
|
||||
}
|
||||
return _appDocsModule;
|
||||
}
|
||||
|
||||
let _sshModule: ToolModule | null | undefined;
|
||||
async function getSshModule(): Promise<ToolModule | null> {
|
||||
if (_sshModule === undefined) {
|
||||
_sshModule = await tryLoadModule('./ssh.js');
|
||||
if (_sshModule) logger.debug('[tools/index] ssh module loaded');
|
||||
}
|
||||
return _sshModule;
|
||||
}
|
||||
|
||||
let _sshConsoleModule: ToolModule | null | undefined;
|
||||
async function getSshConsoleModule(): Promise<ToolModule | null> {
|
||||
if (_sshConsoleModule === undefined) {
|
||||
_sshConsoleModule = await tryLoadModule('./ssh-console.js');
|
||||
if (_sshConsoleModule) logger.debug('[tools/index] ssh-console module loaded');
|
||||
}
|
||||
return _sshConsoleModule;
|
||||
}
|
||||
|
||||
let _notesModule: ToolModule | null | undefined;
|
||||
async function getNotesModule(): Promise<ToolModule | null> {
|
||||
if (_notesModule === undefined) {
|
||||
_notesModule = await tryLoadModule('./notes.js');
|
||||
if (_notesModule) logger.debug('[tools/index] notes module loaded');
|
||||
}
|
||||
return _notesModule;
|
||||
}
|
||||
|
||||
let _dashboardModule: ToolModule | null | undefined = undefined;
|
||||
async function getDashboardModule(): Promise<ToolModule | null> {
|
||||
if (_dashboardModule === undefined) {
|
||||
_dashboardModule = await tryLoadModule('./dashboard.js');
|
||||
if (_dashboardModule) logger.debug('[tools/index] dashboard module loaded');
|
||||
}
|
||||
return _dashboardModule;
|
||||
}
|
||||
|
||||
/**
|
||||
* 全モジュールのツール定義を統合して返す。
|
||||
* allowedTools と editAllowed に応じてフィルタリングする。
|
||||
*/
|
||||
export async function getToolDefs(
|
||||
allowedTools: string[],
|
||||
editAllowed: boolean,
|
||||
options?: { vlmEnabled?: boolean; ownerId?: string | null; mcpDisabled?: boolean },
|
||||
): Promise<ToolDef[]> {
|
||||
// 全ツール定義を収集
|
||||
const allDefs: Record<string, ToolDef> = { ...ALL_TOOL_DEFS };
|
||||
|
||||
const webMod = await getWebModule();
|
||||
if (webMod) Object.assign(allDefs, webMod.TOOL_DEFS);
|
||||
|
||||
const imageMod = await getImageModule();
|
||||
if (imageMod) Object.assign(allDefs, imageMod.TOOL_DEFS);
|
||||
|
||||
const dataMod = await getDataModule();
|
||||
if (dataMod) Object.assign(allDefs, dataMod.TOOL_DEFS);
|
||||
|
||||
const officeMod = await getOfficeModule();
|
||||
if (officeMod) Object.assign(allDefs, officeMod.TOOL_DEFS);
|
||||
|
||||
const reviewMod = await getReviewModule();
|
||||
if (reviewMod) Object.assign(allDefs, reviewMod.TOOL_DEFS);
|
||||
|
||||
const xMod = await getXModule();
|
||||
if (xMod) Object.assign(allDefs, xMod.TOOL_DEFS);
|
||||
|
||||
const orchestrationMod = await getOrchestrationModule();
|
||||
if (orchestrationMod) Object.assign(allDefs, orchestrationMod.TOOL_DEFS);
|
||||
|
||||
const browserMod = await getBrowserModule();
|
||||
if (browserMod) Object.assign(allDefs, browserMod.TOOL_DEFS);
|
||||
|
||||
const mapsMod = await getMapsModule();
|
||||
if (mapsMod) Object.assign(allDefs, mapsMod.TOOL_DEFS);
|
||||
|
||||
const youtubeMod = await getYoutubeModule();
|
||||
if (youtubeMod) Object.assign(allDefs, youtubeMod.TOOL_DEFS);
|
||||
|
||||
const piecesMod = await getPiecesModule();
|
||||
if (piecesMod) Object.assign(allDefs, piecesMod.TOOL_DEFS);
|
||||
|
||||
const amazonMod = await getAmazonModule();
|
||||
if (amazonMod) Object.assign(allDefs, amazonMod.TOOL_DEFS);
|
||||
|
||||
const speechMod = await getSpeechModule();
|
||||
if (speechMod) Object.assign(allDefs, speechMod.TOOL_DEFS);
|
||||
|
||||
const checklistMod = await getChecklistModule();
|
||||
if (checklistMod) Object.assign(allDefs, checklistMod.TOOL_DEFS);
|
||||
|
||||
const knowledgeMod = await getKnowledgeModule();
|
||||
if (knowledgeMod) Object.assign(allDefs, knowledgeMod.TOOL_DEFS);
|
||||
|
||||
const msLearnMod = await getMsLearnModule();
|
||||
if (msLearnMod) Object.assign(allDefs, msLearnMod.TOOL_DEFS);
|
||||
|
||||
const slideMod = await getSlideModule();
|
||||
if (slideMod) Object.assign(allDefs, slideMod.TOOL_DEFS);
|
||||
|
||||
const docsMod = await getDocsModule();
|
||||
if (docsMod) Object.assign(allDefs, docsMod.TOOL_DEFS);
|
||||
|
||||
const missionMod = await getMissionModule();
|
||||
if (missionMod) Object.assign(allDefs, missionMod.TOOL_DEFS);
|
||||
|
||||
const userFolderMod = await getUserFolderModule();
|
||||
if (userFolderMod) Object.assign(allDefs, userFolderMod.TOOL_DEFS);
|
||||
|
||||
const brainstormMod = await getBrainstormModule();
|
||||
if (brainstormMod) Object.assign(allDefs, brainstormMod.TOOL_DEFS);
|
||||
|
||||
const appDocsMod = await getAppDocsModule();
|
||||
if (appDocsMod) Object.assign(allDefs, appDocsMod.TOOL_DEFS);
|
||||
|
||||
const sshMod = await getSshModule();
|
||||
if (sshMod) Object.assign(allDefs, sshMod.TOOL_DEFS);
|
||||
|
||||
const sshConsoleMod = await getSshConsoleModule();
|
||||
if (sshConsoleMod) Object.assign(allDefs, sshConsoleMod.TOOL_DEFS);
|
||||
|
||||
const notesMod = await getNotesModule();
|
||||
if (notesMod) Object.assign(allDefs, notesMod.TOOL_DEFS);
|
||||
|
||||
const dashboardMod = await getDashboardModule();
|
||||
if (dashboardMod) Object.assign(allDefs, dashboardMod.TOOL_DEFS);
|
||||
|
||||
const { TOOL_DEFS: skillToolDefs } = await import('./skills.js');
|
||||
Object.assign(allDefs, skillToolDefs);
|
||||
|
||||
// メタツール: piece の allowed_tools に書かれていなくても常に利用可能
|
||||
// - ReadToolDoc: 全ツールのドキュメント参照
|
||||
// - CreateChecklist / CheckItem / GetChecklist: 進捗管理 (複数ステップタスクで使用)
|
||||
// - MissionUpdate: タスクの目標 / 進捗のピン止めメモを更新 (会話が長くなって
|
||||
// 最初の要件を見失わないため。常時上書き可能、未指定フィールドは保持)
|
||||
// - ListUserAssets / RunUserScript: ユーザーフォルダのスクリプト探索・実行
|
||||
// - Brainstorm: 着手前 or 行き詰まり時の多アプローチ比較 (issue #247)
|
||||
// - ReadAppDoc / ListAppDocs / GetMyOrchestratorState: Help アシスタント用 (#help piece)
|
||||
// ただし他の piece からも参照できるようにメタ扱い
|
||||
const META_TOOLS = ['ReadToolDoc', 'CreateChecklist', 'CheckItem', 'GetChecklist', 'MissionUpdate', 'ListUserAssets', 'RunUserScript', 'UpdateUserMemory', 'ReadUserMemory', 'ReadUserTemplate', 'RenderUserTemplate', 'WriteUserScript', 'WriteUserTemplate', 'Brainstorm', 'ReadAppDoc', 'ListAppDocs', 'GetMyOrchestratorState', 'ReadSkill', 'ListSkills', 'InstallSkill'];
|
||||
const effectiveAllowed = [...allowedTools];
|
||||
for (const meta of META_TOOLS) {
|
||||
if (!effectiveAllowed.includes(meta) && meta in allDefs) {
|
||||
effectiveAllowed.push(meta);
|
||||
}
|
||||
}
|
||||
|
||||
const staticDefs = effectiveAllowed
|
||||
.filter((name) => {
|
||||
if (!editAllowed && (name === 'Write' || name === 'Edit')) return false;
|
||||
if (!options?.vlmEnabled && name === 'ReadImage') return false;
|
||||
return name in allDefs;
|
||||
})
|
||||
.map((name) => allDefs[name]!);
|
||||
|
||||
const mcpDefs =
|
||||
_mcpAggregator && options?.ownerId && !options?.mcpDisabled
|
||||
? await _mcpAggregator.getToolDefs(options.ownerId, allowedTools)
|
||||
: [];
|
||||
|
||||
return [...staticDefs, ...mcpDefs];
|
||||
}
|
||||
|
||||
/**
|
||||
* ツールを実行する内部ルーター。
|
||||
* core → web → image → data の順で各モジュールに委譲し、
|
||||
* 最初に null でない結果を返したモジュールの結果を使う。
|
||||
*/
|
||||
async function executeToolInner(
|
||||
name: string,
|
||||
input: Record<string, unknown>,
|
||||
ctx: ToolContext,
|
||||
): Promise<ToolResult> {
|
||||
if (name.startsWith('mcp__')) {
|
||||
if (ctx.mcpDisabled) {
|
||||
return { output: 'MCP tools are disabled for this task (options.mcpDisabled)', isError: true };
|
||||
}
|
||||
if (!_mcpAggregator) {
|
||||
return { output: 'MCP サブシステムが初期化されていません', isError: true };
|
||||
}
|
||||
const ctxWithMcp = ctx as ExecuteCtxWithMcp;
|
||||
if (!ctxWithMcp.mcpQuotaState) {
|
||||
ctxWithMcp.mcpQuotaState = { files: 0, bytes: 0 };
|
||||
}
|
||||
if (!ctxWithMcp.mcpConfig) {
|
||||
return { output: 'MCP 設定が ToolContext に伝播していません', isError: true };
|
||||
}
|
||||
const result = await _mcpAggregator.executeTool(name, input, {
|
||||
workspacePath: ctx.workspacePath,
|
||||
ownerId: ctxWithMcp.ownerId ?? '',
|
||||
jobId: ctxWithMcp.jobId ?? '',
|
||||
config: ctxWithMcp.mcpConfig,
|
||||
quotaState: ctxWithMcp.mcpQuotaState,
|
||||
});
|
||||
if (result === null) {
|
||||
return { output: `MCP ツール dispatch が ${name} に対して null を返しました`, isError: true };
|
||||
}
|
||||
return { output: result.output, isError: result.isError };
|
||||
}
|
||||
|
||||
// core ツール
|
||||
const coreResult = await executeCoreTools(name, input, ctx);
|
||||
if (coreResult !== null) return coreResult;
|
||||
|
||||
// web ツール
|
||||
const webMod = await getWebModule();
|
||||
if (webMod) {
|
||||
const webResult = await webMod.executeTool(name, input, ctx);
|
||||
if (webResult !== null) return webResult;
|
||||
}
|
||||
|
||||
// image ツール
|
||||
const imageMod = await getImageModule();
|
||||
if (imageMod) {
|
||||
const imageResult = await imageMod.executeTool(name, input, ctx);
|
||||
if (imageResult !== null) return imageResult;
|
||||
}
|
||||
|
||||
// data ツール
|
||||
const dataMod = await getDataModule();
|
||||
if (dataMod) {
|
||||
const dataResult = await dataMod.executeTool(name, input, ctx);
|
||||
if (dataResult !== null) return dataResult;
|
||||
}
|
||||
|
||||
// office ツール
|
||||
const officeMod = await getOfficeModule();
|
||||
if (officeMod) {
|
||||
const officeResult = await officeMod.executeTool(name, input, ctx);
|
||||
if (officeResult !== null) return officeResult;
|
||||
}
|
||||
|
||||
// review ツール
|
||||
const reviewMod = await getReviewModule();
|
||||
if (reviewMod) {
|
||||
const reviewResult = await reviewMod.executeTool(name, input, ctx);
|
||||
if (reviewResult !== null) return reviewResult;
|
||||
}
|
||||
|
||||
// x tools
|
||||
const xMod = await getXModule();
|
||||
if (xMod) {
|
||||
const xResult = await xMod.executeTool(name, input, ctx);
|
||||
if (xResult !== null) return xResult;
|
||||
}
|
||||
|
||||
// orchestration ツール
|
||||
const orchestrationMod = await getOrchestrationModule();
|
||||
if (orchestrationMod) {
|
||||
const orchestrationResult = await orchestrationMod.executeTool(name, input, ctx);
|
||||
if (orchestrationResult !== null) return orchestrationResult;
|
||||
}
|
||||
|
||||
// browser ツール
|
||||
const browserMod = await getBrowserModule();
|
||||
if (browserMod) {
|
||||
const browserResult = await browserMod.executeTool(name, input, ctx);
|
||||
if (browserResult !== null) return browserResult;
|
||||
}
|
||||
|
||||
// maps ツール
|
||||
const mapsMod = await getMapsModule();
|
||||
if (mapsMod) {
|
||||
const mapsResult = await mapsMod.executeTool(name, input, ctx);
|
||||
if (mapsResult !== null) return mapsResult;
|
||||
}
|
||||
|
||||
// youtube ツール
|
||||
const youtubeMod = await getYoutubeModule();
|
||||
if (youtubeMod) {
|
||||
const youtubeResult = await youtubeMod.executeTool(name, input, ctx);
|
||||
if (youtubeResult !== null) return youtubeResult;
|
||||
}
|
||||
|
||||
// pieces ツール
|
||||
const piecesMod = await getPiecesModule();
|
||||
if (piecesMod) {
|
||||
const piecesResult = await piecesMod.executeTool(name, input, ctx);
|
||||
if (piecesResult !== null) return piecesResult;
|
||||
}
|
||||
|
||||
// amazon ツール
|
||||
const amazonMod = await getAmazonModule();
|
||||
if (amazonMod) {
|
||||
const amazonResult = await amazonMod.executeTool(name, input, ctx);
|
||||
if (amazonResult !== null) return amazonResult;
|
||||
}
|
||||
|
||||
// speech ツール
|
||||
const speechMod = await getSpeechModule();
|
||||
if (speechMod) {
|
||||
const speechResult = await speechMod.executeTool(name, input, ctx);
|
||||
if (speechResult !== null) return speechResult;
|
||||
}
|
||||
|
||||
// checklist ツール
|
||||
const checklistMod = await getChecklistModule();
|
||||
if (checklistMod) {
|
||||
const checklistResult = await checklistMod.executeTool(name, input, ctx);
|
||||
if (checklistResult !== null) return checklistResult;
|
||||
}
|
||||
|
||||
// knowledge ツール
|
||||
const knowledgeMod = await getKnowledgeModule();
|
||||
if (knowledgeMod) {
|
||||
const knowledgeResult = await knowledgeMod.executeTool(name, input, ctx);
|
||||
if (knowledgeResult !== null) return knowledgeResult;
|
||||
}
|
||||
|
||||
// ms-learn ツール
|
||||
const msLearnMod = await getMsLearnModule();
|
||||
if (msLearnMod) {
|
||||
const msLearnResult = await msLearnMod.executeTool(name, input, ctx);
|
||||
if (msLearnResult !== null) return msLearnResult;
|
||||
}
|
||||
|
||||
// slide ツール (SetTheme / AddSlide / BuildPptx / ResetSlides)
|
||||
const slideMod = await getSlideModule();
|
||||
if (slideMod) {
|
||||
const slideResult = await slideMod.executeTool(name, input, ctx);
|
||||
if (slideResult !== null) return slideResult;
|
||||
}
|
||||
|
||||
// docs ツール (ReadToolDoc)
|
||||
const docsMod = await getDocsModule();
|
||||
if (docsMod) {
|
||||
const docsResult = await docsMod.executeTool(name, input, ctx);
|
||||
if (docsResult !== null) return docsResult;
|
||||
}
|
||||
|
||||
// mission ツール (MissionUpdate)
|
||||
const missionMod = await getMissionModule();
|
||||
if (missionMod) {
|
||||
const missionResult = await missionMod.executeTool(name, input, ctx);
|
||||
if (missionResult !== null) return missionResult;
|
||||
}
|
||||
|
||||
// user-folder ツール (ListUserAssets / RunUserScript)
|
||||
const userFolderMod = await getUserFolderModule();
|
||||
if (userFolderMod) {
|
||||
const userFolderResult = await userFolderMod.executeTool(name, input, ctx);
|
||||
if (userFolderResult !== null) return userFolderResult;
|
||||
}
|
||||
|
||||
// brainstorm ツール (Brainstorm)
|
||||
const brainstormMod = await getBrainstormModule();
|
||||
if (brainstormMod) {
|
||||
const brainstormResult = await brainstormMod.executeTool(name, input, ctx);
|
||||
if (brainstormResult !== null) return brainstormResult;
|
||||
}
|
||||
|
||||
// app-docs ツール (ReadAppDoc / ListAppDocs / GetMyOrchestratorState)
|
||||
const appDocsMod = await getAppDocsModule();
|
||||
if (appDocsMod) {
|
||||
const appDocsResult = await appDocsMod.executeTool(name, input, ctx);
|
||||
if (appDocsResult !== null) return appDocsResult;
|
||||
}
|
||||
|
||||
// ssh ツール (SshExec / SshUpload / SshDownload)
|
||||
const sshMod = await getSshModule();
|
||||
if (sshMod) {
|
||||
const sshResult = await sshMod.executeTool(name, input, ctx);
|
||||
if (sshResult !== null) return sshResult;
|
||||
}
|
||||
|
||||
// ssh-console ツール (SshConsoleEnsure / Send / Snapshot)
|
||||
const sshConsoleMod = await getSshConsoleModule();
|
||||
if (sshConsoleMod) {
|
||||
const sshConsoleResult = await sshConsoleMod.executeTool(name, input, ctx);
|
||||
if (sshConsoleResult !== null) return sshConsoleResult;
|
||||
}
|
||||
|
||||
// notes ツール (SearchNotes / ReadNote / WriteNote)
|
||||
const notesMod = await getNotesModule();
|
||||
if (notesMod) {
|
||||
const notesResult = await notesMod.executeTool(name, input, ctx);
|
||||
if (notesResult !== null) return notesResult;
|
||||
}
|
||||
|
||||
// dashboard ツール (UpdateDashboardWidget)
|
||||
const dashboardMod = await getDashboardModule();
|
||||
if (dashboardMod) {
|
||||
const dashboardResult = await dashboardMod.executeTool(name, input, ctx);
|
||||
if (dashboardResult !== null) return dashboardResult;
|
||||
}
|
||||
|
||||
// skills ツール (ReadSkill)
|
||||
const { executeSkillTool } = await import('./skills.js');
|
||||
const skillResult = executeSkillTool(name, input, ctx);
|
||||
if (skillResult !== null) return skillResult;
|
||||
|
||||
return { output: `Unknown tool: ${name}`, isError: true };
|
||||
}
|
||||
|
||||
/**
|
||||
* ツールを実行するルーター(生データ自動保存ラッパー付き)。
|
||||
* executeToolInner に委譲した後、成功した対象ツールの結果を logs/raw/ に保存する。
|
||||
*/
|
||||
export async function executeTool(
|
||||
name: string,
|
||||
input: Record<string, unknown>,
|
||||
ctx: ToolContext,
|
||||
): Promise<ToolResult> {
|
||||
logger.debug(`[tools/index] executing ${name}`);
|
||||
|
||||
const result = await executeToolInner(name, input, ctx);
|
||||
|
||||
// raw保存ラッパー: 成功した対象ツールの結果を logs/raw/ に保存
|
||||
if (ctx.workspacePath && !result.isError) {
|
||||
if (RAW_SAVE_TOOLS.has(name)) {
|
||||
saveRawData(ctx.workspacePath, name, result.output);
|
||||
} else if (RAW_LOG_ONLY_TOOLS.has(name)) {
|
||||
const pathMatch = result.output.match(/-> (.+?) \(/);
|
||||
if (pathMatch?.[1]) {
|
||||
logRawDownload(ctx.workspacePath, name, pathMatch[1], result.output.length);
|
||||
}
|
||||
}
|
||||
// 構造化データ保存: structuredBlocks があれば logs/structured/ に保存
|
||||
if (result.structuredBlocks?.length) {
|
||||
saveStructuredBlocks(ctx.workspacePath, result.structuredBlocks);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// 同期版 getToolDefs のラッパー(後方互換のため、コアツールのみを返す同期版)
|
||||
export { getCoreToolDefs as getCoreToolDefs };
|
||||
Reference in New Issue
Block a user