Merge pull request #1363 from pikasTech/fix/1361-route-conversation-detail
fix: hydrate routed workbench conversation detail
This commit is contained in:
@@ -25,7 +25,11 @@ if (explicitAnyCount > 0) {
|
||||
process.exit(2);
|
||||
}
|
||||
|
||||
const vueTscBin = path.join(rootDir, "node_modules/.bin/vue-tsc");
|
||||
const vueTscBin = resolveVueTscBin(rootDir);
|
||||
if (!vueTscBin) {
|
||||
console.error("hwlab-cloud-web tsc-check: vue-tsc not found in ancestor node_modules/.bin or PATH");
|
||||
process.exit(2);
|
||||
}
|
||||
const result = spawnSync(vueTscBin, ["--noEmit", "--project", path.join(rootDir, "tsconfig.json")], { cwd: rootDir, encoding: "utf8" });
|
||||
if (result.stdout) process.stdout.write(result.stdout);
|
||||
if (result.stderr) process.stderr.write(result.stderr);
|
||||
@@ -36,6 +40,30 @@ if (result.status !== 0) {
|
||||
}
|
||||
console.log("hwlab-cloud-web tsc-check: passed (strict Vue TS, 0 explicit any)");
|
||||
|
||||
function resolveVueTscBin(startDir: string): string | null {
|
||||
let current = startDir;
|
||||
while (true) {
|
||||
const candidate = path.join(current, "node_modules/.bin/vue-tsc");
|
||||
if (isRunnableFile(candidate)) return candidate;
|
||||
const parent = path.dirname(current);
|
||||
if (parent === current) break;
|
||||
current = parent;
|
||||
}
|
||||
for (const dir of (process.env.PATH ?? "").split(path.delimiter).filter(Boolean)) {
|
||||
const candidate = path.join(dir, process.platform === "win32" ? "vue-tsc.cmd" : "vue-tsc");
|
||||
if (isRunnableFile(candidate)) return candidate;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function isRunnableFile(candidate: string): boolean {
|
||||
try {
|
||||
return statSync(candidate).isFile();
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function collectSourceFiles(dir: string): string[] {
|
||||
const out: string[] = [];
|
||||
for (const entry of readdirSync(dir)) {
|
||||
|
||||
@@ -13,6 +13,10 @@ const TRACE_HYDRATION_MAX_PAGES = 60;
|
||||
const TRACE_HYDRATION_MAX_ATTEMPTS = 3;
|
||||
const TRACE_HYDRATION_RETRY_DELAY_MS = 700;
|
||||
|
||||
interface HydrateOptions {
|
||||
conversationId?: string | null;
|
||||
}
|
||||
|
||||
export const useWorkbenchStore = defineStore("workbench", () => {
|
||||
const projectId = ref(resolveInitialWorkbenchProjectId());
|
||||
const workspace = ref<WorkspaceRecord | null>(window.HWLAB_CLOUD_WEB_WORKSPACE_BOOTSTRAP?.workspace ?? null);
|
||||
@@ -52,7 +56,7 @@ export const useWorkbenchStore = defineStore("workbench", () => {
|
||||
activityRef.value = { lastActivityAt: now, lastActivityIso: new Date(now).toISOString(), waitingFor: "code-agent", lastEventLabel: label };
|
||||
}
|
||||
|
||||
async function hydrate(): Promise<void> {
|
||||
async function hydrate(options: HydrateOptions = {}): Promise<void> {
|
||||
const requestEpoch = workspaceSelectionEpoch.value;
|
||||
const previousConversationId = activeConversationId.value;
|
||||
conversationsReady.value = conversations.value.length > 0;
|
||||
@@ -67,7 +71,8 @@ export const useWorkbenchStore = defineStore("workbench", () => {
|
||||
const nextWorkspace = workspaceResult.data?.workspace ?? null;
|
||||
const nextProjectId = workspaceProjectId(nextWorkspace, projectId.value);
|
||||
projectId.value = nextProjectId;
|
||||
const selectedConversationId = selectedConversationIdFromWorkspace(nextWorkspace);
|
||||
const routeConversationId = normalizeWorkbenchConversationId(options.conversationId);
|
||||
const selectedConversationId = routeConversationId ?? selectedConversationIdFromWorkspace(nextWorkspace);
|
||||
const [conversationsResult, selectedConversationResult] = await Promise.all([
|
||||
api.workbench.conversations(nextProjectId, { includeConversationId: selectedConversationId }),
|
||||
selectedConversationId ? api.workbench.conversation(selectedConversationId, { projectId: nextProjectId }) : Promise.resolve(null)
|
||||
@@ -89,7 +94,11 @@ export const useWorkbenchStore = defineStore("workbench", () => {
|
||||
error.value = conversations.value.length > 0 ? null : conversationsResult.error ?? "session list unavailable";
|
||||
}
|
||||
if (selectedConversationId && selectedConversationResult && !selectedConversationResult.ok) error.value = selectedConversationResult.error ?? "conversation unavailable";
|
||||
const workspaceSnapshot = selectedConversation ? workspaceWithSelectedConversation(nextWorkspace, selectedConversation, conversationProjectId(selectedConversation, nextProjectId)) : nextWorkspace;
|
||||
const workspaceSnapshot = selectedConversation
|
||||
? workspaceWithSelectedConversation(nextWorkspace, selectedConversation, conversationProjectId(selectedConversation, nextProjectId))
|
||||
: routeConversationId
|
||||
? workspaceWithSelectedConversationId(nextWorkspace, routeConversationId, nextProjectId)
|
||||
: nextWorkspace;
|
||||
if (shouldApplyWorkspaceSnapshot({ requestEpoch, currentEpoch: workspaceSelectionEpoch.value, currentConversationId: activeConversationId.value, workspace: workspaceSnapshot })) {
|
||||
workspace.value = workspaceSnapshot;
|
||||
providerProfile.value = firstNonEmptyString(workspace.value?.providerProfile, workspace.value?.workspace?.providerProfile, providerProfile.value) ?? providerProfile.value;
|
||||
@@ -733,6 +742,22 @@ function workspaceWithSelectedConversation(current: WorkspaceRecord | null, conv
|
||||
};
|
||||
}
|
||||
|
||||
function workspaceWithSelectedConversationId(current: WorkspaceRecord | null, conversationId: string, projectId: string): WorkspaceRecord | null {
|
||||
if (!current) return current;
|
||||
const selectedConversation = current.selectedConversation?.conversationId === conversationId ? current.selectedConversation : undefined;
|
||||
return {
|
||||
...current,
|
||||
projectId,
|
||||
selectedConversationId: conversationId,
|
||||
selectedConversation,
|
||||
workspace: {
|
||||
...(current.workspace ?? {}),
|
||||
projectId,
|
||||
selectedConversationId: conversationId
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function conversationProjectId(conversation: ConversationRecord | null | undefined, fallback: string): string {
|
||||
return firstNonEmptyString(conversation?.projectId, fallback) ?? DEFAULT_WORKBENCH_PROJECT_ID;
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ onMounted(async () => {
|
||||
componentActive.value = true;
|
||||
applyingRouteConversation.value = Boolean(routeConversationId.value);
|
||||
try {
|
||||
await workbench.hydrate();
|
||||
await workbench.hydrate({ conversationId: routeConversationId.value });
|
||||
await applyRouteConversation();
|
||||
} finally {
|
||||
applyingRouteConversation.value = false;
|
||||
|
||||
Reference in New Issue
Block a user