@x-tech-laboratories/x-libs 0.14.0 → 0.14.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 (151) hide show
  1. package/dist/web/react/menus.js +11 -7
  2. package/package.json +1 -1
  3. package/dist/agent/client.d.ts +0 -32
  4. package/dist/agent/client.js +0 -148
  5. package/dist/agent/commands.d.ts +0 -23
  6. package/dist/agent/commands.js +0 -118
  7. package/dist/agent/keys.d.ts +0 -14
  8. package/dist/agent/keys.js +0 -81
  9. package/dist/agent/long_runs.d.ts +0 -32
  10. package/dist/agent/long_runs.js +0 -316
  11. package/dist/agent/protocol.d.ts +0 -148
  12. package/dist/agent/protocol.js +0 -131
  13. package/dist/agent/session.d.ts +0 -50
  14. package/dist/agent/session.js +0 -225
  15. package/dist/agent/tasks.d.ts +0 -17
  16. package/dist/agent/tasks.js +0 -15
  17. package/dist/backups.d.ts +0 -31
  18. package/dist/backups.js +0 -43
  19. package/dist/dates.d.ts +0 -9
  20. package/dist/dates.js +0 -60
  21. package/dist/durations.d.ts +0 -11
  22. package/dist/durations.js +0 -49
  23. package/dist/electron/app.d.ts +0 -13
  24. package/dist/electron/app.js +0 -27
  25. package/dist/electron/bridge.d.ts +0 -55
  26. package/dist/electron/bridge.js +0 -105
  27. package/dist/electron/events.d.ts +0 -21
  28. package/dist/electron/events.js +0 -25
  29. package/dist/electron/fetch.d.ts +0 -52
  30. package/dist/electron/fetch.js +0 -175
  31. package/dist/electron/window.d.ts +0 -96
  32. package/dist/electron/window.js +0 -128
  33. package/dist/log.d.ts +0 -30
  34. package/dist/log.js +0 -79
  35. package/dist/server/agents/agent.d.ts +0 -27
  36. package/dist/server/agents/agent.js +0 -16
  37. package/dist/server/agents/connection.d.ts +0 -51
  38. package/dist/server/agents/connection.js +0 -239
  39. package/dist/server/agents/hub.d.ts +0 -86
  40. package/dist/server/agents/hub.js +0 -241
  41. package/dist/server/agents/local.d.ts +0 -24
  42. package/dist/server/agents/local.js +0 -62
  43. package/dist/server/agents/route.d.ts +0 -3
  44. package/dist/server/agents/route.js +0 -24
  45. package/dist/server/backup_files.d.ts +0 -3
  46. package/dist/server/backup_files.js +0 -25
  47. package/dist/server/config.d.ts +0 -39
  48. package/dist/server/config.js +0 -109
  49. package/dist/server/cors.d.ts +0 -8
  50. package/dist/server/cors.js +0 -13
  51. package/dist/server/events.d.ts +0 -33
  52. package/dist/server/events.js +0 -68
  53. package/dist/server/hash_password.d.ts +0 -1
  54. package/dist/server/hash_password.js +0 -46
  55. package/dist/server/login_page.d.ts +0 -8
  56. package/dist/server/login_page.js +0 -79
  57. package/dist/server/passwords.d.ts +0 -8
  58. package/dist/server/passwords.js +0 -59
  59. package/dist/server/replies.d.ts +0 -12
  60. package/dist/server/replies.js +0 -41
  61. package/dist/server/sign_in.d.ts +0 -27
  62. package/dist/server/sign_in.js +0 -95
  63. package/dist/server/web_folder.d.ts +0 -11
  64. package/dist/server/web_folder.js +0 -40
  65. package/dist/web/dom.d.ts +0 -7
  66. package/dist/web/dom.js +0 -32
  67. package/dist/web/drag.d.ts +0 -3
  68. package/dist/web/drag.js +0 -13
  69. package/dist/web/errors.d.ts +0 -1
  70. package/dist/web/errors.js +0 -27
  71. package/dist/web/format.d.ts +0 -11
  72. package/dist/web/format.js +0 -82
  73. package/dist/web/menus.d.ts +0 -17
  74. package/dist/web/menus.js +0 -40
  75. package/dist/web/prefs.d.ts +0 -12
  76. package/dist/web/prefs.js +0 -62
  77. package/dist/web/react/badges.d.ts +0 -35
  78. package/dist/web/react/badges.js +0 -32
  79. package/dist/web/react/controls.d.ts +0 -86
  80. package/dist/web/react/controls.js +0 -154
  81. package/dist/web/react/dialog.d.ts +0 -45
  82. package/dist/web/react/dialog.js +0 -82
  83. package/dist/web/react/following.d.ts +0 -25
  84. package/dist/web/react/following.js +0 -34
  85. package/dist/web/react/layout.d.ts +0 -111
  86. package/dist/web/react/layout.js +0 -85
  87. package/dist/web/react/list_picker.d.ts +0 -19
  88. package/dist/web/react/list_picker.js +0 -50
  89. package/dist/web/react/markdown.d.ts +0 -8
  90. package/dist/web/react/markdown.js +0 -40
  91. package/dist/web/react/media.d.ts +0 -24
  92. package/dist/web/react/media.js +0 -18
  93. package/dist/web/react/menu_button.d.ts +0 -10
  94. package/dist/web/react/menu_button.js +0 -16
  95. package/dist/web/react/menus.d.ts +0 -31
  96. package/dist/web/react/page_view.d.ts +0 -16
  97. package/dist/web/react/page_view.js +0 -6
  98. package/dist/web/react/prefs.d.ts +0 -2
  99. package/dist/web/react/prefs.js +0 -11
  100. package/dist/web/react/progress.d.ts +0 -10
  101. package/dist/web/react/progress.js +0 -9
  102. package/dist/web/react/rating.d.ts +0 -8
  103. package/dist/web/react/rating.js +0 -23
  104. package/dist/web/react/reveal.d.ts +0 -10
  105. package/dist/web/react/reveal.js +0 -30
  106. package/dist/web/react/shell.d.ts +0 -46
  107. package/dist/web/react/shell.js +0 -94
  108. package/dist/web/react/shortcuts.d.ts +0 -23
  109. package/dist/web/react/shortcuts.js +0 -95
  110. package/dist/web/react/split.d.ts +0 -23
  111. package/dist/web/react/split.js +0 -94
  112. package/dist/web/react/states.d.ts +0 -36
  113. package/dist/web/react/states.js +0 -64
  114. package/dist/web/react/store.d.ts +0 -4
  115. package/dist/web/react/store.js +0 -7
  116. package/dist/web/react/suggestions.d.ts +0 -23
  117. package/dist/web/react/suggestions.js +0 -57
  118. package/dist/web/react/table.d.ts +0 -78
  119. package/dist/web/react/table.js +0 -404
  120. package/dist/web/react/test_stubs.d.ts +0 -1
  121. package/dist/web/react/test_stubs.js +0 -25
  122. package/dist/web/react/time.d.ts +0 -5
  123. package/dist/web/react/time.js +0 -19
  124. package/dist/web/react/toasts.d.ts +0 -29
  125. package/dist/web/react/toasts.js +0 -72
  126. package/dist/web/react/tree.d.ts +0 -28
  127. package/dist/web/react/tree.js +0 -183
  128. package/dist/web/react/volume.d.ts +0 -8
  129. package/dist/web/react/volume.js +0 -42
  130. package/dist/web/react/watch.d.ts +0 -3
  131. package/dist/web/react/watch.js +0 -5
  132. package/dist/web/router.d.ts +0 -7
  133. package/dist/web/router.js +0 -29
  134. package/dist/web/selection.d.ts +0 -25
  135. package/dist/web/selection.js +0 -106
  136. package/dist/web/split.d.ts +0 -15
  137. package/dist/web/split.js +0 -104
  138. package/dist/web/states.d.ts +0 -3
  139. package/dist/web/states.js +0 -10
  140. package/dist/web/store.d.ts +0 -11
  141. package/dist/web/store.js +0 -17
  142. package/dist/web/tables.d.ts +0 -28
  143. package/dist/web/tables.js +0 -88
  144. package/dist/web/theme.d.ts +0 -14
  145. package/dist/web/theme.js +0 -52
  146. package/dist/web/tree.d.ts +0 -40
  147. package/dist/web/tree.js +0 -130
  148. package/dist/web/virtual.d.ts +0 -7
  149. package/dist/web/virtual.js +0 -10
  150. package/dist/web/watch.d.ts +0 -11
  151. package/dist/web/watch.js +0 -37
package/dist/log.js DELETED
@@ -1,79 +0,0 @@
1
- // Logging by scope and level, such as "warn,play:debug", where a mistake in the setting never silences logging.
2
- const level_order = { critical: 0, error: 1, warn: 2, info: 3, debug: 4 };
3
- export const levels = Object.keys(level_order);
4
- const level_aliases = {
5
- crit: "critical", critical: "critical",
6
- err: "error", error: "error",
7
- warn: "warn", warning: "warn",
8
- info: "info",
9
- debug: "debug", verbose: "debug", trace: "debug",
10
- };
11
- export const default_level = "info";
12
- // ── Parsing ──────────────────────────────────────────────────────────────────
13
- // A bare level sets the default and "scope:level" one scope; entries it cannot read are skipped.
14
- export function parse_level_spec(spec, fallback = default_level) {
15
- const parsed = { default: fallback, scopes: {} };
16
- if (!spec)
17
- return parsed;
18
- for (const raw_part of spec.split(",")) {
19
- const part = raw_part.trim().toLowerCase();
20
- if (part === "")
21
- continue;
22
- // Scopes hold colons of their own, so the level follows the last one.
23
- const colon = part.lastIndexOf(":");
24
- if (colon === -1) {
25
- const level = level_aliases[part];
26
- if (level)
27
- parsed.default = level;
28
- continue;
29
- }
30
- const scope = part.slice(0, colon).trim();
31
- const level = level_aliases[part.slice(colon + 1).trim()];
32
- if (!level || scope === "")
33
- continue;
34
- if (scope === "*")
35
- parsed.default = level;
36
- else
37
- parsed.scopes[scope] = level;
38
- }
39
- return parsed;
40
- }
41
- export function level_for(spec, scope) {
42
- return spec.scopes[scope] ?? spec.default;
43
- }
44
- export function is_enabled(spec, scope, level) {
45
- return level_order[level] <= level_order[level_for(spec, scope)];
46
- }
47
- const two_digits = (count) => String(count).padStart(2, "0");
48
- // A line in fixed columns, such as "10:33:35.123 WARN play message {"detail":1}".
49
- export function format_record(record) {
50
- const date = new Date(record.at);
51
- const time = `${two_digits(date.getHours())}:${two_digits(date.getMinutes())}:${two_digits(date.getSeconds())}.${String(date.getMilliseconds()).padStart(3, "0")}`;
52
- let line = `${time} ${record.level.toUpperCase().padEnd(8)} ${record.scope.padEnd(9)} ${record.message}`;
53
- if (record.data !== undefined) {
54
- try {
55
- line += ` ${JSON.stringify(record.data)}`;
56
- }
57
- catch {
58
- line += " [unserializable]";
59
- }
60
- }
61
- return line;
62
- }
63
- const resolve_spec = (source) => typeof source === "function" ? source() : source;
64
- export function create_logger(scope, spec, sink) {
65
- const emit = (level, message, data) => {
66
- if (!is_enabled(resolve_spec(spec), scope, level))
67
- return;
68
- sink({ at: Date.now(), level, scope, message, data });
69
- };
70
- return {
71
- critical: (message, data) => emit("critical", message, data),
72
- error: (message, data) => emit("error", message, data),
73
- warn: (message, data) => emit("warn", message, data),
74
- info: (message, data) => emit("info", message, data),
75
- debug: (message, data) => emit("debug", message, data),
76
- enabled: (level) => is_enabled(resolve_spec(spec), scope, level),
77
- child: (child_scope) => create_logger(`${scope}:${child_scope}`, spec, sink),
78
- };
79
- }
@@ -1,27 +0,0 @@
1
- import type { CommandStream } from "../../agent/commands.ts";
2
- import type { LongRun, LongRunPoll, RunResult } from "../../agent/protocol.ts";
3
- export type { CommandStream } from "../../agent/commands.ts";
4
- export type { LongRun, LongRunPoll, LongRunState, RunResult } from "../../agent/protocol.ts";
5
- export interface AgentRunOptions {
6
- timeout_in_seconds: number;
7
- stdin?: string | null;
8
- }
9
- export interface AgentStreamOptions {
10
- stdin?: string | null;
11
- }
12
- export declare class AgentError extends Error {
13
- readonly unreachable: boolean;
14
- constructor(message: string, unreachable?: boolean);
15
- }
16
- export declare function ended_stream(stderr: string): CommandStream;
17
- export interface Agent<Task> {
18
- run(task: Task, options: AgentRunOptions): Promise<RunResult>;
19
- stream(task: Task, options?: AgentStreamOptions): CommandStream;
20
- start(run_id: string, task: Task, options?: AgentStreamOptions): Promise<LongRun>;
21
- poll(run_id: string, offset: number): Promise<LongRunPoll>;
22
- attach(run_id: string, offset: number): CommandStream;
23
- stop(run_id: string): Promise<LongRun>;
24
- forget(run_id: string): Promise<void>;
25
- runs(): Promise<LongRun[]>;
26
- request(type: string, body?: Record<string, unknown>): Promise<unknown>;
27
- }
@@ -1,16 +0,0 @@
1
- // What the server can ask of one host's agent, whether it is connected over a WebSocket or built into the server.
2
- // ── Imports ──────────────────────────────────────────────────────────────────
3
- import { Readable } from "node:stream";
4
- export class AgentError extends Error {
5
- // Whether the host never answered, so trying again later may work, rather than answering that it failed.
6
- unreachable;
7
- constructor(message, unreachable = false) {
8
- super(message);
9
- this.name = "AgentError";
10
- this.unreachable = unreachable;
11
- }
12
- }
13
- // A stream that has already ended with an error, for a host with no agent or a run that cannot be followed.
14
- export function ended_stream(stderr) {
15
- return { stdout: Readable.from([]), done: Promise.resolve({ exit_code: -1, stderr }), stop: () => { } };
16
- }
@@ -1,51 +0,0 @@
1
- import { type AgentApp, type AgentMessage, type AppMessage, type LongRun, type LongRunPoll, type RunResult, type ServerMessage } from "../../agent/protocol.ts";
2
- import { type Agent, type AgentRunOptions, type AgentStreamOptions, type CommandStream } from "./agent.ts";
3
- export interface ServerSocket {
4
- readonly readyState: number;
5
- send(data: string): void;
6
- close(code?: number, reason?: string): void;
7
- on(event: "message", listener: (data: Buffer | ArrayBuffer | Buffer[], is_binary: boolean) => void): unknown;
8
- on(event: "close", listener: () => void): unknown;
9
- on(event: "error", listener: (error: Error) => void): unknown;
10
- }
11
- export interface ConnectionOptions {
12
- window_in_bytes: number;
13
- request_timeout_in_milliseconds: number;
14
- heartbeat_in_milliseconds: number;
15
- }
16
- export type Hello = Omit<Extract<AgentMessage, {
17
- type: "hello";
18
- }>, "signature">;
19
- export declare class AgentConnection<Task> implements Agent<Task> {
20
- readonly host: string;
21
- readonly hello: Hello;
22
- readonly connected_epoch: number;
23
- on_message: ((message: AppMessage) => void) | null;
24
- private readonly socket;
25
- private readonly app;
26
- private readonly options;
27
- private readonly pending;
28
- private readonly streams;
29
- private next_id;
30
- private last_heard;
31
- private readonly heartbeat;
32
- private closed_reason;
33
- constructor(socket: ServerSocket, app: AgentApp<Task>, host: string, hello: Hello, options: ConnectionOptions);
34
- get is_open(): boolean;
35
- run(task: Task, options: AgentRunOptions): Promise<RunResult>;
36
- stream(task: Task, options?: AgentStreamOptions): CommandStream;
37
- start(run_id: string, task: Task, options?: AgentStreamOptions): Promise<LongRun>;
38
- poll(run_id: string, offset: number): Promise<LongRunPoll>;
39
- attach(run_id: string, offset: number): CommandStream;
40
- stop(run_id: string): Promise<LongRun>;
41
- forget(run_id: string): Promise<void>;
42
- runs(): Promise<LongRun[]>;
43
- request(type: string, body?: Record<string, unknown>): Promise<unknown>;
44
- send(message: ServerMessage<Task> | AppMessage): void;
45
- receive(data: Buffer, is_binary: boolean): void;
46
- closed(reason: string): void;
47
- close(code: number, reason: string): void;
48
- private send_request;
49
- private open_stream;
50
- private beat;
51
- }
@@ -1,239 +0,0 @@
1
- // One connected agent, as the server sees it: sends it requests and matches each reply by id, and turns its streamed
2
- // output back into a readable stream, granting the agent more credit only as the reader takes what has come.
3
- // ── Imports ──────────────────────────────────────────────────────────────────
4
- import { Readable } from "node:stream";
5
- import { decode_chunk, encode_message, is_agent_message, parse_agent_message, } from "../../agent/protocol.js";
6
- import { AgentError } from "./agent.js";
7
- const socket_open = 1;
8
- // A run's reply may come this long after its own timeout, which the agent enforces, before the server gives up.
9
- const run_reply_slack_in_milliseconds = 30_000;
10
- // ── Incoming streams ─────────────────────────────────────────────────────────
11
- // A stream's output arriving from the agent, readable as it comes.
12
- class IncomingStream {
13
- stdout;
14
- done;
15
- id;
16
- connection;
17
- window;
18
- // Credit the agent still holds: bytes it may send before it hears from us again.
19
- outstanding;
20
- reader_full = false;
21
- result = null;
22
- stdout_closed = false;
23
- settle;
24
- constructor(id, connection, window) {
25
- this.id = id;
26
- this.connection = connection;
27
- this.window = window;
28
- this.outstanding = window;
29
- this.done = new Promise((resolve) => (this.settle = resolve));
30
- this.stdout = new Readable({
31
- read: () => {
32
- this.reader_full = false;
33
- this.grant();
34
- },
35
- destroy: (error, callback) => {
36
- if (this.result === null)
37
- this.connection.send({ type: "cancel", id: this.id });
38
- callback(error);
39
- },
40
- });
41
- this.stdout.on("close", () => {
42
- this.stdout_closed = true;
43
- this.settle_when_done();
44
- });
45
- }
46
- receive(data) {
47
- this.outstanding -= data.length;
48
- if (this.result !== null || this.stdout.destroyed)
49
- return;
50
- if (!this.stdout.push(data))
51
- this.reader_full = true;
52
- this.grant();
53
- }
54
- end(result) {
55
- if (this.result !== null)
56
- return;
57
- this.result = result;
58
- if (!this.stdout.destroyed)
59
- this.stdout.push(null);
60
- this.settle_when_done();
61
- }
62
- stop() {
63
- this.stdout.destroy();
64
- }
65
- // Tops the agent's credit back up once half of it has been read.
66
- grant() {
67
- if (this.reader_full || this.result !== null || this.outstanding > this.window / 2)
68
- return;
69
- this.connection.send({ type: "credit", id: this.id, bytes: this.window - this.outstanding });
70
- this.outstanding = this.window;
71
- }
72
- settle_when_done() {
73
- if (this.result !== null && this.stdout_closed)
74
- this.settle(this.result);
75
- }
76
- }
77
- // ── Connection ───────────────────────────────────────────────────────────────
78
- export class AgentConnection {
79
- host;
80
- hello;
81
- connected_epoch = Math.floor(Date.now() / 1000);
82
- // Takes the app's own messages from the agent that are not replies.
83
- on_message = null;
84
- socket;
85
- app;
86
- options;
87
- pending = new Map();
88
- streams = new Map();
89
- next_id = 1;
90
- last_heard = Date.now();
91
- heartbeat;
92
- closed_reason = null;
93
- constructor(socket, app, host, hello, options) {
94
- this.socket = socket;
95
- this.app = app;
96
- this.host = host;
97
- this.hello = hello;
98
- this.options = options;
99
- this.heartbeat = setInterval(() => this.beat(), options.heartbeat_in_milliseconds);
100
- this.heartbeat.unref();
101
- }
102
- get is_open() {
103
- return this.closed_reason === null;
104
- }
105
- // ── Agent ────────────────────────────────────────────────────────────────
106
- async run(task, options) {
107
- try {
108
- const timeout = options.timeout_in_seconds * 1000 + run_reply_slack_in_milliseconds;
109
- return await this.send_request("run", { task, stdin: options.stdin ?? null, timeout_in_seconds: options.timeout_in_seconds }, timeout);
110
- }
111
- catch (error) {
112
- return { exit_code: -1, stdout: "", stderr: error.message };
113
- }
114
- }
115
- stream(task, options = {}) {
116
- return this.open_stream((id, window) => ({ type: "stream", id, task, stdin: options.stdin ?? null, window }));
117
- }
118
- start(run_id, task, options = {}) {
119
- return this.send_request("start", { run_id, task, stdin: options.stdin ?? null });
120
- }
121
- poll(run_id, offset) {
122
- return this.send_request("poll", { run_id, offset });
123
- }
124
- attach(run_id, offset) {
125
- return this.open_stream((id, window) => ({ type: "attach", id, run_id, offset, window }));
126
- }
127
- stop(run_id) {
128
- return this.send_request("stop", { run_id });
129
- }
130
- async forget(run_id) {
131
- await this.send_request("forget", { run_id });
132
- }
133
- runs() {
134
- return this.send_request("runs", {});
135
- }
136
- request(type, body = {}) {
137
- return this.send_request(type, body);
138
- }
139
- // ── Socket ───────────────────────────────────────────────────────────────
140
- send(message) {
141
- if (this.is_open && this.socket.readyState === socket_open)
142
- this.socket.send(encode_message(message, this.app));
143
- }
144
- // Handles one frame from the agent after its hello.
145
- receive(data, is_binary) {
146
- this.last_heard = Date.now();
147
- if (is_binary) {
148
- const chunk = decode_chunk(data);
149
- if (chunk !== null)
150
- this.streams.get(chunk.id)?.receive(chunk.data);
151
- return;
152
- }
153
- const message = parse_agent_message(data.toString("utf8"), this.app);
154
- if (message === null)
155
- return;
156
- if (!is_agent_message(message)) {
157
- this.on_message?.(message);
158
- return;
159
- }
160
- switch (message.type) {
161
- case "ping":
162
- this.send({ type: "pong", epoch_ms: message.epoch_ms });
163
- return;
164
- case "reply":
165
- case "failed": {
166
- const pending = this.pending.get(message.id);
167
- if (pending === undefined)
168
- return;
169
- this.pending.delete(message.id);
170
- clearTimeout(pending.timer);
171
- // The agent answered that the request failed, which is not the host being out of reach.
172
- if (message.type === "reply")
173
- pending.resolve(message.value);
174
- else
175
- pending.reject(new AgentError(message.error));
176
- return;
177
- }
178
- case "stream_end":
179
- this.streams.get(message.id)?.end({ exit_code: message.exit_code, stderr: message.stderr });
180
- this.streams.delete(message.id);
181
- return;
182
- default:
183
- return;
184
- }
185
- }
186
- // Fails what was waiting and ends each stream; the agent's long runs carry on.
187
- closed(reason) {
188
- if (this.closed_reason !== null)
189
- return;
190
- this.closed_reason = reason;
191
- clearInterval(this.heartbeat);
192
- for (const pending of this.pending.values()) {
193
- clearTimeout(pending.timer);
194
- pending.reject(new AgentError(reason, true));
195
- }
196
- this.pending.clear();
197
- for (const stream of this.streams.values())
198
- stream.end({ exit_code: -1, stderr: reason });
199
- this.streams.clear();
200
- }
201
- close(code, reason) {
202
- this.socket.close(code, reason);
203
- this.closed(reason);
204
- }
205
- // ── Helpers ──────────────────────────────────────────────────────────────
206
- send_request(type, body, timeout = this.options.request_timeout_in_milliseconds) {
207
- if (!this.is_open)
208
- return Promise.reject(new AgentError(this.closed_reason, true));
209
- const id = `r${this.next_id++}`;
210
- return new Promise((resolve, reject) => {
211
- const timer = setTimeout(() => {
212
- this.pending.delete(id);
213
- reject(new AgentError(`The agent on ${this.host} did not answer within ${Math.round(timeout / 1000)}s.`, true));
214
- }, timeout);
215
- this.pending.set(id, { resolve: resolve, reject, timer });
216
- this.send({ ...body, type, id });
217
- });
218
- }
219
- open_stream(message) {
220
- const id = `s${this.next_id++}`;
221
- const stream = new IncomingStream(id, this, this.options.window_in_bytes);
222
- if (!this.is_open) {
223
- stream.end({ exit_code: -1, stderr: this.closed_reason });
224
- }
225
- else {
226
- this.streams.set(id, stream);
227
- this.send(message(id, this.options.window_in_bytes));
228
- }
229
- return { stdout: stream.stdout, done: stream.done, stop: () => stream.stop() };
230
- }
231
- // Pings the agent, or drops one that has been silent for three beats.
232
- beat() {
233
- if (Date.now() - this.last_heard > 3 * this.options.heartbeat_in_milliseconds) {
234
- this.close(4008, `The agent on ${this.host} stopped answering.`);
235
- return;
236
- }
237
- this.send({ type: "ping", epoch_ms: Date.now() });
238
- }
239
- }
@@ -1,86 +0,0 @@
1
- import { EventEmitter } from "node:events";
2
- import type { IncomingHttpHeaders } from "node:http";
3
- import { type AgentApp, type AppMessage, type LongRun, type LongRunPoll, type RunResult } from "../../agent/protocol.ts";
4
- import { type Agent, type AgentRunOptions, type AgentStreamOptions, type CommandStream } from "./agent.ts";
5
- import { AgentConnection, type ConnectionOptions, type ServerSocket } from "./connection.ts";
6
- export interface AgentTokenLookup {
7
- host_for(token: string): string | null;
8
- seen?(host: string): void;
9
- }
10
- export interface HubOptions<Task> {
11
- app: AgentApp<Task>;
12
- local?: {
13
- host: string;
14
- agent: Agent<Task>;
15
- };
16
- tokens?: AgentTokenLookup;
17
- on_message?: (host: string, message: AppMessage, connection: AgentConnection<Task>) => void;
18
- hello_timeout_in_milliseconds?: number;
19
- connection?: Partial<ConnectionOptions>;
20
- }
21
- export interface AgentStatus {
22
- host: string;
23
- reported_host: string;
24
- agent_version: string;
25
- connected_epoch: number;
26
- built_in: boolean;
27
- login: AgentLogin | null;
28
- runs: LongRun[];
29
- }
30
- export type AgentLogin = "token" | "key";
31
- export type Admission = {
32
- host: string;
33
- login: AgentLogin;
34
- } | {
35
- error: string;
36
- };
37
- interface HubEvents {
38
- connect: [status: AgentStatus];
39
- disconnect: [host: string];
40
- }
41
- export declare const close_codes: {
42
- readonly protocol: 4002;
43
- readonly replaced: 4003;
44
- readonly revoked: 4004;
45
- readonly no_hello: 4005;
46
- readonly bad_key: 4006;
47
- };
48
- export declare class AgentHub<Task> extends EventEmitter<HubEvents> {
49
- readonly app: AgentApp<Task>;
50
- private readonly local;
51
- private readonly tokens;
52
- private readonly on_message;
53
- private readonly hello_timeout;
54
- private readonly connection_options;
55
- private readonly connections;
56
- private readonly logins;
57
- private agent_keys;
58
- constructor(options: HubOptions<Task>);
59
- set_local_host(host: string): void;
60
- set_agent_keys(lines: Map<string, string>): void;
61
- has_agent_key(host: string): boolean;
62
- declared_hosts(): string[];
63
- disconnect_token_login(host: string, reason: string): void;
64
- authenticate(authorization: string | undefined): string | null;
65
- admit(headers: IncomingHttpHeaders): Admission;
66
- accept(socket: ServerSocket, host: string, login: AgentLogin): void;
67
- private proves_key;
68
- disconnect(host: string, code?: number, reason?: string): void;
69
- close(): void;
70
- is_connected(host: string): boolean;
71
- status(host: string): AgentStatus | null;
72
- statuses(): AgentStatus[];
73
- agent(host: string): Agent<Task> | null;
74
- run(host: string, task: Task, options: AgentRunOptions): Promise<RunResult>;
75
- stream(host: string, task: Task, options?: AgentStreamOptions): CommandStream;
76
- start(host: string, run_id: string, task: Task, options?: AgentStreamOptions): Promise<LongRun>;
77
- poll(host: string, run_id: string, offset: number): Promise<LongRunPoll>;
78
- attach(host: string, run_id: string, offset: number): CommandStream;
79
- stop(host: string, run_id: string): Promise<LongRun>;
80
- forget(host: string, run_id: string): Promise<void>;
81
- runs(host: string): Promise<LongRun[]>;
82
- request(host: string, type: string, body?: Record<string, unknown>): Promise<unknown>;
83
- private require;
84
- private status_of;
85
- }
86
- export {};