mirror of
https://github.com/murashit/codex-panel.git
synced 2026-07-22 06:57:10 +00:00
Organize chat host wiring modules
This commit is contained in:
parent
2cb3844011
commit
2b543f5904
25 changed files with 273 additions and 227 deletions
|
|
@ -63,10 +63,6 @@
|
|||
},
|
||||
|
||||
// App-server and generated protocol boundaries.
|
||||
{
|
||||
"path": "./scripts/grit/import-boundaries/no-app-server-root-module-imports.grit",
|
||||
"includes": ["**/src/**/*.ts", "**/src/**/*.tsx"]
|
||||
},
|
||||
{
|
||||
"path": "./scripts/grit/import-boundaries/no-app-server-subfolder-root-imports.grit",
|
||||
"includes": ["**/src/app-server/**/*.ts"]
|
||||
|
|
|
|||
|
|
@ -1,16 +0,0 @@
|
|||
language js
|
||||
|
||||
private pattern js_module_reference() {
|
||||
or {
|
||||
JsImport(),
|
||||
JsImportCallExpression()
|
||||
}
|
||||
}
|
||||
|
||||
js_module_reference() as $stmt where {
|
||||
$stmt <: contains `$source` where {
|
||||
$source <: r"^[\"'](?:(?:\./)?app-server|(?:\.\./)+app-server|src/app-server)/[^/\"']+[\"']$",
|
||||
not { $filename <: r".*/src/features/chat/[^/]+/.*", $source <: r"^[\"']\.\./app-server/[^/\"']+[\"']$" }
|
||||
},
|
||||
register_diagnostic(span=$stmt, message="Import app-server boundary modules from responsibility subfolders, not src/app-server root modules.", severity="error")
|
||||
}
|
||||
|
|
@ -1,17 +1,17 @@
|
|||
import { Notice } from "obsidian";
|
||||
|
||||
import { runtimeConfigOrDefault } from "../../../domain/runtime/config";
|
||||
import { runtimeSnapshotForChatState } from "../application/runtime/snapshot";
|
||||
import type { ChatStateStore } from "../application/state/store";
|
||||
import { resolveRuntimeControls } from "../domain/runtime/resolution";
|
||||
import { ChatComposerController } from "../panel/composer-controller";
|
||||
import { type ChatPanelComposerSurface, chatPanelComposerProjection } from "../panel/surface/composer-projection";
|
||||
import type { ChatMessageScrollController } from "../panel/surface/message-stream-scroll";
|
||||
import { createVaultComposerAttachmentHandler } from "./composer-attachments.obsidian";
|
||||
import type { ChatPanelEnvironment } from "./contracts";
|
||||
import { runtimeConfigOrDefault } from "../../../../domain/runtime/config";
|
||||
import { runtimeSnapshotForChatState } from "../../application/runtime/snapshot";
|
||||
import type { ChatStateStore } from "../../application/state/store";
|
||||
import { resolveRuntimeControls } from "../../domain/runtime/resolution";
|
||||
import { ChatComposerController } from "../../panel/composer-controller";
|
||||
import { type ChatPanelComposerSurface, chatPanelComposerProjection } from "../../panel/surface/composer-projection";
|
||||
import type { ChatMessageScrollController } from "../../panel/surface/message-stream-scroll";
|
||||
import type { ChatPanelEnvironment } from "../contracts";
|
||||
import { createVaultComposerAttachmentHandler } from "../obsidian/composer-attachments.obsidian";
|
||||
import { VaultComposerContextReferenceProvider } from "../obsidian/vault-composer-context-reference-provider.obsidian";
|
||||
import { VaultNoteCandidateProvider } from "../obsidian/vault-note-candidate-provider.obsidian";
|
||||
import type { ChatPanelRuntimeSettingsActions } from "./runtime-bundle";
|
||||
import { VaultComposerContextReferenceProvider } from "./vault-composer-context-reference-provider.obsidian";
|
||||
import { VaultNoteCandidateProvider } from "./vault-note-candidate-provider.obsidian";
|
||||
|
||||
interface ChatPanelComposerHost {
|
||||
environment: ChatPanelEnvironment;
|
||||
|
|
@ -1,26 +1,26 @@
|
|||
import { Notice } from "obsidian";
|
||||
|
||||
import type { AppServerClient } from "../../../app-server/connection/client";
|
||||
import { type ConnectionManager, StaleConnectionError } from "../../../app-server/connection/connection-manager";
|
||||
import { isStaleAppServerSharedQueryContextError } from "../../../app-server/query/shared-queries";
|
||||
import type { LocalIdSource } from "../../../shared/id/local-id";
|
||||
import type { ConnectionWorkTracker } from "../../../shared/lifecycle/connection-work";
|
||||
import { type ChatServerDiagnosticsActions, createChatServerDiagnosticsActions } from "../app-server/actions/diagnostics";
|
||||
import { type ChatServerMetadataActions, createChatServerMetadataActions } from "../app-server/actions/metadata";
|
||||
import { type ChatServerThreadActions, createChatServerThreadActions } from "../app-server/actions/threads";
|
||||
import { type ChatInboundHandler, createChatInboundHandler } from "../app-server/inbound/handler";
|
||||
import type { AppServerClient } from "../../../../app-server/connection/client";
|
||||
import { type ConnectionManager, StaleConnectionError } from "../../../../app-server/connection/connection-manager";
|
||||
import { isStaleAppServerSharedQueryContextError } from "../../../../app-server/query/shared-queries";
|
||||
import type { LocalIdSource } from "../../../../shared/id/local-id";
|
||||
import type { ConnectionWorkTracker } from "../../../../shared/lifecycle/connection-work";
|
||||
import { type ChatServerDiagnosticsActions, createChatServerDiagnosticsActions } from "../../app-server/actions/diagnostics";
|
||||
import { type ChatServerMetadataActions, createChatServerMetadataActions } from "../../app-server/actions/metadata";
|
||||
import { type ChatServerThreadActions, createChatServerThreadActions } from "../../app-server/actions/threads";
|
||||
import { type ChatInboundHandler, createChatInboundHandler } from "../../app-server/inbound/handler";
|
||||
import {
|
||||
type ChatConnectionController,
|
||||
createChatConnectionController,
|
||||
handleChatConnectionExit,
|
||||
} from "../application/connection/connection-controller";
|
||||
import { runtimeSnapshotForChatState } from "../application/runtime/snapshot";
|
||||
import type { ChatConnectionPhase } from "../application/state/root-reducer";
|
||||
import type { ChatStateStore } from "../application/state/store";
|
||||
import type { AutoTitleCoordinator } from "../application/threads/auto-title-coordinator";
|
||||
import type { createThreadGoalSyncActions } from "../application/threads/goal-actions";
|
||||
import type { ChatPanelEnvironment } from "./contracts";
|
||||
import type { ChatViewDeferredTasks } from "./deferred-work";
|
||||
} from "../../application/connection/connection-controller";
|
||||
import { runtimeSnapshotForChatState } from "../../application/runtime/snapshot";
|
||||
import type { ChatConnectionPhase } from "../../application/state/root-reducer";
|
||||
import type { ChatStateStore } from "../../application/state/store";
|
||||
import type { AutoTitleCoordinator } from "../../application/threads/auto-title-coordinator";
|
||||
import type { createThreadGoalSyncActions } from "../../application/threads/goal-actions";
|
||||
import type { ChatPanelEnvironment } from "../contracts";
|
||||
import type { ChatViewDeferredTasks } from "../session/deferred-work";
|
||||
|
||||
type CurrentAppServerClient = () => AppServerClient | null;
|
||||
|
||||
53
src/features/chat/host/bundles/reconnect-bundle.ts
Normal file
53
src/features/chat/host/bundles/reconnect-bundle.ts
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
import type { ConnectionManager } from "../../../../app-server/connection/connection-manager";
|
||||
import type { ConnectionWorkTracker } from "../../../../shared/lifecycle/connection-work";
|
||||
import { type ChatReconnectActionsHost, reconnectPanel } from "../../application/connection/reconnect-actions";
|
||||
import type { ChatConnectionPhase } from "../../application/state/root-reducer";
|
||||
import type { ChatStateStore } from "../../application/state/store";
|
||||
import type { ChatViewDeferredTasks } from "../session/deferred-work";
|
||||
|
||||
interface ChatPanelReconnectStatus {
|
||||
set: (statusText: string, phase?: ChatConnectionPhase) => void;
|
||||
addSystemMessage: (text: string) => void;
|
||||
}
|
||||
|
||||
interface ChatPanelReconnectHost {
|
||||
stateStore: ChatStateStore;
|
||||
connectionWork: ConnectionWorkTracker;
|
||||
deferredTasks: ChatViewDeferredTasks;
|
||||
}
|
||||
|
||||
interface ChatPanelReconnectInput {
|
||||
connection: ConnectionManager;
|
||||
ensureConnected: () => Promise<void>;
|
||||
invalidateThreadWork: () => void;
|
||||
resumeThread: (threadId: string) => Promise<void>;
|
||||
status: ChatPanelReconnectStatus;
|
||||
}
|
||||
|
||||
export function createReconnectAction(host: ChatPanelReconnectHost, input: ChatPanelReconnectInput): () => Promise<void> {
|
||||
const reconnectHost: ChatReconnectActionsHost = {
|
||||
stateStore: host.stateStore,
|
||||
invalidateConnectionWork: () => {
|
||||
host.connectionWork.invalidate();
|
||||
},
|
||||
invalidateThreadWork: () => {
|
||||
input.invalidateThreadWork();
|
||||
},
|
||||
clearDeferredDiagnostics: () => {
|
||||
host.deferredTasks.clearDiagnostics();
|
||||
},
|
||||
resetConnection: () => {
|
||||
input.connection.resetConnection();
|
||||
},
|
||||
setStatus: (statusText, phase) => {
|
||||
input.status.set(statusText, phase);
|
||||
},
|
||||
ensureConnected: input.ensureConnected,
|
||||
resumeThread: input.resumeThread,
|
||||
addSystemMessage: (text) => {
|
||||
input.status.addSystemMessage(text);
|
||||
},
|
||||
};
|
||||
|
||||
return () => reconnectPanel(reconnectHost);
|
||||
}
|
||||
|
|
@ -1,11 +1,11 @@
|
|||
import type { ConnectionManager } from "../../../app-server/connection/connection-manager";
|
||||
import type { ChatAppServerGateway } from "../app-server/session-gateway";
|
||||
import { type ChatRuntimeSettingsActions, createChatRuntimeSettingsActions } from "../application/runtime/settings-actions";
|
||||
import { runtimeSnapshotForChatState } from "../application/runtime/snapshot";
|
||||
import type { ChatStateStore } from "../application/state/store";
|
||||
import { collaborationModeLabel as formatCollaborationModeLabel } from "../domain/runtime/labels";
|
||||
import { type ChatPanelRuntimeProjection, createChatPanelRuntimeProjection } from "../panel/runtime-status-projection";
|
||||
import type { ChatPanelEnvironment } from "./contracts";
|
||||
import type { ConnectionManager } from "../../../../app-server/connection/connection-manager";
|
||||
import type { ChatAppServerGateway } from "../../app-server/session-gateway";
|
||||
import { type ChatRuntimeSettingsActions, createChatRuntimeSettingsActions } from "../../application/runtime/settings-actions";
|
||||
import { runtimeSnapshotForChatState } from "../../application/runtime/snapshot";
|
||||
import type { ChatStateStore } from "../../application/state/store";
|
||||
import { collaborationModeLabel as formatCollaborationModeLabel } from "../../domain/runtime/labels";
|
||||
import { type ChatPanelRuntimeProjection, createChatPanelRuntimeProjection } from "../../panel/runtime-status-projection";
|
||||
import type { ChatPanelEnvironment } from "../contracts";
|
||||
|
||||
export type ChatPanelRuntimeSettingsActions = ChatRuntimeSettingsActions;
|
||||
|
||||
|
|
@ -1,18 +1,18 @@
|
|||
import type { ConnectionManager } from "../../../app-server/connection/connection-manager";
|
||||
import type { PendingRequestActions } from "../application/pending-requests/pending-request-actions";
|
||||
import type { ChatStateStore } from "../application/state/store";
|
||||
import type { HistoryController } from "../application/threads/history-controller";
|
||||
import type { ThreadRenameEditorActions } from "../application/threads/rename-editor-actions";
|
||||
import type { ChatPanelShellParts } from "../panel/shell.dom";
|
||||
import type { ChatPanelGoalSurface } from "../panel/surface/goal-projection";
|
||||
import { MessageStreamPresenter } from "../panel/surface/message-stream-presenter";
|
||||
import type { ChatMessageScrollController } from "../panel/surface/message-stream-scroll";
|
||||
import type { ChatPanelToolbarSurface } from "../panel/surface/toolbar-projection";
|
||||
import { createToolbarUiActions, type ToolbarPanelActions } from "../panel/toolbar-actions";
|
||||
import { toolbarOutsidePointerHit } from "../panel/toolbar-hit-test.dom";
|
||||
import type { ConnectionManager } from "../../../../app-server/connection/connection-manager";
|
||||
import type { PendingRequestActions } from "../../application/pending-requests/pending-request-actions";
|
||||
import type { ChatStateStore } from "../../application/state/store";
|
||||
import type { HistoryController } from "../../application/threads/history-controller";
|
||||
import type { ThreadRenameEditorActions } from "../../application/threads/rename-editor-actions";
|
||||
import type { ChatPanelShellParts } from "../../panel/shell.dom";
|
||||
import type { ChatPanelGoalSurface } from "../../panel/surface/goal-projection";
|
||||
import { MessageStreamPresenter } from "../../panel/surface/message-stream-presenter";
|
||||
import type { ChatMessageScrollController } from "../../panel/surface/message-stream-scroll";
|
||||
import type { ChatPanelToolbarSurface } from "../../panel/surface/toolbar-projection";
|
||||
import { createToolbarUiActions, type ToolbarPanelActions } from "../../panel/toolbar-actions";
|
||||
import { toolbarOutsidePointerHit } from "../../panel/toolbar-hit-test.dom";
|
||||
import type { ChatPanelEnvironment } from "../contracts";
|
||||
import type { ChatPanelComposerBundle } from "./composer-bundle";
|
||||
import type { ChatPanelConnectionBundle } from "./connection-bundle";
|
||||
import type { ChatPanelEnvironment } from "./contracts";
|
||||
import type { ChatPanelGoalActions, ChatPanelThreadActions, ChatPanelThreadNavigationActions } from "./thread-bundle";
|
||||
import type { ChatPanelTurnBundle } from "./turn-bundle";
|
||||
|
||||
|
|
@ -1,33 +1,33 @@
|
|||
import { Notice } from "obsidian";
|
||||
|
||||
import { recoverRolloutTokenUsage } from "../../../app-server/services/rollout-token-usage";
|
||||
import { normalizeExplicitThreadName } from "../../../domain/threads/model";
|
||||
import type { LocalIdSource } from "../../../shared/id/local-id";
|
||||
import { createThreadOperations, type ThreadOperations } from "../../threads/workflows/thread-operations";
|
||||
import { createThreadTitleService, type ThreadTitleService } from "../../threads/workflows/thread-title-service";
|
||||
import type { ChatServerThreadActions } from "../app-server/actions/threads";
|
||||
import type { ChatAppServerGateway } from "../app-server/session-gateway";
|
||||
import { messageStreamItems } from "../application/state/message-stream";
|
||||
import type { ChatStateStore } from "../application/state/store";
|
||||
import type { ActiveThreadIdentitySync } from "../application/threads/active-thread-identity-sync";
|
||||
import { type AutoTitleCoordinator, createAutoTitleCoordinator } from "../application/threads/auto-title-coordinator";
|
||||
import { createGoalActions, createThreadGoalSyncActions } from "../application/threads/goal-actions";
|
||||
import { HistoryController } from "../application/threads/history-controller";
|
||||
import { createThreadLifecycleParts } from "../application/threads/lifecycle-parts";
|
||||
import { recoverRolloutTokenUsage } from "../../../../app-server/services/rollout-token-usage";
|
||||
import { normalizeExplicitThreadName } from "../../../../domain/threads/model";
|
||||
import type { LocalIdSource } from "../../../../shared/id/local-id";
|
||||
import { createThreadOperations, type ThreadOperations } from "../../../threads/workflows/thread-operations";
|
||||
import { createThreadTitleService, type ThreadTitleService } from "../../../threads/workflows/thread-title-service";
|
||||
import type { ChatServerThreadActions } from "../../app-server/actions/threads";
|
||||
import type { ChatAppServerGateway } from "../../app-server/session-gateway";
|
||||
import { messageStreamItems } from "../../application/state/message-stream";
|
||||
import type { ChatStateStore } from "../../application/state/store";
|
||||
import type { ActiveThreadIdentitySync } from "../../application/threads/active-thread-identity-sync";
|
||||
import { type AutoTitleCoordinator, createAutoTitleCoordinator } from "../../application/threads/auto-title-coordinator";
|
||||
import { createGoalActions, createThreadGoalSyncActions } from "../../application/threads/goal-actions";
|
||||
import { HistoryController } from "../../application/threads/history-controller";
|
||||
import { createThreadLifecycleParts } from "../../application/threads/lifecycle-parts";
|
||||
import {
|
||||
activeThreadRenameTitleContext,
|
||||
createThreadRenameEditorActions,
|
||||
type ThreadRenameEditorActions,
|
||||
} from "../application/threads/rename-editor-actions";
|
||||
import type { RestorationController } from "../application/threads/restoration-controller";
|
||||
import type { ResumeActions } from "../application/threads/resume-actions";
|
||||
import type { ChatResumeWorkTracker } from "../application/threads/resume-work";
|
||||
import { createThreadManagementActions, type ThreadManagementActionsHost } from "../application/threads/thread-management-actions";
|
||||
import { createThreadNavigationActions } from "../application/threads/thread-navigation-actions";
|
||||
import { threadTitleContextFromMessageStreamItems } from "../application/threads/title-context";
|
||||
import type { ChatComposerController } from "../panel/composer-controller";
|
||||
import { createToolbarPanelActions, type ToolbarPanelActions } from "../panel/toolbar-actions";
|
||||
import type { ChatPanelEnvironment } from "./contracts";
|
||||
} from "../../application/threads/rename-editor-actions";
|
||||
import type { RestorationController } from "../../application/threads/restoration-controller";
|
||||
import type { ResumeActions } from "../../application/threads/resume-actions";
|
||||
import type { ChatResumeWorkTracker } from "../../application/threads/resume-work";
|
||||
import { createThreadManagementActions, type ThreadManagementActionsHost } from "../../application/threads/thread-management-actions";
|
||||
import { createThreadNavigationActions } from "../../application/threads/thread-navigation-actions";
|
||||
import { threadTitleContextFromMessageStreamItems } from "../../application/threads/title-context";
|
||||
import type { ChatComposerController } from "../../panel/composer-controller";
|
||||
import { createToolbarPanelActions, type ToolbarPanelActions } from "../../panel/toolbar-actions";
|
||||
import type { ChatPanelEnvironment } from "../contracts";
|
||||
|
||||
type ChatPanelGoalSyncActions = ReturnType<typeof createThreadGoalSyncActions>;
|
||||
export type ChatPanelGoalActions = ReturnType<typeof createGoalActions>;
|
||||
|
|
@ -1,23 +1,17 @@
|
|||
import type { ConnectionManager } from "../../../app-server/connection/connection-manager";
|
||||
import type { LocalIdSource } from "../../../shared/id/local-id";
|
||||
import type { ConnectionWorkTracker } from "../../../shared/lifecycle/connection-work";
|
||||
import type { ChatServerThreadActions } from "../app-server/actions/threads";
|
||||
import type { ChatInboundHandler } from "../app-server/inbound/handler";
|
||||
import type { ChatAppServerGateway } from "../app-server/session-gateway";
|
||||
import { type ChatReconnectActionsHost, reconnectPanel } from "../application/connection/reconnect-actions";
|
||||
import type { LocalIdSource } from "../../../../shared/id/local-id";
|
||||
import type { ChatServerThreadActions } from "../../app-server/actions/threads";
|
||||
import type { ChatInboundHandler } from "../../app-server/inbound/handler";
|
||||
import type { ChatAppServerGateway } from "../../app-server/session-gateway";
|
||||
import {
|
||||
type ConversationTurnActions as ChatPanelConversationTurnActions,
|
||||
createConversationTurnActions,
|
||||
} from "../application/conversation/composition";
|
||||
import { createPendingRequestActions, type PendingRequestActions } from "../application/pending-requests/pending-request-actions";
|
||||
import type { ChatConnectionPhase } from "../application/state/root-reducer";
|
||||
import type { ChatStateStore } from "../application/state/store";
|
||||
import type { AutoTitleCoordinator } from "../application/threads/auto-title-coordinator";
|
||||
import type { MessageStreamNoticeSection } from "../domain/message-stream/items";
|
||||
import type { ChatComposerController } from "../panel/composer-controller";
|
||||
import type { ChatPanelRuntimeProjection } from "../panel/runtime-status-projection";
|
||||
import type { ChatPanelEnvironment } from "./contracts";
|
||||
import type { ChatViewDeferredTasks } from "./deferred-work";
|
||||
} from "../../application/conversation/composition";
|
||||
import { createPendingRequestActions, type PendingRequestActions } from "../../application/pending-requests/pending-request-actions";
|
||||
import type { ChatStateStore } from "../../application/state/store";
|
||||
import type { AutoTitleCoordinator } from "../../application/threads/auto-title-coordinator";
|
||||
import type { MessageStreamNoticeSection } from "../../domain/message-stream/items";
|
||||
import type { ChatComposerController } from "../../panel/composer-controller";
|
||||
import type { ChatPanelRuntimeProjection } from "../../panel/runtime-status-projection";
|
||||
import type { ChatPanelRuntimeSettingsActions } from "./runtime-bundle";
|
||||
import type {
|
||||
ChatPanelGoalActions,
|
||||
|
|
@ -27,16 +21,13 @@ import type {
|
|||
} from "./thread-bundle";
|
||||
|
||||
interface ChatPanelTurnStatus {
|
||||
set: (statusText: string, phase?: ChatConnectionPhase) => void;
|
||||
set: (statusText: string) => void;
|
||||
addSystemMessage: (text: string) => void;
|
||||
addStructuredSystemMessage: (text: string, details: MessageStreamNoticeSection[]) => void;
|
||||
}
|
||||
|
||||
interface ChatPanelTurnHost {
|
||||
environment: ChatPanelEnvironment;
|
||||
stateStore: ChatStateStore;
|
||||
deferredTasks: ChatViewDeferredTasks;
|
||||
connectionWork: ConnectionWorkTracker;
|
||||
messageScrollController: {
|
||||
showLatest(): void;
|
||||
};
|
||||
|
|
@ -44,14 +35,11 @@ interface ChatPanelTurnHost {
|
|||
|
||||
export interface ChatPanelTurnBundle {
|
||||
pendingRequests: PendingRequestActions;
|
||||
reconnect: () => Promise<void>;
|
||||
turnActions: ChatPanelConversationTurnActions;
|
||||
}
|
||||
|
||||
interface ChatPanelTurnInput {
|
||||
connection: ConnectionManager;
|
||||
localItemIds: LocalIdSource;
|
||||
ensureConnected: () => Promise<void>;
|
||||
appServer: ChatAppServerGateway;
|
||||
status: ChatPanelTurnStatus;
|
||||
inboundHandler: ChatInboundHandler;
|
||||
|
|
@ -63,7 +51,7 @@ interface ChatPanelTurnInput {
|
|||
serverThreads: ChatServerThreadActions;
|
||||
goals: ChatPanelGoalActions;
|
||||
autoTitleCoordinator: AutoTitleCoordinator;
|
||||
invalidateThreadWork: () => void;
|
||||
reconnect: () => Promise<void>;
|
||||
runtimeProjection: ChatPanelRuntimeProjection;
|
||||
refreshDiagnostics: () => Promise<void>;
|
||||
refreshLiveState: () => void;
|
||||
|
|
@ -72,9 +60,7 @@ interface ChatPanelTurnInput {
|
|||
|
||||
export function createTurnBundle(host: ChatPanelTurnHost, input: ChatPanelTurnInput): ChatPanelTurnBundle {
|
||||
const {
|
||||
connection,
|
||||
localItemIds,
|
||||
ensureConnected,
|
||||
appServer,
|
||||
status,
|
||||
inboundHandler,
|
||||
|
|
@ -86,7 +72,7 @@ export function createTurnBundle(host: ChatPanelTurnHost, input: ChatPanelTurnIn
|
|||
serverThreads,
|
||||
goals,
|
||||
autoTitleCoordinator,
|
||||
invalidateThreadWork,
|
||||
reconnect,
|
||||
runtimeProjection,
|
||||
refreshDiagnostics,
|
||||
refreshLiveState,
|
||||
|
|
@ -101,30 +87,6 @@ export function createTurnBundle(host: ChatPanelTurnHost, input: ChatPanelTurnIn
|
|||
},
|
||||
refreshLiveState,
|
||||
});
|
||||
const reconnectHost: ChatReconnectActionsHost = {
|
||||
stateStore: host.stateStore,
|
||||
invalidateConnectionWork: () => {
|
||||
host.connectionWork.invalidate();
|
||||
},
|
||||
invalidateThreadWork: () => {
|
||||
invalidateThreadWork();
|
||||
},
|
||||
clearDeferredDiagnostics: () => {
|
||||
host.deferredTasks.clearDiagnostics();
|
||||
},
|
||||
resetConnection: () => {
|
||||
connection.resetConnection();
|
||||
},
|
||||
setStatus: (statusText, phase) => {
|
||||
status.set(statusText, phase);
|
||||
},
|
||||
ensureConnected,
|
||||
resumeThread: (threadId) => threadLifecycle.resume.resumeThread(threadId),
|
||||
addSystemMessage: (text) => {
|
||||
status.addSystemMessage(text);
|
||||
},
|
||||
};
|
||||
const reconnect = () => reconnectPanel(reconnectHost);
|
||||
const threadReferenceResolver = appServer.threadReferences({
|
||||
prepareInput: (text) => composerController.preparedInput(text),
|
||||
addSystemMessage: status.addSystemMessage,
|
||||
|
|
@ -187,7 +149,6 @@ export function createTurnBundle(host: ChatPanelTurnHost, input: ChatPanelTurnIn
|
|||
|
||||
return {
|
||||
pendingRequests,
|
||||
reconnect,
|
||||
turnActions,
|
||||
};
|
||||
}
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
import { type App, normalizePath, type Vault } from "obsidian";
|
||||
|
||||
import { DEFAULT_ATTACHMENT_FOLDER } from "../../../settings/model";
|
||||
import type { ComposerAttachment, ComposerAttachmentHandler } from "../application/composer/attachments";
|
||||
import { DEFAULT_ATTACHMENT_FOLDER } from "../../../../settings/model";
|
||||
import type { ComposerAttachment, ComposerAttachmentHandler } from "../../application/composer/attachments";
|
||||
|
||||
interface VaultComposerAttachmentHandlerOptions {
|
||||
app: App;
|
||||
|
|
@ -5,7 +5,7 @@ import type {
|
|||
ComposerContextRange,
|
||||
ComposerContextReferenceProvider,
|
||||
ComposerContextReferences,
|
||||
} from "../application/composer/context-references";
|
||||
} from "../../application/composer/context-references";
|
||||
import { displayNameForFile, linktextForFile } from "./vault-note-links.obsidian";
|
||||
|
||||
interface EventSource {
|
||||
|
|
@ -1,8 +1,8 @@
|
|||
import type { App, EventRef } from "obsidian";
|
||||
import { stripHeadingForLink, TFile } from "obsidian";
|
||||
|
||||
import type { NoteCandidateProvider, WikiLinkMention } from "../application/composer/note-context";
|
||||
import type { NoteCandidate } from "../application/composer/suggestions";
|
||||
import type { NoteCandidateProvider, WikiLinkMention } from "../../application/composer/note-context";
|
||||
import type { NoteCandidate } from "../../application/composer/suggestions";
|
||||
import { displayNameForFile, linktextForFile } from "./vault-note-links.obsidian";
|
||||
|
||||
interface FileCandidate {
|
||||
|
|
@ -13,15 +13,16 @@ import { createStructuredSystemItem, createSystemItem } from "../domain/message-
|
|||
import type { MessageStreamNoticeSection } from "../domain/message-stream/items";
|
||||
import type { ChatComposerController } from "../panel/composer-controller";
|
||||
import type { ChatMessageScrollController } from "../panel/surface/message-stream-scroll";
|
||||
import { createComposerBundle } from "./composer-bundle";
|
||||
import { type ChatPanelConnectionBundle, createConnectionBundle } from "./connection-bundle";
|
||||
import { createComposerBundle } from "./bundles/composer-bundle";
|
||||
import { type ChatPanelConnectionBundle, createConnectionBundle } from "./bundles/connection-bundle";
|
||||
import { createReconnectAction } from "./bundles/reconnect-bundle";
|
||||
import { createRuntimeBundle } from "./bundles/runtime-bundle";
|
||||
import { type ChatPanelShellBundle, createShellBundle } from "./bundles/shell-bundle";
|
||||
import { createThreadActionBundle, createThreadFoundation, createThreadLifecycleBundle } from "./bundles/thread-bundle";
|
||||
import { createTurnBundle } from "./bundles/turn-bundle";
|
||||
import type { ChatPanelEnvironment } from "./contracts";
|
||||
import type { ChatViewDeferredTasks } from "./deferred-work";
|
||||
import { createRuntimeBundle } from "./runtime-bundle";
|
||||
import { type ChatPanelSharedStateBinding, createChatPanelSharedStateBinding } from "./shared-state-binding";
|
||||
import { type ChatPanelShellBundle, createShellBundle } from "./shell-bundle";
|
||||
import { createThreadActionBundle, createThreadFoundation, createThreadLifecycleBundle } from "./thread-bundle";
|
||||
import { createTurnBundle } from "./turn-bundle";
|
||||
import type { ChatViewDeferredTasks } from "./session/deferred-work";
|
||||
import { type ChatPanelSharedStateBinding, createChatPanelSharedStateBinding } from "./session/shared-state-binding";
|
||||
|
||||
export interface ChatPanelSessionGraph {
|
||||
connection: {
|
||||
|
|
@ -163,10 +164,17 @@ export function createChatPanelSessionGraph(host: ChatPanelSessionGraphHost): Ch
|
|||
refreshActiveThreads,
|
||||
notifyActiveThreadIdentityChanged,
|
||||
});
|
||||
const turn = createTurnBundle(host, {
|
||||
const reconnect = createReconnectAction(host, {
|
||||
connection,
|
||||
localItemIds,
|
||||
ensureConnected,
|
||||
invalidateThreadWork: () => {
|
||||
threadFoundation.invalidateThreadWork();
|
||||
},
|
||||
resumeThread: (threadId) => threadLifecycle.resume.resumeThread(threadId),
|
||||
status,
|
||||
});
|
||||
const turn = createTurnBundle(host, {
|
||||
localItemIds,
|
||||
appServer,
|
||||
status,
|
||||
inboundHandler,
|
||||
|
|
@ -178,9 +186,7 @@ export function createChatPanelSessionGraph(host: ChatPanelSessionGraphHost): Ch
|
|||
serverThreads,
|
||||
goals: threadLifecycle.goals,
|
||||
autoTitleCoordinator: threadFoundation.autoTitleCoordinator,
|
||||
invalidateThreadWork: () => {
|
||||
threadFoundation.invalidateThreadWork();
|
||||
},
|
||||
reconnect,
|
||||
runtimeProjection: runtime.projection,
|
||||
refreshDiagnostics: () => connectionController.refreshDiagnostics(),
|
||||
refreshLiveState,
|
||||
|
|
@ -194,7 +200,7 @@ export function createChatPanelSessionGraph(host: ChatPanelSessionGraphHost): Ch
|
|||
threadActions: threadActions.actions,
|
||||
toolbarPanelActions: threadActions.toolbarPanelActions,
|
||||
navigation: threadActions.navigation,
|
||||
reconnect: turn.reconnect,
|
||||
reconnect,
|
||||
history: threadFoundation.history,
|
||||
pendingRequests: turn.pendingRequests,
|
||||
turn,
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ import { ChatResumeWorkTracker } from "../application/threads/resume-work";
|
|||
import { renderChatPanelShell, unmountChatPanelShell } from "../panel/shell.dom";
|
||||
import { type ChatMessageScrollController, createChatMessageScrollController } from "../panel/surface/message-stream-scroll";
|
||||
import type { ChatPanelEnvironment, ChatPanelHandle, ChatWorkspacePanelSnapshot, ChatWorkspacePanelTurnLifecycle } from "./contracts";
|
||||
import { type ChatViewDeferredTasks, createChatViewDeferredTasks } from "./deferred-work";
|
||||
import { type ChatViewDeferredTasks, createChatViewDeferredTasks } from "./session/deferred-work";
|
||||
import { type ChatPanelSessionGraph, createChatPanelSessionGraph } from "./session-graph";
|
||||
|
||||
export class ChatPanelSession implements ChatPanelHandle {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { DeferredTask, type DeferredTaskWindow } from "../../../shared/lifecycle/deferred-task";
|
||||
import { DeferredTask, type DeferredTaskWindow } from "../../../../shared/lifecycle/deferred-task";
|
||||
|
||||
export interface ChatViewDeferredTasks {
|
||||
scheduleDiagnostics(callback: () => void): void;
|
||||
|
|
@ -1,10 +1,10 @@
|
|||
import type { ModelMetadata } from "../../../domain/catalog/metadata";
|
||||
import type { SharedServerMetadata } from "../../../domain/server/metadata";
|
||||
import type { Thread } from "../../../domain/threads/model";
|
||||
import type { ObservedResult } from "../../../shared/query/observed-result";
|
||||
import { observedValue } from "../../../shared/query/observed-result";
|
||||
import type { ChatStateStore } from "../application/state/store";
|
||||
import type { ChatPanelConnectionBundle } from "./connection-bundle";
|
||||
import type { ModelMetadata } from "../../../../domain/catalog/metadata";
|
||||
import type { SharedServerMetadata } from "../../../../domain/server/metadata";
|
||||
import type { Thread } from "../../../../domain/threads/model";
|
||||
import type { ObservedResult } from "../../../../shared/query/observed-result";
|
||||
import { observedValue } from "../../../../shared/query/observed-result";
|
||||
import type { ChatStateStore } from "../../application/state/store";
|
||||
import type { ChatPanelConnectionBundle } from "../bundles/connection-bundle";
|
||||
|
||||
type ThreadObserver = (result: ObservedResult<readonly Thread[]>) => void;
|
||||
type MetadataObserver = (result: ObservedResult<SharedServerMetadata>) => void;
|
||||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
|
||||
import { createVaultComposerAttachmentHandler } from "../../../../src/features/chat/host/composer-attachments.obsidian";
|
||||
import { createVaultComposerAttachmentHandler } from "../../../../src/features/chat/host/obsidian/composer-attachments.obsidian";
|
||||
|
||||
describe("vault composer attachments", () => {
|
||||
it("saves unnamed pasted images with a generated filename and Obsidian embed marker", async () => {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { describe, expect, it, vi } from "vitest";
|
||||
|
||||
import { scheduleDeferredDiagnosticsRefresh } from "../../../../src/features/chat/host/connection-bundle";
|
||||
import { scheduleDeferredDiagnosticsRefresh } from "../../../../src/features/chat/host/bundles/connection-bundle";
|
||||
|
||||
describe("connection bundle deferred diagnostics", () => {
|
||||
it("reports deferred diagnostics failures without returning a blocking promise", async () => {
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
|
||||
import { createChatViewDeferredTasks } from "../../../../src/features/chat/host/deferred-work";
|
||||
import { createChatViewDeferredTasks } from "../../../../src/features/chat/host/session/deferred-work";
|
||||
|
||||
describe("createChatViewDeferredTasks", () => {
|
||||
beforeEach(() => {
|
||||
|
|
|
|||
57
tests/features/chat/host/reconnect-action.test.ts
Normal file
57
tests/features/chat/host/reconnect-action.test.ts
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
import { describe, expect, it, vi } from "vitest";
|
||||
|
||||
import { ConnectionManager } from "../../../../src/app-server/connection/connection-manager";
|
||||
import { createChatStateStore } from "../../../../src/features/chat/application/state/store";
|
||||
import { createReconnectAction } from "../../../../src/features/chat/host/bundles/reconnect-bundle";
|
||||
import { createChatViewDeferredTasks } from "../../../../src/features/chat/host/session/deferred-work";
|
||||
import { ConnectionWorkTracker } from "../../../../src/shared/lifecycle/connection-work";
|
||||
|
||||
describe("createReconnectAction", () => {
|
||||
it("wires host connection lifecycle cleanup into panel reconnect", async () => {
|
||||
const stateStore = createChatStateStore();
|
||||
stateStore.dispatch({
|
||||
type: "active-thread/resumed",
|
||||
thread: { id: "thread-1" } as never,
|
||||
cwd: "/vault",
|
||||
model: null,
|
||||
reasoningEffort: null,
|
||||
serviceTier: null,
|
||||
approvalsReviewer: null,
|
||||
});
|
||||
const connectionWork = new ConnectionWorkTracker();
|
||||
const activeConnectionWork = connectionWork.begin();
|
||||
const deferredTasks = createChatViewDeferredTasks(() => ({ setTimeout, clearTimeout }) as Pick<Window, "setTimeout" | "clearTimeout">);
|
||||
const connection = new ConnectionManager(() => "codex", "/vault");
|
||||
const resetConnection = vi.spyOn(connection, "resetConnection");
|
||||
const clearDiagnostics = vi.spyOn(deferredTasks, "clearDiagnostics");
|
||||
const status = {
|
||||
set: vi.fn(),
|
||||
addSystemMessage: vi.fn(),
|
||||
};
|
||||
const ensureConnected = vi.fn().mockResolvedValue(undefined);
|
||||
const resumeThread = vi.fn().mockResolvedValue(undefined);
|
||||
const reconnect = createReconnectAction(
|
||||
{
|
||||
stateStore,
|
||||
connectionWork,
|
||||
deferredTasks,
|
||||
},
|
||||
{
|
||||
connection,
|
||||
ensureConnected,
|
||||
invalidateThreadWork: vi.fn(),
|
||||
resumeThread,
|
||||
status,
|
||||
},
|
||||
);
|
||||
|
||||
await reconnect();
|
||||
|
||||
expect(connectionWork.isStale(activeConnectionWork)).toBe(true);
|
||||
expect(clearDiagnostics).toHaveBeenCalledOnce();
|
||||
expect(resetConnection).toHaveBeenCalledOnce();
|
||||
expect(status.set).toHaveBeenCalledWith("Reconnecting...", { kind: "connecting" });
|
||||
expect(ensureConnected).toHaveBeenCalledOnce();
|
||||
expect(resumeThread).toHaveBeenCalledWith("thread-1");
|
||||
});
|
||||
});
|
||||
|
|
@ -9,7 +9,7 @@ import { type ChatStateStore, createChatStateStore } from "../../../../src/featu
|
|||
import { HistoryController } from "../../../../src/features/chat/application/threads/history-controller";
|
||||
import { ChatResumeWorkTracker } from "../../../../src/features/chat/application/threads/resume-work";
|
||||
import type { ChatPanelEnvironment } from "../../../../src/features/chat/host/contracts";
|
||||
import { createChatViewDeferredTasks } from "../../../../src/features/chat/host/deferred-work";
|
||||
import { createChatViewDeferredTasks } from "../../../../src/features/chat/host/session/deferred-work";
|
||||
import { createChatPanelSessionGraph } from "../../../../src/features/chat/host/session-graph";
|
||||
import { ChatComposerController } from "../../../../src/features/chat/panel/composer-controller";
|
||||
import { MessageStreamPresenter } from "../../../../src/features/chat/panel/surface/message-stream-presenter";
|
||||
|
|
|
|||
|
|
@ -3,8 +3,7 @@ import { describe, expect, it, vi } from "vitest";
|
|||
import { createServerDiagnostics, diagnosticsWithToolInventory } from "../../../../src/domain/server/diagnostics";
|
||||
import type { ToolInventorySnapshot } from "../../../../src/domain/server/tool-inventory";
|
||||
import { createChatStateStore } from "../../../../src/features/chat/application/state/store";
|
||||
import { createTurnBundle } from "../../../../src/features/chat/host/turn-bundle";
|
||||
import { ConnectionWorkTracker } from "../../../../src/shared/lifecycle/connection-work";
|
||||
import { createTurnBundle } from "../../../../src/features/chat/host/bundles/turn-bundle";
|
||||
|
||||
describe("createTurnBundle", () => {
|
||||
it("uses cached tool inventory for /tools without refreshing diagnostics", async () => {
|
||||
|
|
@ -51,24 +50,13 @@ function turnBundleFixture(options: { stateStore?: ReturnType<typeof createChatS
|
|||
const refreshDiagnostics = vi.fn().mockResolvedValue(undefined);
|
||||
const bundle = createTurnBundle(
|
||||
{
|
||||
environment: {
|
||||
plugin: {
|
||||
settingsRef: {
|
||||
vaultPath: "/vault",
|
||||
},
|
||||
},
|
||||
},
|
||||
stateStore,
|
||||
deferredTasks: {},
|
||||
connectionWork: new ConnectionWorkTracker(),
|
||||
messageScrollController: {
|
||||
showLatest: vi.fn(),
|
||||
},
|
||||
} as never,
|
||||
{
|
||||
connection: { resetConnection: vi.fn() },
|
||||
localItemIds: { next: vi.fn(() => "local-id") },
|
||||
ensureConnected: vi.fn().mockResolvedValue(undefined),
|
||||
appServer: {
|
||||
connectionAvailable: vi.fn(() => true),
|
||||
threadReferences: vi.fn(() => ({ referThread: vi.fn() })),
|
||||
|
|
@ -100,7 +88,7 @@ function turnBundleFixture(options: { stateStore?: ReturnType<typeof createChatS
|
|||
serverThreads: {},
|
||||
goals: {},
|
||||
autoTitleCoordinator: { resetThreadTurnPresence: vi.fn() },
|
||||
invalidateThreadWork: vi.fn(),
|
||||
reconnect: vi.fn(),
|
||||
runtimeProjection,
|
||||
refreshDiagnostics,
|
||||
refreshLiveState: vi.fn(),
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
import { type App, type EventRef, TFile } from "obsidian";
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
|
||||
import { VaultComposerContextReferenceProvider } from "../../../../src/features/chat/host/vault-composer-context-reference-provider.obsidian";
|
||||
import { VaultNoteCandidateProvider } from "../../../../src/features/chat/host/vault-note-candidate-provider.obsidian";
|
||||
import { VaultComposerContextReferenceProvider } from "../../../../src/features/chat/host/obsidian/vault-composer-context-reference-provider.obsidian";
|
||||
import { VaultNoteCandidateProvider } from "../../../../src/features/chat/host/obsidian/vault-note-candidate-provider.obsidian";
|
||||
|
||||
describe("VaultNoteCandidateProvider", () => {
|
||||
it("builds note candidates from markdown files", () => {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { spawnSync } from "node:child_process";
|
||||
import { readFileSync } from "node:fs";
|
||||
import { copyFile, mkdir, mkdtemp, readdir, writeFile } from "node:fs/promises";
|
||||
import { mkdir, mkdtemp, readdir, writeFile } from "node:fs/promises";
|
||||
import { tmpdir } from "node:os";
|
||||
import path from "node:path";
|
||||
import { describe, expect, it } from "vitest";
|
||||
|
|
@ -19,8 +19,6 @@ const APP_SERVER_PROTOCOL_BOUNDARY_MESSAGE =
|
|||
"Source modules outside root src/app-server must use domain models and app-server services instead of app-server protocol modules. Chat turn-item conversion may consume turn protocol at its app-server boundary; feature state and UI must use Panel-owned models.";
|
||||
const RESPONSIBILITY_ROOT_MODULE_FILE_MESSAGE =
|
||||
"Keep responsibility-split source roots free of module files; add modules to the matching subfolder instead of the root.";
|
||||
const APP_SERVER_ROOT_MODULE_IMPORT_MESSAGE =
|
||||
"Import app-server boundary modules from responsibility subfolders, not src/app-server root modules.";
|
||||
const APP_SERVER_SUBFOLDER_ROOT_IMPORT_MESSAGE =
|
||||
"App-server subfolders must not import sibling root modules; move the dependency into a responsibility subfolder.";
|
||||
const SETTINGS_APP_SERVER_BOUNDARY_MESSAGE =
|
||||
|
|
@ -889,26 +887,14 @@ export const value = statusText;
|
|||
expect(pluginDiagnostics(report, "src/settings/app-server/dynamic-data.ts")).toEqual([]);
|
||||
});
|
||||
|
||||
it("keeps app-server root from becoming a boundary escape hatch", async () => {
|
||||
const cwd = await tempBiomeWorkspace([
|
||||
"no-responsibility-root-module-files.grit",
|
||||
"no-app-server-root-module-imports.grit",
|
||||
"no-app-server-subfolder-root-imports.grit",
|
||||
]);
|
||||
it("keeps app-server root modules from becoming boundary escape hatches", async () => {
|
||||
const cwd = await tempBiomeWorkspace(["no-responsibility-root-module-files.grit", "no-app-server-subfolder-root-imports.grit"]);
|
||||
await writeFile(
|
||||
path.join(cwd, "src/app-server/escape.ts"),
|
||||
`
|
||||
import type { AppServerClient } from "./connection/client";
|
||||
|
||||
export type Escape = AppServerClient;
|
||||
`.trimStart(),
|
||||
);
|
||||
await writeFile(
|
||||
path.join(cwd, "src/features/chat/app-server/root-import.ts"),
|
||||
`
|
||||
import { listThreads } from "../../../../app-server/threads";
|
||||
|
||||
export const read = listThreads;
|
||||
`.trimStart(),
|
||||
);
|
||||
await writeFile(
|
||||
|
|
@ -916,6 +902,22 @@ export const read = listThreads;
|
|||
`
|
||||
import { createChatAppServerGateway } from "../app-server/session-gateway";
|
||||
|
||||
export const gateway = createChatAppServerGateway;
|
||||
`.trimStart(),
|
||||
);
|
||||
await writeFile(
|
||||
path.join(cwd, "src/features/chat/host/bundles/chat-app-server-root-import.ts"),
|
||||
`
|
||||
import { createChatAppServerGateway } from "../../app-server/session-gateway";
|
||||
|
||||
export const gateway = createChatAppServerGateway;
|
||||
`.trimStart(),
|
||||
);
|
||||
await writeFile(
|
||||
path.join(cwd, "src/features/chat/host/session/chat-app-server-root-import.ts"),
|
||||
`
|
||||
import { createChatAppServerGateway } from "../../app-server/session-gateway";
|
||||
|
||||
export const gateway = createChatAppServerGateway;
|
||||
`.trimStart(),
|
||||
);
|
||||
|
|
@ -941,8 +943,9 @@ export const read = listThreads;
|
|||
const report = biomeLint(
|
||||
[
|
||||
"src/app-server/escape.ts",
|
||||
"src/features/chat/app-server/root-import.ts",
|
||||
"src/features/chat/host/chat-app-server-root-import.ts",
|
||||
"src/features/chat/host/bundles/chat-app-server-root-import.ts",
|
||||
"src/features/chat/host/session/chat-app-server-root-import.ts",
|
||||
"src/app-server/services/root-import.ts",
|
||||
"src/app-server/services/allowed.ts",
|
||||
],
|
||||
|
|
@ -950,8 +953,9 @@ export const read = listThreads;
|
|||
);
|
||||
|
||||
expect(pluginMessages(report, "src/app-server/escape.ts")).toEqual([RESPONSIBILITY_ROOT_MODULE_FILE_MESSAGE]);
|
||||
expect(pluginMessages(report, "src/features/chat/app-server/root-import.ts")).toEqual([APP_SERVER_ROOT_MODULE_IMPORT_MESSAGE]);
|
||||
expect(pluginDiagnostics(report, "src/features/chat/host/chat-app-server-root-import.ts")).toEqual([]);
|
||||
expect(pluginDiagnostics(report, "src/features/chat/host/bundles/chat-app-server-root-import.ts")).toEqual([]);
|
||||
expect(pluginDiagnostics(report, "src/features/chat/host/session/chat-app-server-root-import.ts")).toEqual([]);
|
||||
expect(pluginMessages(report, "src/app-server/services/root-import.ts")).toEqual([APP_SERVER_SUBFOLDER_ROOT_IMPORT_MESSAGE]);
|
||||
expect(pluginDiagnostics(report, "src/app-server/services/allowed.ts")).toEqual([]);
|
||||
});
|
||||
|
|
@ -963,7 +967,7 @@ export const read = listThreads;
|
|||
"Keep app-server projection RPCs behind app-server facades; consume Panel-owned snapshots or view models here.",
|
||||
]);
|
||||
expect(pluginDiagnostics(report, "src/app-server/services/threads.ts")).toEqual([]);
|
||||
expect(pluginDiagnostics(report, "src/features/chat/host/connection-bundle.ts")).toEqual([]);
|
||||
expect(pluginDiagnostics(report, "src/features/chat/host/bundles/connection-bundle.ts")).toEqual([]);
|
||||
});
|
||||
|
||||
it("keeps CSS on design tokens and scoped selectors", async () => {
|
||||
|
|
@ -1397,9 +1401,9 @@ export async function read(client: AppServerClient): Promise<void> {
|
|||
`.trimStart(),
|
||||
);
|
||||
await writeFile(
|
||||
path.join(cwd, "src/features/chat/host/connection-bundle.ts"),
|
||||
path.join(cwd, "src/features/chat/host/bundles/connection-bundle.ts"),
|
||||
`
|
||||
import type { AppServerClient } from "../../../app-server/connection/client";
|
||||
import type { AppServerClient } from "../../../../app-server/connection/client";
|
||||
|
||||
export async function resume(client: AppServerClient): Promise<void> {
|
||||
await client.request("thread/resume", { threadId: "thread", cwd: "/vault" });
|
||||
|
|
@ -1462,7 +1466,7 @@ export const load = listHookCatalog;
|
|||
"src/shared/connection-client.ts",
|
||||
"src/features/chat/application/threads/history.ts",
|
||||
"src/app-server/services/threads.ts",
|
||||
"src/features/chat/host/connection-bundle.ts",
|
||||
"src/features/chat/host/bundles/connection-bundle.ts",
|
||||
"src/settings/dynamic-sections-controller.ts",
|
||||
"src/settings/adapter-leak.ts",
|
||||
"src/settings/app-server/dynamic-data.ts",
|
||||
|
|
@ -1473,7 +1477,6 @@ export const load = listHookCatalog;
|
|||
|
||||
async function tempBiomeWorkspace(plugins) {
|
||||
const cwd = await mkdtemp(path.join(tmpdir(), "codex-panel-grit-policy-"));
|
||||
const tempPlugins = await Promise.all(plugins.map((plugin) => tempProjectPluginConfig(cwd, plugin)));
|
||||
await mkdir(cwd, { recursive: true });
|
||||
await mkdir(path.join(cwd, "src/features/chat/domain/message-stream"), { recursive: true });
|
||||
await mkdir(path.join(cwd, "src/features/chat/application/state"), { recursive: true });
|
||||
|
|
@ -1482,6 +1485,8 @@ async function tempBiomeWorkspace(plugins) {
|
|||
await mkdir(path.join(cwd, "src/features/chat/app-server/inbound"), { recursive: true });
|
||||
await mkdir(path.join(cwd, "src/features/chat/app-server/mappers/message-stream"), { recursive: true });
|
||||
await mkdir(path.join(cwd, "src/features/chat/host"), { recursive: true });
|
||||
await mkdir(path.join(cwd, "src/features/chat/host/bundles"), { recursive: true });
|
||||
await mkdir(path.join(cwd, "src/features/chat/host/session"), { recursive: true });
|
||||
await mkdir(path.join(cwd, "src/features/chat/panel"), { recursive: true });
|
||||
await mkdir(path.join(cwd, "src/features/chat/panel/surface"), { recursive: true });
|
||||
await mkdir(path.join(cwd, "src/features/chat/presentation"), { recursive: true });
|
||||
|
|
@ -1506,7 +1511,7 @@ async function tempBiomeWorkspace(plugins) {
|
|||
JSON.stringify({
|
||||
$schema: "https://biomejs.dev/schemas/2.5.1/schema.json",
|
||||
vcs: { enabled: false },
|
||||
plugins: tempPlugins,
|
||||
plugins: plugins.map((plugin) => projectPluginConfig(plugin)),
|
||||
css: { linter: { enabled: true } },
|
||||
}),
|
||||
);
|
||||
|
|
@ -1530,20 +1535,16 @@ function biomeLint(files, cwd, options = {}) {
|
|||
return report;
|
||||
}
|
||||
|
||||
async function tempProjectPluginConfig(cwd, plugin) {
|
||||
function projectPluginConfig(plugin) {
|
||||
const projectPlugin = projectPluginByName.get(plugin);
|
||||
if (!projectPlugin) {
|
||||
throw new Error(`Missing ${plugin} in biome.jsonc plugins`);
|
||||
}
|
||||
const projectPluginRelativePath = normalizeProjectRelativePath(projectPluginPath(projectPlugin));
|
||||
const projectPluginPathAbsolute = path.resolve(repoRoot, projectPluginPath(projectPlugin));
|
||||
const tempPluginPath = path.join(cwd, projectPluginRelativePath);
|
||||
await mkdir(path.dirname(tempPluginPath), { recursive: true });
|
||||
await copyFile(projectPluginPathAbsolute, tempPluginPath);
|
||||
const pluginPath = path.resolve(repoRoot, projectPluginPath(projectPlugin));
|
||||
if (typeof projectPlugin === "string") {
|
||||
return tempPluginPath;
|
||||
return pluginPath;
|
||||
}
|
||||
return { ...projectPlugin, path: tempPluginPath };
|
||||
return { ...projectPlugin, path: pluginPath };
|
||||
}
|
||||
|
||||
function projectPluginPath(plugin) {
|
||||
|
|
|
|||
Loading…
Reference in a new issue