@termfleet/core 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/dist/agent-launch.d.ts +78 -0
- package/dist/agent-launch.js +247 -0
- package/dist/agent-session-id.d.ts +10 -0
- package/dist/agent-session-id.js +36 -0
- package/dist/agent-session-index-client.d.ts +7 -0
- package/dist/agent-session-index-client.js +86 -0
- package/dist/agent-session-index-worker.d.ts +1 -0
- package/dist/agent-session-index-worker.js +20 -0
- package/dist/agent-session-index.d.ts +34 -0
- package/dist/agent-session-index.js +527 -0
- package/dist/agent-session-tail.d.ts +33 -0
- package/dist/agent-session-tail.js +184 -0
- package/dist/agent-session-watcher.d.ts +36 -0
- package/dist/agent-session-watcher.js +194 -0
- package/dist/agent-session.d.ts +380 -0
- package/dist/agent-session.js +1688 -0
- package/dist/background-runner.d.ts +3 -0
- package/dist/background-runner.js +55 -0
- package/dist/boot-queue.d.ts +35 -0
- package/dist/boot-queue.js +66 -0
- package/dist/build-info.d.ts +5 -0
- package/dist/build-info.js +38 -0
- package/dist/collab/canvas-doc.d.ts +47 -0
- package/dist/collab/canvas-doc.js +83 -0
- package/dist/contracts/auth.d.ts +77 -0
- package/dist/contracts/auth.js +1 -0
- package/dist/contracts/canvas.d.ts +34 -0
- package/dist/contracts/canvas.js +76 -0
- package/dist/contracts/console-layout.d.ts +39 -0
- package/dist/contracts/console-layout.js +135 -0
- package/dist/contracts/files.d.ts +38 -0
- package/dist/contracts/files.js +37 -0
- package/dist/contracts/provider-url.d.ts +3 -0
- package/dist/contracts/provider-url.js +49 -0
- package/dist/contracts/registry.d.ts +58 -0
- package/dist/contracts/registry.js +285 -0
- package/dist/launch-trace.d.ts +6 -0
- package/dist/launch-trace.js +33 -0
- package/dist/lib/errors.d.ts +1 -0
- package/dist/lib/errors.js +5 -0
- package/dist/lib/exec.d.ts +13 -0
- package/dist/lib/exec.js +134 -0
- package/dist/local-providers.d.ts +32 -0
- package/dist/local-providers.js +184 -0
- package/dist/local-tunnel.d.ts +6 -0
- package/dist/local-tunnel.js +258 -0
- package/dist/provider-access-token.d.ts +11 -0
- package/dist/provider-access-token.js +77 -0
- package/dist/provider-client.d.ts +152 -0
- package/dist/provider-client.js +666 -0
- package/dist/provider-url-resolver.d.ts +16 -0
- package/dist/provider-url-resolver.js +37 -0
- package/dist/registry-client.d.ts +93 -0
- package/dist/registry-client.js +170 -0
- package/dist/registry.d.ts +56 -0
- package/dist/registry.js +406 -0
- package/dist/session-attention.d.ts +24 -0
- package/dist/session-attention.js +54 -0
- package/dist/session-lifecycle.d.ts +83 -0
- package/dist/session-lifecycle.js +658 -0
- package/dist/session-window.d.ts +3 -0
- package/dist/session-window.js +20 -0
- package/dist/terminal-client.d.ts +49 -0
- package/dist/terminal-client.js +89 -0
- package/dist/types.d.ts +155 -0
- package/dist/types.js +21 -0
- package/package.json +26 -0
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { type ProviderUrlResolver } from "./provider-url-resolver.js";
|
|
2
|
+
export type TerminalHelloMessage = {
|
|
3
|
+
type: "hello";
|
|
4
|
+
cols: number;
|
|
5
|
+
rows: number;
|
|
6
|
+
};
|
|
7
|
+
export type TerminalOutputMessage = {
|
|
8
|
+
type: "output";
|
|
9
|
+
data: string;
|
|
10
|
+
};
|
|
11
|
+
export type TerminalExitMessage = {
|
|
12
|
+
type: "exit";
|
|
13
|
+
exitCode: number;
|
|
14
|
+
signal?: number;
|
|
15
|
+
};
|
|
16
|
+
export type TerminalErrorMessage = {
|
|
17
|
+
type: "error";
|
|
18
|
+
message: string;
|
|
19
|
+
};
|
|
20
|
+
export type TerminalInputRejectedMessage = {
|
|
21
|
+
type: "input-rejected";
|
|
22
|
+
message: string;
|
|
23
|
+
};
|
|
24
|
+
export type TerminalMessage = TerminalHelloMessage | TerminalOutputMessage | TerminalExitMessage | TerminalErrorMessage | TerminalInputRejectedMessage;
|
|
25
|
+
export type TerminalClientOptions = {
|
|
26
|
+
authToken?: () => string | undefined;
|
|
27
|
+
baseUrl: string;
|
|
28
|
+
cols: number;
|
|
29
|
+
rows: number;
|
|
30
|
+
terminalId: string;
|
|
31
|
+
urlResolver?: ProviderUrlResolver;
|
|
32
|
+
};
|
|
33
|
+
export declare class TerminalClient {
|
|
34
|
+
readonly cols: number;
|
|
35
|
+
readonly rows: number;
|
|
36
|
+
readonly terminalId: string;
|
|
37
|
+
private readonly authToken?;
|
|
38
|
+
private socket?;
|
|
39
|
+
private readonly baseUrl;
|
|
40
|
+
private readonly urls;
|
|
41
|
+
constructor({ authToken, baseUrl, cols, rows, terminalId, urlResolver }: TerminalClientOptions);
|
|
42
|
+
connect(): WebSocket;
|
|
43
|
+
write(data: string): void;
|
|
44
|
+
close(): void;
|
|
45
|
+
parse(raw: string): TerminalMessage;
|
|
46
|
+
private requireOpenSocket;
|
|
47
|
+
private url;
|
|
48
|
+
}
|
|
49
|
+
export declare function webSocketBaseUrl(baseUrl: string): string;
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { directProviderUrlResolver } from "./provider-url-resolver.js";
|
|
2
|
+
export class TerminalClient {
|
|
3
|
+
cols;
|
|
4
|
+
rows;
|
|
5
|
+
terminalId;
|
|
6
|
+
authToken;
|
|
7
|
+
socket;
|
|
8
|
+
baseUrl;
|
|
9
|
+
urls;
|
|
10
|
+
constructor({ authToken, baseUrl, cols, rows, terminalId, urlResolver }) {
|
|
11
|
+
this.authToken = authToken;
|
|
12
|
+
this.baseUrl = baseUrl;
|
|
13
|
+
this.cols = cols;
|
|
14
|
+
this.rows = rows;
|
|
15
|
+
this.terminalId = terminalId;
|
|
16
|
+
this.urls = urlResolver ?? directProviderUrlResolver;
|
|
17
|
+
}
|
|
18
|
+
connect() {
|
|
19
|
+
if (this.socket && this.socket.readyState !== WebSocket.CLOSED && this.socket.readyState !== WebSocket.CLOSING) {
|
|
20
|
+
return this.socket;
|
|
21
|
+
}
|
|
22
|
+
this.socket = new WebSocket(this.url());
|
|
23
|
+
return this.socket;
|
|
24
|
+
}
|
|
25
|
+
write(data) {
|
|
26
|
+
const socket = this.requireOpenSocket();
|
|
27
|
+
socket.send(JSON.stringify({ data, type: "input" }));
|
|
28
|
+
}
|
|
29
|
+
close() {
|
|
30
|
+
this.socket?.close();
|
|
31
|
+
}
|
|
32
|
+
parse(raw) {
|
|
33
|
+
const message = JSON.parse(raw);
|
|
34
|
+
if (message.type === "hello") {
|
|
35
|
+
const cols = message.cols;
|
|
36
|
+
const rows = message.rows;
|
|
37
|
+
if (cols === undefined || rows === undefined || !Number.isInteger(cols) || !Number.isInteger(rows)) {
|
|
38
|
+
throw new Error(`Hello message for ${this.terminalId} did not include cols and rows.`);
|
|
39
|
+
}
|
|
40
|
+
return { cols, rows, type: "hello" };
|
|
41
|
+
}
|
|
42
|
+
if (message.type === "output") {
|
|
43
|
+
if (typeof message.data !== "string") {
|
|
44
|
+
throw new Error(`Output message for ${this.terminalId} did not include data.`);
|
|
45
|
+
}
|
|
46
|
+
return { data: message.data, type: "output" };
|
|
47
|
+
}
|
|
48
|
+
if (message.type === "exit") {
|
|
49
|
+
const exitCode = message.exitCode;
|
|
50
|
+
if (exitCode === undefined || !Number.isInteger(exitCode)) {
|
|
51
|
+
throw new Error(`Exit message for ${this.terminalId} did not include an exit code.`);
|
|
52
|
+
}
|
|
53
|
+
return { exitCode, signal: message.signal, type: "exit" };
|
|
54
|
+
}
|
|
55
|
+
if (message.type === "error") {
|
|
56
|
+
return { message: message.message ?? `WebSocket error for ${this.terminalId}.`, type: "error" };
|
|
57
|
+
}
|
|
58
|
+
if (message.type === "input-rejected") {
|
|
59
|
+
return { message: message.message ?? `Input rejected for ${this.terminalId}.`, type: "input-rejected" };
|
|
60
|
+
}
|
|
61
|
+
throw new Error(`Unsupported message type: ${String(message.type)}`);
|
|
62
|
+
}
|
|
63
|
+
requireOpenSocket() {
|
|
64
|
+
const socket = this.socket;
|
|
65
|
+
if (!socket || socket.readyState !== WebSocket.OPEN) {
|
|
66
|
+
throw new Error(`Terminal socket for ${this.terminalId} is not open.`);
|
|
67
|
+
}
|
|
68
|
+
return socket;
|
|
69
|
+
}
|
|
70
|
+
url() {
|
|
71
|
+
const url = new URL(`${this.urls.wsBase(this.baseUrl)}/ws`);
|
|
72
|
+
url.searchParams.set("terminalId", this.terminalId);
|
|
73
|
+
url.searchParams.set("cols", String(this.cols));
|
|
74
|
+
url.searchParams.set("rows", String(this.rows));
|
|
75
|
+
const token = this.authToken?.();
|
|
76
|
+
if (token) {
|
|
77
|
+
url.searchParams.set("token", token);
|
|
78
|
+
}
|
|
79
|
+
for (const [name, value] of Object.entries(this.urls.wsAuthQuery())) {
|
|
80
|
+
url.searchParams.set(name, value);
|
|
81
|
+
}
|
|
82
|
+
return url.href;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
export function webSocketBaseUrl(baseUrl) {
|
|
86
|
+
const url = new URL(baseUrl);
|
|
87
|
+
url.protocol = url.protocol === "https:" ? "wss:" : "ws:";
|
|
88
|
+
return url.origin;
|
|
89
|
+
}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
import type { LifecycleSnapshot, PaneLifecycle } from "./session-lifecycle.js";
|
|
2
|
+
export type Bounds = {
|
|
3
|
+
left: number;
|
|
4
|
+
top: number;
|
|
5
|
+
right: number;
|
|
6
|
+
bottom: number;
|
|
7
|
+
width: number;
|
|
8
|
+
height: number;
|
|
9
|
+
};
|
|
10
|
+
export type TerminalArea = {
|
|
11
|
+
left: number;
|
|
12
|
+
top: number;
|
|
13
|
+
width: number;
|
|
14
|
+
height: number;
|
|
15
|
+
};
|
|
16
|
+
export type TerminalSize = {
|
|
17
|
+
columns: number;
|
|
18
|
+
rows: number;
|
|
19
|
+
};
|
|
20
|
+
export type ChromeRect = {
|
|
21
|
+
left: number;
|
|
22
|
+
top: number;
|
|
23
|
+
width: number;
|
|
24
|
+
height: number;
|
|
25
|
+
};
|
|
26
|
+
export type WindowChrome = {
|
|
27
|
+
id: number;
|
|
28
|
+
title: string;
|
|
29
|
+
titlebar: ChromeRect;
|
|
30
|
+
closeButton: ChromeRect;
|
|
31
|
+
minimizeButton: ChromeRect;
|
|
32
|
+
fullscreenButton: ChromeRect;
|
|
33
|
+
terminalViewport: ChromeRect;
|
|
34
|
+
textArea: TerminalArea;
|
|
35
|
+
scrollbar: ChromeRect;
|
|
36
|
+
};
|
|
37
|
+
export type ProviderWindow = {
|
|
38
|
+
id: number;
|
|
39
|
+
name: string;
|
|
40
|
+
displayId?: string;
|
|
41
|
+
folder?: {
|
|
42
|
+
filesystemId?: string;
|
|
43
|
+
path: string;
|
|
44
|
+
};
|
|
45
|
+
file?: {
|
|
46
|
+
filesystemId?: string;
|
|
47
|
+
path: string;
|
|
48
|
+
terminalId: string;
|
|
49
|
+
};
|
|
50
|
+
iframe?: {
|
|
51
|
+
resolvedSrc?: string;
|
|
52
|
+
src: string;
|
|
53
|
+
};
|
|
54
|
+
filesystemId?: string;
|
|
55
|
+
provider?: string;
|
|
56
|
+
terminalId?: string;
|
|
57
|
+
terminalBackend?: "tmux" | "iterm";
|
|
58
|
+
managed?: boolean;
|
|
59
|
+
windowKind?: "terminal" | "folder" | "file" | "iframe";
|
|
60
|
+
bounds: Bounds;
|
|
61
|
+
chrome: WindowChrome;
|
|
62
|
+
terminalArea: TerminalArea;
|
|
63
|
+
terminalSize: TerminalSize;
|
|
64
|
+
contents?: string;
|
|
65
|
+
effect?: TerminalEffect;
|
|
66
|
+
lifecycle?: PaneLifecycle;
|
|
67
|
+
launchError?: WindowLaunchFailure;
|
|
68
|
+
};
|
|
69
|
+
export type WindowLaunchFailure = {
|
|
70
|
+
agent?: string;
|
|
71
|
+
agentSessionId?: string;
|
|
72
|
+
code: string;
|
|
73
|
+
failedAt: string;
|
|
74
|
+
message: string;
|
|
75
|
+
stage: string;
|
|
76
|
+
};
|
|
77
|
+
export type TerminalEffectKind = "dim" | "flash" | "highlight";
|
|
78
|
+
export type TerminalEffect = {
|
|
79
|
+
expiresAt: number;
|
|
80
|
+
kind: TerminalEffectKind;
|
|
81
|
+
};
|
|
82
|
+
export type ProviderDisplay = {
|
|
83
|
+
id: string;
|
|
84
|
+
name: string;
|
|
85
|
+
bounds: Bounds;
|
|
86
|
+
windows: ProviderWindow[];
|
|
87
|
+
};
|
|
88
|
+
export type ProviderFilesystem = {
|
|
89
|
+
id: string;
|
|
90
|
+
kind: "container" | "host" | "volume";
|
|
91
|
+
name: string;
|
|
92
|
+
root?: string;
|
|
93
|
+
};
|
|
94
|
+
export type ProviderObservationStatus = {
|
|
95
|
+
status: "ok";
|
|
96
|
+
observedAt: string;
|
|
97
|
+
consecutiveFailures?: 0;
|
|
98
|
+
lastFailure?: {
|
|
99
|
+
error: string;
|
|
100
|
+
failedAt: string;
|
|
101
|
+
};
|
|
102
|
+
} | {
|
|
103
|
+
status: "failed";
|
|
104
|
+
error: string;
|
|
105
|
+
failedAt: string;
|
|
106
|
+
consecutiveFailures: number;
|
|
107
|
+
lastSuccessObservedAt?: string;
|
|
108
|
+
};
|
|
109
|
+
export type ProviderSnapshot = {
|
|
110
|
+
build?: ProviderBuildInfo;
|
|
111
|
+
epoch: string;
|
|
112
|
+
instanceId?: string;
|
|
113
|
+
provider: ProviderKind;
|
|
114
|
+
terminalThemeProfile?: TerminalThemeProfile;
|
|
115
|
+
revision: number;
|
|
116
|
+
observedAt: string;
|
|
117
|
+
observation?: ProviderObservationStatus;
|
|
118
|
+
displayBounds: Bounds;
|
|
119
|
+
displays?: ProviderDisplay[];
|
|
120
|
+
filesystems?: ProviderFilesystem[];
|
|
121
|
+
lifecycle: LifecycleSnapshot;
|
|
122
|
+
spaces?: ProviderDisplay[];
|
|
123
|
+
windows: ProviderWindow[];
|
|
124
|
+
};
|
|
125
|
+
export declare const terminalThemeProfiles: readonly ["termfleet-dark", "github-dark", "solarized-dark", "dracula", "nord", "light"];
|
|
126
|
+
export type TerminalThemeProfile = (typeof terminalThemeProfiles)[number];
|
|
127
|
+
export declare function isTerminalThemeProfile(value: unknown): value is TerminalThemeProfile;
|
|
128
|
+
export declare function parseTerminalThemeProfile(value: unknown): TerminalThemeProfile | undefined;
|
|
129
|
+
export type ProviderHealth = {
|
|
130
|
+
build?: ProviderBuildInfo;
|
|
131
|
+
instanceId?: string;
|
|
132
|
+
ok: true;
|
|
133
|
+
provider: string;
|
|
134
|
+
};
|
|
135
|
+
export type ProviderBuildInfo = {
|
|
136
|
+
buildSha?: string;
|
|
137
|
+
version: string;
|
|
138
|
+
};
|
|
139
|
+
export type OrphanSessionPruneResult = {
|
|
140
|
+
discovered: string[];
|
|
141
|
+
errors: {
|
|
142
|
+
message: string;
|
|
143
|
+
session: string;
|
|
144
|
+
}[];
|
|
145
|
+
kept: string[];
|
|
146
|
+
pruned: string[];
|
|
147
|
+
tracked: string[];
|
|
148
|
+
};
|
|
149
|
+
export type ProviderKind = "iterm" | "virtual-tmux" | "wezterm";
|
|
150
|
+
export type ProviderRef = {
|
|
151
|
+
baseUrl: string;
|
|
152
|
+
id: string;
|
|
153
|
+
label: string;
|
|
154
|
+
};
|
|
155
|
+
export declare function addBoundsSize(bounds: Omit<Bounds, "width" | "height">): Bounds;
|
package/dist/types.js
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
// The one source of truth for terminal color-scheme profiles: the runtime list
|
|
2
|
+
// (in display order), the type derived from it, and the parsers every layer shares.
|
|
3
|
+
// Kept here so the CLI, console, provider, persisted-layout reader, and the frontend
|
|
4
|
+
// appearance picker can't drift out of sync.
|
|
5
|
+
export const terminalThemeProfiles = ["termfleet-dark", "github-dark", "solarized-dark", "dracula", "nord", "light"];
|
|
6
|
+
export function isTerminalThemeProfile(value) {
|
|
7
|
+
return typeof value === "string" && terminalThemeProfiles.includes(value);
|
|
8
|
+
}
|
|
9
|
+
// Lenient parse: returns the profile or undefined (for reading persisted/optional data
|
|
10
|
+
// where an unknown value should drop, not throw). Callers that must reject an explicit
|
|
11
|
+
// bad value throw at the call site after this returns undefined.
|
|
12
|
+
export function parseTerminalThemeProfile(value) {
|
|
13
|
+
return isTerminalThemeProfile(value) ? value : undefined;
|
|
14
|
+
}
|
|
15
|
+
export function addBoundsSize(bounds) {
|
|
16
|
+
return {
|
|
17
|
+
...bounds,
|
|
18
|
+
height: bounds.bottom - bounds.top,
|
|
19
|
+
width: bounds.right - bounds.left
|
|
20
|
+
};
|
|
21
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@termfleet/core",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Termfleet core: contracts, the provider SDK, and the agent-transcript/session library (Claude Code / Codex / Gemini). The reusable layer, usable beyond the console.",
|
|
5
|
+
"license": "Apache-2.0",
|
|
6
|
+
"author": "Volter AI",
|
|
7
|
+
"type": "module",
|
|
8
|
+
"exports": {
|
|
9
|
+
"./package.json": "./package.json",
|
|
10
|
+
"./*.js": {
|
|
11
|
+
"types": "./dist/*.d.ts",
|
|
12
|
+
"default": "./dist/*.js"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"dist"
|
|
17
|
+
],
|
|
18
|
+
"scripts": {
|
|
19
|
+
"build": "tsc -p tsconfig.json",
|
|
20
|
+
"prepare": "tsc -p tsconfig.json"
|
|
21
|
+
},
|
|
22
|
+
"dependencies": {
|
|
23
|
+
"socket.io-client": "^4.8.3",
|
|
24
|
+
"yjs": "^13.6.31"
|
|
25
|
+
}
|
|
26
|
+
}
|