补齐 DirectProject 更早历史入口
Project CI / AI game creator shell Rust shard 1/4 (pull_request) Failing after 5m1s
Project CI / AI game creator shell Rust shard 3/4 (pull_request) Failing after 4m24s
Project CI / AI game creator shell Rust shard 2/4 (pull_request) Failing after 4m51s
Project CI / AI game creator shell Rust smoke (pull_request) Successful in 1m45s
Project CI / AI game creator shell Rust shard 4/4 (pull_request) Failing after 4m20s
Project CI / AI game creator shell Rust crates (pull_request) Successful in 2m24s
Project CI / Native shell tests (pull_request) Failing after 2m22s
Project CI / AI game creator shell web tests (pull_request) Failing after 53s
Project CI / Frontend tests (pull_request) Failing after 2m51s
Project CI / Repository checks (pull_request) Failing after 3m5s
Project CI / Backend tests (pull_request) Successful in 6m32s

补充 DirectProject 初始历史 hasMore 时的按钮与滚动入口
修正 rebase 后 Tauri 命令与 Rust 测试辅助函数可见性
同步更新 DirectProject 历史恢复规范与里程碑验收记录
This commit is contained in:
kdletters
2026-09-15 21:53:57 +08:00
parent 47bb42844b
commit 246f49cec8
11 changed files with 41 additions and 13 deletions
@@ -20,7 +20,7 @@ pub(crate) fn direct_codex_canonical_project_identity(
))
}
fn direct_codex_os_path_identity_bytes(path: &std::path::Path) -> Vec<u8> {
pub(super) fn direct_codex_os_path_identity_bytes(path: &std::path::Path) -> Vec<u8> {
#[cfg(unix)]
{
use std::os::unix::ffi::OsStrExt;
@@ -39,7 +39,10 @@ fn direct_codex_os_path_identity_bytes(path: &std::path::Path) -> Vec<u8> {
path.as_os_str().to_string_lossy().as_bytes().to_vec()
}
fn direct_codex_project_identity_digest(path_identity: &[u8], project_id: &[u8]) -> String {
pub(super) fn direct_codex_project_identity_digest(
path_identity: &[u8],
project_id: &[u8],
) -> String {
let mut digest = Sha256::new();
digest.update(b"genarrative-direct-project-identity.v1\0");
digest.update((path_identity.len() as u64).to_le_bytes());
@@ -7,7 +7,7 @@ use std::path::{Path, PathBuf};
use std::sync::{Mutex, OnceLock};
mod user_input;
pub(crate) use user_input::chat_with_game_creator_direct_codex;
pub(crate) use user_input::{chat_with_game_creator_direct_codex, normalize_direct_client_turn_id};
const MAX_DIRECT_SYSTEM_PROMPT_CHARS: usize = 16 * 1024;
const MIN_DIRECT_CLIENT_TURN_ID_CHARS: usize = 6;
@@ -5,7 +5,9 @@
use super::*;
fn normalize_direct_client_turn_id(client_turn_id: Option<&str>) -> Result<String, String> {
pub(crate) fn normalize_direct_client_turn_id(
client_turn_id: Option<&str>,
) -> Result<String, String> {
let Some(client_turn_id) = client_turn_id else {
return Err("Direct 客户端回合缺少稳定 clientTurnId,已拒绝创建可计费生成身份".to_string());
};
@@ -5277,7 +5277,9 @@ pub(crate) async fn read_agent_runtime_error_detail(
})
.await
.map_err(|error| format!("读取统一错误诊断后台任务失败:{error}"))?
}
#[tauri::command]
pub(crate) async fn subscribe_direct_project_thread(
project_path: String,
) -> Result<DirectThreadSubscriptionBootstrap, String> {
+7 -1
View File
@@ -11867,6 +11867,9 @@ export function App({
0,
messages.length - visibleMessages.length,
);
const hasEarlierConversationMessages =
hiddenConversationCount > 0 ||
(directCodexProductRuntime && directHistoryHasMore);
const projectSupervisorTransientReply =
projectSupervisorResponseStream?.accumulatedText.trim() ?? '';
const projectSupervisorNeedsUserInput = agentRuntimeNeedsUserInput(
@@ -11963,7 +11966,7 @@ export function App({
}
function handleConversationScroll(event: UIEvent<HTMLElement>) {
if (hiddenConversationCount === 0) {
if (!hasEarlierConversationMessages) {
return;
}
if (event.currentTarget.scrollTop <= 24) {
@@ -12129,6 +12132,7 @@ export function App({
onOpenRuntimeConfig={() => setRuntimeConfigOpen(true)}
onScroll={handleSupervisorChatScroll}
onShowEarlierMessages={showEarlierConversationMessages}
hasEarlierConversationMessages={hasEarlierConversationMessages}
onSubmit={handleProjectSupervisorOnlySubmit}
onToolAction={handleProjectSupervisorToolAction}
onUserInput={handleProjectSupervisorUserInput}
@@ -12173,6 +12177,7 @@ export function App({
}
directProcessKey={directCodexProcessKey}
hiddenConversationCount={hiddenConversationCount}
hasEarlierConversationMessages={hasEarlierConversationMessages}
messagesRef={supervisorChatMessagesRef}
needsUserInput={
directCodexProductRuntime ? false : projectSupervisorNeedsUserInput
@@ -12408,6 +12413,7 @@ export function App({
}
handleRuntimeConfigOpen={handleRuntimeConfigOpen}
hiddenConversationCount={hiddenConversationCount}
hasEarlierConversationMessages={hasEarlierConversationMessages}
llmConfigStatus={llmConfigStatus}
loadProjectConversation={loadProjectConversation}
localProject={localProject}
@@ -85,6 +85,7 @@ type ProjectSupervisorViewProps = RuntimePanelProps & {
directProcessDetail?: string;
directProcessKey?: string;
hiddenConversationCount: number;
hasEarlierConversationMessages?: boolean;
messagesRef: RefObject<HTMLDivElement | null>;
needsUserInput: boolean;
onCancelConfirmation: () => void;
@@ -139,6 +140,7 @@ export function ProjectSupervisorView({
directProcessDetail = '',
directProcessKey = '',
hiddenConversationCount,
hasEarlierConversationMessages = false,
messagesRef,
needsUserInput,
onCancelConfirmation,
@@ -250,13 +252,15 @@ export function ProjectSupervisorView({
aria-label={directCodex ? '陶泥儿消息' : '项目总控消息'}
onScroll={onScroll}
>
{hiddenConversationCount > 0 ? (
{hiddenConversationCount > 0 || hasEarlierConversationMessages ? (
<button
type="button"
className="message-history-more"
onClick={onShowEarlierMessages}
>
{`显示更早 · 还有 ${hiddenConversationCount} 条对话`}
{hiddenConversationCount > 0
? `显示更早 · 还有 ${hiddenConversationCount} 条对话`
: '显示更早的对话'}
</button>
) : null}
{visibleMessages.map((message, index) => (
@@ -157,6 +157,7 @@ type ProjectWorkspaceChatPaneProps = {
handleRevealCurrentProjectDirectory: () => Promise<void>;
handleRuntimeConfigOpen: () => void;
hiddenConversationCount: number;
hasEarlierConversationMessages?: boolean;
llmConfigStatus: GameCreatorLlmConfigStatus | null;
loadProjectConversation: (
nextProjectPath: string,
@@ -256,6 +257,7 @@ export function ProjectWorkspaceChatPane({
handleRevealCurrentProjectDirectory,
handleRuntimeConfigOpen,
hiddenConversationCount,
hasEarlierConversationMessages = false,
llmConfigStatus,
loadProjectConversation,
localProject,
@@ -809,13 +811,15 @@ export function ProjectWorkspaceChatPane({
</div>
) : null}
<div className="message-list" onScroll={handleConversationScroll}>
{hiddenConversationCount > 0 ? (
{hiddenConversationCount > 0 || hasEarlierConversationMessages ? (
<button
type="button"
className="message-history-more"
onClick={showEarlierConversationMessages}
>
{`显示更早 · 还有 ${hiddenConversationCount} 条对话`}
{hiddenConversationCount > 0
? `显示更早 · 还有 ${hiddenConversationCount} 条对话`
: '显示更早的对话'}
</button>
) : null}
{visibleMessages.map((message, index) => (
@@ -71,6 +71,7 @@ type SupervisorChatOnlyViewProps = {
transientReply: string;
hasConversationControls: boolean;
hiddenConversationCount: number;
hasEarlierConversationMessages?: boolean;
needsUserInput: boolean;
visibleMessages: ChatMessage[];
workspaceStatus: string;
@@ -108,6 +109,7 @@ export function SupervisorChatOnlyView({
transientReply,
hasConversationControls,
hiddenConversationCount,
hasEarlierConversationMessages = false,
needsUserInput,
visibleMessages,
workspaceStatus,
@@ -188,12 +190,16 @@ export function SupervisorChatOnlyView({
aria-label={directCodex ? '陶泥儿消息' : '项目总控消息'}
onScroll={handleScroll}
>
{hiddenConversationCount > 0 ? (
{hiddenConversationCount > 0 || hasEarlierConversationMessages ? (
<button
type="button"
className="message-history-more"
onClick={onShowEarlierMessages}
>{`显示更早 · 还有 ${hiddenConversationCount} 条对话`}</button>
>
{hiddenConversationCount > 0
? `显示更早 · 还有 ${hiddenConversationCount} 条对话`
: '显示更早的对话'}
</button>
) : null}
{visibleMessages.map((message, index) => (
<div