759951ab12
拆出项目工作区视图、命令策略、摘要命令与开发面板模块。 拆出 Runtime action、driver 与 protocol 的职责模块并保留稳定 facade。 保留测试模块、兼容重导出与原有可见性边界。 补充结构拆分决策、踩坑记录与实施计划验收结果。
141 lines
3.4 KiB
TypeScript
141 lines
3.4 KiB
TypeScript
import {
|
|
GAME_CREATION_APP_COMMANDS,
|
|
type GameCreationAppCommandDescriptor,
|
|
} from '../../../../../packages/shared/src/contracts/gameCreationApp';
|
|
import type { PendingCommand } from '../../app/types';
|
|
import {
|
|
isAbsoluteProjectPath,
|
|
projectPathHasControlCharacter,
|
|
} from '../project-summary/projectSummary';
|
|
|
|
export function resolveChatProjectPath(
|
|
localProject: { projectPath: string } | null,
|
|
) {
|
|
const projectPath = localProject?.projectPath?.trim();
|
|
if (
|
|
!projectPath ||
|
|
!isAbsoluteProjectPath(projectPath) ||
|
|
projectPathHasControlCharacter(projectPath)
|
|
) {
|
|
return null;
|
|
}
|
|
return projectPath;
|
|
}
|
|
|
|
export function isAgentTraceFilePath(value: string) {
|
|
const path = value.trim();
|
|
return (
|
|
path === '.agent/run.latest.json' ||
|
|
(path.startsWith('.agent/runs/') && path.endsWith('.json'))
|
|
);
|
|
}
|
|
|
|
export function isRegisteredGameCreationCommandId(value: string) {
|
|
return GAME_CREATION_APP_COMMANDS.some((command) => command.id === value);
|
|
}
|
|
|
|
export function isProjectPolicyConfirmableCommandId(value: string) {
|
|
return [
|
|
'project.index',
|
|
'project.status',
|
|
'project.checkpoint',
|
|
'project.diff',
|
|
'project.restore',
|
|
'project.export_package',
|
|
'project.export_list',
|
|
'file.list',
|
|
'file.read',
|
|
'memory.read',
|
|
'memory.write',
|
|
'memory.delete',
|
|
'asset.register',
|
|
'asset.list',
|
|
'task.list',
|
|
'task.create',
|
|
'task.update',
|
|
'agent.run_status',
|
|
'agent.kill',
|
|
'agent.retry',
|
|
'agent.resume',
|
|
'agent.delegate',
|
|
'agent.spawn_isolated',
|
|
'agent.schedule_ready',
|
|
'agent.audit',
|
|
'agent.trace_read',
|
|
'preview.status',
|
|
'preview.start',
|
|
'preview.validate',
|
|
'preview.open',
|
|
'preview.stop',
|
|
'canvas.project_sync',
|
|
'canvas.asset_import',
|
|
'canvas.asset_generate',
|
|
'canvas.export_import',
|
|
'conversation.read',
|
|
'conversation.write',
|
|
].includes(value);
|
|
}
|
|
|
|
export function isSafeCanvasProjectId(value: string) {
|
|
return !!value.trim() && !projectPathHasControlCharacter(value);
|
|
}
|
|
|
|
export function isSafeCheckpointId(value: string) {
|
|
const checkpointId = value.trim();
|
|
return (
|
|
!!checkpointId &&
|
|
!projectPathHasControlCharacter(checkpointId) &&
|
|
!checkpointId.includes('/') &&
|
|
!checkpointId.includes('\\') &&
|
|
!checkpointId.includes('..')
|
|
);
|
|
}
|
|
|
|
export function needsInitializedChatProject(
|
|
commandId: GameCreationAppCommandDescriptor['id'],
|
|
) {
|
|
return [
|
|
'asset.upload',
|
|
'asset.register',
|
|
'agent.delegate',
|
|
'agent.kill',
|
|
'agent.retry',
|
|
'agent.resume',
|
|
'command.run_limited',
|
|
'game.generate_draft',
|
|
'game.run_local',
|
|
'file.list',
|
|
'file.read',
|
|
'project.checkpoint',
|
|
'project.export_package',
|
|
'project.export_list',
|
|
'project.restore',
|
|
'project.policy_write',
|
|
'preview.open',
|
|
'preview.start',
|
|
'canvas.project_sync',
|
|
'canvas.asset_import',
|
|
'canvas.asset_generate',
|
|
'canvas.export_import',
|
|
'memory.read',
|
|
'memory.write',
|
|
'memory.delete',
|
|
'conversation.read',
|
|
'conversation.write',
|
|
].includes(commandId);
|
|
}
|
|
|
|
export function resolvePendingCommandProjectPath(
|
|
command: PendingCommand,
|
|
localProject: { projectPath: string } | null,
|
|
draftProjectPath: string,
|
|
) {
|
|
if (command.id === 'project.create') {
|
|
return command.projectPath;
|
|
}
|
|
if (needsInitializedChatProject(command.id)) {
|
|
return resolveChatProjectPath(localProject) ?? draftProjectPath;
|
|
}
|
|
return draftProjectPath;
|
|
}
|