Dashboard › opencode › Distillation
dc692a12-98ec-4f39-81b1-b6aa3535e74a["lore_tm_v1_NULKpPJhhuc9-wQ8BT4QOT55ffTFc_us40nbE2GjPx8","lore_tm_v1_4ddA9IM4E3GhNZcLf18KG3fhUepyFnipf8w6ve8UF3U","lore_tm_v1_KAThweJBX3bjZttEcKMJe18FE8Q81eAWN4xYvrnhoqA","lore_tm_v1_0ieRYfmOXa4UH3NIvuGbRIAWFHr6UAsKZzsGRr1eIk0","lore_tm_v1_bQCDzw6A1ReCqkCe19-Lm5bO-src1lxVONljdM-cpfM","lore_tm_v1_z4VsaKWlimlblWpJIokk-QJDOPdhAYOB81glhbg_jW0","lore_tm_v1_aqKxwdqAeiInJeZaEsliZrKHZZ1P5Rdb1N4ScYZHUFw","lore_tm_v1_9A9N-Slqqc4SKtm2JmRHR-wpJBNpEIcpuN-u4wXsjS8","lore_tm_v1_aPKZf6mhp-qstUDjAVq1c3X2h5wENptqXv6zFMqK2c4","lore_tm_v1_eTGAHu8K6Em-CYquW-SJMpFOZ5RYgBRVI-LSljUleUs","lore_tm_v1_qPiRbHZde9GA2XVIW0FdGAl8B__Meojy3JN_tOH2Szw"]
Date: Sep 8, 2026
/home/byk/Code/opencode-v2-pilot and every line of /home/byk/.local/share/opencode-v2-pilot/config/opencode/plugins/pty.ts, verified against the current core implementation rather than cached reviews.EPIPE; regex DoS; memory/process exhaustion; stubborn descendants; unload/session deletion; and synthetic-output injection.file:line evidence, classifications of PASS, CONCERN, or MUST-FIX, and a final line exactly MERGE or DO-NOT-MERGE.sdk composes Client, Core, and Server.bun typecheck from package directories such as packages/core, never invoking tsc directly.packages/core, never from the repository root because of the do-not-run-tests-from-root guard.import { foo as bar } from "..." and resolve as pathResolve.import("...") references such as Schema.declare<import("@opencode/plugin/effect/plugin").Plugin["effect"]>; an aliased type import such as import type { Plugin as PluginDefinition } from "..." is permitted only as a last resort when names genuinely collide and no other option exists.import * as Foo from "..." and import type * as Foo from "...".import { Project } from "@opencode/core/project" followed by Project.ID.await import("./module").then((mod) => mod.value()) and (await import("./module")).value() should be avoided.HttpApi, bun run generate must be run from packages/client; generated client files must not be edited directly..changeset files must not be added.v2; branches/worktrees should default to v2 or origin/v2 if local v2 is unavailable, pull requests should target v2, and diffs should use v2 or origin/v2 because local main may not exist.session-recovery, fix-scroll-state, and regenerate-sdk.type(scope): summary form, with valid types feat, fix, docs, chore, refactor, and test.@opencode/client/effect/api, must not redefine existing API-client functions, and should add only plugin-context-specific functions.effect-smol source rather than memory or older Effect v2/v3 examples; exact APIs should be checked in .opencode/references/effect-smol and nearby repository code.testEffect(...) from packages/opencode/test/lib/effect.ts for Effect services/layers/runtime/scoped-resource tests and it.live(...) for filesystem, git, HTTP servers, sockets, child processes, locks, real time, and other live platform behavior.2ac698d65aa4690a694307e9cbdf44537ea9a4fb.packages/core/src/plugin/host.ts, packages/core/test/plugin.test.ts, packages/core/test/plugin/host.ts, packages/plugin/src/effect/permission.ts, packages/plugin/src/promise/adapter.ts, and packages/plugin/src/promise/permission.ts; diffstat was 53 insertions across 6 files.packages/cli/dist-v2-pilot-final/, packages/cli/dist-v2-pilot-next/, and packages/cli/dist-v2-pilot/; each contains cli-node-linux-x64/package.json and cli-node-linux-x64/bin/opencode2-node.packages/core/src/plugin/host.ts:386 exposes canonical permission assertions to plugins through permission.assert: permission.assert.packages/core/test/plugin/host.ts:108 adds the default test-host stub assert: () => Effect.die("unused permission.assert").packages/core/test/plugin.test.ts adds the test it.effect("exposes canonical permission assertions to Promise plugins", ...); the Promise plugin promise-permission calls ctx.permission.assert(...) with Session ID ses_plugin_permission, action shell, resource "'true'", and tool source IDs msg_plugin_permission and call_plugin_permission, then verifies activation status is active.packages/plugin/src/effect/permission.ts adds PermissionAssertInput with sessionID: Session.ID, action: string, resources: ReadonlyArray<string>, optional save, optional metadata: Record<string, unknown>, optional source: Permission.Source, and optional agent: Agent.ID; PermissionDomain.assert returns Effect.Effect<void, unknown>.packages/plugin/src/promise/permission.ts adds the same PermissionAssertInput shape, with PermissionDomain.assert returning Promise<void>.packages/plugin/src/promise/adapter.ts adapts Promise permission assertions using assert: (input) => run(host.permission.assert(input)).packages/core/src/permission.ts:105 as (input: AssertInput) => Effect.Effect<void, Error | SessionErrors.NotFoundError> and defines it with Effect.fn("Permission.assert") near line 221./home/byk/.local/share/opencode-v2-pilot/config/opencode/plugins/pty.ts defines limits: MAX_BUFFER_SIZE = 1_000_000, MAX_SESSIONS = 25, MAX_SESSIONS_PER_OWNER = 5, DEFAULT_READ_LIMIT = 500, MAX_READ_LIMIT = 2_000, MAX_READ_OFFSET = 10_000, MAX_LINE_LENGTH = 2_000, MAX_PATTERN_LENGTH = 500, MAX_WRITE_SIZE = 65_536, MAX_TIMEOUT_SECONDS = 2_147_483, and KILL_GRACE_MS = 1_000.pty.ts:20-26 supplies child processes a fixed environment containing HOME from the parent or /home/byk, LANG from the parent or C.UTF-8, PATH=/usr/bin:/bin, SHELL=/bin/sh, and TERM=xterm-256color.pty.ts:137-339 registers tools pty_spawn, pty_write, pty_read, pty_list, and pty_kill; spawn, write, and kill declare permission "shell", while read and list do not.pty.ts:145-158 authorizes the requested command/workdir before enforcing per-owner and Location session limits, then runs /usr/bin/script with arguments ["-qefc", shellCommand(input.command, input.args), "/dev/null"], cwd set to the authorized directory, detached: true, and env: FIXED_ENV.pty.ts:146-152 limits each parent Session to 5 PTYs, removing the first exited or killed PTY when at the owner limit, and limits the Location to 25 retained PTYs.pty.ts:153 generates PTY IDs as pty_ plus the first 8 hexadecimal characters of a hyphen-stripped crypto.randomUUID().pty.ts:159-198 captures stdout/stderr during spawn and thereafter retains only the trailing MAX_BUFFER_SIZE characters; process error messages are appended to the same bounded buffer.pty.ts:199-225 marks a closing PTY as killed if it was killing, otherwise exited; records exit code/signal; and, when notifyOnExit is true, sends a synthetic steer to the owning Session containing <pty_exited>, ID, truncated description, exit code, timeout data, line count, and a last line truncated to 200 characters.pty.ts:227-235 implements optional timeout termination: when a running session reaches timeoutSeconds, it sets timedOut = true, changes status to killing, invokes terminate(session), logs failures, and unreferences object-form timers.pty.ts:268-272 restricts pty_write to the owning Session, requires status running, decodes supported escapes, and writes to child stdin with callback-based error propagation.pty.ts:283-303 restricts pty_read to the owning Session, paginates either plain lines or regex matches, truncates each emitted line to 2,000 characters, and wraps output in <pty_output ...> markup containing unescaped session status and optional pattern attributes.pty.ts:313-317 makes pty_list return only sessions whose parentSessionID matches the calling Session.pty.ts:327-336 restricts pty_kill to the owning Session; cleanup: true terminates, deletes, and clears buffered output, while normal kill terminates a running process but retains the session.pty.ts:341-355 subscribes to session.deleted, removes every PTY owned by the deleted Session, aborts the subscription on plugin unload, and removes all retained sessions during unload.pty.ts:363-366 enforces ownership in requireSession(...) by rejecting absent PTY IDs and PTYs whose parentSessionID differs from the callerβs Session ID.pty.ts:404-413 decodes only \xNN, \uNNNN, \n, \r, \t, and \\ escape forms.pty.ts:415-417 constructs shell command text by single-quoting the executable and every argument and replacing embedded single quotes with the shell sequence '\\''.pty.ts:419-440 terminates the detached process group via process.kill(-session.pid, signal), ignores ESRCH, sends SIGTERM, waits up to 1,000 ms for session.closed, sends SIGKILL if still open, then waits indefinitely for session.closed; concurrent termination calls reuse session.terminate.pty.ts:443-474 canonicalizes both requested workdir and project directory with realpath; requests external_directory permission when the canonical workdir is outside the canonical project; requests shell permission with the fully quoted command resource and save: [resource]; then re-runs realpath(workdir), rejects a changed canonical target, verifies it is a directory with stat(current).isDirectory(), and returns the earlier canonical directory.pty.ts:476-514 delegates regex matching to /usr/bin/grep with -a, -m <limit>, -nE, optional -i, and --; kills grep after 250 ms, bounds collected stdout to MAX_BUFFER_SIZE * 2, bounds collected stderr to MAX_LINE_LENGTH, ignores stdin EPIPE, treats exit code 1 as no matches, and parses line:text output.