@ai-ecoverse/slicc-spectrum 1.47.2 → 1.47.4

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.
@@ -1,6 +1,7 @@
1
1
  import {
2
+ cwdPromptCommand,
2
3
  kernelBackend
3
- } from "./chunk-WCSKGA5W.js";
4
+ } from "./chunk-YVJG5657.js";
4
5
  import {
5
6
  DummySettings,
6
7
  clock
@@ -326,6 +327,12 @@ var KernelTerminals = class extends Emitter {
326
327
  this.#backends.delete(id);
327
328
  this.emit("terminals", this.list());
328
329
  }
330
+ #move(id, cwd) {
331
+ const terminal = this.#terminals.find((candidate) => candidate.id === id);
332
+ if (!terminal || terminal.cwd === cwd) return;
333
+ terminal.cwd = cwd;
334
+ this.emit("terminals", this.list());
335
+ }
329
336
  backend(id) {
330
337
  const terminal = this.#terminals.find((candidate) => candidate.id === id);
331
338
  if (!terminal) throw new Error(`No terminal ${id}`);
@@ -334,7 +341,8 @@ var KernelTerminals = class extends Emitter {
334
341
  backend = kernelBackend(this.#kernel, {
335
342
  argv: this.#argv,
336
343
  cwd: terminal.cwd,
337
- env: this.#env
344
+ env: { PROMPT_COMMAND: cwdPromptCommand, ...this.#env },
345
+ onCwd: (cwd) => this.#move(id, cwd)
338
346
  });
339
347
  this.#backends.set(id, backend);
340
348
  }
@@ -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 { 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 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: this.#env,\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 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": ";;;;;;;;;;;;;;AAgBA,SAAS,MAAM,MAAwB;AACrC,SAAO,KAAK,MAAM,GAAG,EAAE,OAAO,OAAO;AACvC;AAEA,SAAS,KAAK,GAA0B,GAAuB;AAC7D,SAAO,GAAG,SAAS,EAAE,QAAQ,EAAE,SAAS,EAAE,QAAQ,EAAE,aAAa,EAAE;AACrE;AAEO,IAAM,cAAN,cAA0B,QAAwC;AAAA,EACvE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,WAAW,oBAAI,IAAuB;AAAA,EACtC,WAAW;AAAA,EACX,WAAiC;AAAA,EACjC,SAAS;AAAA,EACT,SAAgD;AAAA,EAChD,YAA6B;AAAA,EAE7B,YACE,MACA,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,GAAG,WAAW,IAAK,IAAwB,CAAC,GACjE;AACA,UAAM;AACN,SAAK,QAAQ;AACb,SAAK,QAAQ,IAAI,IAAI,IAAI;AACzB,SAAK,QAAQ,IAAI,IAAI,IAAI;AACzB,SAAK,YAAY;AAAA,EACnB;AAAA,EAEA,QAAc;AACZ,QAAI,KAAK,UAAU,KAAK,UAAW;AACnC,UAAM,WAAY,WACf;AACH,QAAI,CAAC,UAAU;AACb,WAAK,MAAM;AACX;AAAA,IACF;AACA,UAAM,WAAW,IAAI,SAAS,MAAM,KAAK,KAAK,QAAQ,CAAC;AACvD,SAAK,YAAY;AACjB,aAAS,QAAQ,KAAK,OAAO,EAAE,WAAW,KAAK,CAAC,EAAE,MAAM,MAAM;AAC5D,UAAI,KAAK,cAAc,SAAU;AACjC,WAAK,YAAY;AACjB,WAAK,MAAM;AAAA,IACb,CAAC;AAAA,EACH;AAAA,EAEA,QAAc;AACZ,SAAK,SAAS,YAAY,MAAM,KAAK,KAAK,QAAQ,GAAG,KAAK,SAAS;AAAA,EACrE;AAAA,EAEA,OAAa;AACX,QAAI,KAAK,OAAQ,eAAc,KAAK,MAAM;AAC1C,SAAK,SAAS;AACd,SAAK,WAAW,WAAW;AAC3B,SAAK,YAAY;AAAA,EACnB;AAAA,EAEA,MAAM,MACJ,KACA,QACA,KACe;AACf,UAAM,SACJ,IAGA,OAAO;AACT,qBAAiB,UAAU,QAAQ;AACjC,YAAM,OAAO,GAAG,MAAM,IAAI,OAAO,IAAI;AACrC,UAAI,KAAK,MAAM,IAAI,IAAI,EAAG;AAC1B,UAAI,OAAO,SAAS,aAAa;AAC/B,YAAI,IAAI,MAAM,EAAE,MAAM,MAAM,aAAa,MAAM,GAAG,UAAU,EAAE,CAAC;AAC/D,YAAI,CAAC,KAAK,MAAM,IAAI,IAAI,EAAG,OAAM,KAAK,MAAM,QAAQ,MAAM,GAAG,EAAE,MAAM,MAAM;AAAA,QAAC,CAAC;AAAA,MAC/E,OAAO;AACL,cAAM,OAAO,MAAM,OAAO,QAAQ,EAAE,MAAM,MAAM,IAAI;AACpD,YAAI;AACF,cAAI,IAAI,MAAM,EAAE,MAAM,MAAM,QAAQ,MAAM,KAAK,MAAM,UAAU,KAAK,aAAa,CAAC;AAAA,MACtF;AAAA,IACF;AAAA,EACF;AAAA,EAEA,QAAqB;AACnB,WAAO,CAAC,GAAG,KAAK,SAAS,OAAO,CAAC,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,KAAK,cAAc,EAAE,IAAI,CAAC;AAAA,EAChF;AAAA,EAEA,MAAM,QAAuB;AAC3B,UAAM,OAAO,oBAAI,IAAuB;AACxC,UAAM,KAAK,MAAM,KAAK,OAAO,IAAI,IAAI;AACrC,UAAM,UAAU,CAAC,GAAG,KAAK,OAAO,CAAC,EAAE;AAAA,MACjC,CAAC,UAAU,CAAC,KAAK,KAAK,SAAS,IAAI,MAAM,IAAI,GAAG,KAAK;AAAA,IACvD;AACA,UAAM,OAAO,CAAC,GAAG,KAAK,SAAS,OAAO,CAAC,EAAE,OAAO,CAAC,UAAU,CAAC,KAAK,IAAI,MAAM,IAAI,CAAC;AAChF,UAAM,QAAQ,CAAC,KAAK;AACpB,UAAM,WAAW,KAAK;AACtB,SAAK,WAAW;AAChB,SAAK,WAAW;AAChB,QAAI,SAAS,QAAQ,SAAS,KAAK,WAAW,EAAG;AACjD,SAAK,KAAK,SAAS,KAAK,MAAM,CAAC;AAC/B,eAAW,SAAS,CAAC,GAAG,SAAS,GAAG,IAAI,GAAG;AACzC,UAAI,MAAM,SAAS,UAAU,SAAS,IAAI,MAAM,IAAI,GAAG,SAAS;AAC9D,aAAK,KAAK,QAAQ,MAAM,IAAI;AAAA,IAChC;AAAA,EACF;AAAA,EAEA,UAAyB;AACvB,QAAI,KAAK,aAAa,MAAM;AAC1B,WAAK,SAAS;AACd,aAAO,KAAK;AAAA,IACd;AACA,SAAK,YAAY,YAAY;AAC3B,SAAG;AACD,aAAK,SAAS;AACd,cAAM,KAAK,MAAM;AAAA,MACnB,SAAS,KAAK;AAAA,IAChB,GAAG,EAAE,QAAQ,MAAM;AACjB,WAAK,WAAW;AAAA,IAClB,CAAC;AACD,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,MAAM,OAAsC;AAC1C,QAAI,CAAC,KAAK,SAAU,OAAM,KAAK,QAAQ;AACvC,WAAO,KAAK,MAAM;AAAA,EACpB;AAAA,EAEA,MAAM,QAAQ,MAAc,QAA+D;AACzF,UAAM,QAAQ,MAAM,IAAI;AACxB,UAAM,OAAO,MAAM,IAAI;AACvB,QAAI,CAAC,KAAM,OAAM,IAAI,MAAM,WAAW,IAAI,EAAE;AAC5C,QAAI,MAAM,KAAK;AACf,eAAW,QAAQ,MAAO,OAAM,MAAM,IAAI,mBAAmB,MAAM,EAAE,OAAO,CAAC;AAC7E,WAAO,CAAC,KAAK,IAAI;AAAA,EACnB;AAAA,EAEA,MAAM,KAAK,MAA+B;AACxC,QAAI;AACF,YAAM,CAAC,KAAK,IAAI,IAAI,MAAM,KAAK,QAAQ,MAAM,KAAK;AAClD,aAAO,OAAO,OAAO,MAAM,IAAI,cAAc,IAAI,GAAG,QAAQ,GAAG,KAAK;AAAA,IACtE,QAAQ;AACN,YAAM,IAAI,MAAM,WAAW,IAAI,EAAE;AAAA,IACnC;AAAA,EACF;AAAA,EAEA,MAAM,MAAM,MAAc,MAA6B;AACrD,UAAM,CAAC,KAAK,IAAI,IAAI,MAAM,KAAK,QAAQ,MAAM,IAAI;AACjD,UAAM,WAAW,OAAO,MAAM,IAAI,cAAc,MAAM,EAAE,QAAQ,KAAK,CAAC,GAAG,eAAe;AACxF,UAAM,SAAS,MAAM,IAAI;AACzB,UAAM,SAAS,MAAM;AACrB,UAAM,KAAK,QAAQ;AAAA,EACrB;AAAA,EAEA,MAAM,OAAO,MAA6B;AACxC,QAAI;AACF,YAAM,CAAC,KAAK,IAAI,IAAI,MAAM,KAAK,QAAQ,MAAM,KAAK;AAClD,YAAM,IAAI,YAAY,MAAM,EAAE,WAAW,KAAK,CAAC;AAAA,IACjD,QAAQ;AACN,YAAM,IAAI,MAAM,WAAW,IAAI,EAAE;AAAA,IACnC;AACA,UAAM,KAAK,QAAQ;AAAA,EACrB;AAAA,EAEA,UAA6B;AAC3B,WAAO,CAAC;AAAA,EACV;AAAA,EAEA,SAAe;AAAA,EAAC;AAAA,EAEhB,MAAM,SAAwB;AAAA,EAAC;AACjC;;;ACjKA,SAAS,QAAQ,MAAqB;AACpC,SAAO,IAAI,MAAM,MAAM,IAAI,oBAAoB;AACjD;AAEO,IAAM,YAAN,cAAwB,QAA0C;AAAA,EACvE,OAAyB;AACvB,WAAO,CAAC;AAAA,EACV;AAAA,EACA,SAAiB;AACf,WAAO;AAAA,EACT;AAAA,EACA,SAAe;AAAA,EAAC;AAAA,EAChB,WAA+B;AAC7B,WAAO,CAAC;AAAA,EACV;AAAA,EACA,MAAM,OAAsB;AAC1B,UAAM,QAAQ,OAAO;AAAA,EACvB;AAAA,EACA,OAAa;AAAA,EAAC;AAAA,EACd,OAAgB;AACd,WAAO;AAAA,EACT;AAAA,EACA,QAAgC;AAC9B,WAAO,CAAC;AAAA,EACV;AAAA,EACA,UAAgB;AAAA,EAAC;AAAA,EACjB,aAA4B;AAC1B,WAAO;AAAA,EACT;AAAA,EACA,SAAe;AAAA,EAAC;AAAA,EAChB,cAAoB;AAAA,EAAC;AAAA,EACrB,UAAgB;AAAA,EAAC;AAAA,EACjB,QAAc;AAAA,EAAC;AAAA,EACf,WAAiB;AAAA,EAAC;AAAA,EAClB,cAAoB;AAAA,EAAC;AAAA,EACrB,MAAM,QAAqC;AACzC,WAAO,CAAC;AAAA,EACV;AAAA,EACA,WAAoC;AAClC,WAAO,CAAC;AAAA,EACV;AAAA,EACA,MAAM,QAAuB;AAAA,EAAC;AAAA,EAC9B,cAAqB;AACnB,UAAM,QAAQ,OAAO;AAAA,EACvB;AAAA,EACA,SAAgC;AAC9B,WAAO,CAAC;AAAA,EACV;AAAA,EACA,SAAe;AAAA,EAAC;AAAA,EAChB,OAAqB;AACnB,WAAO;AAAA,EACT;AAAA,EACA,UAAgB;AAAA,EAAC;AACnB;AAEO,IAAM,cAAN,cAA0B,QAA8C;AAAA,EAC7E,OAA8B;AAC5B,WAAO,CAAC;AAAA,EACV;AAAA,EACA,SAAwB;AACtB,WAAO;AAAA,EACT;AAAA,EACA,WAAiB;AAAA,EAAC;AAAA,EAClB,OAAmB;AACjB,UAAM,QAAQ,SAAS;AAAA,EACzB;AAAA,EACA,WAAiB;AAAA,EAAC;AAAA,EAClB,QAAc;AAAA,EAAC;AAAA,EACf,MAAM,aAA8B;AAClC,UAAM,QAAQ,SAAS;AAAA,EACzB;AACF;AAEO,IAAM,aAAN,cAAyB,QAA4C;AAAA,EAC1E,OAA0B;AACxB,WAAO,CAAC;AAAA,EACV;AAAA,EACA,OAAe;AACb,UAAM,QAAQ,QAAQ;AAAA,EACxB;AAAA,EACA,SAAe;AAAA,EAAC;AAClB;AAEO,IAAM,cAAN,cAA0B,QAA8C;AAAA,EAC7E,WAA4B;AAC1B,WAAO,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAC,GAAG,UAAU,CAAC,GAAG,WAAW,EAAE;AAAA,EAC9D;AAAA,EACA,SAAe;AAAA,EAAC;AAClB;AAEO,IAAM,gBAAN,cAA4B,QAAgD;AAAA,EACjF,OAAoB;AAClB,WAAO,CAAC;AAAA,EACV;AAAA,EACA,OAAa;AAAA,EAAC;AAChB;AAEO,IAAM,WAAN,cAAuB,QAAwC;AAAA,EACpE,SAAqB;AACnB,WAAO;AAAA,MACL,MAAM;AAAA,MACN,MAAM;AAAA,MACN,YAAY;AAAA,MACZ,MAAM;AAAA,MACN,WAAW,CAAC;AAAA,MACZ,OAAO;AAAA,MACP,MAAM;AAAA,MACN,QAAQ,EAAE,SAAS,GAAG,QAAQ,SAAS,QAAQ,GAAG;AAAA,MAClD,SAAS;AAAA,IACX;AAAA,EACF;AAAA,EACA,YAAkB;AAAA,EAAC;AAAA,EACnB,aAAmB;AAAA,EAAC;AACtB;;;AC9HO,IAAM,kBAAN,cAA8B,QAAgD;AAAA,EACnF;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,aAA6B,CAAC;AAAA,EAC9B,YAAY,oBAAI,IAA6B;AAAA,EAC7C,QAAQ;AAAA,EAER,YACE,QACA,EAAE,OAAO,CAAC,QAAQ,IAAI,GAAG,MAAM,SAAS,KAAK,OAAO,EAAE,IAA4B,CAAC,GACnF;AACA,UAAM;AACN,SAAK,UAAU;AACf,SAAK,QAAQ;AACb,SAAK,OAAO;AACZ,SAAK,OAAO;AACZ,aAAS,IAAI,GAAG,IAAI,MAAM,IAAK,MAAK,KAAK;AAAA,EAC3C;AAAA,EAEA,OAAgC;AAC9B,WAAO,KAAK,WAAW,IAAI,CAAC,cAAc,EAAE,GAAG,SAAS,EAAE;AAAA,EAC5D;AAAA,EAEA,KAAK;AAAA,IACH,MAAM,KAAK;AAAA,IACX,UAAU;AAAA,EACZ,IAGI,CAAC,GAAiB;AACpB,UAAM,WAAyB;AAAA,MAC7B,IAAI,QAAQ,KAAK,KAAK;AAAA,MACtB,OAAO,GAAG,KAAK,MAAM,CAAC,CAAC,IAAI,KAAK,KAAK;AAAA,MACrC;AAAA,MACA;AAAA,IACF;AACA,SAAK,SAAS;AACd,SAAK,WAAW,KAAK,QAAQ;AAC7B,SAAK,KAAK,aAAa,KAAK,KAAK,CAAC;AAClC,WAAO,EAAE,GAAG,SAAS;AAAA,EACvB;AAAA,EAEA,MAAM,IAAkB;AACtB,SAAK,aAAa,KAAK,WAAW,OAAO,CAAC,aAAa,SAAS,OAAO,EAAE;AACzE,SAAK,UAAU,OAAO,EAAE;AACxB,SAAK,KAAK,aAAa,KAAK,KAAK,CAAC;AAAA,EACpC;AAAA,EAEA,MAAM,IAAY,KAAmB;AACnC,UAAM,WAAW,KAAK,WAAW,KAAK,CAAC,cAAc,UAAU,OAAO,EAAE;AACxE,QAAI,CAAC,YAAY,SAAS,QAAQ,IAAK;AACvC,aAAS,MAAM;AACf,SAAK,KAAK,aAAa,KAAK,KAAK,CAAC;AAAA,EACpC;AAAA,EAEA,QAAQ,IAA6B;AACnC,UAAM,WAAW,KAAK,WAAW,KAAK,CAAC,cAAc,UAAU,OAAO,EAAE;AACxE,QAAI,CAAC,SAAU,OAAM,IAAI,MAAM,eAAe,EAAE,EAAE;AAClD,QAAI,UAAU,KAAK,UAAU,IAAI,EAAE;AACnC,QAAI,CAAC,SAAS;AACZ,gBAAU,cAAc,KAAK,SAAS;AAAA,QACpC,MAAM,KAAK;AAAA,QACX,KAAK,SAAS;AAAA,QACd,KAAK,EAAE,gBAAgB,kBAAkB,GAAG,KAAK,KAAK;AAAA,QACtD,OAAO,CAAC,QAAQ,KAAK,MAAM,IAAI,GAAG;AAAA,MACpC,CAAC;AACD,WAAK,UAAU,IAAI,IAAI,OAAO;AAAA,IAChC;AACA,WAAO;AAAA,EACT;AACF;;;ACxDA,IAAM,WAAqB;AAAA,EACzB,OAAO;AAAA,EACP,OAAO;AAAA,EACP,UAAU;AAAA,EACV,aAAa;AAAA,EACb,cAAc;AAAA,EACd,WAAW;AACb;AAEO,SAAS,UAAU,UAA0B,MAA+C;AACjG,SAAO;AAAA,IACL,OAAO,IAAI,UAAU;AAAA,IACrB,SAAS,IAAI,YAAY;AAAA,IACzB,UAAU,IAAI,cAAc,UAAU,CAAC,GAAG,CAAC,GAAG,SAAS,MAAM,CAAC,CAAC;AAAA,IAC/D,QAAQ,IAAI,WAAW;AAAA,IACvB,SAAS,IAAI,YAAY;AAAA,IACzB,WAAW,IAAI,cAAc;AAAA,IAC7B,MAAM,IAAI,SAAS;AAAA,EACrB;AACF;AAEO,SAAS,kBAAkB;AAAA,EAChC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,UAAU;AACZ,GAAoC;AAClC,QAAM,QAAqB;AAAA,IACzB,GAAG,UAAU,OAAO;AAAA,IACpB,OAAO,IAAI,YAAY,MAAM,KAAK;AAAA,IAClC,WAAW,IAAI,gBAAgB,QAAQ,SAAS;AAAA,EAClD;AACA,QAAM,MAAM,MAAM;AAClB,SAAO;AACT;",
6
6
  "names": []
7
7
  }
@@ -4,7 +4,7 @@ import {
4
4
  } from "./chunk-TK4ZJ7LA.js";
5
5
  import {
6
6
  kernelBackend
7
- } from "./chunk-WCSKGA5W.js";
7
+ } from "./chunk-YVJG5657.js";
8
8
  import "./chunk-AXQFWXYZ.js";
9
9
 
10
10
  // src/index.ts
package/dist/slicc-ui.js CHANGED
@@ -11231,7 +11231,11 @@ var SliccNetwork = class extends ModelElement {
11231
11231
  return model.network ? [model.network.on("network", () => this.requestUpdate())] : [];
11232
11232
  }
11233
11233
  focus() {
11234
- this.focusOn("swc-button, a, summary, swc-action-button", ".page");
11234
+ this.focusWith(
11235
+ { focusVisible: false },
11236
+ "sp-picker, swc-button, a, summary, swc-action-button",
11237
+ ".page"
11238
+ );
11235
11239
  }
11236
11240
  async check() {
11237
11241
  const port = this.model?.network;
@@ -11349,7 +11353,7 @@ var SliccNetwork = class extends ModelElement {
11349
11353
  </div>` : A}
11350
11354
  <p data-exit=${tailnet.exitNode ? "node" : "none"}>${tailnet.exitNode ? `Internet through the exit node ${tailnet.exitNode}.` : tailnetOnly[status2.route ?? "none"]}</p>`;
11351
11355
  }
11352
- #exitLine(status2) {
11356
+ #exitLine(port, status2) {
11353
11357
  const exit = status2.exit;
11354
11358
  if (!exit) return A;
11355
11359
  if (exit.kind === "tailnet") {
@@ -11360,7 +11364,7 @@ var SliccNetwork = class extends ModelElement {
11360
11364
  const device = status2.links?.devices.find((item2) => item2.id === exit.id);
11361
11365
  if (device?.state === "connected") return A;
11362
11366
  const who = device ? `${device.name} is ${device.state}` : "The linked device isn\u2019t connected";
11363
- return b`<div class="warning" data-exit="device" data-held><swc-icon-alert-triangle size="s" aria-hidden="true"></swc-icon-alert-triangle><span>${who}. Internet traffic waits until it’s connected.</span></div>`;
11367
+ return b`<div class="warning" data-exit="device" data-held><swc-icon-alert-triangle size="s" aria-hidden="true"></swc-icon-alert-triangle><div class="banner"><span>${who}. Internet traffic waits until it’s connected.</span><div class="actions"><swc-button size="s" variant="secondary" fill-style="outline" data-action="exit-direct" ?pending=${this.busy === "exit"} ?disabled=${this.#waiting("exit")} @click=${() => this.#act("exit", () => port.setExit?.(null), "error")}>Send directly</swc-button></div></div></div>`;
11364
11368
  }
11365
11369
  #exitPicker(port, status2) {
11366
11370
  const tailnet = status2.tailnet;
@@ -11381,7 +11385,7 @@ var SliccNetwork = class extends ModelElement {
11381
11385
  </sp-menu-group>` : A}
11382
11386
  </sp-picker>
11383
11387
  </div>
11384
- ${this.#exitLine(status2)}`;
11388
+ ${this.#exitLine(port, status2)}`;
11385
11389
  }
11386
11390
  #exitAll(event2, port) {
11387
11391
  const value = event2.target.value;