@gp2f/client-sdk 1.0.0 → 1.0.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/README.md ADDED
@@ -0,0 +1,114 @@
1
+ # @gp2f/client-sdk
2
+
3
+ GP2F client SDK – reconciliation UX components and WebSocket client.
4
+
5
+ ## Overview
6
+ This SDK provides React components for opportunistic UI state reconciliation, along with a WebSocket client that directly interacts with the GP2F backend server using CRDTs. It is designed to create collaborative, real-time shared experiences seamlessly.
7
+
8
+ ## Installation
9
+ ```bash
10
+ npm install @gp2f/client-sdk
11
+ ```
12
+
13
+ ## Usage
14
+
15
+ ### 1. WebSocket Client (`Gp2fClient`)
16
+ The client provides robust sync over WebSockets with built-in Token Bucket rate-limiting and time-offset tracking.
17
+
18
+ ```typescript
19
+ import { Gp2fClient } from '@gp2f/client-sdk';
20
+
21
+ const client = new Gp2fClient({
22
+ url: 'ws://localhost:3000/ws',
23
+ onMessage: (msg) => {
24
+ console.log('Received from server:', msg);
25
+ },
26
+ onToken: (token, done) => {
27
+ // Helpful for streaming AI responses ("Time to First Token")
28
+ console.log(`Token: ${token}, Done: ${done}`);
29
+ },
30
+ onReloadRequired: (version, reason) => {
31
+ console.warn(`Incompatible AST schema (${version}): ${reason}`);
32
+ window.location.reload();
33
+ }
34
+ });
35
+
36
+ client.connect();
37
+
38
+ // Send messages (automatically rate-limited)
39
+ client.send({
40
+ type: 'SYNC',
41
+ payload: { /* ... */ }
42
+ });
43
+ ```
44
+
45
+ ### 2. Optimistic Updates
46
+ Visual indication for optimistic updates or LLM loading limits.
47
+
48
+ ```typescript
49
+ import { applyOptimisticUpdate } from '@gp2f/client-sdk';
50
+
51
+ const container = document.getElementById('my-loader-div');
52
+
53
+ // Shows a shimmering skeleton loader
54
+ const cleanup = applyOptimisticUpdate({
55
+ container,
56
+ confidence: 0.8, // >= 0.7 triggers high-confidence skeleton loader
57
+ thinkingText: "Vibe checking..."
58
+ });
59
+
60
+ // Later, when the update completes:
61
+ cleanup();
62
+ ```
63
+
64
+ ### 3. React Components
65
+ The SDK ships with React components to handle state conflicts and reconciliation UX:
66
+
67
+ ```tsx
68
+ import React from 'react';
69
+ import { ReconciliationBanner, UndoButton, MergeModal } from '@gp2f/client-sdk';
70
+
71
+ export function EditorHeader() {
72
+ return (
73
+ <header>
74
+ {/* Banner handles showing connection states and sync issues */}
75
+ <ReconciliationBanner
76
+ status="conflict"
77
+ onResolve={() => console.log('Resolve clicked')}
78
+ />
79
+
80
+ {/* Undo integration */}
81
+ <UndoButton
82
+ canUndo={true}
83
+ onUndo={() => console.log('Undo triggered!')}
84
+ />
85
+ </header>
86
+ );
87
+ }
88
+ ```
89
+
90
+ ### 4. Lazy Policy Evaluation (WASM Engine)
91
+ Load the fast WASM policy engine dynamically when needed without blocking the main thread.
92
+
93
+ ```typescript
94
+ import { loadPolicyEngine } from '@gp2f/client-sdk';
95
+
96
+ async function checkPolicy(state: any, ast: any) {
97
+ const engine = await loadPolicyEngine();
98
+ const { result } = engine.evaluate(
99
+ JSON.stringify(state),
100
+ JSON.stringify(ast)
101
+ );
102
+ return result;
103
+ }
104
+ ```
105
+
106
+ ## Peer Dependencies
107
+ Please note that you'll need `react` and `react-dom` version `>=18.0.0` installed in your host project.
108
+
109
+ ## Scripts
110
+ - **Build**: `npm run build`
111
+ - **Test**: `npm run test`
112
+
113
+ ## License
114
+ MIT
package/dist/index.js CHANGED
@@ -32,13 +32,17 @@ let _policyEngineCache = null;
32
32
  * to emit this as a separate chunk so it is only downloaded on demand.
33
33
  */
34
34
  async function _importPolicyEngine() {
35
- // Dynamic import bundlers will split this into a separate chunk.
36
- // We use a try/catch so that the SDK remains usable even when the optional
37
- // @gp2f/policy-core-wasm peer package is not installed.
35
+ // We intentionally defeat static import analysis by building the specifier
36
+ // at runtime. Vite / Rollup / webpack resolve bare string literals in
37
+ // dynamic imports at *build time*, before any try/catch can help. A computed
38
+ // expression is invisible to those static passes, so the try/catch below
39
+ // actually runs at runtime when the package is absent.
40
+ //
41
+ // If @gp2f/policy-core-wasm IS installed, this resolves normally.
42
+ // If it is NOT installed, the runtime import() throws and we return the stub.
43
+ const specifier = /* @vite-ignore */ "@gp2f/" + "policy-core-wasm";
38
44
  try {
39
- // @ts-expect-error: @gp2f/policy-core-wasm is an optional peer package
40
- // that may not be installed. The try/catch below handles the absence case.
41
- const mod = await import(/* webpackChunkName: "policy-engine" */ "@gp2f/policy-core-wasm");
45
+ const mod = await import(/* @vite-ignore */ specifier);
42
46
  return mod;
43
47
  }
44
48
  catch {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gp2f/client-sdk",
3
- "version": "1.0.0",
3
+ "version": "1.0.3",
4
4
  "description": "GP2F client SDK – reconciliation UX components and WebSocket client",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -28,7 +28,13 @@
28
28
  "license": "MIT",
29
29
  "peerDependencies": {
30
30
  "react": ">=18.0.0",
31
- "react-dom": ">=18.0.0"
31
+ "react-dom": ">=18.0.0",
32
+ "@gp2f/policy-core-wasm": "*"
33
+ },
34
+ "peerDependenciesMeta": {
35
+ "@gp2f/policy-core-wasm": {
36
+ "optional": true
37
+ }
32
38
  },
33
39
  "devDependencies": {
34
40
  "@types/react": "^18.0.0",
package/src/index.ts CHANGED
@@ -69,13 +69,17 @@ let _policyEngineCache: PolicyEngineModule | null = null;
69
69
  * to emit this as a separate chunk so it is only downloaded on demand.
70
70
  */
71
71
  async function _importPolicyEngine(): Promise<PolicyEngineModule> {
72
- // Dynamic import bundlers will split this into a separate chunk.
73
- // We use a try/catch so that the SDK remains usable even when the optional
74
- // @gp2f/policy-core-wasm peer package is not installed.
72
+ // We intentionally defeat static import analysis by building the specifier
73
+ // at runtime. Vite / Rollup / webpack resolve bare string literals in
74
+ // dynamic imports at *build time*, before any try/catch can help. A computed
75
+ // expression is invisible to those static passes, so the try/catch below
76
+ // actually runs at runtime when the package is absent.
77
+ //
78
+ // If @gp2f/policy-core-wasm IS installed, this resolves normally.
79
+ // If it is NOT installed, the runtime import() throws and we return the stub.
80
+ const specifier = /* @vite-ignore */ "@gp2f/" + "policy-core-wasm";
75
81
  try {
76
- // @ts-expect-error: @gp2f/policy-core-wasm is an optional peer package
77
- // that may not be installed. The try/catch below handles the absence case.
78
- const mod = await import(/* webpackChunkName: "policy-engine" */ "@gp2f/policy-core-wasm");
82
+ const mod = await import(/* @vite-ignore */ specifier);
79
83
  return mod as PolicyEngineModule;
80
84
  } catch {
81
85
  // WASM package not installed – return a stub that always delegates to the