sync: update from private repo (dfadcd5f)
CI / build-and-test (push) Has been cancelled

This commit is contained in:
oss-sync
2026-06-23 06:38:48 +00:00
parent 6a2f2cc736
commit 29ccaf1e92
377 changed files with 31028 additions and 8994 deletions
+74 -58
View File
@@ -7,6 +7,7 @@ import {
ALL_TOOL_DEFS,
getToolDefs as getCoreToolDefs,
executeCoreTools,
runtimeLogsDir,
} from './core.js';
import { saveRawData, logRawDownload, RAW_SAVE_TOOLS, RAW_LOG_ONLY_TOOLS } from './raw-save.js';
import { saveStructuredBlocks } from './structured-blocks.js';
@@ -58,7 +59,6 @@ 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;
@@ -175,14 +175,6 @@ async function getChecklistModule(): Promise<ToolModule | null> {
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');
@@ -217,6 +209,24 @@ async function getMissionModule(): Promise<ToolModule | null> {
return _missionModule;
}
let _toolRequestModule: ToolModule | null | undefined;
async function getToolRequestModule(): Promise<ToolModule | null> {
if (_toolRequestModule === undefined) {
_toolRequestModule = await tryLoadModule('./tool-request.js');
if (_toolRequestModule) logger.debug('[tools/index] tool-request module loaded');
}
return _toolRequestModule;
}
/**
* Snapshot of all known static tool names, refreshed every getToolDefs() call
* (which runs at movement start, before any tool executes). Injected into
* RequestTool's ctx so it can classify an unknown tool name vs one that exists
* but isn't allowed in the current movement. MCP names are handled separately
* by RequestTool via the `mcp__` prefix, so they need not be in this set.
*/
let _allKnownToolNames: string[] = [];
async function getUserFolderModule(): Promise<ToolModule | null> {
if (_userFolderModule === undefined) {
_userFolderModule = await tryLoadModule('./user-folder.js');
@@ -261,22 +271,13 @@ async function getSshConsoleModule(): Promise<ToolModule | null> {
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');
let _calendarModule: ToolModule | null | undefined = undefined;
async function getCalendarModule(): Promise<ToolModule | null> {
if (_calendarModule === undefined) {
_calendarModule = await tryLoadModule('./calendar.js');
if (_calendarModule) logger.debug('[tools/index] calendar 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;
return _calendarModule;
}
/**
@@ -286,7 +287,7 @@ async function getDashboardModule(): Promise<ToolModule | null> {
export async function getToolDefs(
allowedTools: string[],
editAllowed: boolean,
options?: { vlmEnabled?: boolean; ownerId?: string | null; mcpDisabled?: boolean },
options?: { vlmEnabled?: boolean; ownerId?: string | null; mcpDisabled?: boolean; spaceId?: string | null },
): Promise<ToolDef[]> {
// 全ツール定義を収集
const allDefs: Record<string, ToolDef> = { ...ALL_TOOL_DEFS };
@@ -333,9 +334,6 @@ export async function getToolDefs(
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);
@@ -363,15 +361,30 @@ export async function getToolDefs(
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 calendarMod = await getCalendarModule();
if (calendarMod) Object.assign(allDefs, calendarMod.TOOL_DEFS);
const { TOOL_DEFS: skillToolDefs } = await import('./skills.js');
Object.assign(allDefs, skillToolDefs);
const toolRequestMod = await getToolRequestModule();
if (toolRequestMod) Object.assign(allDefs, toolRequestMod.TOOL_DEFS);
// Refresh the known-tool snapshot for RequestTool classification.
//
// CONCURRENCY INVARIANT (must hold): this is taken HERE — after every static
// module is merged into `allDefs`, but BEFORE the per-job MCP defs are
// appended below. The static catalog does NOT depend on movement / ownerId /
// spaceId / mcpDisabled, so every concurrent getToolDefs() writer produces an
// IDENTICAL array. That is why this module-global is safe to read from a
// different movement's RequestTool dispatch. If you ever make a STATIC tool's
// presence in `allDefs` conditional (feature flag, per-space, etc.), this
// snapshot becomes movement-dependent and the global must move into ctx
// instead — otherwise concurrent movements would misclassify each other's
// tools as `unknown`.
_allKnownToolNames = Object.keys(allDefs);
// メタツール: piece の allowed_tools に書かれていなくても常に利用可能
// - ReadToolDoc: 全ツールのドキュメント参照
// - CreateChecklist / CheckItem / GetChecklist: 進捗管理 (複数ステップタスクで使用)
@@ -383,7 +396,8 @@ export async function getToolDefs(
// - Brainstorm: 着手前 or 行き詰まり時の多アプローチ比較 (issue #247)
// - ReadAppDoc / ListAppDocs / GetMyOrchestratorState: Help アシスタント用 (#help piece)
// ただし他の piece からも参照できるようにメタ扱い
const META_TOOLS = ['ReadToolDoc', 'CreateChecklist', 'CheckItem', 'GetChecklist', 'MissionUpdate', 'ListUserAssets', 'RunUserScript', 'UpdateUserMemory', 'ReadUserMemory', 'ReadUserAgents', 'UpdateUserAgents', 'ReadUserTemplate', 'RenderUserTemplate', 'WriteUserScript', 'WriteUserTemplate', 'Brainstorm', 'ReadAppDoc', 'ListAppDocs', 'GetMyOrchestratorState', 'ReadSkill', 'ListSkills', 'InstallSkill'];
// - RequestTool: 足りないツールの要求を記録(タスク詳細/ピース集計で可視化)
const META_TOOLS = ['ReadToolDoc', 'CreateChecklist', 'CheckItem', 'GetChecklist', 'MissionUpdate', 'ListUserAssets', 'RunUserScript', 'UpdateUserMemory', 'ReadUserMemory', 'ReadUserAgents', 'UpdateUserAgents', 'ReadUserTemplate', 'RenderUserTemplate', 'WriteUserScript', 'WriteUserTemplate', 'Brainstorm', 'ReadAppDoc', 'ListAppDocs', 'GetMyOrchestratorState', 'ReadSkill', 'ListSkills', 'InstallSkill', 'RequestTool'];
const effectiveAllowed = [...allowedTools];
for (const meta of META_TOOLS) {
if (!effectiveAllowed.includes(meta) && meta in allDefs) {
@@ -399,9 +413,12 @@ export async function getToolDefs(
})
.map((name) => allDefs[name]!);
// Per-space isolation: the MCP server set is scoped to the job's space.
// options.spaceId === undefined → aggregator falls back to the legacy
// NULL-space set (non-space jobs keep prior behaviour).
const mcpDefs =
_mcpAggregator && options?.ownerId && !options?.mcpDisabled
? await _mcpAggregator.getToolDefs(options.ownerId, allowedTools)
? await _mcpAggregator.getToolDefs(options.ownerId, allowedTools, options.spaceId)
: [];
return [...staticDefs, ...mcpDefs];
@@ -437,6 +454,9 @@ async function executeToolInner(
jobId: ctxWithMcp.jobId ?? '',
config: ctxWithMcp.mcpConfig,
quotaState: ctxWithMcp.mcpQuotaState,
// Per-space isolation guard (defense in depth). undefined = legacy
// NULL-space job → only NULL-space servers are callable.
spaceId: ctx.spaceId ?? null,
});
if (result === null) {
return { output: `MCP ツール dispatch が ${name} に対して null を返しました`, isError: true };
@@ -546,13 +566,6 @@ async function executeToolInner(
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) {
@@ -581,6 +594,15 @@ async function executeToolInner(
if (missionResult !== null) return missionResult;
}
// RequestTool: 足りないツールの要求を記録。分類用に既知ツール一覧を注入する
// (getToolDefs が movement 開始時に更新した最新スナップショット)。
const toolRequestMod = await getToolRequestModule();
if (toolRequestMod) {
if (name === 'RequestTool') ctx.knownToolNames = _allKnownToolNames;
const toolRequestResult = await toolRequestMod.executeTool(name, input, ctx);
if (toolRequestResult !== null) return toolRequestResult;
}
// user-folder ツール (ListUserAssets / RunUserScript)
const userFolderMod = await getUserFolderModule();
if (userFolderMod) {
@@ -616,18 +638,11 @@ async function executeToolInner(
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;
// calendar ツール (AddCalendarEvent / ListCalendarEvents)
const calendarMod = await getCalendarModule();
if (calendarMod) {
const calendarResult = await calendarMod.executeTool(name, input, ctx);
if (calendarResult !== null) return calendarResult;
}
// skills ツール (ReadSkill)
@@ -651,19 +666,20 @@ export async function executeTool(
const result = await executeToolInner(name, input, ctx);
// raw保存ラッパー: 成功した対象ツールの結果を logs/raw/ に保存
// raw保存ラッパー: 成功した対象ツールの結果を {logsRoot}/raw/ に保存(計画5: runtimeDir 解決)
if (ctx.workspacePath && !result.isError) {
const logsRoot = runtimeLogsDir(ctx);
if (RAW_SAVE_TOOLS.has(name)) {
saveRawData(ctx.workspacePath, name, result.output);
saveRawData(logsRoot, 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);
logRawDownload(logsRoot, name, pathMatch[1], result.output.length);
}
}
// 構造化データ保存: structuredBlocks があれば logs/structured/ に保存
// 構造化データ保存: structuredBlocks があれば {logsRoot}/structured/ に保存
if (result.structuredBlocks?.length) {
saveStructuredBlocks(ctx.workspacePath, result.structuredBlocks);
saveStructuredBlocks(logsRoot, result.structuredBlocks);
}
}