@ai-ecoverse/slicc-kernel 1.108.5 → 1.110.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/README.md +22 -2
- package/dist/index.js.map +2 -2
- package/dist/kernel-worker.js +554 -311
- package/dist/kernel-worker.js.map +4 -4
- package/dist/node-process-worker.js +2 -1
- package/dist/node-process-worker.js.map +3 -3
- package/dist/node.js +272 -29
- package/dist/node.js.map +4 -4
- package/dist/process-worker.js +2 -1
- package/dist/process-worker.js.map +3 -3
- package/dist/types/commands.d.ts +6 -0
- package/dist/types/cron/command.d.ts +4 -0
- package/dist/types/cron/crontab.d.ts +27 -0
- package/dist/types/index.d.ts +1 -1
- package/dist/types/kernel/host.d.ts +1 -0
- package/dist/types/kernel/process.d.ts +4 -1
- package/dist/types/launcher.d.ts +4 -1
- package/dist/types/process/js/js-context.d.ts +13 -0
- package/package.json +1 -6
package/dist/types/commands.d.ts
CHANGED
|
@@ -17,6 +17,11 @@ export interface Command {
|
|
|
17
17
|
imports?: string;
|
|
18
18
|
refused?: string;
|
|
19
19
|
shows?: string;
|
|
20
|
+
variants?: CommandVariant[];
|
|
21
|
+
}
|
|
22
|
+
export interface CommandVariant {
|
|
23
|
+
env: Record<string, string>;
|
|
24
|
+
wasm: string;
|
|
20
25
|
}
|
|
21
26
|
interface Manifest {
|
|
22
27
|
name?: unknown;
|
|
@@ -32,6 +37,7 @@ interface Manifest {
|
|
|
32
37
|
replaces?: unknown;
|
|
33
38
|
};
|
|
34
39
|
}
|
|
40
|
+
export declare function variantFor(variants: readonly CommandVariant[] | undefined, env: Record<string, string>): string | undefined;
|
|
35
41
|
export declare function commandsOf(pkg: string, manifest: Manifest): Command[];
|
|
36
42
|
export declare function pnpmGlobalRoots(fs: KernelFs, home: string): Promise<string[]>;
|
|
37
43
|
export declare function engineRefusal(manifest: Manifest, kernel: string): string | undefined;
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { Command } from '../commands.js';
|
|
2
|
+
export declare const CRONTAB_PATH = "/usr/bin/crontab";
|
|
3
|
+
export declare const CRONTAB_COMMAND: Command;
|
|
4
|
+
export declare const CRONTAB_SOURCE = "export default async function crontab(ctx) {\n const say = (fd, text) => ctx.write(fd, text).catch(() => undefined);\n const usage = async () => {\n await say(2, \"usage: crontab [-u user] { -l | -r | -e | file | - }\\n\");\n return 1;\n };\n const args = ctx.argv.slice(1);\n let user;\n let action;\n let file;\n for (let i = 0; i < args.length; i++) {\n const arg = args[i];\n if (arg === \"-u\") {\n user = args[++i];\n if (user === undefined) return usage();\n } else if (arg === \"-l\" || arg === \"-r\" || arg === \"-e\") {\n if (action !== undefined) return usage();\n action = arg.slice(1);\n } else if (arg === \"-\" || !arg.startsWith(\"-\")) {\n if (file !== undefined) return usage();\n file = arg;\n } else return usage();\n }\n if ((action === undefined) === (file === undefined)) return usage();\n const call = (c) => ctx.crontab(user === undefined ? c : { ...c, user });\n const failed = async (answer) => {\n await say(2, answer.error + \"\\n\");\n return 1;\n };\n const decode = (bytes) => new TextDecoder().decode(bytes);\n if (action === \"l\") {\n const answer = await call({ action: \"list\" });\n if (answer.error !== undefined) return failed(answer);\n await say(1, answer.text);\n return 0;\n }\n if (action === \"r\") {\n const answer = await call({ action: \"remove\" });\n return answer.error !== undefined ? failed(answer) : 0;\n }\n if (action === \"e\") return edit();\n let text;\n try {\n if (file === \"-\") {\n const stream = new TextDecoder();\n const parts = [];\n for (;;) {\n const chunk = await ctx.read(0);\n if (chunk.length === 0) break;\n parts.push(stream.decode(chunk, { stream: true }));\n }\n text = parts.join(\"\") + stream.decode();\n } else text = decode(await ctx.fs.readFile(ctx.resolve(file)));\n } catch (err) {\n await say(2, \"crontab: \" + file + \": \" + (err && err.code ? err.code : String(err)) + \"\\n\");\n return 1;\n }\n const answer = await call({ action: \"install\", text });\n return answer.error !== undefined ? failed(answer) : 0;\n\n async function edit() {\n const editor = ctx.env.VISUAL || ctx.env.EDITOR;\n if (!editor) {\n await say(2, \"crontab: set VISUAL or EDITOR to edit, or install a file with crontab <file>\\n\");\n return 1;\n }\n const current = await call({ action: \"list\" });\n const before = current.error === undefined ? current.text : \"\";\n if (current.error !== undefined && !current.error.startsWith(\"no crontab for \")) return failed(current);\n const tmp = \"/tmp/crontab.\" + ctx.pid + \".\" + crypto.randomUUID();\n try {\n const file = await ctx.open(tmp, { write: true, create: true, exclusive: true, mode: 0o600 });\n await file.write(0, new TextEncoder().encode(before));\n await file.close();\n } catch (err) {\n await say(2, \"crontab: \" + tmp + \": \" + (err && err.code ? err.code : String(err)) + \"\\n\");\n return 1;\n }\n const child = await ctx.spawn({ argv: [\"/bin/bash\", \"-c\", editor + ' \"$1\"', \"crontab\", tmp] });\n const ended = await ctx.wait(child.pid);\n if (ended.status !== 0) {\n await say(2, \"crontab: the editor exited with status \" + ended.status + \", crontab not changed\\n\");\n await ctx.fs.rm(tmp).catch(() => undefined);\n return 1;\n }\n const after = decode(await ctx.fs.readFile(tmp));\n if (after === before) {\n await say(2, \"crontab: no changes made to crontab\\n\");\n await ctx.fs.rm(tmp).catch(() => undefined);\n return 0;\n }\n const answer = await call({ action: \"install\", text: after });\n if (answer.error !== undefined) {\n await say(2, answer.error + \"\\ncrontab: your edit is kept in \" + tmp + \"\\n\");\n return 1;\n }\n await ctx.fs.rm(tmp).catch(() => undefined);\n return 0;\n }\n}\n";
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { KernelFs } from '../fs/types.js';
|
|
2
|
+
import type { Cred } from '../kernel/cred.js';
|
|
3
|
+
import type { Account } from '../users.js';
|
|
4
|
+
export declare const CRONTAB_MAX: number;
|
|
5
|
+
export interface CrontabCall {
|
|
6
|
+
op: 'proc-crontab';
|
|
7
|
+
action: 'list' | 'remove' | 'install';
|
|
8
|
+
user?: string;
|
|
9
|
+
text?: string;
|
|
10
|
+
}
|
|
11
|
+
export type CrontabResult = {
|
|
12
|
+
text: string;
|
|
13
|
+
} | {
|
|
14
|
+
error: string;
|
|
15
|
+
};
|
|
16
|
+
export interface CrontabsOptions {
|
|
17
|
+
fs: KernelFs;
|
|
18
|
+
owners: boolean;
|
|
19
|
+
lookup(user: string | number): Promise<Account | undefined>;
|
|
20
|
+
}
|
|
21
|
+
export declare function crontabCall(req: Partial<CrontabCall>): CrontabCall | undefined;
|
|
22
|
+
export declare class Crontabs {
|
|
23
|
+
private readonly o;
|
|
24
|
+
constructor(options: CrontabsOptions);
|
|
25
|
+
request(cred: Readonly<Cred>, call: CrontabCall): Promise<CrontabResult>;
|
|
26
|
+
private install;
|
|
27
|
+
}
|
package/dist/types/index.d.ts
CHANGED
|
@@ -34,7 +34,7 @@ export { serveHostfsPort } from './mount/hostfs.js';
|
|
|
34
34
|
export type { MountEntry, MountSpec } from './mount/mount-fs.js';
|
|
35
35
|
export type { ProcessMountPolicy, ProcessMountRequest } from './mount/syscall.js';
|
|
36
36
|
export type { JsChild, JsExited, JsSpawnOptions, JsStdio } from './process/js/js-children.js';
|
|
37
|
-
export type { JsFdStatus, JsFdType, JsFile, JsOpenOptions, JsProgramContext, JsSignal, JsSudoAnswer, } from './process/js/js-context.js';
|
|
37
|
+
export type { JsCrontabAnswer, JsCrontabCall, JsFdStatus, JsFdType, JsFile, JsOpenOptions, JsProgramContext, JsSignal, JsSudoAnswer, } from './process/js/js-context.js';
|
|
38
38
|
export type { JsStatFs } from './process/js/js-io.js';
|
|
39
39
|
export type { JsAddress, JsConnection, JsConnectOptions, JsListener, JsListenOptions, JsNet, } from './process/js/js-net.js';
|
|
40
40
|
export type { JsRunOptions, JsRunResult, JsRunStdio } from './process/js/js-run.js';
|
|
@@ -67,6 +67,7 @@ export interface SpawnWasmOptions {
|
|
|
67
67
|
writesBack?: (pid: number) => boolean;
|
|
68
68
|
processes?: () => ProcessListing;
|
|
69
69
|
sudo?: WasmProcessOptions['sudo'];
|
|
70
|
+
crontab?: WasmProcessOptions['crontab'];
|
|
70
71
|
openFiles?: Set<VfsNodes>;
|
|
71
72
|
nodes?: VfsNodes;
|
|
72
73
|
statfs?: (path: string) => Promise<{
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type CrontabCall, type CrontabResult } from '../cron/crontab.js';
|
|
1
2
|
import { type Created, type Dac } from '../fs/dac.js';
|
|
2
3
|
import type { KernelFs } from '../fs/types.js';
|
|
3
4
|
import type { MountCall } from '../mount/syscall.js';
|
|
@@ -255,7 +256,7 @@ export type WasmSyscall = {
|
|
|
255
256
|
op: 'proc-captured';
|
|
256
257
|
pid: number;
|
|
257
258
|
slot: number;
|
|
258
|
-
} | SudoCall | RunRequest | {
|
|
259
|
+
} | SudoCall | CrontabCall | RunRequest | {
|
|
259
260
|
op: 'proc-exit';
|
|
260
261
|
status: number;
|
|
261
262
|
} | {
|
|
@@ -368,6 +369,7 @@ export interface WasmProcessOptions {
|
|
|
368
369
|
writesBack?: (pid: number) => boolean;
|
|
369
370
|
processes?: () => ProcessListing;
|
|
370
371
|
sudo?: (call: SudoCall, signal: AbortSignal) => Promise<SudoResult>;
|
|
372
|
+
crontab?: (call: CrontabCall) => Promise<CrontabResult>;
|
|
371
373
|
openFiles?: Set<VfsNodes>;
|
|
372
374
|
nodes?: VfsNodes;
|
|
373
375
|
mounts?: () => MountLine[];
|
|
@@ -517,6 +519,7 @@ export declare class WasmProcess {
|
|
|
517
519
|
private socketSyscall;
|
|
518
520
|
private tty;
|
|
519
521
|
private procSyscall;
|
|
522
|
+
private crontab;
|
|
520
523
|
private signalSyscall;
|
|
521
524
|
private reapsChildren;
|
|
522
525
|
private sudo;
|
package/dist/types/launcher.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { CdpHosts } from './cdp/hosts.js';
|
|
2
2
|
import type { CdpHook } from './cdp/types.js';
|
|
3
|
-
import { type Abi, type Command } from './commands.js';
|
|
3
|
+
import { type Abi, type Command, type CommandVariant } from './commands.js';
|
|
4
4
|
import type { CronClock } from './cron/clock.js';
|
|
5
5
|
import { CronService } from './cron/service.js';
|
|
6
6
|
import { FacadeHosts } from './facade/hosts.js';
|
|
@@ -129,6 +129,7 @@ interface Target {
|
|
|
129
129
|
imports?: string;
|
|
130
130
|
preopenRoot?: boolean;
|
|
131
131
|
asked?: string;
|
|
132
|
+
variants?: readonly CommandVariant[];
|
|
132
133
|
}
|
|
133
134
|
export declare function tagOption(tag: unknown): void;
|
|
134
135
|
export declare function expandDefaults(defaults: Readonly<Record<string, string>> | undefined, env: Readonly<Record<string, string>>): Record<string, string>;
|
|
@@ -226,6 +227,7 @@ export declare class Launcher {
|
|
|
226
227
|
readonly boot: number;
|
|
227
228
|
readonly bootId: `${string}-${string}-${string}-${string}-${string}`;
|
|
228
229
|
readonly cron: CronService;
|
|
230
|
+
private crontabs;
|
|
229
231
|
private terminals;
|
|
230
232
|
constructor(options: LauncherOptions);
|
|
231
233
|
private cronService;
|
|
@@ -318,6 +320,7 @@ export declare class Launcher {
|
|
|
318
320
|
private timesOf;
|
|
319
321
|
list(viewer?: Readonly<Cred>): ProcessInfo[];
|
|
320
322
|
private threadsOf;
|
|
323
|
+
private crontab;
|
|
321
324
|
private sudo;
|
|
322
325
|
private spawner;
|
|
323
326
|
private childGroup;
|
|
@@ -76,6 +76,7 @@ export interface JsProgramContext {
|
|
|
76
76
|
wait(pid: number, options?: JsWaitOptions): Promise<JsExited>;
|
|
77
77
|
kill(pid: number, signal?: JsSignal): Promise<void>;
|
|
78
78
|
sudo(args: readonly string[]): Promise<JsSudoAnswer>;
|
|
79
|
+
crontab(call: JsCrontabCall): Promise<JsCrontabAnswer>;
|
|
79
80
|
umask(mask?: number): Promise<number>;
|
|
80
81
|
net: JsNet;
|
|
81
82
|
websocket(url: string | URL, options?: JsWebSocketOptions): Promise<JsWebSocket>;
|
|
@@ -85,6 +86,18 @@ export interface JsProgramContext {
|
|
|
85
86
|
onUncaught(listener: JsStrayListener): () => void;
|
|
86
87
|
onUnhandledRejection(listener: JsStrayListener): () => void;
|
|
87
88
|
}
|
|
89
|
+
export interface JsCrontabCall {
|
|
90
|
+
action: 'list' | 'remove' | 'install';
|
|
91
|
+
user?: string;
|
|
92
|
+
text?: string;
|
|
93
|
+
}
|
|
94
|
+
export type JsCrontabAnswer = {
|
|
95
|
+
text: string;
|
|
96
|
+
error?: undefined;
|
|
97
|
+
} | {
|
|
98
|
+
error: string;
|
|
99
|
+
text?: undefined;
|
|
100
|
+
};
|
|
88
101
|
export type JsSudoAnswer = {
|
|
89
102
|
error: string;
|
|
90
103
|
errno: string;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ai-ecoverse/slicc-kernel",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.110.0",
|
|
4
4
|
"description": "SLICC's wasm-realm kernel: run Emscripten programs in the browser against OPFS, with fork, spawn, pipes and waitpid",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -93,10 +93,5 @@
|
|
|
93
93
|
"semantic-release": "25.0.9",
|
|
94
94
|
"typescript": "7.0.2",
|
|
95
95
|
"wabt": "1.0.39"
|
|
96
|
-
},
|
|
97
|
-
"overrides": {
|
|
98
|
-
"@ai-ecoverse/py-numpy": {
|
|
99
|
-
"@ai-ecoverse/wasix-python": "$@ai-ecoverse/wasix-python"
|
|
100
|
-
}
|
|
101
96
|
}
|
|
102
97
|
}
|