@ai-ecoverse/slicc-kernel 1.182.0 → 1.183.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.
Files changed (37) hide show
  1. package/README.md +54 -5
  2. package/dist/driver-worker.js +290 -90
  3. package/dist/driver-worker.js.map +4 -4
  4. package/dist/index.js +328 -102
  5. package/dist/index.js.map +4 -4
  6. package/dist/kernel-worker.js +1705 -695
  7. package/dist/kernel-worker.js.map +4 -4
  8. package/dist/node-driver-worker.js +298 -98
  9. package/dist/node-driver-worker.js.map +4 -4
  10. package/dist/node-process-worker.cjs +849 -193
  11. package/dist/node-process-worker.cjs.map +4 -4
  12. package/dist/node-process-worker.js +849 -193
  13. package/dist/node-process-worker.js.map +4 -4
  14. package/dist/node.js +1875 -743
  15. package/dist/node.js.map +4 -4
  16. package/dist/process-worker.js +805 -149
  17. package/dist/process-worker.js.map +4 -4
  18. package/dist/types/client/attach.d.ts +2 -0
  19. package/dist/types/client/protocol.d.ts +1 -0
  20. package/dist/types/client/serve-client.d.ts +1 -0
  21. package/dist/types/devices-relay.d.ts +74 -0
  22. package/dist/types/index.d.ts +14 -0
  23. package/dist/types/kernel/devices.d.ts +155 -0
  24. package/dist/types/kernel/embedder.d.ts +2 -0
  25. package/dist/types/kernel/fd-table.d.ts +3 -1
  26. package/dist/types/kernel/host.d.ts +2 -0
  27. package/dist/types/kernel/process.d.ts +20 -0
  28. package/dist/types/kernel/serial-ioctl.d.ts +73 -0
  29. package/dist/types/launcher.d.ts +4 -0
  30. package/dist/types/node.d.ts +6 -2
  31. package/dist/types/process/js/js-dev.d.ts +24 -0
  32. package/dist/types/process/kernel-streams.d.ts +11 -1
  33. package/dist/types/process/process-pty.d.ts +1 -0
  34. package/dist/types/process/wasi/wasi-fds.d.ts +1 -0
  35. package/dist/types/process/wasi/wasi-termios.d.ts +1 -0
  36. package/dist/types/serve.d.ts +14 -1
  37. package/package.json +2 -2
@@ -2,6 +2,7 @@ import type { CdpHook } from '../cdp/types.js';
2
2
  import type { FacadeHook } from '../facade/types.js';
3
3
  import type { FsStat, UsersMode } from '../fs/types.js';
4
4
  import type { WatchChange } from '../fs/watch.js';
5
+ import { type DeviceHook } from '../kernel/devices.js';
5
6
  import { type EmbedderHook } from '../kernel/embedder.js';
6
7
  import type { RealmTransport, RealmTransportRequest, RealmTransportResponse, RealmTransportTraits } from '../kernel/net/transport.js';
7
8
  import type { TraceEvent } from '../kernel/trace.js';
@@ -24,6 +25,7 @@ export interface AttachOptions {
24
25
  timeoutMs?: number;
25
26
  locks?: LockManagerLike | null;
26
27
  requests?: EmbedderHook;
28
+ devices?: DeviceHook;
27
29
  }
28
30
  export interface SpawnOptions {
29
31
  cwd?: string;
@@ -12,6 +12,7 @@ export interface ClientHello {
12
12
  group?: string;
13
13
  users?: Array<string | number>;
14
14
  }>;
15
+ devices?: true;
15
16
  }
16
17
  export interface KernelHello {
17
18
  protocol: readonly [number, number];
@@ -12,6 +12,7 @@ export interface ClientHost {
12
12
  tag?: string;
13
13
  session?: number;
14
14
  attachRequests?: boolean;
15
+ attachDevices?: boolean;
15
16
  }
16
17
  export interface ServedClient {
17
18
  detach(kill?: boolean): void;
@@ -0,0 +1,74 @@
1
+ import type { DeviceHook, DeviceStamp } from './kernel/devices.js';
2
+ export interface DevicesPort {
3
+ postMessage(message: unknown, transfer?: Transferable[]): void;
4
+ }
5
+ interface Failure {
6
+ name: string;
7
+ message: string;
8
+ }
9
+ export type DevicesToPage = {
10
+ id: number;
11
+ open: {
12
+ client: number;
13
+ path: string;
14
+ flags: number;
15
+ stamp: DeviceStamp;
16
+ };
17
+ } | {
18
+ id: number;
19
+ pull: true;
20
+ } | {
21
+ id: number;
22
+ write: Uint8Array;
23
+ seq: number;
24
+ } | {
25
+ id: number;
26
+ control: {
27
+ seq: number;
28
+ op: string;
29
+ args?: object;
30
+ };
31
+ } | {
32
+ id: number;
33
+ cancel: string;
34
+ };
35
+ export type DevicesToKernel = {
36
+ id: number;
37
+ opened: true;
38
+ } | {
39
+ id: number;
40
+ failed: Failure;
41
+ } | {
42
+ id: number;
43
+ chunk: Uint8Array;
44
+ } | {
45
+ id: number;
46
+ done: true;
47
+ } | {
48
+ id: number;
49
+ readError: Failure;
50
+ } | {
51
+ id: number;
52
+ wrote: number;
53
+ } | {
54
+ id: number;
55
+ writeError: Failure;
56
+ seq: number;
57
+ } | {
58
+ id: number;
59
+ answered: number;
60
+ value?: unknown;
61
+ } | {
62
+ id: number;
63
+ refused: number;
64
+ error: Failure;
65
+ };
66
+ export declare function devicesAsker(port: DevicesPort): {
67
+ hookFor: (client: number) => DeviceHook;
68
+ answer: (message: DevicesToKernel) => void;
69
+ };
70
+ export declare function devicesAnswerer(port: DevicesPort, hookFor: (client: number) => DeviceHook | undefined): {
71
+ handle(data: unknown): boolean;
72
+ };
73
+ export declare function devicesReplyOf(data: unknown): DevicesToKernel | undefined;
74
+ export {};
@@ -8,6 +8,7 @@ import type { DenialHook } from './fs/dac.js';
8
8
  import { type Protection } from './fs/protect.js';
9
9
  import { type UsersMode } from './fs/types.js';
10
10
  import type { ClipboardHook } from './kernel/clipboard.js';
11
+ import { type DeviceHook, type DeviceSpec } from './kernel/devices.js';
11
12
  import { type EmbedderHook } from './kernel/embedder.js';
12
13
  import type { RouteTable } from './kernel/net/routes.js';
13
14
  import { type SealedOption } from './kernel/net/sealed-fetch.js';
@@ -26,6 +27,7 @@ export type { FacadeConnection, FacadeHook, FacadeInfo, FacadeSpec, FacadeSpecs,
26
27
  export type { Attestation, AttestedDir, AttestOptions, AttestTombstone } from './fs/attest.js';
27
28
  export type { Denial, DenialHook } from './fs/dac.js';
28
29
  export type { ClipboardHook, ClipboardStamp } from './kernel/clipboard.js';
30
+ export type { DeviceHook, DeviceOpenRequest, DeviceSignals, DeviceSpec, DeviceStamp, DeviceStreams, } from './kernel/devices.js';
29
31
  export type { EmbedderHook, EmbedderKindPolicy, EmbedderReply, EmbedderRequest, EmbedderStamp, } from './kernel/embedder.js';
30
32
  export type { RouteTable } from './kernel/net/routes.js';
31
33
  export { SEALED_FETCH_VERSION, type SealedFetchHook, type SealedFetchRequest, type SealedOption, } from './kernel/net/sealed-fetch.js';
@@ -79,6 +81,7 @@ export interface KernelOptions {
79
81
  sealed?: SealedOption;
80
82
  clipboard?: ClipboardHook;
81
83
  requests?: EmbedderHook;
84
+ devices?: DeviceHook;
82
85
  approve?: ApproveHook;
83
86
  protect?: Protection;
84
87
  }
@@ -108,6 +111,16 @@ export interface ConnectOptions {
108
111
  user?: string | number;
109
112
  tag?: string;
110
113
  requests?: EmbedderHook | 'attach';
114
+ devices?: DeviceHook | 'attach';
115
+ }
116
+ export interface DeviceAddOptions extends DeviceSpec {
117
+ client?: MessagePort;
118
+ }
119
+ export interface DeviceNodeHandle {
120
+ remove(): Promise<void>;
121
+ }
122
+ export interface KernelDevices {
123
+ add(spec: DeviceAddOptions): Promise<DeviceNodeHandle>;
111
124
  }
112
125
  export interface KernelGroups {
113
126
  list(): Promise<Group[]>;
@@ -134,6 +147,7 @@ export interface Kernel {
134
147
  sudoRun(request: SudoReplay, options?: SudoRunOptions): Promise<SudoRun>;
135
148
  readonly users: KernelUsers;
136
149
  readonly groups: KernelGroups;
150
+ readonly devices: KernelDevices;
137
151
  setRoutes(routes: RouteTable): Promise<void>;
138
152
  chmod(path: string, mode: number): Promise<void>;
139
153
  readonly integrity: KernelIntegrity;
@@ -0,0 +1,155 @@
1
+ import { type Guard } from '../fs/dac.js';
2
+ import type { UsersMode } from '../fs/types.js';
3
+ import { KernelError, type OpenAccess, OpenFile } from './fd-table.js';
4
+ import { type SerialSettings, type SerialTermios } from './serial-ioctl.js';
5
+ import { KernelTty, type Termios } from './tty.js';
6
+ export declare const DEVICE_NAME: RegExp;
7
+ export declare const BY_ID = "/dev/serial/by-id";
8
+ export interface DeviceSignals {
9
+ clearToSend: boolean;
10
+ dataCarrierDetect: boolean;
11
+ dataSetReady: boolean;
12
+ ringIndicator: boolean;
13
+ }
14
+ export interface DeviceStreams {
15
+ readable: ReadableStream<Uint8Array>;
16
+ writable: WritableStream<Uint8Array>;
17
+ control(op: string, args?: object): unknown;
18
+ }
19
+ export interface DeviceStamp {
20
+ pid: number;
21
+ uid: number;
22
+ gid: number;
23
+ groups: number[];
24
+ users: UsersMode;
25
+ tag?: string;
26
+ tags?: string[];
27
+ }
28
+ export interface DeviceOpenRequest {
29
+ path: string;
30
+ flags: number;
31
+ stamp: DeviceStamp;
32
+ signal: AbortSignal;
33
+ }
34
+ export interface DeviceHook {
35
+ open(request: DeviceOpenRequest): DeviceStreams | Promise<DeviceStreams>;
36
+ }
37
+ export interface DeviceSpec {
38
+ path: string;
39
+ owner?: string | number;
40
+ group?: string | number;
41
+ mode?: number;
42
+ links?: readonly string[];
43
+ }
44
+ export interface DeviceNodeInfo {
45
+ path: string;
46
+ uid: number;
47
+ gid: number;
48
+ mode: number;
49
+ major: number;
50
+ minor: number;
51
+ links: string[];
52
+ atimeMs: number;
53
+ mtimeMs: number;
54
+ ctimeMs: number;
55
+ }
56
+ export interface DeviceMetaChange {
57
+ mode?: number;
58
+ uid?: number;
59
+ gid?: number;
60
+ atimeMs?: number | null;
61
+ mtimeMs?: number | null;
62
+ now?: boolean;
63
+ }
64
+ export interface DeviceLookup {
65
+ userId(name: string): Promise<number | undefined>;
66
+ groupId(name: string): Promise<number | undefined>;
67
+ }
68
+ interface DeviceState {
69
+ termios: Termios;
70
+ ispeed: number;
71
+ ospeed: number;
72
+ }
73
+ interface DeviceNode extends DeviceNodeInfo {
74
+ id: number;
75
+ client: number;
76
+ channel?: DeviceChannel;
77
+ opening: boolean;
78
+ saved?: DeviceState;
79
+ }
80
+ export interface DeviceOpener {
81
+ stamp: DeviceStamp;
82
+ guard?: Guard;
83
+ signal: AbortSignal;
84
+ }
85
+ export declare function devicesHook(hook: DeviceHook): DeviceHook;
86
+ export declare class DeviceNodes {
87
+ private readonly hooks;
88
+ private readonly nodes;
89
+ private readonly links;
90
+ private readonly lookup;
91
+ readonly users: UsersMode;
92
+ private next;
93
+ constructor(users: UsersMode, lookup: DeviceLookup);
94
+ register(client: number, hook: DeviceHook): () => void;
95
+ add(spec: DeviceSpec, client: number): Promise<number>;
96
+ remove(id: number): boolean;
97
+ private drop;
98
+ list(): DeviceNodeInfo[];
99
+ meta(path: string, change: DeviceMetaChange, guard?: Guard): void;
100
+ find(path: string): DeviceNode | undefined;
101
+ openTty(path: string): KernelTty | undefined;
102
+ open(path: string, flags: number, opener: DeviceOpener): Promise<OpenFile>;
103
+ }
104
+ export declare class DeviceChannel {
105
+ readonly tty: KernelTty;
106
+ readonly path: string;
107
+ private readonly inner;
108
+ private readonly reader;
109
+ private readonly writer;
110
+ private readonly streams;
111
+ private readonly onClosed;
112
+ private readonly gone;
113
+ private failure;
114
+ private readonly pending;
115
+ private queued;
116
+ private resume;
117
+ private waiters;
118
+ private closed;
119
+ ispeed: number;
120
+ ospeed: number;
121
+ dtr: boolean;
122
+ rts: boolean;
123
+ constructor(path: string, streams: DeviceStreams, saved: DeviceState | undefined, onClosed: (state: DeviceState) => void);
124
+ file(access: OpenAccess): OpenFile;
125
+ lost(err: KernelError): void;
126
+ private control;
127
+ private buffered;
128
+ private pump;
129
+ private send;
130
+ private check;
131
+ private read;
132
+ private ready;
133
+ private write;
134
+ private poll;
135
+ private changed;
136
+ private wake;
137
+ drain(signal?: AbortSignal): Promise<void>;
138
+ restore(): Promise<void>;
139
+ settings(): SerialSettings;
140
+ termios(): SerialTermios;
141
+ setTermios(termios: SerialTermios, how: {
142
+ drain?: boolean;
143
+ flush?: boolean;
144
+ extended?: boolean;
145
+ }, signal?: AbortSignal): Promise<void>;
146
+ private bits;
147
+ modem(): Promise<number>;
148
+ setModem(bits: number): Promise<void>;
149
+ private signals;
150
+ sendBreak(ms: number, signal?: AbortSignal): Promise<void>;
151
+ flush(input: boolean, output: boolean): Promise<void>;
152
+ ioctl(request: number, arg: unknown, signal?: AbortSignal): Promise<unknown>;
153
+ close(): Promise<void>;
154
+ }
155
+ export {};
@@ -53,7 +53,9 @@ export interface EmbedderLookup {
53
53
  groupId(name: string): Promise<number | undefined>;
54
54
  userId(name: string): Promise<number | undefined>;
55
55
  }
56
+ export declare function lineOf(err: unknown): string;
56
57
  export declare function embedderFailure(err: unknown): KernelError;
58
+ export declare function interruptible<T>(work: Promise<T>, signal: AbortSignal | undefined): Promise<T>;
57
59
  export declare class EmbedderChannel {
58
60
  readonly access: OpenAccess;
59
61
  readonly owner: number;
@@ -1,9 +1,10 @@
1
1
  import type { ClipboardChannel } from './clipboard.js';
2
+ import type { DeviceChannel } from './devices.js';
2
3
  import type { EmbedderChannel } from './embedder.js';
3
4
  import type { PtyPair } from './pty.js';
4
5
  import type { SealedChannel } from './sealed.js';
5
6
  import type { KernelTty } from './tty.js';
6
- export type KernelErrno = 'EBADF' | 'EPROTO' | 'EDEADLK' | 'ENOLCK' | 'EEXIST' | 'ELOOP' | 'EOVERFLOW' | 'ENAMETOOLONG' | 'EPIPE' | 'EMFILE' | 'EINVAL' | 'ENOENT' | 'ENOTDIR' | 'ENOEXEC' | 'ECHILD' | 'ENOSYS' | 'ESPIPE' | 'ENOSPC' | 'EINTR' | 'ESRCH' | 'ENOTTY' | 'ENXIO' | 'EPERM' | 'EIO' | 'EACCES' | 'EAGAIN' | 'ENOTSOCK' | 'EAFNOSUPPORT' | 'EPROTONOSUPPORT' | 'EPROTOTYPE' | 'EOPNOTSUPP' | 'EADDRINUSE' | 'EADDRNOTAVAIL' | 'ENETUNREACH' | 'ECONNREFUSED' | 'EINPROGRESS' | 'EISCONN' | 'ENOTCONN' | 'EROFS' | 'EFBIG' | 'EALREADY' | 'ETIMEDOUT' | 'ECONNABORTED' | 'EHOSTUNREACH' | 'ECONNRESET' | 'EMSGSIZE' | 'EDESTADDRREQ' | 'ENOPROTOOPT' | 'ENOTSUP' | 'EILSEQ';
7
+ export type KernelErrno = 'EBADF' | 'EPROTO' | 'EDEADLK' | 'ENOLCK' | 'EEXIST' | 'ELOOP' | 'EOVERFLOW' | 'ENAMETOOLONG' | 'EPIPE' | 'EMFILE' | 'EINVAL' | 'ENOENT' | 'ENOTDIR' | 'ENOEXEC' | 'ECHILD' | 'ENOSYS' | 'ESPIPE' | 'ENOSPC' | 'EINTR' | 'ESRCH' | 'ENOTTY' | 'ENXIO' | 'EPERM' | 'EIO' | 'EACCES' | 'EAGAIN' | 'ENOTSOCK' | 'EAFNOSUPPORT' | 'EPROTONOSUPPORT' | 'EPROTOTYPE' | 'EOPNOTSUPP' | 'EADDRINUSE' | 'EADDRNOTAVAIL' | 'ENETUNREACH' | 'ECONNREFUSED' | 'EINPROGRESS' | 'EISCONN' | 'ENOTCONN' | 'EROFS' | 'EFBIG' | 'EALREADY' | 'ETIMEDOUT' | 'ECONNABORTED' | 'EHOSTUNREACH' | 'ECONNRESET' | 'EMSGSIZE' | 'EDESTADDRREQ' | 'ENOPROTOOPT' | 'ENOTSUP' | 'EILSEQ' | 'EBUSY';
7
8
  export declare class KernelError extends Error {
8
9
  readonly code: KernelErrno;
9
10
  readonly detail?: string;
@@ -41,6 +42,7 @@ export interface KernelFile {
41
42
  sealed?: SealedChannel;
42
43
  clipboard?: ClipboardChannel;
43
44
  embedder?: EmbedderChannel;
45
+ device?: DeviceChannel;
44
46
  held?: true;
45
47
  heldMeta?: HeldMeta;
46
48
  identity?: object;
@@ -7,6 +7,7 @@ import type { ChildForker, ChildSpawner } from './children.js';
7
7
  import type { ClipboardBroker } from './clipboard.js';
8
8
  import { type CpuTimes } from './cpu-clock.js';
9
9
  import { type Cred } from './cred.js';
10
+ import type { DeviceNodes } from './devices.js';
10
11
  import type { EmbedderBroker } from './embedder.js';
11
12
  import { type FdTable, type OpenFile } from './fd-table.js';
12
13
  import type { FifoTable } from './fifo.js';
@@ -62,6 +63,7 @@ export interface SpawnWasmOptions {
62
63
  uid: number;
63
64
  };
64
65
  };
66
+ devices?: DeviceNodes;
65
67
  readonlyAt?: (path: string) => boolean;
66
68
  dac?: Dac;
67
69
  identity?: () => Promise<{
@@ -10,6 +10,7 @@ import { type SudoCall, type SudoResult, type SudoStdin, type VisudoCall, type V
10
10
  import { type ChildForker, type ChildSpawner, type ChildStdio, type InheritedSlot } from './children.js';
11
11
  import type { ClipboardBroker } from './clipboard.js';
12
12
  import { type Cred, type CredChange } from './cred.js';
13
+ import type { DeviceMetaChange, DeviceNodes } from './devices.js';
13
14
  import { type EmbedderBroker } from './embedder.js';
14
15
  import { type EpollSyscall } from './epoll.js';
15
16
  import { type DeviceAccess, type FdTable, type HeldMeta, type KernelFdKind, type OpenFile } from './fd-table.js';
@@ -235,6 +236,20 @@ export type WasmSyscall = {
235
236
  op: 'fd-open-embedder';
236
237
  flags: number;
237
238
  } | {
239
+ op: 'fd-dev-nodes';
240
+ } | {
241
+ op: 'fd-open-dev';
242
+ path: string;
243
+ flags: number;
244
+ } | {
245
+ op: 'fd-dev-ioctl';
246
+ fd: number;
247
+ request: number;
248
+ arg?: unknown;
249
+ } | ({
250
+ op: 'fd-dev-meta';
251
+ path: string;
252
+ } & DeviceMetaChange) | {
238
253
  op: 'tty-get';
239
254
  fd: number;
240
255
  } | {
@@ -242,6 +257,7 @@ export type WasmSyscall = {
242
257
  fd: number;
243
258
  termios: Termios;
244
259
  flush?: boolean;
260
+ drain?: boolean;
245
261
  } | {
246
262
  op: 'tty-winsz';
247
263
  fd: number;
@@ -380,6 +396,7 @@ export interface WasmProcessOptions {
380
396
  uid: number;
381
397
  };
382
398
  embedderName?: string;
399
+ devices?: DeviceNodes;
383
400
  readonlyAt?: (path: string) => boolean;
384
401
  guard?: {
385
402
  dac: Dac;
@@ -521,6 +538,9 @@ export declare class WasmProcess {
521
538
  private complainLine;
522
539
  private embedderCaller;
523
540
  private closeFd;
541
+ private openDev;
542
+ private devMeta;
543
+ private devIoctl;
524
544
  private openEmbedder;
525
545
  complain(line: string): Promise<boolean>;
526
546
  private clipboardComplaint;
@@ -0,0 +1,73 @@
1
+ import type { Termios } from './tty.js';
2
+ export declare const IOCTL: {
3
+ readonly TCGETS: 21505;
4
+ readonly TCSETS: 21506;
5
+ readonly TCSETSW: 21507;
6
+ readonly TCSETSF: 21508;
7
+ readonly TCSBRK: 21513;
8
+ readonly TCFLSH: 21515;
9
+ readonly TIOCEXCL: 21516;
10
+ readonly TIOCNXCL: 21517;
11
+ readonly TIOCSCTTY: 21518;
12
+ readonly TIOCGPGRP: 21519;
13
+ readonly TIOCSPGRP: 21520;
14
+ readonly TIOCOUTQ: 21521;
15
+ readonly TIOCGWINSZ: 21523;
16
+ readonly TIOCSWINSZ: 21524;
17
+ readonly TIOCMGET: 21525;
18
+ readonly TIOCMBIS: 21526;
19
+ readonly TIOCMBIC: 21527;
20
+ readonly TIOCMSET: 21528;
21
+ readonly FIONREAD: 21531;
22
+ readonly TIOCNOTTY: 21538;
23
+ readonly TCSBRKP: 21541;
24
+ readonly TIOCSBRK: 21543;
25
+ readonly TIOCCBRK: 21544;
26
+ readonly TCGETS2: 2150388778;
27
+ readonly TCSETS2: 1076646955;
28
+ readonly TCSETSW2: 1076646956;
29
+ readonly TCSETSF2: 1076646957;
30
+ };
31
+ export declare const FILE_IOCTLS: ReadonlySet<number>;
32
+ export declare const TERMIOS_GETS: ReadonlySet<number>;
33
+ export declare const TERMIOS_SETS: ReadonlySet<number>;
34
+ export declare const INT_OUT: ReadonlySet<number>;
35
+ export declare const INT_IN: ReadonlySet<number>;
36
+ export declare const INT_ARG: ReadonlySet<number>;
37
+ export declare const TIOCM: {
38
+ readonly DTR: 2;
39
+ readonly RTS: 4;
40
+ readonly CTS: 32;
41
+ readonly CD: 64;
42
+ readonly RI: 128;
43
+ readonly DSR: 256;
44
+ };
45
+ export interface SerialTermios extends Termios {
46
+ c_ispeed?: number;
47
+ c_ospeed?: number;
48
+ }
49
+ export interface SerialSettings {
50
+ baudRate: number;
51
+ dataBits: number;
52
+ parity: 'none' | 'even' | 'odd';
53
+ stopBits: 1 | 2;
54
+ flowControl: 'none' | 'hardware';
55
+ }
56
+ export declare const CBAUD = 4111;
57
+ export declare const BOTHER = 4096;
58
+ export declare function speedOf(code: number): number | undefined;
59
+ export declare function codeOf(speed: number): number;
60
+ export declare function speedsOf(termios: SerialTermios, current: {
61
+ ispeed: number;
62
+ ospeed: number;
63
+ }, extended: boolean): {
64
+ ispeed: number;
65
+ ospeed: number;
66
+ };
67
+ export declare function settingsOf(cflag: number, baudRate: number): SerialSettings;
68
+ export declare function sameSettings(a: SerialSettings, b: SerialSettings): boolean;
69
+ export declare const SERIAL_CFLAG: number;
70
+ export declare const SERIAL_LFLAG: number;
71
+ export declare const SERIAL_OFLAG = 4;
72
+ export declare function ioctlArg(view: DataView, request: number, arg: number): unknown;
73
+ export declare function ioctlResult(view: DataView, request: number, arg: number, result: unknown): void;
@@ -12,6 +12,7 @@ import type { KernelFs, UsersMode } from './fs/types.js';
12
12
  import { type UnlinkOwner } from './fs/unlinked.js';
13
13
  import { FsWatchers } from './fs/watch.js';
14
14
  import { type ClipboardHook } from './kernel/clipboard.js';
15
+ import { type DeviceHook, DeviceNodes } from './kernel/devices.js';
15
16
  import { EmbedderBroker, type EmbedderHook } from './kernel/embedder.js';
16
17
  type EmbedderSession = {
17
18
  client: number;
@@ -75,6 +76,7 @@ export interface LauncherOptions {
75
76
  sealedFetch?: SealedFetchHook;
76
77
  clipboard?: ClipboardHook;
77
78
  embedder?: EmbedderHook;
79
+ devices?: DeviceHook;
78
80
  approve?: ApproveHook;
79
81
  sudoTimeoutMs?: number;
80
82
  sudoClock?: {
@@ -295,6 +297,7 @@ export declare class Launcher {
295
297
  private readonly scrubs;
296
298
  private readonly clipboard;
297
299
  readonly embedder: EmbedderBroker;
300
+ readonly devices: DeviceNodes;
298
301
  private readonly rootFs;
299
302
  private fileWatches;
300
303
  private nextPid;
@@ -457,6 +460,7 @@ export declare class Launcher {
457
460
  private imageOf;
458
461
  credOf(pid: number): Cred;
459
462
  private wireSealed;
463
+ private deviceNodes;
460
464
  private embedderBroker;
461
465
  sessionOf(pid: number): EmbedderSession;
462
466
  tagOf(pid: number): string | undefined;
@@ -7,8 +7,9 @@ import type { Attestation, AttestTombstone } from './fs/attest.js';
7
7
  import type { DenialHook } from './fs/dac.js';
8
8
  import type { Protection } from './fs/protect.js';
9
9
  import { type UsersMode } from './fs/types.js';
10
- import type { ConnectOptions, KernelGroups, KernelIntegrity, KernelSealed, KernelUsers, RunOptions, RunResult, Terminal, TerminalOptions } from './index.js';
10
+ import type { ConnectOptions, KernelDevices, KernelGroups, KernelIntegrity, KernelSealed, KernelUsers, RunOptions, RunResult, Terminal, TerminalOptions } from './index.js';
11
11
  import type { ClipboardHook } from './kernel/clipboard.js';
12
+ import { type DeviceHook } from './kernel/devices.js';
12
13
  import { type EmbedderHook } from './kernel/embedder.js';
13
14
  import type { RouteTable } from './kernel/net/routes.js';
14
15
  import { type SealedOption } from './kernel/net/sealed-fetch.js';
@@ -25,8 +26,9 @@ export { type AttachOptions, attachKernel, type ClientEnded, type ClientFetchReq
25
26
  export type { FacadeConnection, FacadeHook, FacadeInfo, FacadeSpec, FacadeSpecs, } from './facade/types.js';
26
27
  export type { Attestation, AttestedDir, AttestOptions, AttestTombstone } from './fs/attest.js';
27
28
  export type { Denial, DenialHook } from './fs/dac.js';
28
- export type { ConnectOptions, CwdMissing, Ended, KernelGroups, KernelIntegrity, KernelSealed, KernelUsers, NetworkUplink, ResolveAnswer, ResolveFamily, RouteTable, RunOptions, RunResult, Terminal, TerminalOptions, TerminalSignal, } from './index.js';
29
+ export type { ConnectOptions, CwdMissing, DeviceAddOptions, DeviceNodeHandle, Ended, KernelDevices, KernelGroups, KernelIntegrity, KernelSealed, KernelUsers, NetworkUplink, ResolveAnswer, ResolveFamily, RouteTable, RunOptions, RunResult, Terminal, TerminalOptions, TerminalSignal, } from './index.js';
29
30
  export type { ClipboardHook, ClipboardStamp } from './kernel/clipboard.js';
31
+ export type { DeviceHook, DeviceOpenRequest, DeviceSignals, DeviceSpec, DeviceStamp, DeviceStreams, } from './kernel/devices.js';
30
32
  export type { EmbedderHook, EmbedderKindPolicy, EmbedderReply, EmbedderRequest, EmbedderStamp, } from './kernel/embedder.js';
31
33
  export { SEALED_FETCH_VERSION, type SealedFetchHook, type SealedFetchRequest, type SealedOption, } from './kernel/net/sealed-fetch.js';
32
34
  export type { SealedAbortReason, SealedCaller, SealedHook, SealedRequest, SealedRequester, } from './kernel/sealed.js';
@@ -67,6 +69,7 @@ export interface NodeKernelOptions {
67
69
  sealed?: SealedOption;
68
70
  clipboard?: ClipboardHook;
69
71
  requests?: EmbedderHook;
72
+ devices?: DeviceHook;
70
73
  approve?: ApproveHook;
71
74
  protect?: Protection;
72
75
  cron?: {
@@ -104,6 +107,7 @@ export interface NodeKernel {
104
107
  sudoRun(request: SudoReplay, options?: SudoRunOptions): Promise<SudoRun>;
105
108
  readonly users: KernelUsers;
106
109
  readonly groups: KernelGroups;
110
+ readonly devices: KernelDevices;
107
111
  setRoutes(routes: RouteTable): Promise<void>;
108
112
  updateTransportTraits(): Promise<boolean>;
109
113
  mount(spec: MountSpec): Promise<MountEntry>;
@@ -17,6 +17,7 @@ export interface DevOpened {
17
17
  file: boolean;
18
18
  read: boolean;
19
19
  write: boolean;
20
+ device?: boolean;
20
21
  }
21
22
  export declare function devOpen(abs: string, o: JsOpenOptions): DevStep<DevOpened>;
22
23
  export declare function devAsync<T>(kernel: {
@@ -29,15 +30,38 @@ export interface StreamIo {
29
30
  read(fd: number, max: number): Promise<Uint8Array>;
30
31
  write(fd: number, data: Uint8Array): Promise<void>;
31
32
  close(fd: number): Promise<void>;
33
+ ioctl?(fd: number, request: number, arg?: unknown): Promise<unknown>;
32
34
  }
33
35
  export interface StreamSyncIo {
34
36
  read(fd: number, max: number): Uint8Array;
35
37
  write(fd: number, data: Uint8Array): void;
36
38
  close(fd: number): void;
39
+ ioctl?(fd: number, request: number, arg?: unknown): unknown;
37
40
  }
41
+ export declare function ioctlRequest(fd: number, request: number, arg?: unknown): SyncSabRequestBody;
42
+ export interface JsSerialTermios {
43
+ c_iflag: number;
44
+ c_oflag: number;
45
+ c_cflag: number;
46
+ c_lflag: number;
47
+ c_cc: number[];
48
+ ispeed: number;
49
+ ospeed: number;
50
+ }
51
+ export interface JsModem {
52
+ dtr: boolean;
53
+ rts: boolean;
54
+ cts: boolean;
55
+ dsr: boolean;
56
+ cd: boolean;
57
+ ri: boolean;
58
+ }
59
+ export type JsTermiosWhen = 'now' | 'drain' | 'flush';
60
+ export type JsFlushQueue = 'input' | 'output' | 'both';
38
61
  export interface StreamAccess {
39
62
  read: boolean;
40
63
  write: boolean;
64
+ device?: boolean;
41
65
  }
42
66
  export declare function streamFile(fd: number, path: string, io: StreamIo, access: StreamAccess): {
43
67
  file: JsFile;
@@ -1,3 +1,4 @@
1
+ import type { DeviceMetaChange, DeviceNodeInfo } from '../kernel/devices.js';
1
2
  import type { HeldMeta, PollState } from '../kernel/fd-table.js';
2
3
  import type { MountLine, ProcessListing } from '../kernel/proc-info.js';
3
4
  import type { Termios } from '../kernel/tty.js';
@@ -56,7 +57,11 @@ export interface ProcessSys {
56
57
  ttyNames?(): string[];
57
58
  ttyOwner?(name: string): TtyOwner | null;
58
59
  tcgets?(fd: number): Termios;
59
- tcsets?(fd: number, termios: Termios, flush?: boolean): void;
60
+ tcsets?(fd: number, termios: Termios, flush?: boolean, drain?: boolean): void;
61
+ devNodes?(): DeviceNodeInfo[];
62
+ openDev?(path: string, flags: number): number;
63
+ devIoctl?(fd: number, request: number, arg?: unknown): unknown;
64
+ devMeta?(path: string, change: DeviceMetaChange): void;
60
65
  winsize?(fd: number): [number, number];
61
66
  openPty?(): number;
62
67
  openPts?(n: number, noctty: boolean): number;
@@ -87,6 +92,7 @@ export interface ProcessStream {
87
92
  sliccCloexec?: boolean;
88
93
  sliccKernelSocket?: boolean;
89
94
  sliccKernelFifo?: string;
95
+ sliccDevice?: boolean;
90
96
  path?: string;
91
97
  flags: number;
92
98
  position: number;
@@ -174,6 +180,10 @@ export declare class KernelStreams {
174
180
  private creatingTerminal;
175
181
  private useTerminalNodes;
176
182
  private usePtsNodes;
183
+ private useDeviceNodes;
184
+ private useDeviceMeta;
185
+ private liveDeviceStat;
186
+ private openDeviceNode;
177
187
  private ptyNode;
178
188
  private ptsTarget;
179
189
  private ttyNode;
@@ -11,6 +11,7 @@ export interface PtyKernel {
11
11
  setControllingTerminal(kfd: number): void;
12
12
  setPacketMode(kfd: number, on: boolean): void;
13
13
  setWinsize(kfd: number, rows: number, cols: number): void;
14
+ devIoctl?(fd: number, request: number, arg?: unknown): unknown;
14
15
  }
15
16
  export interface PtyIoctlDeps {
16
17
  fs(): ProcessFs | undefined;
@@ -133,6 +133,7 @@ export declare class WasiFds {
133
133
  resolve(dirfd: number, path: string): string;
134
134
  private joined;
135
135
  private openKernelDevice;
136
+ private openSerial;
136
137
  private openCharDevice;
137
138
  open(path: string, oflags: number, rights: bigint, fdflags: number, mode?: number, nofollow?: boolean): number;
138
139
  private nofollow;
@@ -7,4 +7,5 @@ export declare function sliccTty(mem: WasiMemory, fds: WasiFds, kernel: WasiKern
7
7
  tcgetattr: (fd: number, ptr: number) => undefined;
8
8
  tcsetattr: (fd: number, actions: number, ptr: number) => undefined;
9
9
  winsize: (fd: number, ptr: number) => undefined;
10
+ ioctl: (fd: number, request: number, arg: number) => undefined;
10
11
  };