@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,42 @@
1
+ export function normalizeChatOptions(promptParts, options) {
2
+ const presetExplicit = options.preset !== undefined;
3
+ const modelExplicit = options.model !== undefined && options.model !== "";
4
+ const preset = presetExplicit ? options.preset : (modelExplicit ? undefined : "pro-search");
5
+ const parsedAccessMode = parseAccessMode(options.access);
6
+ const accessMode = parsedAccessMode ?? (options.workdir || options.localContext ? "approval" : undefined);
7
+ return {
8
+ profile: options.profile,
9
+ promptParts,
10
+ file: options.file,
11
+ stdin: options.stdin,
12
+ preset,
13
+ presetExplicit,
14
+ model: options.model,
15
+ modelExplicit,
16
+ stream: options.stream !== false,
17
+ conversation: options.conversation || "default",
18
+ continueConversation: true,
19
+ restartConversation: options.restart,
20
+ workdir: options.workdir,
21
+ includeLocalContext: options.localContext,
22
+ contextQuery: options.contextQuery,
23
+ maxContextFiles: optionalNumber(options.maxContextFiles, "--max-context-files"),
24
+ maxContextBytes: optionalNumber(options.maxContextBytes, "--max-context-bytes"),
25
+ accessMode,
26
+ };
27
+ }
28
+ function optionalNumber(value, label) {
29
+ if (value == null || value === "")
30
+ return undefined;
31
+ const parsed = Number(value);
32
+ if (!Number.isFinite(parsed))
33
+ throw new Error(`${label} must be a number`);
34
+ return parsed;
35
+ }
36
+ function parseAccessMode(value) {
37
+ if (!value)
38
+ return undefined;
39
+ if (value === "off" || value === "approval" || value === "full")
40
+ return value;
41
+ throw new Error("--access must be off, approval, or full");
42
+ }
@@ -0,0 +1,66 @@
1
+ import type { ShellIsolationMode, ShellIsolationPreferences } from "./workbench/shell-isolation.js";
2
+ export declare const defaultBaseURL = "https://api.agentsway.dev";
3
+ export declare const configFile = "profiles.json";
4
+ export declare const appConfigurationFile = "configuration.json";
5
+ export declare const conversationsFile = "conversations.json";
6
+ export type AuthProfile = {
7
+ type: "api_key";
8
+ apiKey: string;
9
+ } | {
10
+ type: "browser";
11
+ accessToken: string;
12
+ refreshToken: string;
13
+ accessTokenExpiresAt: number;
14
+ refreshTokenExpiresAt?: number;
15
+ };
16
+ export interface Profile {
17
+ name: string;
18
+ baseURL: string;
19
+ auth: AuthProfile;
20
+ createdAt: number;
21
+ updatedAt: number;
22
+ }
23
+ export interface CLIConfig {
24
+ activeProfile: string;
25
+ profiles: Record<string, Profile>;
26
+ }
27
+ export interface ConversationState {
28
+ name: string;
29
+ profile: string;
30
+ previousResponseId?: string;
31
+ updatedAt: number;
32
+ }
33
+ export interface WorkbenchPreferences {
34
+ defaultPreset?: string | null;
35
+ isolation?: ShellIsolationPreferences;
36
+ }
37
+ export interface AppConfiguration {
38
+ workbench: WorkbenchPreferences;
39
+ }
40
+ export interface ConversationConfiguration {
41
+ conversations: Record<string, ConversationState>;
42
+ }
43
+ export declare function loadConfig(): Promise<CLIConfig>;
44
+ export declare function saveConfig(config: CLIConfig): Promise<void>;
45
+ export declare function loadAppConfiguration(): Promise<AppConfiguration>;
46
+ export declare function saveAppConfiguration(config: AppConfiguration): Promise<void>;
47
+ export declare function loadConversationConfiguration(): Promise<ConversationConfiguration>;
48
+ export declare function saveConversationConfiguration(config: ConversationConfiguration): Promise<void>;
49
+ export declare function upsertProfile(profile: Omit<Profile, "createdAt" | "updatedAt">): Promise<Profile>;
50
+ export declare function activeProfile(profileName?: string): Promise<Profile>;
51
+ export declare function emptyConfig(): CLIConfig;
52
+ export declare function emptyAppConfiguration(): AppConfiguration;
53
+ export declare function emptyConversationConfiguration(): ConversationConfiguration;
54
+ export declare function loadWorkbenchPreferences(): Promise<WorkbenchPreferences>;
55
+ export declare function updateWorkbenchPreferences(patch: {
56
+ defaultPreset?: string | null | undefined;
57
+ isolation?: {
58
+ mode?: ShellIsolationMode | null | undefined;
59
+ executablePath?: string | null | undefined;
60
+ version?: string | null | undefined;
61
+ sourceURL?: string | null | undefined;
62
+ sha256?: string | null | undefined;
63
+ installSkipped?: boolean | null | undefined;
64
+ };
65
+ }): Promise<WorkbenchPreferences>;
66
+ export declare function redactSecret(value: string): string;
package/dist/config.js ADDED
@@ -0,0 +1,201 @@
1
+ import { z } from "zod";
2
+ import { ensureRuntime, runtime } from "./runtime/index.js";
3
+ export const defaultBaseURL = "https://api.agentsway.dev";
4
+ export const configFile = "profiles.json";
5
+ export const appConfigurationFile = "configuration.json";
6
+ export const conversationsFile = "conversations.json";
7
+ const authProfileSchema = z.discriminatedUnion("type", [
8
+ z.object({
9
+ type: z.literal("api_key"),
10
+ apiKey: z.string(),
11
+ }),
12
+ z.object({
13
+ type: z.literal("browser"),
14
+ accessToken: z.string(),
15
+ refreshToken: z.string(),
16
+ accessTokenExpiresAt: z.number(),
17
+ refreshTokenExpiresAt: z.number().optional(),
18
+ }),
19
+ ]);
20
+ const profileSchema = z.object({
21
+ name: z.string(),
22
+ baseURL: z.string(),
23
+ auth: authProfileSchema,
24
+ createdAt: z.number(),
25
+ updatedAt: z.number(),
26
+ });
27
+ const conversationSchema = z.object({
28
+ name: z.string(),
29
+ profile: z.string(),
30
+ previousResponseId: z.string().optional(),
31
+ updatedAt: z.number(),
32
+ });
33
+ const workbenchPreferencesSchema = z.object({
34
+ defaultPreset: z.string().nullable().optional(),
35
+ isolation: z.object({
36
+ mode: z.enum(["none", "auto", "required"]).optional(),
37
+ executablePath: z.string().nullable().optional(),
38
+ version: z.string().nullable().optional(),
39
+ sourceURL: z.string().nullable().optional(),
40
+ sha256: z.string().nullable().optional(),
41
+ installSkipped: z.boolean().nullable().optional(),
42
+ }).optional(),
43
+ }).default({});
44
+ const cliConfigSchema = z.object({
45
+ activeProfile: z.string().default("default"),
46
+ profiles: z.record(z.string(), profileSchema).default({}),
47
+ conversations: z.record(z.string(), conversationSchema).default({}),
48
+ });
49
+ const appConfigurationSchema = z.object({
50
+ workbench: workbenchPreferencesSchema,
51
+ });
52
+ const conversationConfigurationSchema = z.object({
53
+ conversations: z.record(z.string(), conversationSchema).default({}),
54
+ });
55
+ export async function loadConfig() {
56
+ await ensureRuntime();
57
+ const loaded = await runtime.config.read(configFile, emptyConfig());
58
+ const parsed = cliConfigSchema.safeParse(loaded);
59
+ if (!parsed.success) {
60
+ throw new Error(`Invalid CLI config: ${parsed.error.issues.map((issue) => issue.message).join("; ")}`);
61
+ }
62
+ return parsed.data;
63
+ }
64
+ export async function saveConfig(config) {
65
+ await ensureRuntime();
66
+ await runtime.config.write(configFile, {
67
+ activeProfile: config.activeProfile,
68
+ profiles: config.profiles,
69
+ });
70
+ }
71
+ export async function loadAppConfiguration() {
72
+ await ensureRuntime();
73
+ const loaded = await runtime.config.read(appConfigurationFile, emptyAppConfiguration());
74
+ const parsed = appConfigurationSchema.safeParse(loaded);
75
+ if (!parsed.success) {
76
+ throw new Error(`Invalid app configuration: ${parsed.error.issues.map((issue) => issue.message).join("; ")}`);
77
+ }
78
+ return parsed.data;
79
+ }
80
+ export async function saveAppConfiguration(config) {
81
+ await ensureRuntime();
82
+ await runtime.config.write(appConfigurationFile, config);
83
+ }
84
+ export async function loadConversationConfiguration() {
85
+ await ensureRuntime();
86
+ const loaded = await runtime.config.read(conversationsFile, emptyConversationConfiguration());
87
+ const parsed = conversationConfigurationSchema.safeParse(loaded);
88
+ if (!parsed.success) {
89
+ throw new Error(`Invalid conversation configuration: ${parsed.error.issues.map((issue) => issue.message).join("; ")}`);
90
+ }
91
+ return parsed.data;
92
+ }
93
+ export async function saveConversationConfiguration(config) {
94
+ await ensureRuntime();
95
+ await runtime.config.write(conversationsFile, config);
96
+ }
97
+ export async function upsertProfile(profile) {
98
+ const config = await loadConfig();
99
+ const now = Math.floor(Date.now() / 1000);
100
+ const existing = config.profiles[profile.name];
101
+ const next = {
102
+ ...profile,
103
+ createdAt: existing?.createdAt ?? now,
104
+ updatedAt: now,
105
+ };
106
+ config.profiles[profile.name] = next;
107
+ config.activeProfile = profile.name;
108
+ await saveConfig(config);
109
+ return next;
110
+ }
111
+ export async function activeProfile(profileName) {
112
+ const config = await loadConfig();
113
+ const name = profileName || config.activeProfile || "default";
114
+ const profile = config.profiles[name];
115
+ if (!profile) {
116
+ throw new Error(`Profile not found: ${name}. Run agent-api login first.`);
117
+ }
118
+ return profile;
119
+ }
120
+ export function emptyConfig() {
121
+ return { activeProfile: "default", profiles: {} };
122
+ }
123
+ export function emptyAppConfiguration() {
124
+ return { workbench: {} };
125
+ }
126
+ export function emptyConversationConfiguration() {
127
+ return { conversations: {} };
128
+ }
129
+ export async function loadWorkbenchPreferences() {
130
+ const appConfig = await loadAppConfiguration();
131
+ return appConfig.workbench;
132
+ }
133
+ export async function updateWorkbenchPreferences(patch) {
134
+ const appConfig = await loadAppConfiguration();
135
+ const next = { ...appConfig.workbench };
136
+ if ("defaultPreset" in patch) {
137
+ if (patch.defaultPreset === undefined) {
138
+ delete next.defaultPreset;
139
+ }
140
+ else if (patch.defaultPreset === null) {
141
+ next.defaultPreset = null;
142
+ }
143
+ else {
144
+ const value = patch.defaultPreset.trim();
145
+ if (value) {
146
+ next.defaultPreset = value;
147
+ }
148
+ else {
149
+ delete next.defaultPreset;
150
+ }
151
+ }
152
+ }
153
+ if ("isolation" in patch) {
154
+ next.isolation = updateIsolationPreferences(next.isolation, patch.isolation);
155
+ }
156
+ appConfig.workbench = next;
157
+ await saveAppConfiguration(appConfig);
158
+ return next;
159
+ }
160
+ function updateIsolationPreferences(current, patch) {
161
+ const next = { ...(current ?? {}) };
162
+ if (!patch)
163
+ return Object.keys(next).length > 0 ? next : undefined;
164
+ if ("mode" in patch) {
165
+ if (patch.mode === null || patch.mode === undefined) {
166
+ delete next.mode;
167
+ }
168
+ else {
169
+ next.mode = patch.mode;
170
+ }
171
+ }
172
+ for (const key of ["executablePath", "version", "sourceURL", "sha256"]) {
173
+ if (key in patch) {
174
+ const value = patch[key];
175
+ if (value === undefined || value === null) {
176
+ delete next[key];
177
+ }
178
+ else {
179
+ const trimmed = value.trim();
180
+ if (trimmed)
181
+ next[key] = trimmed;
182
+ else
183
+ delete next[key];
184
+ }
185
+ }
186
+ }
187
+ if ("installSkipped" in patch) {
188
+ if (patch.installSkipped === undefined || patch.installSkipped === null) {
189
+ delete next.installSkipped;
190
+ }
191
+ else {
192
+ next.installSkipped = patch.installSkipped;
193
+ }
194
+ }
195
+ return Object.keys(next).length > 0 ? next : undefined;
196
+ }
197
+ export function redactSecret(value) {
198
+ if (value.length <= 10)
199
+ return "***";
200
+ return `${value.slice(0, 6)}…${value.slice(-4)}`;
201
+ }
@@ -0,0 +1,17 @@
1
+ import type { ConversationState } from "../config.js";
2
+ export declare function conversationKey(profile: string, name: string): string;
3
+ export declare function resolvePreviousResponseID(options: {
4
+ profile?: string;
5
+ conversation?: string;
6
+ continueConversation?: boolean;
7
+ restartConversation?: boolean;
8
+ previousResponseId?: string;
9
+ }): Promise<string | undefined>;
10
+ export declare function updateConversation(options: {
11
+ profile?: string;
12
+ conversation?: string;
13
+ }, responseID: string): Promise<void>;
14
+ export declare function listConversations(profileName?: string): Promise<ConversationState[]>;
15
+ export declare function getConversation(name: string, profileName?: string): Promise<ConversationState>;
16
+ export declare function deleteConversation(name: string, profileName?: string): Promise<void>;
17
+ export declare function conversationSummary(conversation: ConversationState): string;
@@ -0,0 +1,54 @@
1
+ import { activeProfile, loadConversationConfiguration, saveConversationConfiguration } from "../config.js";
2
+ export function conversationKey(profile, name) {
3
+ return `${profile}:${name}`;
4
+ }
5
+ export async function resolvePreviousResponseID(options) {
6
+ if (options.previousResponseId)
7
+ return options.previousResponseId;
8
+ if (options.restartConversation || !options.conversation)
9
+ return undefined;
10
+ if (!options.continueConversation)
11
+ return undefined;
12
+ const profile = await activeProfile(options.profile);
13
+ const config = await loadConversationConfiguration();
14
+ return config.conversations[conversationKey(profile.name, options.conversation)]?.previousResponseId;
15
+ }
16
+ export async function updateConversation(options, responseID) {
17
+ if (!options.conversation)
18
+ return;
19
+ const profile = await activeProfile(options.profile);
20
+ const config = await loadConversationConfiguration();
21
+ config.conversations[conversationKey(profile.name, options.conversation)] = {
22
+ name: options.conversation,
23
+ profile: profile.name,
24
+ previousResponseId: responseID,
25
+ updatedAt: Math.floor(Date.now() / 1000),
26
+ };
27
+ await saveConversationConfiguration(config);
28
+ }
29
+ export async function listConversations(profileName) {
30
+ const profile = await activeProfile(profileName);
31
+ const config = await loadConversationConfiguration();
32
+ return Object.values(config.conversations)
33
+ .filter((conversation) => conversation.profile === profile.name)
34
+ .sort((a, b) => b.updatedAt - a.updatedAt);
35
+ }
36
+ export async function getConversation(name, profileName) {
37
+ const profile = await activeProfile(profileName);
38
+ const config = await loadConversationConfiguration();
39
+ const conversation = config.conversations[conversationKey(profile.name, name)];
40
+ if (!conversation)
41
+ throw new Error(`Conversation not found: ${name}`);
42
+ return conversation;
43
+ }
44
+ export async function deleteConversation(name, profileName) {
45
+ const profile = await activeProfile(profileName);
46
+ const config = await loadConversationConfiguration();
47
+ delete config.conversations[conversationKey(profile.name, name)];
48
+ await saveConversationConfiguration(config);
49
+ }
50
+ export function conversationSummary(conversation) {
51
+ const updated = new Date(conversation.updatedAt * 1000).toISOString();
52
+ const response = conversation.previousResponseId ? ` response=${conversation.previousResponseId}` : "";
53
+ return `${conversation.name}\t${conversation.profile}\t${updated}${response}`;
54
+ }
@@ -0,0 +1,38 @@
1
+ import type { AgentRunOptions } from "../agent.js";
2
+ import type { WorkbenchAuthController } from "../workbench/auth-controller.js";
3
+ import { type WorkbenchCommandController } from "../workbench/command-controller.js";
4
+ import { type WorkbenchSession } from "../workbench/session.js";
5
+ import type { WorkbenchLifecycleEffect } from "../workbench/lifecycle-controller.js";
6
+ import type { WorkbenchAction, WorkbenchState } from "../workbench/state.js";
7
+ import type { AgentEngineServices } from "./services.js";
8
+ export interface AgentEngineApp {
9
+ session: WorkbenchSession;
10
+ commands: WorkbenchCommandController;
11
+ snapshot(): WorkbenchState;
12
+ subscribe(listener: () => void): () => void;
13
+ dispatch(action: WorkbenchAction): void;
14
+ maybeCheckForUpdate(options?: AgentEngineLifecycleOptions): Promise<void>;
15
+ loadInitialSettings(options?: AgentEngineLifecycleOptions): Promise<void>;
16
+ loadWorkdir(path?: string, options?: AgentEngineLifecycleOptions): Promise<void>;
17
+ refreshAuth(profile?: string, options?: AgentEngineLifecycleOptions): Promise<void>;
18
+ abortActiveTurn(message?: string): Promise<void>;
19
+ startInitialPrompt(): Promise<void>;
20
+ submit(input: string): Promise<void>;
21
+ runLifecycleEffects(effects: WorkbenchLifecycleEffect[], options?: AgentEngineLifecycleOptions): void;
22
+ dispose(): void;
23
+ }
24
+ export interface AgentEngineAppOptions {
25
+ authController: WorkbenchAuthController;
26
+ baseOptions: AgentRunOptions;
27
+ profileName: string;
28
+ services?: Omit<AgentEngineServices, "auth">;
29
+ onDeleteProfile(): Promise<void>;
30
+ onExit(): void;
31
+ onLogin(): void;
32
+ onLogout(): void;
33
+ onSwitchProfile(name?: string): void;
34
+ }
35
+ export interface AgentEngineLifecycleOptions {
36
+ isMounted?: () => boolean;
37
+ }
38
+ export declare function createAgentEngine(options: AgentEngineAppOptions): AgentEngineApp;
@@ -0,0 +1,146 @@
1
+ import { createWorkbenchCommandController, } from "../workbench/command-controller.js";
2
+ import { createWorkbenchSession, } from "../workbench/session.js";
3
+ export function createAgentEngine(options) {
4
+ const session = createWorkbenchSession({
5
+ authController: options.authController,
6
+ baseOptions: options.baseOptions,
7
+ services: options.services,
8
+ });
9
+ const commands = createWorkbenchCommandController({
10
+ authController: options.authController,
11
+ conversationController: session.conversation,
12
+ engine: session.engine,
13
+ localController: session.local,
14
+ options: options.baseOptions,
15
+ profileName: options.profileName,
16
+ settingsController: session.settings,
17
+ turnController: session.turn,
18
+ onDeleteProfile: options.onDeleteProfile,
19
+ onExit: options.onExit,
20
+ onLogin: options.onLogin,
21
+ onLogout: options.onLogout,
22
+ onSwitchProfile: options.onSwitchProfile,
23
+ });
24
+ async function submit(input) {
25
+ const submission = session.engine.submit(input);
26
+ if (submission.kind === "command") {
27
+ await commands.run(submission.command);
28
+ return;
29
+ }
30
+ if (submission.kind === "prompt") {
31
+ await session.turn.startPrompt(submission.prompt);
32
+ }
33
+ }
34
+ async function maybeCheckForUpdate(lifecycleOptions) {
35
+ const effects = await session.lifecycle.maybeCheckForUpdate();
36
+ runLifecycleEffects(effects, lifecycleOptions);
37
+ }
38
+ async function loadInitialSettings(lifecycleOptions = {}) {
39
+ try {
40
+ const settings = await session.settings.loadInitial({
41
+ modelExplicit: options.baseOptions.modelExplicit,
42
+ preset: options.baseOptions.preset,
43
+ presetExplicit: options.baseOptions.presetExplicit,
44
+ });
45
+ if (lifecycleOptions.isMounted && !lifecycleOptions.isMounted())
46
+ return;
47
+ session.engine.dispatch({ type: "settings.set", settings });
48
+ if (settings.activity) {
49
+ session.engine.dispatch({ type: "activity.add", level: "success", text: settings.activity });
50
+ }
51
+ if (settings.notice) {
52
+ session.engine.dispatch({ type: "message.add", role: "system", text: settings.notice });
53
+ session.engine.dispatch({ type: "activity.add", level: "warning", text: "Shell isolation setup is not configured" });
54
+ }
55
+ if (settings.warning) {
56
+ session.engine.dispatch({ type: "activity.add", level: "warning", text: settings.warning });
57
+ }
58
+ }
59
+ catch (error) {
60
+ if (lifecycleOptions.isMounted && !lifecycleOptions.isMounted())
61
+ return;
62
+ session.engine.dispatch({
63
+ type: "activity.add",
64
+ level: "warning",
65
+ text: `Config preferences unavailable: ${userFacingError(error)}`,
66
+ });
67
+ }
68
+ }
69
+ async function loadWorkdir(path, lifecycleOptions = {}) {
70
+ session.engine.dispatch({ type: "activity.add", text: "Loading workdir" });
71
+ try {
72
+ const workdir = await session.local.load(path);
73
+ if (lifecycleOptions.isMounted && !lifecycleOptions.isMounted())
74
+ return;
75
+ session.engine.dispatch({
76
+ type: "workdir.set",
77
+ workdir,
78
+ });
79
+ }
80
+ catch (error) {
81
+ if (lifecycleOptions.isMounted && !lifecycleOptions.isMounted())
82
+ return;
83
+ session.engine.dispatch({
84
+ type: "activity.add",
85
+ level: "error",
86
+ text: `Workdir unavailable: ${userFacingError(error)}`,
87
+ });
88
+ }
89
+ }
90
+ async function refreshAuth(profile, lifecycleOptions) {
91
+ const effects = await session.lifecycle.refreshAuth(profile);
92
+ runLifecycleEffects(effects, lifecycleOptions);
93
+ }
94
+ async function abortActiveTurn(message = "Abort requested.") {
95
+ await session.turn.abort(message);
96
+ }
97
+ async function startInitialPrompt() {
98
+ const state = session.engine.snapshot();
99
+ const initialPrompt = session.lifecycle.initialPrompt({
100
+ busy: state.busy,
101
+ promptParts: options.baseOptions.promptParts,
102
+ requiresWorkdir: state.contextEnabled,
103
+ workdir: state.workdir,
104
+ });
105
+ if (initialPrompt)
106
+ await session.turn.startPrompt(initialPrompt);
107
+ }
108
+ function runLifecycleEffects(effects, lifecycleOptions = {}) {
109
+ for (const effect of effects) {
110
+ switch (effect.type) {
111
+ case "dispatch":
112
+ session.engine.dispatch(effect.action);
113
+ break;
114
+ case "close":
115
+ setTimeout(() => {
116
+ if (lifecycleOptions.isMounted?.() ?? true)
117
+ options.onExit();
118
+ }, effect.delayMs);
119
+ break;
120
+ }
121
+ }
122
+ }
123
+ return {
124
+ session,
125
+ commands,
126
+ snapshot: session.engine.snapshot,
127
+ subscribe: session.engine.subscribe,
128
+ dispatch: session.engine.dispatch,
129
+ maybeCheckForUpdate,
130
+ loadInitialSettings,
131
+ loadWorkdir,
132
+ refreshAuth,
133
+ abortActiveTurn,
134
+ startInitialPrompt,
135
+ submit,
136
+ runLifecycleEffects,
137
+ dispose() {
138
+ session.runtime.dispose();
139
+ },
140
+ };
141
+ }
142
+ function userFacingError(error) {
143
+ if (error instanceof Error)
144
+ return error.message;
145
+ return String(error);
146
+ }
@@ -0,0 +1,50 @@
1
+ export type { AgentEngineApp, AgentEngineAppOptions, AgentEngineLifecycleOptions, } from "./agent-engine.js";
2
+ export { createAgentEngine, } from "./agent-engine.js";
3
+ export type { AgentRunOptions, AgentTurnEvent, LocalToolApprovalRequest, WorkdirAccessMode, } from "../agent.js";
4
+ export { agentResponseFailureMessage, agentTurnEventFromStreamEvent, clearPresetToolCatalogCache, conversationSummary, deleteConversation, getConversation, isAvailablePreset, listAvailablePresets, listConversations, resumeAgentAfterLocalApproval, runAgent, resolveAgentRequestTools, runAgentTurn, } from "../agent.js";
5
+ export type { ChatOptions } from "../chat-options.js";
6
+ export { normalizeChatOptions } from "../chat-options.js";
7
+ export type { AgentEngineServices } from "./services.js";
8
+ export { defaultBaseURL } from "../config.js";
9
+ export type { AuthProfile, ConversationState, Profile, WorkbenchPreferences, } from "../config.js";
10
+ export { activeProfile, loadAppConfiguration, loadConfig, loadConversationConfiguration, loadWorkbenchPreferences, redactSecret, saveAppConfiguration, saveConfig, saveConversationConfiguration, updateWorkbenchPreferences, } from "../config.js";
11
+ export type { AuthStatus, RuntimeProfile, } from "../profile.js";
12
+ export { AuthSessionExpiredError, browserAccessTokenExpiresWithin, deleteProfile, formatDeviceUserCode, getAuthStatus, listProfiles, loginWithAPIKey, loginWithBrowser, openBrowserURL, profileSummary, refreshActiveProfileIfNeeded, refreshBrowserSession, refreshIfNeeded, resolveRuntimeProfile, saveBrowserProfile, startBrowserAuthChallenge, useProfile, waitForBrowserAuthChallenge, } from "../profile.js";
13
+ export { appVersion, configureAgentAppRuntime, currentAgentAppRuntime, defaultAppAuthor, defaultAppName, defaultAppVersion, ensureRuntime, runtime, } from "../runtime/index.js";
14
+ export type { AgentAppRuntimeContext, AgentAppRuntimeOptions, } from "../runtime/index.js";
15
+ export { checkForUpdate, compareVersions, formatUpdateNotice, } from "../update.js";
16
+ export type { WorkdirContextOptions, WorkdirOptions, WorkdirService, } from "../workdir/index.js";
17
+ export { buildWorkdirContextBlock, openWorkdir, } from "../workdir/index.js";
18
+ export type { WorkbenchAuthController } from "../workbench/auth-controller.js";
19
+ export { authStatusText, createWorkbenchAuthController, } from "../workbench/auth-controller.js";
20
+ export type { AuthGateState, WorkbenchAuthGateController, } from "../workbench/auth-gate-controller.js";
21
+ export { authMethods, createWorkbenchAuthGateController, } from "../workbench/auth-gate-controller.js";
22
+ export type { WorkbenchCommandController } from "../workbench/command-controller.js";
23
+ export { createWorkbenchCommandController } from "../workbench/command-controller.js";
24
+ export type { WorkbenchConversationController } from "../workbench/conversation-controller.js";
25
+ export { createConversationName, createWorkbenchConversationController, defaultTranscriptExportPath, } from "../workbench/conversation-controller.js";
26
+ export type { WorkbenchEngine, WorkbenchSubmission, } from "../workbench/engine.js";
27
+ export { createWorkbenchEngine } from "../workbench/engine.js";
28
+ export type { WorkbenchInputController } from "../workbench/input-controller.js";
29
+ export { createWorkbenchInputController } from "../workbench/input-controller.js";
30
+ export type { IsolatorInstallConfig, IsolatorInstallOptions, IsolatorInstallResult, } from "../workbench/isolator-installer.js";
31
+ export { defaultIsolatorInstallPath, ensureConfiguredIsolator, installConfiguredIsolator, normalizeInstallPath, normalizeSourceURL, relocateInstalledIsolator, validateInstalledIsolator, } from "../workbench/isolator-installer.js";
32
+ export type { WorkbenchLifecycleController, WorkbenchLifecycleEffect, } from "../workbench/lifecycle-controller.js";
33
+ export { createWorkbenchLifecycleController, updateNoticeEffects, } from "../workbench/lifecycle-controller.js";
34
+ export type { WorkbenchLocalController } from "../workbench/local-controller.js";
35
+ export { createWorkbenchLocalController } from "../workbench/local-controller.js";
36
+ export type { WorkbenchRenderModel } from "../workbench/render-model.js";
37
+ export { buildWorkbenchRenderModel, busySpinner, pendingLocalLabel, } from "../workbench/render-model.js";
38
+ export type { WorkbenchRuntimeController } from "../workbench/runtime-controller.js";
39
+ export { createWorkbenchRuntimeController } from "../workbench/runtime-controller.js";
40
+ export type { WorkbenchSession, WorkbenchSessionOptions, } from "../workbench/session.js";
41
+ export { createWorkbenchSession, sessionState, } from "../workbench/session.js";
42
+ export type { WorkbenchSettingsController, WorkbenchSettingsSnapshot, } from "../workbench/settings-controller.js";
43
+ export { createWorkbenchSettingsController, formatPresetList, UnknownPresetError, } from "../workbench/settings-controller.js";
44
+ export type { ShellIsolationMode, ShellIsolationPreferences, } from "../workbench/shell-isolation.js";
45
+ export { localShellIsolationOptions } from "../workbench/shell-isolation.js";
46
+ export type { WorkbenchTurnController } from "../workbench/turn-controller.js";
47
+ export { createWorkbenchTurnController } from "../workbench/turn-controller.js";
48
+ export { buildTranscriptLines, buildTranscriptViewModel, elapsedDots, spinnerGlyph, } from "../workbench/view-model.js";
49
+ export type { ActivityLevel, InputHistory, LocalToolApproval, RenderMode, WorkbenchAction, WorkbenchActivity, WorkbenchCommand, WorkbenchMessage, WorkbenchRole, WorkbenchState, WorkbenchWorkdirStatus, } from "../workbench/state.js";
50
+ export { activityColor, createInitialWorkbenchState, createInputHistory, formatTranscript, formatTranscriptPreview, helpText, parsePendingApprovalCommand, parseWorkbenchCommand, workbenchReducer, workdirText, } from "../workbench/state.js";
@@ -0,0 +1,26 @@
1
+ export { createAgentEngine, } from "./agent-engine.js";
2
+ export { agentResponseFailureMessage, agentTurnEventFromStreamEvent, clearPresetToolCatalogCache, conversationSummary, deleteConversation, getConversation, isAvailablePreset, listAvailablePresets, listConversations, resumeAgentAfterLocalApproval, runAgent, resolveAgentRequestTools, runAgentTurn, } from "../agent.js";
3
+ export { normalizeChatOptions } from "../chat-options.js";
4
+ export { defaultBaseURL } from "../config.js";
5
+ export { activeProfile, loadAppConfiguration, loadConfig, loadConversationConfiguration, loadWorkbenchPreferences, redactSecret, saveAppConfiguration, saveConfig, saveConversationConfiguration, updateWorkbenchPreferences, } from "../config.js";
6
+ export { AuthSessionExpiredError, browserAccessTokenExpiresWithin, deleteProfile, formatDeviceUserCode, getAuthStatus, listProfiles, loginWithAPIKey, loginWithBrowser, openBrowserURL, profileSummary, refreshActiveProfileIfNeeded, refreshBrowserSession, refreshIfNeeded, resolveRuntimeProfile, saveBrowserProfile, startBrowserAuthChallenge, useProfile, waitForBrowserAuthChallenge, } from "../profile.js";
7
+ export { appVersion, configureAgentAppRuntime, currentAgentAppRuntime, defaultAppAuthor, defaultAppName, defaultAppVersion, ensureRuntime, runtime, } from "../runtime/index.js";
8
+ export { checkForUpdate, compareVersions, formatUpdateNotice, } from "../update.js";
9
+ export { buildWorkdirContextBlock, openWorkdir, } from "../workdir/index.js";
10
+ export { authStatusText, createWorkbenchAuthController, } from "../workbench/auth-controller.js";
11
+ export { authMethods, createWorkbenchAuthGateController, } from "../workbench/auth-gate-controller.js";
12
+ export { createWorkbenchCommandController } from "../workbench/command-controller.js";
13
+ export { createConversationName, createWorkbenchConversationController, defaultTranscriptExportPath, } from "../workbench/conversation-controller.js";
14
+ export { createWorkbenchEngine } from "../workbench/engine.js";
15
+ export { createWorkbenchInputController } from "../workbench/input-controller.js";
16
+ export { defaultIsolatorInstallPath, ensureConfiguredIsolator, installConfiguredIsolator, normalizeInstallPath, normalizeSourceURL, relocateInstalledIsolator, validateInstalledIsolator, } from "../workbench/isolator-installer.js";
17
+ export { createWorkbenchLifecycleController, updateNoticeEffects, } from "../workbench/lifecycle-controller.js";
18
+ export { createWorkbenchLocalController } from "../workbench/local-controller.js";
19
+ export { buildWorkbenchRenderModel, busySpinner, pendingLocalLabel, } from "../workbench/render-model.js";
20
+ export { createWorkbenchRuntimeController } from "../workbench/runtime-controller.js";
21
+ export { createWorkbenchSession, sessionState, } from "../workbench/session.js";
22
+ export { createWorkbenchSettingsController, formatPresetList, UnknownPresetError, } from "../workbench/settings-controller.js";
23
+ export { localShellIsolationOptions } from "../workbench/shell-isolation.js";
24
+ export { createWorkbenchTurnController } from "../workbench/turn-controller.js";
25
+ export { buildTranscriptLines, buildTranscriptViewModel, elapsedDots, spinnerGlyph, } from "../workbench/view-model.js";
26
+ export { activityColor, createInitialWorkbenchState, createInputHistory, formatTranscript, formatTranscriptPreview, helpText, parsePendingApprovalCommand, parseWorkbenchCommand, workbenchReducer, workdirText, } from "../workbench/state.js";
@@ -0,0 +1,20 @@
1
+ import type { WorkbenchAuthController } from "../workbench/auth-controller.js";
2
+ import type { WorkbenchConversationController } from "../workbench/conversation-controller.js";
3
+ import type { WorkbenchEngine } from "../workbench/engine.js";
4
+ import type { WorkbenchInputController } from "../workbench/input-controller.js";
5
+ import type { WorkbenchLifecycleController } from "../workbench/lifecycle-controller.js";
6
+ import type { WorkbenchLocalController } from "../workbench/local-controller.js";
7
+ import type { WorkbenchRuntimeController } from "../workbench/runtime-controller.js";
8
+ import type { WorkbenchSettingsController } from "../workbench/settings-controller.js";
9
+ import type { WorkbenchTurnController } from "../workbench/turn-controller.js";
10
+ export interface AgentEngineServices {
11
+ auth?: WorkbenchAuthController;
12
+ conversation?: WorkbenchConversationController;
13
+ engine?: WorkbenchEngine;
14
+ input?: WorkbenchInputController;
15
+ lifecycle?: WorkbenchLifecycleController;
16
+ local?: WorkbenchLocalController;
17
+ runtime?: WorkbenchRuntimeController;
18
+ settings?: WorkbenchSettingsController;
19
+ turn?: WorkbenchTurnController;
20
+ }