@agent-api/app-engine 0.0.7 → 0.1.0

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 CHANGED
@@ -15,9 +15,9 @@ npm install @agent-api/app-engine
15
15
  ```ts
16
16
  import {
17
17
  configureAgentAppRuntime,
18
- createAgentEngine,
19
- createWorkbenchAuthController,
20
- } from "@agent-api/app-engine";
18
+ loginWithAPIKey,
19
+ runAgentTurn,
20
+ } from "@agent-api/app-engine/core";
21
21
 
22
22
  configureAgentAppRuntime({
23
23
  appName: "my-agent-app",
@@ -25,17 +25,34 @@ configureAgentAppRuntime({
25
25
  appVersion: "1.0.0",
26
26
  });
27
27
 
28
- const engine = createAgentEngine();
29
- const auth = createWorkbenchAuthController();
28
+ await loginWithAPIKey({
29
+ profile: "default",
30
+ baseURL: "https://api.agentsway.dev",
31
+ apiKey: process.env.AGENT_API_KEY!,
32
+ });
33
+
34
+ const result = await runAgentTurn({
35
+ profile: "default",
36
+ promptParts: ["Hello"],
37
+ });
30
38
  ```
31
39
 
32
40
  Host applications should call `configureAgentAppRuntime()` during startup so config, profiles, and runtime files live under the host app's own platform config directory.
33
41
 
42
+ ## Import Layers
43
+
44
+ - `@agent-api/app-engine/core`: UI-neutral APIs for auth, config, profiles, conversations, updates, local workdir setup, and agent turns.
45
+ - `@agent-api/app-engine/workbench`: optional app/workbench state controllers for apps that want Agent API's conversation workflow.
46
+ - `@agent-api/app-engine/terminal`: optional terminal-facing helpers for transcript wrapping, input viewport rendering, and spinner glyphs.
47
+
48
+ The root `@agent-api/app-engine` entry is intentionally empty. Use an explicit subpath so your application depends on a clear API layer.
49
+
34
50
  ## Boundaries
35
51
 
36
- - This package owns core application state and side effects.
37
- - Renderers own input widgets, layout, keyboard handling, and screen drawing.
38
- - The CLI/TUI package should import core behavior from this package rather than from private source paths.
52
+ - Core APIs own application state and side effects.
53
+ - Workbench APIs own reusable conversation/workbench semantics.
54
+ - Terminal APIs are optional helpers for terminal renderers.
55
+ - Renderers own widgets, native input controls, layout, keyboard mapping, and screen drawing.
39
56
 
40
57
  ## Local Development
41
58
 
package/dist/core.d.ts ADDED
@@ -0,0 +1,17 @@
1
+ export type { AgentEngineApp, AgentEngineAppOptions, AgentEngineLifecycleOptions, } from "./engine/agent-engine.js";
2
+ export { createAgentEngine, } from "./engine/agent-engine.js";
3
+ export type { AgentRunOptions, AgentTurnEvent, AgentTurnResult, LocalToolApprovalRequest, WorkdirAccessMode, } from "./agent.js";
4
+ export { agentResponseFailureMessage, agentTurnEventFromStreamEvent, clearPresetToolCatalogCache, conversationSummary, deleteConversation, ensureConversation, getConversation, isAvailablePreset, listAvailablePresets, listConversations, localToolExecutionErrorResult, resolveAgentRequestTools, resumeAgentAfterLocalApproval, runAgent, runAgentTurn, startFreshConversation, } from "./agent.js";
5
+ export type { ChatOptions } from "./chat-options.js";
6
+ export { normalizeChatOptions } from "./chat-options.js";
7
+ export type { AgentEngineServices } from "./engine/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";
package/dist/core.js ADDED
@@ -0,0 +1,9 @@
1
+ export { createAgentEngine, } from "./engine/agent-engine.js";
2
+ export { agentResponseFailureMessage, agentTurnEventFromStreamEvent, clearPresetToolCatalogCache, conversationSummary, deleteConversation, ensureConversation, getConversation, isAvailablePreset, listAvailablePresets, listConversations, localToolExecutionErrorResult, resolveAgentRequestTools, resumeAgentAfterLocalApproval, runAgent, runAgentTurn, startFreshConversation, } 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";
@@ -1,50 +1,3 @@
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, ensureConversation, getConversation, isAvailablePreset, listAvailablePresets, listConversations, localToolExecutionErrorResult, resumeAgentAfterLocalApproval, runAgent, resolveAgentRequestTools, runAgentTurn, startFreshConversation, } 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, normalizeInstallTargetPath, normalizeInstallPath, normalizeSourceURL, relocateInstalledIsolator, validateIsolatorInstallTarget, 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";
1
+ export * from "../core.js";
2
+ export * from "../workbench.js";
3
+ export * from "../terminal.js";
@@ -1,26 +1,3 @@
1
- export { createAgentEngine, } from "./agent-engine.js";
2
- export { agentResponseFailureMessage, agentTurnEventFromStreamEvent, clearPresetToolCatalogCache, conversationSummary, deleteConversation, ensureConversation, getConversation, isAvailablePreset, listAvailablePresets, listConversations, localToolExecutionErrorResult, resumeAgentAfterLocalApproval, runAgent, resolveAgentRequestTools, runAgentTurn, startFreshConversation, } 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, normalizeInstallTargetPath, normalizeInstallPath, normalizeSourceURL, relocateInstalledIsolator, validateIsolatorInstallTarget, 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";
1
+ export * from "../core.js";
2
+ export * from "../workbench.js";
3
+ export * from "../terminal.js";
package/dist/index.d.ts CHANGED
@@ -1 +1 @@
1
- export * from "./engine/index.js";
1
+ export {};
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- export * from "./engine/index.js";
1
+ export {};
@@ -0,0 +1,7 @@
1
+ export type { WorkbenchInputController } from "./workbench/input-controller.js";
2
+ export { createWorkbenchInputController } from "./workbench/input-controller.js";
3
+ export type { WorkbenchRenderModel } from "./workbench/render-model.js";
4
+ export { buildWorkbenchRenderModel, busySpinner, pendingLocalLabel, } from "./workbench/render-model.js";
5
+ export type { TranscriptLine, TranscriptSpan, TranscriptViewModel, } from "./workbench/view-model.js";
6
+ export { buildTranscriptLines, buildTranscriptViewModel, elapsedDots, spinnerGlyph, } from "./workbench/view-model.js";
7
+ export { activityColor } from "./workbench/state.js";
@@ -0,0 +1,4 @@
1
+ export { createWorkbenchInputController } from "./workbench/input-controller.js";
2
+ export { buildWorkbenchRenderModel, busySpinner, pendingLocalLabel, } from "./workbench/render-model.js";
3
+ export { buildTranscriptLines, buildTranscriptViewModel, elapsedDots, spinnerGlyph, } from "./workbench/view-model.js";
4
+ export { activityColor } from "./workbench/state.js";
@@ -30,6 +30,7 @@ export interface WorkbenchRenderModel {
30
30
  draft: string;
31
31
  fullAccess: boolean;
32
32
  label: string;
33
+ viewportColumns: number;
33
34
  waitingText: string;
34
35
  };
35
36
  terminalColumns: number;
@@ -16,9 +16,10 @@ export function buildWorkbenchRenderModel(input) {
16
16
  width: transcriptWidth,
17
17
  });
18
18
  const cursor = Math.max(0, Math.min(input.draft.length, input.cursor ?? input.draft.length));
19
- const beforeCursor = input.draft.slice(0, cursor);
20
- const cursorText = input.draft[cursor] ?? " ";
21
- const afterCursor = input.draft.slice(cursor + (cursor < input.draft.length ? 1 : 0));
19
+ const fullAccess = input.state.accessMode === "full";
20
+ const label = input.state.busy ? "working" : "you";
21
+ const inputViewportColumns = Math.max(12, terminalColumns - 10 - label.length - (fullAccess ? 14 : 0));
22
+ const inputViewport = inputViewportText(input.draft, cursor, inputViewportColumns);
22
23
  return {
23
24
  activityHeight,
24
25
  footerText: [
@@ -43,14 +44,15 @@ export function buildWorkbenchRenderModel(input) {
43
44
  workdir: input.state.workdir?.root || input.workdirFallback,
44
45
  },
45
46
  input: {
46
- afterCursor,
47
- beforeCursor,
47
+ afterCursor: inputViewport.afterCursor,
48
+ beforeCursor: inputViewport.beforeCursor,
48
49
  busy: input.state.busy,
49
50
  cursor,
50
- cursorText,
51
+ cursorText: inputViewport.cursorText,
51
52
  draft: input.draft,
52
- fullAccess: input.state.accessMode === "full",
53
- label: input.state.busy ? "working" : "you",
53
+ fullAccess,
54
+ label,
55
+ viewportColumns: inputViewportColumns,
54
56
  waitingText: `waiting for agent ${elapsedDots(input.spinnerFrame)}`,
55
57
  },
56
58
  terminalColumns,
@@ -70,3 +72,30 @@ export function pendingLocalLabel(state) {
70
72
  export function busySpinner(frame) {
71
73
  return spinnerGlyph(frame);
72
74
  }
75
+ function inputViewportText(draft, cursor, maxColumns) {
76
+ if (draft.length === 0) {
77
+ return { beforeCursor: "", cursorText: " ", afterCursor: "" };
78
+ }
79
+ const fullWidth = Math.max(1, maxColumns - (cursor >= draft.length ? 1 : 0));
80
+ if (draft.length <= fullWidth) {
81
+ return {
82
+ beforeCursor: draft.slice(0, cursor),
83
+ cursorText: draft[cursor] ?? " ",
84
+ afterCursor: draft.slice(cursor + (cursor < draft.length ? 1 : 0)),
85
+ };
86
+ }
87
+ const windowColumns = Math.max(4, maxColumns - 3);
88
+ const maxStart = Math.max(0, draft.length - windowColumns);
89
+ const preferredStart = cursor >= draft.length
90
+ ? maxStart
91
+ : Math.max(0, cursor - Math.floor(windowColumns * 0.65));
92
+ const start = Math.min(preferredStart, maxStart);
93
+ const end = Math.min(draft.length, start + windowColumns);
94
+ const visibleCursor = Math.max(start, Math.min(cursor, end));
95
+ const hasLeft = start > 0;
96
+ const hasRight = end < draft.length;
97
+ const beforeCursor = `${hasLeft ? "‹" : ""}${draft.slice(start, visibleCursor)}`;
98
+ const cursorText = draft[visibleCursor] ?? " ";
99
+ const afterCursor = `${draft.slice(visibleCursor + (visibleCursor < draft.length ? 1 : 0), end)}${hasRight ? "›" : ""}`;
100
+ return { beforeCursor, cursorText, afterCursor };
101
+ }
@@ -5,6 +5,13 @@ export type TranscriptLine = {
5
5
  color?: string;
6
6
  bold?: boolean;
7
7
  inverse?: boolean;
8
+ spans?: TranscriptSpan[];
9
+ };
10
+ export type TranscriptSpan = {
11
+ text: string;
12
+ color?: string;
13
+ bold?: boolean;
14
+ inverse?: boolean;
8
15
  };
9
16
  export interface TranscriptViewModel {
10
17
  lines: TranscriptLine[];
@@ -80,16 +80,85 @@ function markdownTranscriptLine(line, options) {
80
80
  return [{ text: "─".repeat(Math.min(48, options.width)), color: "gray" }];
81
81
  const bullet = /^(\s*)[-*]\s+(.+)$/.exec(line);
82
82
  if (bullet)
83
- return wrapTranscriptText(`${bullet[1]}• ${bullet[2]}`, options.width).map((text) => ({ text }));
83
+ return wrapMarkdownInline(`${bullet[1]}• ${bullet[2]}`, options.width);
84
84
  const numbered = /^(\s*)(\d+\.)\s+(.+)$/.exec(line);
85
85
  if (numbered)
86
- return wrapTranscriptText(`${numbered[1]}${numbered[2]} ${numbered[3]}`, options.width).map((text) => ({ text }));
86
+ return wrapMarkdownInline(`${numbered[1]}${numbered[2]} ${numbered[3]}`, options.width);
87
87
  const quote = /^\s*>\s?(.+)$/.exec(line);
88
88
  if (quote)
89
- return wrapTranscriptText(`│ ${quote[1]}`, options.width).map((text) => ({ text, color: "gray" }));
90
- return wrapTranscriptText(line, options.width).map((text) => ({ text }));
89
+ return wrapMarkdownInline(`│ ${quote[1]}`, options.width).map((item) => ({ ...item, color: "gray" }));
90
+ return wrapMarkdownInline(line, options.width);
91
91
  }
92
- function wrapTranscriptText(text, width) {
92
+ function wrapMarkdownInline(text, width) {
93
+ return wrapTranscriptSpans(markdownInlineSpans(text), width);
94
+ }
95
+ function markdownInlineSpans(text) {
96
+ const spans = [];
97
+ const pattern = /(\*\*([^*]+)\*\*)|(\[([^\]]+)\]\(([^)]+)\))/g;
98
+ let lastIndex = 0;
99
+ for (const match of text.matchAll(pattern)) {
100
+ const index = match.index ?? 0;
101
+ if (index > lastIndex) {
102
+ spans.push({ text: text.slice(lastIndex, index) });
103
+ }
104
+ if (match[2]) {
105
+ spans.push({ text: match[2], bold: true });
106
+ }
107
+ else if (match[4]) {
108
+ spans.push({ text: match[4], color: "cyan" });
109
+ if (match[5])
110
+ spans.push({ text: ` (${match[5]})`, color: "gray" });
111
+ }
112
+ lastIndex = index + match[0].length;
113
+ }
114
+ if (lastIndex < text.length) {
115
+ spans.push({ text: text.slice(lastIndex) });
116
+ }
117
+ return spans.length > 0 ? spans : [{ text }];
118
+ }
119
+ function wrapTranscriptSpans(spans, width) {
120
+ const text = spans.map((span) => span.text).join("");
121
+ const wrapped = wrapTranscriptText(text, width, { trimStart: false });
122
+ const lines = [];
123
+ let offset = 0;
124
+ for (const line of wrapped) {
125
+ const lineSpans = sliceSpans(spans, offset, line.length);
126
+ offset += line.length;
127
+ while (text[offset] === " ")
128
+ offset += 1;
129
+ lines.push({
130
+ text: line,
131
+ spans: lineSpans.length > 0 ? lineSpans : undefined,
132
+ });
133
+ }
134
+ return lines;
135
+ }
136
+ function sliceSpans(spans, offset, length) {
137
+ const output = [];
138
+ let position = 0;
139
+ let remaining = length;
140
+ for (const span of spans) {
141
+ if (remaining <= 0)
142
+ break;
143
+ const spanEnd = position + span.text.length;
144
+ if (spanEnd <= offset) {
145
+ position = spanEnd;
146
+ continue;
147
+ }
148
+ if (position >= offset + length)
149
+ break;
150
+ const start = Math.max(0, offset - position);
151
+ const end = Math.min(span.text.length, start + remaining);
152
+ const text = span.text.slice(start, end);
153
+ if (text) {
154
+ output.push({ ...span, text });
155
+ remaining -= text.length;
156
+ }
157
+ position = spanEnd;
158
+ }
159
+ return output;
160
+ }
161
+ function wrapTranscriptText(text, width, options = {}) {
93
162
  const max = Math.max(12, width);
94
163
  if (text.length === 0)
95
164
  return [""];
@@ -105,7 +174,7 @@ function wrapTranscriptText(text, width) {
105
174
  const chunk = useSoftBreak ? soft : hard.text;
106
175
  const index = useSoftBreak ? softBreak : hard.length;
107
176
  lines.push(chunk.trimEnd());
108
- rest = rest.slice(index).trimStart();
177
+ rest = options.trimStart === false ? rest.slice(index) : rest.slice(index).trimStart();
109
178
  }
110
179
  lines.push(rest);
111
180
  return lines;
@@ -0,0 +1,28 @@
1
+ export type { WorkbenchAuthController } from "./workbench/auth-controller.js";
2
+ export { authStatusText, createWorkbenchAuthController, } from "./workbench/auth-controller.js";
3
+ export type { AuthGateState, WorkbenchAuthGateController, } from "./workbench/auth-gate-controller.js";
4
+ export { authMethods, createWorkbenchAuthGateController, } from "./workbench/auth-gate-controller.js";
5
+ export type { WorkbenchCommandController } from "./workbench/command-controller.js";
6
+ export { createWorkbenchCommandController } from "./workbench/command-controller.js";
7
+ export type { WorkbenchConversationController } from "./workbench/conversation-controller.js";
8
+ export { createConversationName, createWorkbenchConversationController, defaultTranscriptExportPath, } from "./workbench/conversation-controller.js";
9
+ export type { WorkbenchEngine, WorkbenchSubmission, } from "./workbench/engine.js";
10
+ export { createWorkbenchEngine } from "./workbench/engine.js";
11
+ export type { IsolatorInstallConfig, IsolatorInstallOptions, IsolatorInstallResult, } from "./workbench/isolator-installer.js";
12
+ export { defaultIsolatorInstallPath, ensureConfiguredIsolator, installConfiguredIsolator, normalizeInstallTargetPath, normalizeInstallPath, normalizeSourceURL, relocateInstalledIsolator, validateIsolatorInstallTarget, validateInstalledIsolator, } from "./workbench/isolator-installer.js";
13
+ export type { WorkbenchLifecycleController, WorkbenchLifecycleEffect, } from "./workbench/lifecycle-controller.js";
14
+ export { createWorkbenchLifecycleController, updateNoticeEffects, } from "./workbench/lifecycle-controller.js";
15
+ export type { WorkbenchLocalController } from "./workbench/local-controller.js";
16
+ export { createWorkbenchLocalController } from "./workbench/local-controller.js";
17
+ export type { WorkbenchRuntimeController } from "./workbench/runtime-controller.js";
18
+ export { createWorkbenchRuntimeController } from "./workbench/runtime-controller.js";
19
+ export type { WorkbenchSession, WorkbenchSessionOptions, } from "./workbench/session.js";
20
+ export { createWorkbenchSession, sessionState, } from "./workbench/session.js";
21
+ export type { WorkbenchSettingsController, WorkbenchSettingsSnapshot, } from "./workbench/settings-controller.js";
22
+ export { createWorkbenchSettingsController, formatPresetList, UnknownPresetError, } from "./workbench/settings-controller.js";
23
+ export type { ShellIsolationMode, ShellIsolationPreferences, } from "./workbench/shell-isolation.js";
24
+ export { localShellIsolationOptions } from "./workbench/shell-isolation.js";
25
+ export type { WorkbenchTurnController } from "./workbench/turn-controller.js";
26
+ export { createWorkbenchTurnController } from "./workbench/turn-controller.js";
27
+ export type { ActivityLevel, InputHistory, LocalToolApproval, RenderMode, WorkbenchAction, WorkbenchActivity, WorkbenchCommand, WorkbenchMessage, WorkbenchRole, WorkbenchState, WorkbenchWorkdirStatus, } from "./workbench/state.js";
28
+ export { createInitialWorkbenchState, createInputHistory, formatTranscript, formatTranscriptPreview, helpText, parsePendingApprovalCommand, parseWorkbenchCommand, workbenchReducer, workdirText, } from "./workbench/state.js";
@@ -0,0 +1,14 @@
1
+ export { authStatusText, createWorkbenchAuthController, } from "./workbench/auth-controller.js";
2
+ export { authMethods, createWorkbenchAuthGateController, } from "./workbench/auth-gate-controller.js";
3
+ export { createWorkbenchCommandController } from "./workbench/command-controller.js";
4
+ export { createConversationName, createWorkbenchConversationController, defaultTranscriptExportPath, } from "./workbench/conversation-controller.js";
5
+ export { createWorkbenchEngine } from "./workbench/engine.js";
6
+ export { defaultIsolatorInstallPath, ensureConfiguredIsolator, installConfiguredIsolator, normalizeInstallTargetPath, normalizeInstallPath, normalizeSourceURL, relocateInstalledIsolator, validateIsolatorInstallTarget, validateInstalledIsolator, } from "./workbench/isolator-installer.js";
7
+ export { createWorkbenchLifecycleController, updateNoticeEffects, } from "./workbench/lifecycle-controller.js";
8
+ export { createWorkbenchLocalController } from "./workbench/local-controller.js";
9
+ export { createWorkbenchRuntimeController } from "./workbench/runtime-controller.js";
10
+ export { createWorkbenchSession, sessionState, } from "./workbench/session.js";
11
+ export { createWorkbenchSettingsController, formatPresetList, UnknownPresetError, } from "./workbench/settings-controller.js";
12
+ export { localShellIsolationOptions } from "./workbench/shell-isolation.js";
13
+ export { createWorkbenchTurnController } from "./workbench/turn-controller.js";
14
+ export { createInitialWorkbenchState, createInputHistory, formatTranscript, formatTranscriptPreview, helpText, parsePendingApprovalCommand, parseWorkbenchCommand, workbenchReducer, workdirText, } from "./workbench/state.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agent-api/app-engine",
3
- "version": "0.0.7",
3
+ "version": "0.1.0",
4
4
  "description": "Renderer-neutral application engine for Agent API apps",
5
5
  "license": "MIT",
6
6
  "homepage": "https://github.com/scalebox-dev/agent-tui#readme",
@@ -18,6 +18,18 @@
18
18
  "types": "./dist/index.d.ts",
19
19
  "import": "./dist/index.js"
20
20
  },
21
+ "./core": {
22
+ "types": "./dist/core.d.ts",
23
+ "import": "./dist/core.js"
24
+ },
25
+ "./workbench": {
26
+ "types": "./dist/workbench.d.ts",
27
+ "import": "./dist/workbench.js"
28
+ },
29
+ "./terminal": {
30
+ "types": "./dist/terminal.d.ts",
31
+ "import": "./dist/terminal.js"
32
+ },
21
33
  "./package.json": "./package.json"
22
34
  },
23
35
  "scripts": {