mirror of
https://github.com/murashit/codex-panel.git
synced 2026-07-22 06:57:10 +00:00
Rehome shared modules by ownership boundary
This commit is contained in:
parent
4ed285cedd
commit
5a1d55de22
130 changed files with 306 additions and 345 deletions
101
biome.jsonc
101
biome.jsonc
|
|
@ -9,43 +9,30 @@
|
|||
// Project-wide source shape and placement.
|
||||
{
|
||||
"path": "./scripts/grit/source-shape/no-handwritten-reexports.grit",
|
||||
"includes": ["**/*.ts", "**/*.tsx", "**/*.mjs"]
|
||||
"includes": ["**/*.{ts,tsx,mjs}"]
|
||||
},
|
||||
{
|
||||
"path": "./scripts/grit/source-shape/no-responsibility-root-module-files.grit",
|
||||
"includes": [
|
||||
"**/src/app-server/*.ts",
|
||||
"**/src/app-server/*.tsx",
|
||||
"**/src/domain/*.ts",
|
||||
"**/src/domain/*.tsx",
|
||||
"**/src/features/chat/*.ts",
|
||||
"**/src/features/chat/*.tsx",
|
||||
"**/src/features/threads/*.ts",
|
||||
"**/src/features/threads/*.tsx",
|
||||
"**/src/shared/*.ts",
|
||||
"**/src/shared/*.tsx"
|
||||
]
|
||||
"includes": ["**/src/{app-server,domain}/*.{ts,tsx}", "**/src/features/{chat,threads}/*.{ts,tsx}"]
|
||||
},
|
||||
{
|
||||
"path": "./scripts/grit/source-shape/no-misplaced-tsx.grit",
|
||||
"includes": [
|
||||
"**/src/**/*.tsx",
|
||||
"!**/src/features/chat/panel/**",
|
||||
"!**/src/features/chat/ui/**",
|
||||
"!**/src/features/selection-rewrite/*.dom.tsx",
|
||||
"!**/src/features/turn-diff/*.dom.tsx",
|
||||
"!**/src/features/threads-view/*.dom.tsx",
|
||||
"!**/src/settings/**",
|
||||
"!**/src/shared/ui/**"
|
||||
"!**/src/{settings,shared/ui}/**",
|
||||
"!**/src/features/chat/{panel,ui}/**",
|
||||
"!**/src/features/{selection-rewrite,threads-view,turn-diff}/*.dom.tsx",
|
||||
"!**/src/shared/dom/*.dom.tsx",
|
||||
"!**/src/shared/obsidian/*.obsidian.tsx"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "./scripts/grit/source-shape/no-self-referential-initializer-callback.grit",
|
||||
"includes": ["**/*.ts", "**/*.tsx", "**/*.mjs"]
|
||||
"includes": ["**/*.{ts,tsx,mjs}"]
|
||||
},
|
||||
{
|
||||
"path": "./scripts/grit/source-shape/no-unsafe-iterator-value.grit",
|
||||
"includes": ["**/*.ts", "**/*.tsx", "**/*.mjs"]
|
||||
"includes": ["**/*.{ts,tsx,mjs}"]
|
||||
},
|
||||
{
|
||||
"path": "./scripts/grit/source-shape/no-uncontrolled-preact-form-state.grit",
|
||||
|
|
@ -59,7 +46,7 @@
|
|||
},
|
||||
{
|
||||
"path": "./scripts/grit/import-boundaries/no-lower-level-feature-imports.grit",
|
||||
"includes": ["**/src/app-server/**/*.ts", "**/src/shared/**/*.ts", "**/src/shared/**/*.tsx"]
|
||||
"includes": ["**/src/app-server/**/*.ts", "**/src/shared/**/*.{ts,tsx}"]
|
||||
},
|
||||
|
||||
// App-server and generated protocol boundaries.
|
||||
|
|
@ -69,17 +56,16 @@
|
|||
},
|
||||
{
|
||||
"path": "./scripts/grit/import-boundaries/no-app-server-connection-boundary-imports.grit",
|
||||
"includes": ["**/src/app-server/protocol/**/*.ts", "**/src/domain/**/*.ts", "**/src/shared/**/*.ts", "**/src/shared/**/*.tsx"]
|
||||
"includes": ["**/src/app-server/protocol/**/*.ts", "**/src/domain/**/*.ts", "**/src/shared/**/*.{ts,tsx}"]
|
||||
},
|
||||
{
|
||||
"path": "./scripts/grit/import-boundaries/no-app-server-protocol-boundary-imports.grit",
|
||||
"includes": ["**/src/**/*.ts", "**/src/**/*.tsx", "!**/src/app-server/**"]
|
||||
"includes": ["**/src/**/*.{ts,tsx}", "!**/src/app-server/**"]
|
||||
},
|
||||
{
|
||||
"path": "./scripts/grit/import-boundaries/no-generated-app-server-boundary-imports.grit",
|
||||
"includes": [
|
||||
"**/src/**/*.ts",
|
||||
"**/src/**/*.tsx",
|
||||
"**/src/**/*.{ts,tsx}",
|
||||
"!**/src/app-server/connection/**",
|
||||
"!**/src/app-server/protocol/server-requests.ts",
|
||||
"!**/src/app-server/protocol/turn.ts"
|
||||
|
|
@ -87,16 +73,16 @@
|
|||
},
|
||||
{
|
||||
"path": "./scripts/grit/runtime/no-app-server-direct-rpcs.grit",
|
||||
"includes": ["**/src/**/*.ts", "**/src/**/*.tsx", "!**/src/app-server/**", "!**/src/features/chat/app-server/**"]
|
||||
"includes": ["**/src/**/*.{ts,tsx}", "!**/src/app-server/**", "!**/src/features/chat/app-server/**"]
|
||||
},
|
||||
// Workspace and feature coordination boundaries.
|
||||
{
|
||||
"path": "./scripts/grit/import-boundaries/no-chat-workspace-boundary-imports.grit",
|
||||
"includes": ["**/src/features/chat/**/*.ts", "**/src/features/chat/**/*.tsx"]
|
||||
"includes": ["**/src/features/chat/**/*.{ts,tsx}"]
|
||||
},
|
||||
{
|
||||
"path": "./scripts/grit/import-boundaries/no-feature-workspace-boundary-imports.grit",
|
||||
"includes": ["**/src/features/**/*.ts", "**/src/features/**/*.tsx", "!**/src/features/chat/**"]
|
||||
"includes": ["**/src/features/**/*.{ts,tsx}", "!**/src/features/chat/**"]
|
||||
},
|
||||
{
|
||||
"path": "./scripts/grit/import-boundaries/no-workspace-chat-internal-imports.grit",
|
||||
|
|
@ -118,7 +104,7 @@
|
|||
},
|
||||
{
|
||||
"path": "./scripts/grit/import-boundaries/no-chat-panel-runtime-boundary-imports.grit",
|
||||
"includes": ["**/src/features/chat/panel/**/*.ts", "**/src/features/chat/panel/**/*.tsx"]
|
||||
"includes": ["**/src/features/chat/panel/**/*.{ts,tsx}"]
|
||||
},
|
||||
{
|
||||
"path": "./scripts/grit/import-boundaries/no-chat-presentation-outer-layer-imports.grit",
|
||||
|
|
@ -126,40 +112,34 @@
|
|||
},
|
||||
{
|
||||
"path": "./scripts/grit/import-boundaries/no-chat-ui-outer-layer-imports.grit",
|
||||
"includes": ["**/src/features/chat/ui/**/*.ts", "**/src/features/chat/ui/**/*.tsx"]
|
||||
"includes": ["**/src/features/chat/ui/**/*.{ts,tsx}"]
|
||||
},
|
||||
|
||||
// Chat state and runtime ownership.
|
||||
{
|
||||
"path": "./scripts/grit/import-boundaries/no-preact-signal-imports.grit",
|
||||
"includes": [
|
||||
"**/src/**/*.ts",
|
||||
"**/src/**/*.tsx",
|
||||
"**/src/**/*.{ts,tsx}",
|
||||
"!**/src/features/chat/panel/shell-read-model.ts",
|
||||
"!**/src/features/chat/panel/surface/**/*.ts",
|
||||
"!**/src/features/chat/panel/surface/**/*.tsx"
|
||||
"!**/src/features/chat/panel/surface/**/*.{ts,tsx}"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "./scripts/grit/import-boundaries/no-chat-shell-read-model-imports.grit",
|
||||
"includes": [
|
||||
"**/src/features/chat/**/*.ts",
|
||||
"**/src/features/chat/**/*.tsx",
|
||||
"**/src/features/chat/**/*.{ts,tsx}",
|
||||
"!**/src/features/chat/panel/shell-read-model.ts",
|
||||
"!**/src/features/chat/panel/shell.dom.tsx",
|
||||
"!**/src/features/chat/panel/composer-controller.ts",
|
||||
"!**/src/features/chat/panel/surface/**/*.ts",
|
||||
"!**/src/features/chat/panel/surface/**/*.tsx"
|
||||
"!**/src/features/chat/panel/surface/**/*.{ts,tsx}"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "./scripts/grit/import-boundaries/no-chat-signal-type-references.grit",
|
||||
"includes": [
|
||||
"**/src/features/chat/**/*.ts",
|
||||
"**/src/features/chat/**/*.tsx",
|
||||
"**/src/features/chat/**/*.{ts,tsx}",
|
||||
"!**/src/features/chat/panel/shell-read-model.ts",
|
||||
"!**/src/features/chat/panel/surface/**/*.ts",
|
||||
"!**/src/features/chat/panel/surface/**/*.tsx"
|
||||
"!**/src/features/chat/panel/surface/**/*.{ts,tsx}"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
|
@ -170,40 +150,15 @@
|
|||
// DOM bridge and Preact root boundaries.
|
||||
{
|
||||
"path": "./scripts/grit/dom/no-implicit-dom-bridges.grit",
|
||||
"includes": [
|
||||
"**/src/**/*.ts",
|
||||
"**/src/**/*.tsx",
|
||||
"!**/src/**/*.dom.ts",
|
||||
"!**/src/**/*.dom.tsx",
|
||||
"!**/src/**/*.obsidian.ts",
|
||||
"!**/src/**/*.obsidian.tsx",
|
||||
"!**/src/**/*.measure.ts",
|
||||
"!**/src/**/*.measure.tsx"
|
||||
]
|
||||
"includes": ["**/src/**/*.{ts,tsx}", "!**/src/**/*.{dom,obsidian,measure}.{ts,tsx}"]
|
||||
},
|
||||
{
|
||||
"path": "./scripts/grit/dom/no-dom-events-imports.grit",
|
||||
"includes": [
|
||||
"**/src/**/*.ts",
|
||||
"**/src/**/*.tsx",
|
||||
"!**/src/**/*.dom.ts",
|
||||
"!**/src/**/*.dom.tsx",
|
||||
"!**/src/**/*.obsidian.ts",
|
||||
"!**/src/**/*.obsidian.tsx",
|
||||
"!**/src/**/*.measure.ts",
|
||||
"!**/src/**/*.measure.tsx"
|
||||
]
|
||||
"includes": ["**/src/**/*.{ts,tsx}", "!**/src/**/*.{dom,obsidian,measure}.{ts,tsx}"]
|
||||
},
|
||||
{
|
||||
"path": "./scripts/grit/dom/no-ui-root-imports.grit",
|
||||
"includes": [
|
||||
"**/src/**/*.ts",
|
||||
"**/src/**/*.tsx",
|
||||
"!**/src/**/*.dom.ts",
|
||||
"!**/src/**/*.dom.tsx",
|
||||
"!**/src/**/*.obsidian.ts",
|
||||
"!**/src/**/*.obsidian.tsx"
|
||||
]
|
||||
"path": "./scripts/grit/dom/no-preact-root-imports.grit",
|
||||
"includes": ["**/src/**/*.{ts,tsx}", "!**/src/**/*.{dom,obsidian}.{ts,tsx}"]
|
||||
},
|
||||
|
||||
// CSS source policy.
|
||||
|
|
|
|||
|
|
@ -31,17 +31,15 @@ npm run check
|
|||
|
||||
The generation script uses `codex app-server generate-ts --experimental` because the panel depends on experimental app-server fields. Do not hand-edit generated bindings.
|
||||
|
||||
## Source Layout
|
||||
## Placement Rules
|
||||
|
||||
The source tree is organized by implementation ownership, not by the single Obsidian plugin entrypoint. Put behavior where its reason to change lives: app-server protocol adaptation at the app-server boundary, app-server-independent domain models in domain code, feature-neutral helpers in shared code, feature workflows under their owning feature, and Obsidian lifecycle or workspace wiring at Obsidian-facing boundaries.
|
||||
The source tree is organized by implementation ownership, not by the single Obsidian plugin entrypoint. Put behavior where its reason to change lives: app-server protocol adaptation at the app-server boundary, app-server-independent domain models in domain code, cross-feature reusable adapters and primitives under `src/shared/`, and feature workflows under their owning feature. Keep shared subfolders named by the boundary or primitive they own, such as DOM, Obsidian, runtime, or UI rendering.
|
||||
|
||||
Within chat, keep state transitions and workflow orchestration separate from app-server adaptation, session/Obsidian wiring, and rendering surfaces. Tests should mirror the ownership boundary of the code under test.
|
||||
|
||||
## Placement Rules
|
||||
Keep new code near the state or API it owns. A feature may import another feature only for a capability that feature owns. When moving behavior across an ownership boundary or adding a new shared classification, update the lint policy and its tests with that boundary in the same change.
|
||||
|
||||
Keep new code near the state or API it owns. A feature may import another feature only for a capability that feature owns. Move feature-neutral helpers to `src/shared/`, panel-wide domain models to `src/domain/`, and app-server protocol adaptation to `src/app-server/`.
|
||||
|
||||
Generated app-server types should stay behind app-server connection and protocol adapter modules. If domain, shared, settings, workspace, or UI code needs app-server data, add or reuse a panel-owned projection at the boundary instead of importing generated payload types directly.
|
||||
Generated app-server types should stay behind app-server connection and protocol adapter modules. If domain, shared code, settings, workspace, or feature code needs app-server data, add or reuse a panel-owned projection at the boundary instead of importing generated payload types directly.
|
||||
|
||||
Chat application workflows should receive chat-owned contracts, not root `src/app-server/` modules or direct `AppServerClient` access. Keep app-server access, connection freshness checks, vault-path injection, and payload projection in `src/features/chat/app-server/` transports or host-owned wiring.
|
||||
|
||||
|
|
@ -53,7 +51,7 @@ Chat modules should not import `src/workspace/` directly; workspace operations e
|
|||
|
||||
Use DOM reads, writes, measurements, hit-tests, focus/selection operations, and DOM event listener wiring only from explicit bridge modules, Obsidian-owned API boundaries, or rendering and measurement code that cannot be expressed cleanly as Preact components. Normal modules may keep refs and call named adapters, but they should not interpret DOM structure or layout directly. Name bridge files with a `.dom`, `.obsidian`, or `.measure` suffix.
|
||||
|
||||
Use `.tsx` only in rendering-owned source folders: chat panel and UI modules, Obsidian/settings surfaces, shared UI components, and explicit `.dom.tsx` rendering boundaries such as the selection rewrite popover and threads view shell. Non-rendering source should use `.ts`.
|
||||
Use `.tsx` only where the module owns rendering or a host rendering bridge. Non-rendering source should use `.ts`; when a new rendering-owned location is intentional, update the source-shape lint policy and its tests rather than relying on convention alone.
|
||||
|
||||
## CSS Rules
|
||||
|
||||
|
|
|
|||
|
|
@ -8,6 +8,6 @@ private pattern js_module_reference() {
|
|||
}
|
||||
|
||||
js_module_reference() as $stmt where {
|
||||
$stmt <: contains `$source` where { $source <: r"^[\"'].*shared/ui/dom-events\.dom[\"']$" },
|
||||
$stmt <: contains `$source` where { $source <: r"^[\"'].*shared/dom/events\.dom[\"']$" },
|
||||
register_diagnostic(span=$stmt, message="Import DOM event listener helpers only from explicit .dom, .obsidian, or .measure bridge files.", severity="error")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,6 +8,6 @@ private pattern js_module_reference() {
|
|||
}
|
||||
|
||||
js_module_reference() as $stmt where {
|
||||
$stmt <: contains `$source` where { $source <: r"^[\"'].*shared/ui/ui-root\.dom[\"']$" },
|
||||
$stmt <: contains `$source` where { $source <: r"^[\"'].*shared/dom/preact-root\.dom[\"']$" },
|
||||
register_diagnostic(span=$stmt, message="Import the Preact root adapter only from explicit root bridge files.", severity="error")
|
||||
}
|
||||
|
|
@ -9,8 +9,8 @@ private pattern js_module_reference() {
|
|||
|
||||
private pattern root_outer_layer_source() {
|
||||
or {
|
||||
r"^[\"'](?:\.\./)+(?:app-server|settings|workspace|shared/ui|features)(?:/.*)?[\"']$",
|
||||
r"^[\"']src/(?:app-server|settings|workspace|shared/ui|features)(?:/.*)?[\"']$",
|
||||
r"^[\"'](?:\.\./)+(?:app-server|settings|workspace|shared|features)(?:/.*)?[\"']$",
|
||||
r"^[\"']src/(?:app-server|settings|workspace|shared|features)(?:/.*)?[\"']$",
|
||||
r"^[\"']obsidian[\"']$"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,5 +9,5 @@ private pattern js_module_reference() {
|
|||
|
||||
js_module_reference() as $stmt where {
|
||||
$stmt <: contains `$source` where { $source <: r"^[\"'](?:(?:\.\./)+features|src/features)(?:/.*)?[\"']$" },
|
||||
register_diagnostic(span=$stmt, message="Do not import feature modules from this layer. Move shared behavior to shared, domain, or app-server adapters.", severity="error")
|
||||
register_diagnostic(span=$stmt, message="Do not import feature modules from this layer. Move reusable behavior to domain, shared DOM/Obsidian/runtime/UI, or app-server adapters.", severity="error")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import { jsonPreview } from "../../domain/display/json-preview";
|
||||
import type {
|
||||
ApprovalAction,
|
||||
ApprovalActionIntent,
|
||||
|
|
@ -12,9 +13,8 @@ import type {
|
|||
PendingUserInput,
|
||||
PendingUserInputQuestion,
|
||||
} from "../../domain/pending-requests/model";
|
||||
import { pathRelativeToRoot } from "../../domain/vault/paths";
|
||||
import type { ServerRequest as GeneratedServerRequest } from "../../generated/app-server/ServerRequest";
|
||||
import { pathRelativeToRoot } from "../../shared/path/file-paths";
|
||||
import { jsonPreview } from "../../shared/text/preview";
|
||||
|
||||
interface AppServerGrantedPermissionProfile {
|
||||
network?: unknown;
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@ import type { ModelMetadata } from "../../domain/catalog/metadata";
|
|||
import { createServerDiagnostics, diagnosticProbeError, diagnosticProbeOk, diagnosticsWithProbe } from "../../domain/server/diagnostics";
|
||||
import type { SharedServerMetadata } from "../../domain/server/metadata";
|
||||
import type { Thread } from "../../domain/threads/model";
|
||||
import type { ObservedResult, ObservedResultListener } from "../../shared/query/observed-result";
|
||||
import type { AppServerClient } from "../connection/client";
|
||||
import type { AppServerClientAccessOptions } from "../connection/client-access";
|
||||
import { runtimeConfigSnapshotFromAppServerConfig } from "../protocol/runtime-config";
|
||||
|
|
@ -21,6 +20,7 @@ import {
|
|||
cloneAppServerQueryContext,
|
||||
} from "./keys";
|
||||
import { readRateLimitMetadataProbe, readSkillMetadataProbe } from "./metadata-probes";
|
||||
import type { ObservedResult, ObservedResultListener } from "./observed-result";
|
||||
import { cloneModelMetadata, cloneSharedServerMetadata, cloneThreads } from "./snapshots";
|
||||
|
||||
const THREAD_LIST_STALE_TIME_MS = 10_000;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
import type { ModelMetadata } from "../../domain/catalog/metadata";
|
||||
import type { SharedServerMetadata } from "../../domain/server/metadata";
|
||||
import type { Thread } from "../../domain/threads/model";
|
||||
import type { ObservedResultListener } from "../../shared/query/observed-result";
|
||||
import type { AppServerQueryCache } from "./cache";
|
||||
import {
|
||||
type AppServerQueryContext,
|
||||
|
|
@ -9,6 +8,7 @@ import {
|
|||
appServerQueryContextRawEquals,
|
||||
cloneAppServerQueryContext,
|
||||
} from "./keys";
|
||||
import type { ObservedResultListener } from "./observed-result";
|
||||
|
||||
export interface AppServerSharedQueriesOptions {
|
||||
cache: AppServerQueryCache;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { listenAbortSignal } from "../../shared/lifecycle/abort-signal";
|
||||
import { listenAbortSignal } from "../../shared/runtime/abort-signal";
|
||||
import { AppServerClient, type AppServerClientHandlers } from "../connection/client";
|
||||
import type { AppServerClientRequestPolicy } from "../connection/client-access";
|
||||
import type { ServerNotification } from "../connection/rpc-messages";
|
||||
|
|
|
|||
7
src/domain/display/json-preview.ts
Normal file
7
src/domain/display/json-preview.ts
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
export function jsonPreview(value: unknown): string {
|
||||
try {
|
||||
return JSON.stringify(value, null, 2);
|
||||
} catch {
|
||||
return String(value);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,11 +1,3 @@
|
|||
export function truncate(value: string, maxLength: number): string {
|
||||
return value.length > maxLength ? `${value.slice(0, maxLength - 1)}...` : value;
|
||||
}
|
||||
|
||||
export function jsonPreview(value: unknown): string {
|
||||
try {
|
||||
return JSON.stringify(value, null, 2);
|
||||
} catch {
|
||||
return String(value);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,11 +1,5 @@
|
|||
import {
|
||||
isExternalFileHref,
|
||||
isFilesystemAbsolutePath,
|
||||
isVaultConfigPath,
|
||||
normalizeFilePath,
|
||||
parseFileHref,
|
||||
vaultRelativePath,
|
||||
} from "../../shared/path/file-paths";
|
||||
import { isExternalFileHref, parseFileHref } from "../vault/file-hrefs";
|
||||
import { isFilesystemAbsolutePath, isVaultConfigPath, normalizeFilePath, vaultRelativePath } from "../vault/paths";
|
||||
import type { Thread } from "./model";
|
||||
import { referencedThreadMetadataFromPrompt } from "./reference";
|
||||
import { threadArchiveTitle } from "./title";
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { truncate } from "../../shared/text/preview";
|
||||
import { truncate } from "../display/text-preview";
|
||||
import type { ThreadConversationSummary } from "./transcript";
|
||||
|
||||
const THREAD_TITLE_CONTEXT_MAX_CHARS = 4_000;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { shortThreadId } from "../../shared/id/thread-id";
|
||||
import { shortThreadId } from "./id";
|
||||
import type { Thread } from "./model";
|
||||
|
||||
const MAX_ARCHIVED_THREAD_DISPLAY_TITLE_LENGTH = 96;
|
||||
|
|
|
|||
56
src/domain/vault/file-hrefs.ts
Normal file
56
src/domain/vault/file-hrefs.ts
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
import { isFilesystemAbsolutePath, isVaultConfigPath, normalizeFilePath, vaultRelativePath } from "./paths";
|
||||
|
||||
export interface ParsedFileHref {
|
||||
path: string;
|
||||
subpath: string;
|
||||
}
|
||||
|
||||
export function parseFileHref(href: string): ParsedFileHref | null {
|
||||
const trimmed = href.trim();
|
||||
if (!trimmed || isExternalFileHref(trimmed)) return null;
|
||||
|
||||
const fragmentIndex = trimmed.indexOf("#");
|
||||
const withoutFragment = fragmentIndex === -1 ? trimmed : trimmed.slice(0, fragmentIndex);
|
||||
if (!withoutFragment) return null;
|
||||
|
||||
const decoded = decodeFileHref(withoutFragment);
|
||||
const path = decoded.replace(/:(\d+)(?::\d+)?$/, "");
|
||||
const subpath = fragmentIndex === -1 ? "" : decodeFileHref(trimmed.slice(fragmentIndex));
|
||||
return path ? { path, subpath } : null;
|
||||
}
|
||||
|
||||
export function isExternalFileHref(href: string): boolean {
|
||||
if (/^[a-z]:[\\/]/i.test(href)) return false;
|
||||
return /^[a-z][a-z\d+.-]*:/i.test(href) || href.startsWith("//");
|
||||
}
|
||||
|
||||
export function vaultRelativeFileLinkTarget(vaultPath: string, configDir: string, href: string): string | null {
|
||||
const relativePath = vaultRelativeFileHref(vaultPath, configDir, href);
|
||||
return relativePath ? `${relativePath.path}${relativePath.subpath}` : null;
|
||||
}
|
||||
|
||||
export function isAbsoluteFileHref(href: string): boolean {
|
||||
const parsed = parseFileHref(href);
|
||||
return parsed ? isFilesystemAbsolutePath(normalizeFilePath(parsed.path)) : false;
|
||||
}
|
||||
|
||||
export function vaultRelativeFileHref(vaultPath: string, configDir: string, href: string): { path: string; subpath: string } | null {
|
||||
const parsed = parseFileHref(href);
|
||||
if (!parsed) return null;
|
||||
|
||||
const relativePath = vaultRelativePath(vaultPath, parsed.path, { allowRelative: true });
|
||||
if (!relativePath) return null;
|
||||
|
||||
const normalized = normalizeFilePath(relativePath);
|
||||
if (isVaultConfigPath(normalized, configDir)) return null;
|
||||
|
||||
return { path: normalized, subpath: parsed.subpath };
|
||||
}
|
||||
|
||||
function decodeFileHref(href: string): string {
|
||||
try {
|
||||
return decodeURI(href);
|
||||
} catch {
|
||||
return href;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,31 +1,7 @@
|
|||
export interface ParsedFileHref {
|
||||
path: string;
|
||||
subpath: string;
|
||||
}
|
||||
|
||||
export interface VaultRelativePathOptions {
|
||||
allowRelative?: boolean;
|
||||
}
|
||||
|
||||
export function parseFileHref(href: string): ParsedFileHref | null {
|
||||
const trimmed = href.trim();
|
||||
if (!trimmed || isExternalFileHref(trimmed)) return null;
|
||||
|
||||
const fragmentIndex = trimmed.indexOf("#");
|
||||
const withoutFragment = fragmentIndex === -1 ? trimmed : trimmed.slice(0, fragmentIndex);
|
||||
if (!withoutFragment) return null;
|
||||
|
||||
const decoded = decodeFileHref(withoutFragment);
|
||||
const path = decoded.replace(/:(\d+)(?::\d+)?$/, "");
|
||||
const subpath = fragmentIndex === -1 ? "" : decodeFileHref(trimmed.slice(fragmentIndex));
|
||||
return path ? { path, subpath } : null;
|
||||
}
|
||||
|
||||
export function isExternalFileHref(href: string): boolean {
|
||||
if (isWindowsAbsolutePath(href)) return false;
|
||||
return /^[a-z][a-z\d+.-]*:/i.test(href) || href.startsWith("//");
|
||||
}
|
||||
|
||||
export function vaultRelativePath(vaultPath: string, path: string, options: VaultRelativePathOptions = {}): string | null {
|
||||
const normalizedPath = normalizeFilePath(path);
|
||||
const normalizedVaultPath = normalizeFilePath(vaultPath);
|
||||
|
|
@ -61,14 +37,6 @@ export function normalizeFilePath(path: string): string {
|
|||
return normalized.replace(/^\.\//, "");
|
||||
}
|
||||
|
||||
function decodeFileHref(href: string): string {
|
||||
try {
|
||||
return decodeURI(href);
|
||||
} catch {
|
||||
return href;
|
||||
}
|
||||
}
|
||||
|
||||
function isWindowsAbsolutePath(path: string): boolean {
|
||||
return /^[a-z]:[\\/]/i.test(path);
|
||||
}
|
||||
|
|
@ -14,9 +14,9 @@ import {
|
|||
type PendingUserInput,
|
||||
} from "../../../../domain/pending-requests/model";
|
||||
import type { ThreadConversationSummary } from "../../../../domain/threads/transcript";
|
||||
import type { LocalIdSource } from "../../../../shared/id/local-id";
|
||||
import type { ThreadCatalogEvent } from "../../../threads/catalog/thread-catalog";
|
||||
import { activeTurnId } from "../../application/conversation/turn-state";
|
||||
import type { LocalIdSource } from "../../application/local-id-source";
|
||||
import type { ChatAction, ChatState } from "../../application/state/root-reducer";
|
||||
import type { ChatStateStore } from "../../application/state/store";
|
||||
import { createStructuredSystemItem, createSystemItem } from "../../domain/message-stream/factories/system-items";
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
import type { ServerNotification } from "../../../../app-server/connection/rpc-messages";
|
||||
import { threadFromAppServerRecord } from "../../../../app-server/services/threads";
|
||||
import { jsonPreview } from "../../../../domain/display/json-preview";
|
||||
import { threadTokenUsageFromRuntimeUsage } from "../../../../domain/runtime/metrics";
|
||||
import { normalizeExplicitThreadName } from "../../../../domain/threads/model";
|
||||
import type { ThreadConversationSummary } from "../../../../domain/threads/transcript";
|
||||
import { jsonPreview } from "../../../../shared/text/preview";
|
||||
import type { ThreadCatalogEvent } from "../../../threads/catalog/thread-catalog";
|
||||
import { activeTurnId, pendingTurnStart as pendingTurnStartForState } from "../../application/conversation/turn-state";
|
||||
import { activeThreadSettingsAppliedAction } from "../../application/state/actions";
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { pathRelativeToRoot } from "../../../../../shared/path/file-paths";
|
||||
import { pathRelativeToRoot } from "../../../../../domain/vault/paths";
|
||||
import { permissionRows } from "../../../domain/message-stream/format/permission-rows";
|
||||
import type { ExecutionState, MessageStreamAuditFact, MessageStreamItem } from "../../../domain/message-stream/items";
|
||||
import { type ExecutionStateByStatus, executionStateFromStatus, RUNNING_EXECUTION_STATE } from "./execution-state";
|
||||
|
|
|
|||
|
|
@ -4,10 +4,10 @@ import {
|
|||
type TurnRecord,
|
||||
turnUserItemText,
|
||||
} from "../../../../../app-server/protocol/turn";
|
||||
import { jsonPreview } from "../../../../../domain/display/json-preview";
|
||||
import type { HistoricalTurn } from "../../../../../domain/threads/history";
|
||||
import { referencedThreadMetadataFromPrompt } from "../../../../../domain/threads/reference";
|
||||
import type { ThreadConversationSummary } from "../../../../../domain/threads/transcript";
|
||||
import { jsonPreview } from "../../../../../shared/text/preview";
|
||||
import { fileMentionsFromInput } from "../../../domain/message-stream/format/file-mentions";
|
||||
import { normalizeProposedPlanMarkdown } from "../../../domain/message-stream/format/proposed-plan";
|
||||
import { userMessageDisplayText } from "../../../domain/message-stream/format/user-message-text";
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
import { readReferencedThreadConversationSummaries, type ThreadConversationSummaryClient } from "../../../app-server/services/threads";
|
||||
import { type CodexInput, codexTextInputWithAttachments } from "../../../domain/chat/input";
|
||||
import { shortThreadId } from "../../../domain/threads/id";
|
||||
import type { Thread } from "../../../domain/threads/model";
|
||||
import { REFERENCED_THREAD_TURN_LIMIT, referencedThreadPromptBundle } from "../../../domain/threads/reference";
|
||||
import { shortThreadId } from "../../../shared/id/thread-id";
|
||||
import type { ThreadReferenceInput } from "../application/conversation/slash-command-execution";
|
||||
|
||||
interface ThreadReferenceResolverHost {
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
import { prepareFuzzySearch, type SearchResult, sortSearchResults } from "obsidian";
|
||||
import type { ModelMetadata, SkillMetadata } from "../../../../domain/catalog/metadata";
|
||||
import { findModelMetadataByIdOrName, sortedModelMetadata, supportedEffortsForModelMetadata } from "../../../../domain/catalog/metadata";
|
||||
import { shortThreadId } from "../../../../domain/threads/id";
|
||||
import type { Thread } from "../../../../domain/threads/model";
|
||||
import { threadDisplayTitle } from "../../../../domain/threads/title";
|
||||
import { shortThreadId } from "../../../../shared/id/thread-id";
|
||||
import {
|
||||
type ActiveNoteContextReference,
|
||||
activeNoteContextReferenceMarker,
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import type { ServerInitialization } from "../../../../domain/server/initialization";
|
||||
import type { ActiveConnectionWork, ConnectionWorkTracker } from "../../../../shared/lifecycle/connection-work";
|
||||
import type { ChatConnectionPhase } from "../state/root-reducer";
|
||||
import type { ChatStateStore } from "../state/store";
|
||||
import type { ActiveConnectionWork, ConnectionWorkTracker } from "./connection-work";
|
||||
|
||||
const STATUS_CONNECTION_STOPPED = "Codex app-server stopped.";
|
||||
const STATUS_CONNECTION_STARTING = "Starting Codex app-server...";
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import type { CodexInput } from "../../../../domain/chat/input";
|
||||
import type { Thread } from "../../../../domain/threads/model";
|
||||
import type { LocalIdSource } from "../../../../shared/id/local-id";
|
||||
import type { MessageStreamNoticeSection } from "../../domain/message-stream/items";
|
||||
import type { LocalIdSource } from "../local-id-source";
|
||||
import type { ChatRuntimeSettingsActions } from "../runtime/settings-actions";
|
||||
import type { ChatStateStore } from "../state/store";
|
||||
import type { GoalActions } from "../threads/goal-actions";
|
||||
|
|
|
|||
|
|
@ -2,10 +2,10 @@ import type { ReasoningEffort } from "../../../../domain/catalog/metadata";
|
|||
import { normalizeReasoningEffort } from "../../../../domain/catalog/metadata";
|
||||
import type { CodexInput } from "../../../../domain/chat/input";
|
||||
import type { ThreadGoal } from "../../../../domain/threads/goal";
|
||||
import { shortThreadId } from "../../../../domain/threads/id";
|
||||
import type { Thread } from "../../../../domain/threads/model";
|
||||
import type { ReferencedThreadMetadata } from "../../../../domain/threads/reference";
|
||||
import { threadDisplayTitle } from "../../../../domain/threads/title";
|
||||
import { shortThreadId } from "../../../../shared/id/thread-id";
|
||||
import type { MessageStreamAuditFact, MessageStreamNoticeSection } from "../../domain/message-stream/items";
|
||||
import { modelOverrideMessage, reasoningEffortOverrideMessage } from "../../domain/runtime/labels";
|
||||
import {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import type { CodexInput } from "../../../../domain/chat/input";
|
||||
import type { ReferencedThreadMetadata } from "../../../../domain/threads/reference";
|
||||
import type { LocalIdSource } from "../../../../shared/id/local-id";
|
||||
import type { LocalIdSource } from "../local-id-source";
|
||||
import type { ChatStateStore } from "../state/store";
|
||||
import {
|
||||
acknowledgeOptimisticTurnStart,
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import type { ThreadGoal, ThreadGoalStatus, ThreadGoalUpdate } from "../../../../domain/threads/goal";
|
||||
import type { LocalIdSource } from "../../../../shared/id/local-id";
|
||||
import { goalChangeItem } from "../../domain/message-stream/factories/goal-items";
|
||||
import type { GoalMessageStreamItem } from "../../domain/message-stream/items";
|
||||
import type { LocalIdSource } from "../local-id-source";
|
||||
import type { ChatStateStore } from "../state/store";
|
||||
import type { ThreadGoalReadTransport, ThreadGoalTransport } from "./goal-transport";
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { truncate } from "../../../../../domain/display/text-preview";
|
||||
import type { ThreadGoal, ThreadGoalStatus } from "../../../../../domain/threads/goal";
|
||||
import { truncate } from "../../../../../shared/text/preview";
|
||||
import type { GoalMessageStreamItem } from "../items";
|
||||
|
||||
const GOAL_SUMMARY_LIMIT = 140;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { jsonPreview } from "../../../../../shared/text/preview";
|
||||
import { jsonPreview } from "../../../../../domain/display/json-preview";
|
||||
|
||||
interface DetailRow {
|
||||
key: string;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { truncate } from "../../../../../shared/text/preview";
|
||||
import { truncate } from "../../../../../domain/display/text-preview";
|
||||
import type {
|
||||
AgentRunSummary,
|
||||
AgentRunSummaryAgent,
|
||||
|
|
|
|||
|
|
@ -3,8 +3,6 @@ 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";
|
||||
|
|
@ -14,6 +12,8 @@ import {
|
|||
createChatConnectionController,
|
||||
handleChatConnectionExit,
|
||||
} from "../../application/connection/connection-controller";
|
||||
import type { ConnectionWorkTracker } from "../../application/connection/connection-work";
|
||||
import type { LocalIdSource } from "../../application/local-id-source";
|
||||
import { runtimeSnapshotForChatState } from "../../application/runtime/snapshot";
|
||||
import type { ChatConnectionPhase } from "../../application/state/root-reducer";
|
||||
import type { ChatStateStore } from "../../application/state/store";
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import type { ConnectionManager } from "../../../../app-server/connection/connection-manager";
|
||||
import type { ConnectionWorkTracker } from "../../../../shared/lifecycle/connection-work";
|
||||
import type { ConnectionWorkTracker } from "../../application/connection/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";
|
||||
|
|
|
|||
|
|
@ -2,11 +2,11 @@ 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 type { LocalIdSource } from "../../application/local-id-source";
|
||||
import { messageStreamItems } from "../../application/state/message-stream";
|
||||
import type { ChatStateStore } from "../../application/state/store";
|
||||
import type { ActiveThreadIdentitySync } from "../../application/threads/active-thread-identity-sync";
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
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";
|
||||
|
|
@ -6,6 +5,7 @@ import {
|
|||
type ConversationTurnActions as ChatPanelConversationTurnActions,
|
||||
createConversationTurnActions,
|
||||
} from "../../application/conversation/composition";
|
||||
import type { LocalIdSource } from "../../application/local-id-source";
|
||||
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";
|
||||
|
|
|
|||
|
|
@ -2,12 +2,12 @@ import type { App, Component, EventRef } from "obsidian";
|
|||
|
||||
import type { AppServerClient } from "../../../app-server/connection/client";
|
||||
import type { AppServerQueryContext } from "../../../app-server/query/keys";
|
||||
import type { ObservedResultListener } from "../../../app-server/query/observed-result";
|
||||
import type { ModelMetadata, ReasoningEffort } from "../../../domain/catalog/metadata";
|
||||
import type { SendShortcut } from "../../../domain/input/send-shortcut";
|
||||
import type { PendingRequestCounts } from "../../../domain/pending-requests/aggregate";
|
||||
import type { SharedServerMetadata } from "../../../domain/server/metadata";
|
||||
import type { ArchiveExportSettings } from "../../../domain/threads/archive-markdown";
|
||||
import type { ObservedResultListener } from "../../../shared/query/observed-result";
|
||||
import type { SendShortcut } from "../../../shared/ui/keyboard";
|
||||
import type { ThreadCatalogActiveReader, ThreadCatalogEventSink } from "../../threads/catalog/thread-catalog";
|
||||
import type { ArchiveExportDestination } from "../../threads/workflows/archive-export";
|
||||
import type { TurnDiffViewState } from "../../turn-diff/model";
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
import { ConnectionManager } from "../../../app-server/connection/connection-manager";
|
||||
import { isStaleAppServerSharedQueryContextError } from "../../../app-server/query/shared-queries";
|
||||
import { createLocalIdSource, type LocalIdSource } from "../../../shared/id/local-id";
|
||||
import type { ConnectionWorkTracker } from "../../../shared/lifecycle/connection-work";
|
||||
import { createChatAppServerGateway } from "../app-server/session-gateway";
|
||||
import type { ConnectionWorkTracker } from "../application/connection/connection-work";
|
||||
import { createLocalIdSource, type LocalIdSource } from "../application/local-id-source";
|
||||
import type { ChatAction, ChatConnectionPhase } from "../application/state/root-reducer";
|
||||
import type { ChatStateStore } from "../application/state/store";
|
||||
import type { ActiveThreadIdentitySync } from "../application/threads/active-thread-identity-sync";
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import type { AppServerClient } from "../../../app-server/connection/client";
|
|||
import { type AppServerQueryContext, appServerQueryContextMatches, appServerQueryContextRawEquals } from "../../../app-server/query/keys";
|
||||
import { pendingRequestCountsFromQueues } from "../../../domain/pending-requests/aggregate";
|
||||
import { threadMeaningfulTitle, threadWindowTitle } from "../../../domain/threads/title";
|
||||
import { ConnectionWorkTracker } from "../../../shared/lifecycle/connection-work";
|
||||
import { ConnectionWorkTracker } from "../application/connection/connection-work";
|
||||
import type { ChatState } from "../application/state/root-reducer";
|
||||
import { type ChatStateStore, createChatStateStore } from "../application/state/store";
|
||||
import { parseRestoredThreadState, type RestoredThreadPlaceholderState } from "../application/threads/restored-thread-lifecycle";
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { DeferredTask, type DeferredTaskWindow } from "../../../../shared/lifecycle/deferred-task";
|
||||
import { DeferredTask, type DeferredTaskWindow } from "../../../../shared/runtime/deferred-task";
|
||||
|
||||
export interface ChatViewDeferredTasks {
|
||||
scheduleDiagnostics(callback: () => void): void;
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
import type { ObservedResult } from "../../../../app-server/query/observed-result";
|
||||
import { observedValue } from "../../../../app-server/query/observed-result";
|
||||
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";
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
import { ItemView, type ViewStateResult, type WorkspaceLeaf } from "obsidian";
|
||||
|
||||
import { VIEW_TYPE_CODEX_PANEL } from "../../../constants";
|
||||
import { createLocalIdSource } from "../../../shared/id/local-id";
|
||||
import { createObsidianArchiveExportDestination } from "../../../shared/obsidian/archive-export-destination";
|
||||
import { createObsidianArchiveExportDestination } from "../../threads/obsidian/archive-export-destination.obsidian";
|
||||
import { createLocalIdSource } from "../application/local-id-source";
|
||||
import type { ChatPanelHandle, CodexChatHost } from "./contracts";
|
||||
import { ChatPanelSession } from "./session";
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { textareaCursorAtVisualBoundary } from "../../../shared/ui/textarea-caret.measure";
|
||||
import { textareaCursorAtVisualBoundary } from "../../../shared/dom/textarea-caret.measure";
|
||||
import { type ComposerBoundaryScrollAction, composerBoundaryScrollDirection } from "../application/composer/boundary-scroll";
|
||||
import { composerSuggestionSignature } from "../application/composer/suggestions";
|
||||
import { syncComposerHeight } from "../ui/composer.dom";
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import type { CodexInput } from "../../../domain/chat/input";
|
||||
import { isComposerSendKey, type SendShortcut } from "../../../shared/ui/keyboard";
|
||||
import { isComposerSendKey, type SendShortcut } from "../../../domain/input/send-shortcut";
|
||||
import {
|
||||
type ComposerAttachment,
|
||||
type ComposerAttachmentHandler,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import type { ComponentChild as UiNode } from "preact";
|
||||
import { listenDomEvent } from "../../../shared/ui/dom-events.dom";
|
||||
import { renderUiRoot, unmountUiRoot } from "../../../shared/ui/ui-root.dom";
|
||||
import { listenDomEvent } from "../../../shared/dom/events.dom";
|
||||
import { renderUiRoot, unmountUiRoot } from "../../../shared/dom/preact-root.dom";
|
||||
import type { ChatStateStore } from "../application/state/store";
|
||||
import type { ToolbarActions } from "../ui/toolbar";
|
||||
import { type ChatPanelShellReadModelBinding, createChatPanelShellReadModelBinding } from "./shell-read-model";
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import type { ComponentChild as UiNode } from "preact";
|
||||
import { h } from "preact";
|
||||
import type { SendShortcut } from "../../../../shared/ui/keyboard";
|
||||
import type { SendShortcut } from "../../../../domain/input/send-shortcut";
|
||||
import type { GoalPanelActions, GoalPanelDisplayState, GoalPanelEditorState, GoalPanelOptions } from "../../ui/goal";
|
||||
import { GoalPanel } from "../../ui/goal";
|
||||
import type { ChatPanelGoalReadModel } from "../shell-read-model";
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import type { App, Component } from "obsidian";
|
||||
import type { ComponentChild as UiNode } from "preact";
|
||||
import { h } from "preact";
|
||||
import { copyTextWithNotice } from "../../../../shared/ui/clipboard";
|
||||
import { copyTextWithNotice } from "../../../../shared/obsidian/clipboard.obsidian";
|
||||
import type { TurnDiffViewState } from "../../../turn-diff/model";
|
||||
import type { PendingRequestBlockActions } from "../../application/pending-requests/block";
|
||||
import type { ChatAction } from "../../application/state/root-reducer";
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { copyTextWithNotice } from "../../../shared/ui/clipboard";
|
||||
import { copyTextWithNotice } from "../../../shared/obsidian/clipboard.obsidian";
|
||||
import type { ChatConnectionController } from "../application/connection/connection-controller";
|
||||
import type { ChatAction, ChatState } from "../application/state/root-reducer";
|
||||
import type { ChatStateStore } from "../application/state/store";
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { shortThreadId } from "../../../../shared/id/thread-id";
|
||||
import { pathRelativeToRoot } from "../../../../shared/path/file-paths";
|
||||
import { truncate } from "../../../../shared/text/preview";
|
||||
import { truncate } from "../../../../domain/display/text-preview";
|
||||
import { shortThreadId } from "../../../../domain/threads/id";
|
||||
import { pathRelativeToRoot } from "../../../../domain/vault/paths";
|
||||
import type {
|
||||
AgentMessageStreamItem,
|
||||
ApprovalResultMessageStreamItem,
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { pathRelativeToRoot } from "../../../../shared/path/file-paths";
|
||||
import { pathRelativeToRoot } from "../../../../domain/vault/paths";
|
||||
import type { MessageStreamItem } from "../../domain/message-stream/items";
|
||||
import { messageStreamSemanticClassifications } from "../../domain/message-stream/semantics/classify";
|
||||
import {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { shortThreadId } from "../../../../shared/id/thread-id";
|
||||
import { shortThreadId } from "../../../../domain/threads/id";
|
||||
import type {
|
||||
AgentRunSummary,
|
||||
AgentRunSummaryAgent,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { jsonPreview } from "../../../../domain/display/json-preview";
|
||||
import { type RuntimeConfigSnapshot, runtimeConfigOrDefault } from "../../../../domain/runtime/config";
|
||||
import type { RateLimitWindow, SpendControlLimitSnapshot, ThreadTokenUsage } from "../../../../domain/runtime/metrics";
|
||||
import { jsonPreview } from "../../../../shared/text/preview";
|
||||
import { serviceTierLabel as formatServiceTierLabel, pendingRuntimeSettingLabel } from "../../domain/runtime/labels";
|
||||
import { resolveRuntimeControls } from "../../domain/runtime/resolution";
|
||||
import type { RuntimeSnapshot } from "../../domain/runtime/snapshot";
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { setIcon } from "obsidian";
|
||||
|
||||
import { disposeDomListeners, listenDomEscapeKey, listenDomEvent, listenOutsideDomEvent } from "../../../shared/ui/dom-events.dom";
|
||||
import { syncTextareaHeight } from "../../../shared/ui/textarea-autogrow.measure";
|
||||
import { disposeDomListeners, listenDomEscapeKey, listenDomEvent, listenOutsideDomEvent } from "../../../shared/dom/events.dom";
|
||||
import { syncTextareaHeight } from "../../../shared/dom/textarea-autogrow.measure";
|
||||
|
||||
const COMPOSER_META_EFFORT_HIDDEN_CLASS = "is-effort-hidden";
|
||||
const COMPOSER_META_MODEL_HIDDEN_CLASS = "is-model-hidden";
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import type { ButtonHTMLAttributes, Ref, ComponentChild as UiNode } from "preact";
|
||||
import { useLayoutEffect, useRef, useState } from "preact/hooks";
|
||||
|
||||
import { IconButton } from "../../../shared/ui/components.obsidian";
|
||||
import { IconButton } from "../../../shared/obsidian/components.obsidian";
|
||||
import {
|
||||
type ComposerMetaPickerState,
|
||||
closeComposerMetaPickerOnOutsidePointer,
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { disposeDomListeners, listenDomEscapeKey, listenOutsideDomEvent } from "../../../shared/ui/dom-events.dom";
|
||||
import { syncTextareaHeight } from "../../../shared/ui/textarea-autogrow.measure";
|
||||
import { disposeDomListeners, listenDomEscapeKey, listenOutsideDomEvent } from "../../../shared/dom/events.dom";
|
||||
import { syncTextareaHeight } from "../../../shared/dom/textarea-autogrow.measure";
|
||||
|
||||
export function syncGoalObjectiveHeight(textarea: HTMLTextAreaElement | null): void {
|
||||
syncTextareaHeight(textarea, {
|
||||
|
|
|
|||
|
|
@ -1,9 +1,8 @@
|
|||
import type { ComponentChild as UiNode } from "preact";
|
||||
import { useEffect, useLayoutEffect, useRef, useState } from "preact/hooks";
|
||||
|
||||
import { isComposerSendKey, type SendShortcut } from "../../../domain/input/send-shortcut";
|
||||
import type { ThreadGoal, ThreadGoalStatus } from "../../../domain/threads/goal";
|
||||
import { IconButton } from "../../../shared/ui/components.obsidian";
|
||||
import { isComposerSendKey, type SendShortcut } from "../../../shared/ui/keyboard";
|
||||
import { IconButton } from "../../../shared/obsidian/components.obsidian";
|
||||
import {
|
||||
closeGoalEditorOnOutsidePointer,
|
||||
collapseGoalObjectiveOnOutsidePointer,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import type { ComponentChild as UiNode } from "preact";
|
||||
|
||||
import { RawDiffView } from "../../../../shared/ui/diff";
|
||||
import { RawDiffView } from "../../../../shared/ui/diff-view";
|
||||
import type { DetailSection, DetailView } from "../../presentation/message-stream/detail-view";
|
||||
import type { MessageStreamDisclosureState } from "./context";
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { Component, h, type ComponentChild as UiNode } from "preact";
|
||||
|
||||
import { disposeDomListeners, listenDomEvent } from "../../../../shared/ui/dom-events.dom";
|
||||
import { disposeDomListeners, listenDomEvent } from "../../../../shared/dom/events.dom";
|
||||
import { MESSAGE_CONTENT_RENDERED_EVENT } from "./content-rendered-event.dom";
|
||||
|
||||
type MessageScrollDirection = -1 | 1;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
import { micromark } from "micromark";
|
||||
import { type App, type Component, MarkdownRenderer, Notice } from "obsidian";
|
||||
|
||||
import { isAbsoluteFileHref, vaultFileLinkTarget, vaultRelativeFileLinkTarget } from "../../../../shared/obsidian/file-links";
|
||||
import { isAbsoluteFileHref, vaultRelativeFileLinkTarget } from "../../../../domain/vault/file-hrefs";
|
||||
import { vaultFileLinkTarget } from "../../../../shared/obsidian/vault-file-links.obsidian";
|
||||
import { notifyMessageContentRendered } from "./content-rendered-event.dom";
|
||||
|
||||
interface MarkdownMessageRendererOptions {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import type { Ref, ComponentChild as UiNode } from "preact";
|
||||
import { useEffect, useLayoutEffect, useRef, useState } from "preact/hooks";
|
||||
|
||||
import { listenDomEvent, listenOutsideDomEvent } from "../../../../shared/ui/dom-events.dom";
|
||||
import { listenDomEvent, listenOutsideDomEvent } from "../../../../shared/dom/events.dom";
|
||||
import type { MessageStreamTextView } from "../../presentation/message-stream/text-view";
|
||||
import { MESSAGE_CONTENT_RENDERED_EVENT } from "./content-rendered-event.dom";
|
||||
import type { TextItemContentContext } from "./context";
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { listenOutsideDomEvent } from "../../../../shared/ui/dom-events.dom";
|
||||
import { listenOutsideDomEvent } from "../../../../shared/dom/events.dom";
|
||||
|
||||
export function closeMessageRoleMenuOnOutsidePointer(root: HTMLElement, onClose: () => void): () => void {
|
||||
return listenOutsideDomEvent(root, "pointerdown", onClose, true);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { Fragment, type ComponentChild as UiNode } from "preact";
|
||||
import { useEffect, useRef } from "preact/hooks";
|
||||
import { IconButton } from "../../../../shared/ui/components.obsidian";
|
||||
import { IconButton } from "../../../../shared/obsidian/components.obsidian";
|
||||
import type {
|
||||
EditedFilesTextView,
|
||||
MentionedFileTextView,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import type { ButtonHTMLAttributes, ComponentChild as UiNode } from "preact";
|
||||
import { useLayoutEffect, useRef } from "preact/hooks";
|
||||
import { IconButton, ObsidianToolbarAction, type ObsidianToolbarActionProps } from "../../../shared/ui/components.obsidian";
|
||||
import { IconButton, ObsidianToolbarAction, type ObsidianToolbarActionProps } from "../../../shared/obsidian/components.obsidian";
|
||||
import type { RateLimitSummary } from "../presentation/runtime/status";
|
||||
import { focusToolbarRenameInput } from "./toolbar.dom";
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { type Editor, MarkdownView, Notice, type Plugin } from "obsidian";
|
||||
import type { SendShortcut } from "../../shared/ui/keyboard";
|
||||
import type { SendShortcut } from "../../domain/input/send-shortcut";
|
||||
import type { SelectionRewriteRuntimeSettings, SelectionRewriteState } from "./model";
|
||||
import { SelectionRewritePopover } from "./popover.dom";
|
||||
|
||||
|
|
|
|||
|
|
@ -1,13 +1,12 @@
|
|||
import { type Editor, Notice } from "obsidian";
|
||||
import type { TargetedKeyboardEvent, ComponentChild as UiNode } from "preact";
|
||||
|
||||
import { IconButton } from "../../shared/ui/components.obsidian";
|
||||
import { DiffLineList, unifiedDiffDisplayLines } from "../../shared/ui/diff";
|
||||
import { listenDomEscapeKey, listenDomEvent, listenOutsideDomEvent } from "../../shared/ui/dom-events.dom";
|
||||
import { isComposerSendKey, type SendShortcut } from "../../shared/ui/keyboard";
|
||||
import { syncTextareaHeight } from "../../shared/ui/textarea-autogrow.measure";
|
||||
import { textareaCursorAtVisualBoundary } from "../../shared/ui/textarea-caret.measure";
|
||||
import { renderUiRoot, unmountUiRoot } from "../../shared/ui/ui-root.dom";
|
||||
import { isComposerSendKey, type SendShortcut } from "../../domain/input/send-shortcut";
|
||||
import { listenDomEscapeKey, listenDomEvent, listenOutsideDomEvent } from "../../shared/dom/events.dom";
|
||||
import { renderUiRoot, unmountUiRoot } from "../../shared/dom/preact-root.dom";
|
||||
import { syncTextareaHeight } from "../../shared/dom/textarea-autogrow.measure";
|
||||
import { textareaCursorAtVisualBoundary } from "../../shared/dom/textarea-caret.measure";
|
||||
import { IconButton } from "../../shared/obsidian/components.obsidian";
|
||||
import { DiffLineList, unifiedDiffDisplayLines } from "../../shared/ui/diff-view";
|
||||
import { buildSelectionUnifiedDiff } from "./diff";
|
||||
import {
|
||||
canApplySelectionRewrite,
|
||||
|
|
|
|||
|
|
@ -1,8 +1,7 @@
|
|||
import { type App, Notice, Platform, SuggestModal } from "obsidian";
|
||||
|
||||
import { shortThreadId } from "../../domain/threads/id";
|
||||
import { type Thread, threadRecencyAt } from "../../domain/threads/model";
|
||||
import { threadDisplayTitle } from "../../domain/threads/title";
|
||||
import { shortThreadId } from "../../shared/id/thread-id";
|
||||
import type { ThreadCatalogActiveReader } from "../threads/catalog/thread-catalog";
|
||||
|
||||
export interface ThreadPickerHost {
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
import { Notice } from "obsidian";
|
||||
|
||||
import type { AppServerClientAccess } from "../../app-server/connection/client-access";
|
||||
import type { ObservedResult } from "../../app-server/query/observed-result";
|
||||
import { observedInitialError, observedInitialLoading, observedValue } from "../../app-server/query/observed-result";
|
||||
import { isStaleAppServerSharedQueryContextError } from "../../app-server/query/shared-queries";
|
||||
import type { ReasoningEffort } from "../../domain/catalog/metadata";
|
||||
import type { ArchiveExportSettings } from "../../domain/threads/archive-markdown";
|
||||
import type { Thread } from "../../domain/threads/model";
|
||||
import type { ObservedResult } from "../../shared/query/observed-result";
|
||||
import { observedInitialError, observedInitialLoading, observedValue } from "../../shared/query/observed-result";
|
||||
import type { ThreadCatalogActiveReader, ThreadCatalogEventSink } from "../threads/catalog/thread-catalog";
|
||||
import type { ArchiveExportDestination } from "../threads/workflows/archive-export";
|
||||
import { createThreadOperations, type ThreadOperations } from "../threads/workflows/thread-operations";
|
||||
|
|
|
|||
|
|
@ -1,8 +1,7 @@
|
|||
import type { ButtonHTMLAttributes, ComponentChild as UiNode } from "preact";
|
||||
import { useLayoutEffect, useRef } from "preact/hooks";
|
||||
|
||||
import { IconButton, ObsidianToolbarAction, type ObsidianToolbarActionProps } from "../../shared/ui/components.obsidian";
|
||||
import { renderUiRoot, unmountUiRoot } from "../../shared/ui/ui-root.dom";
|
||||
import { renderUiRoot, unmountUiRoot } from "../../shared/dom/preact-root.dom";
|
||||
import { IconButton, ObsidianToolbarAction, type ObsidianToolbarActionProps } from "../../shared/obsidian/components.obsidian";
|
||||
import type { ThreadsRowModel } from "./state";
|
||||
|
||||
type ButtonProps = ButtonHTMLAttributes & {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { DeferredTask, type DeferredTaskWindow } from "../../shared/lifecycle/deferred-task";
|
||||
import { DeferredTask, type DeferredTaskWindow } from "../../shared/runtime/deferred-task";
|
||||
|
||||
export type ThreadsViewRefreshLifecycleState = { kind: "idle" } | { kind: "loading" };
|
||||
export type ActiveThreadsViewRefresh = Extract<ThreadsViewRefreshLifecycleState, { kind: "loading" }>;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { ItemView, type WorkspaceLeaf } from "obsidian";
|
||||
|
||||
import { VIEW_TYPE_CODEX_THREADS } from "../../constants";
|
||||
import { createObsidianArchiveExportDestination } from "../../shared/obsidian/archive-export-destination";
|
||||
import { createObsidianArchiveExportDestination } from "../threads/obsidian/archive-export-destination.obsidian";
|
||||
import { type ThreadsViewHost, ThreadsViewSession } from "./session";
|
||||
|
||||
export class CodexThreadsView extends ItemView {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import type { ObservedResultListener } from "../../../app-server/query/observed-result";
|
||||
import type { Thread } from "../../../domain/threads/model";
|
||||
import type { ObservedResultListener } from "../../../shared/query/observed-result";
|
||||
|
||||
type ThreadListObserver = ObservedResultListener<readonly Thread[]>;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { type ArchiveExportSettings, type ArchiveThreadInput, archivedThreadMarkdown } from "../../../domain/threads/archive-markdown";
|
||||
import { shortThreadId } from "../../../domain/threads/id";
|
||||
import { threadArchiveTitle } from "../../../domain/threads/title";
|
||||
import { shortThreadId } from "../../../shared/id/thread-id";
|
||||
|
||||
export interface ArchiveExportResult {
|
||||
path: string;
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
import type { ComponentChild as UiNode } from "preact";
|
||||
|
||||
import { shortThreadId } from "../../shared/id/thread-id";
|
||||
import { IconButton } from "../../shared/ui/components.obsidian";
|
||||
import { UnifiedDiffView } from "../../shared/ui/diff";
|
||||
import { renderUiRoot } from "../../shared/ui/ui-root.dom";
|
||||
import { shortThreadId } from "../../domain/threads/id";
|
||||
import { renderUiRoot } from "../../shared/dom/preact-root.dom";
|
||||
import { IconButton } from "../../shared/obsidian/components.obsidian";
|
||||
import { UnifiedDiffView } from "../../shared/ui/diff-view";
|
||||
import type { PersistedTurnDiffViewState, TurnDiffViewState } from "./model";
|
||||
|
||||
export interface TurnDiffViewActions {
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
import { ItemView, type ViewStateResult } from "obsidian";
|
||||
|
||||
import { VIEW_TYPE_CODEX_TURN_DIFF } from "../../constants";
|
||||
import { copyTextWithNotice } from "../../shared/ui/clipboard";
|
||||
import { unmountUiRoot } from "../../shared/ui/ui-root.dom";
|
||||
import { unmountUiRoot } from "../../shared/dom/preact-root.dom";
|
||||
import { copyTextWithNotice } from "../../shared/obsidian/clipboard.obsidian";
|
||||
import { isPersistedTurnDiffViewState, type PersistedTurnDiffViewState, persistedTurnDiffViewState, type TurnDiffViewState } from "./model";
|
||||
import { renderTurnDiffView } from "./render.dom";
|
||||
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
import type { AppServerClient } from "../app-server/connection/client";
|
||||
import type { AppServerClientAccess } from "../app-server/connection/client-access";
|
||||
import type { ObservedResultListener } from "../app-server/query/observed-result";
|
||||
import { isStaleAppServerSharedQueryContextError } from "../app-server/query/shared-queries";
|
||||
import { listHookCatalog, setHookItemEnabled, trustHookItem } from "../app-server/services/catalog";
|
||||
import { deleteThread, restoreArchivedThread as restoreArchivedThreadOnAppServer } from "../app-server/services/threads";
|
||||
import type { ModelMetadata } from "../domain/catalog/metadata";
|
||||
import type { ThreadCatalogArchivedReader, ThreadCatalogEventSink } from "../features/threads/catalog/thread-catalog";
|
||||
import type { ObservedResultListener } from "../shared/query/observed-result";
|
||||
import { type SettingsDynamicDataAccess, type SettingsHookCatalog, StaleSettingsDynamicDataContextError } from "./dynamic-data";
|
||||
|
||||
interface SettingsAppServerQueries {
|
||||
|
|
|
|||
|
|
@ -1,9 +1,8 @@
|
|||
import type { ComponentChild as UiNode } from "preact";
|
||||
|
||||
import { shortThreadId } from "../domain/threads/id";
|
||||
import type { Thread } from "../domain/threads/model";
|
||||
import { threadArchiveDisplayTitle } from "../domain/threads/title";
|
||||
import { shortThreadId } from "../shared/id/thread-id";
|
||||
import { ObsidianExtraButton, ObsidianTextInput, ObsidianToggle } from "../shared/ui/components.obsidian";
|
||||
import { ObsidianExtraButton, ObsidianTextInput, ObsidianToggle } from "../shared/obsidian/components.obsidian";
|
||||
import type { ArchivedThreadSectionState } from "./section-state";
|
||||
import { SettingRow, SettingsGroup, SettingsHeading, SettingsItems, SettingsStatusRow } from "./setting-components";
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import type { ObservedResultListener } from "../app-server/query/observed-result";
|
||||
import type { HookItem, ModelMetadata } from "../domain/catalog/metadata";
|
||||
import type { Thread } from "../domain/threads/model";
|
||||
import type { ObservedResultListener } from "../shared/query/observed-result";
|
||||
|
||||
export interface SettingsHookCatalog {
|
||||
hooks: readonly HookItem[];
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
import type { ObservedResult } from "../app-server/query/observed-result";
|
||||
import { observedValue } from "../app-server/query/observed-result";
|
||||
import type { HookItem, ModelMetadata, ReasoningEffort } from "../domain/catalog/metadata";
|
||||
import { findModelMetadataByIdOrName, sortedModelMetadata, supportedEffortsForModelMetadata } from "../domain/catalog/metadata";
|
||||
import type { Thread } from "../domain/threads/model";
|
||||
import { threadArchiveDisplayTitle } from "../domain/threads/title";
|
||||
import type { ObservedResult } from "../shared/query/observed-result";
|
||||
import { observedValue } from "../shared/query/observed-result";
|
||||
import { isStaleSettingsDynamicDataContextError } from "./dynamic-data";
|
||||
import type { SettingsDynamicSectionsHost } from "./host";
|
||||
import {
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import type { ComponentChild as UiNode } from "preact";
|
|||
|
||||
import type { ModelMetadata, ReasoningEffort } from "../domain/catalog/metadata";
|
||||
import { findModelMetadataByIdOrName, supportedEffortsForModelMetadata } from "../domain/catalog/metadata";
|
||||
import { ObsidianDropdown } from "../shared/ui/components.obsidian";
|
||||
import { ObsidianDropdown } from "../shared/obsidian/components.obsidian";
|
||||
import type { HelperSettingsState } from "./section-state";
|
||||
import { SettingRow, SettingsGroup, SettingsHeading, SettingsItems } from "./setting-components";
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import type { ComponentChild as UiNode } from "preact";
|
||||
|
||||
import type { HookItem } from "../domain/catalog/metadata";
|
||||
import { ObsidianButton } from "../shared/ui/components.obsidian";
|
||||
import { ObsidianButton } from "../shared/obsidian/components.obsidian";
|
||||
import type { HookSectionState } from "./section-state";
|
||||
import { SettingRow, SettingsGroup, SettingsHeading, SettingsItems, SettingsStatusRow } from "./setting-components";
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import { type App, FileSystemAdapter } from "obsidian";
|
|||
import { DEFAULT_CODEX_PATH } from "../constants";
|
||||
import type { ReasoningEffort } from "../domain/catalog/metadata";
|
||||
import { normalizeReasoningEffort } from "../domain/catalog/metadata";
|
||||
import type { SendShortcut } from "../shared/ui/keyboard";
|
||||
import type { SendShortcut } from "../domain/input/send-shortcut";
|
||||
|
||||
export interface CodexPanelSettings {
|
||||
codexPath: string;
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
import type { ComponentChild as UiNode } from "preact";
|
||||
|
||||
import { DEFAULT_CODEX_PATH } from "../constants";
|
||||
import { IconButton, ObsidianCommitTextInput, ObsidianDropdown, ObsidianToggle } from "../shared/ui/components.obsidian";
|
||||
import type { SendShortcut } from "../shared/ui/keyboard";
|
||||
import type { SendShortcut } from "../domain/input/send-shortcut";
|
||||
import { IconButton, ObsidianCommitTextInput, ObsidianDropdown, ObsidianToggle } from "../shared/obsidian/components.obsidian";
|
||||
import { ArchivedThreadSection } from "./archived-section";
|
||||
import { HelperSettingsSection } from "./helper-section";
|
||||
import { HookSection } from "./hook-section";
|
||||
|
|
|
|||
|
|
@ -2,8 +2,8 @@ import { type App, Notice, type Plugin, PluginSettingTab } from "obsidian";
|
|||
|
||||
import { DEFAULT_CODEX_PATH } from "../constants";
|
||||
import type { ReasoningEffort } from "../domain/catalog/metadata";
|
||||
import { listenDomEvent } from "../shared/ui/dom-events.dom";
|
||||
import { renderUiRoot, unmountUiRoot } from "../shared/ui/ui-root.dom";
|
||||
import { listenDomEvent } from "../shared/dom/events.dom";
|
||||
import { renderUiRoot, unmountUiRoot } from "../shared/dom/preact-root.dom";
|
||||
import { SettingsDynamicSectionsController } from "./dynamic-sections-controller";
|
||||
import type { CodexPanelSettingTabHost } from "./host";
|
||||
import { DEFAULT_ATTACHMENT_FOLDER } from "./model";
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import { ButtonComponent, DropdownComponent, ExtraButtonComponent, setIcon, Text
|
|||
import type { ButtonHTMLAttributes, HTMLAttributes, Ref, ComponentChild as UiNode } from "preact";
|
||||
import { useLayoutEffect, useRef } from "preact/hooks";
|
||||
|
||||
import { disposeDomListeners, listenDomEvent } from "./dom-events.dom";
|
||||
import { disposeDomListeners, listenDomEvent } from "../dom/events.dom";
|
||||
|
||||
interface ObsidianIconProps {
|
||||
icon: string;
|
||||
|
|
@ -1,34 +0,0 @@
|
|||
import { type App, TFile } from "obsidian";
|
||||
|
||||
import { isFilesystemAbsolutePath, isVaultConfigPath, normalizeFilePath, parseFileHref, vaultRelativePath } from "../path/file-paths";
|
||||
|
||||
export function vaultFileLinkTarget(app: App, vaultPath: string, href: string): string | null {
|
||||
const relativePath = vaultRelativeFileHref(vaultPath, app.vault.configDir, href);
|
||||
if (!relativePath) return null;
|
||||
|
||||
const abstractFile = app.vault.getAbstractFileByPath(relativePath.path);
|
||||
return abstractFile instanceof TFile ? `${relativePath.path}${relativePath.subpath}` : null;
|
||||
}
|
||||
|
||||
export function vaultRelativeFileLinkTarget(vaultPath: string, configDir: string, href: string): string | null {
|
||||
const relativePath = vaultRelativeFileHref(vaultPath, configDir, href);
|
||||
return relativePath ? `${relativePath.path}${relativePath.subpath}` : null;
|
||||
}
|
||||
|
||||
export function isAbsoluteFileHref(href: string): boolean {
|
||||
const parsed = parseFileHref(href);
|
||||
return parsed ? isFilesystemAbsolutePath(normalizeFilePath(parsed.path)) : false;
|
||||
}
|
||||
|
||||
function vaultRelativeFileHref(vaultPath: string, configDir: string, href: string): { path: string; subpath: string } | null {
|
||||
const parsed = parseFileHref(href);
|
||||
if (!parsed) return null;
|
||||
|
||||
const relativePath = vaultRelativePath(vaultPath, parsed.path, { allowRelative: true });
|
||||
if (!relativePath) return null;
|
||||
|
||||
const normalized = normalizeFilePath(relativePath);
|
||||
if (isVaultConfigPath(normalized, configDir)) return null;
|
||||
|
||||
return { path: normalized, subpath: parsed.subpath };
|
||||
}
|
||||
11
src/shared/obsidian/vault-file-links.obsidian.ts
Normal file
11
src/shared/obsidian/vault-file-links.obsidian.ts
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
import { type App, TFile } from "obsidian";
|
||||
|
||||
import { vaultRelativeFileHref } from "../../domain/vault/file-hrefs";
|
||||
|
||||
export function vaultFileLinkTarget(app: App, vaultPath: string, href: string): string | null {
|
||||
const relativePath = vaultRelativeFileHref(vaultPath, app.vault.configDir, href);
|
||||
if (!relativePath) return null;
|
||||
|
||||
const abstractFile = app.vault.getAbstractFileByPath(relativePath.path);
|
||||
return abstractFile instanceof TFile ? `${relativePath.path}${relativePath.subpath}` : null;
|
||||
}
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
import { describe, expect, it } from "vitest";
|
||||
|
||||
import type { ObservedResult } from "../../../src/shared/query/observed-result";
|
||||
import { observedInitialError, observedInitialLoading, observedValue } from "../../../src/shared/query/observed-result";
|
||||
import type { ObservedResult } from "../../../src/app-server/query/observed-result";
|
||||
import { observedInitialError, observedInitialLoading, observedValue } from "../../../src/app-server/query/observed-result";
|
||||
|
||||
describe("observed query result helpers", () => {
|
||||
it("treats successful empty arrays as current values", () => {
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue