@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.
- package/README.md +46 -0
- package/dist/agent/runner.d.ts +117 -0
- package/dist/agent/runner.js +486 -0
- package/dist/agent.d.ts +2 -0
- package/dist/agent.js +2 -0
- package/dist/chat-options.d.ts +37 -0
- package/dist/chat-options.js +42 -0
- package/dist/config.d.ts +66 -0
- package/dist/config.js +201 -0
- package/dist/conversation/index.d.ts +17 -0
- package/dist/conversation/index.js +54 -0
- package/dist/engine/agent-engine.d.ts +38 -0
- package/dist/engine/agent-engine.js +146 -0
- package/dist/engine/index.d.ts +50 -0
- package/dist/engine/index.js +26 -0
- package/dist/engine/services.d.ts +20 -0
- package/dist/engine/services.js +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/profile.d.ts +57 -0
- package/dist/profile.js +211 -0
- package/dist/runtime/index.d.ts +23 -0
- package/dist/runtime/index.js +177 -0
- package/dist/update.d.ts +16 -0
- package/dist/update.js +74 -0
- package/dist/workbench/auth-controller.d.ts +43 -0
- package/dist/workbench/auth-controller.js +84 -0
- package/dist/workbench/auth-gate-controller.d.ts +62 -0
- package/dist/workbench/auth-gate-controller.js +231 -0
- package/dist/workbench/command-controller.d.ts +29 -0
- package/dist/workbench/command-controller.js +426 -0
- package/dist/workbench/conversation-controller.d.ts +32 -0
- package/dist/workbench/conversation-controller.js +53 -0
- package/dist/workbench/engine.d.ts +66 -0
- package/dist/workbench/engine.js +291 -0
- package/dist/workbench/input-controller.d.ts +44 -0
- package/dist/workbench/input-controller.js +71 -0
- package/dist/workbench/isolator-installer.d.ts +29 -0
- package/dist/workbench/isolator-installer.js +208 -0
- package/dist/workbench/lifecycle-controller.d.ts +30 -0
- package/dist/workbench/lifecycle-controller.js +75 -0
- package/dist/workbench/local-controller.d.ts +21 -0
- package/dist/workbench/local-controller.js +94 -0
- package/dist/workbench/render-model.d.ts +46 -0
- package/dist/workbench/render-model.js +61 -0
- package/dist/workbench/runtime-controller.d.ts +12 -0
- package/dist/workbench/runtime-controller.js +57 -0
- package/dist/workbench/session.d.ts +29 -0
- package/dist/workbench/session.js +42 -0
- package/dist/workbench/settings-controller.d.ts +80 -0
- package/dist/workbench/settings-controller.js +309 -0
- package/dist/workbench/shell-isolation.d.ts +20 -0
- package/dist/workbench/shell-isolation.js +13 -0
- package/dist/workbench/state.d.ts +187 -0
- package/dist/workbench/state.js +392 -0
- package/dist/workbench/turn-controller.d.ts +25 -0
- package/dist/workbench/turn-controller.js +164 -0
- package/dist/workbench/view-model.d.ts +34 -0
- package/dist/workbench/view-model.js +121 -0
- package/dist/workdir/index.d.ts +22 -0
- package/dist/workdir/index.js +46 -0
- package/package.json +50 -0
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
export function buildTranscriptViewModel(input) {
|
|
2
|
+
const lines = buildTranscriptLines(input.messages, {
|
|
3
|
+
activeAssistantMessageId: input.activeAssistantMessageId,
|
|
4
|
+
busy: input.busy,
|
|
5
|
+
renderMode: input.renderMode,
|
|
6
|
+
spinnerFrame: input.spinnerFrame,
|
|
7
|
+
width: input.width,
|
|
8
|
+
});
|
|
9
|
+
const maxOffset = Math.max(0, lines.length - input.viewportHeight);
|
|
10
|
+
const offset = Math.min(input.offset, maxOffset);
|
|
11
|
+
const start = Math.max(0, lines.length - input.viewportHeight - offset);
|
|
12
|
+
return {
|
|
13
|
+
lines,
|
|
14
|
+
visibleLines: lines.slice(start, start + input.viewportHeight),
|
|
15
|
+
maxOffset,
|
|
16
|
+
offset,
|
|
17
|
+
viewportHeight: input.viewportHeight,
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
export function buildTranscriptLines(messages, options) {
|
|
21
|
+
const lines = [];
|
|
22
|
+
for (const message of messages) {
|
|
23
|
+
const waiting = message.role === "assistant" && options.busy && message.id === options.activeAssistantMessageId && !message.text;
|
|
24
|
+
lines.push({
|
|
25
|
+
id: `${message.id}:role`,
|
|
26
|
+
text: roleLabel(message.role),
|
|
27
|
+
color: roleColor(message.role),
|
|
28
|
+
});
|
|
29
|
+
const content = message.text || (waiting ? `${spinnerGlyph(options.spinnerFrame)} thinking ${elapsedDots(options.spinnerFrame)}` : "");
|
|
30
|
+
const rendered = options.renderMode === "raw"
|
|
31
|
+
? rawTranscriptLines(content, options.width)
|
|
32
|
+
: markdownTranscriptLines(content, options.width);
|
|
33
|
+
rendered.forEach((line, index) => {
|
|
34
|
+
lines.push({
|
|
35
|
+
...line,
|
|
36
|
+
id: `${message.id}:line:${index}`,
|
|
37
|
+
});
|
|
38
|
+
});
|
|
39
|
+
if (message.role !== "system") {
|
|
40
|
+
lines.push({ id: `${message.id}:space`, text: "" });
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
return lines;
|
|
44
|
+
}
|
|
45
|
+
export function spinnerGlyph(frame) {
|
|
46
|
+
return ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"][frame % 10];
|
|
47
|
+
}
|
|
48
|
+
export function elapsedDots(frame) {
|
|
49
|
+
return ".".repeat((Math.floor(frame / 4) % 3) + 1);
|
|
50
|
+
}
|
|
51
|
+
function rawTranscriptLines(text, width) {
|
|
52
|
+
const source = text ? text.split(/\r?\n/) : [""];
|
|
53
|
+
return source.flatMap((line) => wrapTranscriptText(line, width).map((text) => ({ text })));
|
|
54
|
+
}
|
|
55
|
+
function markdownTranscriptLines(text, width) {
|
|
56
|
+
const source = text ? text.split(/\r?\n/) : [""];
|
|
57
|
+
const lines = [];
|
|
58
|
+
let inCode = false;
|
|
59
|
+
for (const sourceLine of source) {
|
|
60
|
+
if (/^\s*```/.test(sourceLine)) {
|
|
61
|
+
inCode = !inCode;
|
|
62
|
+
lines.push(...wrapTranscriptText(sourceLine, width).map((line) => ({ text: line, color: "gray" })));
|
|
63
|
+
continue;
|
|
64
|
+
}
|
|
65
|
+
lines.push(...markdownTranscriptLine(sourceLine, { code: inCode, width }));
|
|
66
|
+
}
|
|
67
|
+
return lines;
|
|
68
|
+
}
|
|
69
|
+
function markdownTranscriptLine(line, options) {
|
|
70
|
+
if (line === "")
|
|
71
|
+
return [{ text: "" }];
|
|
72
|
+
if (options.code)
|
|
73
|
+
return wrapTranscriptText(line, options.width).map((text) => ({ text, color: "gray" }));
|
|
74
|
+
const heading = /^(#{1,6})\s+(.+)$/.exec(line);
|
|
75
|
+
if (heading) {
|
|
76
|
+
const color = heading[1].length <= 2 ? "cyan" : "blue";
|
|
77
|
+
return wrapTranscriptText(heading[2], options.width).map((text) => ({ text, bold: true, color }));
|
|
78
|
+
}
|
|
79
|
+
if (/^\s*---+\s*$/.test(line))
|
|
80
|
+
return [{ text: "─".repeat(Math.min(48, options.width)), color: "gray" }];
|
|
81
|
+
const bullet = /^(\s*)[-*]\s+(.+)$/.exec(line);
|
|
82
|
+
if (bullet)
|
|
83
|
+
return wrapTranscriptText(`${bullet[1]}• ${bullet[2]}`, options.width).map((text) => ({ text }));
|
|
84
|
+
const numbered = /^(\s*)(\d+\.)\s+(.+)$/.exec(line);
|
|
85
|
+
if (numbered)
|
|
86
|
+
return wrapTranscriptText(`${numbered[1]}${numbered[2]} ${numbered[3]}`, options.width).map((text) => ({ text }));
|
|
87
|
+
const quote = /^\s*>\s?(.+)$/.exec(line);
|
|
88
|
+
if (quote)
|
|
89
|
+
return wrapTranscriptText(`│ ${quote[1]}`, options.width).map((text) => ({ text, color: "gray" }));
|
|
90
|
+
return wrapTranscriptText(line, options.width).map((text) => ({ text }));
|
|
91
|
+
}
|
|
92
|
+
function wrapTranscriptText(text, width) {
|
|
93
|
+
const max = Math.max(12, width);
|
|
94
|
+
if (text.length === 0)
|
|
95
|
+
return [""];
|
|
96
|
+
const lines = [];
|
|
97
|
+
let rest = text;
|
|
98
|
+
while (rest.length > max) {
|
|
99
|
+
const hard = rest.slice(0, max);
|
|
100
|
+
const softBreak = Math.max(hard.lastIndexOf(" "), hard.lastIndexOf("\t"));
|
|
101
|
+
const index = softBreak > Math.floor(max * 0.45) ? softBreak : max;
|
|
102
|
+
lines.push(rest.slice(0, index).trimEnd());
|
|
103
|
+
rest = rest.slice(index).trimStart();
|
|
104
|
+
}
|
|
105
|
+
lines.push(rest);
|
|
106
|
+
return lines;
|
|
107
|
+
}
|
|
108
|
+
function roleLabel(role) {
|
|
109
|
+
if (role === "user")
|
|
110
|
+
return "You";
|
|
111
|
+
if (role === "assistant")
|
|
112
|
+
return "Agent";
|
|
113
|
+
return "System";
|
|
114
|
+
}
|
|
115
|
+
function roleColor(role) {
|
|
116
|
+
if (role === "user")
|
|
117
|
+
return "green";
|
|
118
|
+
if (role === "assistant")
|
|
119
|
+
return "cyan";
|
|
120
|
+
return "gray";
|
|
121
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { type LocalContextManifest, type LocalSummary, type LocalWorkdir, type LocalWorkdirSnapshot } from "@agent-api/sdk/local";
|
|
2
|
+
export interface WorkdirOptions {
|
|
3
|
+
path?: string;
|
|
4
|
+
name?: string;
|
|
5
|
+
}
|
|
6
|
+
export interface WorkdirContextOptions extends WorkdirOptions {
|
|
7
|
+
query?: string;
|
|
8
|
+
maxFiles?: number;
|
|
9
|
+
maxBytes?: number;
|
|
10
|
+
includeContent?: boolean;
|
|
11
|
+
}
|
|
12
|
+
export interface WorkdirService {
|
|
13
|
+
root: string;
|
|
14
|
+
name: string;
|
|
15
|
+
workdir: LocalWorkdir;
|
|
16
|
+
summarize(): Promise<LocalSummary>;
|
|
17
|
+
snapshot(): Promise<LocalWorkdirSnapshot>;
|
|
18
|
+
packageContext(options?: Omit<WorkdirContextOptions, "path" | "name">): Promise<LocalContextManifest>;
|
|
19
|
+
contextBlock(options?: Omit<WorkdirContextOptions, "path" | "name">): Promise<string>;
|
|
20
|
+
}
|
|
21
|
+
export declare function openWorkdir(options?: WorkdirOptions): Promise<WorkdirService>;
|
|
22
|
+
export declare function buildWorkdirContextBlock(options: WorkdirContextOptions): Promise<string>;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { createLocalContextPackage, } from "@agent-api/sdk/local";
|
|
2
|
+
import { resolve } from "node:path";
|
|
3
|
+
import { runtime } from "../runtime/index.js";
|
|
4
|
+
export async function openWorkdir(options = {}) {
|
|
5
|
+
await runtime.ensure();
|
|
6
|
+
const root = resolve(options.path || process.cwd());
|
|
7
|
+
const name = options.name || root.split(/[\\/]/).filter(Boolean).at(-1) || "workdir";
|
|
8
|
+
const workdir = runtime.workdir(root, {
|
|
9
|
+
name,
|
|
10
|
+
trusted: true,
|
|
11
|
+
gitignore: true,
|
|
12
|
+
});
|
|
13
|
+
return {
|
|
14
|
+
root,
|
|
15
|
+
name,
|
|
16
|
+
workdir,
|
|
17
|
+
summarize: () => workdir.summarize(),
|
|
18
|
+
snapshot: () => workdir.snapshot({ hash: true }),
|
|
19
|
+
packageContext: (contextOptions = {}) => createLocalContextPackage(workdir, {
|
|
20
|
+
query: contextOptions.query,
|
|
21
|
+
includeSearch: Boolean(contextOptions.query),
|
|
22
|
+
maxFiles: contextOptions.maxFiles,
|
|
23
|
+
maxBytes: contextOptions.maxBytes,
|
|
24
|
+
includeContent: contextOptions.includeContent,
|
|
25
|
+
}),
|
|
26
|
+
contextBlock: async (contextOptions = {}) => {
|
|
27
|
+
const context = await createLocalContextPackage(workdir, {
|
|
28
|
+
query: contextOptions.query,
|
|
29
|
+
includeSearch: Boolean(contextOptions.query),
|
|
30
|
+
maxFiles: contextOptions.maxFiles,
|
|
31
|
+
maxBytes: contextOptions.maxBytes,
|
|
32
|
+
includeContent: contextOptions.includeContent,
|
|
33
|
+
});
|
|
34
|
+
return [
|
|
35
|
+
"Local workdir context follows. Use it as user-provided project context; do not assume files outside this manifest exist.",
|
|
36
|
+
"```json",
|
|
37
|
+
JSON.stringify(context, null, 2),
|
|
38
|
+
"```",
|
|
39
|
+
].join("\n");
|
|
40
|
+
},
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
export async function buildWorkdirContextBlock(options) {
|
|
44
|
+
const service = await openWorkdir(options);
|
|
45
|
+
return service.contextBlock(options);
|
|
46
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@agent-api/app-engine",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "Renderer-neutral application engine for Agent API apps",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"homepage": "https://github.com/scalebox-dev/agent-tui#readme",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/scalebox-dev/agent-tui.git",
|
|
10
|
+
"directory": "packages/app-engine"
|
|
11
|
+
},
|
|
12
|
+
"bugs": {
|
|
13
|
+
"url": "https://github.com/scalebox-dev/agent-tui/issues"
|
|
14
|
+
},
|
|
15
|
+
"type": "module",
|
|
16
|
+
"exports": {
|
|
17
|
+
".": {
|
|
18
|
+
"types": "./dist/index.d.ts",
|
|
19
|
+
"import": "./dist/index.js"
|
|
20
|
+
},
|
|
21
|
+
"./package.json": "./package.json"
|
|
22
|
+
},
|
|
23
|
+
"scripts": {
|
|
24
|
+
"clean": "node -e \"require('node:fs').rmSync('dist',{recursive:true,force:true})\"",
|
|
25
|
+
"build": "npm run clean && tsc -p tsconfig.json",
|
|
26
|
+
"smoke": "node test/smoke.mjs",
|
|
27
|
+
"test": "npm run build && npm run smoke",
|
|
28
|
+
"prepack": "npm run build",
|
|
29
|
+
"pack:local": "npm pack --pack-destination ./artifacts"
|
|
30
|
+
},
|
|
31
|
+
"dependencies": {
|
|
32
|
+
"@agent-api/sdk": "^1.3.0",
|
|
33
|
+
"zod": "^4.4.3"
|
|
34
|
+
},
|
|
35
|
+
"devDependencies": {
|
|
36
|
+
"@types/node": "^24.0.0",
|
|
37
|
+
"typescript": "^5.0.0"
|
|
38
|
+
},
|
|
39
|
+
"engines": {
|
|
40
|
+
"node": ">=20"
|
|
41
|
+
},
|
|
42
|
+
"files": [
|
|
43
|
+
"dist",
|
|
44
|
+
"README.md",
|
|
45
|
+
"package.json"
|
|
46
|
+
],
|
|
47
|
+
"publishConfig": {
|
|
48
|
+
"access": "public"
|
|
49
|
+
}
|
|
50
|
+
}
|