refactor: dedupe the jscpd clones; drop the baseline loading gate

- Extract the shared New Session action into WorkspacesService.startSession
  (sidebar button and workspace browser both delegate; recent-Workspace
  targeting and the no-workspace clear live in one place).
- Fold the chip-insertion transaction shared by insert-ref and paste-upgrade
  into one InputMachine helper.
- Share the fixture's session-not-found guard across the sessionId-addressed
  catalog routes.
- Drop the AppFrame baselines-ready loading gate (user ruling: the bare
  status line reads worse than the shell's own pending rendering); both
  column occupants mount from first paint.
This commit is contained in:
imccyu
2026-07-27 08:51:05 +08:00
parent 084e64744a
commit dd2d9ca50a
9 changed files with 75 additions and 103 deletions

View File

@@ -428,6 +428,15 @@ export function createFixtureApi(options: FixtureOptions = {}): ApiProxy {
}
const summaryOf = (id: SessionId): SessionSummary | undefined => sessions.find(s => s.sessionId === id)
/** Shared session guard for sessionId-addressed catalog routes: the error response when the session is unknown, undefined when it exists. */
const requireSession = (request: RpcRequest<{ sessionId: SessionId }>): Promise<RpcResponse<never>> | undefined =>
summaryOf(request.payload.sessionId) === undefined
? err<{ sessionId: SessionId }, never>(request, {
code: 'session-not-found',
message: `no session ${request.payload.sessionId}`,
details: { sessionId: request.payload.sessionId },
})
: undefined
const setRunning = (id: SessionId, running: boolean): void => {
const summary = summaryOf(id)
if (summary === undefined || summary.running === running) return
@@ -746,14 +755,8 @@ export function createFixtureApi(options: FixtureOptions = {}): ApiProxy {
// The catalog mirrors one session's effective view (every fixture
// session has an agent, like the real host).
list: (request) => {
const summary = summaryOf(request.payload.sessionId)
if (summary === undefined) {
return err(request, {
code: 'session-not-found',
message: `no session ${request.payload.sessionId}`,
details: { sessionId: request.payload.sessionId },
})
}
const missing = requireSession(request)
if (missing !== undefined) return missing
return ok(request, {
commands: [
{ name: 'compact', description: 'fixture压缩当前会话上下文' },
@@ -763,14 +766,8 @@ export function createFixtureApi(options: FixtureOptions = {}): ApiProxy {
})
},
execute: (request) => {
const summary = summaryOf(request.payload.sessionId)
if (summary === undefined) {
return err(request, {
code: 'session-not-found',
message: `no session ${request.payload.sessionId}`,
details: { sessionId: request.payload.sessionId },
})
}
const missing = requireSession(request)
if (missing !== undefined) return missing
const line = request.payload.line.trim()
const match = /^\/(\S+)(?:\s+(.*))?$/.exec(line)
const name = match?.[1]
@@ -791,14 +788,8 @@ export function createFixtureApi(options: FixtureOptions = {}): ApiProxy {
},
skills: {
list: (request) => {
const summary = summaryOf(request.payload.sessionId)
if (summary === undefined) {
return err(request, {
code: 'session-not-found',
message: `no session ${request.payload.sessionId}`,
details: { sessionId: request.payload.sessionId },
})
}
const missing = requireSession(request)
if (missing !== undefined) return missing
return ok(request, {
skills: [
{ name: 'fixture-demo', description: 'fixture 技能样本', whenToUse: '仅供 UI 目录渲染验收' },