agent-Specialization/static/src/app/state.ts
JOJO 08d9812f45 feat(docker): support isolated projects in web mode
Implement Docker Web project management on top of workspace_id while keeping host mode workspace behavior intact.

Backend changes:

- Move Docker user files to users/<user>/projects/<project_id>/{project,data,logs} and shared user state to users/<user>/personal.

- Add automatic legacy migration from old project/data/logs/agentskills layouts and from the temporary project/shared layout.

- Generate project IDs server-side from the project name, reserve internal IDs, and hide project paths from the UI.

- Add project rename/delete APIs; deleting a Docker project removes its project directory and releases terminal/container state.

- Add host workspace rename/delete APIs; deleting a host workspace only removes catalog entries and keeps files on disk.

- Scope Docker containers, terminals, uploads, conversations, storage, and running task metadata by workspace_id.

- Store private skills under users/<user>/personal/agentskills and sync them into each project workspace.

- Inject the current project/workspace name through prompts/workspace_system.txt.

Frontend changes:

- Replace Docker file-tree area with project management UX and reuse host multi-workspace running-task behavior.

- Add a management dialog for creating, renaming, and deleting projects/workspaces.

- Show project labels instead of internal IDs in toasts and project lists.

- Clear stale conversation history during project/workspace switching and show loading until the new list is ready.

- Keep running-task loader/check behavior consistent across host workspaces and Docker projects.

Validation:

- python3 -m py_compile modules/user_manager.py modules/host_workspace_manager.py modules/skills_manager.py core/main_terminal_parts/tools_execution.py server/auth.py server/context.py server/status.py server/conversation.py server/tasks.py utils/context_manager.py

- python3 -m unittest test.test_server_refactor_smoke

- npm run build --silent 2>&1 | tail -n 20
2026-05-29 19:49:48 +08:00

254 lines
8.1 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// @ts-nocheck
import { ICONS, TOOL_CATEGORY_ICON_MAP } from '../utils/icons';
export function dataState() {
return {
// 路由相关
initialRouteResolved: false,
dropToolEvents: false,
// 轮询模式标志(禁用 WebSocket 事件处理)
usePollingMode: true,
// 后台子智能体等待状态
waitingForSubAgent: false,
// 后台 run_command 等待状态(用于文案区分)
waitingForBackgroundCommand: false,
// 是否在对话区展示 system 消息
hideSystemMessages: true,
// 工具状态跟踪
preparingTools: new Map(),
activeTools: new Map(),
toolActionIndex: new Map(),
toolStacks: new Map(),
// 当前任务是否仍在进行中(用于保持输入区的"停止"状态)
taskInProgress: false,
// 等待后台通知期间,用于发现并接管新建任务的轮询定时器
waitingTaskProbeTimer: null,
// 宿主机多工作区任务列表后台刷新定时器(用于当前未查看运行对话时同步完成态)
runningWorkspaceTasksRefreshTimer: null,
// 运行期消息堆积(提前发送 / 引导对话)
runtimeQueuedMessages: [],
runtimeGuidanceFallbackQueue: [],
runtimeQueueSuppressedMessageIds: new Set(),
runtimeGuidanceSuppressedTextCounts: {},
runtimeQueueLimit: 5,
runtimeQueueAutoSendInProgress: false,
runtimeQueueSyncLockKey: '',
runtimeQueueSyncLockUntil: 0,
// 输入区动态保留高度(用于同步扩大消息区可滚动范围)
composerReservedHeight: 80,
// 记录上一次成功加载历史的对话ID防止初始化阶段重复加载导致动画播放两次
lastHistoryLoadedConversationId: null,
// ==========================================
// 对话管理相关状态
// ==========================================
// 搜索功能
// ==========================================
searchRequestSeq: 0,
searchActiveQuery: '',
searchResultIdSet: new Set(),
searchPreviewCache: {},
// Token统计相关状态修复版
// ==========================================
// 对话压缩状态
compressing: false,
compressionInProgress: false,
compressionMode: '',
compressionStage: '',
compressionError: '',
compressionToastId: null,
skipConversationLoadedEvent: false,
skipConversationHistoryReload: false,
_scrollListenerReady: false,
historyLoading: false,
historyLoadingFor: null,
historyLoadSeq: 0,
blankHeroActive: false,
blankHeroExiting: false,
blankWelcomeText: '',
lastBlankConversationId: null,
// 对话标题打字效果
titleTypingText: '',
titleTypingTarget: '',
titleTypingTimer: null,
titleReady: false,
suppressTitleTyping: false,
headerMenuOpen: false,
blankWelcomePool: [
'有什么可以帮忙的?',
'想了解些热点吗?',
'要我帮你完成作业吗?',
'整点代码?',
'随便聊点什么?',
'想让我帮你整理一下思路吗?',
'要不要我帮你写个小工具?',
'发我一句话,我来接着做。',
'我来给你画幅画?',
'想看小猫吗?',
'有什么难题丢过来吧。',
'想不想看个有意思的?',
'来,说说你的需求~'
],
mobileViewportQuery: null,
modeMenuOpen: false,
modelMenuOpen: false,
permissionMenuOpen: false,
currentPermissionMode: 'unrestricted',
pendingPermissionMode: '',
executionModeEnabled: false,
currentExecutionMode: 'sandbox',
pendingExecutionMode: '',
executionModeDirectUntil: null,
executionModeAutoFallbackToastId: null,
executionModeTtlSeconds: 600,
executionModeExpirySyncTimer: null,
pathAuthorizationDialogOpen: false,
pathAuthorizationMode: 'writable',
pathAuthorizationWritableDraft: '',
pathAuthorizationReadableDraft: '',
pathAuthorizationDraft: '',
pathAuthorizationSaving: false,
versioningHostMode: false,
dockerProjectMode: false,
hostWorkspaces: [],
currentHostWorkspaceId: '',
defaultHostWorkspaceId: '',
hostWorkspaceSwitching: false,
hostWorkspaceCreateDialogOpen: false,
hostWorkspaceCreatePath: '',
hostWorkspaceCreateLabel: '',
hostWorkspaceCreateSubmitting: false,
hostWorkspaceCreateError: '',
hostWorkspaceManageDialogOpen: false,
hostWorkspaceManageSubmitting: false,
versioningEnabled: false,
newConversationVersioningEnabled: false,
versioningTrackingMode: 'workspace_and_conversation',
newConversationVersioningTrackingMode: 'workspace_and_conversation',
versioningMode: 'overwrite',
versioningMismatch: false,
versioningWorkspaceMatched: true,
versioningDialogOpen: false,
versioningLoading: false,
versioningCheckpoints: [],
versioningSelectedSeq: null,
versioningSelectedDetail: null,
versioningDetailLoading: false,
versioningRestoring: false,
versioningRestoreMode: 'overwrite',
permissionModeOptions: [
{
value: 'readonly',
label: '只读',
description: '仅允许读取/搜索类工具,禁止修改工作区'
},
{
value: 'approval',
label: '批准',
description: '对工作区文件进行修改的工具需用户批准后才会执行'
},
{
value: 'auto_approval',
label: '自动审核',
description: '工作区内写入直通,高风险操作由后台审核智能体自动审批'
},
{
value: 'unrestricted',
label: '无限制',
description: '保持当前默认行为,不额外拦截'
}
],
executionModeOptions: [
{
value: 'sandbox',
label: '沙箱',
description: '所有指令会在系统沙箱中执行'
},
{
value: 'direct',
label: '完全访问权限',
description: '所有指令会在宿主机直接执行'
}
],
pendingToolApprovals: [],
decidingApprovalIds: [],
pendingUserQuestions: [],
userQuestionDialogVisible: false,
userQuestionMinimized: false,
userQuestionActiveIndex: 0,
answeringUserQuestionIds: [],
userQuestionOriginalTitle: '',
userQuestionTitleBlinkTimer: null,
userQuestionTitleBlinkRed: true,
autoApprovalFeedLines: [],
autoApprovalFinalMessage: '',
approvalAutoCloseTimer: null,
imageEntries: [],
imageLoading: false,
videoEntries: [],
videoLoading: false,
conversationHasImages: false,
conversationHasVideos: false,
conversationListRequestSeq: 0,
conversationListRefreshToken: 0,
connectionHeartbeatTimer: null,
connectionHeartbeatActive: false,
connectionHeartbeatFailCount: 0,
connectionHeartbeatSeq: 0,
connectionHeartbeatLastLatencyMs: 0,
connectionHeartbeatLastError: '',
connectionHeartbeatLastStatusCode: null,
connectionHeartbeatLastChangeAt: 0,
connectionHeartbeatInFlight: false,
connectionHeartbeatFailThreshold: 3,
connectionHeartbeatRequestTimeoutMs: 5000,
connectionHeartbeatIntervalMs: 8000,
connectionHeartbeatDisconnectedIntervalMs: 1000,
composerDraftSaveTimer: null,
composerDraftDirty: false,
composerDraftLastSyncedContent: '',
composerDraftFetchSeq: 0,
// 工具控制菜单
icons: ICONS,
toolCategoryIcons: TOOL_CATEGORY_ICON_MAP,
// 对话回顾
reviewDialogOpen: false,
reviewSelectedConversationId: null,
reviewSubmitting: false,
reviewPreviewLines: [],
reviewPreviewLoading: false,
reviewPreviewError: null,
reviewPreviewLimit: 20,
reviewSendToModel: true,
reviewGeneratedPath: null,
// 新手教程首次引导弹窗
tutorialPromptVisible: false,
tutorialPromptLoading: false,
tutorialPromptUsername: '',
// 拖拽上传状态
dragOverActive: false,
// 拖拽事件绑定函数(用于正确移除监听)
_boundDragEnter: null,
_boundDragOver: null,
_boundDragLeave: null,
_boundDrop: null,
_manualScrollSuppressUntil: 0,
_escapedByUserScroll: false,
_autoRelockCooldownUntil: 0,
// stick-to-bottom 状态(用于“回到底部”按钮显隐)
stickIsAtBottom: true,
stickIsNearBottom: true
};
}