opencode-session-port 0.1.0 → 0.1.3

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/package.json CHANGED
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "name": "opencode-session-port",
3
- "version": "0.1.0",
3
+ "version": "0.1.3",
4
4
  "private": false,
5
5
  "license": "MIT",
6
- "description": "SessionPort: experimental Windows-first OpenCode TUI plugin for password-encrypted session checkpoint and restore.",
6
+ "description": "SessionPort: experimental OpenCode TUI plugin for password-encrypted session checkpoint and restore.",
7
7
  "keywords": [
8
8
  "opencode",
9
9
  "opencode-plugin",
@@ -17,15 +17,18 @@
17
17
  "files": [
18
18
  "tui.ts",
19
19
  "src/**",
20
+ "dist/**",
20
21
  "tsconfig.json"
21
22
  ],
22
23
  "exports": {
23
- "./tui": "./src/tui.ts"
24
+ "./tui": "./dist/tui.js"
24
25
  },
25
26
  "scripts": {
26
27
  "typecheck": "tsc --noEmit",
27
28
  "test": "bun test",
28
- "verify:package": "bun run scripts/package-verify/verify.ts"
29
+ "verify:package": "bun run scripts/package-verify/verify.ts",
30
+ "build:tui": "bun run scripts/build-tui.ts",
31
+ "prepack": "bun run build:tui"
29
32
  },
30
33
  "dependencies": {
31
34
  "@opencode/plugin": "2.0.22",
@@ -33,26 +36,15 @@
33
36
  "pako": "3.0.2"
34
37
  },
35
38
  "peerDependencies": {
36
- "@opentui/core": ">=0.5.14",
37
- "@opentui/solid": ">=0.5.14",
38
- "solid-js": ">=1.9.0"
39
- },
40
- "peerDependenciesMeta": {
41
- "@opentui/core": {
42
- "optional": true
43
- },
44
- "@opentui/solid": {
45
- "optional": true
46
- },
47
- "solid-js": {
48
- "optional": true
49
- }
39
+ "@opentui/core": "0.5.14",
40
+ "@opentui/solid": "0.5.14",
41
+ "solid-js": "1.9.12"
50
42
  },
51
43
  "devDependencies": {
52
44
  "@opentui/core": "0.5.14",
53
45
  "@opentui/solid": "0.5.14",
54
46
  "@types/node": "24.12.2",
55
- "solid-js": "1.9.15",
47
+ "solid-js": "1.9.12",
56
48
  "typescript": "5.9.3"
57
49
  }
58
50
  }
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Experimental project-location resolver over the public TUI client
3
- * `context.client.location.get` method (Windows-first experimental lane).
3
+ * `context.client.location.get` method (experimental wiring lane).
4
4
  *
5
5
  * Scope and boundaries (owner decision 2026-10-11, decision-log F):
6
6
  * - `Plugin.Context.location` carries only a directory, so the experimental
@@ -17,7 +17,10 @@ export interface SessionPortCommandHost {
17
17
  }
18
18
 
19
19
  /**
20
- * Register native slash commands from an app-slot component scope. The slot
20
+ * Register native slash commands from an app-slot component scope. The layer
21
+ * opts out of the default `base` input mode with `mode: "global"` so the
22
+ * commands are reachable from every OpenCode input mode (palette and slash
23
+ * discovery included); without it the host hides them outside `base`. The slot
21
24
  * disposer is returned unchanged so the plugin can clean up its contribution.
22
25
  * Command input is forwarded as received; parsing belongs to the injected
23
26
  * handlers.
@@ -30,6 +33,7 @@ export function installSessionPortCommands(
30
33
  append: "app",
31
34
  render() {
32
35
  context.keymap.layer(() => ({
36
+ mode: "global",
33
37
  commands: [
34
38
  {
35
39
  id: SESSIONPORT_COMMAND_IDS.checkpoint,
@@ -1,5 +1,5 @@
1
1
  /**
2
- * SessionPort TUI command composition (Phase 2 experimental Windows wiring).
2
+ * SessionPort TUI command composition (Phase 2 experimental wiring).
3
3
  *
4
4
  * `createSessionPortHandlers` composes the completed Phase 2-4 seams into the
5
5
  * two injected command callbacks consumed by `installSessionPortCommands`:
@@ -112,7 +112,7 @@ export interface SessionPortHandlerDependencies {
112
112
  readonly showRestoreReport: (model: RestoreReportPresentationModel) => void;
113
113
  /** Masked password provider (real UI or a fake in tests). */
114
114
  readonly requestPassword: SessionPortPasswordProvider;
115
- /** Initialized crypto factory; production uses the experimental Windows profile. */
115
+ /** Initialized crypto factory; production uses the experimental profile (historical `-win-` selector name). */
116
116
  readonly cryptoFactory: CheckpointCryptoFactory;
117
117
  /** Remapped-ID deriver for restore planning. */
118
118
  readonly idDeriver: RemappedIdDeriver;
@@ -1,10 +1,17 @@
1
1
  /**
2
- * Windows-first experimental runtime defaults (Phase 2 wiring).
2
+ * Experimental runtime defaults (Phase 2 wiring; originally recorded for the
3
+ * Windows-first lane).
4
+ *
5
+ * The `sessionport-experimental-win-v1` selector name is historical and is NOT
6
+ * portability evidence: enabling macOS/Linux changes no profile, format, or cap
7
+ * value below.
3
8
  *
4
9
  * These are the explicitly selected, owner-authorized experimental values
5
- * recorded in `docs/v1/decision-log.md` (2026-10-11 entries) for a Windows
6
- * experimental build only. They are NOT a production approval, not a format
7
- * freeze, and not a general memory budget, compatibility, or support claim.
10
+ * recorded in `docs/v1/decision-log.md` (2026-10-11 entries) for the Windows
11
+ * experimental build; they now apply unchanged to the experimental macOS/Linux
12
+ * enablement, which is NOT host-tested. They are NOT a production approval, not
13
+ * a format freeze, and not a general memory budget, compatibility, or support
14
+ * claim.
8
15
  *
9
16
  * - Crypto profile `sessionport-experimental-win-v1`: profile code 1,
10
17
  * Argon2id13 `crypto_pwhash`, `opslimit=2`, `memlimit=128 MiB`, the current
@@ -22,7 +29,7 @@ import type { CryptoPolicy } from "../../core/contracts/index.ts";
22
29
  import type { CryptoPolicyDefinition } from "../../core/crypto/index.ts";
23
30
  import type { SessionCollectionPolicy } from "../../core/sessions/index.ts";
24
31
 
25
- /** Explicit allow-listed policy id for the Windows experimental profile. */
32
+ /** Explicit allow-listed policy id for the experimental profile (historical `-win-` name). */
26
33
  export const EXPERIMENTAL_CRYPTO_POLICY_ID = "sessionport-experimental-win-v1";
27
34
 
28
35
  /** The explicit policy selector passed to the crypto factory; never read from an artifact. */
@@ -2,10 +2,10 @@
2
2
  * SessionPort TUI wiring (Phase 2 experimental Windows lane).
3
3
  *
4
4
  * Public surface:
5
- * - `installSessionPortWiring(context, options?)` — Windows-only install root:
6
- * pinned-sodium initialization, real adapters/artifact I/O/password modal,
7
- * command registration through the existing component-scoped seam, and the
8
- * slot disposer returned unchanged.
5
+ * - `installSessionPortWiring(context, options?)` — install root gated to the
6
+ * explicit `win32`/`darwin`/`linux` allowlist: pinned-sodium initialization,
7
+ * real adapters/artifact I/O/password modal, command registration through the
8
+ * existing component-scoped seam, and the slot disposer returned unchanged.
9
9
  * - `createSessionPortHandlers(dependencies)` — fully injected composition of
10
10
  * the `/checkpoint` and `/restore` command callbacks (fake-based testable).
11
11
  * - Experimental runtime defaults (crypto profile + collection bounds +
@@ -16,7 +16,8 @@
16
16
  * is written, only encrypted artifacts are read, and every failure report is
17
17
  * generic/sanitized. No production approval, format freeze, or platform-support
18
18
  * claim is made (O-01/O-02/O-03 remain PARTIALLY RESOLVED for the experimental
19
- * Windows build only; OQ-16 stays OPEN).
19
+ * build only — the `-win-` profile selector name is historical; OQ-16 stays
20
+ * OPEN).
20
21
  */
21
22
 
22
23
  export {
@@ -1,13 +1,16 @@
1
1
  /// <reference types="node" />
2
2
  /**
3
- * SessionPort TUI install/composition root (Phase 2 experimental Windows wiring).
3
+ * SessionPort TUI install/composition root (Phase 2 experimental wiring).
4
4
  *
5
5
  * `installSessionPortWiring` is the only host-facing composition entry:
6
6
  *
7
- * - **Windows-first experimental only.** On any non-`win32` platform it returns
8
- * `undefined` immediately: no sodium initialization, no host-context access,
9
- * no command registration, and no platform-support claim.
10
- * - On Windows it initializes the pinned `libsodium-wrappers-sumo@0.8.4`
7
+ * - **Explicit platform allowlist (`win32`/`darwin`/`linux`), experimental
8
+ * only.** On any other platform it returns `undefined` immediately: no sodium
9
+ * initialization, no host-context access, no command registration, and no
10
+ * platform-support claim. Windows has bounded actual-host evidence; macOS and
11
+ * Linux are enabled but NOT host-tested, and cross-OS artifact interchange is
12
+ * UNVERIFIED.
13
+ * - On an allowed platform it initializes the pinned `libsodium-wrappers-sumo@0.8.4`
11
14
  * runtime first (`await sodium.ready` plus primitive/constant validation
12
15
  * through `createCheckpointCryptoFactory`; `createRemappedIdDeriver` also
13
16
  * awaits/validates it) and fails closed: a rejected initialization aborts
@@ -25,8 +28,8 @@
25
28
  * This module statically imports the designer-owned UI modules (password modal
26
29
  * and restore report dialog), which import the optional UI peers
27
30
  * (`@opentui/solid`, `solid-js`). The entry (`src/tui.ts`) imports this module
28
- * dynamically only after its `process.platform === "win32"` check, so
29
- * non-Windows plugin setup never evaluates those modules.
31
+ * dynamically only after its own allowlist check, so unsupported-platform
32
+ * plugin setup never evaluates those modules.
30
33
  *
31
34
  * Test seams (platform/factory/deriver/password provider) exist only for
32
35
  * fake-based tests; production calls use the real defaults. The real password
@@ -49,7 +52,7 @@ import { EXPERIMENTAL_CRYPTO_POLICY_DEFINITION } from "./experimental-profile.ts
49
52
  export interface SessionPortInstallOptions {
50
53
  /** Platform gate override for tests; defaults to `process.platform`. */
51
54
  readonly platform?: string;
52
- /** Crypto-factory seam; the default creates the experimental Windows profile and awaits pinned sodium. */
55
+ /** Crypto-factory seam; the default creates the experimental profile (historical `-win-` selector name) and awaits pinned sodium. */
53
56
  readonly createCryptoFactory?: () => Promise<CheckpointCryptoFactory>;
54
57
  /** Remapped-ID deriver seam; the default awaits/validates pinned sodium. */
55
58
  readonly createIdDeriver?: () => Promise<RemappedIdDeriver>;
@@ -57,18 +60,21 @@ export interface SessionPortInstallOptions {
57
60
  readonly requestPassword?: SessionPortPasswordProvider;
58
61
  }
59
62
 
63
+ /** Explicit platform allowlist; unsupported platforms fail closed before any host access. */
64
+ const SUPPORTED_PLATFORMS: readonly string[] = ["win32", "darwin", "linux"];
65
+
60
66
  /**
61
- * Installs the SessionPort commands for the experimental Windows lane and
62
- * returns the slot disposer, or `undefined` when this platform is not
63
- * registered. Fails closed (rejects) when the pinned runtime or the host
64
- * command surface is unavailable; nothing is registered in that case.
67
+ * Installs the SessionPort commands for the experimental lane and returns the
68
+ * slot disposer, or `undefined` when this platform is not registered. Fails
69
+ * closed (rejects) when the pinned runtime or the host command surface is
70
+ * unavailable; nothing is registered in that case.
65
71
  */
66
72
  export async function installSessionPortWiring(
67
73
  context: Plugin.Context,
68
74
  options: SessionPortInstallOptions = {},
69
75
  ): Promise<(() => void) | undefined> {
70
- // Windows-first experimental gate: no registration and no host access anywhere else.
71
- if ((options.platform ?? process.platform) !== "win32") return undefined;
76
+ // Explicit allowlist gate: no registration and no host access on unsupported platforms.
77
+ if (!SUPPORTED_PLATFORMS.includes(options.platform ?? process.platform)) return undefined;
72
78
 
73
79
  // Pinned-runtime initialization (fail closed): the default factory awaits
74
80
  // `sodium.ready` and validates every primitive the provisional format needs;
@@ -102,7 +108,11 @@ export async function installSessionPortWiring(
102
108
  return installSessionPortCommands(context, handlers);
103
109
  }
104
110
 
105
- /** Default factory: the experimental Windows profile over the pinned runtime. */
111
+ /**
112
+ * Default factory: the experimental profile over the pinned runtime. The
113
+ * `sessionport-experimental-win-v1` selector name is historical and is not
114
+ * portability evidence; macOS/Linux enablement changes no profile value.
115
+ */
106
116
  async function createExperimentalCryptoFactory(): Promise<CheckpointCryptoFactory> {
107
117
  return createCheckpointCryptoFactory([EXPERIMENTAL_CRYPTO_POLICY_DEFINITION]);
108
118
  }
package/src/tui.ts CHANGED
@@ -1,13 +1,13 @@
1
1
  import { Plugin } from "@opencode/plugin/tui"
2
2
 
3
3
  /**
4
- * SessionPort TUI plugin entrypoint (Phase 2 experimental Windows wiring).
4
+ * SessionPort TUI plugin entrypoint (Phase 2 experimental wiring).
5
5
  *
6
- * Setup checks `process.platform` first and only on Windows dynamically imports
6
+ * Setup checks `process.platform` first and only on an explicitly allowed
7
+ * platform (`win32`, `darwin`, or `linux`) dynamically imports
7
8
  * `installSessionPortWiring`, which:
8
- * - registers `/checkpoint` and `/restore` only on Windows (`process.platform
9
- * === "win32"`); every other platform gets no registration and no
10
- * platform-support claim;
9
+ * - registers `/checkpoint` and `/restore` only on those platforms; every other
10
+ * platform gets no registration and no platform-support claim;
11
11
  * - initializes the pinned `libsodium-wrappers-sumo@0.8.4` runtime first and
12
12
  * fails closed if it is unavailable (setup rejects; nothing is registered);
13
13
  * - registers commands inside the existing app-slot/keymap component scope
@@ -15,19 +15,25 @@ import { Plugin } from "@opencode/plugin/tui"
15
15
  *
16
16
  * The platform gate deliberately runs before the dynamic import: the wiring
17
17
  * module statically imports the designer-owned UI modules, which import the
18
- * optional UI peers (`@opentui/solid`, `solid-js`). Non-Windows plugin setup
19
- * therefore never evaluates them, and no OpenTUI dependency is added to the
20
- * package surface.
18
+ * optional UI peers (`@opentui/solid`, `solid-js`). Unsupported-platform plugin
19
+ * setup therefore never evaluates them, and no OpenTUI dependency is added to
20
+ * the package surface.
21
21
  *
22
- * Command handlers own their errors and report sanitized copy; no raw host
23
- * error crosses to the host. The active Windows experimental defaults are
24
- * recorded in `docs/v1/decision-log.md`; this is not a production approval or
25
- * format freeze.
22
+ * Platform status: Windows has bounded actual-host evidence; macOS and Linux
23
+ * are owner-approved experimental targets enabled here but NOT host-tested, and
24
+ * cross-OS artifact interchange is UNVERIFIED. Command handlers own their
25
+ * errors and report sanitized copy; no raw host error crosses to the host. The
26
+ * active experimental defaults are recorded in `docs/v1/decision-log.md`; this
27
+ * is not a production approval or format freeze.
26
28
  */
29
+
30
+ /** Explicit allowlist; unsupported platforms fail closed before any host call. */
31
+ const SUPPORTED_PLATFORMS: readonly string[] = ["win32", "darwin", "linux"]
32
+
27
33
  export default Plugin.define({
28
34
  id: "sessionport",
29
35
  async setup(context) {
30
- if (process.platform !== "win32") return undefined
36
+ if (!SUPPORTED_PLATFORMS.includes(process.platform)) return undefined
31
37
  const { installSessionPortWiring } = await import("./tui/wiring/index.ts")
32
38
  return installSessionPortWiring(context)
33
39
  },
package/tui.ts CHANGED
@@ -2,11 +2,16 @@
2
2
  * SessionPort TUI entrypoint shim for the host's directory-based plugin
3
3
  * resolution (`Host.resolve` probes `<directory>/tui` by path, before any
4
4
  * package `exports` lookup). It re-exports the product entrypoint unchanged;
5
- * all behavior (Windows platform gate, pinned-sodium initialization, deferred
5
+ * all behavior (platform allowlist gate, pinned-sodium initialization, deferred
6
6
  * `./tui/wiring/index.ts` import) stays in `src/tui.ts`.
7
7
  *
8
8
  * This file is part of the packaged `files` allowlist so an installed copy of
9
9
  * the package resolves under the pinned Host.resolve convention. It adds no
10
10
  * registration, host access, or activation of its own.
11
+ *
12
+ * The re-export targets the compiled bundle `dist/tui.js`, not the TSX source:
13
+ * the directory loader probes `<directory>/tui` by path and would otherwise
14
+ * bypass the `exports["./tui"]` bundle entirely. `dist/tui.js` is produced by
15
+ * `build:tui` (wired as `prepack`) from `src/tui.ts`.
11
16
  */
12
- export { default } from "./src/tui.ts"
17
+ export { default } from "./dist/tui.js"