@cortexkit/aft-opencode 0.29.1 → 0.30.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/dist/bg-notifications.d.ts +68 -0
- package/dist/bg-notifications.d.ts.map +1 -1
- package/dist/config.d.ts +3 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4566 -174
- package/dist/shared/pty-cache.d.ts +18 -0
- package/dist/shared/pty-cache.d.ts.map +1 -0
- package/dist/tools/bash.d.ts.map +1 -1
- package/dist/tools/bash_watch.d.ts +24 -0
- package/dist/tools/bash_watch.d.ts.map +1 -0
- package/dist/tools/bash_write.d.ts +38 -0
- package/dist/tools/bash_write.d.ts.map +1 -0
- package/dist/tools/hoisted.d.ts +1 -1
- package/dist/tools/hoisted.d.ts.map +1 -1
- package/dist/tui.js +9 -8
- package/dist/workflow-hints.d.ts.map +1 -1
- package/package.json +9 -8
- package/src/shared/pty-cache.ts +113 -0
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import * as fs from "node:fs/promises";
|
|
2
|
+
import { Terminal } from "@xterm/headless";
|
|
3
|
+
export interface PtyTerminalState {
|
|
4
|
+
terminal: Terminal;
|
|
5
|
+
fileHandle: fs.FileHandle;
|
|
6
|
+
offset: number;
|
|
7
|
+
rows: number;
|
|
8
|
+
cols: number;
|
|
9
|
+
lastAccessMs: number;
|
|
10
|
+
}
|
|
11
|
+
export declare function getOrCreatePtyTerminal(key: string, outputPath: string, rows?: number, cols?: number): Promise<PtyTerminalState>;
|
|
12
|
+
export declare function readPtyBytes(state: PtyTerminalState): Promise<Buffer>;
|
|
13
|
+
export declare function disposePtyTerminal(key: string): Promise<void>;
|
|
14
|
+
export declare function disposeAllPtyTerminals(): Promise<void>;
|
|
15
|
+
export declare function renderScreen(state: PtyTerminalState, rows?: number, cols?: number): string;
|
|
16
|
+
export declare function __resetPtyCacheForTests(): void;
|
|
17
|
+
export declare function __ptyCacheSizeForTests(): number;
|
|
18
|
+
//# sourceMappingURL=pty-cache.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pty-cache.d.ts","sourceRoot":"","sources":["../../src/shared/pty-cache.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,kBAAkB,CAAC;AACvC,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAM3C,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,QAAQ,CAAC;IACnB,UAAU,EAAE,EAAE,CAAC,UAAU,CAAC;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,CAAC;CACtB;AAID,wBAAsB,sBAAsB,CAC1C,GAAG,EAAE,MAAM,EACX,UAAU,EAAE,MAAM,EAClB,IAAI,SAAe,EACnB,IAAI,SAAe,GAClB,OAAO,CAAC,gBAAgB,CAAC,CAuB3B;AAED,wBAAsB,YAAY,CAAC,KAAK,EAAE,gBAAgB,GAAG,OAAO,CAAC,MAAM,CAAC,CAa3E;AAED,wBAAsB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAMnE;AAED,wBAAsB,sBAAsB,IAAI,OAAO,CAAC,IAAI,CAAC,CAE5D;AAED,wBAAgB,YAAY,CAC1B,KAAK,EAAE,gBAAgB,EACvB,IAAI,SAAa,EACjB,IAAI,SAAa,GAChB,MAAM,CAiBR;AAED,wBAAgB,uBAAuB,IAAI,IAAI,CAM9C;AAED,wBAAgB,sBAAsB,IAAI,MAAM,CAE/C"}
|
package/dist/tools/bash.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bash.d.ts","sourceRoot":"","sources":["../../src/tools/bash.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAe,cAAc,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"bash.d.ts","sourceRoot":"","sources":["../../src/tools/bash.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAe,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAavE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AA0EjD,wBAAgB,cAAc,CAAC,GAAG,EAAE,aAAa,GAAG,cAAc,CAmRjE;AAED,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,aAAa,GAAG,cAAc,CAyBvE;AAED,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,aAAa,GAAG,cAAc,CAuBrE"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { ToolContext, ToolDefinition } from "@opencode-ai/plugin";
|
|
2
|
+
import type { PluginContext } from "../types.js";
|
|
3
|
+
export type BashWaitPattern = {
|
|
4
|
+
kind: "substring";
|
|
5
|
+
value: string;
|
|
6
|
+
} | {
|
|
7
|
+
kind: "regex";
|
|
8
|
+
value: RegExp;
|
|
9
|
+
source: string;
|
|
10
|
+
};
|
|
11
|
+
export type BashStatusWaited = {
|
|
12
|
+
reason: "matched" | "exited" | "timeout";
|
|
13
|
+
elapsed_ms: number;
|
|
14
|
+
match?: string;
|
|
15
|
+
match_offset?: number;
|
|
16
|
+
};
|
|
17
|
+
type BashStatusWithWait = Record<string, unknown> & {
|
|
18
|
+
waited?: BashStatusWaited;
|
|
19
|
+
};
|
|
20
|
+
export declare function createBashWatchTool(ctx: PluginContext): ToolDefinition;
|
|
21
|
+
export declare function waitForBashStatus(ctx: PluginContext, runtime: ToolContext, taskId: string, outputMode: string | undefined, waitFor: BashWaitPattern | undefined, effectiveWaitMs: number): Promise<BashStatusWithWait>;
|
|
22
|
+
export declare function parseWaitPattern(value: unknown): BashWaitPattern | undefined;
|
|
23
|
+
export {};
|
|
24
|
+
//# sourceMappingURL=bash_watch.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bash_watch.d.ts","sourceRoot":"","sources":["../../src/tools/bash_watch.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAavE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AASjD,MAAM,MAAM,eAAe,GACvB;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GACpC;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AACrD,MAAM,MAAM,gBAAgB,GAAG;IAC7B,MAAM,EAAE,SAAS,GAAG,QAAQ,GAAG,SAAS,CAAC;IACzC,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,CAAC;AACF,KAAK,kBAAkB,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG;IAAE,MAAM,CAAC,EAAE,gBAAgB,CAAA;CAAE,CAAC;AAElF,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,aAAa,GAAG,cAAc,CA4FtE;AAiDD,wBAAsB,iBAAiB,CACrC,GAAG,EAAE,aAAa,EAClB,OAAO,EAAE,WAAW,EACpB,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,MAAM,GAAG,SAAS,EAC9B,OAAO,EAAE,eAAe,GAAG,SAAS,EACpC,eAAe,EAAE,MAAM,GACtB,OAAO,CAAC,kBAAkB,CAAC,CAmD7B;AAsCD,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,GAAG,eAAe,GAAG,SAAS,CAK5E"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { ToolDefinition } from "@opencode-ai/plugin";
|
|
2
|
+
import type { PluginContext } from "../types.js";
|
|
3
|
+
/**
|
|
4
|
+
* Write bytes to a running PTY background task.
|
|
5
|
+
*
|
|
6
|
+
* Two input shapes:
|
|
7
|
+
*
|
|
8
|
+
* - **String** — verbatim bytes written to the PTY. Use this for plain text
|
|
9
|
+
* such as REPL commands (`"print(1)\n"`) or when the agent specifically
|
|
10
|
+
* wants the literal characters `\u001b` (e.g. writing source code).
|
|
11
|
+
*
|
|
12
|
+
* - **Sequence array** — mix plain strings (text) with `{ key: "<name>" }`
|
|
13
|
+
* objects (named control keys). Items concatenate into one atomic write
|
|
14
|
+
* so the PTY sees the whole sequence as one input chunk. The agent never
|
|
15
|
+
* has to JSON-encode escape characters.
|
|
16
|
+
*
|
|
17
|
+
* Allowed key names: `enter`, `return`, `tab`, `space`, `backspace`,
|
|
18
|
+
* `esc`, `escape`, `up`, `down`, `left`, `right`, `home`, `end`,
|
|
19
|
+
* `page-up`, `page-down`, `delete`, `insert`, `f1`..`f12`,
|
|
20
|
+
* `ctrl-a`..`ctrl-z`. Names are case-insensitive.
|
|
21
|
+
*
|
|
22
|
+
* The vim "type text, exit insert, save and quit" idiom:
|
|
23
|
+
*
|
|
24
|
+
* ```ts
|
|
25
|
+
* bash_write({ taskId, input: [
|
|
26
|
+
* "iHello",
|
|
27
|
+
* { key: "esc" },
|
|
28
|
+
* ":wq",
|
|
29
|
+
* { key: "enter" },
|
|
30
|
+
* ]})
|
|
31
|
+
* ```
|
|
32
|
+
*
|
|
33
|
+
* Rust enforces a 1 MiB maximum on the EXPANDED byte stream. Agents should
|
|
34
|
+
* check `bash_status` first and only call `bash_write` when the task reports
|
|
35
|
+
* `mode: "pty"`.
|
|
36
|
+
*/
|
|
37
|
+
export declare function createBashWriteTool(ctx: PluginContext): ToolDefinition;
|
|
38
|
+
//# sourceMappingURL=bash_write.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bash_write.d.ts","sourceRoot":"","sources":["../../src/tools/bash_write.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAE1D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAKjD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,aAAa,GAAG,cAAc,CA6CtE"}
|
package/dist/tools/hoisted.d.ts
CHANGED
|
@@ -20,7 +20,7 @@ export declare function createReadTool(ctx: PluginContext): ToolDefinition;
|
|
|
20
20
|
* Returns hoisted tools keyed by opencode's built-in names.
|
|
21
21
|
* Overrides: read, write, edit, apply_patch (always when hoisting is on).
|
|
22
22
|
*
|
|
23
|
-
* Bash hoisting is opt-in: `bash`, `bash_status`, and `bash_kill` are
|
|
23
|
+
* Bash hoisting is opt-in: `bash`, `bash_status`, `bash_write`, and `bash_kill` are
|
|
24
24
|
* registered together when at least one `experimental.bash.*` flag is
|
|
25
25
|
* enabled (rewrite, compress, or background). When all flags are off,
|
|
26
26
|
* opencode's native bash stays in place — users without bash experimentals
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hoisted.d.ts","sourceRoot":"","sources":["../../src/tools/hoisted.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAIH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAK1D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"hoisted.d.ts","sourceRoot":"","sources":["../../src/tools/hoisted.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAIH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAK1D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAyEjD,wEAAwE;AACxE,eAAO,MAAM,wBAAwB,GAAI,IAAI,MAAM,EAAE,QAAQ,MAAM,EAAE,OAAO,MAAM,KAAG,MAChD,CAAC;AAqRtC;;GAEG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,aAAa,GAAG,cAAc,CA+JjE;AAmmCD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CA0B/E;AAMD;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CA8FnF"}
|
package/dist/tui.js
CHANGED
|
@@ -3,7 +3,7 @@ import { createMemo as createMemo2, createSignal as createSignal2, onCleanup as
|
|
|
3
3
|
// package.json
|
|
4
4
|
var package_default = {
|
|
5
5
|
name: "@cortexkit/aft-opencode",
|
|
6
|
-
version: "0.
|
|
6
|
+
version: "0.30.0",
|
|
7
7
|
type: "module",
|
|
8
8
|
description: "OpenCode plugin for Agent File Tools (AFT) — tree-sitter and lsp powered code analysis",
|
|
9
9
|
main: "dist/index.js",
|
|
@@ -32,20 +32,21 @@ var package_default = {
|
|
|
32
32
|
},
|
|
33
33
|
dependencies: {
|
|
34
34
|
"@clack/prompts": "^1.2.0",
|
|
35
|
-
"@cortexkit/aft-bridge": "0.
|
|
35
|
+
"@cortexkit/aft-bridge": "0.30.0",
|
|
36
36
|
"@opencode-ai/plugin": "^1.15.5",
|
|
37
37
|
"@opencode-ai/sdk": "^1.15.5",
|
|
38
|
+
"@xterm/headless": "^5.5.0",
|
|
38
39
|
"comment-json": "^4.6.2",
|
|
39
40
|
undici: "^7.25.0",
|
|
40
41
|
zod: "^4.1.8"
|
|
41
42
|
},
|
|
42
43
|
optionalDependencies: {
|
|
43
|
-
"@cortexkit/aft-darwin-arm64": "0.
|
|
44
|
-
"@cortexkit/aft-darwin-x64": "0.
|
|
45
|
-
"@cortexkit/aft-linux-arm64": "0.
|
|
46
|
-
"@cortexkit/aft-linux-x64": "0.
|
|
47
|
-
"@cortexkit/aft-win32-arm64": "0.
|
|
48
|
-
"@cortexkit/aft-win32-x64": "0.
|
|
44
|
+
"@cortexkit/aft-darwin-arm64": "0.30.0",
|
|
45
|
+
"@cortexkit/aft-darwin-x64": "0.30.0",
|
|
46
|
+
"@cortexkit/aft-linux-arm64": "0.30.0",
|
|
47
|
+
"@cortexkit/aft-linux-x64": "0.30.0",
|
|
48
|
+
"@cortexkit/aft-win32-arm64": "0.30.0",
|
|
49
|
+
"@cortexkit/aft-win32-x64": "0.30.0"
|
|
49
50
|
},
|
|
50
51
|
devDependencies: {
|
|
51
52
|
"@types/node": "^22.0.0",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"workflow-hints.d.ts","sourceRoot":"","sources":["../src/workflow-hints.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,KAAK,SAAS,EAAqB,MAAM,aAAa,CAAC;AAEhE,MAAM,WAAW,iBAAiB;IAChC,oEAAoE;IACpE,WAAW,EAAE,SAAS,GAAG,aAAa,GAAG,KAAK,CAAC;IAC/C,4EAA4E;IAC5E,aAAa,EAAE,OAAO,CAAC;IACvB,mEAAmE;IACnE,eAAe,EAAE,OAAO,CAAC;IACzB,wEAAwE;IACxE,qBAAqB,EAAE,OAAO,CAAC;IAC/B,4DAA4D;IAC5D,aAAa,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;CAC5B;AAID;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,iBAAiB,GAAG,MAAM,GAAG,IAAI,
|
|
1
|
+
{"version":3,"file":"workflow-hints.d.ts","sourceRoot":"","sources":["../src/workflow-hints.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,KAAK,SAAS,EAAqB,MAAM,aAAa,CAAC;AAEhE,MAAM,WAAW,iBAAiB;IAChC,oEAAoE;IACpE,WAAW,EAAE,SAAS,GAAG,aAAa,GAAG,KAAK,CAAC;IAC/C,4EAA4E;IAC5E,aAAa,EAAE,OAAO,CAAC;IACvB,mEAAmE;IACnE,eAAe,EAAE,OAAO,CAAC;IACzB,wEAAwE;IACxE,qBAAqB,EAAE,OAAO,CAAC;IAC/B,4DAA4D;IAC5D,aAAa,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;CAC5B;AAID;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,iBAAiB,GAAG,MAAM,GAAG,IAAI,CAuEzE;AAED;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,SAAS,EAAE,aAAa,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,MAAM,GAAG,IAAI,CAQjG"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cortexkit/aft-opencode",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.30.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "OpenCode plugin for Agent File Tools (AFT) — tree-sitter and lsp powered code analysis",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -29,20 +29,21 @@
|
|
|
29
29
|
},
|
|
30
30
|
"dependencies": {
|
|
31
31
|
"@clack/prompts": "^1.2.0",
|
|
32
|
-
"@cortexkit/aft-bridge": "0.
|
|
32
|
+
"@cortexkit/aft-bridge": "0.30.0",
|
|
33
33
|
"@opencode-ai/plugin": "^1.15.5",
|
|
34
34
|
"@opencode-ai/sdk": "^1.15.5",
|
|
35
|
+
"@xterm/headless": "^5.5.0",
|
|
35
36
|
"comment-json": "^4.6.2",
|
|
36
37
|
"undici": "^7.25.0",
|
|
37
38
|
"zod": "^4.1.8"
|
|
38
39
|
},
|
|
39
40
|
"optionalDependencies": {
|
|
40
|
-
"@cortexkit/aft-darwin-arm64": "0.
|
|
41
|
-
"@cortexkit/aft-darwin-x64": "0.
|
|
42
|
-
"@cortexkit/aft-linux-arm64": "0.
|
|
43
|
-
"@cortexkit/aft-linux-x64": "0.
|
|
44
|
-
"@cortexkit/aft-win32-arm64": "0.
|
|
45
|
-
"@cortexkit/aft-win32-x64": "0.
|
|
41
|
+
"@cortexkit/aft-darwin-arm64": "0.30.0",
|
|
42
|
+
"@cortexkit/aft-darwin-x64": "0.30.0",
|
|
43
|
+
"@cortexkit/aft-linux-arm64": "0.30.0",
|
|
44
|
+
"@cortexkit/aft-linux-x64": "0.30.0",
|
|
45
|
+
"@cortexkit/aft-win32-arm64": "0.30.0",
|
|
46
|
+
"@cortexkit/aft-win32-x64": "0.30.0"
|
|
46
47
|
},
|
|
47
48
|
"devDependencies": {
|
|
48
49
|
"@types/node": "^22.0.0",
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import * as fs from "node:fs/promises";
|
|
2
|
+
import { Terminal } from "@xterm/headless";
|
|
3
|
+
|
|
4
|
+
const DEFAULT_COLS = 80;
|
|
5
|
+
const DEFAULT_ROWS = 24;
|
|
6
|
+
const READ_CHUNK_SIZE = 64 * 1024;
|
|
7
|
+
|
|
8
|
+
export interface PtyTerminalState {
|
|
9
|
+
terminal: Terminal;
|
|
10
|
+
fileHandle: fs.FileHandle;
|
|
11
|
+
offset: number;
|
|
12
|
+
rows: number;
|
|
13
|
+
cols: number;
|
|
14
|
+
lastAccessMs: number;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const terminals = new Map<string, PtyTerminalState>();
|
|
18
|
+
|
|
19
|
+
export async function getOrCreatePtyTerminal(
|
|
20
|
+
key: string,
|
|
21
|
+
outputPath: string,
|
|
22
|
+
rows = DEFAULT_ROWS,
|
|
23
|
+
cols = DEFAULT_COLS,
|
|
24
|
+
): Promise<PtyTerminalState> {
|
|
25
|
+
const existing = terminals.get(key);
|
|
26
|
+
if (existing) {
|
|
27
|
+
existing.lastAccessMs = Date.now();
|
|
28
|
+
if (existing.rows === rows && existing.cols === cols) {
|
|
29
|
+
return existing;
|
|
30
|
+
}
|
|
31
|
+
terminals.delete(key);
|
|
32
|
+
existing.terminal.dispose();
|
|
33
|
+
await existing.fileHandle.close().catch(() => undefined);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const fileHandle = await fs.open(outputPath, "r");
|
|
37
|
+
const state: PtyTerminalState = {
|
|
38
|
+
terminal: new Terminal({ cols, rows, allowProposedApi: true }),
|
|
39
|
+
fileHandle,
|
|
40
|
+
offset: 0,
|
|
41
|
+
rows,
|
|
42
|
+
cols,
|
|
43
|
+
lastAccessMs: Date.now(),
|
|
44
|
+
};
|
|
45
|
+
terminals.set(key, state);
|
|
46
|
+
return state;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export async function readPtyBytes(state: PtyTerminalState): Promise<Buffer> {
|
|
50
|
+
const chunks: Buffer[] = [];
|
|
51
|
+
while (true) {
|
|
52
|
+
const buffer = Buffer.allocUnsafe(READ_CHUNK_SIZE);
|
|
53
|
+
const { bytesRead } = await state.fileHandle.read(buffer, 0, buffer.length, state.offset);
|
|
54
|
+
if (bytesRead === 0) break;
|
|
55
|
+
const chunk = buffer.subarray(0, bytesRead);
|
|
56
|
+
chunks.push(Buffer.from(chunk));
|
|
57
|
+
await writeTerminal(state.terminal, chunk);
|
|
58
|
+
state.offset += bytesRead;
|
|
59
|
+
}
|
|
60
|
+
state.lastAccessMs = Date.now();
|
|
61
|
+
return Buffer.concat(chunks);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export async function disposePtyTerminal(key: string): Promise<void> {
|
|
65
|
+
const state = terminals.get(key);
|
|
66
|
+
if (!state) return;
|
|
67
|
+
terminals.delete(key);
|
|
68
|
+
state.terminal.dispose();
|
|
69
|
+
await state.fileHandle.close().catch(() => undefined);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export async function disposeAllPtyTerminals(): Promise<void> {
|
|
73
|
+
await Promise.all([...terminals.keys()].map((key) => disposePtyTerminal(key)));
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export function renderScreen(
|
|
77
|
+
state: PtyTerminalState,
|
|
78
|
+
rows = state.rows,
|
|
79
|
+
cols = state.cols,
|
|
80
|
+
): string {
|
|
81
|
+
const active = state.terminal.buffer.active;
|
|
82
|
+
const lines: string[] = [];
|
|
83
|
+
for (let y = 0; y < rows; y++) {
|
|
84
|
+
const line = active.getLine(active.baseY + y);
|
|
85
|
+
if (!line) {
|
|
86
|
+
lines.push("");
|
|
87
|
+
continue;
|
|
88
|
+
}
|
|
89
|
+
let text = "";
|
|
90
|
+
for (let x = 0; x < cols; x++) {
|
|
91
|
+
text += line.getCell(x)?.getChars() || " ";
|
|
92
|
+
}
|
|
93
|
+
lines.push(text.trimEnd());
|
|
94
|
+
}
|
|
95
|
+
while (lines.length > 0 && lines[lines.length - 1] === "") lines.pop();
|
|
96
|
+
return lines.join("\n");
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
export function __resetPtyCacheForTests(): void {
|
|
100
|
+
for (const state of terminals.values()) {
|
|
101
|
+
state.terminal.dispose();
|
|
102
|
+
void state.fileHandle.close().catch(() => undefined);
|
|
103
|
+
}
|
|
104
|
+
terminals.clear();
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
export function __ptyCacheSizeForTests(): number {
|
|
108
|
+
return terminals.size;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function writeTerminal(terminal: Terminal, data: Uint8Array): Promise<void> {
|
|
112
|
+
return new Promise((resolve) => terminal.write(data, resolve));
|
|
113
|
+
}
|