@ai-ecoverse/slicc-spectrum 1.56.0 → 1.56.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.
- package/README.md +2 -2
- package/dist/{chunk-YVJG5657.js → chunk-XYPGNJAO.js} +10 -3
- package/dist/chunk-XYPGNJAO.js.map +7 -0
- package/dist/slicc-kernel-model.js +5 -2
- package/dist/slicc-kernel-model.js.map +2 -2
- package/dist/slicc-terminal.js +1 -1
- package/dist/types/kernel/terminals.d.ts +2 -1
- package/dist/types/kernel-backend.d.ts +3 -1
- package/package.json +3 -3
- package/dist/chunk-YVJG5657.js.map +0 -7
package/README.md
CHANGED
|
@@ -58,7 +58,7 @@ Keystrokes reach `write` as the bytes a terminal would send: UTF-8 text, `\r` fo
|
|
|
58
58
|
|
|
59
59
|
### slicc-kernel
|
|
60
60
|
|
|
61
|
-
`kernelBackend(kernel, { argv, cwd, env })` adapts slicc-kernel's terminal API to the interface above. `argv` defaults to `['bash', '-i']`. It is typed structurally, so this package doesn't depend on slicc-kernel. If the session fails, its error message is printed and `exit` reports status 1.
|
|
61
|
+
`kernelBackend(kernel, { argv, cwd, user, env })` adapts slicc-kernel's terminal API to the interface above. `argv` defaults to `['bash', '-i']`. `user` (a name or uid, slicc-kernel 1.44 and later) is who the session runs as; without it the kernel runs it as `root`, with `HOME=/root`. It is typed structurally, so this package doesn't depend on slicc-kernel. If the session fails, its error message is printed and `exit` reports status 1.
|
|
62
62
|
|
|
63
63
|
```js
|
|
64
64
|
import { createKernel } from './node_modules/@ai-ecoverse/slicc-kernel/dist/index.js';
|
|
@@ -240,7 +240,7 @@ app.model = createKernelModel({ kernel, root, storage: localStorage, files: { sk
|
|
|
240
240
|
```
|
|
241
241
|
|
|
242
242
|
- **`KernelFiles`** lists the OPFS root as the tree, reads and writes files through the OPFS API, and removes them recursively. Directories in `skip` show up but aren't scanned; paths in `hide` (and everything under them) don't show up at all. `start()` rescans on every `FileSystemObserver` record, or every `interval` ms (default 2000) where the browser can't observe OPFS, and emits `files` and a `file` per changed file, so open tabs follow what the terminal writes. Without an agent there are no pending changes.
|
|
243
|
-
- **`KernelTerminals`** opens `bash -i` (or `argv`) in `cwd` (default `/home`) through `kernelBackend`, one session per terminal, as many as the user opens. `open` (default 1) is how many it starts with.
|
|
243
|
+
- **`KernelTerminals`** opens `bash -i` (or `argv`) in `cwd` (default `/home`) as `user` (default the kernel's, `root`) through `kernelBackend`, one session per terminal, as many as the user opens. `open` (default 1) is how many it starts with.
|
|
244
244
|
- Everything else is idle (`IdleAgent`, `IdleBrowser`, `IdleMemory`, `IdleMonitor`, `IdleSprinkles`, `IdleTray`, from `idleModel(storage)`): empty lists, and actions that need a backend throw. Settings are kept in `storage`. Leave their surfaces out of `surfaces`.
|
|
245
245
|
|
|
246
246
|
Each section is its own port, so an embedder can mix real and dummy per section, for example `{ ...createDummyModel(), files: new KernelFiles(root) }`.
|
|
@@ -21,7 +21,7 @@ function cwdWatcher(onCwd) {
|
|
|
21
21
|
pending = open >= 0 && !text.slice(open).match(/\x07|\x1b\\/) ? text.slice(open) : "";
|
|
22
22
|
};
|
|
23
23
|
}
|
|
24
|
-
function kernelBackend(kernel, { argv = ["bash", "-i"], cwd, env, onCwd } = {}) {
|
|
24
|
+
function kernelBackend(kernel, { argv = ["bash", "-i"], cwd, user, env, onCwd } = {}) {
|
|
25
25
|
return {
|
|
26
26
|
async open(sink, { cols, rows }) {
|
|
27
27
|
const watch = onCwd && cwdWatcher(onCwd);
|
|
@@ -29,7 +29,14 @@ function kernelBackend(kernel, { argv = ["bash", "-i"], cwd, env, onCwd } = {})
|
|
|
29
29
|
watch?.(bytes);
|
|
30
30
|
sink.output(bytes);
|
|
31
31
|
};
|
|
32
|
-
const terminal = await kernel.openTerminal(argv, {
|
|
32
|
+
const terminal = await kernel.openTerminal(argv, {
|
|
33
|
+
cwd,
|
|
34
|
+
...user === void 0 ? {} : { user },
|
|
35
|
+
env,
|
|
36
|
+
cols,
|
|
37
|
+
rows,
|
|
38
|
+
onData
|
|
39
|
+
});
|
|
33
40
|
terminal.exited.then(
|
|
34
41
|
(status) => sink.exit(status),
|
|
35
42
|
(error) => {
|
|
@@ -53,4 +60,4 @@ export {
|
|
|
53
60
|
cwdPromptCommand,
|
|
54
61
|
kernelBackend
|
|
55
62
|
};
|
|
56
|
-
//# sourceMappingURL=chunk-
|
|
63
|
+
//# sourceMappingURL=chunk-XYPGNJAO.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/kernel-backend.ts"],
|
|
4
|
+
"sourcesContent": ["import type { TerminalBackend, TerminalSignal } from './backend.ts';\n\nexport interface KernelTerminal {\n readonly exited: Promise<number>;\n write(data: Uint8Array): void;\n resize(cols: number, rows: number): void;\n signal(name: TerminalSignal): void;\n close(): void;\n}\n\nexport interface KernelTerminalOptions {\n cwd?: string;\n user?: string | number;\n env?: Record<string, string>;\n cols: number;\n rows: number;\n onData: (bytes: Uint8Array) => void;\n}\n\nexport interface TerminalKernel {\n openTerminal(argv: string[], options: KernelTerminalOptions): Promise<KernelTerminal>;\n}\n\nexport interface KernelBackendOptions {\n argv?: string[];\n cwd?: string;\n user?: string | number;\n env?: Record<string, string>;\n onCwd?: (cwd: string) => void;\n}\n\nconst encoder = new TextEncoder();\nconst decoder = new TextDecoder();\nconst osc7 = /\\x1b\\]7;file:\\/\\/[^/\\x07\\x1b]*(\\/[^\\x07\\x1b]*)(?:\\x07|\\x1b\\\\)/g;\n\nexport const cwdPromptCommand = `printf '\\\\033]7;file://%s%s\\\\007' \"\\${HOSTNAME:-}\" \"$PWD\"`;\n\nfunction decodePath(path: string): string {\n try {\n return decodeURIComponent(path);\n } catch {\n return path;\n }\n}\n\nexport function cwdWatcher(onCwd: (cwd: string) => void): (bytes: Uint8Array) => void {\n let pending = '';\n return (bytes) => {\n const text = pending + decoder.decode(bytes, { stream: true });\n let last: string | undefined;\n for (const match of text.matchAll(osc7)) last = match[1];\n if (last !== undefined) onCwd(decodePath(last));\n const open = text.lastIndexOf('\\x1b]7;');\n pending = open >= 0 && !text.slice(open).match(/\\x07|\\x1b\\\\/) ? text.slice(open) : '';\n };\n}\n\nexport function kernelBackend(\n kernel: TerminalKernel,\n { argv = ['bash', '-i'], cwd, user, env, onCwd }: KernelBackendOptions = {}\n): TerminalBackend {\n return {\n async open(sink, { cols, rows }) {\n const watch = onCwd && cwdWatcher(onCwd);\n const onData = (bytes: Uint8Array) => {\n watch?.(bytes);\n sink.output(bytes);\n };\n const terminal = await kernel.openTerminal(argv, {\n cwd,\n ...(user === undefined ? {} : { user }),\n env,\n cols,\n rows,\n onData,\n });\n terminal.exited.then(\n (status) => sink.exit(status),\n (error) => {\n sink.output(encoder.encode(`\\r\\n${error instanceof Error ? error.message : error}\\r\\n`));\n sink.exit(1);\n }\n );\n return {\n write: (data) => terminal.write(data),\n resize: (c, r) => terminal.resize(c, r),\n signal: (name) => terminal.signal(name),\n close: () => terminal.close(),\n };\n },\n };\n}\n"],
|
|
5
|
+
"mappings": ";AA+BA,IAAM,UAAU,IAAI,YAAY;AAChC,IAAM,UAAU,IAAI,YAAY;AAChC,IAAM,OAAO;AAEN,IAAM,mBAAmB;AAEhC,SAAS,WAAW,MAAsB;AACxC,MAAI;AACF,WAAO,mBAAmB,IAAI;AAAA,EAChC,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEO,SAAS,WAAW,OAA2D;AACpF,MAAI,UAAU;AACd,SAAO,CAAC,UAAU;AAChB,UAAM,OAAO,UAAU,QAAQ,OAAO,OAAO,EAAE,QAAQ,KAAK,CAAC;AAC7D,QAAI;AACJ,eAAW,SAAS,KAAK,SAAS,IAAI,EAAG,QAAO,MAAM,CAAC;AACvD,QAAI,SAAS,OAAW,OAAM,WAAW,IAAI,CAAC;AAC9C,UAAM,OAAO,KAAK,YAAY,SAAS;AACvC,cAAU,QAAQ,KAAK,CAAC,KAAK,MAAM,IAAI,EAAE,MAAM,aAAa,IAAI,KAAK,MAAM,IAAI,IAAI;AAAA,EACrF;AACF;AAEO,SAAS,cACd,QACA,EAAE,OAAO,CAAC,QAAQ,IAAI,GAAG,KAAK,MAAM,KAAK,MAAM,IAA0B,CAAC,GACzD;AACjB,SAAO;AAAA,IACL,MAAM,KAAK,MAAM,EAAE,MAAM,KAAK,GAAG;AAC/B,YAAM,QAAQ,SAAS,WAAW,KAAK;AACvC,YAAM,SAAS,CAAC,UAAsB;AACpC,gBAAQ,KAAK;AACb,aAAK,OAAO,KAAK;AAAA,MACnB;AACA,YAAM,WAAW,MAAM,OAAO,aAAa,MAAM;AAAA,QAC/C;AAAA,QACA,GAAI,SAAS,SAAY,CAAC,IAAI,EAAE,KAAK;AAAA,QACrC;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF,CAAC;AACD,eAAS,OAAO;AAAA,QACd,CAAC,WAAW,KAAK,KAAK,MAAM;AAAA,QAC5B,CAAC,UAAU;AACT,eAAK,OAAO,QAAQ,OAAO;AAAA,EAAO,iBAAiB,QAAQ,MAAM,UAAU,KAAK;AAAA,CAAM,CAAC;AACvF,eAAK,KAAK,CAAC;AAAA,QACb;AAAA,MACF;AACA,aAAO;AAAA,QACL,OAAO,CAAC,SAAS,SAAS,MAAM,IAAI;AAAA,QACpC,QAAQ,CAAC,GAAG,MAAM,SAAS,OAAO,GAAG,CAAC;AAAA,QACtC,QAAQ,CAAC,SAAS,SAAS,OAAO,IAAI;AAAA,QACtC,OAAO,MAAM,SAAS,MAAM;AAAA,MAC9B;AAAA,IACF;AAAA,EACF;AACF;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
cwdPromptCommand,
|
|
3
3
|
kernelBackend
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-XYPGNJAO.js";
|
|
5
5
|
import {
|
|
6
6
|
DummySettings,
|
|
7
7
|
clock
|
|
@@ -292,15 +292,17 @@ var KernelTerminals = class extends Emitter {
|
|
|
292
292
|
#kernel;
|
|
293
293
|
#argv;
|
|
294
294
|
#cwd;
|
|
295
|
+
#user;
|
|
295
296
|
#env;
|
|
296
297
|
#terminals = [];
|
|
297
298
|
#backends = /* @__PURE__ */ new Map();
|
|
298
299
|
#next = 1;
|
|
299
|
-
constructor(kernel, { argv = ["bash", "-i"], cwd = "/home", env, open = 1 } = {}) {
|
|
300
|
+
constructor(kernel, { argv = ["bash", "-i"], cwd = "/home", user, env, open = 1 } = {}) {
|
|
300
301
|
super();
|
|
301
302
|
this.#kernel = kernel;
|
|
302
303
|
this.#argv = argv;
|
|
303
304
|
this.#cwd = cwd;
|
|
305
|
+
this.#user = user;
|
|
304
306
|
this.#env = env;
|
|
305
307
|
for (let i = 0; i < open; i++) this.open();
|
|
306
308
|
}
|
|
@@ -341,6 +343,7 @@ var KernelTerminals = class extends Emitter {
|
|
|
341
343
|
backend = kernelBackend(this.#kernel, {
|
|
342
344
|
argv: this.#argv,
|
|
343
345
|
cwd: terminal.cwd,
|
|
346
|
+
user: this.#user,
|
|
344
347
|
env: { PROMPT_COMMAND: cwdPromptCommand, ...this.#env },
|
|
345
348
|
onCwd: (cwd) => this.#move(id, cwd)
|
|
346
349
|
});
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/kernel/files.ts", "../src/kernel/idle.ts", "../src/kernel/terminals.ts", "../src/kernel/index.ts"],
|
|
4
|
-
"sourcesContent": ["import { Emitter } from '../model/emitter.ts';\nimport type { Change, FileEntry, FileEvents, FilePort } from '../model/types.ts';\n\nexport interface KernelFilesOptions {\n skip?: readonly string[];\n hide?: readonly string[];\n interval?: number;\n}\n\ninterface Observer {\n observe(handle: FileSystemHandle, options: { recursive: boolean }): Promise<void>;\n disconnect(): void;\n}\n\ntype ObserverConstructor = new (callback: () => void) => Observer;\n\nfunction split(path: string): string[] {\n return path.split('/').filter(Boolean);\n}\n\nfunction same(a: FileEntry | undefined, b: FileEntry): boolean {\n return a?.kind === b.kind && a.size === b.size && a.modified === b.modified;\n}\n\nexport class KernelFiles extends Emitter<FileEvents> implements FilePort {\n #root: FileSystemDirectoryHandle;\n #skip: Set<string>;\n #hide: Set<string>;\n #interval: number;\n #entries = new Map<string, FileEntry>();\n #scanned = false;\n #running: Promise<void> | null = null;\n #again = false;\n #timer: ReturnType<typeof setInterval> | null = null;\n #observer: Observer | null = null;\n\n constructor(\n root: FileSystemDirectoryHandle,\n { skip = [], hide = [], interval = 2000 }: KernelFilesOptions = {}\n ) {\n super();\n this.#root = root;\n this.#skip = new Set(skip);\n this.#hide = new Set(hide);\n this.#interval = interval;\n }\n\n start(): void {\n if (this.#timer || this.#observer) return;\n const Observer = (globalThis as { FileSystemObserver?: ObserverConstructor })\n .FileSystemObserver;\n if (!Observer) {\n this.#poll();\n return;\n }\n const observer = new Observer(() => void this.refresh());\n this.#observer = observer;\n observer.observe(this.#root, { recursive: true }).catch(() => {\n if (this.#observer !== observer) return;\n this.#observer = null;\n this.#poll();\n });\n }\n\n #poll(): void {\n this.#timer = setInterval(() => void this.refresh(), this.#interval);\n }\n\n stop(): void {\n if (this.#timer) clearInterval(this.#timer);\n this.#timer = null;\n this.#observer?.disconnect();\n this.#observer = null;\n }\n\n async #walk(\n dir: FileSystemDirectoryHandle,\n prefix: string,\n out: Map<string, FileEntry>\n ): Promise<void> {\n const values = (\n dir as FileSystemDirectoryHandle & {\n values(): AsyncIterable<FileSystemDirectoryHandle | FileSystemFileHandle>;\n }\n ).values();\n for await (const handle of values) {\n const path = `${prefix}/${handle.name}`;\n if (this.#hide.has(path)) continue;\n if (handle.kind === 'directory') {\n out.set(path, { path, kind: 'directory', size: 0, modified: 0 });\n if (!this.#skip.has(path)) await this.#walk(handle, path, out).catch(() => {});\n } else {\n const file = await handle.getFile().catch(() => null);\n if (file)\n out.set(path, { path, kind: 'file', size: file.size, modified: file.lastModified });\n }\n }\n }\n\n #list(): FileEntry[] {\n return [...this.#entries.values()].sort((a, b) => a.path.localeCompare(b.path));\n }\n\n async #scan(): Promise<void> {\n const next = new Map<string, FileEntry>();\n await this.#walk(this.#root, '', next);\n const touched = [...next.values()].filter(\n (entry) => !same(this.#entries.get(entry.path), entry)\n );\n const gone = [...this.#entries.values()].filter((entry) => !next.has(entry.path));\n const first = !this.#scanned;\n const previous = this.#entries;\n this.#entries = next;\n this.#scanned = true;\n if (first || touched.length + gone.length === 0) return;\n this.emit('files', this.#list());\n for (const entry of [...touched, ...gone]) {\n if (entry.kind === 'file' || previous.get(entry.path)?.kind === 'file')\n this.emit('file', entry.path);\n }\n }\n\n refresh(): Promise<void> {\n if (this.#running !== null) {\n this.#again = true;\n return this.#running;\n }\n this.#running = (async () => {\n do {\n this.#again = false;\n await this.#scan();\n } while (this.#again);\n })().finally(() => {\n this.#running = null;\n });\n return this.#running;\n }\n\n async list(): Promise<readonly FileEntry[]> {\n if (!this.#scanned) await this.refresh();\n return this.#list();\n }\n\n async #parent(path: string, create: boolean): Promise<[FileSystemDirectoryHandle, string]> {\n const parts = split(path);\n const name = parts.pop();\n if (!name) throw new Error(`EISDIR: ${path}`);\n let dir = this.#root;\n for (const part of parts) dir = await dir.getDirectoryHandle(part, { create });\n return [dir, name];\n }\n\n async read(path: string): Promise<string> {\n try {\n const [dir, name] = await this.#parent(path, false);\n return await (await (await dir.getFileHandle(name)).getFile()).text();\n } catch {\n throw new Error(`ENOENT: ${path}`);\n }\n }\n\n async write(path: string, text: string): Promise<void> {\n const [dir, name] = await this.#parent(path, true);\n const writable = await (await dir.getFileHandle(name, { create: true })).createWritable();\n await writable.write(text);\n await writable.close();\n await this.refresh();\n }\n\n async remove(path: string): Promise<void> {\n try {\n const [dir, name] = await this.#parent(path, false);\n await dir.removeEntry(name, { recursive: true });\n } catch {\n throw new Error(`ENOENT: ${path}`);\n }\n await this.refresh();\n }\n\n changes(): readonly Change[] {\n return [];\n }\n\n accept(): void {}\n\n async revert(): Promise<void> {}\n}\n", "import { Emitter } from '../model/emitter.ts';\nimport type {\n Agent,\n AgentEvents,\n AgentPort,\n BrowserEvents,\n BrowserPort,\n BrowserTab,\n FrozenCone,\n Memory,\n MemoryEvents,\n MemoryPort,\n Message,\n MonitorEvents,\n MonitorPort,\n MonitorSnapshot,\n SlashCommand,\n SprinkleEvents,\n SprinklePort,\n TrayEvents,\n TrayPort,\n TrayStatus,\n UserMessage,\n} from '../model/types.ts';\n\nfunction missing(what: string): Error {\n return new Error(`No ${what} in this SLICC yet`);\n}\n\nexport class IdleAgent extends Emitter<AgentEvents> implements AgentPort {\n list(): readonly Agent[] {\n return [];\n }\n active(): string {\n return '';\n }\n select(): void {}\n messages(): readonly Message[] {\n return [];\n }\n async send(): Promise<void> {\n throw missing('agent');\n }\n stop(): void {}\n busy(): boolean {\n return false;\n }\n queue(): readonly UserMessage[] {\n return [];\n }\n unqueue(): void {}\n suggestion(): string | null {\n return null;\n }\n answer(): void {}\n resolveLick(): void {}\n compact(): void {}\n clear(): void {}\n setModel(): void {}\n setThinking(): void {}\n async older(): Promise<readonly Message[]> {\n return [];\n }\n commands(): readonly SlashCommand[] {\n return [];\n }\n async ready(): Promise<void> {}\n createScoop(): Agent {\n throw missing('agent');\n }\n frozen(): readonly FrozenCone[] {\n return [];\n }\n freeze(): void {}\n thaw(): Agent | null {\n return null;\n }\n discard(): void {}\n}\n\nexport class IdleBrowser extends Emitter<BrowserEvents> implements BrowserPort {\n list(): readonly BrowserTab[] {\n return [];\n }\n active(): string | null {\n return null;\n }\n activate(): void {}\n open(): BrowserTab {\n throw missing('browser');\n }\n navigate(): void {}\n close(): void {}\n async screenshot(): Promise<string> {\n throw missing('browser');\n }\n}\n\nexport class IdleMemory extends Emitter<MemoryEvents> implements MemoryPort {\n list(): readonly Memory[] {\n return [];\n }\n save(): Memory {\n throw missing('memory');\n }\n remove(): void {}\n}\n\nexport class IdleMonitor extends Emitter<MonitorEvents> implements MonitorPort {\n snapshot(): MonitorSnapshot {\n return { vitals: [], alerts: [], sections: [], updatedAt: 0 };\n }\n resync(): void {}\n}\n\nexport class IdleSprinkles extends Emitter<SprinkleEvents> implements SprinklePort {\n list(): readonly [] {\n return [];\n }\n send(): void {}\n}\n\nexport class IdleTray extends Emitter<TrayEvents> implements TrayPort {\n status(): TrayStatus {\n return {\n name: 'slicc',\n kind: 'hosted',\n connection: 'offline',\n role: 'none',\n followers: [],\n spent: 0,\n rate: 0,\n budget: { percent: 0, window: 'daily', resets: '' },\n joinUrl: '',\n };\n }\n reconnect(): void {}\n disconnect(): void {}\n}\n", "import type { TerminalBackend } from '../backend.ts';\nimport { cwdPromptCommand, kernelBackend, type TerminalKernel } from '../kernel-backend.ts';\nimport { Emitter } from '../model/emitter.ts';\nimport type { TerminalEvents, TerminalInfo, TerminalPort } from '../model/types.ts';\n\nexport interface KernelTerminalsOptions {\n argv?: string[];\n cwd?: string;\n env?: Record<string, string>;\n open?: number;\n}\n\nexport class KernelTerminals extends Emitter<TerminalEvents> implements TerminalPort {\n #kernel: TerminalKernel;\n #argv: string[];\n #cwd: string;\n #env: Record<string, string> | undefined;\n #terminals: TerminalInfo[] = [];\n #backends = new Map<string, TerminalBackend>();\n #next = 1;\n\n constructor(\n kernel: TerminalKernel,\n { argv = ['bash', '-i'], cwd = '/home', env, open = 1 }: KernelTerminalsOptions = {}\n ) {\n super();\n this.#kernel = kernel;\n this.#argv = argv;\n this.#cwd = cwd;\n this.#env = env;\n for (let i = 0; i < open; i++) this.open();\n }\n\n list(): readonly TerminalInfo[] {\n return this.#terminals.map((terminal) => ({ ...terminal }));\n }\n\n open({\n cwd = this.#cwd,\n agentId = null,\n }: {\n cwd?: string;\n agentId?: string | null;\n } = {}): TerminalInfo {\n const terminal: TerminalInfo = {\n id: `term-${this.#next}`,\n title: `${this.#argv[0]} ${this.#next}`,\n cwd,\n agentId,\n };\n this.#next += 1;\n this.#terminals.push(terminal);\n this.emit('terminals', this.list());\n return { ...terminal };\n }\n\n close(id: string): void {\n this.#terminals = this.#terminals.filter((terminal) => terminal.id !== id);\n this.#backends.delete(id);\n this.emit('terminals', this.list());\n }\n\n #move(id: string, cwd: string): void {\n const terminal = this.#terminals.find((candidate) => candidate.id === id);\n if (!terminal || terminal.cwd === cwd) return;\n terminal.cwd = cwd;\n this.emit('terminals', this.list());\n }\n\n backend(id: string): TerminalBackend {\n const terminal = this.#terminals.find((candidate) => candidate.id === id);\n if (!terminal) throw new Error(`No terminal ${id}`);\n let backend = this.#backends.get(id);\n if (!backend) {\n backend = kernelBackend(this.#kernel, {\n argv: this.#argv,\n cwd: terminal.cwd,\n env: { PROMPT_COMMAND: cwdPromptCommand, ...this.#env },\n onCwd: (cwd) => this.#move(id, cwd),\n });\n this.#backends.set(id, backend);\n }\n return backend;\n }\n}\n", "import { clock } from '../dummy/clock.ts';\nimport { DummySettings } from '../dummy/settings.ts';\nimport type { TerminalKernel } from '../kernel-backend.ts';\nimport type { Settings, SliccModel } from '../model/types.ts';\nimport { KernelFiles, type KernelFilesOptions } from './files.ts';\nimport {\n IdleAgent,\n IdleBrowser,\n IdleMemory,\n IdleMonitor,\n IdleSprinkles,\n IdleTray,\n} from './idle.ts';\nimport { KernelTerminals, type KernelTerminalsOptions } from './terminals.ts';\n\nexport interface KernelModelOptions {\n kernel: TerminalKernel;\n root: FileSystemDirectoryHandle;\n files?: KernelFilesOptions;\n terminals?: KernelTerminalsOptions;\n storage?: Storage | null;\n}\n\nexport interface KernelModel extends SliccModel {\n files: KernelFiles;\n terminals: KernelTerminals;\n}\n\nconst defaults: Settings = {\n color: 'system',\n model: '',\n thinking: 'off',\n sendOnEnter: true,\n showThinking: false,\n diffStyle: 'unified',\n};\n\nexport function idleModel(storage: Storage | null = null): Omit<SliccModel, 'files' | 'terminals'> {\n return {\n agent: new IdleAgent(),\n browser: new IdleBrowser(),\n settings: new DummySettings(defaults, [], [], storage, clock(0)),\n memory: new IdleMemory(),\n monitor: new IdleMonitor(),\n sprinkles: new IdleSprinkles(),\n tray: new IdleTray(),\n };\n}\n\nexport function createKernelModel({\n kernel,\n root,\n files,\n terminals,\n storage = null,\n}: KernelModelOptions): KernelModel {\n const model: KernelModel = {\n ...idleModel(storage),\n files: new KernelFiles(root, files),\n terminals: new KernelTerminals(kernel, terminals),\n };\n model.files.start();\n return model;\n}\n"],
|
|
5
|
-
"mappings": "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
|
|
4
|
+
"sourcesContent": ["import { Emitter } from '../model/emitter.ts';\nimport type { Change, FileEntry, FileEvents, FilePort } from '../model/types.ts';\n\nexport interface KernelFilesOptions {\n skip?: readonly string[];\n hide?: readonly string[];\n interval?: number;\n}\n\ninterface Observer {\n observe(handle: FileSystemHandle, options: { recursive: boolean }): Promise<void>;\n disconnect(): void;\n}\n\ntype ObserverConstructor = new (callback: () => void) => Observer;\n\nfunction split(path: string): string[] {\n return path.split('/').filter(Boolean);\n}\n\nfunction same(a: FileEntry | undefined, b: FileEntry): boolean {\n return a?.kind === b.kind && a.size === b.size && a.modified === b.modified;\n}\n\nexport class KernelFiles extends Emitter<FileEvents> implements FilePort {\n #root: FileSystemDirectoryHandle;\n #skip: Set<string>;\n #hide: Set<string>;\n #interval: number;\n #entries = new Map<string, FileEntry>();\n #scanned = false;\n #running: Promise<void> | null = null;\n #again = false;\n #timer: ReturnType<typeof setInterval> | null = null;\n #observer: Observer | null = null;\n\n constructor(\n root: FileSystemDirectoryHandle,\n { skip = [], hide = [], interval = 2000 }: KernelFilesOptions = {}\n ) {\n super();\n this.#root = root;\n this.#skip = new Set(skip);\n this.#hide = new Set(hide);\n this.#interval = interval;\n }\n\n start(): void {\n if (this.#timer || this.#observer) return;\n const Observer = (globalThis as { FileSystemObserver?: ObserverConstructor })\n .FileSystemObserver;\n if (!Observer) {\n this.#poll();\n return;\n }\n const observer = new Observer(() => void this.refresh());\n this.#observer = observer;\n observer.observe(this.#root, { recursive: true }).catch(() => {\n if (this.#observer !== observer) return;\n this.#observer = null;\n this.#poll();\n });\n }\n\n #poll(): void {\n this.#timer = setInterval(() => void this.refresh(), this.#interval);\n }\n\n stop(): void {\n if (this.#timer) clearInterval(this.#timer);\n this.#timer = null;\n this.#observer?.disconnect();\n this.#observer = null;\n }\n\n async #walk(\n dir: FileSystemDirectoryHandle,\n prefix: string,\n out: Map<string, FileEntry>\n ): Promise<void> {\n const values = (\n dir as FileSystemDirectoryHandle & {\n values(): AsyncIterable<FileSystemDirectoryHandle | FileSystemFileHandle>;\n }\n ).values();\n for await (const handle of values) {\n const path = `${prefix}/${handle.name}`;\n if (this.#hide.has(path)) continue;\n if (handle.kind === 'directory') {\n out.set(path, { path, kind: 'directory', size: 0, modified: 0 });\n if (!this.#skip.has(path)) await this.#walk(handle, path, out).catch(() => {});\n } else {\n const file = await handle.getFile().catch(() => null);\n if (file)\n out.set(path, { path, kind: 'file', size: file.size, modified: file.lastModified });\n }\n }\n }\n\n #list(): FileEntry[] {\n return [...this.#entries.values()].sort((a, b) => a.path.localeCompare(b.path));\n }\n\n async #scan(): Promise<void> {\n const next = new Map<string, FileEntry>();\n await this.#walk(this.#root, '', next);\n const touched = [...next.values()].filter(\n (entry) => !same(this.#entries.get(entry.path), entry)\n );\n const gone = [...this.#entries.values()].filter((entry) => !next.has(entry.path));\n const first = !this.#scanned;\n const previous = this.#entries;\n this.#entries = next;\n this.#scanned = true;\n if (first || touched.length + gone.length === 0) return;\n this.emit('files', this.#list());\n for (const entry of [...touched, ...gone]) {\n if (entry.kind === 'file' || previous.get(entry.path)?.kind === 'file')\n this.emit('file', entry.path);\n }\n }\n\n refresh(): Promise<void> {\n if (this.#running !== null) {\n this.#again = true;\n return this.#running;\n }\n this.#running = (async () => {\n do {\n this.#again = false;\n await this.#scan();\n } while (this.#again);\n })().finally(() => {\n this.#running = null;\n });\n return this.#running;\n }\n\n async list(): Promise<readonly FileEntry[]> {\n if (!this.#scanned) await this.refresh();\n return this.#list();\n }\n\n async #parent(path: string, create: boolean): Promise<[FileSystemDirectoryHandle, string]> {\n const parts = split(path);\n const name = parts.pop();\n if (!name) throw new Error(`EISDIR: ${path}`);\n let dir = this.#root;\n for (const part of parts) dir = await dir.getDirectoryHandle(part, { create });\n return [dir, name];\n }\n\n async read(path: string): Promise<string> {\n try {\n const [dir, name] = await this.#parent(path, false);\n return await (await (await dir.getFileHandle(name)).getFile()).text();\n } catch {\n throw new Error(`ENOENT: ${path}`);\n }\n }\n\n async write(path: string, text: string): Promise<void> {\n const [dir, name] = await this.#parent(path, true);\n const writable = await (await dir.getFileHandle(name, { create: true })).createWritable();\n await writable.write(text);\n await writable.close();\n await this.refresh();\n }\n\n async remove(path: string): Promise<void> {\n try {\n const [dir, name] = await this.#parent(path, false);\n await dir.removeEntry(name, { recursive: true });\n } catch {\n throw new Error(`ENOENT: ${path}`);\n }\n await this.refresh();\n }\n\n changes(): readonly Change[] {\n return [];\n }\n\n accept(): void {}\n\n async revert(): Promise<void> {}\n}\n", "import { Emitter } from '../model/emitter.ts';\nimport type {\n Agent,\n AgentEvents,\n AgentPort,\n BrowserEvents,\n BrowserPort,\n BrowserTab,\n FrozenCone,\n Memory,\n MemoryEvents,\n MemoryPort,\n Message,\n MonitorEvents,\n MonitorPort,\n MonitorSnapshot,\n SlashCommand,\n SprinkleEvents,\n SprinklePort,\n TrayEvents,\n TrayPort,\n TrayStatus,\n UserMessage,\n} from '../model/types.ts';\n\nfunction missing(what: string): Error {\n return new Error(`No ${what} in this SLICC yet`);\n}\n\nexport class IdleAgent extends Emitter<AgentEvents> implements AgentPort {\n list(): readonly Agent[] {\n return [];\n }\n active(): string {\n return '';\n }\n select(): void {}\n messages(): readonly Message[] {\n return [];\n }\n async send(): Promise<void> {\n throw missing('agent');\n }\n stop(): void {}\n busy(): boolean {\n return false;\n }\n queue(): readonly UserMessage[] {\n return [];\n }\n unqueue(): void {}\n suggestion(): string | null {\n return null;\n }\n answer(): void {}\n resolveLick(): void {}\n compact(): void {}\n clear(): void {}\n setModel(): void {}\n setThinking(): void {}\n async older(): Promise<readonly Message[]> {\n return [];\n }\n commands(): readonly SlashCommand[] {\n return [];\n }\n async ready(): Promise<void> {}\n createScoop(): Agent {\n throw missing('agent');\n }\n frozen(): readonly FrozenCone[] {\n return [];\n }\n freeze(): void {}\n thaw(): Agent | null {\n return null;\n }\n discard(): void {}\n}\n\nexport class IdleBrowser extends Emitter<BrowserEvents> implements BrowserPort {\n list(): readonly BrowserTab[] {\n return [];\n }\n active(): string | null {\n return null;\n }\n activate(): void {}\n open(): BrowserTab {\n throw missing('browser');\n }\n navigate(): void {}\n close(): void {}\n async screenshot(): Promise<string> {\n throw missing('browser');\n }\n}\n\nexport class IdleMemory extends Emitter<MemoryEvents> implements MemoryPort {\n list(): readonly Memory[] {\n return [];\n }\n save(): Memory {\n throw missing('memory');\n }\n remove(): void {}\n}\n\nexport class IdleMonitor extends Emitter<MonitorEvents> implements MonitorPort {\n snapshot(): MonitorSnapshot {\n return { vitals: [], alerts: [], sections: [], updatedAt: 0 };\n }\n resync(): void {}\n}\n\nexport class IdleSprinkles extends Emitter<SprinkleEvents> implements SprinklePort {\n list(): readonly [] {\n return [];\n }\n send(): void {}\n}\n\nexport class IdleTray extends Emitter<TrayEvents> implements TrayPort {\n status(): TrayStatus {\n return {\n name: 'slicc',\n kind: 'hosted',\n connection: 'offline',\n role: 'none',\n followers: [],\n spent: 0,\n rate: 0,\n budget: { percent: 0, window: 'daily', resets: '' },\n joinUrl: '',\n };\n }\n reconnect(): void {}\n disconnect(): void {}\n}\n", "import type { TerminalBackend } from '../backend.ts';\nimport { cwdPromptCommand, kernelBackend, type TerminalKernel } from '../kernel-backend.ts';\nimport { Emitter } from '../model/emitter.ts';\nimport type { TerminalEvents, TerminalInfo, TerminalPort } from '../model/types.ts';\n\nexport interface KernelTerminalsOptions {\n argv?: string[];\n cwd?: string;\n user?: string | number;\n env?: Record<string, string>;\n open?: number;\n}\n\nexport class KernelTerminals extends Emitter<TerminalEvents> implements TerminalPort {\n #kernel: TerminalKernel;\n #argv: string[];\n #cwd: string;\n #user: string | number | undefined;\n #env: Record<string, string> | undefined;\n #terminals: TerminalInfo[] = [];\n #backends = new Map<string, TerminalBackend>();\n #next = 1;\n\n constructor(\n kernel: TerminalKernel,\n { argv = ['bash', '-i'], cwd = '/home', user, env, open = 1 }: KernelTerminalsOptions = {}\n ) {\n super();\n this.#kernel = kernel;\n this.#argv = argv;\n this.#cwd = cwd;\n this.#user = user;\n this.#env = env;\n for (let i = 0; i < open; i++) this.open();\n }\n\n list(): readonly TerminalInfo[] {\n return this.#terminals.map((terminal) => ({ ...terminal }));\n }\n\n open({\n cwd = this.#cwd,\n agentId = null,\n }: {\n cwd?: string;\n agentId?: string | null;\n } = {}): TerminalInfo {\n const terminal: TerminalInfo = {\n id: `term-${this.#next}`,\n title: `${this.#argv[0]} ${this.#next}`,\n cwd,\n agentId,\n };\n this.#next += 1;\n this.#terminals.push(terminal);\n this.emit('terminals', this.list());\n return { ...terminal };\n }\n\n close(id: string): void {\n this.#terminals = this.#terminals.filter((terminal) => terminal.id !== id);\n this.#backends.delete(id);\n this.emit('terminals', this.list());\n }\n\n #move(id: string, cwd: string): void {\n const terminal = this.#terminals.find((candidate) => candidate.id === id);\n if (!terminal || terminal.cwd === cwd) return;\n terminal.cwd = cwd;\n this.emit('terminals', this.list());\n }\n\n backend(id: string): TerminalBackend {\n const terminal = this.#terminals.find((candidate) => candidate.id === id);\n if (!terminal) throw new Error(`No terminal ${id}`);\n let backend = this.#backends.get(id);\n if (!backend) {\n backend = kernelBackend(this.#kernel, {\n argv: this.#argv,\n cwd: terminal.cwd,\n user: this.#user,\n env: { PROMPT_COMMAND: cwdPromptCommand, ...this.#env },\n onCwd: (cwd) => this.#move(id, cwd),\n });\n this.#backends.set(id, backend);\n }\n return backend;\n }\n}\n", "import { clock } from '../dummy/clock.ts';\nimport { DummySettings } from '../dummy/settings.ts';\nimport type { TerminalKernel } from '../kernel-backend.ts';\nimport type { Settings, SliccModel } from '../model/types.ts';\nimport { KernelFiles, type KernelFilesOptions } from './files.ts';\nimport {\n IdleAgent,\n IdleBrowser,\n IdleMemory,\n IdleMonitor,\n IdleSprinkles,\n IdleTray,\n} from './idle.ts';\nimport { KernelTerminals, type KernelTerminalsOptions } from './terminals.ts';\n\nexport interface KernelModelOptions {\n kernel: TerminalKernel;\n root: FileSystemDirectoryHandle;\n files?: KernelFilesOptions;\n terminals?: KernelTerminalsOptions;\n storage?: Storage | null;\n}\n\nexport interface KernelModel extends SliccModel {\n files: KernelFiles;\n terminals: KernelTerminals;\n}\n\nconst defaults: Settings = {\n color: 'system',\n model: '',\n thinking: 'off',\n sendOnEnter: true,\n showThinking: false,\n diffStyle: 'unified',\n};\n\nexport function idleModel(storage: Storage | null = null): Omit<SliccModel, 'files' | 'terminals'> {\n return {\n agent: new IdleAgent(),\n browser: new IdleBrowser(),\n settings: new DummySettings(defaults, [], [], storage, clock(0)),\n memory: new IdleMemory(),\n monitor: new IdleMonitor(),\n sprinkles: new IdleSprinkles(),\n tray: new IdleTray(),\n };\n}\n\nexport function createKernelModel({\n kernel,\n root,\n files,\n terminals,\n storage = null,\n}: KernelModelOptions): KernelModel {\n const model: KernelModel = {\n ...idleModel(storage),\n files: new KernelFiles(root, files),\n terminals: new KernelTerminals(kernel, terminals),\n };\n model.files.start();\n return model;\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/dist/slicc-terminal.js
CHANGED
|
@@ -5,12 +5,13 @@ import type { TerminalEvents, TerminalInfo, TerminalPort } from '../model/types.
|
|
|
5
5
|
export interface KernelTerminalsOptions {
|
|
6
6
|
argv?: string[];
|
|
7
7
|
cwd?: string;
|
|
8
|
+
user?: string | number;
|
|
8
9
|
env?: Record<string, string>;
|
|
9
10
|
open?: number;
|
|
10
11
|
}
|
|
11
12
|
export declare class KernelTerminals extends Emitter<TerminalEvents> implements TerminalPort {
|
|
12
13
|
#private;
|
|
13
|
-
constructor(kernel: TerminalKernel, { argv, cwd, env, open }?: KernelTerminalsOptions);
|
|
14
|
+
constructor(kernel: TerminalKernel, { argv, cwd, user, env, open }?: KernelTerminalsOptions);
|
|
14
15
|
list(): readonly TerminalInfo[];
|
|
15
16
|
open({ cwd, agentId, }?: {
|
|
16
17
|
cwd?: string;
|
|
@@ -8,6 +8,7 @@ export interface KernelTerminal {
|
|
|
8
8
|
}
|
|
9
9
|
export interface KernelTerminalOptions {
|
|
10
10
|
cwd?: string;
|
|
11
|
+
user?: string | number;
|
|
11
12
|
env?: Record<string, string>;
|
|
12
13
|
cols: number;
|
|
13
14
|
rows: number;
|
|
@@ -19,9 +20,10 @@ export interface TerminalKernel {
|
|
|
19
20
|
export interface KernelBackendOptions {
|
|
20
21
|
argv?: string[];
|
|
21
22
|
cwd?: string;
|
|
23
|
+
user?: string | number;
|
|
22
24
|
env?: Record<string, string>;
|
|
23
25
|
onCwd?: (cwd: string) => void;
|
|
24
26
|
}
|
|
25
27
|
export declare const cwdPromptCommand = "printf '\\033]7;file://%s%s\\007' \"${HOSTNAME:-}\" \"$PWD\"";
|
|
26
28
|
export declare function cwdWatcher(onCwd: (cwd: string) => void): (bytes: Uint8Array) => void;
|
|
27
|
-
export declare function kernelBackend(kernel: TerminalKernel, { argv, cwd, env, onCwd }?: KernelBackendOptions): TerminalBackend;
|
|
29
|
+
export declare function kernelBackend(kernel: TerminalKernel, { argv, cwd, user, env, onCwd }?: KernelBackendOptions): TerminalBackend;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ai-ecoverse/slicc-spectrum",
|
|
3
|
-
"version": "1.56.
|
|
3
|
+
"version": "1.56.1",
|
|
4
4
|
"description": "Web components for SLICC on Spectrum Web Components: the terminal, the app shell and its surfaces",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -72,8 +72,8 @@
|
|
|
72
72
|
"devDependencies": {
|
|
73
73
|
"@adobe/spectrum-wc": "2.0.0-beta.4",
|
|
74
74
|
"@adobe/spectrum-wc-icons": "2.0.0-beta.4",
|
|
75
|
-
"@ai-ecoverse/slicc-kernel": "1.
|
|
76
|
-
"@ai-ecoverse/slicc-shared-web": "1.12.
|
|
75
|
+
"@ai-ecoverse/slicc-kernel": "1.59.0",
|
|
76
|
+
"@ai-ecoverse/slicc-shared-web": "1.12.2",
|
|
77
77
|
"@ai-ecoverse/wasm-bash": "5.3.0-17",
|
|
78
78
|
"@ai-ecoverse/wasm-coreutils": "9.7.0-3",
|
|
79
79
|
"@biomejs/biome": "2.5.15",
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../src/kernel-backend.ts"],
|
|
4
|
-
"sourcesContent": ["import type { TerminalBackend, TerminalSignal } from './backend.ts';\n\nexport interface KernelTerminal {\n readonly exited: Promise<number>;\n write(data: Uint8Array): void;\n resize(cols: number, rows: number): void;\n signal(name: TerminalSignal): void;\n close(): void;\n}\n\nexport interface KernelTerminalOptions {\n cwd?: string;\n env?: Record<string, string>;\n cols: number;\n rows: number;\n onData: (bytes: Uint8Array) => void;\n}\n\nexport interface TerminalKernel {\n openTerminal(argv: string[], options: KernelTerminalOptions): Promise<KernelTerminal>;\n}\n\nexport interface KernelBackendOptions {\n argv?: string[];\n cwd?: string;\n env?: Record<string, string>;\n onCwd?: (cwd: string) => void;\n}\n\nconst encoder = new TextEncoder();\nconst decoder = new TextDecoder();\nconst osc7 = /\\x1b\\]7;file:\\/\\/[^/\\x07\\x1b]*(\\/[^\\x07\\x1b]*)(?:\\x07|\\x1b\\\\)/g;\n\nexport const cwdPromptCommand = `printf '\\\\033]7;file://%s%s\\\\007' \"\\${HOSTNAME:-}\" \"$PWD\"`;\n\nfunction decodePath(path: string): string {\n try {\n return decodeURIComponent(path);\n } catch {\n return path;\n }\n}\n\nexport function cwdWatcher(onCwd: (cwd: string) => void): (bytes: Uint8Array) => void {\n let pending = '';\n return (bytes) => {\n const text = pending + decoder.decode(bytes, { stream: true });\n let last: string | undefined;\n for (const match of text.matchAll(osc7)) last = match[1];\n if (last !== undefined) onCwd(decodePath(last));\n const open = text.lastIndexOf('\\x1b]7;');\n pending = open >= 0 && !text.slice(open).match(/\\x07|\\x1b\\\\/) ? text.slice(open) : '';\n };\n}\n\nexport function kernelBackend(\n kernel: TerminalKernel,\n { argv = ['bash', '-i'], cwd, env, onCwd }: KernelBackendOptions = {}\n): TerminalBackend {\n return {\n async open(sink, { cols, rows }) {\n const watch = onCwd && cwdWatcher(onCwd);\n const onData = (bytes: Uint8Array) => {\n watch?.(bytes);\n sink.output(bytes);\n };\n const terminal = await kernel.openTerminal(argv, { cwd, env, cols, rows, onData });\n terminal.exited.then(\n (status) => sink.exit(status),\n (error) => {\n sink.output(encoder.encode(`\\r\\n${error instanceof Error ? error.message : error}\\r\\n`));\n sink.exit(1);\n }\n );\n return {\n write: (data) => terminal.write(data),\n resize: (c, r) => terminal.resize(c, r),\n signal: (name) => terminal.signal(name),\n close: () => terminal.close(),\n };\n },\n };\n}\n"],
|
|
5
|
-
"mappings": ";AA6BA,IAAM,UAAU,IAAI,YAAY;AAChC,IAAM,UAAU,IAAI,YAAY;AAChC,IAAM,OAAO;AAEN,IAAM,mBAAmB;AAEhC,SAAS,WAAW,MAAsB;AACxC,MAAI;AACF,WAAO,mBAAmB,IAAI;AAAA,EAChC,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEO,SAAS,WAAW,OAA2D;AACpF,MAAI,UAAU;AACd,SAAO,CAAC,UAAU;AAChB,UAAM,OAAO,UAAU,QAAQ,OAAO,OAAO,EAAE,QAAQ,KAAK,CAAC;AAC7D,QAAI;AACJ,eAAW,SAAS,KAAK,SAAS,IAAI,EAAG,QAAO,MAAM,CAAC;AACvD,QAAI,SAAS,OAAW,OAAM,WAAW,IAAI,CAAC;AAC9C,UAAM,OAAO,KAAK,YAAY,SAAS;AACvC,cAAU,QAAQ,KAAK,CAAC,KAAK,MAAM,IAAI,EAAE,MAAM,aAAa,IAAI,KAAK,MAAM,IAAI,IAAI;AAAA,EACrF;AACF;AAEO,SAAS,cACd,QACA,EAAE,OAAO,CAAC,QAAQ,IAAI,GAAG,KAAK,KAAK,MAAM,IAA0B,CAAC,GACnD;AACjB,SAAO;AAAA,IACL,MAAM,KAAK,MAAM,EAAE,MAAM,KAAK,GAAG;AAC/B,YAAM,QAAQ,SAAS,WAAW,KAAK;AACvC,YAAM,SAAS,CAAC,UAAsB;AACpC,gBAAQ,KAAK;AACb,aAAK,OAAO,KAAK;AAAA,MACnB;AACA,YAAM,WAAW,MAAM,OAAO,aAAa,MAAM,EAAE,KAAK,KAAK,MAAM,MAAM,OAAO,CAAC;AACjF,eAAS,OAAO;AAAA,QACd,CAAC,WAAW,KAAK,KAAK,MAAM;AAAA,QAC5B,CAAC,UAAU;AACT,eAAK,OAAO,QAAQ,OAAO;AAAA,EAAO,iBAAiB,QAAQ,MAAM,UAAU,KAAK;AAAA,CAAM,CAAC;AACvF,eAAK,KAAK,CAAC;AAAA,QACb;AAAA,MACF;AACA,aAAO;AAAA,QACL,OAAO,CAAC,SAAS,SAAS,MAAM,IAAI;AAAA,QACpC,QAAQ,CAAC,GAAG,MAAM,SAAS,OAAO,GAAG,CAAC;AAAA,QACtC,QAAQ,CAAC,SAAS,SAAS,OAAO,IAAI;AAAA,QACtC,OAAO,MAAM,SAAS,MAAM;AAAA,MAC9B;AAAA,IACF;AAAA,EACF;AACF;",
|
|
6
|
-
"names": []
|
|
7
|
-
}
|