@di-code/coding-agent 0.1.7 → 0.1.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +104 -46
- package/compositions/base.yml +54 -0
- package/compositions/interactive.yml +14 -0
- package/compositions/json.yml +6 -0
- package/compositions/print.yml +5 -0
- package/compositions/rpc.yml +12 -0
- package/compositions/webui.yml +9 -0
- package/dist/cli.d.ts +22 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +97 -3
- package/dist/cli.js.map +1 -1
- package/dist/composition-loader-entry.d.ts +11 -0
- package/dist/composition-loader-entry.d.ts.map +1 -0
- package/dist/composition-loader-entry.js +12 -0
- package/dist/composition-loader-entry.js.map +1 -0
- package/dist/compositions.d.ts +32 -0
- package/dist/compositions.d.ts.map +1 -0
- package/dist/compositions.js +173 -0
- package/dist/compositions.js.map +1 -0
- package/dist/core/session/session-manager.d.ts +9 -2
- package/dist/core/session/session-manager.d.ts.map +1 -1
- package/dist/core/session/session-manager.js +28 -0
- package/dist/core/session/session-manager.js.map +1 -1
- package/dist/core/session/session-storage.d.ts.map +1 -1
- package/dist/core/session/session-storage.js +20 -3
- package/dist/core/session/session-storage.js.map +1 -1
- package/dist/core/session/types.d.ts +11 -2
- package/dist/core/session/types.d.ts.map +1 -1
- package/dist/core/session/types.js.map +1 -1
- package/dist/core/session-tools.d.ts +5 -0
- package/dist/core/session-tools.d.ts.map +1 -0
- package/dist/core/session-tools.js +17 -0
- package/dist/core/session-tools.js.map +1 -0
- package/dist/core/session.d.ts +19 -7
- package/dist/core/session.d.ts.map +1 -1
- package/dist/core/session.js +71 -39
- package/dist/core/session.js.map +1 -1
- package/dist/core/tools/bash.d.ts +1 -38
- package/dist/core/tools/bash.d.ts.map +1 -1
- package/dist/core/tools/bash.js +1 -207
- package/dist/core/tools/bash.js.map +1 -1
- package/dist/core/tools/edit-diff.d.ts +1 -24
- package/dist/core/tools/edit-diff.d.ts.map +1 -1
- package/dist/core/tools/edit-diff.js +1 -135
- package/dist/core/tools/edit-diff.js.map +1 -1
- package/dist/core/tools/edit.d.ts +1 -26
- package/dist/core/tools/edit.d.ts.map +1 -1
- package/dist/core/tools/edit.js +1 -140
- package/dist/core/tools/edit.js.map +1 -1
- package/dist/core/tools/file-mutation-queue.d.ts +1 -1
- package/dist/core/tools/file-mutation-queue.d.ts.map +1 -1
- package/dist/core/tools/file-mutation-queue.js +1 -23
- package/dist/core/tools/file-mutation-queue.js.map +1 -1
- package/dist/core/tools/file-search.d.ts +1 -13
- package/dist/core/tools/file-search.d.ts.map +1 -1
- package/dist/core/tools/file-search.js +1 -98
- package/dist/core/tools/file-search.js.map +1 -1
- package/dist/core/tools/glob.d.ts +1 -10
- package/dist/core/tools/glob.d.ts.map +1 -1
- package/dist/core/tools/glob.js +1 -43
- package/dist/core/tools/glob.js.map +1 -1
- package/dist/core/tools/grep.d.ts +1 -12
- package/dist/core/tools/grep.d.ts.map +1 -1
- package/dist/core/tools/grep.js +1 -66
- package/dist/core/tools/grep.js.map +1 -1
- package/dist/core/tools/load-skill.d.ts +1 -9
- package/dist/core/tools/load-skill.d.ts.map +1 -1
- package/dist/core/tools/load-skill.js +1 -21
- package/dist/core/tools/load-skill.js.map +1 -1
- package/dist/core/tools/path-boundary.d.ts +1 -4
- package/dist/core/tools/path-boundary.d.ts.map +1 -1
- package/dist/core/tools/path-boundary.js +1 -65
- package/dist/core/tools/path-boundary.js.map +1 -1
- package/dist/core/tools/read.d.ts +1 -16
- package/dist/core/tools/read.d.ts.map +1 -1
- package/dist/core/tools/read.js +1 -131
- package/dist/core/tools/read.js.map +1 -1
- package/dist/core/tools/write.d.ts +1 -16
- package/dist/core/tools/write.d.ts.map +1 -1
- package/dist/core/tools/write.js +1 -44
- package/dist/core/tools/write.js.map +1 -1
- package/dist/entry.js +30 -28
- package/dist/entry.js.map +1 -1
- package/dist/index.d.ts +6 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -3
- package/dist/index.js.map +1 -1
- package/dist/interactive/builtin.d.ts +17 -0
- package/dist/interactive/builtin.d.ts.map +1 -0
- package/dist/interactive/builtin.js +47 -0
- package/dist/interactive/builtin.js.map +1 -0
- package/dist/interactive/controller.d.ts +85 -0
- package/dist/interactive/controller.d.ts.map +1 -0
- package/dist/interactive/controller.js +211 -0
- package/dist/interactive/controller.js.map +1 -0
- package/dist/interactive/index.d.ts +3 -0
- package/dist/interactive/index.d.ts.map +1 -0
- package/dist/interactive/index.js +3 -0
- package/dist/interactive/index.js.map +1 -0
- package/dist/interactive-host-entry.d.ts +7 -0
- package/dist/interactive-host-entry.d.ts.map +1 -0
- package/dist/interactive-host-entry.js +123 -0
- package/dist/interactive-host-entry.js.map +1 -0
- package/dist/interactive-profile.d.ts +18 -0
- package/dist/interactive-profile.d.ts.map +1 -0
- package/dist/interactive-profile.js +290 -0
- package/dist/interactive-profile.js.map +1 -0
- package/dist/interactive-resources-entry.d.ts +7 -0
- package/dist/interactive-resources-entry.d.ts.map +1 -0
- package/dist/interactive-resources-entry.js +42 -0
- package/dist/interactive-resources-entry.js.map +1 -0
- package/dist/legacy-main.d.ts +39 -0
- package/dist/legacy-main.d.ts.map +1 -0
- package/dist/legacy-main.js +611 -0
- package/dist/legacy-main.js.map +1 -0
- package/dist/main.d.ts +15 -34
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +130 -518
- package/dist/main.js.map +1 -1
- package/dist/mcp/entries.d.ts +42 -0
- package/dist/mcp/entries.d.ts.map +1 -0
- package/dist/mcp/entries.js +98 -0
- package/dist/mcp/entries.js.map +1 -0
- package/dist/mcp-client-entry.d.ts +5 -0
- package/dist/mcp-client-entry.d.ts.map +1 -0
- package/dist/mcp-client-entry.js +6 -0
- package/dist/mcp-client-entry.js.map +1 -0
- package/dist/mcp-config-entry.d.ts +5 -0
- package/dist/mcp-config-entry.d.ts.map +1 -0
- package/dist/mcp-config-entry.js +6 -0
- package/dist/mcp-config-entry.js.map +1 -0
- package/dist/mcp-tools-entry.d.ts +5 -0
- package/dist/mcp-tools-entry.d.ts.map +1 -0
- package/dist/mcp-tools-entry.js +6 -0
- package/dist/mcp-tools-entry.js.map +1 -0
- package/dist/mcp-transport-entry.d.ts +5 -0
- package/dist/mcp-transport-entry.d.ts.map +1 -0
- package/dist/mcp-transport-entry.js +6 -0
- package/dist/mcp-transport-entry.js.map +1 -0
- package/dist/modes/interactive-entry.d.ts +18 -0
- package/dist/modes/interactive-entry.d.ts.map +1 -0
- package/dist/modes/interactive-entry.js +21 -0
- package/dist/modes/interactive-entry.js.map +1 -0
- package/dist/modes/interactive.d.ts +16 -6
- package/dist/modes/interactive.d.ts.map +1 -1
- package/dist/modes/interactive.js +81 -32
- package/dist/modes/interactive.js.map +1 -1
- package/dist/modes/json-entry.d.ts +13 -0
- package/dist/modes/json-entry.d.ts.map +1 -0
- package/dist/modes/json-entry.js +14 -0
- package/dist/modes/json-entry.js.map +1 -0
- package/dist/modes/json.d.ts +4 -1
- package/dist/modes/json.d.ts.map +1 -1
- package/dist/modes/json.js +3 -3
- package/dist/modes/json.js.map +1 -1
- package/dist/modes/print-entry.d.ts +10 -0
- package/dist/modes/print-entry.d.ts.map +1 -0
- package/dist/modes/print-entry.js +11 -0
- package/dist/modes/print-entry.js.map +1 -0
- package/dist/modes/tree-selector.d.ts.map +1 -1
- package/dist/modes/tree-selector.js +4 -0
- package/dist/modes/tree-selector.js.map +1 -1
- package/dist/plugin-dump-composition.d.ts +6 -0
- package/dist/plugin-dump-composition.d.ts.map +1 -0
- package/dist/plugin-dump-composition.js +7 -0
- package/dist/plugin-dump-composition.js.map +1 -0
- package/dist/plugin-inventory.d.ts +7 -0
- package/dist/plugin-inventory.d.ts.map +1 -0
- package/dist/plugin-inventory.js +8 -0
- package/dist/plugin-inventory.js.map +1 -0
- package/dist/plugin-manager.d.ts +6 -0
- package/dist/plugin-manager.d.ts.map +1 -0
- package/dist/plugin-manager.js +7 -0
- package/dist/plugin-manager.js.map +1 -0
- package/dist/plugin-trace.d.ts +6 -0
- package/dist/plugin-trace.d.ts.map +1 -0
- package/dist/plugin-trace.js +7 -0
- package/dist/plugin-trace.js.map +1 -0
- package/dist/plugins/dynamic-broker.d.ts +76 -0
- package/dist/plugins/dynamic-broker.d.ts.map +1 -0
- package/dist/plugins/dynamic-broker.js +852 -0
- package/dist/plugins/dynamic-broker.js.map +1 -0
- package/dist/plugins/profile.d.ts +15 -0
- package/dist/plugins/profile.d.ts.map +1 -0
- package/dist/plugins/profile.js +34 -0
- package/dist/plugins/profile.js.map +1 -0
- package/dist/plugins/runtime-host.d.ts +37 -0
- package/dist/plugins/runtime-host.d.ts.map +1 -0
- package/dist/plugins/runtime-host.js +95 -0
- package/dist/plugins/runtime-host.js.map +1 -0
- package/dist/plugins/trust.d.ts +8 -0
- package/dist/plugins/trust.d.ts.map +1 -0
- package/dist/plugins/trust.js +59 -0
- package/dist/plugins/trust.js.map +1 -0
- package/dist/project-trust-entry.d.ts +15 -0
- package/dist/project-trust-entry.d.ts.map +1 -0
- package/dist/project-trust-entry.js +15 -0
- package/dist/project-trust-entry.js.map +1 -0
- package/dist/rpc/client.d.ts +78 -6
- package/dist/rpc/client.d.ts.map +1 -1
- package/dist/rpc/client.js +172 -4
- package/dist/rpc/client.js.map +1 -1
- package/dist/rpc/dispatcher.d.ts +121 -0
- package/dist/rpc/dispatcher.d.ts.map +1 -0
- package/dist/rpc/dispatcher.js +994 -0
- package/dist/rpc/dispatcher.js.map +1 -0
- package/dist/rpc/index.d.ts +2 -0
- package/dist/rpc/index.d.ts.map +1 -1
- package/dist/rpc/index.js +2 -0
- package/dist/rpc/index.js.map +1 -1
- package/dist/rpc/lifecycle.d.ts +6 -0
- package/dist/rpc/lifecycle.d.ts.map +1 -0
- package/dist/rpc/lifecycle.js +24 -0
- package/dist/rpc/lifecycle.js.map +1 -0
- package/dist/rpc/protocol.d.ts +112 -31
- package/dist/rpc/protocol.d.ts.map +1 -1
- package/dist/rpc/protocol.js +569 -117
- package/dist/rpc/protocol.js.map +1 -1
- package/dist/rpc/server-service.d.ts +7 -0
- package/dist/rpc/server-service.d.ts.map +1 -0
- package/dist/rpc/server-service.js +3 -0
- package/dist/rpc/server-service.js.map +1 -0
- package/dist/rpc/server.d.ts +16 -19
- package/dist/rpc/server.d.ts.map +1 -1
- package/dist/rpc/server.js +59 -115
- package/dist/rpc/server.js.map +1 -1
- package/dist/rpc-client-sdk-entry.d.ts +12 -0
- package/dist/rpc-client-sdk-entry.d.ts.map +1 -0
- package/dist/rpc-client-sdk-entry.js +11 -0
- package/dist/rpc-client-sdk-entry.js.map +1 -0
- package/dist/rpc-entry.js +50 -18
- package/dist/rpc-entry.js.map +1 -1
- package/dist/rpc-server-entry.d.ts +8 -0
- package/dist/rpc-server-entry.d.ts.map +1 -0
- package/dist/rpc-server-entry.js +67 -0
- package/dist/rpc-server-entry.js.map +1 -0
- package/dist/runtime/attachment-store.d.ts +13 -0
- package/dist/runtime/attachment-store.d.ts.map +1 -0
- package/dist/runtime/attachment-store.js +93 -0
- package/dist/runtime/attachment-store.js.map +1 -0
- package/dist/runtime/bootstrap.d.ts +14 -0
- package/dist/runtime/bootstrap.d.ts.map +1 -0
- package/dist/runtime/bootstrap.js +29 -0
- package/dist/runtime/bootstrap.js.map +1 -0
- package/dist/runtime/interactive-host-service.d.ts +22 -0
- package/dist/runtime/interactive-host-service.d.ts.map +1 -0
- package/dist/runtime/interactive-host-service.js +2 -0
- package/dist/runtime/interactive-host-service.js.map +1 -0
- package/dist/runtime/interactive-resource-service.d.ts +11 -0
- package/dist/runtime/interactive-resource-service.d.ts.map +1 -0
- package/dist/runtime/interactive-resource-service.js +3 -0
- package/dist/runtime/interactive-resource-service.js.map +1 -0
- package/dist/runtime/plugin-inventory-entry.d.ts +5 -0
- package/dist/runtime/plugin-inventory-entry.d.ts.map +1 -0
- package/dist/runtime/plugin-inventory-entry.js +18 -0
- package/dist/runtime/plugin-inventory-entry.js.map +1 -0
- package/dist/runtime/plugin-inventory-service.d.ts +8 -0
- package/dist/runtime/plugin-inventory-service.d.ts.map +1 -0
- package/dist/runtime/plugin-inventory-service.js +3 -0
- package/dist/runtime/plugin-inventory-service.js.map +1 -0
- package/dist/runtime/plugin-manager-entry.d.ts +20 -0
- package/dist/runtime/plugin-manager-entry.d.ts.map +1 -0
- package/dist/runtime/plugin-manager-entry.js +96 -0
- package/dist/runtime/plugin-manager-entry.js.map +1 -0
- package/dist/runtime/plugin-observability-entry.d.ts +12 -0
- package/dist/runtime/plugin-observability-entry.d.ts.map +1 -0
- package/dist/runtime/plugin-observability-entry.js +73 -0
- package/dist/runtime/plugin-observability-entry.js.map +1 -0
- package/dist/runtime/product-host.d.ts +91 -0
- package/dist/runtime/product-host.d.ts.map +1 -0
- package/dist/runtime/product-host.js +529 -0
- package/dist/runtime/product-host.js.map +1 -0
- package/dist/runtime/session-factory.d.ts +17 -0
- package/dist/runtime/session-factory.d.ts.map +1 -0
- package/dist/runtime/session-factory.js +75 -0
- package/dist/runtime/session-factory.js.map +1 -0
- package/dist/runtime/session-host.d.ts +152 -0
- package/dist/runtime/session-host.d.ts.map +1 -0
- package/dist/runtime/session-host.js +895 -0
- package/dist/runtime/session-host.js.map +1 -0
- package/dist/runtime-core-entry.d.ts +11 -0
- package/dist/runtime-core-entry.d.ts.map +1 -0
- package/dist/runtime-core-entry.js +9 -0
- package/dist/runtime-core-entry.js.map +1 -0
- package/dist/session-factory-entry.d.ts +7 -0
- package/dist/session-factory-entry.d.ts.map +1 -0
- package/dist/session-factory-entry.js +9 -0
- package/dist/session-factory-entry.js.map +1 -0
- package/dist/session-store-jsonl-entry.d.ts +7 -0
- package/dist/session-store-jsonl-entry.d.ts.map +1 -0
- package/dist/session-store-jsonl-entry.js +33 -0
- package/dist/session-store-jsonl-entry.js.map +1 -0
- package/dist/startup.d.ts +12 -1
- package/dist/startup.d.ts.map +1 -1
- package/dist/startup.js +106 -15
- package/dist/startup.js.map +1 -1
- package/dist/subagents/index.d.ts +2 -0
- package/dist/subagents/index.d.ts.map +1 -0
- package/dist/subagents/index.js +2 -0
- package/dist/subagents/index.js.map +1 -0
- package/dist/subagents/service.d.ts +50 -0
- package/dist/subagents/service.d.ts.map +1 -0
- package/dist/subagents/service.js +521 -0
- package/dist/subagents/service.js.map +1 -0
- package/dist/ui-host.d.ts +125 -0
- package/dist/ui-host.d.ts.map +1 -0
- package/dist/ui-host.js +275 -0
- package/dist/ui-host.js.map +1 -0
- package/dist/web/assets/index-BwfuGMvv.css +1 -0
- package/dist/web/assets/index-DPUaJqFJ.js +41 -0
- package/dist/web/assets/index-DPUaJqFJ.js.map +1 -0
- package/dist/web/index.html +14 -0
- package/dist/web-command.d.ts +11 -0
- package/dist/web-command.d.ts.map +1 -0
- package/dist/web-command.js +114 -0
- package/dist/web-command.js.map +1 -0
- package/dist/web-frontend.d.ts +73 -0
- package/dist/web-frontend.d.ts.map +1 -0
- package/dist/web-frontend.js +249 -0
- package/dist/web-frontend.js.map +1 -0
- package/dist/web.d.ts +254 -0
- package/dist/web.d.ts.map +1 -0
- package/dist/web.js +740 -0
- package/dist/web.js.map +1 -0
- package/dist/webui-entry.d.ts +3 -0
- package/dist/webui-entry.d.ts.map +1 -0
- package/dist/webui-entry.js +73 -0
- package/dist/webui-entry.js.map +1 -0
- package/dist/webui.d.ts +91 -0
- package/dist/webui.d.ts.map +1 -0
- package/dist/webui.js +882 -0
- package/dist/webui.js.map +1 -0
- package/package.json +89 -8
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import type { AssistantMessage, ImageContent, Message, Model, Provider, ThinkingLevel } from "@di-code/ai";
|
|
2
|
+
import { type PluginDefinition } from "@di-code/plugin-runtime";
|
|
3
|
+
import { type KeybindingsConfig, type TuiTheme } from "@di-code/tui";
|
|
4
|
+
import type { Locale } from "./i18n.ts";
|
|
5
|
+
import { type PromptInput, type SessionHost, type SessionHostEvent } from "./runtime/session-host.ts";
|
|
6
|
+
/** Version of the stable in-process custom TUI contract. */
|
|
7
|
+
export declare const UI_HOST_API_VERSION: 1;
|
|
8
|
+
export type UiHostApiVersion = typeof UI_HOST_API_VERSION;
|
|
9
|
+
export type UiHostErrorCode = "INVALID_WORKSPACE" | "NOT_FOUND" | "BUSY" | "SESSION_IN_USE" | "DISPOSED" | "INVALID_INPUT" | "INTERNAL";
|
|
10
|
+
/** Errors from SessionHost-owned operations expose a stable code but not internal causes. */
|
|
11
|
+
export interface UiHostError extends Error {
|
|
12
|
+
readonly code: UiHostErrorCode;
|
|
13
|
+
}
|
|
14
|
+
/** Thrown synchronously when a facade is used after host disposal begins. */
|
|
15
|
+
export declare class UiHostLifecycleError extends Error {
|
|
16
|
+
readonly code: "DISPOSED";
|
|
17
|
+
constructor();
|
|
18
|
+
}
|
|
19
|
+
export type UiHostEvent = SessionHostEvent;
|
|
20
|
+
export interface UiHostSessionSnapshot {
|
|
21
|
+
readonly id: string;
|
|
22
|
+
readonly label: string;
|
|
23
|
+
readonly modifiedAt?: number;
|
|
24
|
+
}
|
|
25
|
+
export type UiHostOperationKind = "prompt" | "steer" | "retry" | "compact" | "tree" | "session";
|
|
26
|
+
/** Read-only Session state that intentionally omits managed paths and internal Session references. */
|
|
27
|
+
export interface UiHostSessionState {
|
|
28
|
+
readonly disposed: false;
|
|
29
|
+
readonly activeSession?: UiHostSessionSnapshot;
|
|
30
|
+
readonly busy: boolean;
|
|
31
|
+
readonly operations: readonly {
|
|
32
|
+
readonly requestId: string;
|
|
33
|
+
readonly kind: UiHostOperationKind;
|
|
34
|
+
}[];
|
|
35
|
+
}
|
|
36
|
+
/** Read-only resources selected by product bootstrap for this TUI lifetime. */
|
|
37
|
+
export interface UiHostResourceSnapshot {
|
|
38
|
+
readonly models: readonly Model[];
|
|
39
|
+
readonly skills: readonly {
|
|
40
|
+
readonly name: string;
|
|
41
|
+
readonly description: string;
|
|
42
|
+
readonly scope: string;
|
|
43
|
+
}[];
|
|
44
|
+
}
|
|
45
|
+
export interface UiHostDiagnostics {
|
|
46
|
+
/** Writes redacted diagnostic text to the CLI diagnostic stream. */
|
|
47
|
+
report(message: string): void;
|
|
48
|
+
/** Returns a read-only snapshot of runtime diagnostics known when it is called. */
|
|
49
|
+
snapshot(): readonly {
|
|
50
|
+
readonly type: string;
|
|
51
|
+
readonly message?: string;
|
|
52
|
+
readonly pluginName?: string;
|
|
53
|
+
}[];
|
|
54
|
+
}
|
|
55
|
+
export interface UiHostThemeRegistry {
|
|
56
|
+
readonly list: () => readonly {
|
|
57
|
+
readonly name: string;
|
|
58
|
+
readonly theme: TuiTheme;
|
|
59
|
+
}[];
|
|
60
|
+
/** Registration belongs to the plugin Fiber and is removed during composition disposal. */
|
|
61
|
+
readonly register: (name: string, theme: TuiTheme) => () => void;
|
|
62
|
+
}
|
|
63
|
+
export interface UiHostKeybindingRegistry {
|
|
64
|
+
readonly snapshot: () => KeybindingsConfig;
|
|
65
|
+
/** Replaces the presentation keybinding snapshot for this composition scope. */
|
|
66
|
+
readonly set: (bindings: KeybindingsConfig) => () => void;
|
|
67
|
+
}
|
|
68
|
+
/** Product-scoped facilities. It deliberately does not expose command execution or bootstrap service keys. */
|
|
69
|
+
export interface ProductHost {
|
|
70
|
+
readonly apiVersion: UiHostApiVersion;
|
|
71
|
+
readonly locale: Locale;
|
|
72
|
+
readonly projectTrusted: boolean;
|
|
73
|
+
readonly resources: () => UiHostResourceSnapshot;
|
|
74
|
+
readonly themes: UiHostThemeRegistry;
|
|
75
|
+
readonly keybindings: UiHostKeybindingRegistry;
|
|
76
|
+
readonly diagnostics: UiHostDiagnostics;
|
|
77
|
+
}
|
|
78
|
+
/** A lifecycle-checked view over the current product Session, never an AgentSession instance. */
|
|
79
|
+
export interface UiSessionHost {
|
|
80
|
+
readonly state: () => UiHostSessionState;
|
|
81
|
+
readonly listSessions: () => Promise<readonly UiHostSessionSnapshot[]>;
|
|
82
|
+
readonly createSession: () => Promise<UiHostSessionSnapshot>;
|
|
83
|
+
readonly openSession: (sessionId: string) => Promise<UiHostSessionSnapshot>;
|
|
84
|
+
readonly closeSession: () => Promise<void>;
|
|
85
|
+
readonly prompt: (input: PromptInput | string, signal?: AbortSignal) => Promise<AssistantMessage>;
|
|
86
|
+
readonly promptWithImages: (text: string, images: readonly ImageContent[], signal?: AbortSignal) => Promise<AssistantMessage>;
|
|
87
|
+
readonly steer: (input: PromptInput | string, signal?: AbortSignal) => Promise<void>;
|
|
88
|
+
readonly steerWithImages: (text: string, images: readonly ImageContent[], signal?: AbortSignal) => Promise<void>;
|
|
89
|
+
readonly retry: (signal?: AbortSignal) => Promise<AssistantMessage>;
|
|
90
|
+
readonly cancel: (requestId: string) => boolean;
|
|
91
|
+
readonly transcript: () => readonly Message[];
|
|
92
|
+
readonly tree: SessionHost["tree"];
|
|
93
|
+
readonly navigateTree: SessionHost["navigateTree"];
|
|
94
|
+
readonly setModel: SessionHost["setModel"];
|
|
95
|
+
readonly setRuntime: (provider: Provider, model: Model) => Model;
|
|
96
|
+
readonly cycleThinkingLevel: () => ThinkingLevel | undefined;
|
|
97
|
+
readonly compact: SessionHost["compact"];
|
|
98
|
+
readonly setCompactionEnabled: SessionHost["setCompactionEnabled"];
|
|
99
|
+
readonly usage: SessionHost["usage"];
|
|
100
|
+
readonly subscribe: SessionHost["subscribe"];
|
|
101
|
+
}
|
|
102
|
+
/** Stable facade passed to a custom TUI. It becomes unusable as soon as `dispose()` begins. */
|
|
103
|
+
export interface UiHost {
|
|
104
|
+
readonly apiVersion: UiHostApiVersion;
|
|
105
|
+
readonly signal: AbortSignal;
|
|
106
|
+
readonly product: ProductHost;
|
|
107
|
+
readonly session: UiSessionHost;
|
|
108
|
+
readonly initialPrompt: string;
|
|
109
|
+
readonly dispose: () => Promise<void>;
|
|
110
|
+
}
|
|
111
|
+
export interface UiHostStartContext {
|
|
112
|
+
readonly host: UiHost;
|
|
113
|
+
readonly signal: AbortSignal;
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* The only callback a replacement interactive host supplies. Resolve when its UI exits; reject to fail startup.
|
|
117
|
+
* The product then aborts in-flight work, releases the Session/MCP resources, and invalidates the facade.
|
|
118
|
+
*/
|
|
119
|
+
export type UiHostStart = (context: UiHostStartContext) => void | Promise<void>;
|
|
120
|
+
/**
|
|
121
|
+
* Creates a composition entry that replaces `interactive-host` without granting command-registry access.
|
|
122
|
+
* The returned entry owns the product bootstrap and always disposes its UiHost after `start` settles.
|
|
123
|
+
*/
|
|
124
|
+
export declare function createUiHostEntry(start: UiHostStart): PluginDefinition;
|
|
125
|
+
//# sourceMappingURL=ui-host.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ui-host.d.ts","sourceRoot":"","sources":["../src/ui-host.ts"],"names":[],"mappings":"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"}
|
package/dist/ui-host.js
ADDED
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
import { resolve } from "node:path";
|
|
2
|
+
import { diagnosticsKey, hostCommandRegistryKey, keybindingRegistryKey, themeRegistryKey } from "@di-code/builtins";
|
|
3
|
+
import { redactSensitiveText } from "@di-code/plugin-runtime";
|
|
4
|
+
import { ProcessTerminal } from "@di-code/tui";
|
|
5
|
+
import { runProviderOnboarding, shouldStartProviderOnboarding } from "./provider-onboarding.js";
|
|
6
|
+
import { createSessionHost, } from "./runtime/session-host.js";
|
|
7
|
+
import { loadStartupConfiguration, resolveStartupRuntime } from "./startup.js";
|
|
8
|
+
/** Version of the stable in-process custom TUI contract. */
|
|
9
|
+
export const UI_HOST_API_VERSION = 1;
|
|
10
|
+
/** Thrown synchronously when a facade is used after host disposal begins. */
|
|
11
|
+
export class UiHostLifecycleError extends Error {
|
|
12
|
+
code = "DISPOSED";
|
|
13
|
+
constructor() {
|
|
14
|
+
super("UiHost has been disposed.");
|
|
15
|
+
this.name = "UiHostLifecycleError";
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
function isInteractiveHostRequest(value) {
|
|
19
|
+
return (typeof value === "object" &&
|
|
20
|
+
value !== null &&
|
|
21
|
+
"command" in value &&
|
|
22
|
+
typeof value.command === "object" &&
|
|
23
|
+
value.command !== null &&
|
|
24
|
+
"mode" in value.command &&
|
|
25
|
+
value.command.mode === "interactive" &&
|
|
26
|
+
"cwd" in value &&
|
|
27
|
+
typeof value.cwd === "string" &&
|
|
28
|
+
"agentDir" in value &&
|
|
29
|
+
typeof value.agentDir === "string" &&
|
|
30
|
+
"projectTrusted" in value &&
|
|
31
|
+
typeof value.projectTrusted === "boolean" &&
|
|
32
|
+
"stderr" in value &&
|
|
33
|
+
typeof value.stderr === "function");
|
|
34
|
+
}
|
|
35
|
+
function snapshotSession(info) {
|
|
36
|
+
return Object.freeze({
|
|
37
|
+
id: info.id,
|
|
38
|
+
label: info.label,
|
|
39
|
+
...(info.modifiedAt === undefined ? {} : { modifiedAt: info.modifiedAt }),
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
function createUiSession(host, isDisposed) {
|
|
43
|
+
const assertLive = () => {
|
|
44
|
+
if (isDisposed())
|
|
45
|
+
throw new UiHostLifecycleError();
|
|
46
|
+
};
|
|
47
|
+
return {
|
|
48
|
+
state: () => {
|
|
49
|
+
assertLive();
|
|
50
|
+
const state = host.state();
|
|
51
|
+
return Object.freeze({
|
|
52
|
+
disposed: false,
|
|
53
|
+
...(state.activeSession ? { activeSession: snapshotSession(state.activeSession) } : {}),
|
|
54
|
+
busy: state.busy,
|
|
55
|
+
operations: Object.freeze(state.operations.map((operation) => Object.freeze({ requestId: operation.requestId, kind: operation.kind }))),
|
|
56
|
+
});
|
|
57
|
+
},
|
|
58
|
+
listSessions: async () => {
|
|
59
|
+
assertLive();
|
|
60
|
+
return (await host.listSessions()).map(snapshotSession);
|
|
61
|
+
},
|
|
62
|
+
createSession: async () => {
|
|
63
|
+
assertLive();
|
|
64
|
+
return snapshotSession(await host.createSession());
|
|
65
|
+
},
|
|
66
|
+
openSession: async (sessionId) => {
|
|
67
|
+
assertLive();
|
|
68
|
+
return snapshotSession(await host.openSession(sessionId));
|
|
69
|
+
},
|
|
70
|
+
closeSession: async () => {
|
|
71
|
+
assertLive();
|
|
72
|
+
await host.closeSession();
|
|
73
|
+
},
|
|
74
|
+
prompt: (input, signal) => {
|
|
75
|
+
assertLive();
|
|
76
|
+
return host.prompt(input, signal);
|
|
77
|
+
},
|
|
78
|
+
promptWithImages: (text, images, signal) => {
|
|
79
|
+
assertLive();
|
|
80
|
+
return host.promptWithImages(text, images, signal);
|
|
81
|
+
},
|
|
82
|
+
steer: (input, signal) => {
|
|
83
|
+
assertLive();
|
|
84
|
+
return host.steer(input, signal);
|
|
85
|
+
},
|
|
86
|
+
steerWithImages: (text, images, signal) => {
|
|
87
|
+
assertLive();
|
|
88
|
+
return host.steerWithImages(text, images, signal);
|
|
89
|
+
},
|
|
90
|
+
retry: (signal) => {
|
|
91
|
+
assertLive();
|
|
92
|
+
return host.retry(signal);
|
|
93
|
+
},
|
|
94
|
+
cancel: (requestId) => {
|
|
95
|
+
assertLive();
|
|
96
|
+
return host.cancel(requestId);
|
|
97
|
+
},
|
|
98
|
+
transcript: () => {
|
|
99
|
+
assertLive();
|
|
100
|
+
return host.transcript();
|
|
101
|
+
},
|
|
102
|
+
tree: () => {
|
|
103
|
+
assertLive();
|
|
104
|
+
return host.tree();
|
|
105
|
+
},
|
|
106
|
+
navigateTree: (entryId) => {
|
|
107
|
+
assertLive();
|
|
108
|
+
return host.navigateTree(entryId);
|
|
109
|
+
},
|
|
110
|
+
setModel: (modelId) => {
|
|
111
|
+
assertLive();
|
|
112
|
+
return host.setModel(modelId);
|
|
113
|
+
},
|
|
114
|
+
setRuntime: (provider, model) => {
|
|
115
|
+
assertLive();
|
|
116
|
+
return host.setRuntime(provider.id, model.id);
|
|
117
|
+
},
|
|
118
|
+
cycleThinkingLevel: () => {
|
|
119
|
+
assertLive();
|
|
120
|
+
return host.cycleThinkingLevel();
|
|
121
|
+
},
|
|
122
|
+
compact: (signal) => {
|
|
123
|
+
assertLive();
|
|
124
|
+
return host.compact(signal);
|
|
125
|
+
},
|
|
126
|
+
setCompactionEnabled: (enabled) => {
|
|
127
|
+
assertLive();
|
|
128
|
+
return host.setCompactionEnabled(enabled);
|
|
129
|
+
},
|
|
130
|
+
usage: () => {
|
|
131
|
+
assertLive();
|
|
132
|
+
return host.usage();
|
|
133
|
+
},
|
|
134
|
+
subscribe: (listener) => {
|
|
135
|
+
assertLive();
|
|
136
|
+
return host.subscribe(listener);
|
|
137
|
+
},
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
function createUiHost(context, request, host, signal, locale) {
|
|
141
|
+
let disposed = false;
|
|
142
|
+
const assertLive = () => {
|
|
143
|
+
if (disposed)
|
|
144
|
+
throw new UiHostLifecycleError();
|
|
145
|
+
};
|
|
146
|
+
const product = {
|
|
147
|
+
apiVersion: UI_HOST_API_VERSION,
|
|
148
|
+
locale,
|
|
149
|
+
projectTrusted: request.projectTrusted,
|
|
150
|
+
resources: () => {
|
|
151
|
+
assertLive();
|
|
152
|
+
const session = host.ui();
|
|
153
|
+
return Object.freeze({
|
|
154
|
+
models: Object.freeze([...session.availableModels]),
|
|
155
|
+
skills: Object.freeze(session.availableSkills.map((skill) => Object.freeze({ name: skill.name, description: skill.description, scope: skill.scope }))),
|
|
156
|
+
});
|
|
157
|
+
},
|
|
158
|
+
themes: {
|
|
159
|
+
list: () => {
|
|
160
|
+
assertLive();
|
|
161
|
+
return context.require(themeRegistryKey).list();
|
|
162
|
+
},
|
|
163
|
+
register: (name, theme) => {
|
|
164
|
+
assertLive();
|
|
165
|
+
return context.require(themeRegistryKey).register(name, theme);
|
|
166
|
+
},
|
|
167
|
+
},
|
|
168
|
+
keybindings: {
|
|
169
|
+
snapshot: () => {
|
|
170
|
+
assertLive();
|
|
171
|
+
return context.require(keybindingRegistryKey).snapshot();
|
|
172
|
+
},
|
|
173
|
+
set: (bindings) => {
|
|
174
|
+
assertLive();
|
|
175
|
+
return context.require(keybindingRegistryKey).set(bindings);
|
|
176
|
+
},
|
|
177
|
+
},
|
|
178
|
+
diagnostics: {
|
|
179
|
+
report: (message) => {
|
|
180
|
+
assertLive();
|
|
181
|
+
request.stderr(`${redactSensitiveText(message)}\n`);
|
|
182
|
+
},
|
|
183
|
+
snapshot: () => {
|
|
184
|
+
assertLive();
|
|
185
|
+
return context.require(diagnosticsKey).records.map((record) => Object.freeze({
|
|
186
|
+
type: record.type,
|
|
187
|
+
...(record.message ? { message: redactSensitiveText(record.message) } : {}),
|
|
188
|
+
...(record.pluginName ? { pluginName: record.pluginName } : {}),
|
|
189
|
+
}));
|
|
190
|
+
},
|
|
191
|
+
},
|
|
192
|
+
};
|
|
193
|
+
const api = {
|
|
194
|
+
apiVersion: UI_HOST_API_VERSION,
|
|
195
|
+
signal,
|
|
196
|
+
product,
|
|
197
|
+
session: createUiSession(host, () => disposed),
|
|
198
|
+
initialPrompt: request.command.prompt,
|
|
199
|
+
dispose: async () => {
|
|
200
|
+
if (disposed)
|
|
201
|
+
return;
|
|
202
|
+
disposed = true;
|
|
203
|
+
await host.dispose();
|
|
204
|
+
},
|
|
205
|
+
};
|
|
206
|
+
return api;
|
|
207
|
+
}
|
|
208
|
+
async function runUiHost(context, input, start, signal) {
|
|
209
|
+
if (!isInteractiveHostRequest(input))
|
|
210
|
+
throw new TypeError("Interactive host request is invalid");
|
|
211
|
+
const request = input;
|
|
212
|
+
const configuration = await loadStartupConfiguration(request.cwd, process.env, request.agentDir);
|
|
213
|
+
const runtime = shouldStartProviderOnboarding(request.command, true, configuration)
|
|
214
|
+
? await runProviderOnboarding({ configuration, terminal: new ProcessTerminal(), agentDir: request.agentDir })
|
|
215
|
+
: resolveStartupRuntime(configuration.environment, configuration.providers, configuration.defaults);
|
|
216
|
+
if (!runtime)
|
|
217
|
+
return 0;
|
|
218
|
+
const host = await createSessionHost(context, {
|
|
219
|
+
cwd: request.cwd,
|
|
220
|
+
agentDir: request.agentDir,
|
|
221
|
+
projectTrusted: request.projectTrusted,
|
|
222
|
+
noSkills: request.command.noSkills,
|
|
223
|
+
noContextFiles: request.command.noContextFiles,
|
|
224
|
+
skillPaths: request.command.skillPaths,
|
|
225
|
+
provider: runtime.provider,
|
|
226
|
+
model: runtime.model,
|
|
227
|
+
signal,
|
|
228
|
+
...(request.command.sessionPath ? { initialSessionPath: resolve(request.cwd, request.command.sessionPath) } : {}),
|
|
229
|
+
});
|
|
230
|
+
if (!host.state().activeSession)
|
|
231
|
+
await host.createSession();
|
|
232
|
+
const ui = createUiHost(context, request, host, signal ?? new AbortController().signal, configuration.locale ?? "en");
|
|
233
|
+
try {
|
|
234
|
+
const started = Promise.resolve(start({ host: ui, signal: ui.signal }));
|
|
235
|
+
if (signal === undefined)
|
|
236
|
+
await started;
|
|
237
|
+
else {
|
|
238
|
+
let onAbort;
|
|
239
|
+
const cancelled = new Promise((_resolve, reject) => {
|
|
240
|
+
onAbort = () => reject(signal.reason ?? new DOMException("The operation was aborted.", "AbortError"));
|
|
241
|
+
if (signal.aborted) {
|
|
242
|
+
onAbort();
|
|
243
|
+
return;
|
|
244
|
+
}
|
|
245
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
246
|
+
});
|
|
247
|
+
try {
|
|
248
|
+
await Promise.race([started, cancelled]);
|
|
249
|
+
}
|
|
250
|
+
finally {
|
|
251
|
+
if (onAbort)
|
|
252
|
+
signal.removeEventListener("abort", onAbort);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
return 0;
|
|
256
|
+
}
|
|
257
|
+
finally {
|
|
258
|
+
await ui.dispose();
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
/**
|
|
262
|
+
* Creates a composition entry that replaces `interactive-host` without granting command-registry access.
|
|
263
|
+
* The returned entry owns the product bootstrap and always disposes its UiHost after `start` settles.
|
|
264
|
+
*/
|
|
265
|
+
export function createUiHostEntry(start) {
|
|
266
|
+
return {
|
|
267
|
+
apiVersion: UI_HOST_API_VERSION,
|
|
268
|
+
name: "ui-host",
|
|
269
|
+
apply: (context, _config, fiber) => {
|
|
270
|
+
const registry = context.require(hostCommandRegistryKey);
|
|
271
|
+
fiber.addDisposer(registry.register("interactive", (input, signal) => runUiHost(context, input, start, signal)));
|
|
272
|
+
},
|
|
273
|
+
};
|
|
274
|
+
}
|
|
275
|
+
//# sourceMappingURL=ui-host.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ui-host.js","sourceRoot":"","sources":["../src/ui-host.ts"],"names":[],"mappings":"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","sourcesContent":["import { resolve } from \"node:path\";\nimport type { AssistantMessage, ImageContent, Message, Model, Provider, ThinkingLevel } from \"@di-code/ai\";\nimport { diagnosticsKey, hostCommandRegistryKey, keybindingRegistryKey, themeRegistryKey } from \"@di-code/builtins\";\nimport { type Context, type PluginDefinition, redactSensitiveText } from \"@di-code/plugin-runtime\";\nimport { type KeybindingsConfig, ProcessTerminal, type TuiTheme } from \"@di-code/tui\";\nimport type { Locale } from \"./i18n.ts\";\nimport { runProviderOnboarding, shouldStartProviderOnboarding } from \"./provider-onboarding.ts\";\nimport type { InteractiveHostRequest } from \"./runtime/interactive-host-service.ts\";\nimport {\n\tcreateSessionHost,\n\ttype PromptInput,\n\ttype SessionHost,\n\ttype SessionHostEvent,\n\ttype SessionInfo,\n} from \"./runtime/session-host.ts\";\nimport { loadStartupConfiguration, resolveStartupRuntime } from \"./startup.ts\";\n\n/** Version of the stable in-process custom TUI contract. */\nexport const UI_HOST_API_VERSION = 1 as const;\n\nexport type UiHostApiVersion = typeof UI_HOST_API_VERSION;\n\nexport type UiHostErrorCode =\n\t| \"INVALID_WORKSPACE\"\n\t| \"NOT_FOUND\"\n\t| \"BUSY\"\n\t| \"SESSION_IN_USE\"\n\t| \"DISPOSED\"\n\t| \"INVALID_INPUT\"\n\t| \"INTERNAL\";\n\n/** Errors from SessionHost-owned operations expose a stable code but not internal causes. */\nexport interface UiHostError extends Error {\n\treadonly code: UiHostErrorCode;\n}\n\n/** Thrown synchronously when a facade is used after host disposal begins. */\nexport class UiHostLifecycleError extends Error {\n\treadonly code = \"DISPOSED\" as const;\n\tconstructor() {\n\t\tsuper(\"UiHost has been disposed.\");\n\t\tthis.name = \"UiHostLifecycleError\";\n\t}\n}\n\nexport type UiHostEvent = SessionHostEvent;\n\nexport interface UiHostSessionSnapshot {\n\treadonly id: string;\n\treadonly label: string;\n\treadonly modifiedAt?: number;\n}\n\nexport type UiHostOperationKind = \"prompt\" | \"steer\" | \"retry\" | \"compact\" | \"tree\" | \"session\";\n\n/** Read-only Session state that intentionally omits managed paths and internal Session references. */\nexport interface UiHostSessionState {\n\treadonly disposed: false;\n\treadonly activeSession?: UiHostSessionSnapshot;\n\treadonly busy: boolean;\n\treadonly operations: readonly { readonly requestId: string; readonly kind: UiHostOperationKind }[];\n}\n\n/** Read-only resources selected by product bootstrap for this TUI lifetime. */\nexport interface UiHostResourceSnapshot {\n\treadonly models: readonly Model[];\n\treadonly skills: readonly { readonly name: string; readonly description: string; readonly scope: string }[];\n}\n\nexport interface UiHostDiagnostics {\n\t/** Writes redacted diagnostic text to the CLI diagnostic stream. */\n\treport(message: string): void;\n\t/** Returns a read-only snapshot of runtime diagnostics known when it is called. */\n\tsnapshot(): readonly { readonly type: string; readonly message?: string; readonly pluginName?: string }[];\n}\n\nexport interface UiHostThemeRegistry {\n\treadonly list: () => readonly { readonly name: string; readonly theme: TuiTheme }[];\n\t/** Registration belongs to the plugin Fiber and is removed during composition disposal. */\n\treadonly register: (name: string, theme: TuiTheme) => () => void;\n}\n\nexport interface UiHostKeybindingRegistry {\n\treadonly snapshot: () => KeybindingsConfig;\n\t/** Replaces the presentation keybinding snapshot for this composition scope. */\n\treadonly set: (bindings: KeybindingsConfig) => () => void;\n}\n\n/** Product-scoped facilities. It deliberately does not expose command execution or bootstrap service keys. */\nexport interface ProductHost {\n\treadonly apiVersion: UiHostApiVersion;\n\treadonly locale: Locale;\n\treadonly projectTrusted: boolean;\n\treadonly resources: () => UiHostResourceSnapshot;\n\treadonly themes: UiHostThemeRegistry;\n\treadonly keybindings: UiHostKeybindingRegistry;\n\treadonly diagnostics: UiHostDiagnostics;\n}\n\n/** A lifecycle-checked view over the current product Session, never an AgentSession instance. */\nexport interface UiSessionHost {\n\treadonly state: () => UiHostSessionState;\n\treadonly listSessions: () => Promise<readonly UiHostSessionSnapshot[]>;\n\treadonly createSession: () => Promise<UiHostSessionSnapshot>;\n\treadonly openSession: (sessionId: string) => Promise<UiHostSessionSnapshot>;\n\treadonly closeSession: () => Promise<void>;\n\treadonly prompt: (input: PromptInput | string, signal?: AbortSignal) => Promise<AssistantMessage>;\n\treadonly promptWithImages: (\n\t\ttext: string,\n\t\timages: readonly ImageContent[],\n\t\tsignal?: AbortSignal,\n\t) => Promise<AssistantMessage>;\n\treadonly steer: (input: PromptInput | string, signal?: AbortSignal) => Promise<void>;\n\treadonly steerWithImages: (text: string, images: readonly ImageContent[], signal?: AbortSignal) => Promise<void>;\n\treadonly retry: (signal?: AbortSignal) => Promise<AssistantMessage>;\n\treadonly cancel: (requestId: string) => boolean;\n\treadonly transcript: () => readonly Message[];\n\treadonly tree: SessionHost[\"tree\"];\n\treadonly navigateTree: SessionHost[\"navigateTree\"];\n\treadonly setModel: SessionHost[\"setModel\"];\n\treadonly setRuntime: (provider: Provider, model: Model) => Model;\n\treadonly cycleThinkingLevel: () => ThinkingLevel | undefined;\n\treadonly compact: SessionHost[\"compact\"];\n\treadonly setCompactionEnabled: SessionHost[\"setCompactionEnabled\"];\n\treadonly usage: SessionHost[\"usage\"];\n\treadonly subscribe: SessionHost[\"subscribe\"];\n}\n\n/** Stable facade passed to a custom TUI. It becomes unusable as soon as `dispose()` begins. */\nexport interface UiHost {\n\treadonly apiVersion: UiHostApiVersion;\n\treadonly signal: AbortSignal;\n\treadonly product: ProductHost;\n\treadonly session: UiSessionHost;\n\treadonly initialPrompt: string;\n\treadonly dispose: () => Promise<void>;\n}\n\nexport interface UiHostStartContext {\n\treadonly host: UiHost;\n\treadonly signal: AbortSignal;\n}\n\n/**\n * The only callback a replacement interactive host supplies. Resolve when its UI exits; reject to fail startup.\n * The product then aborts in-flight work, releases the Session/MCP resources, and invalidates the facade.\n */\nexport type UiHostStart = (context: UiHostStartContext) => void | Promise<void>;\n\nfunction isInteractiveHostRequest(value: unknown): value is InteractiveHostRequest {\n\treturn (\n\t\ttypeof value === \"object\" &&\n\t\tvalue !== null &&\n\t\t\"command\" in value &&\n\t\ttypeof value.command === \"object\" &&\n\t\tvalue.command !== null &&\n\t\t\"mode\" in value.command &&\n\t\tvalue.command.mode === \"interactive\" &&\n\t\t\"cwd\" in value &&\n\t\ttypeof value.cwd === \"string\" &&\n\t\t\"agentDir\" in value &&\n\t\ttypeof value.agentDir === \"string\" &&\n\t\t\"projectTrusted\" in value &&\n\t\ttypeof value.projectTrusted === \"boolean\" &&\n\t\t\"stderr\" in value &&\n\t\ttypeof value.stderr === \"function\"\n\t);\n}\n\nfunction snapshotSession(info: SessionInfo): UiHostSessionSnapshot {\n\treturn Object.freeze({\n\t\tid: info.id,\n\t\tlabel: info.label,\n\t\t...(info.modifiedAt === undefined ? {} : { modifiedAt: info.modifiedAt }),\n\t});\n}\n\nfunction createUiSession(host: SessionHost, isDisposed: () => boolean): UiSessionHost {\n\tconst assertLive = (): void => {\n\t\tif (isDisposed()) throw new UiHostLifecycleError();\n\t};\n\treturn {\n\t\tstate: () => {\n\t\t\tassertLive();\n\t\t\tconst state = host.state();\n\t\t\treturn Object.freeze({\n\t\t\t\tdisposed: false as const,\n\t\t\t\t...(state.activeSession ? { activeSession: snapshotSession(state.activeSession) } : {}),\n\t\t\t\tbusy: state.busy,\n\t\t\t\toperations: Object.freeze(\n\t\t\t\t\tstate.operations.map((operation) =>\n\t\t\t\t\t\tObject.freeze({ requestId: operation.requestId, kind: operation.kind as UiHostOperationKind }),\n\t\t\t\t\t),\n\t\t\t\t),\n\t\t\t});\n\t\t},\n\t\tlistSessions: async () => {\n\t\t\tassertLive();\n\t\t\treturn (await host.listSessions()).map(snapshotSession);\n\t\t},\n\t\tcreateSession: async () => {\n\t\t\tassertLive();\n\t\t\treturn snapshotSession(await host.createSession());\n\t\t},\n\t\topenSession: async (sessionId) => {\n\t\t\tassertLive();\n\t\t\treturn snapshotSession(await host.openSession(sessionId));\n\t\t},\n\t\tcloseSession: async () => {\n\t\t\tassertLive();\n\t\t\tawait host.closeSession();\n\t\t},\n\t\tprompt: (input, signal) => {\n\t\t\tassertLive();\n\t\t\treturn host.prompt(input, signal);\n\t\t},\n\t\tpromptWithImages: (text, images, signal) => {\n\t\t\tassertLive();\n\t\t\treturn host.promptWithImages(text, images, signal);\n\t\t},\n\t\tsteer: (input, signal) => {\n\t\t\tassertLive();\n\t\t\treturn host.steer(input, signal);\n\t\t},\n\t\tsteerWithImages: (text, images, signal) => {\n\t\t\tassertLive();\n\t\t\treturn host.steerWithImages(text, images, signal);\n\t\t},\n\t\tretry: (signal) => {\n\t\t\tassertLive();\n\t\t\treturn host.retry(signal);\n\t\t},\n\t\tcancel: (requestId) => {\n\t\t\tassertLive();\n\t\t\treturn host.cancel(requestId);\n\t\t},\n\t\ttranscript: () => {\n\t\t\tassertLive();\n\t\t\treturn host.transcript();\n\t\t},\n\t\ttree: () => {\n\t\t\tassertLive();\n\t\t\treturn host.tree();\n\t\t},\n\t\tnavigateTree: (entryId) => {\n\t\t\tassertLive();\n\t\t\treturn host.navigateTree(entryId);\n\t\t},\n\t\tsetModel: (modelId) => {\n\t\t\tassertLive();\n\t\t\treturn host.setModel(modelId);\n\t\t},\n\t\tsetRuntime: (provider, model) => {\n\t\t\tassertLive();\n\t\t\treturn host.setRuntime(provider.id, model.id);\n\t\t},\n\t\tcycleThinkingLevel: () => {\n\t\t\tassertLive();\n\t\t\treturn host.cycleThinkingLevel();\n\t\t},\n\t\tcompact: (signal) => {\n\t\t\tassertLive();\n\t\t\treturn host.compact(signal);\n\t\t},\n\t\tsetCompactionEnabled: (enabled) => {\n\t\t\tassertLive();\n\t\t\treturn host.setCompactionEnabled(enabled);\n\t\t},\n\t\tusage: () => {\n\t\t\tassertLive();\n\t\t\treturn host.usage();\n\t\t},\n\t\tsubscribe: (listener) => {\n\t\t\tassertLive();\n\t\t\treturn host.subscribe(listener);\n\t\t},\n\t};\n}\n\nfunction createUiHost(\n\tcontext: Context,\n\trequest: InteractiveHostRequest,\n\thost: SessionHost,\n\tsignal: AbortSignal,\n\tlocale: Locale,\n): UiHost {\n\tlet disposed = false;\n\tconst assertLive = (): void => {\n\t\tif (disposed) throw new UiHostLifecycleError();\n\t};\n\tconst product: ProductHost = {\n\t\tapiVersion: UI_HOST_API_VERSION,\n\t\tlocale,\n\t\tprojectTrusted: request.projectTrusted,\n\t\tresources: () => {\n\t\t\tassertLive();\n\t\t\tconst session = host.ui();\n\t\t\treturn Object.freeze({\n\t\t\t\tmodels: Object.freeze([...session.availableModels]),\n\t\t\t\tskills: Object.freeze(\n\t\t\t\t\tsession.availableSkills.map((skill) =>\n\t\t\t\t\t\tObject.freeze({ name: skill.name, description: skill.description, scope: skill.scope }),\n\t\t\t\t\t),\n\t\t\t\t),\n\t\t\t});\n\t\t},\n\t\tthemes: {\n\t\t\tlist: () => {\n\t\t\t\tassertLive();\n\t\t\t\treturn context.require(themeRegistryKey).list() as readonly {\n\t\t\t\t\treadonly name: string;\n\t\t\t\t\treadonly theme: TuiTheme;\n\t\t\t\t}[];\n\t\t\t},\n\t\t\tregister: (name, theme) => {\n\t\t\t\tassertLive();\n\t\t\t\treturn context.require(themeRegistryKey).register(name, theme);\n\t\t\t},\n\t\t},\n\t\tkeybindings: {\n\t\t\tsnapshot: () => {\n\t\t\t\tassertLive();\n\t\t\t\treturn context.require(keybindingRegistryKey).snapshot() as KeybindingsConfig;\n\t\t\t},\n\t\t\tset: (bindings) => {\n\t\t\t\tassertLive();\n\t\t\t\treturn context.require(keybindingRegistryKey).set(bindings);\n\t\t\t},\n\t\t},\n\t\tdiagnostics: {\n\t\t\treport: (message) => {\n\t\t\t\tassertLive();\n\t\t\t\trequest.stderr(`${redactSensitiveText(message)}\\n`);\n\t\t\t},\n\t\t\tsnapshot: () => {\n\t\t\t\tassertLive();\n\t\t\t\treturn context.require(diagnosticsKey).records.map((record) =>\n\t\t\t\t\tObject.freeze({\n\t\t\t\t\t\ttype: record.type,\n\t\t\t\t\t\t...(record.message ? { message: redactSensitiveText(record.message) } : {}),\n\t\t\t\t\t\t...(record.pluginName ? { pluginName: record.pluginName } : {}),\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t},\n\t\t},\n\t};\n\tconst api: UiHost = {\n\t\tapiVersion: UI_HOST_API_VERSION,\n\t\tsignal,\n\t\tproduct,\n\t\tsession: createUiSession(host, () => disposed),\n\t\tinitialPrompt: request.command.prompt,\n\t\tdispose: async () => {\n\t\t\tif (disposed) return;\n\t\t\tdisposed = true;\n\t\t\tawait host.dispose();\n\t\t},\n\t};\n\treturn api;\n}\n\nasync function runUiHost(context: Context, input: unknown, start: UiHostStart, signal?: AbortSignal): Promise<number> {\n\tif (!isInteractiveHostRequest(input)) throw new TypeError(\"Interactive host request is invalid\");\n\tconst request = input;\n\tconst configuration = await loadStartupConfiguration(request.cwd, process.env, request.agentDir);\n\tconst runtime = shouldStartProviderOnboarding(request.command, true, configuration)\n\t\t? await runProviderOnboarding({ configuration, terminal: new ProcessTerminal(), agentDir: request.agentDir })\n\t\t: resolveStartupRuntime(configuration.environment, configuration.providers, configuration.defaults);\n\tif (!runtime) return 0;\n\tconst host = await createSessionHost(context, {\n\t\tcwd: request.cwd,\n\t\tagentDir: request.agentDir,\n\t\tprojectTrusted: request.projectTrusted,\n\t\tnoSkills: request.command.noSkills,\n\t\tnoContextFiles: request.command.noContextFiles,\n\t\tskillPaths: request.command.skillPaths,\n\t\tprovider: runtime.provider,\n\t\tmodel: runtime.model,\n\t\tsignal,\n\t\t...(request.command.sessionPath ? { initialSessionPath: resolve(request.cwd, request.command.sessionPath) } : {}),\n\t});\n\tif (!host.state().activeSession) await host.createSession();\n\tconst ui = createUiHost(context, request, host, signal ?? new AbortController().signal, configuration.locale ?? \"en\");\n\ttry {\n\t\tconst started = Promise.resolve(start({ host: ui, signal: ui.signal }));\n\t\tif (signal === undefined) await started;\n\t\telse {\n\t\t\tlet onAbort: (() => void) | undefined;\n\t\t\tconst cancelled = new Promise<never>((_resolve, reject) => {\n\t\t\t\tonAbort = () => reject(signal.reason ?? new DOMException(\"The operation was aborted.\", \"AbortError\"));\n\t\t\t\tif (signal.aborted) {\n\t\t\t\t\tonAbort();\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tsignal.addEventListener(\"abort\", onAbort, { once: true });\n\t\t\t});\n\t\t\ttry {\n\t\t\t\tawait Promise.race([started, cancelled]);\n\t\t\t} finally {\n\t\t\t\tif (onAbort) signal.removeEventListener(\"abort\", onAbort);\n\t\t\t}\n\t\t}\n\t\treturn 0;\n\t} finally {\n\t\tawait ui.dispose();\n\t}\n}\n\n/**\n * Creates a composition entry that replaces `interactive-host` without granting command-registry access.\n * The returned entry owns the product bootstrap and always disposes its UiHost after `start` settles.\n */\nexport function createUiHostEntry(start: UiHostStart): PluginDefinition {\n\treturn {\n\t\tapiVersion: UI_HOST_API_VERSION,\n\t\tname: \"ui-host\",\n\t\tapply: (context, _config, fiber) => {\n\t\t\tconst registry = context.require(hostCommandRegistryKey);\n\t\t\tfiber.addDisposer(registry.register(\"interactive\", (input, signal) => runUiHost(context, input, start, signal)));\n\t\t},\n\t};\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
:root{color:#18202a;font-synthesis:none;--ink:#18202a;--muted:#77808c;--line:#e6e8eb;--sidebar:#f1f3f5;--surface:#fff;--accent:#2957d6;--accent-soft:#e9efff;background:#f7f8fa;font-family:Inter,ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,sans-serif}*{box-sizing:border-box}body{background:#f7f8fa;min-width:320px;min-height:100vh;margin:0;overflow:hidden}button,textarea,input{font:inherit}button{cursor:pointer;border:0}button:focus-visible,input:focus-visible,textarea:focus-visible{outline-offset:2px;outline:2px solid #5b7bea}.app-shell{grid-template-columns:264px minmax(0,1fr);height:100vh;min-height:0;display:grid;overflow:hidden}.app-shell.sidebar-collapsed{grid-template-columns:68px minmax(0,1fr)}.sidebar{background:var(--sidebar);border-right:1px solid var(--line);flex-direction:column;min-height:0;padding:16px 12px 12px;display:flex;overflow:hidden}.sidebar-topline{align-items:center;gap:9px;height:34px;padding:0 4px;display:flex}.mark{color:#fff;background:#1e2732;border-radius:7px;flex:none;place-items:center;width:26px;height:26px;display:grid}.wordmark{flex:1;font-size:15px;font-weight:700}.icon-button{color:#6f7884;background:0 0;border-radius:6px;flex:none;place-items:center;width:32px;height:32px;display:inline-grid}.icon-button:hover,.icon-button.is-active{color:var(--ink);background:#e4e7eb}.workspace-switcher{text-align:left;width:100%;color:var(--ink);background:0 0;border-radius:6px;align-items:center;gap:9px;margin-top:22px;padding:8px;font-size:13px;display:flex}.workspace-switcher:hover{background:#e7eaed}.workspace-avatar{color:#fff;background:#3c7b6e;border-radius:6px;place-items:center;width:23px;height:23px;font-size:11px;font-weight:700;display:grid}.workspace-name{min-width:0;color:inherit;appearance:none;cursor:pointer;background:0 0;border:0;outline:0;flex:1;font-weight:600}.workspace-switcher svg{pointer-events:none;flex:none}.new-session{color:#fff;background:#25303c;border-radius:6px;align-items:center;gap:9px;width:100%;margin-top:18px;padding:10px 9px;font-size:13px;display:flex}.new-session:hover{background:#344151}.shortcut{color:#aeb7c2;margin-left:auto;font-size:11px}.session-search{color:#8c949f;background:#e8ebee;border-radius:6px;align-items:center;gap:8px;height:34px;margin-top:12px;padding:0 9px;display:flex}.session-search input{width:100%;min-width:0;color:var(--ink);background:0 0;border:0;outline:0;font-size:12px}.session-search input::placeholder{color:#8c949f}.session-heading{color:#8b939e;text-transform:uppercase;letter-spacing:.06em;align-items:center;gap:7px;margin:24px 9px 8px;font-size:11px;font-weight:650;display:flex}.session-count{color:#9da4ad}.session-tree{flex:1;min-height:90px;overflow:auto}.tree-placeholder{color:#a0a8b1;margin:0;padding:12px 10px;font-size:12px;line-height:1.45}.session-item{color:#66707c;text-align:left;background:0 0;border-radius:5px;align-items:center;gap:8px;width:100%;padding:8px 9px;font-size:12px;display:flex}.session-item:hover{color:var(--ink);background:#e4e7ea}.session-item span{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.sidebar-footer{border-top:1px solid #e1e4e7;gap:2px;padding-top:12px;display:grid}.footer-button{color:#6f7884;text-align:left;background:0 0;border-radius:5px;align-items:center;gap:9px;padding:9px;font-size:12px;display:flex}.footer-button:hover{color:var(--ink);background:#e5e8eb}.is-collapsed .sidebar-topline{justify-content:center}.is-collapsed .icon-button{display:none}.is-collapsed .sidebar-topline .icon-button{display:inline-grid}.collapsed-actions{justify-items:center;gap:8px;margin-top:20px;display:grid}.main-column{flex-direction:column;min-width:0;min-height:0;display:flex;overflow:hidden}.workspace-bar{border-bottom:1px solid var(--line);background:#ffffffc7;align-items:center;gap:10px;height:58px;padding:0 22px;display:flex}.workspace-bar>.icon-button{display:none}.bar-title{align-items:center;gap:8px;font-size:13px;font-weight:650;display:flex}.bar-title-dot{background:#3c7b6e;border-radius:50%;width:8px;height:8px}.bar-actions{align-items:center;gap:4px;margin-left:auto;display:flex}.bar-action{color:#6e7783;background:0 0;border-radius:5px;align-items:center;gap:7px;padding:7px 10px;font-size:12px;display:flex}.bar-action:hover{color:var(--ink);background:#f0f2f4}.main-content{flex-direction:column;flex:1;min-height:0;display:flex;position:relative;overflow-y:auto}.empty-state{text-align:center;width:min(560px,100% - 40px);margin:auto;transform:translateY(-6vh)}.empty-icon{color:#536273;background:#e9edf1;border:1px solid #dde2e7;border-radius:12px;place-items:center;width:46px;height:46px;margin:0 auto 18px;display:grid}.empty-state h1{margin:0;font-size:26px;font-weight:680;line-height:1.2}.empty-state p{max-width:420px;color:var(--muted);margin:12px auto 18px;font-size:14px;line-height:1.5}.example-link{color:var(--accent);background:var(--accent-soft);border-radius:5px;align-items:center;gap:6px;padding:7px 10px;font-size:12px;display:inline-flex}.composer-wrap{width:min(760px,100% - 40px);margin:auto auto 24px}.composer{background:var(--surface);border:1px solid #d9dde2;border-radius:9px;box-shadow:0 5px 20px #26303e0f}.composer textarea{resize:none;width:100%;min-height:58px;max-height:180px;color:var(--ink);background:0 0;border:0;outline:0;padding:15px 16px 8px;font-size:14px;display:block}.composer textarea::placeholder{color:#9aa2ad}.composer-toolbar{align-items:center;gap:3px;padding:7px 9px 9px;display:flex}.composer-tool{color:#788390;background:0 0;border-radius:5px;place-items:center;width:29px;height:29px;display:grid}.composer-spacer{flex:1}.model-select{color:#727c88;background:0 0;border-radius:5px;align-items:center;gap:6px;padding:6px 8px;font-size:11px;display:flex}.send-button{color:#fff;background:#25303c;border-radius:6px;place-items:center;width:30px;height:30px;display:grid}.send-button:disabled{color:#b7bec6;background:#e3e6e9}.composer-note{color:#a5acb5;text-align:center;margin:8px 0 0;font-size:10px}.loading-state{color:var(--muted);margin:auto;font-size:13px}.connection-banner{color:#90534f;background:#fff3f1;border:1px solid #f1d6d1;border-radius:6px;margin:16px auto 0;padding:9px 12px;font-size:12px}.session-item.is-active{color:var(--ink);background:#e4e7ea}.workspace-heading{color:#8b939e;text-transform:uppercase;letter-spacing:.06em;align-items:center;gap:7px;margin:22px 9px 8px;font-size:11px;font-weight:650;display:flex}.workspace-heading-actions{align-items:center;gap:1px;margin-left:auto;display:inline-flex}.workspace-heading-actions .icon-button{width:28px;height:28px}.workspace-add-overlay{z-index:30;background:#191f2640;place-items:center;padding:24px;display:grid;position:fixed;inset:0}.workspace-add-dialog{width:min(420px,100%);color:var(--ink);background:var(--surface);border:1px solid var(--line);border-radius:8px;padding:18px;box-shadow:0 16px 48px #12192133}.workspace-pick-button{width:100%;color:var(--ink);border:1px solid var(--line);background:#f0f2f4;border-radius:5px;align-items:center;gap:7px;margin-top:18px;padding:10px 12px;font-size:12px;display:inline-flex}.workspace-pick-button:hover{background:#e7eaed}.workspace-drop-zone{color:var(--muted);text-align:center;border:1px dashed #b9c2cc;border-radius:6px;justify-items:center;gap:6px;margin-top:16px;padding:22px 12px;display:grid}.workspace-drop-zone svg{color:#5a789d}.workspace-drop-zone span{color:var(--ink);font-size:12px}.workspace-drop-zone small{font-size:11px}.workspace-add-header{border-bottom:1px solid var(--line);justify-content:space-between;align-items:flex-start;padding-bottom:14px;display:flex}.workspace-add-header h2{margin:0;font-size:18px}.workspace-add-note{color:var(--muted);margin:16px 0 0;font-size:12px;line-height:1.5}.workspace-add-field{color:var(--muted);gap:7px;margin-top:18px;font-size:12px;display:grid}.workspace-add-field input{width:100%;color:var(--ink);background:var(--surface);border:1px solid var(--line);border-radius:5px;padding:9px 10px;font-size:13px}.workspace-add-error{color:#9b453e;margin:10px 0 0;font-size:12px}.workspace-add-actions{justify-content:flex-end;gap:8px;margin-top:18px;display:flex}.workspace-add-actions button{color:var(--muted);background:0 0;border-radius:5px;padding:7px 11px;font-size:12px}.workspace-add-actions button:hover{color:var(--ink);background:#f0f2f4}.workspace-add-actions .workspace-add-submit{color:#fff;background:#25303c}.workspace-add-actions .workspace-add-submit:disabled{color:#aab2bb;cursor:not-allowed;background:#e3e6e9}.workspace-search{margin-top:0}.workspace-list{flex:1;min-height:90px;padding:2px 0 10px;overflow:auto}.workspace-section{margin:2px 0}.workspace-section-header-wrap{border-radius:6px;align-items:center;min-width:0;display:flex;position:relative}.workspace-section-header-wrap:hover,.workspace-section.is-active>.workspace-section-header-wrap{background:#e4e7ea}.workspace-section-header{color:#5f6975;text-align:left;background:0 0;border-radius:6px;flex:1;align-items:center;gap:8px;min-width:0;padding:8px;font-size:13px;display:flex}.workspace-section-header-wrap:hover .workspace-section-header,.workspace-section.is-active>.workspace-section-header-wrap .workspace-section-header{color:var(--ink)}.workspace-folder-icon{color:#65717e;flex:none;place-items:center;width:17px;height:17px;display:grid;position:relative}.workspace-folder-icon>svg:last-child{display:none;position:absolute}.workspace-section-header-wrap:hover .workspace-folder-icon>svg:first-child{display:none}.workspace-section-header-wrap:hover .workspace-folder-icon>svg:last-child{display:block}.workspace-section.is-active>.workspace-section-header-wrap .workspace-folder-icon{color:#376fda}.workspace-section-name{text-overflow:ellipsis;white-space:nowrap;flex:1;min-width:0;font-weight:600;overflow:hidden}.workspace-session-count{color:#929aa5;font-size:11px}.workspace-row-actions{opacity:0;align-items:center;gap:1px;padding-right:4px;display:inline-flex}.workspace-section-header-wrap:hover .workspace-row-actions,.workspace-section.is-active>.workspace-section-header-wrap .workspace-row-actions,.workspace-row-actions:focus-within{opacity:1}.workspace-row-actions .icon-button{width:26px;height:26px}.workspace-menu-anchor{position:relative}.workspace-action-menu{z-index:9;min-width:132px;color:var(--ink);background:var(--surface);border:1px solid var(--line);border-radius:6px;gap:2px;padding:5px;display:grid;position:absolute;top:calc(100% + 3px);right:0;box-shadow:0 10px 28px #17202b29}.workspace-action-menu button{color:inherit;text-align:left;background:0 0;border-radius:4px;padding:7px 8px;font-size:11px}.workspace-action-menu button:hover{background:#f0f2f4}.workspace-inline-name{border:1px solid var(--line);min-width:0;color:var(--ink);background:var(--surface);border-radius:4px;flex:1;padding:3px 5px;font-size:12px}.workspace-section-sessions{padding:0 0 4px 17px}.workspace-section-sessions .session-tree{min-height:0;overflow:visible}.workspace-section-sessions .session-item{padding-top:7px;padding-bottom:7px}.workspace-section-sessions .session-item-actions{margin-right:2px}.session-search svg{flex:none}.session-item-wrap{align-items:center;gap:2px;min-width:0;display:flex;position:relative}.session-item-wrap .session-item{flex:1;min-width:0}.session-item-actions{opacity:0;flex:none;display:flex;position:relative}.session-item-wrap:hover .session-item-actions,.session-item-wrap.is-active .session-item-actions,.session-item-actions:focus-within{opacity:1}.session-item-actions button{color:var(--muted);background:0 0;border:0;padding:4px}.session-more{border-radius:4px;place-items:center;display:grid}.session-more:hover,.session-more:focus-visible{color:var(--ink);background:#e4e7eb}.session-action-menu{z-index:9;background:var(--surface);border:1px solid var(--line);border-radius:6px;gap:2px;min-width:128px;padding:5px;display:grid;position:absolute;top:calc(100% + 3px);right:0;box-shadow:0 10px 28px #17202b29}.session-action-menu button{width:100%;color:var(--ink);text-align:left;border-radius:4px;align-items:center;gap:7px;padding:7px 8px;font-size:11px;display:flex}.session-action-menu button:hover{background:#f0f2f4}.session-filters{gap:4px;margin:6px 0;display:flex}.session-filters button{border:1px solid var(--line);color:var(--muted);background:0 0;border-radius:4px;padding:3px 7px;font-size:11px}.session-filters .is-selected{background:var(--accent-soft);color:var(--ink)}.session-inspect{z-index:20;background:var(--surface);border:1px solid var(--line);padding:18px;position:fixed;inset:12% 10%;overflow:auto;box-shadow:0 20px 60px #12192133}.session-inspect pre{white-space:pre-wrap;font-size:11px}.cancel-button{background:#9b453e}.attachment-input{display:none}.attachment-tray{flex-wrap:wrap;gap:6px;padding:10px 12px 0;display:flex}.attachment-chip{color:#536273;background:#edf0f3;border:1px solid #dfe4e8;border-radius:5px;align-items:center;gap:5px;max-width:100%;padding:5px 6px;font-size:11px;display:inline-flex}.attachment-chip span{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.attachment-chip button{color:inherit;background:0 0;padding:1px;display:grid}.attachment-chip img{object-fit:cover;border-radius:3px;width:18px;height:18px}.connection-state{color:#5c6671;background:#eff2f5;border:1px solid #dbe0e5;border-radius:6px;align-self:center;margin-top:16px;padding:9px 12px;font-size:12px}.transcript{overflow-wrap:anywhere;gap:22px;width:min(760px,100% - 40px);margin:26px auto 16px;display:grid}.conversation-tabs{border-bottom:1px solid var(--line);gap:18px;width:min(760px,100% - 40px);margin:18px auto 0;display:flex}.conversation-tabs button{color:var(--muted);background:0 0;border-bottom:2px solid #0000;padding:9px 2px 10px;font-size:12px}.conversation-tabs button.is-selected{color:var(--ink);border-bottom-color:var(--accent);font-weight:650}.trajectory{gap:10px;width:min(760px,100% - 40px);min-height:180px;margin:18px auto 16px;display:grid;overflow:auto}.trajectory-row{color:var(--muted);grid-template-columns:18px minmax(0,1fr);align-items:start;gap:8px;font-size:12px;display:grid}.trajectory-row>svg{margin-top:10px}.trajectory-empty{color:var(--muted);font-size:13px}.trajectory-context,.trajectory-row.compaction-running,.trajectory-row.compaction-success,.trajectory-row.compaction-error{border:1px solid var(--line);background:var(--surface);border-radius:6px;padding:10px 12px}.trajectory-context summary{cursor:pointer;color:var(--ink);align-items:center;gap:7px;display:flex}.trajectory-context ul{gap:4px;margin:8px 0 0;padding-left:22px;display:grid}.trajectory-context li{color:var(--muted);justify-content:space-between;gap:8px;display:flex}.trajectory-context code{color:var(--ink);text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.tool-card{border:1px solid var(--line);background:var(--surface);min-width:0;color:var(--ink);border-radius:7px;overflow:hidden}.tool-card-header{align-items:center;gap:7px;padding:10px 12px;display:flex}.tool-icon{color:#2f7a65;place-items:center;display:inline-grid}.tool-error .tool-icon,.tool-timeout .tool-icon,.tool-cancelled .tool-icon{color:#a04e48}.tool-status{color:var(--muted);margin-left:auto;font-size:11px}.tool-card-details,.tool-output,.tool-diff{border-top:1px solid var(--line);padding:8px 12px}.tool-card-details summary,.tool-output summary,.tool-diff summary{cursor:pointer;color:var(--muted);align-items:center;gap:5px;font-size:11px;display:flex}.tool-card pre{white-space:pre-wrap;overflow-wrap:anywhere;max-height:220px;color:var(--ink);margin:8px 0 0;font:11px/1.5 ui-monospace,SFMono-Regular,Consolas,monospace;overflow:auto}.approval-bar{gap:6px;width:min(760px,100% - 40px);margin:0 auto 10px;display:grid}.approval-item{color:#77501f;background:#fff8e8;border:1px solid #ead9ad;border-radius:6px;flex-wrap:wrap;align-items:center;gap:8px;padding:10px 12px;font-size:12px;display:flex}.approval-item button{color:var(--ink);background:var(--surface);border:1px solid #d8cda9;border-radius:4px;align-items:center;gap:4px;padding:5px 8px;font-size:11px;display:inline-flex}.approval-item button:first-of-type{margin-left:auto}.approval-item code{color:#9a8864;font-size:10px}.spin{animation:.9s linear infinite spin}@keyframes spin{to{transform:rotate(360deg)}}.conversation-empty{color:var(--muted);margin:auto;font-size:13px}.message{gap:7px;display:grid}.message-user{background:#edf1f5;border-radius:7px;justify-self:end;max-width:min(88%,620px);padding:12px 14px}.message-label{color:var(--muted);font-size:11px;font-weight:700}.message-body{font-size:14px;line-height:1.65}.message-user .message-body{white-space:pre-wrap}.message-body>:first-child{margin-top:0}.message-body>:last-child{margin-bottom:0}.message-body p,.message-body ul,.message-body ol,.message-body blockquote,.message-body pre,.message-body table{margin:0 0 12px}.message-body h1,.message-body h2,.message-body h3,.message-body h4,.message-body h5,.message-body h6{color:var(--ink);margin:18px 0 8px;line-height:1.3}.message-body h1{font-size:22px}.message-body h2{font-size:19px}.message-body h3{font-size:16px}.message-body h4,.message-body h5,.message-body h6{font-size:14px}.message-body ul,.message-body ol{padding-left:24px}.message-body li+li{margin-top:4px}.message-body input[type=checkbox]{accent-color:var(--accent);margin:0 6px 0 0}.message-body a{color:var(--accent);text-underline-offset:2px;text-decoration:underline}.message-body a:hover{color:#1d45b5}.message-body :not(pre)>code{color:#4d5d70;background:#edf0f3;border:1px solid #e0e4e8;border-radius:4px;padding:2px 4px;font:.9em ui-monospace,SFMono-Regular,Consolas,monospace}.message-body pre{color:#dce5ee;background:#202a35;border-radius:6px;padding:12px;overflow:auto}.message-body pre code{font:12px/1.55 ui-monospace,SFMono-Regular,Consolas,monospace}.message-body blockquote{color:#566575;border-left:3px solid #aebdce;padding:2px 0 2px 12px}.message-body hr{background:var(--line);border:0;height:1px;margin:16px 0}.message-body table{border-spacing:0;border-collapse:collapse;max-width:100%;display:block;overflow-x:auto}.message-body th,.message-body td{border:1px solid var(--line);text-align:left;vertical-align:top;padding:7px 9px}.message-body th{background:#f2f4f6;font-weight:650}.message-skill{color:#536e9d;align-items:center;gap:6px;min-width:0;font-size:12px;display:inline-flex}.message-skill code{text-overflow:ellipsis;white-space:nowrap;min-width:0;color:inherit;overflow:hidden}.message-images{grid-template-columns:repeat(auto-fit,minmax(120px,1fr));gap:8px;display:grid}.message-images img{object-fit:contain;background:#fff;border:1px solid #d8dde2;border-radius:5px;max-width:100%;max-height:360px;display:block}.message-error{color:#8f3833;background:#fff2f0;border:1px solid #efcbc7;border-radius:6px;padding:10px 12px}.message-error .message-label{color:#9b453e}.thinking{color:#586574;background:#f3f5f7;border:1px solid #e1e5e8;border-radius:6px;padding:8px 10px;font-size:12px}.thinking summary{cursor:pointer;align-items:center;gap:6px;display:flex}.thinking pre{white-space:pre-wrap;font:inherit;margin:8px 0 0;line-height:1.55}.message-retry,.runtime-action{color:#55616e;background:#edf0f3;border-radius:5px;justify-content:center;align-items:center;gap:6px;width:fit-content;padding:6px 8px;font-size:11px;display:inline-flex}.runtime-controls{width:min(760px,100% - 40px);color:var(--muted);flex-wrap:wrap;align-items:center;gap:8px;margin:auto auto 10px;font-size:11px;display:flex}.usage{align-items:center;gap:6px;margin-right:auto;display:inline-flex}.usage span{border-left:1px solid var(--line);padding-left:6px}.runtime-action.danger,.runtime-error{color:#9b453e}.runtime-action.danger{background:#fff0ee}.overlay{z-index:10;background:#191f2642;place-items:center;padding:24px;display:grid;position:fixed;inset:0}.settings-panel{background:#fff;border:1px solid #dfe3e7;border-radius:10px;grid-template-columns:170px minmax(0,1fr);width:min(680px,100%);max-height:min(700px,100vh - 48px);display:grid;overflow:hidden;box-shadow:0 16px 50px #1219212e}.settings-header{border-bottom:1px solid var(--line);grid-column:1/-1;justify-content:space-between;align-items:flex-start;padding:22px;display:flex}.eyebrow{color:#9099a4;letter-spacing:.08em;text-transform:uppercase;margin:0 0 5px;font-size:10px;font-weight:700}.settings-header h2{margin:0;font-size:20px}.settings-nav{border-right:1px solid var(--line);background:#f7f8fa;padding:16px 10px}.settings-nav-item{color:#707a86;text-align:left;background:0 0;border-radius:5px;width:100%;padding:9px 10px;font-size:12px}.settings-nav-item.is-selected,.settings-nav-item:hover{color:var(--ink);background:#e8ecf2;font-weight:600}.settings-content{padding:16px 22px;overflow:auto}.setting-row{border-bottom:1px solid var(--line);justify-content:space-between;align-items:center;gap:24px;padding:18px 0;display:flex}.setting-row>div:first-child{gap:5px;display:grid}.setting-row strong{font-size:13px}.setting-row span{color:var(--muted);font-size:11px}.setting-row code{color:#536273;background:#f1f3f5;border-radius:4px;padding:5px 7px;font-size:11px}.theme-options{gap:4px;display:flex!important}.theme-option{color:#78828e;background:#f3f5f7;border-radius:5px;align-items:center;gap:5px;padding:7px 8px;font-size:11px;display:inline-flex}.theme-option.is-selected{color:#254aab;background:#e7edff}@media (width<=800px){.app-shell,.app-shell.sidebar-collapsed{grid-template-columns:1fr}.sidebar{z-index:5;width:264px;transition:transform .18s;position:fixed;inset:0 auto 0 0;transform:translate(-101%);box-shadow:8px 0 24px #191f2614}.app-shell:not(.sidebar-collapsed) .sidebar{transform:translate(0)}.app-shell:not(.sidebar-collapsed):after{content:"";z-index:4;background:#191f262e;position:fixed;inset:0}.workspace-bar{padding:0 14px}.workspace-bar>.icon-button{display:inline-grid}.bar-actions .bar-action{display:none}.empty-state{transform:translateY(-4vh)}.composer-wrap{width:calc(100% - 24px);margin-bottom:14px}}@media (width<=480px){.workspace-bar{height:52px}.main-content{min-height:calc(100vh - 52px)}.empty-state{width:calc(100% - 32px)}.empty-state h1{font-size:22px}.empty-state p{font-size:13px}.composer textarea{min-height:52px}.settings-panel{grid-template-columns:1fr;max-height:calc(100vh - 24px)}.settings-nav{border-right:0;border-bottom:1px solid var(--line);gap:4px;display:flex;overflow-x:auto}.settings-nav-item{white-space:nowrap;width:auto}.settings-content{padding:8px 18px 18px}.setting-row{flex-direction:column;align-items:flex-start;gap:12px}.theme-options{flex-wrap:wrap}}@media (prefers-reduced-motion:reduce){*,:before,:after{scroll-behavior:auto!important;transition-duration:.01ms!important;animation-duration:.01ms!important;animation-iteration-count:1!important}}@media (prefers-color-scheme:dark){:root{color:#e7ebf0;--ink:#e7ebf0;--muted:#9ca6b2;--line:#303842;--sidebar:#20262d;--surface:#242b33;--accent-soft:#283a6e;background:#1b2026}body{background:#1b2026}.workspace-bar{background:#1c2229e6}.mark,.new-session{background:#10161c}.session-search{background:#2b323a}.composer,.settings-panel{background:#242b33;border-color:#3a434e}.settings-nav{background:#20262d;border-color:#303842}.setting-row code,.theme-option{background:#303842}.empty-icon{color:#c5cfda;background:#303842;border-color:#3b4550}}[data-theme=light]{--lightningcss-light:initial;--lightningcss-dark: ;color-scheme:light}[data-theme=light] body{background:#f7f8fa}[data-theme=dark]{--lightningcss-light: ;--lightningcss-dark:initial;color-scheme:dark;--ink:#e7ebf0;--muted:#9ca6b2;--line:#303842;--sidebar:#20262d;--surface:#242b33;--accent-soft:#283a6e;background:#1b2026}[data-theme=dark] body{background:#1b2026}[data-theme=dark] .workspace-bar{background:#1c2229e6}[data-theme=dark] .sidebar{border-color:#303842}[data-theme=dark] .mark,[data-theme=dark] .new-session{background:#10161c}[data-theme=dark] .session-search{background:#2b323a}[data-theme=dark] .composer,[data-theme=dark] .settings-panel{background:#242b33;border-color:#3a434e}[data-theme=dark] .settings-nav{background:#20262d;border-color:#303842}[data-theme=dark] .setting-row code,[data-theme=dark] .theme-option{background:#303842}[data-theme=dark] .empty-icon{color:#c5cfda;background:#303842;border-color:#3b4550}.web-slot-sidebar,.web-slot-session-tree,.web-slot-settings{gap:6px;margin:8px 0;display:grid}.web-contribution-slot{max-width:100%;display:inline-flex}.web-contribution-badge,.web-contribution-tool{color:var(--muted);font-size:11px}.web-contribution-link{color:var(--accent);text-align:left;background:0 0;font-size:11px}.web-contribution-node{color:var(--muted);background:var(--surface);border-left:2px solid var(--accent);margin:6px 0;padding:6px 8px;font-size:11px}.app-shell.is-hero .main-column{background:var(--surface)}.app-shell.is-hero .main-content{overflow:hidden}.app-shell.is-hero .runtime-controls{display:none}.app-shell.is-hero .composer-wrap{margin:0 auto}.main-content.is-hero{justify-content:center}.main-content.is-hero .empty-state{margin:0 auto 18px;transform:none}.empty-brand{color:var(--ink);align-items:center;gap:8px;margin-bottom:18px;font-size:24px;font-weight:650;display:inline-flex}.empty-brand svg{color:#202936}.empty-brand small{color:#4770ba;background:#eaf0ff;border-radius:5px;padding:3px 6px;font-size:10px;font-weight:600}.hero-picker-row{justify-content:center;gap:18px;margin-top:30px;display:flex}.hero-picker{color:#596574;background:0 0;align-items:center;gap:6px;padding:5px 4px;font-size:12px;display:inline-flex}.hero-picker:hover{color:var(--ink)}.composer-hero{width:min(780px,100% - 40px);margin:0 auto}.composer-hero .composer{box-shadow:0 8px 32px #3657a01f}.composer-hero .composer-toolbar{padding-bottom:11px}.composer-hero textarea{min-height:68px;font-size:15px}.access-mode{color:#6e7783;background:0 0;border-radius:5px;align-items:center;gap:5px;padding:6px 7px;font-size:11px;display:inline-flex}.access-mode:hover,.model-select:hover,.context-meter:hover{color:var(--ink);background:#f0f2f4}.context-meter{color:#737e8a;background:0 0;border-radius:5px;min-width:31px;padding:6px;font-size:11px}.composer-menu-anchor{display:inline-flex;position:relative}.composer-menu{z-index:8;min-width:188px;color:var(--ink);background:var(--surface);border:1px solid var(--line);border-radius:7px;gap:2px;padding:6px;display:grid;position:absolute;bottom:calc(100% + 8px);left:0;box-shadow:0 10px 28px #17202b24}.composer-menu-right{left:auto;right:0}.composer-menu button{width:100%;color:inherit;text-align:left;background:0 0;border-radius:4px;align-items:center;gap:8px;padding:8px;font-size:12px;display:flex}.composer-menu button:hover{background:#f0f2f4}.composer-command-menu button.is-selected{background:#e8ecf2}.composer-menu button:disabled{cursor:not-allowed;opacity:.48}.composer-command-menu{min-width:236px;max-height:min(380px,100vh - 140px);overflow-y:auto}.composer-command-menu .menu-item-copy strong{color:var(--ink);font-size:12px;font-weight:600}.composer-menu p,.composer-menu span,.composer-menu strong{margin:2px 4px;font-size:11px;line-height:1.45}.composer-menu p,.composer-menu span{color:var(--muted)}.menu-item-copy{flex:1;gap:1px;display:grid;color:var(--ink)!important;font-size:12px!important}.menu-item-copy small{color:var(--muted);font-size:10px}.menu-item-skill small{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.composer-model-menu{max-height:min(380px,100vh - 140px);overflow-y:auto}.composer-model-menu .menu-back{border-bottom:1px solid var(--line);border-radius:0;margin-bottom:4px}.model-group+.model-group{border-top:1px solid var(--line);margin-top:4px;padding-top:4px}.composer-menu .model-group>p{color:var(--muted);letter-spacing:.04em;text-transform:uppercase;margin:5px 8px 3px;font-size:10px;font-weight:700}.composer-menu .model-group button{justify-content:space-between}.composer-menu .model-group button[aria-checked=true]{color:#254aab;background:#eaf0ff}.composer-session-meta{min-height:34px;color:var(--muted);border-top:1px solid var(--line);align-items:center;gap:8px;padding:5px 12px 6px;font-size:11px;display:flex}.composer-session-meta>span:not(.composer-spacer){align-items:center;gap:4px;display:inline-flex}.composer-session-meta>span:not(.composer-spacer)+span:not(.composer-spacer){border-left:1px solid var(--line);padding-left:8px}.composer-session-meta button{color:#55616e;background:#edf0f3;border-radius:5px;align-items:center;gap:5px;padding:5px 7px;font-size:11px;display:inline-flex}.composer-session-meta button:hover{color:var(--ink);background:#e5e9ed}.composer-runtime-error{color:#9b453e}.context-menu{min-width:174px}.bar-session-title{text-overflow:ellipsis;white-space:nowrap;max-width:min(38vw,280px);overflow:hidden}.bar-mode{color:var(--muted);align-items:center;gap:6px;font-size:12px;font-weight:400;display:inline-flex}.session-log{border:1px solid var(--line);border-radius:999px;padding-inline:12px}.session-log-panel{background:var(--surface);border:1px solid var(--line);border-radius:8px;width:min(430px,100%);padding:22px;box-shadow:0 16px 50px #1219212e}.session-log-panel header{border-bottom:1px solid var(--line);justify-content:space-between;align-items:flex-start;padding-bottom:16px;display:flex}.session-log-panel h2{margin:0;font-size:19px}.session-log-panel dl{grid-template-columns:repeat(2,minmax(0,1fr));gap:12px;margin:18px 0 0;display:grid}.session-log-panel dl div{background:#f4f6f8;border-radius:6px;padding:10px}.session-log-panel dt{color:var(--muted);font-size:11px}.session-log-panel dd{color:var(--ink);margin:4px 0 0;font-size:15px;font-weight:650}.conversation-tabs{margin-top:0;padding-top:10px}.main-content:not(.is-hero){background:var(--surface)}.main-content:not(.is-hero) .composer-wrap{z-index:3;background:linear-gradient(to bottom, transparent, var(--surface) 24px);margin-bottom:0;padding-top:24px;position:sticky;bottom:0}.main-content:not(.is-hero) .composer-note{padding-bottom:10px}.streaming-status{min-height:18px;color:var(--muted);align-items:center;gap:8px;font-size:12px;display:inline-flex}.turn-status{width:min(760px,100% - 40px);color:var(--muted);align-items:center;gap:8px;margin:0 auto 8px;font-size:12px;display:inline-flex}.compaction-status{width:min(760px,100% - 40px);color:var(--muted);align-items:center;gap:7px;margin:12px auto 8px;font-size:12px;display:flex}.streaming-dots{gap:3px;display:inline-flex}.streaming-dots i{background:currentColor;border-radius:50%;width:4px;height:4px;animation:1.1s ease-in-out infinite dot-bounce}.streaming-dots i:nth-child(2){animation-delay:.15s}.streaming-dots i:nth-child(3){animation-delay:.3s}@keyframes dot-bounce{0%,60%,to{opacity:.35;transform:translateY(0)}30%{opacity:1;transform:translateY(-3px)}}.message{animation:.18s ease-out both message-in}@keyframes message-in{0%{opacity:0;transform:translateY(5px)}to{opacity:1;transform:translateY(0)}}.message-actions{color:#9099a4;align-items:center;gap:4px;min-height:24px;display:flex}.message-actions button{width:26px;height:26px;color:inherit;background:0 0;border-radius:5px;place-items:center;display:inline-grid}.message-actions button:hover{color:var(--ink);background:#eef1f4}.message-complete{color:#6a7888;align-items:center;gap:4px;margin-left:5px;font-size:10px;display:inline-flex}.conversation-skeleton{gap:14px;width:min(760px,100% - 40px);margin:48px auto;display:grid}.skeleton-line,.skeleton-block{background:linear-gradient(90deg,#edf0f3 25%,#f7f8fa 50%,#edf0f3 75%) 0 0/200% 100%;border-radius:5px;animation:1.4s ease-in-out infinite skeleton-shimmer}.skeleton-line{height:12px}.skeleton-line-short{width:30%}.skeleton-line-medium{width:52%}.skeleton-line-long{width:70%}.skeleton-block{width:100%;height:92px}@keyframes skeleton-shimmer{0%{background-position:200% 0}to{background-position:-200% 0}}.session-tree{min-width:0;overflow-x:hidden}.session-item-wrap{min-width:0}.session-item-actions,.session-item>svg{flex:none}.session-item span{flex:1;min-width:0}.activity-timeline{color:#788390;gap:4px;min-width:0;font-size:12px;display:grid}.activity-timeline-live{min-height:22px}.activity-row,.activity-row summary{grid-template-columns:16px auto auto minmax(0,1fr) auto;align-items:center;column-gap:6px;min-width:0;display:grid}.activity-row{min-height:22px}.activity-row summary{cursor:pointer;list-style:none}.activity-row summary::-webkit-details-marker{display:none}.activity-row strong{color:#687482;font-size:12px;font-weight:500}.activity-icon{color:#8a96a2;place-items:center;display:inline-grid}.activity-separator{color:#b1b8c0}.activity-summary{text-overflow:ellipsis;white-space:nowrap;min-width:0;overflow:hidden}.activity-status{color:#579178;place-items:center;display:inline-grid}.activity-loading .activity-status{color:#647cbb}.activity-error .activity-status,.activity-cancelled .activity-status,.activity-timeout .activity-status{color:#a4514a}.activity-thinking{display:block}.activity-thinking[open]{padding:5px 0 2px}.activity-thinking pre{max-height:220px;color:var(--ink);white-space:pre-wrap;overflow-wrap:anywhere;background:#f4f6f8;border-left:2px solid #d9dfe5;margin:6px 0 0 22px;padding:8px 10px;font:12px/1.55 ui-monospace,SFMono-Regular,Consolas,monospace;overflow:auto}.activity-row-live{animation:.22s ease-out both activity-in}@keyframes activity-in{0%{opacity:.35;transform:translateY(2px)}to{opacity:1;transform:translateY(0)}}@media (prefers-color-scheme:dark){.activity-row strong{color:#bdc5cf}.activity-icon{color:#a5afbb}.activity-separator{color:#737e8a}.activity-thinking pre{background:#20262d;border-left-color:#3e4854}}[data-theme=dark] .activity-row strong{color:#bdc5cf}[data-theme=dark] .activity-icon{color:#a5afbb}[data-theme=dark] .activity-separator{color:#737e8a}[data-theme=dark] .activity-thinking pre{background:#20262d;border-left-color:#3e4854}@media (width<=800px){.main-content.is-hero{padding-bottom:12vh}.composer-hero{width:calc(100% - 24px)}.hero-picker-row{gap:10px;margin-top:22px}.empty-brand{font-size:20px}.main-content:not(.is-hero) .composer-wrap{padding-top:16px}.composer-menu{min-width:0;position:fixed;bottom:82px;left:12px;right:12px}.composer-menu-right{left:12px;right:12px}.composer-session-meta{flex-wrap:wrap;gap:6px;padding-inline:10px}.composer-session-meta .composer-spacer{display:none}}.settings-panel{grid-template-rows:auto minmax(0,1fr);height:min(700px,100dvh - 48px);max-height:min(700px,100dvh - 48px)}.settings-nav,.settings-content{min-height:0;overflow-y:auto}.toast{z-index:20;border:1px solid var(--line);border-radius:6px;align-items:flex-start;gap:10px;width:min(420px,100% - 32px);padding:10px 12px;font-size:12px;line-height:1.45;display:flex;position:fixed;bottom:24px;right:24px;box-shadow:0 12px 28px #12192129}.toast-error{color:#8d3d37;background:#fff4f2;border-color:#efcdc8}.toast span{overflow-wrap:anywhere;flex:1}.toast button{color:currentColor;background:0 0;border-radius:4px;flex:none;place-items:center;width:24px;height:24px;margin:-4px -5px -4px 0;display:inline-grid}.toast button:hover{background:#8d3d371a}.tree-overlay{z-index:14}.tree-dialog{width:min(760px,100%);max-height:min(680px,100dvh - 48px);color:var(--ink);background:var(--surface);border:1px solid var(--line);border-radius:8px;grid-template-rows:auto minmax(0,1fr) auto;display:grid;overflow:hidden;box-shadow:0 16px 50px #1219212e}.tree-dialog-header,.tree-dialog-footer{border-bottom:1px solid var(--line);justify-content:space-between;align-items:center;gap:12px;padding:16px 18px;display:flex}.tree-dialog-header h2{margin:0;font-size:16px}.tree-dialog-header .eyebrow{margin-bottom:3px}.tree-dialog-footer{border-top:1px solid var(--line);color:var(--muted);border-bottom:0;font-size:11px}.tree-dialog-list{min-height:160px;padding:8px;overflow:auto}.tree-dialog-node{width:100%;min-height:42px;color:var(--ink);text-align:left;background:0 0;border-radius:5px;grid-template-columns:auto 16px minmax(0,1fr);align-items:center;gap:7px;padding:6px 8px;display:grid}.tree-dialog-node:hover:not(:disabled),.tree-dialog-node.is-selected{background:#edf1f5}.tree-dialog-node:disabled{cursor:not-allowed;opacity:.54}.tree-dialog-branch{color:#a4adb7;white-space:pre;align-items:center;font:11px/1 ui-monospace,SFMono-Regular,Consolas,monospace;display:inline-flex}.tree-dialog-branch i{text-align:center;width:13px;font-style:normal;display:inline-block}.tree-dialog-branch b{font-weight:400}.tree-dialog-copy{gap:2px;min-width:0;display:grid}.tree-dialog-copy strong{color:#697582;font-size:10px;font-weight:650}.tree-dialog-copy span{color:var(--ink);text-overflow:ellipsis;white-space:nowrap;font-size:12px;line-height:1.3;overflow:hidden}.tree-dialog-icon{color:#788390}.tree-dialog-you{color:#397eaa}.tree-dialog-assistant{color:#4b8f68}.tree-dialog-tool{color:#8d7b50}.tree-dialog-empty{color:var(--muted);margin:14px 10px;font-size:12px}.tree-continue{color:#fff;background:#25303c;border-radius:5px;align-items:center;gap:6px;padding:7px 9px;font-size:12px;display:inline-flex}.tree-continue:disabled{color:#aeb6c0;background:#e4e7ea}@media (width<=480px){.settings-panel{height:calc(100dvh - 24px);max-height:calc(100dvh - 24px)}.settings-nav{overflow:auto hidden}.toast{bottom:16px;right:16px}}.settings-section h3{margin:0 0 6px;font-size:16px}.settings-section-note{color:var(--muted);margin:0 0 12px;font-size:11px;line-height:1.45}.setting-row small{color:var(--muted);margin-top:4px;font-size:11px;display:block}.setting-row select,.model-controls select,.onboarding-panel select,.onboarding-panel input,.login-row input{min-width:150px;color:var(--ink);background:var(--surface);border:1px solid var(--line);border-radius:5px;padding:7px 9px}.provider-list{gap:7px;display:grid}.provider-card{border:1px solid var(--line);border-radius:6px;align-items:center;gap:10px;padding:10px;display:flex}.provider-card.is-selected{background:var(--accent-soft);border-color:#7d9aee}.provider-card-main{color:var(--ink);text-align:left;background:0 0;flex:1;gap:3px;display:grid}.provider-card-main span,.provider-status,.readonly-note{color:var(--muted);font-size:11px}.status-settings{color:#3d6ca4}.status-environment{color:#5f6f61}.status-missing{color:#8c6c58}.model-controls{gap:12px;margin-top:14px;display:grid}.model-controls label,.onboarding-panel label{color:var(--muted);gap:6px;font-size:11px;display:grid}.login-row{flex-wrap:wrap;gap:7px;display:flex}.login-row button,.onboarding-panel button{color:#fff;background:#25303c;border-radius:5px;padding:8px 12px}.button-quiet{color:var(--ink)!important;background:#e9edf1!important}.settings-error{color:#90534f;background:#fff3f1;border:1px solid #f1d6d1;border-radius:5px;margin-bottom:10px;padding:8px 10px;font-size:11px}.settings-loading{color:var(--muted);font-size:12px}.onboarding-panel{background:var(--surface);border:1px solid var(--line);border-radius:8px;gap:12px;width:min(420px,100%);padding:24px;display:grid;box-shadow:0 16px 50px #1219212e}.onboarding-panel h2{margin:0;font-size:20px}.onboarding-panel p{color:var(--muted);margin:0;font-size:12px;line-height:1.45}.advanced-list{gap:6px;display:grid}.advanced-row{border-bottom:1px solid var(--line);justify-content:space-between;align-items:center;gap:10px;padding:10px 0;display:flex}.advanced-row>div:first-child{gap:4px;min-width:0;display:grid}.advanced-row strong{overflow-wrap:anywhere;font-size:12px}.advanced-row span{color:var(--muted);overflow-wrap:anywhere;font-size:11px}.advanced-meta,.advanced-actions{flex-wrap:wrap;justify-content:flex-end;align-items:center;gap:6px;display:flex}.advanced-meta code{color:#536273;background:#f1f3f5;border-radius:4px;padding:3px 5px;font-size:10px}.advanced-actions button,.inline-form button,.trust-toggle{color:var(--ink);border:1px solid var(--line);background:#edf0f3;border-radius:4px;padding:6px 8px;font-size:11px}.inline-form{flex-wrap:wrap;gap:6px;margin-top:14px;display:flex}.inline-form input,.inline-form select{min-width:0;color:var(--ink);background:var(--surface);border:1px solid var(--line);border-radius:5px;flex:1;padding:7px 8px;font-size:11px}.switch{color:var(--muted);white-space:nowrap;align-items:center;gap:6px;font-size:11px;display:inline-flex}.switch input{accent-color:var(--accent)}.trust-impact{background:var(--accent-soft);border:1px solid #cad6fa;border-radius:6px;gap:6px;margin:14px 0;padding:12px;display:grid}.trust-impact strong{font-size:13px}.trust-impact span,.trust-impact small{color:var(--muted);font-size:11px;line-height:1.4}.shortcut-list{color:var(--muted);gap:10px;font-size:12px;display:grid}.shortcut-list kbd{text-align:center;min-width:76px;color:var(--ink);border:1px solid var(--line);background:#edf0f3;border-bottom-width:2px;border-radius:4px;margin-right:8px;padding:4px 6px;font:11px ui-monospace,monospace;display:inline-block}.provider-selector{grid-template-columns:repeat(2,minmax(0,1fr));gap:8px;display:grid}.provider-choice{min-width:0;color:var(--ink);background:var(--surface);border:1px solid var(--line);text-align:left;border-radius:6px;grid-template-columns:minmax(0,1fr) auto auto;align-items:center;gap:8px;padding:10px;display:grid}.provider-choice:hover{background:#f7f9fc;border-color:#b9c7df}.provider-choice.is-selected{background:var(--accent-soft);border-color:#6f8ee0}.provider-choice>span{gap:2px;min-width:0;display:grid}.provider-choice strong,.provider-choice small{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.provider-choice strong{font-size:12px}.provider-choice small{color:var(--muted);font-size:10px}.provider-choice em{white-space:nowrap;font-size:10px;font-style:normal}.provider-choice-custom{border-style:dashed;grid-column:span 2}.model-controls,.custom-provider-form{border-top:1px solid var(--line);gap:12px;margin-top:16px;padding-top:16px;display:grid}.model-controls h4,.custom-provider-heading h4{color:var(--ink);margin:0;font-size:13px}.custom-provider-heading{justify-content:space-between;align-items:center;gap:12px;display:flex}.custom-provider-heading>div{gap:3px;display:grid}.custom-provider-heading p{color:var(--muted);margin:0;font-size:11px}.custom-provider-grid{grid-template-columns:repeat(2,minmax(0,1fr));gap:10px;display:grid}.custom-provider-grid label{min-width:0;color:var(--muted);gap:5px;font-size:11px;display:grid}.custom-provider-grid input,.custom-provider-grid select{width:100%;min-width:0;color:var(--ink);background:var(--surface);border:1px solid var(--line);border-radius:5px;padding:8px 9px}.custom-provider-wide{grid-column:1/-1}.custom-save{color:#fff;background:#25303c;border-radius:5px;justify-self:start;padding:8px 10px;font-size:12px}.custom-save:disabled{cursor:not-allowed;opacity:.48}.masked-key::placeholder{color:var(--ink);opacity:.72}.masked-key-indicator{color:var(--ink)}@media (width<=480px){.provider-selector,.custom-provider-grid{grid-template-columns:1fr}.provider-choice-custom,.custom-provider-wide{grid-column:auto}}
|