补充发布准备聊天入口
新增 /publish 发布准备清单和安全草稿 补充发布准备入口界面测试和帮助覆盖 同步技术方案和项目决策记录
This commit is contained in:
@@ -1860,6 +1860,7 @@ const chatCommandHelp = [
|
||||
'/risks:查看当前项目风险',
|
||||
'/handoff:生成当前项目交接摘要',
|
||||
'/next:查看下一步建议',
|
||||
'/publish:查看发布准备清单',
|
||||
'/open-project:在系统文件管理器中显示项目目录',
|
||||
'/switch-project:回到项目启动器切换工作区',
|
||||
'/index:刷新本地项目索引',
|
||||
@@ -2149,6 +2150,14 @@ function summarizeProjectRisks(
|
||||
};
|
||||
}
|
||||
|
||||
function isAgentRunTracePassed(trace: GameCreationAgentRunTrace | null) {
|
||||
return (
|
||||
trace?.status === 'passed' ||
|
||||
trace?.status === 'artifacts-written' ||
|
||||
trace?.stopReason === 'evaluator-passed'
|
||||
);
|
||||
}
|
||||
|
||||
function summarizeProjectHandoff(
|
||||
nextManifest: GameCreationAppManifest,
|
||||
nextProjectPath: string,
|
||||
@@ -2226,6 +2235,101 @@ function summarizeProjectHandoff(
|
||||
}`;
|
||||
}
|
||||
|
||||
function summarizeProjectPublishReadiness(
|
||||
nextManifest: GameCreationAppManifest,
|
||||
nextProjectPath: string,
|
||||
trace: GameCreationAgentRunTrace | null,
|
||||
) {
|
||||
const tasks = taskRowsFromManifest(nextManifest);
|
||||
const completedCount = tasks.filter(
|
||||
(task) => task.status === 'completed',
|
||||
).length;
|
||||
const failedCount = tasks.filter((task) => task.status === 'failed').length;
|
||||
const readyCount = selectGameCreationAppReadyTasks({ tasks }).length;
|
||||
const tracePassed = isAgentRunTracePassed(trace);
|
||||
const preview = nextManifest.preview;
|
||||
const previewRunning = preview?.status === 'running' && preview.url;
|
||||
const previewSummary = previewRunning
|
||||
? `运行中 ${preview.url}`
|
||||
: preview
|
||||
? previewStatusLabels[preview.status]
|
||||
: '未启动';
|
||||
const sourceCounts = nextManifest.assets.reduce(
|
||||
(counts, asset) => {
|
||||
counts[asset.source.kind] += 1;
|
||||
return counts;
|
||||
},
|
||||
{ uploaded: 0, generated: 0, canvas: 0 } satisfies Record<
|
||||
GameCreationAppAssetSourceKind,
|
||||
number
|
||||
>,
|
||||
);
|
||||
const audioAssetCount =
|
||||
nextManifest.assets.filter(isProjectAudioAsset).length;
|
||||
const commandRuns = nextManifest.commandRuns ?? [];
|
||||
const latestCommandRun = commandRuns[commandRuns.length - 1] ?? null;
|
||||
const hasPublishReadme =
|
||||
trace?.artifacts.some(
|
||||
(artifact) => artifact.path === 'exports/README.md',
|
||||
) ?? false;
|
||||
|
||||
let draftCommand = '/export';
|
||||
let draftCommandLabel = '导出试玩包';
|
||||
if (!trace) {
|
||||
draftCommand = '/next';
|
||||
draftCommandLabel = '查看下一步';
|
||||
} else if (
|
||||
trace.lifecycleStatus === 'killed' ||
|
||||
trace.status === 'failed' ||
|
||||
trace.stopReason === 'max-passes-exhausted'
|
||||
) {
|
||||
draftCommand = '/agent-resume ';
|
||||
draftCommandLabel = '继续最近 run';
|
||||
} else if (!tracePassed) {
|
||||
draftCommand = '/trace';
|
||||
draftCommandLabel = '查看 trace';
|
||||
} else if (!previewRunning) {
|
||||
draftCommand = '/run';
|
||||
draftCommandLabel = '启动预览';
|
||||
}
|
||||
|
||||
return {
|
||||
text: [
|
||||
'发布准备:',
|
||||
`- 项目:${nextManifest.name}`,
|
||||
`- 目录:${nextProjectPath}`,
|
||||
`- 原型:${
|
||||
tracePassed
|
||||
? `最近 run 已通过 ${trace?.runId ?? ''}`.trim()
|
||||
: trace
|
||||
? `最近 run 未通过 ${trace.status} / ${trace.stopReason}`
|
||||
: '暂无最近 run'
|
||||
}`,
|
||||
`- 预览:${previewSummary}${previewRunning ? '' : ' · 建议 /run'}`,
|
||||
`- 任务:完成 ${completedCount}/${tasks.length} · ready ${readyCount} · 失败 ${failedCount}`,
|
||||
`- 资产:${nextManifest.assets.length} 个 · 上传 ${sourceCounts.uploaded} / 生成 ${sourceCounts.generated} / 画板 ${sourceCounts.canvas}`,
|
||||
`- 音频:${audioAssetCount > 0 ? `${audioAssetCount} 个` : '暂无 · 建议 /audio'}`,
|
||||
`- 包装:${
|
||||
hasPublishReadme
|
||||
? '最近 Run 包含 exports/README.md · /read exports/README.md'
|
||||
: '可用 /artifacts 查看发布说明草稿'
|
||||
}`,
|
||||
`- 试玩包:${
|
||||
tracePassed
|
||||
? '可执行 /export 生成本地 ZIP'
|
||||
: '等待最近 run 通过后再导出'
|
||||
}`,
|
||||
latestCommandRun?.status === 'failed'
|
||||
? `- 阻塞:最近命令 ${latestCommandRun.commandId} 失败 · /logs`
|
||||
: null,
|
||||
]
|
||||
.filter(Boolean)
|
||||
.join('\n'),
|
||||
draftCommand,
|
||||
draftCommandLabel,
|
||||
};
|
||||
}
|
||||
|
||||
function summarizeNextProjectActions(
|
||||
nextManifest: GameCreationAppManifest,
|
||||
trace: GameCreationAgentRunTrace | null,
|
||||
@@ -2291,6 +2395,7 @@ function summarizeNextProjectActions(
|
||||
}
|
||||
|
||||
if (trace) {
|
||||
addSuggestion('查看发布准备清单', '/publish');
|
||||
addSuggestion('查看最近 trace 摘要', '/trace');
|
||||
addSuggestion('列出最近 Run 产物', '/run-artifacts');
|
||||
addSuggestion('列出 Agent 运行辅助文件', '/run-files');
|
||||
@@ -5797,6 +5902,28 @@ export function App() {
|
||||
return;
|
||||
}
|
||||
|
||||
if (prompt === '/publish') {
|
||||
const nextProjectPath = requireChatProjectForUserAction();
|
||||
if (!nextProjectPath) {
|
||||
return;
|
||||
}
|
||||
const summary = summarizeProjectPublishReadiness(
|
||||
manifest,
|
||||
nextProjectPath,
|
||||
agentRunTrace,
|
||||
);
|
||||
setMessages((current) => [
|
||||
...current,
|
||||
{
|
||||
role: 'assistant',
|
||||
text: summary.text,
|
||||
draftCommand: summary.draftCommand,
|
||||
draftCommandLabel: summary.draftCommandLabel,
|
||||
},
|
||||
]);
|
||||
return;
|
||||
}
|
||||
|
||||
if (prompt === '/index') {
|
||||
void queueOrExecuteProjectIndex();
|
||||
return;
|
||||
|
||||
@@ -2289,6 +2289,7 @@ describe('AI 游戏创作 App 界面边界', () => {
|
||||
expect(await screen.findByText(/下一步建议:/)).not.toBeNull();
|
||||
expect(screen.getByText(/运行自检并启动本地预览:\/run/)).not.toBeNull();
|
||||
expect(screen.getByText(/查看 .* 个 ready 任务:\/tasks/)).not.toBeNull();
|
||||
expect(screen.getByText(/查看发布准备清单:\/publish/)).not.toBeNull();
|
||||
expect(
|
||||
screen.getByText(/列出 Agent 运行辅助文件:\/run-files/),
|
||||
).not.toBeNull();
|
||||
@@ -2306,6 +2307,56 @@ describe('AI 游戏创作 App 界面边界', () => {
|
||||
),
|
||||
).toHaveLength(runLocalCountBeforeNext);
|
||||
|
||||
const manifestReadCountBeforePublish = invoke.mock.calls.filter(
|
||||
([command]) => command === 'get_local_game_manifest',
|
||||
).length;
|
||||
const fileReadCountBeforePublish = invoke.mock.calls.filter(
|
||||
([command]) => command === 'read_local_project_file',
|
||||
).length;
|
||||
const runLocalCountBeforePublish = invoke.mock.calls.filter(
|
||||
([command]) => command === 'run_limited_local_command',
|
||||
).length;
|
||||
const startPreviewCountBeforePublish = invoke.mock.calls.filter(
|
||||
([command]) => command === 'start_local_game_preview',
|
||||
).length;
|
||||
submitChat('/publish');
|
||||
expect(await screen.findByText(/发布准备:/)).not.toBeNull();
|
||||
expect(
|
||||
screen.getByText(/原型:最近 run 已通过 run-main-shortcut-trace/),
|
||||
).not.toBeNull();
|
||||
expect(screen.getByText(/预览:未启动 · 建议 \/run/)).not.toBeNull();
|
||||
expect(screen.getByText(/音频:暂无 · 建议 \/audio/)).not.toBeNull();
|
||||
expect(
|
||||
screen.getByText(
|
||||
/包装:最近 Run 包含 exports\/README\.md · \/read exports\/README\.md/,
|
||||
),
|
||||
).not.toBeNull();
|
||||
const publishDraftButtons = screen.getAllByRole('button', {
|
||||
name: '启动预览',
|
||||
});
|
||||
fireEvent.click(publishDraftButtons[publishDraftButtons.length - 1]);
|
||||
expect(screen.getByLabelText('创作想法')).toHaveProperty('value', '/run');
|
||||
expect(
|
||||
invoke.mock.calls.filter(
|
||||
([command]) => command === 'get_local_game_manifest',
|
||||
),
|
||||
).toHaveLength(manifestReadCountBeforePublish);
|
||||
expect(
|
||||
invoke.mock.calls.filter(
|
||||
([command]) => command === 'read_local_project_file',
|
||||
),
|
||||
).toHaveLength(fileReadCountBeforePublish);
|
||||
expect(
|
||||
invoke.mock.calls.filter(
|
||||
([command]) => command === 'run_limited_local_command',
|
||||
),
|
||||
).toHaveLength(runLocalCountBeforePublish);
|
||||
expect(
|
||||
invoke.mock.calls.filter(
|
||||
([command]) => command === 'start_local_game_preview',
|
||||
),
|
||||
).toHaveLength(startPreviewCountBeforePublish);
|
||||
|
||||
fireEvent.click(screen.getByRole('button', { name: '权限' }));
|
||||
expect(
|
||||
await screen.findByText(/策略:\.agent\/policy\.json/),
|
||||
@@ -8008,6 +8059,7 @@ describe('AI 游戏创作 App 界面边界', () => {
|
||||
expect(screen.getByText(/\/risks:查看当前项目风险/)).not.toBeNull();
|
||||
expect(screen.getByText(/\/handoff:生成当前项目交接摘要/)).not.toBeNull();
|
||||
expect(screen.getByText(/\/next:查看下一步建议/)).not.toBeNull();
|
||||
expect(screen.getByText(/\/publish:查看发布准备清单/)).not.toBeNull();
|
||||
expect(
|
||||
screen.getByText(/\/run-files:列出 Agent 运行辅助文件读取命令/),
|
||||
).not.toBeNull();
|
||||
|
||||
@@ -3875,7 +3875,8 @@
|
||||
- 2026-07-03 调整:单 Agent 对话面板允许用户把当前输入手动追加到该 agent 的 `memory/agents/<group>/<role>.md` 私有记忆;写入复用 `memory.write` 项目策略、项目锁和 Tauri 本地目录能力,不把普通对话流水自动混入私有记忆;聊天侧 `/agent-conversations` 和 `/agent-memories` 只列出同一批 Agent 对话与私有记忆读取命令并提供首个 `/read` 草稿,不直接读取文件。
|
||||
- 2026-07-03 调整:主窗口新增音效登记和画板音频导入快捷入口,只填入 `/asset-register assets/audio/sfx.wav audio audio/wav` 或 `/import-canvas-asset assets/audio/sfx.wav ` 草稿;聊天输入 `/audio` 只基于当前 manifest 盘点音频素材、来源和路径,并给出登记音效或读取 `assets/manifest.audio.json` 的草稿。音乐组仍复用现有资产登记 / 画板回流链路,不新增独立音频生成系统。
|
||||
- 2026-07-03 调整:主窗口新增常用生成产物读取入口,只把入口 HTML、设计、数值、美术清单、音频清单和发布说明对应的 `/read` 草稿填入聊天输入框;聊天命令 `/artifacts` 只列出同一组固定读取命令并提供首个读取草稿,`/run-artifacts` 只列出最近 trace 里的产物读取命令并提供首个 `/read` 草稿,`/logs` 只列出固定日志读取命令;实际读取仍走聊天侧 `file.read` 权限流,不直接读本地文件。
|
||||
- 2026-07-03 调整:普通用户通过聊天输入 `/next` 触发下一步建议入口,只基于主窗口当前已加载的 manifest、最近 run trace 和最近命令摘要生成聊天建议,列出 `/tasks`、`/trace`、`/run`、`/open-preview`、`/assets`、`/audio`、`/artifacts`、`/run-artifacts`、`/run-files`、`/logs`、`/agent-resume ` 等安全命令草稿方向,并提供一个首选草稿;该命令不得直接执行 Tauri 读写、启动或打开预览、读取本地文件,也不得绕过原有命令确认和 `file.read` 权限流。
|
||||
- 2026-07-03 调整:普通用户通过聊天输入 `/next` 触发下一步建议入口,只基于主窗口当前已加载的 manifest、最近 run trace 和最近命令摘要生成聊天建议,列出 `/tasks`、`/trace`、`/run`、`/open-preview`、`/assets`、`/audio`、`/publish`、`/artifacts`、`/run-artifacts`、`/run-files`、`/logs`、`/agent-resume ` 等安全命令草稿方向,并提供一个首选草稿;该命令不得直接执行 Tauri 读写、启动或打开预览、读取本地文件,也不得绕过原有命令确认和 `file.read` 权限流。
|
||||
- 2026-07-03 调整:普通用户通过聊天输入 `/publish` 生成发布准备清单,只基于主窗口当前已加载的 manifest、最近 run trace、预览状态、资产来源和最近命令摘要列出原型通过、预览、任务、资产、音频、包装说明和试玩包状态,并提供 `/run`、`/trace`、`/agent-resume ` 或 `/export` 草稿;该入口不得触发 Tauri 读写、不得启动或打开预览、不得读取文件,也不得新增普通用户发布面板。
|
||||
- 2026-06-25 调整:本地 HTTP 预览静态 `HEAD` 必须返回与 `GET` 相同的真实 `Content-Length`,但不返回 body;浏览器、图片、音频和视频探测不能拿到 `Content-Length: 0` 的假响应。
|
||||
- 2026-06-25 调整:普通用户通过聊天输入 `/run` 触发待确认 `game.run_local`,确认后只能复用白名单 `game.static_smoke` 自检当前 `game/index.html`,通过后启动 `127.0.0.1` 本地 HTTP 预览。独立执行 `game.static_smoke` 时如果已有 `.agent/run.latest.json`,必须追加 `Playtest / game.static_smoke` trace step,避免“运行了代码但编排 trace 不可见”。
|
||||
- 2026-06-25 调整:普通用户通过聊天输入 `/trace` 触发只读 `agent.trace_read`,读取 `.agent/run.latest.json` 并在聊天里摘要 loop 轮次、stopReason、nextStep、active / carry-over 任务、repairRoutes、agent 建议命令和最近 step。trace 面板仍只在开发窗口展示,普通用户窗口不新增面板。
|
||||
|
||||
@@ -100,7 +100,7 @@ game-project/
|
||||
## v1 验收
|
||||
|
||||
- 用户能创建本地 Web 游戏项目。
|
||||
- 用户侧看到当前工作区项目名 / 路径、最近 run、预览状态、任务完成数 / ready 数、资产数量 / 来源分布、最近命令摘要、聊天框、上传入口、Agent 状态列表和单 Agent 对话;聊天输入 `/brief` 可在普通聊天消息里生成当前项目简报并提供 `/next` 草稿,不新增普通用户面板;聊天输入 `/risks` 可在普通聊天消息里查看当前项目风险并提供首个风险处理草稿,不新增普通用户面板;聊天输入 `/handoff` 可在普通聊天消息里生成当前项目交接摘要并提供 `/next` 草稿,不新增普通用户面板;聊天输入 `/runs` 可在普通聊天消息里列出已加载 Run 历史读取命令,不新增普通用户面板;聊天输入 `/run-files` 可在普通聊天消息里列出 Agent 运行辅助文件读取命令,不新增普通用户面板;聊天输入 `/audio` 可基于当前 manifest 盘点音频素材并提供登记或读取草稿,不新增音频生成系统;聊天输入 `/export` 确认后把当前可试玩原型导出为本地试玩 ZIP,聊天输入 `/exports` 可只读列出已导出的本地试玩包;Agent 状态列表和单 Agent 对话在 `/llm-status` 后显示该 agent 当前 LLM provider / 模型 / 流式 / API Key 读取状态,但不显示密钥本体;最近项目资产入口显示本地路径、kind、mediaType 和来源类型,并可一键填入 `/read` 草稿,开发环境通过独立窗口查看任务拆分、专业组细节、产物、文件面板、嵌入预览以及 `.agent/logs/command.log` / `preview.log` / `agent.log`。
|
||||
- 用户侧看到当前工作区项目名 / 路径、最近 run、预览状态、任务完成数 / ready 数、资产数量 / 来源分布、最近命令摘要、聊天框、上传入口、Agent 状态列表和单 Agent 对话;聊天输入 `/brief` 可在普通聊天消息里生成当前项目简报并提供 `/next` 草稿,不新增普通用户面板;聊天输入 `/risks` 可在普通聊天消息里查看当前项目风险并提供首个风险处理草稿,不新增普通用户面板;聊天输入 `/handoff` 可在普通聊天消息里生成当前项目交接摘要并提供 `/next` 草稿,不新增普通用户面板;聊天输入 `/runs` 可在普通聊天消息里列出已加载 Run 历史读取命令,不新增普通用户面板;聊天输入 `/run-files` 可在普通聊天消息里列出 Agent 运行辅助文件读取命令,不新增普通用户面板;聊天输入 `/audio` 可基于当前 manifest 盘点音频素材并提供登记或读取草稿,不新增音频生成系统;聊天输入 `/publish` 可基于当前 manifest 和最近 run 生成发布准备清单并提供运行、trace、继续或导出草稿,不新增发布面板;聊天输入 `/export` 确认后把当前可试玩原型导出为本地试玩 ZIP,聊天输入 `/exports` 可只读列出已导出的本地试玩包;Agent 状态列表和单 Agent 对话在 `/llm-status` 后显示该 agent 当前 LLM provider / 模型 / 流式 / API Key 读取状态,但不显示密钥本体;最近项目资产入口显示本地路径、kind、mediaType 和来源类型,并可一键填入 `/read` 草稿,开发环境通过独立窗口查看任务拆分、专业组细节、产物、文件面板、嵌入预览以及 `.agent/logs/command.log` / `preview.log` / `agent.log`。
|
||||
- 生成代码和资产进入用户本地项目目录。
|
||||
- 本地 HTTP 预览能启动,并在外部浏览器展示可玩原型。
|
||||
- 美术/音乐资产能从画板链路回流到本地项目。
|
||||
@@ -119,6 +119,7 @@ game-project/
|
||||
- `/export` 聊天入口由 `appSurface.test.ts` 的主窗口 smoke 和 Tauri Rust 测试覆盖:确认后执行 `project.export_package`,导出 `exports/playtest-package-*.zip`,只打包 `game/**`、`assets/**` 和 `exports/README.md`,不包含 `.agent/`、`memory/`、运行时配置、日志、trace 或密钥文件;导出前必须通过 `game/index.html` 可试玩静态验收,并写入 manifest `commandRuns`、`.agent/logs/command.log` 和 `.agent/agent.db`。
|
||||
- `/exports` 聊天入口由 `appSurface.test.ts` 主窗口 smoke、项目权限确认测试和 Tauri Rust 测试覆盖:只读执行 `project.export_list`,列出 `exports/playtest-package-*.zip`,跳过符号链接和非试玩包文件,不删除旧包、不做系统分享、不新增普通用户面板。
|
||||
- `/audio` 聊天入口由 `appSurface.test.ts` 主窗口 smoke 和音频资产定向测试覆盖:只基于当前已加载 manifest 盘点音频素材数量、来源和路径,提供 `/asset-register assets/audio/sfx.wav audio audio/wav` 或 `/read assets/manifest.audio.json` 草稿,不触发 Tauri 文件读取、资产写入、画板导入或新增普通用户面板。
|
||||
- `/publish` 聊天入口由 `appSurface.test.ts` 主窗口 smoke 覆盖:只基于当前已加载 manifest、最近 run trace、预览状态、资产来源和最近命令生成发布准备清单,提供 `/run`、`/trace`、`/agent-resume ` 或 `/export` 草稿,不触发 Tauri 读写、预览启动、文件读取或新增普通用户面板。
|
||||
- 主窗口策略快捷入口只填入 `/policy-confirm project.index`、`/policy-confirm asset.register`、`/policy-confirm memory.write`、`/policy-confirm preview.start`、`/policy-confirm preview.open`、`/policy-confirm preview.stop`、`/policy-confirm agent.run_status`、`/policy-confirm conversation.read` 或 `/policy-confirm conversation.write` 草稿;Agent 状态栏的“继续说明”只填入 `/agent-resume ` 草稿,不直接触发 run 生命周期写入。
|
||||
- 主窗口最近 checkpoint 列表展示 checkpoint id、文件数、大小和创建时间,同时提供直接对比、填入 `/diff`、确认回滚和填入 `/restore`;回滚继续走 `project.restore` 确认卡,不直接写项目文件。
|
||||
- `npm run check:native-shells`:覆盖 AI 游戏创作壳的 release/dev 窗口边界、正式用户 App 不嵌入游戏预览 iframe、用户侧预览命令交给外部浏览器和 Tauri release `--no-bundle` 构建 smoke;用于证明正式发布只登记 `launcher` 启动器窗口,选择工作区后才关闭启动器并打开 `main` 主窗口,开发面板只在 debug/dev 路径打开,独立壳能完成 release 编译。
|
||||
@@ -186,7 +187,8 @@ game-project/
|
||||
- 聊天输入 `/risks` 只使用主窗口当前已加载的 manifest、最近 run trace、预览状态、任务状态、资产来源和最近命令摘要,在聊天里列出当前项目风险,并提供首个风险处理草稿;该命令不调用 Tauri 读写、不读取文件、不启动或打开预览、不新增普通用户面板,用户必须再发送草稿并按原命令权限流继续。
|
||||
- 聊天输入 `/handoff` 只使用主窗口当前已加载的 manifest、最近 run trace、Agent 状态和已载入历史 run 批次,在聊天里生成项目交接摘要,并提供 `/next` 作为后续草稿;该命令不调用 Tauri 读写、不读取文件、不启动或打开预览、不新增普通用户面板,用户必须再发送草稿并按原命令权限流继续。
|
||||
- 聊天输入 `/runs` 只使用主窗口当前已加载的 latest trace 和已载入历史 run 批次,在聊天里列出 `/trace` 和 `/read .agent/runs/...` 读取草稿;该命令不调用 Tauri 读写、不滚动加载更多历史、不启动或打开预览、不新增普通用户面板,用户必须再发送草稿并按原命令权限流继续。
|
||||
- 聊天输入 `/next` 只使用主窗口当前已加载的 manifest、最近 run trace 和最近命令摘要,在聊天里给出下一步建议,列出 `/tasks`、`/trace`、`/run`、`/export`、`/exports`、`/open-preview`、`/assets`、`/audio`、`/artifacts`、`/run-artifacts`、`/run-files`、`/logs`、`/agent-resume ` 等安全命令草稿方向,并提供一个首选草稿;该命令不调用 Tauri 读写、不启动或打开预览、不读取文件,用户必须再发送草稿并按原命令权限流继续。
|
||||
- 聊天输入 `/next` 只使用主窗口当前已加载的 manifest、最近 run trace 和最近命令摘要,在聊天里给出下一步建议,列出 `/tasks`、`/trace`、`/run`、`/export`、`/exports`、`/open-preview`、`/assets`、`/audio`、`/publish`、`/artifacts`、`/run-artifacts`、`/run-files`、`/logs`、`/agent-resume ` 等安全命令草稿方向,并提供一个首选草稿;该命令不调用 Tauri 读写、不启动或打开预览、不读取文件,用户必须再发送草稿并按原命令权限流继续。
|
||||
- 聊天输入 `/publish` 只使用主窗口当前已加载的 manifest、最近 run trace、预览状态、资产来源和最近命令摘要,在聊天里生成发布准备清单,列出原型通过状态、预览、任务、资产、音频、包装说明和试玩包导出状态,并提供 `/run`、`/trace`、`/agent-resume ` 或 `/export` 草稿;该命令不调用 Tauri 读写、不启动或打开预览、不读取文件、不新增普通用户面板,真正导出仍由用户发送 `/export` 并走确认流。
|
||||
- 主窗口可从 agent 状态列表进入单个 agent 对话;该入口只加载目标 agent 的 conversation JSONL,发送消息后追加到同一 agent conversation,不开启平行任务图、不 fork run,也不归档历史会话。
|
||||
- v1 通过独立启动器窗口选择本地项目后再进入主窗口;主窗口只承载当前工作区的聊天、配置和 agent 状态,切换项目时关闭当前主窗口并回到启动器,主窗口按钮和 `/switch-project` 聊天命令都复用同一 Tauri 启动器入口,避免在主窗口内用遮罩面板混合多个工作区上下文。
|
||||
- 主窗口可通过系统文件管理器显示当前项目目录,也可在聊天输入 `/open-project` 走同一只读打开动作;该操作只打开本地目录,不初始化项目、不写项目文件、不切换工作区。主窗口头部显示最近 `.agent/run.latest.json` 的 run 状态摘要和当前项目预览状态,并通过“刷新状态”重新读取同一 trace,不新增状态数据库。
|
||||
|
||||
Reference in New Issue
Block a user