@agent-api/app-engine 0.0.1

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.
Files changed (62) hide show
  1. package/README.md +46 -0
  2. package/dist/agent/runner.d.ts +117 -0
  3. package/dist/agent/runner.js +486 -0
  4. package/dist/agent.d.ts +2 -0
  5. package/dist/agent.js +2 -0
  6. package/dist/chat-options.d.ts +37 -0
  7. package/dist/chat-options.js +42 -0
  8. package/dist/config.d.ts +66 -0
  9. package/dist/config.js +201 -0
  10. package/dist/conversation/index.d.ts +17 -0
  11. package/dist/conversation/index.js +54 -0
  12. package/dist/engine/agent-engine.d.ts +38 -0
  13. package/dist/engine/agent-engine.js +146 -0
  14. package/dist/engine/index.d.ts +50 -0
  15. package/dist/engine/index.js +26 -0
  16. package/dist/engine/services.d.ts +20 -0
  17. package/dist/engine/services.js +1 -0
  18. package/dist/index.d.ts +1 -0
  19. package/dist/index.js +1 -0
  20. package/dist/profile.d.ts +57 -0
  21. package/dist/profile.js +211 -0
  22. package/dist/runtime/index.d.ts +23 -0
  23. package/dist/runtime/index.js +177 -0
  24. package/dist/update.d.ts +16 -0
  25. package/dist/update.js +74 -0
  26. package/dist/workbench/auth-controller.d.ts +43 -0
  27. package/dist/workbench/auth-controller.js +84 -0
  28. package/dist/workbench/auth-gate-controller.d.ts +62 -0
  29. package/dist/workbench/auth-gate-controller.js +231 -0
  30. package/dist/workbench/command-controller.d.ts +29 -0
  31. package/dist/workbench/command-controller.js +426 -0
  32. package/dist/workbench/conversation-controller.d.ts +32 -0
  33. package/dist/workbench/conversation-controller.js +53 -0
  34. package/dist/workbench/engine.d.ts +66 -0
  35. package/dist/workbench/engine.js +291 -0
  36. package/dist/workbench/input-controller.d.ts +44 -0
  37. package/dist/workbench/input-controller.js +71 -0
  38. package/dist/workbench/isolator-installer.d.ts +29 -0
  39. package/dist/workbench/isolator-installer.js +208 -0
  40. package/dist/workbench/lifecycle-controller.d.ts +30 -0
  41. package/dist/workbench/lifecycle-controller.js +75 -0
  42. package/dist/workbench/local-controller.d.ts +21 -0
  43. package/dist/workbench/local-controller.js +94 -0
  44. package/dist/workbench/render-model.d.ts +46 -0
  45. package/dist/workbench/render-model.js +61 -0
  46. package/dist/workbench/runtime-controller.d.ts +12 -0
  47. package/dist/workbench/runtime-controller.js +57 -0
  48. package/dist/workbench/session.d.ts +29 -0
  49. package/dist/workbench/session.js +42 -0
  50. package/dist/workbench/settings-controller.d.ts +80 -0
  51. package/dist/workbench/settings-controller.js +309 -0
  52. package/dist/workbench/shell-isolation.d.ts +20 -0
  53. package/dist/workbench/shell-isolation.js +13 -0
  54. package/dist/workbench/state.d.ts +187 -0
  55. package/dist/workbench/state.js +392 -0
  56. package/dist/workbench/turn-controller.d.ts +25 -0
  57. package/dist/workbench/turn-controller.js +164 -0
  58. package/dist/workbench/view-model.d.ts +34 -0
  59. package/dist/workbench/view-model.js +121 -0
  60. package/dist/workdir/index.d.ts +22 -0
  61. package/dist/workdir/index.js +46 -0
  62. package/package.json +50 -0
@@ -0,0 +1,75 @@
1
+ import { checkForUpdate, formatUpdateNotice } from "../update.js";
2
+ export function createWorkbenchLifecycleController(options) {
3
+ const checkForUpdateImpl = options.checkForUpdateImpl ?? checkForUpdate;
4
+ const formatUpdateNoticeImpl = options.formatUpdateNoticeImpl ?? formatUpdateNotice;
5
+ const formatError = options.formatError ?? userFacingError;
6
+ const refreshWindowMs = options.refreshWindowMs ?? 5 * 60_000;
7
+ const updateCheckEnabled = options.updateCheckEnabled ?? process.env.AGENT_TUI_UPDATE_CHECK !== "0";
8
+ let updateNoticeShown = false;
9
+ let authRefreshWarningShown = false;
10
+ let initialPromptSubmitted = false;
11
+ return {
12
+ async maybeCheckForUpdate() {
13
+ if (updateNoticeShown || !updateCheckEnabled)
14
+ return [];
15
+ updateNoticeShown = true;
16
+ try {
17
+ const result = await checkForUpdateImpl();
18
+ return updateNoticeEffects(result, formatUpdateNoticeImpl);
19
+ }
20
+ catch {
21
+ return [];
22
+ }
23
+ },
24
+ async refreshAuth(profile) {
25
+ try {
26
+ const result = await options.authController.refresh(profile, refreshWindowMs);
27
+ if (!result.refreshed)
28
+ return [];
29
+ authRefreshWarningShown = false;
30
+ return [
31
+ { type: "dispatch", action: { type: "activity.add", level: "success", text: "Auth session refreshed" } },
32
+ ];
33
+ }
34
+ catch (error) {
35
+ if (authRefreshWarningShown)
36
+ return [];
37
+ authRefreshWarningShown = true;
38
+ return [
39
+ {
40
+ type: "dispatch",
41
+ action: {
42
+ type: "message.add",
43
+ role: "system",
44
+ text: `${formatError(error)}\n\nClosing the workbench because authenticated agent conversations are unavailable.`,
45
+ },
46
+ },
47
+ { type: "dispatch", action: { type: "activity.add", level: "error", text: "Auth session needs login; closing" } },
48
+ { type: "close", delayMs: 1500 },
49
+ ];
50
+ }
51
+ },
52
+ initialPrompt(input) {
53
+ if (initialPromptSubmitted || input.busy || (input.requiresWorkdir && !input.workdir))
54
+ return undefined;
55
+ const prompt = input.promptParts.join(" ").trim();
56
+ if (!prompt)
57
+ return undefined;
58
+ initialPromptSubmitted = true;
59
+ return prompt;
60
+ },
61
+ };
62
+ }
63
+ export function updateNoticeEffects(result, formatNotice = formatUpdateNotice) {
64
+ if (!result?.updateAvailable)
65
+ return [];
66
+ return [
67
+ { type: "dispatch", action: { type: "activity.add", level: "warning", text: `Update available: ${result.latest}` } },
68
+ { type: "dispatch", action: { type: "message.add", role: "system", text: formatNotice(result) } },
69
+ ];
70
+ }
71
+ function userFacingError(error) {
72
+ if (error instanceof Error)
73
+ return error.message;
74
+ return String(error);
75
+ }
@@ -0,0 +1,21 @@
1
+ import { openWorkdir } from "../workdir/index.js";
2
+ import type { WorkbenchState, WorkbenchWorkdirStatus } from "./state.js";
3
+ import type { ShellIsolationPreferences } from "./shell-isolation.js";
4
+ export interface WorkbenchLocalController {
5
+ load(path?: string): Promise<WorkbenchWorkdirStatus>;
6
+ isLoaded(): boolean;
7
+ summaryText(): Promise<string>;
8
+ searchText(query: string): Promise<{
9
+ text: string;
10
+ count: number;
11
+ }>;
12
+ approvalPreview(approval: LocalApprovalLike): string;
13
+ applyApproval(approval: LocalApprovalLike): Promise<string | Record<string, unknown>>;
14
+ }
15
+ export interface WorkbenchLocalControllerOptions {
16
+ openWorkdirImpl?: typeof openWorkdir;
17
+ getShellIsolation?: () => ShellIsolationPreferences | undefined;
18
+ }
19
+ type LocalApprovalLike = NonNullable<WorkbenchState["pendingLocalTool"]>;
20
+ export declare function createWorkbenchLocalController(options?: WorkbenchLocalControllerOptions): WorkbenchLocalController;
21
+ export {};
@@ -0,0 +1,94 @@
1
+ import { createLocalShellToolRegistry, createLocalWorkdirToolRegistry } from "@agent-api/sdk/local";
2
+ import { openWorkdir } from "../workdir/index.js";
3
+ import { localShellIsolationOptions } from "./shell-isolation.js";
4
+ export function createWorkbenchLocalController(options = {}) {
5
+ const openWorkdirImpl = options.openWorkdirImpl ?? openWorkdir;
6
+ let workdir = null;
7
+ return {
8
+ async load(path) {
9
+ const next = await openWorkdirImpl({ path });
10
+ const summary = await next.summarize();
11
+ workdir = next;
12
+ return {
13
+ root: next.root,
14
+ name: next.name,
15
+ fileCount: summary.file_count,
16
+ totalBytes: summary.total_bytes,
17
+ scanTruncated: summary.scan_truncated,
18
+ };
19
+ },
20
+ isLoaded() {
21
+ return Boolean(workdir);
22
+ },
23
+ async summaryText() {
24
+ const current = requireWorkdir();
25
+ const summary = await current.summarize();
26
+ const previews = summary.text_previews
27
+ .slice(0, 5)
28
+ .map((preview) => `- ${preview.path} (${formatBytes(preview.size)})`)
29
+ .join("\n");
30
+ return [
31
+ `Workdir summary for ${current.name}`,
32
+ `Files: ${summary.file_count}`,
33
+ `Size: ${formatBytes(summary.total_bytes)}`,
34
+ previews ? `Previews:\n${previews}` : "No text previews available.",
35
+ ].join("\n");
36
+ },
37
+ async searchText(query) {
38
+ const trimmed = query.trim();
39
+ if (!trimmed) {
40
+ return { text: "Usage: /search <query>", count: 0 };
41
+ }
42
+ const current = requireWorkdir();
43
+ const results = await current.workdir.grep({ pattern: trimmed, limit: 12 });
44
+ const matches = results.matches
45
+ .map((match) => `${match.path}:${match.line_number}: ${match.line.trim()}`)
46
+ .join("\n");
47
+ return {
48
+ text: matches || `No matches for "${trimmed}".`,
49
+ count: results.matches.length,
50
+ };
51
+ },
52
+ approvalPreview(approval) {
53
+ return formatLocalToolApproval(approval);
54
+ },
55
+ async applyApproval(approval) {
56
+ const current = requireWorkdir();
57
+ const workdirRegistry = createLocalWorkdirToolRegistry(current.workdir, { accessMode: "full" });
58
+ const shellRegistry = createLocalShellToolRegistry({
59
+ workdir: current.workdir,
60
+ accessMode: "full",
61
+ ...localShellIsolationOptions(options.getShellIsolation?.()),
62
+ });
63
+ if (approval.name === workdirRegistry.toolName) {
64
+ return await workdirRegistry.execute(approval.name, approval.arguments);
65
+ }
66
+ if (approval.name === shellRegistry.toolName) {
67
+ return await shellRegistry.execute(approval.name, approval.arguments);
68
+ }
69
+ throw new Error(`no local handler registered for function ${approval.name}`);
70
+ },
71
+ };
72
+ function requireWorkdir() {
73
+ if (!workdir)
74
+ throw new Error("Workdir is still loading.");
75
+ return workdir;
76
+ }
77
+ }
78
+ function formatLocalToolApproval(approval) {
79
+ return [
80
+ `Local approval requested: ${approval.name}${approval.action ? `.${approval.action}` : ""}`,
81
+ "Arguments:",
82
+ JSON.stringify(approval.arguments, null, 2),
83
+ approval.preview ? ["Preview:", JSON.stringify(approval.preview, null, 2)].join("\n") : "",
84
+ "",
85
+ "Use /apply to execute this action once, /apply-all to allow future local actions, or /reject to discard it.",
86
+ ].filter(Boolean).join("\n");
87
+ }
88
+ function formatBytes(bytes) {
89
+ if (bytes < 1024)
90
+ return `${bytes} B`;
91
+ if (bytes < 1024 * 1024)
92
+ return `${(bytes / 1024).toFixed(1)} KB`;
93
+ return `${(bytes / 1024 / 1024).toFixed(2)} MB`;
94
+ }
@@ -0,0 +1,46 @@
1
+ import type { RenderMode, WorkbenchState } from "./state.js";
2
+ import { type TranscriptViewModel } from "./view-model.js";
3
+ export interface WorkbenchRendererViewport {
4
+ rows: number;
5
+ columns: number;
6
+ }
7
+ export interface WorkbenchRenderModel {
8
+ activityHeight: number;
9
+ footerText: string;
10
+ header: {
11
+ accessMode: string;
12
+ contextEnabled: boolean;
13
+ conversation: string;
14
+ model: string;
15
+ pendingLocalLabel: string;
16
+ preset: string;
17
+ profile: string;
18
+ renderMode: RenderMode;
19
+ workdir: string;
20
+ };
21
+ input: {
22
+ busy: boolean;
23
+ draft: string;
24
+ fullAccess: boolean;
25
+ label: string;
26
+ waitingText: string;
27
+ };
28
+ terminalColumns: number;
29
+ terminalRows: number;
30
+ transcript: TranscriptViewModel;
31
+ transcriptWidth: number;
32
+ viewportHeight: number;
33
+ visibleActivities: WorkbenchState["activities"];
34
+ }
35
+ export interface BuildWorkbenchRenderModelInput {
36
+ draft: string;
37
+ profileName: string;
38
+ spinnerFrame: number;
39
+ state: WorkbenchState;
40
+ transcriptOffset: number;
41
+ viewport: Partial<WorkbenchRendererViewport>;
42
+ workdirFallback: string;
43
+ }
44
+ export declare function buildWorkbenchRenderModel(input: BuildWorkbenchRenderModelInput): WorkbenchRenderModel;
45
+ export declare function pendingLocalLabel(state: WorkbenchState): string;
46
+ export declare function busySpinner(frame: number): string;
@@ -0,0 +1,61 @@
1
+ import { buildTranscriptViewModel, elapsedDots, spinnerGlyph, } from "./view-model.js";
2
+ export function buildWorkbenchRenderModel(input) {
3
+ const terminalRows = Math.max(18, input.viewport.rows || 32);
4
+ const terminalColumns = Math.max(80, input.viewport.columns || 100);
5
+ const viewportHeight = Math.max(6, terminalRows - 11);
6
+ const activityHeight = viewportHeight;
7
+ const transcriptWidth = Math.max(36, Math.floor(terminalColumns * 0.72) - 4);
8
+ const transcript = buildTranscriptViewModel({
9
+ activeAssistantMessageId: input.state.activeAssistantMessageId,
10
+ busy: input.state.busy,
11
+ messages: input.state.messages,
12
+ offset: input.transcriptOffset,
13
+ renderMode: input.state.renderMode,
14
+ spinnerFrame: input.spinnerFrame,
15
+ viewportHeight,
16
+ width: transcriptWidth,
17
+ });
18
+ return {
19
+ activityHeight,
20
+ footerText: [
21
+ "PgUp/PgDn scroll",
22
+ "End live",
23
+ "/export save",
24
+ "/transcript preview",
25
+ transcript.offset > 0 ? `${transcript.offset} rows from latest` : "live",
26
+ ].join(" · "),
27
+ header: {
28
+ accessMode: input.state.accessMode,
29
+ contextEnabled: input.state.contextEnabled,
30
+ conversation: input.state.currentConversation,
31
+ model: input.state.runModel || "auto",
32
+ pendingLocalLabel: pendingLocalLabel(input.state),
33
+ preset: input.state.runPreset || "none",
34
+ profile: input.profileName,
35
+ renderMode: input.state.renderMode,
36
+ workdir: input.state.workdir?.root || input.workdirFallback,
37
+ },
38
+ input: {
39
+ busy: input.state.busy,
40
+ draft: input.draft,
41
+ fullAccess: input.state.accessMode === "full",
42
+ label: input.state.busy ? "working" : "you",
43
+ waitingText: `waiting for agent ${elapsedDots(input.spinnerFrame)}`,
44
+ },
45
+ terminalColumns,
46
+ terminalRows,
47
+ transcript,
48
+ transcriptWidth,
49
+ viewportHeight,
50
+ visibleActivities: input.state.activities.slice(-Math.max(1, activityHeight - 2)),
51
+ };
52
+ }
53
+ export function pendingLocalLabel(state) {
54
+ if (state.pendingLocalTool) {
55
+ return `${state.pendingLocalTool.name}${state.pendingLocalTool.action ? `.${state.pendingLocalTool.action}` : ""}`;
56
+ }
57
+ return "none";
58
+ }
59
+ export function busySpinner(frame) {
60
+ return spinnerGlyph(frame);
61
+ }
@@ -0,0 +1,12 @@
1
+ import type { WorkbenchAction } from "./state.js";
2
+ import type { WorkbenchRuntimeEffect } from "./engine.js";
3
+ export interface WorkbenchRuntimeController {
4
+ dispose(): void;
5
+ flushTextDeltaBuffer(): void;
6
+ runEffects(effects: WorkbenchRuntimeEffect[], assistantId: string): void;
7
+ }
8
+ export interface WorkbenchRuntimeControllerOptions {
9
+ dispatch(action: WorkbenchAction): void;
10
+ flushDelayMs?: number;
11
+ }
12
+ export declare function createWorkbenchRuntimeController(options: WorkbenchRuntimeControllerOptions): WorkbenchRuntimeController;
@@ -0,0 +1,57 @@
1
+ export function createWorkbenchRuntimeController(options) {
2
+ let textDeltaBuffer = null;
3
+ let textDeltaFlushTimer = null;
4
+ const flushDelayMs = options.flushDelayMs ?? 80;
5
+ return {
6
+ dispose() {
7
+ if (textDeltaFlushTimer) {
8
+ clearTimeout(textDeltaFlushTimer);
9
+ textDeltaFlushTimer = null;
10
+ }
11
+ textDeltaBuffer = null;
12
+ },
13
+ flushTextDeltaBuffer,
14
+ runEffects(effects, assistantId) {
15
+ for (const effect of effects) {
16
+ switch (effect.type) {
17
+ case "append_text_delta":
18
+ appendTextDeltaBuffered(assistantId, effect.delta);
19
+ break;
20
+ case "set_active_response_id":
21
+ break;
22
+ case "flush_text_delta_buffer":
23
+ flushTextDeltaBuffer();
24
+ break;
25
+ }
26
+ }
27
+ },
28
+ };
29
+ function appendTextDeltaBuffered(id, delta) {
30
+ if (!delta)
31
+ return;
32
+ if (!textDeltaBuffer || textDeltaBuffer.id !== id) {
33
+ flushTextDeltaBuffer();
34
+ textDeltaBuffer = { id, text: delta };
35
+ }
36
+ else {
37
+ textDeltaBuffer.text += delta;
38
+ }
39
+ if (textDeltaFlushTimer)
40
+ return;
41
+ textDeltaFlushTimer = setTimeout(() => {
42
+ textDeltaFlushTimer = null;
43
+ flushTextDeltaBuffer();
44
+ }, flushDelayMs);
45
+ }
46
+ function flushTextDeltaBuffer() {
47
+ if (textDeltaFlushTimer) {
48
+ clearTimeout(textDeltaFlushTimer);
49
+ textDeltaFlushTimer = null;
50
+ }
51
+ if (!textDeltaBuffer || !textDeltaBuffer.text)
52
+ return;
53
+ const buffered = textDeltaBuffer;
54
+ textDeltaBuffer = null;
55
+ options.dispatch({ type: "message.append", id: buffered.id, delta: buffered.text });
56
+ }
57
+ }
@@ -0,0 +1,29 @@
1
+ import type { AgentRunOptions } from "../agent.js";
2
+ import type { AgentEngineServices } from "../engine/services.js";
3
+ import type { WorkbenchState } from "./state.js";
4
+ import type { WorkbenchAuthController } from "./auth-controller.js";
5
+ import { type WorkbenchConversationController } from "./conversation-controller.js";
6
+ import { type WorkbenchEngine } from "./engine.js";
7
+ import { type WorkbenchInputController } from "./input-controller.js";
8
+ import { type WorkbenchLifecycleController } from "./lifecycle-controller.js";
9
+ import { type WorkbenchLocalController } from "./local-controller.js";
10
+ import { type WorkbenchRuntimeController } from "./runtime-controller.js";
11
+ import { type WorkbenchSettingsController } from "./settings-controller.js";
12
+ import { type WorkbenchTurnController } from "./turn-controller.js";
13
+ export interface WorkbenchSession {
14
+ conversation: WorkbenchConversationController;
15
+ engine: WorkbenchEngine;
16
+ input: WorkbenchInputController;
17
+ lifecycle: WorkbenchLifecycleController;
18
+ local: WorkbenchLocalController;
19
+ runtime: WorkbenchRuntimeController;
20
+ settings: WorkbenchSettingsController;
21
+ turn: WorkbenchTurnController;
22
+ }
23
+ export interface WorkbenchSessionOptions {
24
+ authController: WorkbenchAuthController;
25
+ baseOptions: AgentRunOptions;
26
+ services?: Omit<AgentEngineServices, "auth">;
27
+ }
28
+ export declare function createWorkbenchSession(options: WorkbenchSessionOptions): WorkbenchSession;
29
+ export declare function sessionState(session: Pick<WorkbenchSession, "engine">): WorkbenchState;
@@ -0,0 +1,42 @@
1
+ import { createWorkbenchConversationController } from "./conversation-controller.js";
2
+ import { createWorkbenchEngine } from "./engine.js";
3
+ import { createWorkbenchInputController } from "./input-controller.js";
4
+ import { createWorkbenchLifecycleController } from "./lifecycle-controller.js";
5
+ import { createWorkbenchLocalController } from "./local-controller.js";
6
+ import { createWorkbenchRuntimeController } from "./runtime-controller.js";
7
+ import { createWorkbenchSettingsController } from "./settings-controller.js";
8
+ import { createWorkbenchTurnController } from "./turn-controller.js";
9
+ export function createWorkbenchSession(options) {
10
+ const engine = options.services?.engine ?? createWorkbenchEngine({
11
+ accessMode: options.baseOptions.accessMode,
12
+ conversation: options.baseOptions.conversation,
13
+ contextEnabled: Boolean(options.baseOptions.includeLocalContext || options.baseOptions.workdir),
14
+ model: options.baseOptions.model,
15
+ preset: options.baseOptions.preset,
16
+ });
17
+ const local = options.services?.local ?? createWorkbenchLocalController({
18
+ getShellIsolation: () => engine.snapshot().shellIsolation,
19
+ });
20
+ const runtime = options.services?.runtime ?? createWorkbenchRuntimeController({ dispatch: engine.dispatch });
21
+ const turn = options.services?.turn ?? createWorkbenchTurnController({
22
+ baseOptions: options.baseOptions,
23
+ dispatch: engine.dispatch,
24
+ engine,
25
+ flushTextDeltaBuffer: runtime.flushTextDeltaBuffer,
26
+ getState: engine.snapshot,
27
+ runRuntimeEffects: runtime.runEffects,
28
+ });
29
+ return {
30
+ conversation: options.services?.conversation ?? createWorkbenchConversationController(),
31
+ engine,
32
+ input: options.services?.input ?? createWorkbenchInputController(),
33
+ lifecycle: options.services?.lifecycle ?? createWorkbenchLifecycleController({ authController: options.authController }),
34
+ local,
35
+ runtime,
36
+ settings: options.services?.settings ?? createWorkbenchSettingsController(),
37
+ turn,
38
+ };
39
+ }
40
+ export function sessionState(session) {
41
+ return session.engine.snapshot();
42
+ }
@@ -0,0 +1,80 @@
1
+ import { clearPresetToolCatalogCache, isAvailablePreset, listAvailablePresets, type AgentRunOptions } from "../agent.js";
2
+ import { loadWorkbenchPreferences, updateWorkbenchPreferences, type WorkbenchPreferences } from "../config.js";
3
+ import type { RenderMode } from "./state.js";
4
+ import type { ShellIsolationMode, ShellIsolationPreferences } from "./shell-isolation.js";
5
+ import { type IsolatorInstallOptions } from "./isolator-installer.js";
6
+ export interface WorkbenchSettingsSnapshot {
7
+ defaultPreset?: string | null;
8
+ runPreset?: string;
9
+ shellIsolation?: ShellIsolationPreferences;
10
+ activity?: string;
11
+ notice?: string;
12
+ warning?: string;
13
+ }
14
+ export interface WorkbenchSettingsController {
15
+ loadInitial(options: Pick<AgentRunOptions, "modelExplicit" | "preset" | "presetExplicit">): Promise<WorkbenchSettingsSnapshot>;
16
+ saveDefaultPreset(input: {
17
+ value: string;
18
+ profileName?: string;
19
+ options: Pick<AgentRunOptions, "modelExplicit" | "preset" | "presetExplicit">;
20
+ }): Promise<WorkbenchSettingsSnapshot & {
21
+ message: string;
22
+ activity: string;
23
+ }>;
24
+ saveShellIsolationMode(value: string): Promise<WorkbenchSettingsSnapshot & {
25
+ message: string;
26
+ activity: string;
27
+ }>;
28
+ saveIsolatorPath(value: string): Promise<WorkbenchSettingsSnapshot & {
29
+ message: string;
30
+ activity: string;
31
+ }>;
32
+ saveIsolatorSource(value: string): Promise<WorkbenchSettingsSnapshot & {
33
+ message: string;
34
+ activity: string;
35
+ }>;
36
+ validatePreset(profileName: string | undefined, preset: string): Promise<boolean>;
37
+ presetListText(input: {
38
+ profileName?: string;
39
+ currentPreset?: string;
40
+ prefix: string;
41
+ }): Promise<string>;
42
+ configText(input: {
43
+ accessMode: string;
44
+ contextEnabled: boolean;
45
+ defaultPreset?: string | null;
46
+ profileName: string;
47
+ runModel?: string;
48
+ runPreset?: string;
49
+ renderMode: RenderMode;
50
+ shellIsolation?: ShellIsolationPreferences;
51
+ }): string;
52
+ defaultPresetHelp(defaultPreset?: string | null): string;
53
+ shellIsolationHelp(shellIsolation?: ShellIsolationPreferences): string;
54
+ isolatorPathHelp(shellIsolation?: ShellIsolationPreferences): string;
55
+ clearPresetToolCatalogCache(baseURL?: string): void;
56
+ }
57
+ export interface WorkbenchSettingsControllerOptions {
58
+ loadWorkbenchPreferencesImpl?: typeof loadWorkbenchPreferences;
59
+ updateWorkbenchPreferencesImpl?: typeof updateWorkbenchPreferences;
60
+ isAvailablePresetImpl?: typeof isAvailablePreset;
61
+ listAvailablePresetsImpl?: typeof listAvailablePresets;
62
+ clearPresetToolCatalogCacheImpl?: typeof clearPresetToolCatalogCache;
63
+ isolatorInstallOptions?: IsolatorInstallOptions;
64
+ formatError?: (error: unknown) => string;
65
+ }
66
+ export declare function createWorkbenchSettingsController(options?: WorkbenchSettingsControllerOptions): WorkbenchSettingsController;
67
+ export declare class UnknownPresetError extends Error {
68
+ readonly preset: string;
69
+ constructor(preset: string);
70
+ }
71
+ export declare function normalizeDefaultPreset(value: string): string | null | undefined;
72
+ export declare function formatDefaultPreset(value: string | null | undefined): string;
73
+ export declare function normalizeShellIsolationMode(value: string): ShellIsolationMode;
74
+ export declare function normalizeIsolatorPath(value: string): string | null;
75
+ export declare function normalizeIsolatorSource(value: string): string | null;
76
+ export declare function formatShellIsolation(value: ShellIsolationPreferences | undefined): ShellIsolationMode;
77
+ export declare function formatIsolatorPath(value: ShellIsolationPreferences | undefined): string;
78
+ export declare function formatIsolatorSource(value: ShellIsolationPreferences | undefined): string;
79
+ export declare function effectiveDefaultPreset(preferences: WorkbenchPreferences, builtInPreset?: string): string | undefined;
80
+ export declare function formatPresetList(presets: Awaited<ReturnType<typeof listAvailablePresets>>, currentPreset?: string): string[];