opencode-session-port 0.1.3 → 0.1.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.
package/README.md CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  SessionPort is a local plugin for the OpenCode TUI. It captures the sessions of your current project into a single password-encrypted artifact and restores them in another checkout, worktree, or machine. Artifacts travel with Git or any other channel you choose — SessionPort never runs Git commands itself.
6
6
 
7
- > **Status: experimental pre-release (0.1.3).** SessionPort completed one bounded synthetic checkpoint/restore round trip on Windows with OpenCode v2.0.22. That test used test-only password and project-selector seams and staged source, not the npm tarball. On one real Windows OpenCode v2.0.22 host, a bounded diagnostic observed both commands registered (`commands=yes`) but hidden from the command palette and slash list until the keymap layer opted into global mode; 0.1.2 applies that global-mode registration fix, with focused command-registration tests and the TUI build passing. 0.1.3 additionally enables the commands on macOS and Linux through an explicit platform allowlist (`win32`/`darwin`/`linux`); macOS and Linux have NOT been host-tested, and cross-OS artifact interchange is UNVERIFIED. End-to-end execution from the packed package has not been host-tested. Real modal interactions and loading the packed package in OpenCode have not been verified. The checkpoint format may change; no compatibility, security, or platform-support guarantee is made.
7
+ > **Status: experimental pre-release (0.1.4).** SessionPort completed one bounded synthetic checkpoint/restore round trip on Windows with OpenCode v2.0.22. That test used test-only password and project-selector seams and staged source, not the npm tarball. On one real Windows OpenCode v2.0.22 host, a bounded diagnostic observed both commands registered (`commands=yes`) but hidden from the command palette and slash list until the keymap layer opted into global mode; 0.1.2 applies that global-mode registration fix, with focused command-registration tests and the TUI build passing. 0.1.3 additionally enables the commands on macOS and Linux through an explicit platform allowlist (`win32`/`darwin`/`linux`). 0.1.2 and 0.1.3 are published to npm (0.1.3 latest, per a read-only registry check); 0.1.4 is the current local candidate. 0.1.4 is a diagnostics/copy patch only: a failed checkpoint collection now appends a fixed sanitized reason and the known machine code (`Reason: <fixed reason> (<code>).`) for the 17 current collection codes; unknown codes keep the generic text and raw host/exception text is never shown. Collector behavior is unchanged, and no root cause is established for an earlier Windows collection failure; a user later reported a local checkpoint succeeding from the repository checkout, which is not attributed to this patch. macOS has one user-reported successful checkpoint only; Linux is untested; restore and cross-OS artifact interchange remain unestablished. End-to-end execution from the packed package has not been host-tested. Real modal interactions and loading the packed package in OpenCode have not been verified. The checkpoint format may change; no compatibility, security, or platform-support guarantee is made.
8
8
 
9
9
  ## Commands
10
10
 
@@ -24,17 +24,17 @@ Add the plugin to the `plugins` array in your global CLI-only config (`cli.json`
24
24
 
25
25
  ```json
26
26
  {
27
- "plugins": ["opencode-session-port@0.1.3"]
27
+ "plugins": ["opencode-session-port@0.1.4"]
28
28
  }
29
29
  ```
30
30
 
31
31
  Or install the package plugin with the OpenCode CLI:
32
32
 
33
33
  ```sh
34
- opencode plugin add opencode-session-port@0.1.3
34
+ opencode plugin add opencode-session-port@0.1.4
35
35
  ```
36
36
 
37
- `cli.json` is the documented OpenCode v2 config for CLI-only plugins: they run locally in the terminal and remain active when the CLI connects to a remote server. No published tarball exists yet, so no published artifact has been loaded by OpenCode. The 0.1.1 tarball passed npm consumer checks, but a direct Bun package-manager install timed out in the verification environment, so that install path remains unverified. The 0.1.2 tarball passed manifest/allowlist and packed-entry checks only. The 0.1.3 metadata/platform-allowlist update has not been package-verified, published, or loaded by OpenCode.
37
+ `cli.json` is the documented OpenCode v2 config for CLI-only plugins: they run locally in the terminal and remain active when the CLI connects to a remote server. The npm registry shows 0.1.2 and 0.1.3 published (0.1.3 latest; read-only registry check); no published artifact has been loaded by OpenCode here, and no local package-verification record exists for the published 0.1.3 tarball. The 0.1.1 tarball passed npm consumer checks, but a direct Bun package-manager install timed out in the verification environment, so that install path remains unverified. The 0.1.2 tarball passed manifest/allowlist and packed-entry checks only. The 0.1.4 candidate tarball passed the same local manifest/allowlist and packed-entry checks (including the sanitized collection-failure copy); it is not published.
38
38
 
39
39
  ## Usage
40
40
 
package/dist/tui.js CHANGED
@@ -5866,7 +5866,7 @@ function reportCheckpointFailure(error) {
5866
5866
  case "capability":
5867
5867
  return checkpointFailure("This OpenCode host does not expose the required session-listing capability; no artifact was written.");
5868
5868
  case "collection":
5869
- return checkpointFailure("Collecting the project's sessions failed; no artifact was written.");
5869
+ return checkpointFailure(checkpointCollectionFailureMessage(error));
5870
5870
  case "path-exists":
5871
5871
  return checkpointFailure("An artifact already exists at that path; nothing was overwritten.");
5872
5872
  case "artifact-path":
@@ -5885,6 +5885,15 @@ function reportCheckpointFailure(error) {
5885
5885
  function checkpointFailure(message) {
5886
5886
  return { title: "Checkpoint failed", message, variant: "error" };
5887
5887
  }
5888
+ function checkpointCollectionFailureMessage(error) {
5889
+ if (!(error instanceof SessionCollectionError))
5890
+ return CHECKPOINT_COLLECTION_FAILURE;
5891
+ const code = error.code;
5892
+ if (!Object.hasOwn(CHECKPOINT_COLLECTION_REASONS, code))
5893
+ return CHECKPOINT_COLLECTION_FAILURE;
5894
+ const reason = CHECKPOINT_COLLECTION_REASONS[code];
5895
+ return `${CHECKPOINT_COLLECTION_FAILURE} Reason: ${reason} (${code}).`;
5896
+ }
5888
5897
  function reportRestoreUsage() {
5889
5898
  return {
5890
5899
  title: "Restore needs an artifact path",
@@ -6039,6 +6048,7 @@ function classifyFailure(error) {
6039
6048
  }
6040
6049
  return "unknown";
6041
6050
  }
6051
+ var CHECKPOINT_COLLECTION_FAILURE = "Collecting the project's sessions failed; no artifact was written.", CHECKPOINT_COLLECTION_REASONS;
6042
6052
  var init_reports = __esm(() => {
6043
6053
  init_files();
6044
6054
  init_adapters();
@@ -6047,6 +6057,25 @@ var init_reports = __esm(() => {
6047
6057
  init_planner();
6048
6058
  init_sessions();
6049
6059
  init_orchestration();
6060
+ CHECKPOINT_COLLECTION_REASONS = {
6061
+ "invalid-request": "the session collection request was invalid",
6062
+ "invalid-policy": "the session collection policy was invalid",
6063
+ "session-list-failed": "the host session list could not be read",
6064
+ "message-list-failed": "a session's message history could not be read",
6065
+ "malformed-session-page": "the host returned a malformed session list page",
6066
+ "malformed-message-page": "the host returned a malformed message list page",
6067
+ "malformed-session-record": "the host returned a malformed session record",
6068
+ "malformed-message-record": "the host returned a malformed message record",
6069
+ "session-project-mismatch": "a listed session did not belong to the requested project",
6070
+ "duplicate-session-id": "the host returned a session more than once",
6071
+ "duplicate-message-id": "the host returned a message more than once",
6072
+ "repeated-session-cursor": "the host repeated a session list cursor",
6073
+ "repeated-message-cursor": "the host repeated a message list cursor",
6074
+ "session-limit-exceeded": "the session count exceeded the configured limit",
6075
+ "message-limit-exceeded": "a session's message count exceeded the configured limit",
6076
+ "total-message-limit-exceeded": "the total message count exceeded the configured limit",
6077
+ "unsettled-message": "the project history contains an unfinished message"
6078
+ };
6050
6079
  });
6051
6080
 
6052
6081
  // src/tui/wiring/composition.ts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencode-session-port",
3
- "version": "0.1.3",
3
+ "version": "0.1.4",
4
4
  "private": false,
5
5
  "license": "MIT",
6
6
  "description": "SessionPort: experimental OpenCode TUI plugin for password-encrypted session checkpoint and restore.",
@@ -4,7 +4,10 @@
4
4
  * Every function here returns a fixed, generic notification object; raw host
5
5
  * or exception text is NEVER interpolated. Classification uses stable error
6
6
  * classes/codes only, never message text, so a failure report cannot leak
7
- * session IDs, paths, host internals, or password material. Exact user-facing
7
+ * session IDs, paths, host internals, or password material. Checkpoint
8
+ * collection failures additionally append a fixed human reason and the exact
9
+ * machine code, but only for `SessionCollectionError` codes on an explicit
10
+ * allowlist; unknown or forged codes keep the generic text. Exact user-facing
8
11
  * copy remains OPEN (OQ-15); these strings are the wiring lane's generic
9
12
  * sanitized categories.
10
13
  *
@@ -31,7 +34,7 @@ import { HostAdapterError, ProjectDestinationError } from "../adapters/index.ts"
31
34
  import { LocationResolutionError } from "../adapters/location-resolver.ts";
32
35
  import { CryptoContainerError } from "../../core/crypto/errors.ts";
33
36
  import { RestorePlanError } from "../../core/restore/planner.ts";
34
- import { SessionCollectionError } from "../../core/sessions/index.ts";
37
+ import { SessionCollectionError, type SessionCollectionErrorCode } from "../../core/sessions/index.ts";
35
38
  import { RESTORE_PASSWORD_ATTEMPT_LIMIT } from "../orchestration/index.ts";
36
39
  import type { CheckpointOutcome, RestoreExecutionResult } from "../orchestration/index.ts";
37
40
  import type {
@@ -94,7 +97,7 @@ export function reportCheckpointFailure(error: unknown): SessionPortNotification
94
97
  case "capability":
95
98
  return checkpointFailure("This OpenCode host does not expose the required session-listing capability; no artifact was written.");
96
99
  case "collection":
97
- return checkpointFailure("Collecting the project's sessions failed; no artifact was written.");
100
+ return checkpointFailure(checkpointCollectionFailureMessage(error));
98
101
  case "path-exists":
99
102
  return checkpointFailure("An artifact already exists at that path; nothing was overwritten.");
100
103
  case "artifact-path":
@@ -116,6 +119,51 @@ function checkpointFailure(message: string): SessionPortNotification {
116
119
  return { title: "Checkpoint failed", message, variant: "error" };
117
120
  }
118
121
 
122
+ /** Existing generic checkpoint collection failure copy; also the fallback for unknown codes. */
123
+ const CHECKPOINT_COLLECTION_FAILURE = "Collecting the project's sessions failed; no artifact was written.";
124
+
125
+ /**
126
+ * Fixed human reason per known `SessionCollectionError` code. This record is
127
+ * the explicit allowlist: the raw code is echoed to the user only when it
128
+ * exactly matches one of these keys, and the raw `error.message` (which can
129
+ * contain session/project IDs, paths, and host error text) is never used.
130
+ * Adding a code to `SessionCollectionErrorCode` fails compilation until a
131
+ * fixed reason is added here.
132
+ */
133
+ const CHECKPOINT_COLLECTION_REASONS: Readonly<Record<SessionCollectionErrorCode, string>> = {
134
+ "invalid-request": "the session collection request was invalid",
135
+ "invalid-policy": "the session collection policy was invalid",
136
+ "session-list-failed": "the host session list could not be read",
137
+ "message-list-failed": "a session's message history could not be read",
138
+ "malformed-session-page": "the host returned a malformed session list page",
139
+ "malformed-message-page": "the host returned a malformed message list page",
140
+ "malformed-session-record": "the host returned a malformed session record",
141
+ "malformed-message-record": "the host returned a malformed message record",
142
+ "session-project-mismatch": "a listed session did not belong to the requested project",
143
+ "duplicate-session-id": "the host returned a session more than once",
144
+ "duplicate-message-id": "the host returned a message more than once",
145
+ "repeated-session-cursor": "the host repeated a session list cursor",
146
+ "repeated-message-cursor": "the host repeated a message list cursor",
147
+ "session-limit-exceeded": "the session count exceeded the configured limit",
148
+ "message-limit-exceeded": "a session's message count exceeded the configured limit",
149
+ "total-message-limit-exceeded": "the total message count exceeded the configured limit",
150
+ "unsettled-message": "the project history contains an unfinished message",
151
+ };
152
+
153
+ /**
154
+ * Checkpoint collection failure copy: the existing generic message plus
155
+ * `Reason: <fixed human reason> (<known code>).` for a `SessionCollectionError`
156
+ * whose code is on the allowlist. Any other error or code keeps the generic
157
+ * text; only allowlisted literal code strings are ever echoed.
158
+ */
159
+ function checkpointCollectionFailureMessage(error: unknown): string {
160
+ if (!(error instanceof SessionCollectionError)) return CHECKPOINT_COLLECTION_FAILURE;
161
+ const code: string = error.code;
162
+ if (!Object.hasOwn(CHECKPOINT_COLLECTION_REASONS, code)) return CHECKPOINT_COLLECTION_FAILURE;
163
+ const reason = CHECKPOINT_COLLECTION_REASONS[code as SessionCollectionErrorCode];
164
+ return `${CHECKPOINT_COLLECTION_FAILURE} Reason: ${reason} (${code}).`;
165
+ }
166
+
119
167
  /* ------------------------------------------------------------------------- */
120
168
  /* Restore reports */
121
169
  /* ------------------------------------------------------------------------- */