usemycontext 1.0.1 → 1.0.2
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 +29 -2
- package/dist/index.cjs +0 -12
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +0 -12
- package/dist/index.js.map +1 -1
- package/dist/react.cjs +0 -35
- package/dist/react.cjs.map +1 -1
- package/dist/react.js +0 -35
- package/dist/react.js.map +1 -1
- package/package.json +4 -1
package/README.md
CHANGED
|
@@ -109,8 +109,35 @@ v1 is **token-in only**: you supply the user's UseMyContext session token to
|
|
|
109
109
|
|
|
110
110
|
## Persistence
|
|
111
111
|
|
|
112
|
-
|
|
113
|
-
`
|
|
112
|
+
**Default: the token is kept in memory only and is never written to
|
|
113
|
+
`localStorage` unless you opt in.** It does not survive a page reload by default.
|
|
114
|
+
|
|
115
|
+
This is deliberate, but be clear about what it does and does not do. The v1 token
|
|
116
|
+
is the user's long-lived session credential. Memory-only persistence **reduces**
|
|
117
|
+
its exposure - the token is never written to disk, is gone on reload, and cannot
|
|
118
|
+
be read at rest from `localStorage` - but it does **not** eliminate it: while the
|
|
119
|
+
client is connected the token still lives in the host page's memory, so a script
|
|
120
|
+
running on your page (an XSS) could still read it during a live session.
|
|
121
|
+
|
|
122
|
+
The long-lived-token-in-the-host-page problem is **not** solved by storage choice.
|
|
123
|
+
It is solved by **v2's token lifecycle**: short-lived access tokens plus an
|
|
124
|
+
httpOnly refresh cookie on `connect.usemycontext.ai`, so the host page never holds
|
|
125
|
+
a long-lived credential at all. Until then, treat the v1 token as sensitive and
|
|
126
|
+
keep your page free of untrusted scripts.
|
|
127
|
+
|
|
128
|
+
If you want the token to survive reloads, opt in knowingly (this trades the
|
|
129
|
+
above reduction away - the token is now also readable at rest from `localStorage`):
|
|
130
|
+
|
|
131
|
+
```js
|
|
132
|
+
import { useMyContext, webStorage } from "usemycontext";
|
|
133
|
+
|
|
134
|
+
// You accept that the token now lives in localStorage, readable by any
|
|
135
|
+
// script on the page. The httpOnly-cookie model (no token in the host page)
|
|
136
|
+
// lands in v2.
|
|
137
|
+
useMyContext({ storage: webStorage(localStorage) });
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
Pass `storage: null` to use a no-op store, or supply your own `StorageAdapter`:
|
|
114
141
|
|
|
115
142
|
```js
|
|
116
143
|
useMyContext({ storage: null });
|
package/dist/index.cjs
CHANGED
|
@@ -147,18 +147,6 @@ function resolveStorage(opt) {
|
|
|
147
147
|
} };
|
|
148
148
|
}
|
|
149
149
|
if (opt) return opt;
|
|
150
|
-
try {
|
|
151
|
-
if (typeof globalThis !== "undefined") {
|
|
152
|
-
const ls = globalThis.localStorage;
|
|
153
|
-
if (ls) {
|
|
154
|
-
const probe = "__umc_probe__";
|
|
155
|
-
ls.setItem(probe, "1");
|
|
156
|
-
ls.removeItem(probe);
|
|
157
|
-
return webStorage(ls);
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
} catch {
|
|
161
|
-
}
|
|
162
150
|
return memoryStorage();
|
|
163
151
|
}
|
|
164
152
|
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/jsonrpc.ts","../src/machine.ts","../src/storage.ts","../src/transport.ts","../src/client.ts"],"names":[],"mappings":"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","file":"index.cjs","sourcesContent":["// JSON-RPC 2.0 framing for the membrane MCP wire, plus the SDK error taxonomy.\n//\n// The membrane speaks hand-rolled JSON-RPC over Streamable HTTP. The SDK only\n// ever sends `initialize` and `tools/call`. A tools/call comes back as a RESULT\n// shaped `{ content: [{ type:\"text\", text }], isError }`; a protocol-level\n// failure comes back as a JSON-RPC `error` object. This module owns the framing\n// + the parsing helpers; the wrappers in client.ts decode the text content.\n\n/** A JSON-RPC request envelope. */\nexport interface JsonRpcRequest {\n jsonrpc: \"2.0\";\n id: number;\n method: string;\n params?: unknown;\n}\n\n/** A JSON-RPC error object. */\nexport interface JsonRpcErrorObject {\n code: number;\n message: string;\n data?: unknown;\n}\n\n/** A parsed JSON-RPC response (success xor error). */\nexport interface JsonRpcResponse {\n jsonrpc: \"2.0\";\n id: number | null;\n result?: unknown;\n error?: JsonRpcErrorObject;\n}\n\n/** The MCP tools/call result shape (`content` blocks + an error flag). */\nexport interface ToolResult {\n content: Array<{ type: string; text?: string }>;\n isError?: boolean;\n}\n\n/** Base class for every error the SDK throws, so callers can `catch (e)`. */\nexport class UseMyContextError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"UseMyContextError\";\n // Restore the prototype chain (TS target < ES2015 / transpiled extends).\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\n/** Thrown when a tool wrapper is called before a successful `connect()`. */\nexport class NotConnectedError extends UseMyContextError {\n constructor(message = \"Not connected. Call connect({ token }) first.\") {\n super(message);\n this.name = \"NotConnectedError\";\n }\n}\n\n/**\n * Thrown when the membrane rejects the token (HTTP 401 + WWW-Authenticate).\n * The client also transitions to `expired` so the host can re-connect.\n */\nexport class TokenExpiredError extends UseMyContextError {\n /** The raw `WWW-Authenticate` header, when the server sent one. */\n readonly wwwAuthenticate?: string;\n constructor(message = \"The connection token was rejected (expired or revoked).\", wwwAuthenticate?: string) {\n super(message);\n this.name = \"TokenExpiredError\";\n this.wwwAuthenticate = wwwAuthenticate;\n }\n}\n\n/** Thrown when a tool call is refused for lack of scope (membrane -32604). */\nexport class ScopeDeniedError extends UseMyContextError {\n readonly code = -32604;\n constructor(message: string) {\n super(message);\n this.name = \"ScopeDeniedError\";\n }\n}\n\n/** Thrown for a JSON-RPC protocol error or a tool-level `isError` result. */\nexport class ToolCallError extends UseMyContextError {\n /** The JSON-RPC error code, when the failure was a protocol error. */\n readonly code?: number;\n constructor(message: string, code?: number) {\n super(message);\n this.name = \"ToolCallError\";\n this.code = code;\n }\n}\n\n/** Thrown for transport/parse failures (network down, non-JSON body, ...). */\nexport class TransportError extends UseMyContextError {\n constructor(message: string) {\n super(message);\n this.name = \"TransportError\";\n }\n}\n\nlet nextId = 1;\n\n/** Build an `initialize` request (the connect handshake). */\nexport function initializeRequest(): JsonRpcRequest {\n return {\n jsonrpc: \"2.0\",\n id: nextId++,\n method: \"initialize\",\n params: {\n protocolVersion: \"2025-06-18\",\n capabilities: {},\n clientInfo: { name: \"usemycontext-sdk\", version: \"0.1.0\" },\n },\n };\n}\n\n/** Build a `tools/call` request for a tool name + arguments. */\nexport function toolCallRequest(name: string, args: Record<string, unknown>): JsonRpcRequest {\n return {\n jsonrpc: \"2.0\",\n id: nextId++,\n method: \"tools/call\",\n params: { name, arguments: args },\n };\n}\n\n/**\n * Narrow an unknown body to a JSON-RPC response. Throws TransportError when the\n * body is not a well-formed JSON-RPC 2.0 envelope (a defensive guard against a\n * misbehaving transport or an HTML error page).\n */\nexport function asJsonRpcResponse(body: unknown): JsonRpcResponse {\n if (body === null || typeof body !== \"object\") {\n throw new TransportError(\"Membrane returned a non-object response body.\");\n }\n const b = body as Record<string, unknown>;\n if (b.jsonrpc !== \"2.0\") {\n throw new TransportError(\"Membrane response was not JSON-RPC 2.0.\");\n }\n return b as unknown as JsonRpcResponse;\n}\n\n/** True iff a JSON-RPC error code denotes a missing-scope denial (-32604). */\nexport function isScopeDenied(code: number): boolean {\n return code === -32604;\n}\n\n/**\n * Pull the single text block out of a tools/call RESULT. The membrane always\n * renders to ONE text content block, so this returns its `text` (or \"\" when a\n * result carried no text block).\n */\nexport function resultText(result: ToolResult): string {\n for (const block of result.content ?? []) {\n if (block.type === \"text\" && typeof block.text === \"string\") return block.text;\n }\n return \"\";\n}\n","// The connect state machine - a PURE reducer (no IO, no timers, no `this`).\n//\n// States (ConnectState):\n// idle -> connecting -> connected\n// \\-> declined (user/host refused; v2 OAuth path)\n// \\-> error (network/transport/parse failure)\n// connected -> expired (membrane 401 mid-session)\n// connected -> disconnected (explicit disconnect)\n// <any> -> disconnected (disconnect is always reachable)\n// <terminal>-> connecting (a fresh connect() retries)\n//\n// The reducer is the single source of truth for legality: an event that does\n// not apply to the current state is a NO-OP (returns the same state), so the\n// client can fire events without guarding, and tests can assert every legal AND\n// illegal transition deterministically.\n\nimport type { ConnectState } from \"./types.js\";\n\n/** The events that drive the machine. */\nexport type ConnectEvent =\n | { type: \"CONNECT\" } // begin a connect attempt\n | { type: \"CONNECT_SUCCESS\" } // membrane accepted the token\n | { type: \"CONNECT_DECLINED\" } // user/host refused (v2 OAuth path)\n | { type: \"TOKEN_EXPIRED\" } // membrane 401 (expired/revoked)\n | { type: \"ERROR\" } // a non-auth failure\n | { type: \"DISCONNECT\" }; // explicit disconnect / token cleared\n\n/** The initial state of a fresh client. */\nexport const INITIAL_STATE: ConnectState = \"idle\";\n\n/**\n * The pure transition function. Returns the NEXT state for `(state, event)`, or\n * the SAME state when the event is illegal in that state (a no-op).\n */\nexport function reduce(state: ConnectState, event: ConnectEvent): ConnectState {\n switch (event.type) {\n case \"CONNECT\":\n // A connect attempt is legal from any NON-in-flight state: a fresh client,\n // a terminal/failed state (retry), or an already-connected client\n // (re-connect with a new token). It is a no-op only while already\n // connecting (a second concurrent connect does nothing).\n return state === \"connecting\" ? state : \"connecting\";\n\n case \"CONNECT_SUCCESS\":\n // Only a connect IN FLIGHT can succeed. Any other state ignores it (a\n // stale/duplicate success after disconnect must not resurrect the client).\n return state === \"connecting\" ? \"connected\" : state;\n\n case \"CONNECT_DECLINED\":\n // Only a connect in flight can be declined.\n return state === \"connecting\" ? \"declined\" : state;\n\n case \"ERROR\":\n // A connect in flight can fail with a non-auth error. (A wrapper-call\n // failure while `connected` does NOT change the connect state - the\n // connection is still valid - so ERROR is a no-op when connected.)\n return state === \"connecting\" ? \"error\" : state;\n\n case \"TOKEN_EXPIRED\":\n // The membrane rejected the token. Legal from `connecting` (the token was\n // bad at connect time) or `connected` (it expired/was revoked mid-session).\n return state === \"connecting\" || state === \"connected\" ? \"expired\" : state;\n\n case \"DISCONNECT\":\n // Disconnect is ALWAYS reachable and idempotent: it moves any state to\n // `disconnected` (a no-op only when already there).\n return state === \"disconnected\" ? state : \"disconnected\";\n\n default: {\n // Exhaustiveness: a new event type must be handled above.\n const _never: never = event;\n return state;\n }\n }\n}\n\n/** Every state the machine can occupy (for reachability assertions). */\nexport const ALL_STATES: readonly ConnectState[] = [\n \"idle\",\n \"connecting\",\n \"connected\",\n \"declined\",\n \"expired\",\n \"error\",\n \"disconnected\",\n] as const;\n\n/** Whether the 7 tool wrappers may be called in this state. */\nexport function isConnected(state: ConnectState): boolean {\n return state === \"connected\";\n}\n","// Token persistence. Defaults to `localStorage` when present (the browser host\n// page), falls back to an in-memory store (SSR / Node / tests), and can be\n// disabled entirely (pass `storage: null` to the client).\n\nimport type { StorageAdapter } from \"./types.js\";\n\n/** The default storage key the token is persisted under. */\nexport const DEFAULT_STORAGE_KEY = \"usemycontext.token\";\n\n/** An in-memory storage adapter (SSR-safe; the fallback when no localStorage). */\nexport function memoryStorage(): StorageAdapter {\n const map = new Map<string, string>();\n return {\n get: (k) => (map.has(k) ? (map.get(k) as string) : null),\n set: (k, v) => void map.set(k, v),\n remove: (k) => void map.delete(k),\n };\n}\n\n/** Wrap a Web Storage (localStorage/sessionStorage) as a StorageAdapter. */\nexport function webStorage(store: Storage): StorageAdapter {\n return {\n get: (k) => {\n try {\n return store.getItem(k);\n } catch {\n return null;\n }\n },\n set: (k, v) => {\n try {\n store.setItem(k, v);\n } catch {\n /* quota / privacy mode - degrade to no-persist, never throw */\n }\n },\n remove: (k) => {\n try {\n store.removeItem(k);\n } catch {\n /* ignore */\n }\n },\n };\n}\n\n/**\n * Resolve the storage adapter to use given the option:\n * - an explicit adapter -> use it;\n * - `null` -> persistence disabled (a no-op adapter);\n * - `undefined` -> localStorage when available, else in-memory.\n */\nexport function resolveStorage(opt: StorageAdapter | null | undefined): StorageAdapter {\n if (opt === null) {\n return { get: () => null, set: () => {}, remove: () => {} };\n }\n if (opt) return opt;\n // Browser: prefer localStorage. Guarded for SSR + privacy-mode throws.\n try {\n if (typeof globalThis !== \"undefined\") {\n const ls = (globalThis as { localStorage?: Storage }).localStorage;\n if (ls) {\n // Probe it - some environments expose a localStorage that throws on use.\n const probe = \"__umc_probe__\";\n ls.setItem(probe, \"1\");\n ls.removeItem(probe);\n return webStorage(ls);\n }\n }\n } catch {\n /* fall through to in-memory */\n }\n return memoryStorage();\n}\n","// The default `fetch`-based transport. Tests inject a mock transport instead, so\n// this module is never exercised by the (zero-network) test suite - it is the\n// production wiring that POSTs one JSON-RPC request to the membrane `/mcp`\n// endpoint with the user's bearer token.\n\nimport type { Transport, TransportResponse } from \"./types.js\";\n\n/** A `fetch`-backed Transport (the default when none is supplied). */\nexport const fetchTransport: Transport = async ({ url, token, body }): Promise<TransportResponse> => {\n const res = await fetch(url, {\n method: \"POST\",\n headers: {\n \"content-type\": \"application/json\",\n accept: \"application/json\",\n authorization: `Bearer ${token}`,\n },\n body: JSON.stringify(body),\n });\n let parsed: unknown = null;\n try {\n parsed = await res.json();\n } catch {\n parsed = null; // non-JSON / empty body (e.g. a 401 with no body)\n }\n return {\n status: res.status,\n body: parsed,\n wwwAuthenticate: res.headers.get(\"www-authenticate\"),\n };\n};\n","// The core client: `useMyContext()` (a framework-free factory) + the 7 tool\n// wrappers. It holds the user's OWN token and calls the membrane exactly like\n// Claude does - same trust model, new client shape. The service stays\n// structurally blind.\n//\n// v1 IS TOKEN-IN ONLY: `connect({ token })`. The full browser-OAuth-in-the-SDK\n// flow (a hosted popup on connect.usemycontext.ai) is v2, gated on the Phase 2\n// CORS landing - deliberately NOT built here.\n\nimport {\n initializeRequest,\n toolCallRequest,\n asJsonRpcResponse,\n resultText,\n isScopeDenied,\n NotConnectedError,\n TokenExpiredError,\n ScopeDeniedError,\n ToolCallError,\n TransportError,\n UseMyContextError,\n type ToolResult,\n} from \"./jsonrpc.js\";\nimport { reduce, INITIAL_STATE, isConnected } from \"./machine.js\";\nimport { resolveStorage, DEFAULT_STORAGE_KEY } from \"./storage.js\";\nimport { fetchTransport } from \"./transport.js\";\nimport type {\n ClientOptions,\n ConnectArgs,\n ConnectState,\n FileMeta,\n ProfileResult,\n AskOptions,\n AskResult,\n AskPassage,\n GetFileResult,\n SuggestUpdateResult,\n SharedContextResult,\n SharedContextEntry,\n StorageAdapter,\n Transport,\n} from \"./types.js\";\n\n/** The production membrane MCP endpoint. */\nexport const DEFAULT_ENDPOINT = \"https://mcp.usemycontext.ai/mcp\";\n\n/** The shape `useMyContext()` returns - the client handle. */\nexport interface UseMyContextClient {\n /** The current connect state. */\n readonly state: ConnectState;\n /** Convenience: true iff `state === \"connected\"`. */\n readonly connected: boolean;\n /** The held token, when connected (else null). */\n readonly token: string | null;\n\n /** Subscribe to state changes. Returns an unsubscribe fn. */\n subscribe(listener: (state: ConnectState) => void): () => void;\n\n /** v1 TOKEN-IN connect: validate the token against the membrane. */\n connect(args: ConnectArgs): Promise<ConnectState>;\n /** Clear the token + persisted storage; -> `disconnected`. */\n disconnect(): void;\n\n // --- the 7 MCP tool wrappers ---\n profile(): Promise<ProfileResult>;\n listFiles(): Promise<FileMeta[]>;\n searchFiles(query: string): Promise<FileMeta[]>;\n getFile(fileId: string): Promise<GetFileResult>;\n ask(query: string, opts?: AskOptions): Promise<AskResult>;\n suggestUpdate(suggestion: string): Promise<SuggestUpdateResult>;\n sharedContext(from?: string): Promise<SharedContextResult>;\n}\n\n/**\n * Create a UseMyContext client. Framework-free: the React hook wraps this.\n * Restores a persisted token (without revalidating) so a returning host page\n * starts `connected`; a stale token surfaces as `expired` on the first call.\n */\nexport function useMyContext(options: ClientOptions = {}): UseMyContextClient {\n const endpoint = options.endpoint ?? DEFAULT_ENDPOINT;\n const transport: Transport = options.transport ?? fetchTransport;\n const storage: StorageAdapter = resolveStorage(options.storage);\n const storageKey = options.storageKey ?? DEFAULT_STORAGE_KEY;\n\n const listeners = new Set<(state: ConnectState) => void>();\n let state: ConnectState = INITIAL_STATE;\n let token: string | null = null;\n\n // Restore a persisted token: a returning page is `connected` optimistically\n // (the membrane is the authority - a stale token -> `expired` on first call).\n const persisted = storage.get(storageKey);\n if (persisted) {\n token = persisted;\n state = \"connected\";\n }\n\n function setState(next: ConnectState): void {\n if (next === state) return;\n state = next;\n options.onStateChange?.(state);\n for (const l of listeners) l(state);\n }\n\n function dispatch(event: Parameters<typeof reduce>[1]): void {\n setState(reduce(state, event));\n }\n\n /** One JSON-RPC round-trip against the membrane with the held token. */\n async function rpc(body: unknown): Promise<unknown> {\n if (!token) throw new NotConnectedError();\n let res;\n try {\n res = await transport({ url: endpoint, token, body });\n } catch (e) {\n throw new TransportError(\n `Transport failed: ${e instanceof Error ? e.message : String(e)}`,\n );\n }\n // A 401 means the token is bad/expired/revoked. Drive the machine to\n // `expired` and throw - the host should re-connect.\n if (res.status === 401) {\n dispatch({ type: \"TOKEN_EXPIRED\" });\n throw new TokenExpiredError(undefined, res.wwwAuthenticate ?? undefined);\n }\n const parsed = asJsonRpcResponse(res.body);\n if (parsed.error) {\n if (isScopeDenied(parsed.error.code)) {\n throw new ScopeDeniedError(parsed.error.message);\n }\n throw new ToolCallError(parsed.error.message, parsed.error.code);\n }\n return parsed.result;\n }\n\n /** A tools/call that returns the single rendered text block. */\n async function callTool(name: string, args: Record<string, unknown>): Promise<string> {\n if (!isConnected(state)) throw new NotConnectedError();\n const result = (await rpc(toolCallRequest(name, args))) as ToolResult;\n if (result.isError) {\n throw new ToolCallError(resultText(result) || `${name} failed.`);\n }\n return resultText(result);\n }\n\n return {\n get state() {\n return state;\n },\n get connected() {\n return state === \"connected\";\n },\n get token() {\n return state === \"connected\" ? token : null;\n },\n\n subscribe(listener) {\n listeners.add(listener);\n return () => void listeners.delete(listener);\n },\n\n async connect({ token: t }: ConnectArgs): Promise<ConnectState> {\n if (typeof t !== \"string\" || t.length === 0) {\n // A bad arg is a developer error, not a state transition.\n throw new UseMyContextConnectArgError();\n }\n dispatch({ type: \"CONNECT\" });\n token = t;\n try {\n const res = await transport({ url: endpoint, token: t, body: initializeRequest() });\n if (res.status === 401) {\n token = null;\n dispatch({ type: \"TOKEN_EXPIRED\" });\n throw new TokenExpiredError(undefined, res.wwwAuthenticate ?? undefined);\n }\n // Validate the handshake came back as a well-formed JSON-RPC result.\n const parsed = asJsonRpcResponse(res.body);\n if (parsed.error) {\n token = null;\n dispatch({ type: \"ERROR\" });\n throw new ToolCallError(parsed.error.message, parsed.error.code);\n }\n dispatch({ type: \"CONNECT_SUCCESS\" });\n if (storage) storage.set(storageKey, t);\n return state;\n } catch (e) {\n token = null;\n // TokenExpiredError already drove the machine to `expired`; any other\n // failure is a non-auth `error`.\n if (!(e instanceof TokenExpiredError)) {\n dispatch({ type: \"ERROR\" });\n if (e instanceof TransportError || e instanceof ToolCallError) throw e;\n throw new TransportError(\n `Connect failed: ${e instanceof Error ? e.message : String(e)}`,\n );\n }\n throw e;\n }\n },\n\n disconnect(): void {\n token = null;\n storage.remove(storageKey);\n dispatch({ type: \"DISCONNECT\" });\n },\n\n // --- profile ---------------------------------------------------------\n async profile(): Promise<ProfileResult> {\n const text = await callTool(\"profile\", {});\n // The membrane serves the compiled composite as plain text, OR (no compile\n // yet) the JSON of `{ facts: [...] }`. Detect the fallback by parsing.\n const facts = tryParseFacts(text);\n if (facts) return { composite: text, facts };\n return { composite: text };\n },\n\n // --- list_files / search_files (JSON array of FileMeta) --------------\n async listFiles(): Promise<FileMeta[]> {\n return parseFileList(await callTool(\"list_files\", {}));\n },\n async searchFiles(query: string): Promise<FileMeta[]> {\n if (typeof query !== \"string\") throw new UseMyContextConnectArgError(\"search query must be a string\");\n return parseFileList(await callTool(\"search_files\", { query }));\n },\n\n // --- get_file --------------------------------------------------------\n async getFile(fileId: string): Promise<GetFileResult> {\n if (typeof fileId !== \"string\" || !fileId) {\n throw new UseMyContextConnectArgError(\"fileId must be a non-empty string\");\n }\n const text = await callTool(\"get_file\", { fileId });\n return { text, downloadUrl: parseDownloadUrl(text) };\n },\n\n // --- ask_docs --------------------------------------------------------\n async ask(query: string, opts: AskOptions = {}): Promise<AskResult> {\n if (typeof query !== \"string\" || !query) {\n throw new UseMyContextConnectArgError(\"ask query must be a non-empty string\");\n }\n const args: Record<string, unknown> = { query };\n if (typeof opts.k === \"number\") args.k = opts.k;\n if (typeof opts.projectId === \"string\") args.projectId = opts.projectId;\n const text = await callTool(\"ask_docs\", args);\n return { passages: parseAskPassages(text), text };\n },\n\n // --- suggest_update (the one write) ----------------------------------\n async suggestUpdate(suggestion: string): Promise<SuggestUpdateResult> {\n if (typeof suggestion !== \"string\" || !suggestion.trim()) {\n throw new UseMyContextConnectArgError(\"suggestion must be a non-empty string\");\n }\n const text = await callTool(\"suggest_update\", { suggestion });\n const m = text.match(/\\(id:\\s*([^)]+)\\)/);\n return { id: m ? m[1].trim() : undefined, text };\n },\n\n // --- shared_context --------------------------------------------------\n async sharedContext(from?: string): Promise<SharedContextResult> {\n const args: Record<string, unknown> = {};\n if (typeof from === \"string\" && from) args.from = from;\n const text = await callTool(\"shared_context\", args);\n return from ? parseSharedRead(text) : parseSharedList(text);\n },\n };\n}\n\n/** Thrown for a bad SDK call argument (a developer error, not a state event). */\nexport class UseMyContextConnectArgError extends UseMyContextError {\n constructor(message = \"connect() requires a non-empty token string.\") {\n super(message);\n this.name = \"UseMyContextConnectArgError\";\n }\n}\n\n// --- parsers (decode the membrane's RENDERED text back to typed shapes) ---\n\n/** Parse `profile`'s JSON fallback (`{facts:[...]}`); null when it's prose. */\nfunction tryParseFacts(text: string): string[] | undefined {\n const trimmed = text.trimStart();\n if (!trimmed.startsWith(\"{\")) return undefined;\n try {\n const obj = JSON.parse(text) as { facts?: unknown };\n if (Array.isArray(obj.facts)) return obj.facts.filter((f): f is string => typeof f === \"string\");\n } catch {\n /* prose composite that happens to start with \"{\" - treat as composite */\n }\n return undefined;\n}\n\n/** Parse a list/search JSON array into FileMeta[]. */\nfunction parseFileList(text: string): FileMeta[] {\n try {\n const arr = JSON.parse(text) as unknown;\n if (!Array.isArray(arr)) return [];\n return arr.map((r) => {\n const o = (r ?? {}) as Record<string, unknown>;\n return {\n id: String(o.id ?? \"\"),\n name: String(o.name ?? \"\"),\n size: typeof o.size === \"number\" ? o.size : 0,\n contentType: String(o.contentType ?? \"\"),\n modified: String(o.modified ?? \"\"),\n ...(typeof o.status === \"string\" ? { status: o.status as FileMeta[\"status\"] } : {}),\n };\n });\n } catch {\n return [];\n }\n}\n\n/** Pull a `Download link ... : <url>` out of a get_file render. */\nfunction parseDownloadUrl(text: string): string | undefined {\n const m = text.match(/Download link[^:]*:\\s*(\\S+)/);\n return m ? m[1] : undefined;\n}\n\n/**\n * Parse `renderAskDocs` output: blocks separated by a blank line, each a\n * `[n] file · scope · score X.XXX` citation line then the passage text. An empty\n * result is the calm \"No relevant passages...\" sentence -> zero passages.\n */\nfunction parseAskPassages(text: string): AskPassage[] {\n if (/^No relevant passages/i.test(text.trimStart())) return [];\n const blocks = text.split(\"\\n\\n\");\n const out: AskPassage[] = [];\n for (const block of blocks) {\n const nl = block.indexOf(\"\\n\");\n const citation = nl === -1 ? block : block.slice(0, nl);\n const body = nl === -1 ? \"\" : block.slice(nl + 1);\n const m = citation.match(/^\\[(\\d+)\\]\\s*(.*)$/);\n if (!m) continue;\n const index = Number(m[1]);\n const rest = m[2];\n // rest = `file · scope · score N.NNN`\n const parts = rest.split(\" · \");\n const passage: AskPassage = { index, text: body };\n if (parts[0]) passage.file = parts[0].trim();\n if (parts[1]) passage.scope = parts[1].trim();\n const scoreM = rest.match(/score\\s+([\\d.]+)/);\n if (scoreM) passage.score = Number(scoreM[1]);\n out.push(passage);\n }\n return out;\n}\n\n/** Parse `renderSharedContext` LIST output (lines `- who (from: grantId)`). */\nfunction parseSharedList(text: string): SharedContextResult {\n if (/^No one has shared/i.test(text.trimStart())) {\n return { mode: \"list\", shares: [], composite: null, text };\n }\n const shares: SharedContextEntry[] = [];\n for (const line of text.split(\"\\n\")) {\n const m = line.match(/^-\\s*(.*?)\\s*\\(from:\\s*([^)]+)\\)\\s*$/);\n if (m) shares.push({ ownerLabel: m[1].trim(), grantId: m[2].trim() });\n }\n return { mode: \"list\", shares, composite: null, text };\n}\n\n/** Parse `renderSharedContext` READ output (`Shared context from X:\\n\\n<text>`). */\nfunction parseSharedRead(text: string): SharedContextResult {\n if (/not available/i.test(text)) {\n return { mode: \"read\", shares: [], composite: null, text };\n }\n const m = text.match(/^Shared context from [^:]*:\\n\\n([\\s\\S]*)$/);\n const composite = m ? m[1] : text;\n return { mode: \"read\", shares: [], composite, text };\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/jsonrpc.ts","../src/machine.ts","../src/storage.ts","../src/transport.ts","../src/client.ts"],"names":[],"mappings":";;;AAsCO,IAAM,iBAAA,GAAN,cAAgC,KAAA,CAAM;AAAA,EAC3C,YAAY,OAAA,EAAiB;AAC3B,IAAA,KAAA,CAAM,OAAO,CAAA;AACb,IAAA,IAAA,CAAK,IAAA,GAAO,mBAAA;AAEZ,IAAA,MAAA,CAAO,cAAA,CAAe,IAAA,EAAM,GAAA,CAAA,MAAA,CAAW,SAAS,CAAA;AAAA,EAClD;AACF;AAGO,IAAM,iBAAA,GAAN,cAAgC,iBAAA,CAAkB;AAAA,EACvD,WAAA,CAAY,UAAU,+CAAA,EAAiD;AACrE,IAAA,KAAA,CAAM,OAAO,CAAA;AACb,IAAA,IAAA,CAAK,IAAA,GAAO,mBAAA;AAAA,EACd;AACF;AAMO,IAAM,iBAAA,GAAN,cAAgC,iBAAA,CAAkB;AAAA,EAGvD,WAAA,CAAY,OAAA,GAAU,yDAAA,EAA2D,eAAA,EAA0B;AACzG,IAAA,KAAA,CAAM,OAAO,CAAA;AACb,IAAA,IAAA,CAAK,IAAA,GAAO,mBAAA;AACZ,IAAA,IAAA,CAAK,eAAA,GAAkB,eAAA;AAAA,EACzB;AACF;AAGO,IAAM,gBAAA,GAAN,cAA+B,iBAAA,CAAkB;AAAA,EAEtD,YAAY,OAAA,EAAiB;AAC3B,IAAA,KAAA,CAAM,OAAO,CAAA;AAFf,IAAA,IAAA,CAAS,IAAA,GAAO,MAAA;AAGd,IAAA,IAAA,CAAK,IAAA,GAAO,kBAAA;AAAA,EACd;AACF;AAGO,IAAM,aAAA,GAAN,cAA4B,iBAAA,CAAkB;AAAA,EAGnD,WAAA,CAAY,SAAiB,IAAA,EAAe;AAC1C,IAAA,KAAA,CAAM,OAAO,CAAA;AACb,IAAA,IAAA,CAAK,IAAA,GAAO,eAAA;AACZ,IAAA,IAAA,CAAK,IAAA,GAAO,IAAA;AAAA,EACd;AACF;AAGO,IAAM,cAAA,GAAN,cAA6B,iBAAA,CAAkB;AAAA,EACpD,YAAY,OAAA,EAAiB;AAC3B,IAAA,KAAA,CAAM,OAAO,CAAA;AACb,IAAA,IAAA,CAAK,IAAA,GAAO,gBAAA;AAAA,EACd;AACF;AAEA,IAAI,MAAA,GAAS,CAAA;AAGN,SAAS,iBAAA,GAAoC;AAClD,EAAA,OAAO;AAAA,IACL,OAAA,EAAS,KAAA;AAAA,IACT,EAAA,EAAI,MAAA,EAAA;AAAA,IACJ,MAAA,EAAQ,YAAA;AAAA,IACR,MAAA,EAAQ;AAAA,MACN,eAAA,EAAiB,YAAA;AAAA,MACjB,cAAc,EAAC;AAAA,MACf,UAAA,EAAY,EAAE,IAAA,EAAM,kBAAA,EAAoB,SAAS,OAAA;AAAQ;AAC3D,GACF;AACF;AAGO,SAAS,eAAA,CAAgB,MAAc,IAAA,EAA+C;AAC3F,EAAA,OAAO;AAAA,IACL,OAAA,EAAS,KAAA;AAAA,IACT,EAAA,EAAI,MAAA,EAAA;AAAA,IACJ,MAAA,EAAQ,YAAA;AAAA,IACR,MAAA,EAAQ,EAAE,IAAA,EAAM,SAAA,EAAW,IAAA;AAAK,GAClC;AACF;AAOO,SAAS,kBAAkB,IAAA,EAAgC;AAChE,EAAA,IAAI,IAAA,KAAS,IAAA,IAAQ,OAAO,IAAA,KAAS,QAAA,EAAU;AAC7C,IAAA,MAAM,IAAI,eAAe,+CAA+C,CAAA;AAAA,EAC1E;AACA,EAAA,MAAM,CAAA,GAAI,IAAA;AACV,EAAA,IAAI,CAAA,CAAE,YAAY,KAAA,EAAO;AACvB,IAAA,MAAM,IAAI,eAAe,yCAAyC,CAAA;AAAA,EACpE;AACA,EAAA,OAAO,CAAA;AACT;AAGO,SAAS,cAAc,IAAA,EAAuB;AACnD,EAAA,OAAO,IAAA,KAAS,MAAA;AAClB;AAOO,SAAS,WAAW,MAAA,EAA4B;AACrD,EAAA,KAAA,MAAW,KAAA,IAAS,MAAA,CAAO,OAAA,IAAW,EAAC,EAAG;AACxC,IAAA,IAAI,KAAA,CAAM,SAAS,MAAA,IAAU,OAAO,MAAM,IAAA,KAAS,QAAA,SAAiB,KAAA,CAAM,IAAA;AAAA,EAC5E;AACA,EAAA,OAAO,EAAA;AACT;;;AC9HO,IAAM,aAAA,GAA8B,MAAA;AAMpC,SAAS,MAAA,CAAO,OAAqB,KAAA,EAAmC;AAC7E,EAAA,QAAQ,MAAM,IAAA;AAAM,IAClB,KAAK,SAAA;AAKH,MAAA,OAAO,KAAA,KAAU,eAAe,KAAA,GAAQ,YAAA;AAAA,IAE1C,KAAK,iBAAA;AAGH,MAAA,OAAO,KAAA,KAAU,eAAe,WAAA,GAAc,KAAA;AAAA,IAEhD,KAAK,kBAAA;AAEH,MAAA,OAAO,KAAA,KAAU,eAAe,UAAA,GAAa,KAAA;AAAA,IAE/C,KAAK,OAAA;AAIH,MAAA,OAAO,KAAA,KAAU,eAAe,OAAA,GAAU,KAAA;AAAA,IAE5C,KAAK,eAAA;AAGH,MAAA,OAAO,KAAA,KAAU,YAAA,IAAgB,KAAA,KAAU,WAAA,GAAc,SAAA,GAAY,KAAA;AAAA,IAEvE,KAAK,YAAA;AAGH,MAAA,OAAO,KAAA,KAAU,iBAAiB,KAAA,GAAQ,cAAA;AAAA,IAE5C,SAAS;AAGP,MAAA,OAAO,KAAA;AAAA,IACT;AAAA;AAEJ;AAcO,SAAS,YAAY,KAAA,EAA8B;AACxD,EAAA,OAAO,KAAA,KAAU,WAAA;AACnB;;;AC9EO,IAAM,mBAAA,GAAsB;AAG5B,SAAS,aAAA,GAAgC;AAC9C,EAAA,MAAM,GAAA,uBAAU,GAAA,EAAoB;AACpC,EAAA,OAAO;AAAA,IACL,GAAA,EAAK,CAAC,CAAA,KAAO,GAAA,CAAI,GAAA,CAAI,CAAC,CAAA,GAAK,GAAA,CAAI,GAAA,CAAI,CAAC,CAAA,GAAe,IAAA;AAAA,IACnD,GAAA,EAAK,CAAC,CAAA,EAAG,CAAA,KAAM,KAAK,GAAA,CAAI,GAAA,CAAI,GAAG,CAAC,CAAA;AAAA,IAChC,QAAQ,CAAC,CAAA,KAAM,KAAK,GAAA,CAAI,OAAO,CAAC;AAAA,GAClC;AACF;AAGO,SAAS,WAAW,KAAA,EAAgC;AACzD,EAAA,OAAO;AAAA,IACL,GAAA,EAAK,CAAC,CAAA,KAAM;AACV,MAAA,IAAI;AACF,QAAA,OAAO,KAAA,CAAM,QAAQ,CAAC,CAAA;AAAA,MACxB,CAAA,CAAA,MAAQ;AACN,QAAA,OAAO,IAAA;AAAA,MACT;AAAA,IACF,CAAA;AAAA,IACA,GAAA,EAAK,CAAC,CAAA,EAAG,CAAA,KAAM;AACb,MAAA,IAAI;AACF,QAAA,KAAA,CAAM,OAAA,CAAQ,GAAG,CAAC,CAAA;AAAA,MACpB,CAAA,CAAA,MAAQ;AAAA,MAER;AAAA,IACF,CAAA;AAAA,IACA,MAAA,EAAQ,CAAC,CAAA,KAAM;AACb,MAAA,IAAI;AACF,QAAA,KAAA,CAAM,WAAW,CAAC,CAAA;AAAA,MACpB,CAAA,CAAA,MAAQ;AAAA,MAER;AAAA,IACF;AAAA,GACF;AACF;AAUO,SAAS,eAAe,GAAA,EAAwD;AACrF,EAAA,IAAI,QAAQ,IAAA,EAAM;AAChB,IAAA,OAAO,EAAE,GAAA,EAAK,MAAM,IAAA,EAAM,KAAK,MAAM;AAAA,IAAC,CAAA,EAAG,QAAQ,MAAM;AAAA,IAAC,CAAA,EAAE;AAAA,EAC5D;AACA,EAAA,IAAI,KAAK,OAAO,GAAA;AAGhB,EAAA,OAAO,aAAA,EAAc;AACvB;;;AC3DO,IAAM,iBAA4B,OAAO,EAAE,GAAA,EAAK,KAAA,EAAO,MAAK,KAAkC;AACnG,EAAA,MAAM,GAAA,GAAM,MAAM,KAAA,CAAM,GAAA,EAAK;AAAA,IAC3B,MAAA,EAAQ,MAAA;AAAA,IACR,OAAA,EAAS;AAAA,MACP,cAAA,EAAgB,kBAAA;AAAA,MAChB,MAAA,EAAQ,kBAAA;AAAA,MACR,aAAA,EAAe,UAAU,KAAK,CAAA;AAAA,KAChC;AAAA,IACA,IAAA,EAAM,IAAA,CAAK,SAAA,CAAU,IAAI;AAAA,GAC1B,CAAA;AACD,EAAA,IAAI,MAAA,GAAkB,IAAA;AACtB,EAAA,IAAI;AACF,IAAA,MAAA,GAAS,MAAM,IAAI,IAAA,EAAK;AAAA,EAC1B,CAAA,CAAA,MAAQ;AACN,IAAA,MAAA,GAAS,IAAA;AAAA,EACX;AACA,EAAA,OAAO;AAAA,IACL,QAAQ,GAAA,CAAI,MAAA;AAAA,IACZ,IAAA,EAAM,MAAA;AAAA,IACN,eAAA,EAAiB,GAAA,CAAI,OAAA,CAAQ,GAAA,CAAI,kBAAkB;AAAA,GACrD;AACF;;;ACeO,IAAM,gBAAA,GAAmB;AAkCzB,SAAS,YAAA,CAAa,OAAA,GAAyB,EAAC,EAAuB;AAC5E,EAAA,MAAM,QAAA,GAAW,QAAQ,QAAA,IAAY,gBAAA;AACrC,EAAA,MAAM,SAAA,GAAuB,QAAQ,SAAA,IAAa,cAAA;AAClD,EAAA,MAAM,OAAA,GAA0B,cAAA,CAAe,OAAA,CAAQ,OAAO,CAAA;AAC9D,EAAA,MAAM,UAAA,GAAa,QAAQ,UAAA,IAAc,mBAAA;AAEzC,EAAA,MAAM,SAAA,uBAAgB,GAAA,EAAmC;AACzD,EAAA,IAAI,KAAA,GAAsB,aAAA;AAC1B,EAAA,IAAI,KAAA,GAAuB,IAAA;AAI3B,EAAA,MAAM,SAAA,GAAY,OAAA,CAAQ,GAAA,CAAI,UAAU,CAAA;AACxC,EAAA,IAAI,SAAA,EAAW;AACb,IAAA,KAAA,GAAQ,SAAA;AACR,IAAA,KAAA,GAAQ,WAAA;AAAA,EACV;AAEA,EAAA,SAAS,SAAS,IAAA,EAA0B;AAC1C,IAAA,IAAI,SAAS,KAAA,EAAO;AACpB,IAAA,KAAA,GAAQ,IAAA;AACR,IAAA,OAAA,CAAQ,gBAAgB,KAAK,CAAA;AAC7B,IAAA,KAAA,MAAW,CAAA,IAAK,SAAA,EAAW,CAAA,CAAE,KAAK,CAAA;AAAA,EACpC;AAEA,EAAA,SAAS,SAAS,KAAA,EAA2C;AAC3D,IAAA,QAAA,CAAS,MAAA,CAAO,KAAA,EAAO,KAAK,CAAC,CAAA;AAAA,EAC/B;AAGA,EAAA,eAAe,IAAI,IAAA,EAAiC;AAClD,IAAA,IAAI,CAAC,KAAA,EAAO,MAAM,IAAI,iBAAA,EAAkB;AACxC,IAAA,IAAI,GAAA;AACJ,IAAA,IAAI;AACF,MAAA,GAAA,GAAM,MAAM,SAAA,CAAU,EAAE,KAAK,QAAA,EAAU,KAAA,EAAO,MAAM,CAAA;AAAA,IACtD,SAAS,CAAA,EAAG;AACV,MAAA,MAAM,IAAI,cAAA;AAAA,QACR,qBAAqB,CAAA,YAAa,KAAA,GAAQ,EAAE,OAAA,GAAU,MAAA,CAAO,CAAC,CAAC,CAAA;AAAA,OACjE;AAAA,IACF;AAGA,IAAA,IAAI,GAAA,CAAI,WAAW,GAAA,EAAK;AACtB,MAAA,QAAA,CAAS,EAAE,IAAA,EAAM,eAAA,EAAiB,CAAA;AAClC,MAAA,MAAM,IAAI,iBAAA,CAAkB,MAAA,EAAW,GAAA,CAAI,mBAAmB,MAAS,CAAA;AAAA,IACzE;AACA,IAAA,MAAM,MAAA,GAAS,iBAAA,CAAkB,GAAA,CAAI,IAAI,CAAA;AACzC,IAAA,IAAI,OAAO,KAAA,EAAO;AAChB,MAAA,IAAI,aAAA,CAAc,MAAA,CAAO,KAAA,CAAM,IAAI,CAAA,EAAG;AACpC,QAAA,MAAM,IAAI,gBAAA,CAAiB,MAAA,CAAO,KAAA,CAAM,OAAO,CAAA;AAAA,MACjD;AACA,MAAA,MAAM,IAAI,aAAA,CAAc,MAAA,CAAO,MAAM,OAAA,EAAS,MAAA,CAAO,MAAM,IAAI,CAAA;AAAA,IACjE;AACA,IAAA,OAAO,MAAA,CAAO,MAAA;AAAA,EAChB;AAGA,EAAA,eAAe,QAAA,CAAS,MAAc,IAAA,EAAgD;AACpF,IAAA,IAAI,CAAC,WAAA,CAAY,KAAK,CAAA,EAAG,MAAM,IAAI,iBAAA,EAAkB;AACrD,IAAA,MAAM,SAAU,MAAM,GAAA,CAAI,eAAA,CAAgB,IAAA,EAAM,IAAI,CAAC,CAAA;AACrD,IAAA,IAAI,OAAO,OAAA,EAAS;AAClB,MAAA,MAAM,IAAI,aAAA,CAAc,UAAA,CAAW,MAAM,CAAA,IAAK,CAAA,EAAG,IAAI,CAAA,QAAA,CAAU,CAAA;AAAA,IACjE;AACA,IAAA,OAAO,WAAW,MAAM,CAAA;AAAA,EAC1B;AAEA,EAAA,OAAO;AAAA,IACL,IAAI,KAAA,GAAQ;AACV,MAAA,OAAO,KAAA;AAAA,IACT,CAAA;AAAA,IACA,IAAI,SAAA,GAAY;AACd,MAAA,OAAO,KAAA,KAAU,WAAA;AAAA,IACnB,CAAA;AAAA,IACA,IAAI,KAAA,GAAQ;AACV,MAAA,OAAO,KAAA,KAAU,cAAc,KAAA,GAAQ,IAAA;AAAA,IACzC,CAAA;AAAA,IAEA,UAAU,QAAA,EAAU;AAClB,MAAA,SAAA,CAAU,IAAI,QAAQ,CAAA;AACtB,MAAA,OAAO,MAAM,KAAK,SAAA,CAAU,MAAA,CAAO,QAAQ,CAAA;AAAA,IAC7C,CAAA;AAAA,IAEA,MAAM,OAAA,CAAQ,EAAE,KAAA,EAAO,GAAE,EAAuC;AAC9D,MAAA,IAAI,OAAO,CAAA,KAAM,QAAA,IAAY,CAAA,CAAE,WAAW,CAAA,EAAG;AAE3C,QAAA,MAAM,IAAI,2BAAA,EAA4B;AAAA,MACxC;AACA,MAAA,QAAA,CAAS,EAAE,IAAA,EAAM,SAAA,EAAW,CAAA;AAC5B,MAAA,KAAA,GAAQ,CAAA;AACR,MAAA,IAAI;AACF,QAAA,MAAM,GAAA,GAAM,MAAM,SAAA,CAAU,EAAE,GAAA,EAAK,QAAA,EAAU,KAAA,EAAO,CAAA,EAAG,IAAA,EAAM,iBAAA,EAAkB,EAAG,CAAA;AAClF,QAAA,IAAI,GAAA,CAAI,WAAW,GAAA,EAAK;AACtB,UAAA,KAAA,GAAQ,IAAA;AACR,UAAA,QAAA,CAAS,EAAE,IAAA,EAAM,eAAA,EAAiB,CAAA;AAClC,UAAA,MAAM,IAAI,iBAAA,CAAkB,KAAA,CAAA,EAAW,GAAA,CAAI,mBAAmB,KAAA,CAAS,CAAA;AAAA,QACzE;AAEA,QAAA,MAAM,MAAA,GAAS,iBAAA,CAAkB,GAAA,CAAI,IAAI,CAAA;AACzC,QAAA,IAAI,OAAO,KAAA,EAAO;AAChB,UAAA,KAAA,GAAQ,IAAA;AACR,UAAA,QAAA,CAAS,EAAE,IAAA,EAAM,OAAA,EAAS,CAAA;AAC1B,UAAA,MAAM,IAAI,aAAA,CAAc,MAAA,CAAO,MAAM,OAAA,EAAS,MAAA,CAAO,MAAM,IAAI,CAAA;AAAA,QACjE;AACA,QAAA,QAAA,CAAS,EAAE,IAAA,EAAM,iBAAA,EAAmB,CAAA;AACpC,QAAA,IAAI,OAAA,EAAS,OAAA,CAAQ,GAAA,CAAI,UAAA,EAAY,CAAC,CAAA;AACtC,QAAA,OAAO,KAAA;AAAA,MACT,SAAS,CAAA,EAAG;AACV,QAAA,KAAA,GAAQ,IAAA;AAGR,QAAA,IAAI,EAAE,aAAa,iBAAA,CAAA,EAAoB;AACrC,UAAA,QAAA,CAAS,EAAE,IAAA,EAAM,OAAA,EAAS,CAAA;AAC1B,UAAA,IAAI,CAAA,YAAa,cAAA,IAAkB,CAAA,YAAa,aAAA,EAAe,MAAM,CAAA;AACrE,UAAA,MAAM,IAAI,cAAA;AAAA,YACR,mBAAmB,CAAA,YAAa,KAAA,GAAQ,EAAE,OAAA,GAAU,MAAA,CAAO,CAAC,CAAC,CAAA;AAAA,WAC/D;AAAA,QACF;AACA,QAAA,MAAM,CAAA;AAAA,MACR;AAAA,IACF,CAAA;AAAA,IAEA,UAAA,GAAmB;AACjB,MAAA,KAAA,GAAQ,IAAA;AACR,MAAA,OAAA,CAAQ,OAAO,UAAU,CAAA;AACzB,MAAA,QAAA,CAAS,EAAE,IAAA,EAAM,YAAA,EAAc,CAAA;AAAA,IACjC,CAAA;AAAA;AAAA,IAGA,MAAM,OAAA,GAAkC;AACtC,MAAA,MAAM,IAAA,GAAO,MAAM,QAAA,CAAS,SAAA,EAAW,EAAE,CAAA;AAGzC,MAAA,MAAM,KAAA,GAAQ,cAAc,IAAI,CAAA;AAChC,MAAA,IAAI,KAAA,EAAO,OAAO,EAAE,SAAA,EAAW,MAAM,KAAA,EAAM;AAC3C,MAAA,OAAO,EAAE,WAAW,IAAA,EAAK;AAAA,IAC3B,CAAA;AAAA;AAAA,IAGA,MAAM,SAAA,GAAiC;AACrC,MAAA,OAAO,cAAc,MAAM,QAAA,CAAS,YAAA,EAAc,EAAE,CAAC,CAAA;AAAA,IACvD,CAAA;AAAA,IACA,MAAM,YAAY,KAAA,EAAoC;AACpD,MAAA,IAAI,OAAO,KAAA,KAAU,QAAA,EAAU,MAAM,IAAI,4BAA4B,+BAA+B,CAAA;AACpG,MAAA,OAAO,cAAc,MAAM,QAAA,CAAS,gBAAgB,EAAE,KAAA,EAAO,CAAC,CAAA;AAAA,IAChE,CAAA;AAAA;AAAA,IAGA,MAAM,QAAQ,MAAA,EAAwC;AACpD,MAAA,IAAI,OAAO,MAAA,KAAW,QAAA,IAAY,CAAC,MAAA,EAAQ;AACzC,QAAA,MAAM,IAAI,4BAA4B,mCAAmC,CAAA;AAAA,MAC3E;AACA,MAAA,MAAM,OAAO,MAAM,QAAA,CAAS,UAAA,EAAY,EAAE,QAAQ,CAAA;AAClD,MAAA,OAAO,EAAE,IAAA,EAAM,WAAA,EAAa,gBAAA,CAAiB,IAAI,CAAA,EAAE;AAAA,IACrD,CAAA;AAAA;AAAA,IAGA,MAAM,GAAA,CAAI,KAAA,EAAe,IAAA,GAAmB,EAAC,EAAuB;AAClE,MAAA,IAAI,OAAO,KAAA,KAAU,QAAA,IAAY,CAAC,KAAA,EAAO;AACvC,QAAA,MAAM,IAAI,4BAA4B,sCAAsC,CAAA;AAAA,MAC9E;AACA,MAAA,MAAM,IAAA,GAAgC,EAAE,KAAA,EAAM;AAC9C,MAAA,IAAI,OAAO,IAAA,CAAK,CAAA,KAAM,QAAA,EAAU,IAAA,CAAK,IAAI,IAAA,CAAK,CAAA;AAC9C,MAAA,IAAI,OAAO,IAAA,CAAK,SAAA,KAAc,QAAA,EAAU,IAAA,CAAK,YAAY,IAAA,CAAK,SAAA;AAC9D,MAAA,MAAM,IAAA,GAAO,MAAM,QAAA,CAAS,UAAA,EAAY,IAAI,CAAA;AAC5C,MAAA,OAAO,EAAE,QAAA,EAAU,gBAAA,CAAiB,IAAI,GAAG,IAAA,EAAK;AAAA,IAClD,CAAA;AAAA;AAAA,IAGA,MAAM,cAAc,UAAA,EAAkD;AACpE,MAAA,IAAI,OAAO,UAAA,KAAe,QAAA,IAAY,CAAC,UAAA,CAAW,MAAK,EAAG;AACxD,QAAA,MAAM,IAAI,4BAA4B,uCAAuC,CAAA;AAAA,MAC/E;AACA,MAAA,MAAM,OAAO,MAAM,QAAA,CAAS,gBAAA,EAAkB,EAAE,YAAY,CAAA;AAC5D,MAAA,MAAM,CAAA,GAAI,IAAA,CAAK,KAAA,CAAM,mBAAmB,CAAA;AACxC,MAAA,OAAO,EAAE,IAAI,CAAA,GAAI,CAAA,CAAE,CAAC,CAAA,CAAE,IAAA,EAAK,GAAI,MAAA,EAAW,IAAA,EAAK;AAAA,IACjD,CAAA;AAAA;AAAA,IAGA,MAAM,cAAc,IAAA,EAA6C;AAC/D,MAAA,MAAM,OAAgC,EAAC;AACvC,MAAA,IAAI,OAAO,IAAA,KAAS,QAAA,IAAY,IAAA,OAAW,IAAA,GAAO,IAAA;AAClD,MAAA,MAAM,IAAA,GAAO,MAAM,QAAA,CAAS,gBAAA,EAAkB,IAAI,CAAA;AAClD,MAAA,OAAO,IAAA,GAAO,eAAA,CAAgB,IAAI,CAAA,GAAI,gBAAgB,IAAI,CAAA;AAAA,IAC5D;AAAA,GACF;AACF;AAGO,IAAM,2BAAA,GAAN,cAA0C,iBAAA,CAAkB;AAAA,EACjE,WAAA,CAAY,UAAU,8CAAA,EAAgD;AACpE,IAAA,KAAA,CAAM,OAAO,CAAA;AACb,IAAA,IAAA,CAAK,IAAA,GAAO,6BAAA;AAAA,EACd;AACF;AAKA,SAAS,cAAc,IAAA,EAAoC;AACzD,EAAA,MAAM,OAAA,GAAU,KAAK,SAAA,EAAU;AAC/B,EAAA,IAAI,CAAC,OAAA,CAAQ,UAAA,CAAW,GAAG,GAAG,OAAO,MAAA;AACrC,EAAA,IAAI;AACF,IAAA,MAAM,GAAA,GAAM,IAAA,CAAK,KAAA,CAAM,IAAI,CAAA;AAC3B,IAAA,IAAI,KAAA,CAAM,OAAA,CAAQ,GAAA,CAAI,KAAK,CAAA,EAAG,OAAO,GAAA,CAAI,KAAA,CAAM,MAAA,CAAO,CAAC,CAAA,KAAmB,OAAO,MAAM,QAAQ,CAAA;AAAA,EACjG,CAAA,CAAA,MAAQ;AAAA,EAER;AACA,EAAA,OAAO,MAAA;AACT;AAGA,SAAS,cAAc,IAAA,EAA0B;AAC/C,EAAA,IAAI;AACF,IAAA,MAAM,GAAA,GAAM,IAAA,CAAK,KAAA,CAAM,IAAI,CAAA;AAC3B,IAAA,IAAI,CAAC,KAAA,CAAM,OAAA,CAAQ,GAAG,CAAA,SAAU,EAAC;AACjC,IAAA,OAAO,GAAA,CAAI,GAAA,CAAI,CAAC,CAAA,KAAM;AACpB,MAAA,MAAM,CAAA,GAAK,KAAK,EAAC;AACjB,MAAA,OAAO;AAAA,QACL,EAAA,EAAI,MAAA,CAAO,CAAA,CAAE,EAAA,IAAM,EAAE,CAAA;AAAA,QACrB,IAAA,EAAM,MAAA,CAAO,CAAA,CAAE,IAAA,IAAQ,EAAE,CAAA;AAAA,QACzB,MAAM,OAAO,CAAA,CAAE,IAAA,KAAS,QAAA,GAAW,EAAE,IAAA,GAAO,CAAA;AAAA,QAC5C,WAAA,EAAa,MAAA,CAAO,CAAA,CAAE,WAAA,IAAe,EAAE,CAAA;AAAA,QACvC,QAAA,EAAU,MAAA,CAAO,CAAA,CAAE,QAAA,IAAY,EAAE,CAAA;AAAA,QACjC,GAAI,OAAO,CAAA,CAAE,MAAA,KAAW,QAAA,GAAW,EAAE,MAAA,EAAQ,CAAA,CAAE,MAAA,EAA6B,GAAI;AAAC,OACnF;AAAA,IACF,CAAC,CAAA;AAAA,EACH,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,EAAC;AAAA,EACV;AACF;AAGA,SAAS,iBAAiB,IAAA,EAAkC;AAC1D,EAAA,MAAM,CAAA,GAAI,IAAA,CAAK,KAAA,CAAM,6BAA6B,CAAA;AAClD,EAAA,OAAO,CAAA,GAAI,CAAA,CAAE,CAAC,CAAA,GAAI,MAAA;AACpB;AAOA,SAAS,iBAAiB,IAAA,EAA4B;AACpD,EAAA,IAAI,yBAAyB,IAAA,CAAK,IAAA,CAAK,WAAW,CAAA,SAAU,EAAC;AAC7D,EAAA,MAAM,MAAA,GAAS,IAAA,CAAK,KAAA,CAAM,MAAM,CAAA;AAChC,EAAA,MAAM,MAAoB,EAAC;AAC3B,EAAA,KAAA,MAAW,SAAS,MAAA,EAAQ;AAC1B,IAAA,MAAM,EAAA,GAAK,KAAA,CAAM,OAAA,CAAQ,IAAI,CAAA;AAC7B,IAAA,MAAM,WAAW,EAAA,KAAO,EAAA,GAAK,QAAQ,KAAA,CAAM,KAAA,CAAM,GAAG,EAAE,CAAA;AACtD,IAAA,MAAM,OAAO,EAAA,KAAO,EAAA,GAAK,KAAK,KAAA,CAAM,KAAA,CAAM,KAAK,CAAC,CAAA;AAChD,IAAA,MAAM,CAAA,GAAI,QAAA,CAAS,KAAA,CAAM,oBAAoB,CAAA;AAC7C,IAAA,IAAI,CAAC,CAAA,EAAG;AACR,IAAA,MAAM,KAAA,GAAQ,MAAA,CAAO,CAAA,CAAE,CAAC,CAAC,CAAA;AACzB,IAAA,MAAM,IAAA,GAAO,EAAE,CAAC,CAAA;AAEhB,IAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,KAAA,CAAM,QAAK,CAAA;AAC9B,IAAA,MAAM,OAAA,GAAsB,EAAE,KAAA,EAAO,IAAA,EAAM,IAAA,EAAK;AAChD,IAAA,IAAI,KAAA,CAAM,CAAC,CAAA,EAAG,OAAA,CAAQ,OAAO,KAAA,CAAM,CAAC,EAAE,IAAA,EAAK;AAC3C,IAAA,IAAI,KAAA,CAAM,CAAC,CAAA,EAAG,OAAA,CAAQ,QAAQ,KAAA,CAAM,CAAC,EAAE,IAAA,EAAK;AAC5C,IAAA,MAAM,MAAA,GAAS,IAAA,CAAK,KAAA,CAAM,kBAAkB,CAAA;AAC5C,IAAA,IAAI,QAAQ,OAAA,CAAQ,KAAA,GAAQ,MAAA,CAAO,MAAA,CAAO,CAAC,CAAC,CAAA;AAC5C,IAAA,GAAA,CAAI,KAAK,OAAO,CAAA;AAAA,EAClB;AACA,EAAA,OAAO,GAAA;AACT;AAGA,SAAS,gBAAgB,IAAA,EAAmC;AAC1D,EAAA,IAAI,qBAAA,CAAsB,IAAA,CAAK,IAAA,CAAK,SAAA,EAAW,CAAA,EAAG;AAChD,IAAA,OAAO,EAAE,MAAM,MAAA,EAAQ,MAAA,EAAQ,EAAC,EAAG,SAAA,EAAW,MAAM,IAAA,EAAK;AAAA,EAC3D;AACA,EAAA,MAAM,SAA+B,EAAC;AACtC,EAAA,KAAA,MAAW,IAAA,IAAQ,IAAA,CAAK,KAAA,CAAM,IAAI,CAAA,EAAG;AACnC,IAAA,MAAM,CAAA,GAAI,IAAA,CAAK,KAAA,CAAM,sCAAsC,CAAA;AAC3D,IAAA,IAAI,GAAG,MAAA,CAAO,IAAA,CAAK,EAAE,UAAA,EAAY,EAAE,CAAC,CAAA,CAAE,IAAA,EAAK,EAAG,SAAS,CAAA,CAAE,CAAC,CAAA,CAAE,IAAA,IAAQ,CAAA;AAAA,EACtE;AACA,EAAA,OAAO,EAAE,IAAA,EAAM,MAAA,EAAQ,MAAA,EAAQ,SAAA,EAAW,MAAM,IAAA,EAAK;AACvD;AAGA,SAAS,gBAAgB,IAAA,EAAmC;AAC1D,EAAA,IAAI,gBAAA,CAAiB,IAAA,CAAK,IAAI,CAAA,EAAG;AAC/B,IAAA,OAAO,EAAE,MAAM,MAAA,EAAQ,MAAA,EAAQ,EAAC,EAAG,SAAA,EAAW,MAAM,IAAA,EAAK;AAAA,EAC3D;AACA,EAAA,MAAM,CAAA,GAAI,IAAA,CAAK,KAAA,CAAM,2CAA2C,CAAA;AAChE,EAAA,MAAM,SAAA,GAAY,CAAA,GAAI,CAAA,CAAE,CAAC,CAAA,GAAI,IAAA;AAC7B,EAAA,OAAO,EAAE,IAAA,EAAM,MAAA,EAAQ,QAAQ,EAAC,EAAG,WAAW,IAAA,EAAK;AACrD","file":"index.cjs","sourcesContent":["// JSON-RPC 2.0 framing for the membrane MCP wire, plus the SDK error taxonomy.\n//\n// The membrane speaks hand-rolled JSON-RPC over Streamable HTTP. The SDK only\n// ever sends `initialize` and `tools/call`. A tools/call comes back as a RESULT\n// shaped `{ content: [{ type:\"text\", text }], isError }`; a protocol-level\n// failure comes back as a JSON-RPC `error` object. This module owns the framing\n// + the parsing helpers; the wrappers in client.ts decode the text content.\n\n/** A JSON-RPC request envelope. */\nexport interface JsonRpcRequest {\n jsonrpc: \"2.0\";\n id: number;\n method: string;\n params?: unknown;\n}\n\n/** A JSON-RPC error object. */\nexport interface JsonRpcErrorObject {\n code: number;\n message: string;\n data?: unknown;\n}\n\n/** A parsed JSON-RPC response (success xor error). */\nexport interface JsonRpcResponse {\n jsonrpc: \"2.0\";\n id: number | null;\n result?: unknown;\n error?: JsonRpcErrorObject;\n}\n\n/** The MCP tools/call result shape (`content` blocks + an error flag). */\nexport interface ToolResult {\n content: Array<{ type: string; text?: string }>;\n isError?: boolean;\n}\n\n/** Base class for every error the SDK throws, so callers can `catch (e)`. */\nexport class UseMyContextError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"UseMyContextError\";\n // Restore the prototype chain (TS target < ES2015 / transpiled extends).\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\n/** Thrown when a tool wrapper is called before a successful `connect()`. */\nexport class NotConnectedError extends UseMyContextError {\n constructor(message = \"Not connected. Call connect({ token }) first.\") {\n super(message);\n this.name = \"NotConnectedError\";\n }\n}\n\n/**\n * Thrown when the membrane rejects the token (HTTP 401 + WWW-Authenticate).\n * The client also transitions to `expired` so the host can re-connect.\n */\nexport class TokenExpiredError extends UseMyContextError {\n /** The raw `WWW-Authenticate` header, when the server sent one. */\n readonly wwwAuthenticate?: string;\n constructor(message = \"The connection token was rejected (expired or revoked).\", wwwAuthenticate?: string) {\n super(message);\n this.name = \"TokenExpiredError\";\n this.wwwAuthenticate = wwwAuthenticate;\n }\n}\n\n/** Thrown when a tool call is refused for lack of scope (membrane -32604). */\nexport class ScopeDeniedError extends UseMyContextError {\n readonly code = -32604;\n constructor(message: string) {\n super(message);\n this.name = \"ScopeDeniedError\";\n }\n}\n\n/** Thrown for a JSON-RPC protocol error or a tool-level `isError` result. */\nexport class ToolCallError extends UseMyContextError {\n /** The JSON-RPC error code, when the failure was a protocol error. */\n readonly code?: number;\n constructor(message: string, code?: number) {\n super(message);\n this.name = \"ToolCallError\";\n this.code = code;\n }\n}\n\n/** Thrown for transport/parse failures (network down, non-JSON body, ...). */\nexport class TransportError extends UseMyContextError {\n constructor(message: string) {\n super(message);\n this.name = \"TransportError\";\n }\n}\n\nlet nextId = 1;\n\n/** Build an `initialize` request (the connect handshake). */\nexport function initializeRequest(): JsonRpcRequest {\n return {\n jsonrpc: \"2.0\",\n id: nextId++,\n method: \"initialize\",\n params: {\n protocolVersion: \"2025-06-18\",\n capabilities: {},\n clientInfo: { name: \"usemycontext-sdk\", version: \"0.1.0\" },\n },\n };\n}\n\n/** Build a `tools/call` request for a tool name + arguments. */\nexport function toolCallRequest(name: string, args: Record<string, unknown>): JsonRpcRequest {\n return {\n jsonrpc: \"2.0\",\n id: nextId++,\n method: \"tools/call\",\n params: { name, arguments: args },\n };\n}\n\n/**\n * Narrow an unknown body to a JSON-RPC response. Throws TransportError when the\n * body is not a well-formed JSON-RPC 2.0 envelope (a defensive guard against a\n * misbehaving transport or an HTML error page).\n */\nexport function asJsonRpcResponse(body: unknown): JsonRpcResponse {\n if (body === null || typeof body !== \"object\") {\n throw new TransportError(\"Membrane returned a non-object response body.\");\n }\n const b = body as Record<string, unknown>;\n if (b.jsonrpc !== \"2.0\") {\n throw new TransportError(\"Membrane response was not JSON-RPC 2.0.\");\n }\n return b as unknown as JsonRpcResponse;\n}\n\n/** True iff a JSON-RPC error code denotes a missing-scope denial (-32604). */\nexport function isScopeDenied(code: number): boolean {\n return code === -32604;\n}\n\n/**\n * Pull the single text block out of a tools/call RESULT. The membrane always\n * renders to ONE text content block, so this returns its `text` (or \"\" when a\n * result carried no text block).\n */\nexport function resultText(result: ToolResult): string {\n for (const block of result.content ?? []) {\n if (block.type === \"text\" && typeof block.text === \"string\") return block.text;\n }\n return \"\";\n}\n","// The connect state machine - a PURE reducer (no IO, no timers, no `this`).\n//\n// States (ConnectState):\n// idle -> connecting -> connected\n// \\-> declined (user/host refused; v2 OAuth path)\n// \\-> error (network/transport/parse failure)\n// connected -> expired (membrane 401 mid-session)\n// connected -> disconnected (explicit disconnect)\n// <any> -> disconnected (disconnect is always reachable)\n// <terminal>-> connecting (a fresh connect() retries)\n//\n// The reducer is the single source of truth for legality: an event that does\n// not apply to the current state is a NO-OP (returns the same state), so the\n// client can fire events without guarding, and tests can assert every legal AND\n// illegal transition deterministically.\n\nimport type { ConnectState } from \"./types.js\";\n\n/** The events that drive the machine. */\nexport type ConnectEvent =\n | { type: \"CONNECT\" } // begin a connect attempt\n | { type: \"CONNECT_SUCCESS\" } // membrane accepted the token\n | { type: \"CONNECT_DECLINED\" } // user/host refused (v2 OAuth path)\n | { type: \"TOKEN_EXPIRED\" } // membrane 401 (expired/revoked)\n | { type: \"ERROR\" } // a non-auth failure\n | { type: \"DISCONNECT\" }; // explicit disconnect / token cleared\n\n/** The initial state of a fresh client. */\nexport const INITIAL_STATE: ConnectState = \"idle\";\n\n/**\n * The pure transition function. Returns the NEXT state for `(state, event)`, or\n * the SAME state when the event is illegal in that state (a no-op).\n */\nexport function reduce(state: ConnectState, event: ConnectEvent): ConnectState {\n switch (event.type) {\n case \"CONNECT\":\n // A connect attempt is legal from any NON-in-flight state: a fresh client,\n // a terminal/failed state (retry), or an already-connected client\n // (re-connect with a new token). It is a no-op only while already\n // connecting (a second concurrent connect does nothing).\n return state === \"connecting\" ? state : \"connecting\";\n\n case \"CONNECT_SUCCESS\":\n // Only a connect IN FLIGHT can succeed. Any other state ignores it (a\n // stale/duplicate success after disconnect must not resurrect the client).\n return state === \"connecting\" ? \"connected\" : state;\n\n case \"CONNECT_DECLINED\":\n // Only a connect in flight can be declined.\n return state === \"connecting\" ? \"declined\" : state;\n\n case \"ERROR\":\n // A connect in flight can fail with a non-auth error. (A wrapper-call\n // failure while `connected` does NOT change the connect state - the\n // connection is still valid - so ERROR is a no-op when connected.)\n return state === \"connecting\" ? \"error\" : state;\n\n case \"TOKEN_EXPIRED\":\n // The membrane rejected the token. Legal from `connecting` (the token was\n // bad at connect time) or `connected` (it expired/was revoked mid-session).\n return state === \"connecting\" || state === \"connected\" ? \"expired\" : state;\n\n case \"DISCONNECT\":\n // Disconnect is ALWAYS reachable and idempotent: it moves any state to\n // `disconnected` (a no-op only when already there).\n return state === \"disconnected\" ? state : \"disconnected\";\n\n default: {\n // Exhaustiveness: a new event type must be handled above.\n const _never: never = event;\n return state;\n }\n }\n}\n\n/** Every state the machine can occupy (for reachability assertions). */\nexport const ALL_STATES: readonly ConnectState[] = [\n \"idle\",\n \"connecting\",\n \"connected\",\n \"declined\",\n \"expired\",\n \"error\",\n \"disconnected\",\n] as const;\n\n/** Whether the 7 tool wrappers may be called in this state. */\nexport function isConnected(state: ConnectState): boolean {\n return state === \"connected\";\n}\n","// Token persistence. SAFE BY DEFAULT: persistence is in-memory only, so the\n// token NEVER touches `localStorage` unless the host page opts in explicitly\n// (pass `storage: webStorage(localStorage)`). The v1 token-in credential is the\n// user's long-lived session JWT - writing it to `localStorage` would expose a\n// ~decade-long key to any script on the host page (one XSS = full context\n// theft), which the threat model forbids. So the default is memory; opt IN to\n// cross-reload persistence knowingly, never opt out. Pass `storage: null` to\n// disable persistence entirely (a no-op store).\n\nimport type { StorageAdapter } from \"./types.js\";\n\n/** The default storage key the token is persisted under. */\nexport const DEFAULT_STORAGE_KEY = \"usemycontext.token\";\n\n/** An in-memory storage adapter (SSR-safe; the DEFAULT - token never leaves JS memory). */\nexport function memoryStorage(): StorageAdapter {\n const map = new Map<string, string>();\n return {\n get: (k) => (map.has(k) ? (map.get(k) as string) : null),\n set: (k, v) => void map.set(k, v),\n remove: (k) => void map.delete(k),\n };\n}\n\n/** Wrap a Web Storage (localStorage/sessionStorage) as a StorageAdapter. */\nexport function webStorage(store: Storage): StorageAdapter {\n return {\n get: (k) => {\n try {\n return store.getItem(k);\n } catch {\n return null;\n }\n },\n set: (k, v) => {\n try {\n store.setItem(k, v);\n } catch {\n /* quota / privacy mode - degrade to no-persist, never throw */\n }\n },\n remove: (k) => {\n try {\n store.removeItem(k);\n } catch {\n /* ignore */\n }\n },\n };\n}\n\n/**\n * Resolve the storage adapter to use given the option:\n * - an explicit adapter -> use it (e.g. `webStorage(localStorage)` to opt IN\n * to cross-reload persistence, knowingly accepting host-page token exposure);\n * - `null` -> persistence disabled (a no-op adapter);\n * - `undefined` (the DEFAULT) -> in-memory. The token NEVER touches\n * `localStorage` unless the caller asks for it. Safe by default.\n */\nexport function resolveStorage(opt: StorageAdapter | null | undefined): StorageAdapter {\n if (opt === null) {\n return { get: () => null, set: () => {}, remove: () => {} };\n }\n if (opt) return opt;\n // DEFAULT: in-memory only. We deliberately do NOT auto-select localStorage -\n // persisting the long-lived session JWT to the host page is an opt-in choice.\n return memoryStorage();\n}\n","// The default `fetch`-based transport. Tests inject a mock transport instead, so\n// this module is never exercised by the (zero-network) test suite - it is the\n// production wiring that POSTs one JSON-RPC request to the membrane `/mcp`\n// endpoint with the user's bearer token.\n\nimport type { Transport, TransportResponse } from \"./types.js\";\n\n/** A `fetch`-backed Transport (the default when none is supplied). */\nexport const fetchTransport: Transport = async ({ url, token, body }): Promise<TransportResponse> => {\n const res = await fetch(url, {\n method: \"POST\",\n headers: {\n \"content-type\": \"application/json\",\n accept: \"application/json\",\n authorization: `Bearer ${token}`,\n },\n body: JSON.stringify(body),\n });\n let parsed: unknown = null;\n try {\n parsed = await res.json();\n } catch {\n parsed = null; // non-JSON / empty body (e.g. a 401 with no body)\n }\n return {\n status: res.status,\n body: parsed,\n wwwAuthenticate: res.headers.get(\"www-authenticate\"),\n };\n};\n","// The core client: `useMyContext()` (a framework-free factory) + the 7 tool\n// wrappers. It holds the user's OWN token and calls the membrane exactly like\n// Claude does - same trust model, new client shape. The service stays\n// structurally blind.\n//\n// v1 IS TOKEN-IN ONLY: `connect({ token })`. The full browser-OAuth-in-the-SDK\n// flow (a hosted popup on connect.usemycontext.ai) is v2, gated on the Phase 2\n// CORS landing - deliberately NOT built here.\n\nimport {\n initializeRequest,\n toolCallRequest,\n asJsonRpcResponse,\n resultText,\n isScopeDenied,\n NotConnectedError,\n TokenExpiredError,\n ScopeDeniedError,\n ToolCallError,\n TransportError,\n UseMyContextError,\n type ToolResult,\n} from \"./jsonrpc.js\";\nimport { reduce, INITIAL_STATE, isConnected } from \"./machine.js\";\nimport { resolveStorage, DEFAULT_STORAGE_KEY } from \"./storage.js\";\nimport { fetchTransport } from \"./transport.js\";\nimport type {\n ClientOptions,\n ConnectArgs,\n ConnectState,\n FileMeta,\n ProfileResult,\n AskOptions,\n AskResult,\n AskPassage,\n GetFileResult,\n SuggestUpdateResult,\n SharedContextResult,\n SharedContextEntry,\n StorageAdapter,\n Transport,\n} from \"./types.js\";\n\n/** The production membrane MCP endpoint. */\nexport const DEFAULT_ENDPOINT = \"https://mcp.usemycontext.ai/mcp\";\n\n/** The shape `useMyContext()` returns - the client handle. */\nexport interface UseMyContextClient {\n /** The current connect state. */\n readonly state: ConnectState;\n /** Convenience: true iff `state === \"connected\"`. */\n readonly connected: boolean;\n /** The held token, when connected (else null). */\n readonly token: string | null;\n\n /** Subscribe to state changes. Returns an unsubscribe fn. */\n subscribe(listener: (state: ConnectState) => void): () => void;\n\n /** v1 TOKEN-IN connect: validate the token against the membrane. */\n connect(args: ConnectArgs): Promise<ConnectState>;\n /** Clear the token + persisted storage; -> `disconnected`. */\n disconnect(): void;\n\n // --- the 7 MCP tool wrappers ---\n profile(): Promise<ProfileResult>;\n listFiles(): Promise<FileMeta[]>;\n searchFiles(query: string): Promise<FileMeta[]>;\n getFile(fileId: string): Promise<GetFileResult>;\n ask(query: string, opts?: AskOptions): Promise<AskResult>;\n suggestUpdate(suggestion: string): Promise<SuggestUpdateResult>;\n sharedContext(from?: string): Promise<SharedContextResult>;\n}\n\n/**\n * Create a UseMyContext client. Framework-free: the React hook wraps this.\n * Restores a persisted token (without revalidating) so a returning host page\n * starts `connected`; a stale token surfaces as `expired` on the first call.\n */\nexport function useMyContext(options: ClientOptions = {}): UseMyContextClient {\n const endpoint = options.endpoint ?? DEFAULT_ENDPOINT;\n const transport: Transport = options.transport ?? fetchTransport;\n const storage: StorageAdapter = resolveStorage(options.storage);\n const storageKey = options.storageKey ?? DEFAULT_STORAGE_KEY;\n\n const listeners = new Set<(state: ConnectState) => void>();\n let state: ConnectState = INITIAL_STATE;\n let token: string | null = null;\n\n // Restore a persisted token: a returning page is `connected` optimistically\n // (the membrane is the authority - a stale token -> `expired` on first call).\n const persisted = storage.get(storageKey);\n if (persisted) {\n token = persisted;\n state = \"connected\";\n }\n\n function setState(next: ConnectState): void {\n if (next === state) return;\n state = next;\n options.onStateChange?.(state);\n for (const l of listeners) l(state);\n }\n\n function dispatch(event: Parameters<typeof reduce>[1]): void {\n setState(reduce(state, event));\n }\n\n /** One JSON-RPC round-trip against the membrane with the held token. */\n async function rpc(body: unknown): Promise<unknown> {\n if (!token) throw new NotConnectedError();\n let res;\n try {\n res = await transport({ url: endpoint, token, body });\n } catch (e) {\n throw new TransportError(\n `Transport failed: ${e instanceof Error ? e.message : String(e)}`,\n );\n }\n // A 401 means the token is bad/expired/revoked. Drive the machine to\n // `expired` and throw - the host should re-connect.\n if (res.status === 401) {\n dispatch({ type: \"TOKEN_EXPIRED\" });\n throw new TokenExpiredError(undefined, res.wwwAuthenticate ?? undefined);\n }\n const parsed = asJsonRpcResponse(res.body);\n if (parsed.error) {\n if (isScopeDenied(parsed.error.code)) {\n throw new ScopeDeniedError(parsed.error.message);\n }\n throw new ToolCallError(parsed.error.message, parsed.error.code);\n }\n return parsed.result;\n }\n\n /** A tools/call that returns the single rendered text block. */\n async function callTool(name: string, args: Record<string, unknown>): Promise<string> {\n if (!isConnected(state)) throw new NotConnectedError();\n const result = (await rpc(toolCallRequest(name, args))) as ToolResult;\n if (result.isError) {\n throw new ToolCallError(resultText(result) || `${name} failed.`);\n }\n return resultText(result);\n }\n\n return {\n get state() {\n return state;\n },\n get connected() {\n return state === \"connected\";\n },\n get token() {\n return state === \"connected\" ? token : null;\n },\n\n subscribe(listener) {\n listeners.add(listener);\n return () => void listeners.delete(listener);\n },\n\n async connect({ token: t }: ConnectArgs): Promise<ConnectState> {\n if (typeof t !== \"string\" || t.length === 0) {\n // A bad arg is a developer error, not a state transition.\n throw new UseMyContextConnectArgError();\n }\n dispatch({ type: \"CONNECT\" });\n token = t;\n try {\n const res = await transport({ url: endpoint, token: t, body: initializeRequest() });\n if (res.status === 401) {\n token = null;\n dispatch({ type: \"TOKEN_EXPIRED\" });\n throw new TokenExpiredError(undefined, res.wwwAuthenticate ?? undefined);\n }\n // Validate the handshake came back as a well-formed JSON-RPC result.\n const parsed = asJsonRpcResponse(res.body);\n if (parsed.error) {\n token = null;\n dispatch({ type: \"ERROR\" });\n throw new ToolCallError(parsed.error.message, parsed.error.code);\n }\n dispatch({ type: \"CONNECT_SUCCESS\" });\n if (storage) storage.set(storageKey, t);\n return state;\n } catch (e) {\n token = null;\n // TokenExpiredError already drove the machine to `expired`; any other\n // failure is a non-auth `error`.\n if (!(e instanceof TokenExpiredError)) {\n dispatch({ type: \"ERROR\" });\n if (e instanceof TransportError || e instanceof ToolCallError) throw e;\n throw new TransportError(\n `Connect failed: ${e instanceof Error ? e.message : String(e)}`,\n );\n }\n throw e;\n }\n },\n\n disconnect(): void {\n token = null;\n storage.remove(storageKey);\n dispatch({ type: \"DISCONNECT\" });\n },\n\n // --- profile ---------------------------------------------------------\n async profile(): Promise<ProfileResult> {\n const text = await callTool(\"profile\", {});\n // The membrane serves the compiled composite as plain text, OR (no compile\n // yet) the JSON of `{ facts: [...] }`. Detect the fallback by parsing.\n const facts = tryParseFacts(text);\n if (facts) return { composite: text, facts };\n return { composite: text };\n },\n\n // --- list_files / search_files (JSON array of FileMeta) --------------\n async listFiles(): Promise<FileMeta[]> {\n return parseFileList(await callTool(\"list_files\", {}));\n },\n async searchFiles(query: string): Promise<FileMeta[]> {\n if (typeof query !== \"string\") throw new UseMyContextConnectArgError(\"search query must be a string\");\n return parseFileList(await callTool(\"search_files\", { query }));\n },\n\n // --- get_file --------------------------------------------------------\n async getFile(fileId: string): Promise<GetFileResult> {\n if (typeof fileId !== \"string\" || !fileId) {\n throw new UseMyContextConnectArgError(\"fileId must be a non-empty string\");\n }\n const text = await callTool(\"get_file\", { fileId });\n return { text, downloadUrl: parseDownloadUrl(text) };\n },\n\n // --- ask_docs --------------------------------------------------------\n async ask(query: string, opts: AskOptions = {}): Promise<AskResult> {\n if (typeof query !== \"string\" || !query) {\n throw new UseMyContextConnectArgError(\"ask query must be a non-empty string\");\n }\n const args: Record<string, unknown> = { query };\n if (typeof opts.k === \"number\") args.k = opts.k;\n if (typeof opts.projectId === \"string\") args.projectId = opts.projectId;\n const text = await callTool(\"ask_docs\", args);\n return { passages: parseAskPassages(text), text };\n },\n\n // --- suggest_update (the one write) ----------------------------------\n async suggestUpdate(suggestion: string): Promise<SuggestUpdateResult> {\n if (typeof suggestion !== \"string\" || !suggestion.trim()) {\n throw new UseMyContextConnectArgError(\"suggestion must be a non-empty string\");\n }\n const text = await callTool(\"suggest_update\", { suggestion });\n const m = text.match(/\\(id:\\s*([^)]+)\\)/);\n return { id: m ? m[1].trim() : undefined, text };\n },\n\n // --- shared_context --------------------------------------------------\n async sharedContext(from?: string): Promise<SharedContextResult> {\n const args: Record<string, unknown> = {};\n if (typeof from === \"string\" && from) args.from = from;\n const text = await callTool(\"shared_context\", args);\n return from ? parseSharedRead(text) : parseSharedList(text);\n },\n };\n}\n\n/** Thrown for a bad SDK call argument (a developer error, not a state event). */\nexport class UseMyContextConnectArgError extends UseMyContextError {\n constructor(message = \"connect() requires a non-empty token string.\") {\n super(message);\n this.name = \"UseMyContextConnectArgError\";\n }\n}\n\n// --- parsers (decode the membrane's RENDERED text back to typed shapes) ---\n\n/** Parse `profile`'s JSON fallback (`{facts:[...]}`); null when it's prose. */\nfunction tryParseFacts(text: string): string[] | undefined {\n const trimmed = text.trimStart();\n if (!trimmed.startsWith(\"{\")) return undefined;\n try {\n const obj = JSON.parse(text) as { facts?: unknown };\n if (Array.isArray(obj.facts)) return obj.facts.filter((f): f is string => typeof f === \"string\");\n } catch {\n /* prose composite that happens to start with \"{\" - treat as composite */\n }\n return undefined;\n}\n\n/** Parse a list/search JSON array into FileMeta[]. */\nfunction parseFileList(text: string): FileMeta[] {\n try {\n const arr = JSON.parse(text) as unknown;\n if (!Array.isArray(arr)) return [];\n return arr.map((r) => {\n const o = (r ?? {}) as Record<string, unknown>;\n return {\n id: String(o.id ?? \"\"),\n name: String(o.name ?? \"\"),\n size: typeof o.size === \"number\" ? o.size : 0,\n contentType: String(o.contentType ?? \"\"),\n modified: String(o.modified ?? \"\"),\n ...(typeof o.status === \"string\" ? { status: o.status as FileMeta[\"status\"] } : {}),\n };\n });\n } catch {\n return [];\n }\n}\n\n/** Pull a `Download link ... : <url>` out of a get_file render. */\nfunction parseDownloadUrl(text: string): string | undefined {\n const m = text.match(/Download link[^:]*:\\s*(\\S+)/);\n return m ? m[1] : undefined;\n}\n\n/**\n * Parse `renderAskDocs` output: blocks separated by a blank line, each a\n * `[n] file · scope · score X.XXX` citation line then the passage text. An empty\n * result is the calm \"No relevant passages...\" sentence -> zero passages.\n */\nfunction parseAskPassages(text: string): AskPassage[] {\n if (/^No relevant passages/i.test(text.trimStart())) return [];\n const blocks = text.split(\"\\n\\n\");\n const out: AskPassage[] = [];\n for (const block of blocks) {\n const nl = block.indexOf(\"\\n\");\n const citation = nl === -1 ? block : block.slice(0, nl);\n const body = nl === -1 ? \"\" : block.slice(nl + 1);\n const m = citation.match(/^\\[(\\d+)\\]\\s*(.*)$/);\n if (!m) continue;\n const index = Number(m[1]);\n const rest = m[2];\n // rest = `file · scope · score N.NNN`\n const parts = rest.split(\" · \");\n const passage: AskPassage = { index, text: body };\n if (parts[0]) passage.file = parts[0].trim();\n if (parts[1]) passage.scope = parts[1].trim();\n const scoreM = rest.match(/score\\s+([\\d.]+)/);\n if (scoreM) passage.score = Number(scoreM[1]);\n out.push(passage);\n }\n return out;\n}\n\n/** Parse `renderSharedContext` LIST output (lines `- who (from: grantId)`). */\nfunction parseSharedList(text: string): SharedContextResult {\n if (/^No one has shared/i.test(text.trimStart())) {\n return { mode: \"list\", shares: [], composite: null, text };\n }\n const shares: SharedContextEntry[] = [];\n for (const line of text.split(\"\\n\")) {\n const m = line.match(/^-\\s*(.*?)\\s*\\(from:\\s*([^)]+)\\)\\s*$/);\n if (m) shares.push({ ownerLabel: m[1].trim(), grantId: m[2].trim() });\n }\n return { mode: \"list\", shares, composite: null, text };\n}\n\n/** Parse `renderSharedContext` READ output (`Shared context from X:\\n\\n<text>`). */\nfunction parseSharedRead(text: string): SharedContextResult {\n if (/not available/i.test(text)) {\n return { mode: \"read\", shares: [], composite: null, text };\n }\n const m = text.match(/^Shared context from [^:]*:\\n\\n([\\s\\S]*)$/);\n const composite = m ? m[1] : text;\n return { mode: \"read\", shares: [], composite, text };\n}\n"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -3,7 +3,7 @@ export { A as AskOptions, a as AskPassage, b as AskResult, C as ClientOptions, c
|
|
|
3
3
|
|
|
4
4
|
/** The default storage key the token is persisted under. */
|
|
5
5
|
declare const DEFAULT_STORAGE_KEY = "usemycontext.token";
|
|
6
|
-
/** An in-memory storage adapter (SSR-safe; the
|
|
6
|
+
/** An in-memory storage adapter (SSR-safe; the DEFAULT - token never leaves JS memory). */
|
|
7
7
|
declare function memoryStorage(): StorageAdapter;
|
|
8
8
|
/** Wrap a Web Storage (localStorage/sessionStorage) as a StorageAdapter. */
|
|
9
9
|
declare function webStorage(store: Storage): StorageAdapter;
|
package/dist/index.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ export { A as AskOptions, a as AskPassage, b as AskResult, C as ClientOptions, c
|
|
|
3
3
|
|
|
4
4
|
/** The default storage key the token is persisted under. */
|
|
5
5
|
declare const DEFAULT_STORAGE_KEY = "usemycontext.token";
|
|
6
|
-
/** An in-memory storage adapter (SSR-safe; the
|
|
6
|
+
/** An in-memory storage adapter (SSR-safe; the DEFAULT - token never leaves JS memory). */
|
|
7
7
|
declare function memoryStorage(): StorageAdapter;
|
|
8
8
|
/** Wrap a Web Storage (localStorage/sessionStorage) as a StorageAdapter. */
|
|
9
9
|
declare function webStorage(store: Storage): StorageAdapter;
|
package/dist/index.js
CHANGED
|
@@ -145,18 +145,6 @@ function resolveStorage(opt) {
|
|
|
145
145
|
} };
|
|
146
146
|
}
|
|
147
147
|
if (opt) return opt;
|
|
148
|
-
try {
|
|
149
|
-
if (typeof globalThis !== "undefined") {
|
|
150
|
-
const ls = globalThis.localStorage;
|
|
151
|
-
if (ls) {
|
|
152
|
-
const probe = "__umc_probe__";
|
|
153
|
-
ls.setItem(probe, "1");
|
|
154
|
-
ls.removeItem(probe);
|
|
155
|
-
return webStorage(ls);
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
} catch {
|
|
159
|
-
}
|
|
160
148
|
return memoryStorage();
|
|
161
149
|
}
|
|
162
150
|
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/jsonrpc.ts","../src/machine.ts","../src/storage.ts","../src/transport.ts","../src/client.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["// JSON-RPC 2.0 framing for the membrane MCP wire, plus the SDK error taxonomy.\n//\n// The membrane speaks hand-rolled JSON-RPC over Streamable HTTP. The SDK only\n// ever sends `initialize` and `tools/call`. A tools/call comes back as a RESULT\n// shaped `{ content: [{ type:\"text\", text }], isError }`; a protocol-level\n// failure comes back as a JSON-RPC `error` object. This module owns the framing\n// + the parsing helpers; the wrappers in client.ts decode the text content.\n\n/** A JSON-RPC request envelope. */\nexport interface JsonRpcRequest {\n jsonrpc: \"2.0\";\n id: number;\n method: string;\n params?: unknown;\n}\n\n/** A JSON-RPC error object. */\nexport interface JsonRpcErrorObject {\n code: number;\n message: string;\n data?: unknown;\n}\n\n/** A parsed JSON-RPC response (success xor error). */\nexport interface JsonRpcResponse {\n jsonrpc: \"2.0\";\n id: number | null;\n result?: unknown;\n error?: JsonRpcErrorObject;\n}\n\n/** The MCP tools/call result shape (`content` blocks + an error flag). */\nexport interface ToolResult {\n content: Array<{ type: string; text?: string }>;\n isError?: boolean;\n}\n\n/** Base class for every error the SDK throws, so callers can `catch (e)`. */\nexport class UseMyContextError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"UseMyContextError\";\n // Restore the prototype chain (TS target < ES2015 / transpiled extends).\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\n/** Thrown when a tool wrapper is called before a successful `connect()`. */\nexport class NotConnectedError extends UseMyContextError {\n constructor(message = \"Not connected. Call connect({ token }) first.\") {\n super(message);\n this.name = \"NotConnectedError\";\n }\n}\n\n/**\n * Thrown when the membrane rejects the token (HTTP 401 + WWW-Authenticate).\n * The client also transitions to `expired` so the host can re-connect.\n */\nexport class TokenExpiredError extends UseMyContextError {\n /** The raw `WWW-Authenticate` header, when the server sent one. */\n readonly wwwAuthenticate?: string;\n constructor(message = \"The connection token was rejected (expired or revoked).\", wwwAuthenticate?: string) {\n super(message);\n this.name = \"TokenExpiredError\";\n this.wwwAuthenticate = wwwAuthenticate;\n }\n}\n\n/** Thrown when a tool call is refused for lack of scope (membrane -32604). */\nexport class ScopeDeniedError extends UseMyContextError {\n readonly code = -32604;\n constructor(message: string) {\n super(message);\n this.name = \"ScopeDeniedError\";\n }\n}\n\n/** Thrown for a JSON-RPC protocol error or a tool-level `isError` result. */\nexport class ToolCallError extends UseMyContextError {\n /** The JSON-RPC error code, when the failure was a protocol error. */\n readonly code?: number;\n constructor(message: string, code?: number) {\n super(message);\n this.name = \"ToolCallError\";\n this.code = code;\n }\n}\n\n/** Thrown for transport/parse failures (network down, non-JSON body, ...). */\nexport class TransportError extends UseMyContextError {\n constructor(message: string) {\n super(message);\n this.name = \"TransportError\";\n }\n}\n\nlet nextId = 1;\n\n/** Build an `initialize` request (the connect handshake). */\nexport function initializeRequest(): JsonRpcRequest {\n return {\n jsonrpc: \"2.0\",\n id: nextId++,\n method: \"initialize\",\n params: {\n protocolVersion: \"2025-06-18\",\n capabilities: {},\n clientInfo: { name: \"usemycontext-sdk\", version: \"0.1.0\" },\n },\n };\n}\n\n/** Build a `tools/call` request for a tool name + arguments. */\nexport function toolCallRequest(name: string, args: Record<string, unknown>): JsonRpcRequest {\n return {\n jsonrpc: \"2.0\",\n id: nextId++,\n method: \"tools/call\",\n params: { name, arguments: args },\n };\n}\n\n/**\n * Narrow an unknown body to a JSON-RPC response. Throws TransportError when the\n * body is not a well-formed JSON-RPC 2.0 envelope (a defensive guard against a\n * misbehaving transport or an HTML error page).\n */\nexport function asJsonRpcResponse(body: unknown): JsonRpcResponse {\n if (body === null || typeof body !== \"object\") {\n throw new TransportError(\"Membrane returned a non-object response body.\");\n }\n const b = body as Record<string, unknown>;\n if (b.jsonrpc !== \"2.0\") {\n throw new TransportError(\"Membrane response was not JSON-RPC 2.0.\");\n }\n return b as unknown as JsonRpcResponse;\n}\n\n/** True iff a JSON-RPC error code denotes a missing-scope denial (-32604). */\nexport function isScopeDenied(code: number): boolean {\n return code === -32604;\n}\n\n/**\n * Pull the single text block out of a tools/call RESULT. The membrane always\n * renders to ONE text content block, so this returns its `text` (or \"\" when a\n * result carried no text block).\n */\nexport function resultText(result: ToolResult): string {\n for (const block of result.content ?? []) {\n if (block.type === \"text\" && typeof block.text === \"string\") return block.text;\n }\n return \"\";\n}\n","// The connect state machine - a PURE reducer (no IO, no timers, no `this`).\n//\n// States (ConnectState):\n// idle -> connecting -> connected\n// \\-> declined (user/host refused; v2 OAuth path)\n// \\-> error (network/transport/parse failure)\n// connected -> expired (membrane 401 mid-session)\n// connected -> disconnected (explicit disconnect)\n// <any> -> disconnected (disconnect is always reachable)\n// <terminal>-> connecting (a fresh connect() retries)\n//\n// The reducer is the single source of truth for legality: an event that does\n// not apply to the current state is a NO-OP (returns the same state), so the\n// client can fire events without guarding, and tests can assert every legal AND\n// illegal transition deterministically.\n\nimport type { ConnectState } from \"./types.js\";\n\n/** The events that drive the machine. */\nexport type ConnectEvent =\n | { type: \"CONNECT\" } // begin a connect attempt\n | { type: \"CONNECT_SUCCESS\" } // membrane accepted the token\n | { type: \"CONNECT_DECLINED\" } // user/host refused (v2 OAuth path)\n | { type: \"TOKEN_EXPIRED\" } // membrane 401 (expired/revoked)\n | { type: \"ERROR\" } // a non-auth failure\n | { type: \"DISCONNECT\" }; // explicit disconnect / token cleared\n\n/** The initial state of a fresh client. */\nexport const INITIAL_STATE: ConnectState = \"idle\";\n\n/**\n * The pure transition function. Returns the NEXT state for `(state, event)`, or\n * the SAME state when the event is illegal in that state (a no-op).\n */\nexport function reduce(state: ConnectState, event: ConnectEvent): ConnectState {\n switch (event.type) {\n case \"CONNECT\":\n // A connect attempt is legal from any NON-in-flight state: a fresh client,\n // a terminal/failed state (retry), or an already-connected client\n // (re-connect with a new token). It is a no-op only while already\n // connecting (a second concurrent connect does nothing).\n return state === \"connecting\" ? state : \"connecting\";\n\n case \"CONNECT_SUCCESS\":\n // Only a connect IN FLIGHT can succeed. Any other state ignores it (a\n // stale/duplicate success after disconnect must not resurrect the client).\n return state === \"connecting\" ? \"connected\" : state;\n\n case \"CONNECT_DECLINED\":\n // Only a connect in flight can be declined.\n return state === \"connecting\" ? \"declined\" : state;\n\n case \"ERROR\":\n // A connect in flight can fail with a non-auth error. (A wrapper-call\n // failure while `connected` does NOT change the connect state - the\n // connection is still valid - so ERROR is a no-op when connected.)\n return state === \"connecting\" ? \"error\" : state;\n\n case \"TOKEN_EXPIRED\":\n // The membrane rejected the token. Legal from `connecting` (the token was\n // bad at connect time) or `connected` (it expired/was revoked mid-session).\n return state === \"connecting\" || state === \"connected\" ? \"expired\" : state;\n\n case \"DISCONNECT\":\n // Disconnect is ALWAYS reachable and idempotent: it moves any state to\n // `disconnected` (a no-op only when already there).\n return state === \"disconnected\" ? state : \"disconnected\";\n\n default: {\n // Exhaustiveness: a new event type must be handled above.\n const _never: never = event;\n return state;\n }\n }\n}\n\n/** Every state the machine can occupy (for reachability assertions). */\nexport const ALL_STATES: readonly ConnectState[] = [\n \"idle\",\n \"connecting\",\n \"connected\",\n \"declined\",\n \"expired\",\n \"error\",\n \"disconnected\",\n] as const;\n\n/** Whether the 7 tool wrappers may be called in this state. */\nexport function isConnected(state: ConnectState): boolean {\n return state === \"connected\";\n}\n","// Token persistence. Defaults to `localStorage` when present (the browser host\n// page), falls back to an in-memory store (SSR / Node / tests), and can be\n// disabled entirely (pass `storage: null` to the client).\n\nimport type { StorageAdapter } from \"./types.js\";\n\n/** The default storage key the token is persisted under. */\nexport const DEFAULT_STORAGE_KEY = \"usemycontext.token\";\n\n/** An in-memory storage adapter (SSR-safe; the fallback when no localStorage). */\nexport function memoryStorage(): StorageAdapter {\n const map = new Map<string, string>();\n return {\n get: (k) => (map.has(k) ? (map.get(k) as string) : null),\n set: (k, v) => void map.set(k, v),\n remove: (k) => void map.delete(k),\n };\n}\n\n/** Wrap a Web Storage (localStorage/sessionStorage) as a StorageAdapter. */\nexport function webStorage(store: Storage): StorageAdapter {\n return {\n get: (k) => {\n try {\n return store.getItem(k);\n } catch {\n return null;\n }\n },\n set: (k, v) => {\n try {\n store.setItem(k, v);\n } catch {\n /* quota / privacy mode - degrade to no-persist, never throw */\n }\n },\n remove: (k) => {\n try {\n store.removeItem(k);\n } catch {\n /* ignore */\n }\n },\n };\n}\n\n/**\n * Resolve the storage adapter to use given the option:\n * - an explicit adapter -> use it;\n * - `null` -> persistence disabled (a no-op adapter);\n * - `undefined` -> localStorage when available, else in-memory.\n */\nexport function resolveStorage(opt: StorageAdapter | null | undefined): StorageAdapter {\n if (opt === null) {\n return { get: () => null, set: () => {}, remove: () => {} };\n }\n if (opt) return opt;\n // Browser: prefer localStorage. Guarded for SSR + privacy-mode throws.\n try {\n if (typeof globalThis !== \"undefined\") {\n const ls = (globalThis as { localStorage?: Storage }).localStorage;\n if (ls) {\n // Probe it - some environments expose a localStorage that throws on use.\n const probe = \"__umc_probe__\";\n ls.setItem(probe, \"1\");\n ls.removeItem(probe);\n return webStorage(ls);\n }\n }\n } catch {\n /* fall through to in-memory */\n }\n return memoryStorage();\n}\n","// The default `fetch`-based transport. Tests inject a mock transport instead, so\n// this module is never exercised by the (zero-network) test suite - it is the\n// production wiring that POSTs one JSON-RPC request to the membrane `/mcp`\n// endpoint with the user's bearer token.\n\nimport type { Transport, TransportResponse } from \"./types.js\";\n\n/** A `fetch`-backed Transport (the default when none is supplied). */\nexport const fetchTransport: Transport = async ({ url, token, body }): Promise<TransportResponse> => {\n const res = await fetch(url, {\n method: \"POST\",\n headers: {\n \"content-type\": \"application/json\",\n accept: \"application/json\",\n authorization: `Bearer ${token}`,\n },\n body: JSON.stringify(body),\n });\n let parsed: unknown = null;\n try {\n parsed = await res.json();\n } catch {\n parsed = null; // non-JSON / empty body (e.g. a 401 with no body)\n }\n return {\n status: res.status,\n body: parsed,\n wwwAuthenticate: res.headers.get(\"www-authenticate\"),\n };\n};\n","// The core client: `useMyContext()` (a framework-free factory) + the 7 tool\n// wrappers. It holds the user's OWN token and calls the membrane exactly like\n// Claude does - same trust model, new client shape. The service stays\n// structurally blind.\n//\n// v1 IS TOKEN-IN ONLY: `connect({ token })`. The full browser-OAuth-in-the-SDK\n// flow (a hosted popup on connect.usemycontext.ai) is v2, gated on the Phase 2\n// CORS landing - deliberately NOT built here.\n\nimport {\n initializeRequest,\n toolCallRequest,\n asJsonRpcResponse,\n resultText,\n isScopeDenied,\n NotConnectedError,\n TokenExpiredError,\n ScopeDeniedError,\n ToolCallError,\n TransportError,\n UseMyContextError,\n type ToolResult,\n} from \"./jsonrpc.js\";\nimport { reduce, INITIAL_STATE, isConnected } from \"./machine.js\";\nimport { resolveStorage, DEFAULT_STORAGE_KEY } from \"./storage.js\";\nimport { fetchTransport } from \"./transport.js\";\nimport type {\n ClientOptions,\n ConnectArgs,\n ConnectState,\n FileMeta,\n ProfileResult,\n AskOptions,\n AskResult,\n AskPassage,\n GetFileResult,\n SuggestUpdateResult,\n SharedContextResult,\n SharedContextEntry,\n StorageAdapter,\n Transport,\n} from \"./types.js\";\n\n/** The production membrane MCP endpoint. */\nexport const DEFAULT_ENDPOINT = \"https://mcp.usemycontext.ai/mcp\";\n\n/** The shape `useMyContext()` returns - the client handle. */\nexport interface UseMyContextClient {\n /** The current connect state. */\n readonly state: ConnectState;\n /** Convenience: true iff `state === \"connected\"`. */\n readonly connected: boolean;\n /** The held token, when connected (else null). */\n readonly token: string | null;\n\n /** Subscribe to state changes. Returns an unsubscribe fn. */\n subscribe(listener: (state: ConnectState) => void): () => void;\n\n /** v1 TOKEN-IN connect: validate the token against the membrane. */\n connect(args: ConnectArgs): Promise<ConnectState>;\n /** Clear the token + persisted storage; -> `disconnected`. */\n disconnect(): void;\n\n // --- the 7 MCP tool wrappers ---\n profile(): Promise<ProfileResult>;\n listFiles(): Promise<FileMeta[]>;\n searchFiles(query: string): Promise<FileMeta[]>;\n getFile(fileId: string): Promise<GetFileResult>;\n ask(query: string, opts?: AskOptions): Promise<AskResult>;\n suggestUpdate(suggestion: string): Promise<SuggestUpdateResult>;\n sharedContext(from?: string): Promise<SharedContextResult>;\n}\n\n/**\n * Create a UseMyContext client. Framework-free: the React hook wraps this.\n * Restores a persisted token (without revalidating) so a returning host page\n * starts `connected`; a stale token surfaces as `expired` on the first call.\n */\nexport function useMyContext(options: ClientOptions = {}): UseMyContextClient {\n const endpoint = options.endpoint ?? DEFAULT_ENDPOINT;\n const transport: Transport = options.transport ?? fetchTransport;\n const storage: StorageAdapter = resolveStorage(options.storage);\n const storageKey = options.storageKey ?? DEFAULT_STORAGE_KEY;\n\n const listeners = new Set<(state: ConnectState) => void>();\n let state: ConnectState = INITIAL_STATE;\n let token: string | null = null;\n\n // Restore a persisted token: a returning page is `connected` optimistically\n // (the membrane is the authority - a stale token -> `expired` on first call).\n const persisted = storage.get(storageKey);\n if (persisted) {\n token = persisted;\n state = \"connected\";\n }\n\n function setState(next: ConnectState): void {\n if (next === state) return;\n state = next;\n options.onStateChange?.(state);\n for (const l of listeners) l(state);\n }\n\n function dispatch(event: Parameters<typeof reduce>[1]): void {\n setState(reduce(state, event));\n }\n\n /** One JSON-RPC round-trip against the membrane with the held token. */\n async function rpc(body: unknown): Promise<unknown> {\n if (!token) throw new NotConnectedError();\n let res;\n try {\n res = await transport({ url: endpoint, token, body });\n } catch (e) {\n throw new TransportError(\n `Transport failed: ${e instanceof Error ? e.message : String(e)}`,\n );\n }\n // A 401 means the token is bad/expired/revoked. Drive the machine to\n // `expired` and throw - the host should re-connect.\n if (res.status === 401) {\n dispatch({ type: \"TOKEN_EXPIRED\" });\n throw new TokenExpiredError(undefined, res.wwwAuthenticate ?? undefined);\n }\n const parsed = asJsonRpcResponse(res.body);\n if (parsed.error) {\n if (isScopeDenied(parsed.error.code)) {\n throw new ScopeDeniedError(parsed.error.message);\n }\n throw new ToolCallError(parsed.error.message, parsed.error.code);\n }\n return parsed.result;\n }\n\n /** A tools/call that returns the single rendered text block. */\n async function callTool(name: string, args: Record<string, unknown>): Promise<string> {\n if (!isConnected(state)) throw new NotConnectedError();\n const result = (await rpc(toolCallRequest(name, args))) as ToolResult;\n if (result.isError) {\n throw new ToolCallError(resultText(result) || `${name} failed.`);\n }\n return resultText(result);\n }\n\n return {\n get state() {\n return state;\n },\n get connected() {\n return state === \"connected\";\n },\n get token() {\n return state === \"connected\" ? token : null;\n },\n\n subscribe(listener) {\n listeners.add(listener);\n return () => void listeners.delete(listener);\n },\n\n async connect({ token: t }: ConnectArgs): Promise<ConnectState> {\n if (typeof t !== \"string\" || t.length === 0) {\n // A bad arg is a developer error, not a state transition.\n throw new UseMyContextConnectArgError();\n }\n dispatch({ type: \"CONNECT\" });\n token = t;\n try {\n const res = await transport({ url: endpoint, token: t, body: initializeRequest() });\n if (res.status === 401) {\n token = null;\n dispatch({ type: \"TOKEN_EXPIRED\" });\n throw new TokenExpiredError(undefined, res.wwwAuthenticate ?? undefined);\n }\n // Validate the handshake came back as a well-formed JSON-RPC result.\n const parsed = asJsonRpcResponse(res.body);\n if (parsed.error) {\n token = null;\n dispatch({ type: \"ERROR\" });\n throw new ToolCallError(parsed.error.message, parsed.error.code);\n }\n dispatch({ type: \"CONNECT_SUCCESS\" });\n if (storage) storage.set(storageKey, t);\n return state;\n } catch (e) {\n token = null;\n // TokenExpiredError already drove the machine to `expired`; any other\n // failure is a non-auth `error`.\n if (!(e instanceof TokenExpiredError)) {\n dispatch({ type: \"ERROR\" });\n if (e instanceof TransportError || e instanceof ToolCallError) throw e;\n throw new TransportError(\n `Connect failed: ${e instanceof Error ? e.message : String(e)}`,\n );\n }\n throw e;\n }\n },\n\n disconnect(): void {\n token = null;\n storage.remove(storageKey);\n dispatch({ type: \"DISCONNECT\" });\n },\n\n // --- profile ---------------------------------------------------------\n async profile(): Promise<ProfileResult> {\n const text = await callTool(\"profile\", {});\n // The membrane serves the compiled composite as plain text, OR (no compile\n // yet) the JSON of `{ facts: [...] }`. Detect the fallback by parsing.\n const facts = tryParseFacts(text);\n if (facts) return { composite: text, facts };\n return { composite: text };\n },\n\n // --- list_files / search_files (JSON array of FileMeta) --------------\n async listFiles(): Promise<FileMeta[]> {\n return parseFileList(await callTool(\"list_files\", {}));\n },\n async searchFiles(query: string): Promise<FileMeta[]> {\n if (typeof query !== \"string\") throw new UseMyContextConnectArgError(\"search query must be a string\");\n return parseFileList(await callTool(\"search_files\", { query }));\n },\n\n // --- get_file --------------------------------------------------------\n async getFile(fileId: string): Promise<GetFileResult> {\n if (typeof fileId !== \"string\" || !fileId) {\n throw new UseMyContextConnectArgError(\"fileId must be a non-empty string\");\n }\n const text = await callTool(\"get_file\", { fileId });\n return { text, downloadUrl: parseDownloadUrl(text) };\n },\n\n // --- ask_docs --------------------------------------------------------\n async ask(query: string, opts: AskOptions = {}): Promise<AskResult> {\n if (typeof query !== \"string\" || !query) {\n throw new UseMyContextConnectArgError(\"ask query must be a non-empty string\");\n }\n const args: Record<string, unknown> = { query };\n if (typeof opts.k === \"number\") args.k = opts.k;\n if (typeof opts.projectId === \"string\") args.projectId = opts.projectId;\n const text = await callTool(\"ask_docs\", args);\n return { passages: parseAskPassages(text), text };\n },\n\n // --- suggest_update (the one write) ----------------------------------\n async suggestUpdate(suggestion: string): Promise<SuggestUpdateResult> {\n if (typeof suggestion !== \"string\" || !suggestion.trim()) {\n throw new UseMyContextConnectArgError(\"suggestion must be a non-empty string\");\n }\n const text = await callTool(\"suggest_update\", { suggestion });\n const m = text.match(/\\(id:\\s*([^)]+)\\)/);\n return { id: m ? m[1].trim() : undefined, text };\n },\n\n // --- shared_context --------------------------------------------------\n async sharedContext(from?: string): Promise<SharedContextResult> {\n const args: Record<string, unknown> = {};\n if (typeof from === \"string\" && from) args.from = from;\n const text = await callTool(\"shared_context\", args);\n return from ? parseSharedRead(text) : parseSharedList(text);\n },\n };\n}\n\n/** Thrown for a bad SDK call argument (a developer error, not a state event). */\nexport class UseMyContextConnectArgError extends UseMyContextError {\n constructor(message = \"connect() requires a non-empty token string.\") {\n super(message);\n this.name = \"UseMyContextConnectArgError\";\n }\n}\n\n// --- parsers (decode the membrane's RENDERED text back to typed shapes) ---\n\n/** Parse `profile`'s JSON fallback (`{facts:[...]}`); null when it's prose. */\nfunction tryParseFacts(text: string): string[] | undefined {\n const trimmed = text.trimStart();\n if (!trimmed.startsWith(\"{\")) return undefined;\n try {\n const obj = JSON.parse(text) as { facts?: unknown };\n if (Array.isArray(obj.facts)) return obj.facts.filter((f): f is string => typeof f === \"string\");\n } catch {\n /* prose composite that happens to start with \"{\" - treat as composite */\n }\n return undefined;\n}\n\n/** Parse a list/search JSON array into FileMeta[]. */\nfunction parseFileList(text: string): FileMeta[] {\n try {\n const arr = JSON.parse(text) as unknown;\n if (!Array.isArray(arr)) return [];\n return arr.map((r) => {\n const o = (r ?? {}) as Record<string, unknown>;\n return {\n id: String(o.id ?? \"\"),\n name: String(o.name ?? \"\"),\n size: typeof o.size === \"number\" ? o.size : 0,\n contentType: String(o.contentType ?? \"\"),\n modified: String(o.modified ?? \"\"),\n ...(typeof o.status === \"string\" ? { status: o.status as FileMeta[\"status\"] } : {}),\n };\n });\n } catch {\n return [];\n }\n}\n\n/** Pull a `Download link ... : <url>` out of a get_file render. */\nfunction parseDownloadUrl(text: string): string | undefined {\n const m = text.match(/Download link[^:]*:\\s*(\\S+)/);\n return m ? m[1] : undefined;\n}\n\n/**\n * Parse `renderAskDocs` output: blocks separated by a blank line, each a\n * `[n] file · scope · score X.XXX` citation line then the passage text. An empty\n * result is the calm \"No relevant passages...\" sentence -> zero passages.\n */\nfunction parseAskPassages(text: string): AskPassage[] {\n if (/^No relevant passages/i.test(text.trimStart())) return [];\n const blocks = text.split(\"\\n\\n\");\n const out: AskPassage[] = [];\n for (const block of blocks) {\n const nl = block.indexOf(\"\\n\");\n const citation = nl === -1 ? block : block.slice(0, nl);\n const body = nl === -1 ? \"\" : block.slice(nl + 1);\n const m = citation.match(/^\\[(\\d+)\\]\\s*(.*)$/);\n if (!m) continue;\n const index = Number(m[1]);\n const rest = m[2];\n // rest = `file · scope · score N.NNN`\n const parts = rest.split(\" · \");\n const passage: AskPassage = { index, text: body };\n if (parts[0]) passage.file = parts[0].trim();\n if (parts[1]) passage.scope = parts[1].trim();\n const scoreM = rest.match(/score\\s+([\\d.]+)/);\n if (scoreM) passage.score = Number(scoreM[1]);\n out.push(passage);\n }\n return out;\n}\n\n/** Parse `renderSharedContext` LIST output (lines `- who (from: grantId)`). */\nfunction parseSharedList(text: string): SharedContextResult {\n if (/^No one has shared/i.test(text.trimStart())) {\n return { mode: \"list\", shares: [], composite: null, text };\n }\n const shares: SharedContextEntry[] = [];\n for (const line of text.split(\"\\n\")) {\n const m = line.match(/^-\\s*(.*?)\\s*\\(from:\\s*([^)]+)\\)\\s*$/);\n if (m) shares.push({ ownerLabel: m[1].trim(), grantId: m[2].trim() });\n }\n return { mode: \"list\", shares, composite: null, text };\n}\n\n/** Parse `renderSharedContext` READ output (`Shared context from X:\\n\\n<text>`). */\nfunction parseSharedRead(text: string): SharedContextResult {\n if (/not available/i.test(text)) {\n return { mode: \"read\", shares: [], composite: null, text };\n }\n const m = text.match(/^Shared context from [^:]*:\\n\\n([\\s\\S]*)$/);\n const composite = m ? m[1] : text;\n return { mode: \"read\", shares: [], composite, text };\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/jsonrpc.ts","../src/machine.ts","../src/storage.ts","../src/transport.ts","../src/client.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["// JSON-RPC 2.0 framing for the membrane MCP wire, plus the SDK error taxonomy.\n//\n// The membrane speaks hand-rolled JSON-RPC over Streamable HTTP. The SDK only\n// ever sends `initialize` and `tools/call`. A tools/call comes back as a RESULT\n// shaped `{ content: [{ type:\"text\", text }], isError }`; a protocol-level\n// failure comes back as a JSON-RPC `error` object. This module owns the framing\n// + the parsing helpers; the wrappers in client.ts decode the text content.\n\n/** A JSON-RPC request envelope. */\nexport interface JsonRpcRequest {\n jsonrpc: \"2.0\";\n id: number;\n method: string;\n params?: unknown;\n}\n\n/** A JSON-RPC error object. */\nexport interface JsonRpcErrorObject {\n code: number;\n message: string;\n data?: unknown;\n}\n\n/** A parsed JSON-RPC response (success xor error). */\nexport interface JsonRpcResponse {\n jsonrpc: \"2.0\";\n id: number | null;\n result?: unknown;\n error?: JsonRpcErrorObject;\n}\n\n/** The MCP tools/call result shape (`content` blocks + an error flag). */\nexport interface ToolResult {\n content: Array<{ type: string; text?: string }>;\n isError?: boolean;\n}\n\n/** Base class for every error the SDK throws, so callers can `catch (e)`. */\nexport class UseMyContextError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"UseMyContextError\";\n // Restore the prototype chain (TS target < ES2015 / transpiled extends).\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\n/** Thrown when a tool wrapper is called before a successful `connect()`. */\nexport class NotConnectedError extends UseMyContextError {\n constructor(message = \"Not connected. Call connect({ token }) first.\") {\n super(message);\n this.name = \"NotConnectedError\";\n }\n}\n\n/**\n * Thrown when the membrane rejects the token (HTTP 401 + WWW-Authenticate).\n * The client also transitions to `expired` so the host can re-connect.\n */\nexport class TokenExpiredError extends UseMyContextError {\n /** The raw `WWW-Authenticate` header, when the server sent one. */\n readonly wwwAuthenticate?: string;\n constructor(message = \"The connection token was rejected (expired or revoked).\", wwwAuthenticate?: string) {\n super(message);\n this.name = \"TokenExpiredError\";\n this.wwwAuthenticate = wwwAuthenticate;\n }\n}\n\n/** Thrown when a tool call is refused for lack of scope (membrane -32604). */\nexport class ScopeDeniedError extends UseMyContextError {\n readonly code = -32604;\n constructor(message: string) {\n super(message);\n this.name = \"ScopeDeniedError\";\n }\n}\n\n/** Thrown for a JSON-RPC protocol error or a tool-level `isError` result. */\nexport class ToolCallError extends UseMyContextError {\n /** The JSON-RPC error code, when the failure was a protocol error. */\n readonly code?: number;\n constructor(message: string, code?: number) {\n super(message);\n this.name = \"ToolCallError\";\n this.code = code;\n }\n}\n\n/** Thrown for transport/parse failures (network down, non-JSON body, ...). */\nexport class TransportError extends UseMyContextError {\n constructor(message: string) {\n super(message);\n this.name = \"TransportError\";\n }\n}\n\nlet nextId = 1;\n\n/** Build an `initialize` request (the connect handshake). */\nexport function initializeRequest(): JsonRpcRequest {\n return {\n jsonrpc: \"2.0\",\n id: nextId++,\n method: \"initialize\",\n params: {\n protocolVersion: \"2025-06-18\",\n capabilities: {},\n clientInfo: { name: \"usemycontext-sdk\", version: \"0.1.0\" },\n },\n };\n}\n\n/** Build a `tools/call` request for a tool name + arguments. */\nexport function toolCallRequest(name: string, args: Record<string, unknown>): JsonRpcRequest {\n return {\n jsonrpc: \"2.0\",\n id: nextId++,\n method: \"tools/call\",\n params: { name, arguments: args },\n };\n}\n\n/**\n * Narrow an unknown body to a JSON-RPC response. Throws TransportError when the\n * body is not a well-formed JSON-RPC 2.0 envelope (a defensive guard against a\n * misbehaving transport or an HTML error page).\n */\nexport function asJsonRpcResponse(body: unknown): JsonRpcResponse {\n if (body === null || typeof body !== \"object\") {\n throw new TransportError(\"Membrane returned a non-object response body.\");\n }\n const b = body as Record<string, unknown>;\n if (b.jsonrpc !== \"2.0\") {\n throw new TransportError(\"Membrane response was not JSON-RPC 2.0.\");\n }\n return b as unknown as JsonRpcResponse;\n}\n\n/** True iff a JSON-RPC error code denotes a missing-scope denial (-32604). */\nexport function isScopeDenied(code: number): boolean {\n return code === -32604;\n}\n\n/**\n * Pull the single text block out of a tools/call RESULT. The membrane always\n * renders to ONE text content block, so this returns its `text` (or \"\" when a\n * result carried no text block).\n */\nexport function resultText(result: ToolResult): string {\n for (const block of result.content ?? []) {\n if (block.type === \"text\" && typeof block.text === \"string\") return block.text;\n }\n return \"\";\n}\n","// The connect state machine - a PURE reducer (no IO, no timers, no `this`).\n//\n// States (ConnectState):\n// idle -> connecting -> connected\n// \\-> declined (user/host refused; v2 OAuth path)\n// \\-> error (network/transport/parse failure)\n// connected -> expired (membrane 401 mid-session)\n// connected -> disconnected (explicit disconnect)\n// <any> -> disconnected (disconnect is always reachable)\n// <terminal>-> connecting (a fresh connect() retries)\n//\n// The reducer is the single source of truth for legality: an event that does\n// not apply to the current state is a NO-OP (returns the same state), so the\n// client can fire events without guarding, and tests can assert every legal AND\n// illegal transition deterministically.\n\nimport type { ConnectState } from \"./types.js\";\n\n/** The events that drive the machine. */\nexport type ConnectEvent =\n | { type: \"CONNECT\" } // begin a connect attempt\n | { type: \"CONNECT_SUCCESS\" } // membrane accepted the token\n | { type: \"CONNECT_DECLINED\" } // user/host refused (v2 OAuth path)\n | { type: \"TOKEN_EXPIRED\" } // membrane 401 (expired/revoked)\n | { type: \"ERROR\" } // a non-auth failure\n | { type: \"DISCONNECT\" }; // explicit disconnect / token cleared\n\n/** The initial state of a fresh client. */\nexport const INITIAL_STATE: ConnectState = \"idle\";\n\n/**\n * The pure transition function. Returns the NEXT state for `(state, event)`, or\n * the SAME state when the event is illegal in that state (a no-op).\n */\nexport function reduce(state: ConnectState, event: ConnectEvent): ConnectState {\n switch (event.type) {\n case \"CONNECT\":\n // A connect attempt is legal from any NON-in-flight state: a fresh client,\n // a terminal/failed state (retry), or an already-connected client\n // (re-connect with a new token). It is a no-op only while already\n // connecting (a second concurrent connect does nothing).\n return state === \"connecting\" ? state : \"connecting\";\n\n case \"CONNECT_SUCCESS\":\n // Only a connect IN FLIGHT can succeed. Any other state ignores it (a\n // stale/duplicate success after disconnect must not resurrect the client).\n return state === \"connecting\" ? \"connected\" : state;\n\n case \"CONNECT_DECLINED\":\n // Only a connect in flight can be declined.\n return state === \"connecting\" ? \"declined\" : state;\n\n case \"ERROR\":\n // A connect in flight can fail with a non-auth error. (A wrapper-call\n // failure while `connected` does NOT change the connect state - the\n // connection is still valid - so ERROR is a no-op when connected.)\n return state === \"connecting\" ? \"error\" : state;\n\n case \"TOKEN_EXPIRED\":\n // The membrane rejected the token. Legal from `connecting` (the token was\n // bad at connect time) or `connected` (it expired/was revoked mid-session).\n return state === \"connecting\" || state === \"connected\" ? \"expired\" : state;\n\n case \"DISCONNECT\":\n // Disconnect is ALWAYS reachable and idempotent: it moves any state to\n // `disconnected` (a no-op only when already there).\n return state === \"disconnected\" ? state : \"disconnected\";\n\n default: {\n // Exhaustiveness: a new event type must be handled above.\n const _never: never = event;\n return state;\n }\n }\n}\n\n/** Every state the machine can occupy (for reachability assertions). */\nexport const ALL_STATES: readonly ConnectState[] = [\n \"idle\",\n \"connecting\",\n \"connected\",\n \"declined\",\n \"expired\",\n \"error\",\n \"disconnected\",\n] as const;\n\n/** Whether the 7 tool wrappers may be called in this state. */\nexport function isConnected(state: ConnectState): boolean {\n return state === \"connected\";\n}\n","// Token persistence. SAFE BY DEFAULT: persistence is in-memory only, so the\n// token NEVER touches `localStorage` unless the host page opts in explicitly\n// (pass `storage: webStorage(localStorage)`). The v1 token-in credential is the\n// user's long-lived session JWT - writing it to `localStorage` would expose a\n// ~decade-long key to any script on the host page (one XSS = full context\n// theft), which the threat model forbids. So the default is memory; opt IN to\n// cross-reload persistence knowingly, never opt out. Pass `storage: null` to\n// disable persistence entirely (a no-op store).\n\nimport type { StorageAdapter } from \"./types.js\";\n\n/** The default storage key the token is persisted under. */\nexport const DEFAULT_STORAGE_KEY = \"usemycontext.token\";\n\n/** An in-memory storage adapter (SSR-safe; the DEFAULT - token never leaves JS memory). */\nexport function memoryStorage(): StorageAdapter {\n const map = new Map<string, string>();\n return {\n get: (k) => (map.has(k) ? (map.get(k) as string) : null),\n set: (k, v) => void map.set(k, v),\n remove: (k) => void map.delete(k),\n };\n}\n\n/** Wrap a Web Storage (localStorage/sessionStorage) as a StorageAdapter. */\nexport function webStorage(store: Storage): StorageAdapter {\n return {\n get: (k) => {\n try {\n return store.getItem(k);\n } catch {\n return null;\n }\n },\n set: (k, v) => {\n try {\n store.setItem(k, v);\n } catch {\n /* quota / privacy mode - degrade to no-persist, never throw */\n }\n },\n remove: (k) => {\n try {\n store.removeItem(k);\n } catch {\n /* ignore */\n }\n },\n };\n}\n\n/**\n * Resolve the storage adapter to use given the option:\n * - an explicit adapter -> use it (e.g. `webStorage(localStorage)` to opt IN\n * to cross-reload persistence, knowingly accepting host-page token exposure);\n * - `null` -> persistence disabled (a no-op adapter);\n * - `undefined` (the DEFAULT) -> in-memory. The token NEVER touches\n * `localStorage` unless the caller asks for it. Safe by default.\n */\nexport function resolveStorage(opt: StorageAdapter | null | undefined): StorageAdapter {\n if (opt === null) {\n return { get: () => null, set: () => {}, remove: () => {} };\n }\n if (opt) return opt;\n // DEFAULT: in-memory only. We deliberately do NOT auto-select localStorage -\n // persisting the long-lived session JWT to the host page is an opt-in choice.\n return memoryStorage();\n}\n","// The default `fetch`-based transport. Tests inject a mock transport instead, so\n// this module is never exercised by the (zero-network) test suite - it is the\n// production wiring that POSTs one JSON-RPC request to the membrane `/mcp`\n// endpoint with the user's bearer token.\n\nimport type { Transport, TransportResponse } from \"./types.js\";\n\n/** A `fetch`-backed Transport (the default when none is supplied). */\nexport const fetchTransport: Transport = async ({ url, token, body }): Promise<TransportResponse> => {\n const res = await fetch(url, {\n method: \"POST\",\n headers: {\n \"content-type\": \"application/json\",\n accept: \"application/json\",\n authorization: `Bearer ${token}`,\n },\n body: JSON.stringify(body),\n });\n let parsed: unknown = null;\n try {\n parsed = await res.json();\n } catch {\n parsed = null; // non-JSON / empty body (e.g. a 401 with no body)\n }\n return {\n status: res.status,\n body: parsed,\n wwwAuthenticate: res.headers.get(\"www-authenticate\"),\n };\n};\n","// The core client: `useMyContext()` (a framework-free factory) + the 7 tool\n// wrappers. It holds the user's OWN token and calls the membrane exactly like\n// Claude does - same trust model, new client shape. The service stays\n// structurally blind.\n//\n// v1 IS TOKEN-IN ONLY: `connect({ token })`. The full browser-OAuth-in-the-SDK\n// flow (a hosted popup on connect.usemycontext.ai) is v2, gated on the Phase 2\n// CORS landing - deliberately NOT built here.\n\nimport {\n initializeRequest,\n toolCallRequest,\n asJsonRpcResponse,\n resultText,\n isScopeDenied,\n NotConnectedError,\n TokenExpiredError,\n ScopeDeniedError,\n ToolCallError,\n TransportError,\n UseMyContextError,\n type ToolResult,\n} from \"./jsonrpc.js\";\nimport { reduce, INITIAL_STATE, isConnected } from \"./machine.js\";\nimport { resolveStorage, DEFAULT_STORAGE_KEY } from \"./storage.js\";\nimport { fetchTransport } from \"./transport.js\";\nimport type {\n ClientOptions,\n ConnectArgs,\n ConnectState,\n FileMeta,\n ProfileResult,\n AskOptions,\n AskResult,\n AskPassage,\n GetFileResult,\n SuggestUpdateResult,\n SharedContextResult,\n SharedContextEntry,\n StorageAdapter,\n Transport,\n} from \"./types.js\";\n\n/** The production membrane MCP endpoint. */\nexport const DEFAULT_ENDPOINT = \"https://mcp.usemycontext.ai/mcp\";\n\n/** The shape `useMyContext()` returns - the client handle. */\nexport interface UseMyContextClient {\n /** The current connect state. */\n readonly state: ConnectState;\n /** Convenience: true iff `state === \"connected\"`. */\n readonly connected: boolean;\n /** The held token, when connected (else null). */\n readonly token: string | null;\n\n /** Subscribe to state changes. Returns an unsubscribe fn. */\n subscribe(listener: (state: ConnectState) => void): () => void;\n\n /** v1 TOKEN-IN connect: validate the token against the membrane. */\n connect(args: ConnectArgs): Promise<ConnectState>;\n /** Clear the token + persisted storage; -> `disconnected`. */\n disconnect(): void;\n\n // --- the 7 MCP tool wrappers ---\n profile(): Promise<ProfileResult>;\n listFiles(): Promise<FileMeta[]>;\n searchFiles(query: string): Promise<FileMeta[]>;\n getFile(fileId: string): Promise<GetFileResult>;\n ask(query: string, opts?: AskOptions): Promise<AskResult>;\n suggestUpdate(suggestion: string): Promise<SuggestUpdateResult>;\n sharedContext(from?: string): Promise<SharedContextResult>;\n}\n\n/**\n * Create a UseMyContext client. Framework-free: the React hook wraps this.\n * Restores a persisted token (without revalidating) so a returning host page\n * starts `connected`; a stale token surfaces as `expired` on the first call.\n */\nexport function useMyContext(options: ClientOptions = {}): UseMyContextClient {\n const endpoint = options.endpoint ?? DEFAULT_ENDPOINT;\n const transport: Transport = options.transport ?? fetchTransport;\n const storage: StorageAdapter = resolveStorage(options.storage);\n const storageKey = options.storageKey ?? DEFAULT_STORAGE_KEY;\n\n const listeners = new Set<(state: ConnectState) => void>();\n let state: ConnectState = INITIAL_STATE;\n let token: string | null = null;\n\n // Restore a persisted token: a returning page is `connected` optimistically\n // (the membrane is the authority - a stale token -> `expired` on first call).\n const persisted = storage.get(storageKey);\n if (persisted) {\n token = persisted;\n state = \"connected\";\n }\n\n function setState(next: ConnectState): void {\n if (next === state) return;\n state = next;\n options.onStateChange?.(state);\n for (const l of listeners) l(state);\n }\n\n function dispatch(event: Parameters<typeof reduce>[1]): void {\n setState(reduce(state, event));\n }\n\n /** One JSON-RPC round-trip against the membrane with the held token. */\n async function rpc(body: unknown): Promise<unknown> {\n if (!token) throw new NotConnectedError();\n let res;\n try {\n res = await transport({ url: endpoint, token, body });\n } catch (e) {\n throw new TransportError(\n `Transport failed: ${e instanceof Error ? e.message : String(e)}`,\n );\n }\n // A 401 means the token is bad/expired/revoked. Drive the machine to\n // `expired` and throw - the host should re-connect.\n if (res.status === 401) {\n dispatch({ type: \"TOKEN_EXPIRED\" });\n throw new TokenExpiredError(undefined, res.wwwAuthenticate ?? undefined);\n }\n const parsed = asJsonRpcResponse(res.body);\n if (parsed.error) {\n if (isScopeDenied(parsed.error.code)) {\n throw new ScopeDeniedError(parsed.error.message);\n }\n throw new ToolCallError(parsed.error.message, parsed.error.code);\n }\n return parsed.result;\n }\n\n /** A tools/call that returns the single rendered text block. */\n async function callTool(name: string, args: Record<string, unknown>): Promise<string> {\n if (!isConnected(state)) throw new NotConnectedError();\n const result = (await rpc(toolCallRequest(name, args))) as ToolResult;\n if (result.isError) {\n throw new ToolCallError(resultText(result) || `${name} failed.`);\n }\n return resultText(result);\n }\n\n return {\n get state() {\n return state;\n },\n get connected() {\n return state === \"connected\";\n },\n get token() {\n return state === \"connected\" ? token : null;\n },\n\n subscribe(listener) {\n listeners.add(listener);\n return () => void listeners.delete(listener);\n },\n\n async connect({ token: t }: ConnectArgs): Promise<ConnectState> {\n if (typeof t !== \"string\" || t.length === 0) {\n // A bad arg is a developer error, not a state transition.\n throw new UseMyContextConnectArgError();\n }\n dispatch({ type: \"CONNECT\" });\n token = t;\n try {\n const res = await transport({ url: endpoint, token: t, body: initializeRequest() });\n if (res.status === 401) {\n token = null;\n dispatch({ type: \"TOKEN_EXPIRED\" });\n throw new TokenExpiredError(undefined, res.wwwAuthenticate ?? undefined);\n }\n // Validate the handshake came back as a well-formed JSON-RPC result.\n const parsed = asJsonRpcResponse(res.body);\n if (parsed.error) {\n token = null;\n dispatch({ type: \"ERROR\" });\n throw new ToolCallError(parsed.error.message, parsed.error.code);\n }\n dispatch({ type: \"CONNECT_SUCCESS\" });\n if (storage) storage.set(storageKey, t);\n return state;\n } catch (e) {\n token = null;\n // TokenExpiredError already drove the machine to `expired`; any other\n // failure is a non-auth `error`.\n if (!(e instanceof TokenExpiredError)) {\n dispatch({ type: \"ERROR\" });\n if (e instanceof TransportError || e instanceof ToolCallError) throw e;\n throw new TransportError(\n `Connect failed: ${e instanceof Error ? e.message : String(e)}`,\n );\n }\n throw e;\n }\n },\n\n disconnect(): void {\n token = null;\n storage.remove(storageKey);\n dispatch({ type: \"DISCONNECT\" });\n },\n\n // --- profile ---------------------------------------------------------\n async profile(): Promise<ProfileResult> {\n const text = await callTool(\"profile\", {});\n // The membrane serves the compiled composite as plain text, OR (no compile\n // yet) the JSON of `{ facts: [...] }`. Detect the fallback by parsing.\n const facts = tryParseFacts(text);\n if (facts) return { composite: text, facts };\n return { composite: text };\n },\n\n // --- list_files / search_files (JSON array of FileMeta) --------------\n async listFiles(): Promise<FileMeta[]> {\n return parseFileList(await callTool(\"list_files\", {}));\n },\n async searchFiles(query: string): Promise<FileMeta[]> {\n if (typeof query !== \"string\") throw new UseMyContextConnectArgError(\"search query must be a string\");\n return parseFileList(await callTool(\"search_files\", { query }));\n },\n\n // --- get_file --------------------------------------------------------\n async getFile(fileId: string): Promise<GetFileResult> {\n if (typeof fileId !== \"string\" || !fileId) {\n throw new UseMyContextConnectArgError(\"fileId must be a non-empty string\");\n }\n const text = await callTool(\"get_file\", { fileId });\n return { text, downloadUrl: parseDownloadUrl(text) };\n },\n\n // --- ask_docs --------------------------------------------------------\n async ask(query: string, opts: AskOptions = {}): Promise<AskResult> {\n if (typeof query !== \"string\" || !query) {\n throw new UseMyContextConnectArgError(\"ask query must be a non-empty string\");\n }\n const args: Record<string, unknown> = { query };\n if (typeof opts.k === \"number\") args.k = opts.k;\n if (typeof opts.projectId === \"string\") args.projectId = opts.projectId;\n const text = await callTool(\"ask_docs\", args);\n return { passages: parseAskPassages(text), text };\n },\n\n // --- suggest_update (the one write) ----------------------------------\n async suggestUpdate(suggestion: string): Promise<SuggestUpdateResult> {\n if (typeof suggestion !== \"string\" || !suggestion.trim()) {\n throw new UseMyContextConnectArgError(\"suggestion must be a non-empty string\");\n }\n const text = await callTool(\"suggest_update\", { suggestion });\n const m = text.match(/\\(id:\\s*([^)]+)\\)/);\n return { id: m ? m[1].trim() : undefined, text };\n },\n\n // --- shared_context --------------------------------------------------\n async sharedContext(from?: string): Promise<SharedContextResult> {\n const args: Record<string, unknown> = {};\n if (typeof from === \"string\" && from) args.from = from;\n const text = await callTool(\"shared_context\", args);\n return from ? parseSharedRead(text) : parseSharedList(text);\n },\n };\n}\n\n/** Thrown for a bad SDK call argument (a developer error, not a state event). */\nexport class UseMyContextConnectArgError extends UseMyContextError {\n constructor(message = \"connect() requires a non-empty token string.\") {\n super(message);\n this.name = \"UseMyContextConnectArgError\";\n }\n}\n\n// --- parsers (decode the membrane's RENDERED text back to typed shapes) ---\n\n/** Parse `profile`'s JSON fallback (`{facts:[...]}`); null when it's prose. */\nfunction tryParseFacts(text: string): string[] | undefined {\n const trimmed = text.trimStart();\n if (!trimmed.startsWith(\"{\")) return undefined;\n try {\n const obj = JSON.parse(text) as { facts?: unknown };\n if (Array.isArray(obj.facts)) return obj.facts.filter((f): f is string => typeof f === \"string\");\n } catch {\n /* prose composite that happens to start with \"{\" - treat as composite */\n }\n return undefined;\n}\n\n/** Parse a list/search JSON array into FileMeta[]. */\nfunction parseFileList(text: string): FileMeta[] {\n try {\n const arr = JSON.parse(text) as unknown;\n if (!Array.isArray(arr)) return [];\n return arr.map((r) => {\n const o = (r ?? {}) as Record<string, unknown>;\n return {\n id: String(o.id ?? \"\"),\n name: String(o.name ?? \"\"),\n size: typeof o.size === \"number\" ? o.size : 0,\n contentType: String(o.contentType ?? \"\"),\n modified: String(o.modified ?? \"\"),\n ...(typeof o.status === \"string\" ? { status: o.status as FileMeta[\"status\"] } : {}),\n };\n });\n } catch {\n return [];\n }\n}\n\n/** Pull a `Download link ... : <url>` out of a get_file render. */\nfunction parseDownloadUrl(text: string): string | undefined {\n const m = text.match(/Download link[^:]*:\\s*(\\S+)/);\n return m ? m[1] : undefined;\n}\n\n/**\n * Parse `renderAskDocs` output: blocks separated by a blank line, each a\n * `[n] file · scope · score X.XXX` citation line then the passage text. An empty\n * result is the calm \"No relevant passages...\" sentence -> zero passages.\n */\nfunction parseAskPassages(text: string): AskPassage[] {\n if (/^No relevant passages/i.test(text.trimStart())) return [];\n const blocks = text.split(\"\\n\\n\");\n const out: AskPassage[] = [];\n for (const block of blocks) {\n const nl = block.indexOf(\"\\n\");\n const citation = nl === -1 ? block : block.slice(0, nl);\n const body = nl === -1 ? \"\" : block.slice(nl + 1);\n const m = citation.match(/^\\[(\\d+)\\]\\s*(.*)$/);\n if (!m) continue;\n const index = Number(m[1]);\n const rest = m[2];\n // rest = `file · scope · score N.NNN`\n const parts = rest.split(\" · \");\n const passage: AskPassage = { index, text: body };\n if (parts[0]) passage.file = parts[0].trim();\n if (parts[1]) passage.scope = parts[1].trim();\n const scoreM = rest.match(/score\\s+([\\d.]+)/);\n if (scoreM) passage.score = Number(scoreM[1]);\n out.push(passage);\n }\n return out;\n}\n\n/** Parse `renderSharedContext` LIST output (lines `- who (from: grantId)`). */\nfunction parseSharedList(text: string): SharedContextResult {\n if (/^No one has shared/i.test(text.trimStart())) {\n return { mode: \"list\", shares: [], composite: null, text };\n }\n const shares: SharedContextEntry[] = [];\n for (const line of text.split(\"\\n\")) {\n const m = line.match(/^-\\s*(.*?)\\s*\\(from:\\s*([^)]+)\\)\\s*$/);\n if (m) shares.push({ ownerLabel: m[1].trim(), grantId: m[2].trim() });\n }\n return { mode: \"list\", shares, composite: null, text };\n}\n\n/** Parse `renderSharedContext` READ output (`Shared context from X:\\n\\n<text>`). */\nfunction parseSharedRead(text: string): SharedContextResult {\n if (/not available/i.test(text)) {\n return { mode: \"read\", shares: [], composite: null, text };\n }\n const m = text.match(/^Shared context from [^:]*:\\n\\n([\\s\\S]*)$/);\n const composite = m ? m[1] : text;\n return { mode: \"read\", shares: [], composite, text };\n}\n"]}
|
package/dist/react.cjs
CHANGED
|
@@ -141,29 +141,6 @@ function memoryStorage() {
|
|
|
141
141
|
remove: (k) => void map.delete(k)
|
|
142
142
|
};
|
|
143
143
|
}
|
|
144
|
-
function webStorage(store) {
|
|
145
|
-
return {
|
|
146
|
-
get: (k) => {
|
|
147
|
-
try {
|
|
148
|
-
return store.getItem(k);
|
|
149
|
-
} catch {
|
|
150
|
-
return null;
|
|
151
|
-
}
|
|
152
|
-
},
|
|
153
|
-
set: (k, v) => {
|
|
154
|
-
try {
|
|
155
|
-
store.setItem(k, v);
|
|
156
|
-
} catch {
|
|
157
|
-
}
|
|
158
|
-
},
|
|
159
|
-
remove: (k) => {
|
|
160
|
-
try {
|
|
161
|
-
store.removeItem(k);
|
|
162
|
-
} catch {
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
};
|
|
166
|
-
}
|
|
167
144
|
function resolveStorage(opt) {
|
|
168
145
|
if (opt === null) {
|
|
169
146
|
return { get: () => null, set: () => {
|
|
@@ -171,18 +148,6 @@ function resolveStorage(opt) {
|
|
|
171
148
|
} };
|
|
172
149
|
}
|
|
173
150
|
if (opt) return opt;
|
|
174
|
-
try {
|
|
175
|
-
if (typeof globalThis !== "undefined") {
|
|
176
|
-
const ls = globalThis.localStorage;
|
|
177
|
-
if (ls) {
|
|
178
|
-
const probe = "__umc_probe__";
|
|
179
|
-
ls.setItem(probe, "1");
|
|
180
|
-
ls.removeItem(probe);
|
|
181
|
-
return webStorage(ls);
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
} catch {
|
|
185
|
-
}
|
|
186
151
|
return memoryStorage();
|
|
187
152
|
}
|
|
188
153
|
|
package/dist/react.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/jsonrpc.ts","../src/machine.ts","../src/storage.ts","../src/transport.ts","../src/client.ts","../src/react.tsx"],"names":["React","isConnected"],"mappings":"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","file":"react.cjs","sourcesContent":["// JSON-RPC 2.0 framing for the membrane MCP wire, plus the SDK error taxonomy.\n//\n// The membrane speaks hand-rolled JSON-RPC over Streamable HTTP. The SDK only\n// ever sends `initialize` and `tools/call`. A tools/call comes back as a RESULT\n// shaped `{ content: [{ type:\"text\", text }], isError }`; a protocol-level\n// failure comes back as a JSON-RPC `error` object. This module owns the framing\n// + the parsing helpers; the wrappers in client.ts decode the text content.\n\n/** A JSON-RPC request envelope. */\nexport interface JsonRpcRequest {\n jsonrpc: \"2.0\";\n id: number;\n method: string;\n params?: unknown;\n}\n\n/** A JSON-RPC error object. */\nexport interface JsonRpcErrorObject {\n code: number;\n message: string;\n data?: unknown;\n}\n\n/** A parsed JSON-RPC response (success xor error). */\nexport interface JsonRpcResponse {\n jsonrpc: \"2.0\";\n id: number | null;\n result?: unknown;\n error?: JsonRpcErrorObject;\n}\n\n/** The MCP tools/call result shape (`content` blocks + an error flag). */\nexport interface ToolResult {\n content: Array<{ type: string; text?: string }>;\n isError?: boolean;\n}\n\n/** Base class for every error the SDK throws, so callers can `catch (e)`. */\nexport class UseMyContextError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"UseMyContextError\";\n // Restore the prototype chain (TS target < ES2015 / transpiled extends).\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\n/** Thrown when a tool wrapper is called before a successful `connect()`. */\nexport class NotConnectedError extends UseMyContextError {\n constructor(message = \"Not connected. Call connect({ token }) first.\") {\n super(message);\n this.name = \"NotConnectedError\";\n }\n}\n\n/**\n * Thrown when the membrane rejects the token (HTTP 401 + WWW-Authenticate).\n * The client also transitions to `expired` so the host can re-connect.\n */\nexport class TokenExpiredError extends UseMyContextError {\n /** The raw `WWW-Authenticate` header, when the server sent one. */\n readonly wwwAuthenticate?: string;\n constructor(message = \"The connection token was rejected (expired or revoked).\", wwwAuthenticate?: string) {\n super(message);\n this.name = \"TokenExpiredError\";\n this.wwwAuthenticate = wwwAuthenticate;\n }\n}\n\n/** Thrown when a tool call is refused for lack of scope (membrane -32604). */\nexport class ScopeDeniedError extends UseMyContextError {\n readonly code = -32604;\n constructor(message: string) {\n super(message);\n this.name = \"ScopeDeniedError\";\n }\n}\n\n/** Thrown for a JSON-RPC protocol error or a tool-level `isError` result. */\nexport class ToolCallError extends UseMyContextError {\n /** The JSON-RPC error code, when the failure was a protocol error. */\n readonly code?: number;\n constructor(message: string, code?: number) {\n super(message);\n this.name = \"ToolCallError\";\n this.code = code;\n }\n}\n\n/** Thrown for transport/parse failures (network down, non-JSON body, ...). */\nexport class TransportError extends UseMyContextError {\n constructor(message: string) {\n super(message);\n this.name = \"TransportError\";\n }\n}\n\nlet nextId = 1;\n\n/** Build an `initialize` request (the connect handshake). */\nexport function initializeRequest(): JsonRpcRequest {\n return {\n jsonrpc: \"2.0\",\n id: nextId++,\n method: \"initialize\",\n params: {\n protocolVersion: \"2025-06-18\",\n capabilities: {},\n clientInfo: { name: \"usemycontext-sdk\", version: \"0.1.0\" },\n },\n };\n}\n\n/** Build a `tools/call` request for a tool name + arguments. */\nexport function toolCallRequest(name: string, args: Record<string, unknown>): JsonRpcRequest {\n return {\n jsonrpc: \"2.0\",\n id: nextId++,\n method: \"tools/call\",\n params: { name, arguments: args },\n };\n}\n\n/**\n * Narrow an unknown body to a JSON-RPC response. Throws TransportError when the\n * body is not a well-formed JSON-RPC 2.0 envelope (a defensive guard against a\n * misbehaving transport or an HTML error page).\n */\nexport function asJsonRpcResponse(body: unknown): JsonRpcResponse {\n if (body === null || typeof body !== \"object\") {\n throw new TransportError(\"Membrane returned a non-object response body.\");\n }\n const b = body as Record<string, unknown>;\n if (b.jsonrpc !== \"2.0\") {\n throw new TransportError(\"Membrane response was not JSON-RPC 2.0.\");\n }\n return b as unknown as JsonRpcResponse;\n}\n\n/** True iff a JSON-RPC error code denotes a missing-scope denial (-32604). */\nexport function isScopeDenied(code: number): boolean {\n return code === -32604;\n}\n\n/**\n * Pull the single text block out of a tools/call RESULT. The membrane always\n * renders to ONE text content block, so this returns its `text` (or \"\" when a\n * result carried no text block).\n */\nexport function resultText(result: ToolResult): string {\n for (const block of result.content ?? []) {\n if (block.type === \"text\" && typeof block.text === \"string\") return block.text;\n }\n return \"\";\n}\n","// The connect state machine - a PURE reducer (no IO, no timers, no `this`).\n//\n// States (ConnectState):\n// idle -> connecting -> connected\n// \\-> declined (user/host refused; v2 OAuth path)\n// \\-> error (network/transport/parse failure)\n// connected -> expired (membrane 401 mid-session)\n// connected -> disconnected (explicit disconnect)\n// <any> -> disconnected (disconnect is always reachable)\n// <terminal>-> connecting (a fresh connect() retries)\n//\n// The reducer is the single source of truth for legality: an event that does\n// not apply to the current state is a NO-OP (returns the same state), so the\n// client can fire events without guarding, and tests can assert every legal AND\n// illegal transition deterministically.\n\nimport type { ConnectState } from \"./types.js\";\n\n/** The events that drive the machine. */\nexport type ConnectEvent =\n | { type: \"CONNECT\" } // begin a connect attempt\n | { type: \"CONNECT_SUCCESS\" } // membrane accepted the token\n | { type: \"CONNECT_DECLINED\" } // user/host refused (v2 OAuth path)\n | { type: \"TOKEN_EXPIRED\" } // membrane 401 (expired/revoked)\n | { type: \"ERROR\" } // a non-auth failure\n | { type: \"DISCONNECT\" }; // explicit disconnect / token cleared\n\n/** The initial state of a fresh client. */\nexport const INITIAL_STATE: ConnectState = \"idle\";\n\n/**\n * The pure transition function. Returns the NEXT state for `(state, event)`, or\n * the SAME state when the event is illegal in that state (a no-op).\n */\nexport function reduce(state: ConnectState, event: ConnectEvent): ConnectState {\n switch (event.type) {\n case \"CONNECT\":\n // A connect attempt is legal from any NON-in-flight state: a fresh client,\n // a terminal/failed state (retry), or an already-connected client\n // (re-connect with a new token). It is a no-op only while already\n // connecting (a second concurrent connect does nothing).\n return state === \"connecting\" ? state : \"connecting\";\n\n case \"CONNECT_SUCCESS\":\n // Only a connect IN FLIGHT can succeed. Any other state ignores it (a\n // stale/duplicate success after disconnect must not resurrect the client).\n return state === \"connecting\" ? \"connected\" : state;\n\n case \"CONNECT_DECLINED\":\n // Only a connect in flight can be declined.\n return state === \"connecting\" ? \"declined\" : state;\n\n case \"ERROR\":\n // A connect in flight can fail with a non-auth error. (A wrapper-call\n // failure while `connected` does NOT change the connect state - the\n // connection is still valid - so ERROR is a no-op when connected.)\n return state === \"connecting\" ? \"error\" : state;\n\n case \"TOKEN_EXPIRED\":\n // The membrane rejected the token. Legal from `connecting` (the token was\n // bad at connect time) or `connected` (it expired/was revoked mid-session).\n return state === \"connecting\" || state === \"connected\" ? \"expired\" : state;\n\n case \"DISCONNECT\":\n // Disconnect is ALWAYS reachable and idempotent: it moves any state to\n // `disconnected` (a no-op only when already there).\n return state === \"disconnected\" ? state : \"disconnected\";\n\n default: {\n // Exhaustiveness: a new event type must be handled above.\n const _never: never = event;\n return state;\n }\n }\n}\n\n/** Every state the machine can occupy (for reachability assertions). */\nexport const ALL_STATES: readonly ConnectState[] = [\n \"idle\",\n \"connecting\",\n \"connected\",\n \"declined\",\n \"expired\",\n \"error\",\n \"disconnected\",\n] as const;\n\n/** Whether the 7 tool wrappers may be called in this state. */\nexport function isConnected(state: ConnectState): boolean {\n return state === \"connected\";\n}\n","// Token persistence. Defaults to `localStorage` when present (the browser host\n// page), falls back to an in-memory store (SSR / Node / tests), and can be\n// disabled entirely (pass `storage: null` to the client).\n\nimport type { StorageAdapter } from \"./types.js\";\n\n/** The default storage key the token is persisted under. */\nexport const DEFAULT_STORAGE_KEY = \"usemycontext.token\";\n\n/** An in-memory storage adapter (SSR-safe; the fallback when no localStorage). */\nexport function memoryStorage(): StorageAdapter {\n const map = new Map<string, string>();\n return {\n get: (k) => (map.has(k) ? (map.get(k) as string) : null),\n set: (k, v) => void map.set(k, v),\n remove: (k) => void map.delete(k),\n };\n}\n\n/** Wrap a Web Storage (localStorage/sessionStorage) as a StorageAdapter. */\nexport function webStorage(store: Storage): StorageAdapter {\n return {\n get: (k) => {\n try {\n return store.getItem(k);\n } catch {\n return null;\n }\n },\n set: (k, v) => {\n try {\n store.setItem(k, v);\n } catch {\n /* quota / privacy mode - degrade to no-persist, never throw */\n }\n },\n remove: (k) => {\n try {\n store.removeItem(k);\n } catch {\n /* ignore */\n }\n },\n };\n}\n\n/**\n * Resolve the storage adapter to use given the option:\n * - an explicit adapter -> use it;\n * - `null` -> persistence disabled (a no-op adapter);\n * - `undefined` -> localStorage when available, else in-memory.\n */\nexport function resolveStorage(opt: StorageAdapter | null | undefined): StorageAdapter {\n if (opt === null) {\n return { get: () => null, set: () => {}, remove: () => {} };\n }\n if (opt) return opt;\n // Browser: prefer localStorage. Guarded for SSR + privacy-mode throws.\n try {\n if (typeof globalThis !== \"undefined\") {\n const ls = (globalThis as { localStorage?: Storage }).localStorage;\n if (ls) {\n // Probe it - some environments expose a localStorage that throws on use.\n const probe = \"__umc_probe__\";\n ls.setItem(probe, \"1\");\n ls.removeItem(probe);\n return webStorage(ls);\n }\n }\n } catch {\n /* fall through to in-memory */\n }\n return memoryStorage();\n}\n","// The default `fetch`-based transport. Tests inject a mock transport instead, so\n// this module is never exercised by the (zero-network) test suite - it is the\n// production wiring that POSTs one JSON-RPC request to the membrane `/mcp`\n// endpoint with the user's bearer token.\n\nimport type { Transport, TransportResponse } from \"./types.js\";\n\n/** A `fetch`-backed Transport (the default when none is supplied). */\nexport const fetchTransport: Transport = async ({ url, token, body }): Promise<TransportResponse> => {\n const res = await fetch(url, {\n method: \"POST\",\n headers: {\n \"content-type\": \"application/json\",\n accept: \"application/json\",\n authorization: `Bearer ${token}`,\n },\n body: JSON.stringify(body),\n });\n let parsed: unknown = null;\n try {\n parsed = await res.json();\n } catch {\n parsed = null; // non-JSON / empty body (e.g. a 401 with no body)\n }\n return {\n status: res.status,\n body: parsed,\n wwwAuthenticate: res.headers.get(\"www-authenticate\"),\n };\n};\n","// The core client: `useMyContext()` (a framework-free factory) + the 7 tool\n// wrappers. It holds the user's OWN token and calls the membrane exactly like\n// Claude does - same trust model, new client shape. The service stays\n// structurally blind.\n//\n// v1 IS TOKEN-IN ONLY: `connect({ token })`. The full browser-OAuth-in-the-SDK\n// flow (a hosted popup on connect.usemycontext.ai) is v2, gated on the Phase 2\n// CORS landing - deliberately NOT built here.\n\nimport {\n initializeRequest,\n toolCallRequest,\n asJsonRpcResponse,\n resultText,\n isScopeDenied,\n NotConnectedError,\n TokenExpiredError,\n ScopeDeniedError,\n ToolCallError,\n TransportError,\n UseMyContextError,\n type ToolResult,\n} from \"./jsonrpc.js\";\nimport { reduce, INITIAL_STATE, isConnected } from \"./machine.js\";\nimport { resolveStorage, DEFAULT_STORAGE_KEY } from \"./storage.js\";\nimport { fetchTransport } from \"./transport.js\";\nimport type {\n ClientOptions,\n ConnectArgs,\n ConnectState,\n FileMeta,\n ProfileResult,\n AskOptions,\n AskResult,\n AskPassage,\n GetFileResult,\n SuggestUpdateResult,\n SharedContextResult,\n SharedContextEntry,\n StorageAdapter,\n Transport,\n} from \"./types.js\";\n\n/** The production membrane MCP endpoint. */\nexport const DEFAULT_ENDPOINT = \"https://mcp.usemycontext.ai/mcp\";\n\n/** The shape `useMyContext()` returns - the client handle. */\nexport interface UseMyContextClient {\n /** The current connect state. */\n readonly state: ConnectState;\n /** Convenience: true iff `state === \"connected\"`. */\n readonly connected: boolean;\n /** The held token, when connected (else null). */\n readonly token: string | null;\n\n /** Subscribe to state changes. Returns an unsubscribe fn. */\n subscribe(listener: (state: ConnectState) => void): () => void;\n\n /** v1 TOKEN-IN connect: validate the token against the membrane. */\n connect(args: ConnectArgs): Promise<ConnectState>;\n /** Clear the token + persisted storage; -> `disconnected`. */\n disconnect(): void;\n\n // --- the 7 MCP tool wrappers ---\n profile(): Promise<ProfileResult>;\n listFiles(): Promise<FileMeta[]>;\n searchFiles(query: string): Promise<FileMeta[]>;\n getFile(fileId: string): Promise<GetFileResult>;\n ask(query: string, opts?: AskOptions): Promise<AskResult>;\n suggestUpdate(suggestion: string): Promise<SuggestUpdateResult>;\n sharedContext(from?: string): Promise<SharedContextResult>;\n}\n\n/**\n * Create a UseMyContext client. Framework-free: the React hook wraps this.\n * Restores a persisted token (without revalidating) so a returning host page\n * starts `connected`; a stale token surfaces as `expired` on the first call.\n */\nexport function useMyContext(options: ClientOptions = {}): UseMyContextClient {\n const endpoint = options.endpoint ?? DEFAULT_ENDPOINT;\n const transport: Transport = options.transport ?? fetchTransport;\n const storage: StorageAdapter = resolveStorage(options.storage);\n const storageKey = options.storageKey ?? DEFAULT_STORAGE_KEY;\n\n const listeners = new Set<(state: ConnectState) => void>();\n let state: ConnectState = INITIAL_STATE;\n let token: string | null = null;\n\n // Restore a persisted token: a returning page is `connected` optimistically\n // (the membrane is the authority - a stale token -> `expired` on first call).\n const persisted = storage.get(storageKey);\n if (persisted) {\n token = persisted;\n state = \"connected\";\n }\n\n function setState(next: ConnectState): void {\n if (next === state) return;\n state = next;\n options.onStateChange?.(state);\n for (const l of listeners) l(state);\n }\n\n function dispatch(event: Parameters<typeof reduce>[1]): void {\n setState(reduce(state, event));\n }\n\n /** One JSON-RPC round-trip against the membrane with the held token. */\n async function rpc(body: unknown): Promise<unknown> {\n if (!token) throw new NotConnectedError();\n let res;\n try {\n res = await transport({ url: endpoint, token, body });\n } catch (e) {\n throw new TransportError(\n `Transport failed: ${e instanceof Error ? e.message : String(e)}`,\n );\n }\n // A 401 means the token is bad/expired/revoked. Drive the machine to\n // `expired` and throw - the host should re-connect.\n if (res.status === 401) {\n dispatch({ type: \"TOKEN_EXPIRED\" });\n throw new TokenExpiredError(undefined, res.wwwAuthenticate ?? undefined);\n }\n const parsed = asJsonRpcResponse(res.body);\n if (parsed.error) {\n if (isScopeDenied(parsed.error.code)) {\n throw new ScopeDeniedError(parsed.error.message);\n }\n throw new ToolCallError(parsed.error.message, parsed.error.code);\n }\n return parsed.result;\n }\n\n /** A tools/call that returns the single rendered text block. */\n async function callTool(name: string, args: Record<string, unknown>): Promise<string> {\n if (!isConnected(state)) throw new NotConnectedError();\n const result = (await rpc(toolCallRequest(name, args))) as ToolResult;\n if (result.isError) {\n throw new ToolCallError(resultText(result) || `${name} failed.`);\n }\n return resultText(result);\n }\n\n return {\n get state() {\n return state;\n },\n get connected() {\n return state === \"connected\";\n },\n get token() {\n return state === \"connected\" ? token : null;\n },\n\n subscribe(listener) {\n listeners.add(listener);\n return () => void listeners.delete(listener);\n },\n\n async connect({ token: t }: ConnectArgs): Promise<ConnectState> {\n if (typeof t !== \"string\" || t.length === 0) {\n // A bad arg is a developer error, not a state transition.\n throw new UseMyContextConnectArgError();\n }\n dispatch({ type: \"CONNECT\" });\n token = t;\n try {\n const res = await transport({ url: endpoint, token: t, body: initializeRequest() });\n if (res.status === 401) {\n token = null;\n dispatch({ type: \"TOKEN_EXPIRED\" });\n throw new TokenExpiredError(undefined, res.wwwAuthenticate ?? undefined);\n }\n // Validate the handshake came back as a well-formed JSON-RPC result.\n const parsed = asJsonRpcResponse(res.body);\n if (parsed.error) {\n token = null;\n dispatch({ type: \"ERROR\" });\n throw new ToolCallError(parsed.error.message, parsed.error.code);\n }\n dispatch({ type: \"CONNECT_SUCCESS\" });\n if (storage) storage.set(storageKey, t);\n return state;\n } catch (e) {\n token = null;\n // TokenExpiredError already drove the machine to `expired`; any other\n // failure is a non-auth `error`.\n if (!(e instanceof TokenExpiredError)) {\n dispatch({ type: \"ERROR\" });\n if (e instanceof TransportError || e instanceof ToolCallError) throw e;\n throw new TransportError(\n `Connect failed: ${e instanceof Error ? e.message : String(e)}`,\n );\n }\n throw e;\n }\n },\n\n disconnect(): void {\n token = null;\n storage.remove(storageKey);\n dispatch({ type: \"DISCONNECT\" });\n },\n\n // --- profile ---------------------------------------------------------\n async profile(): Promise<ProfileResult> {\n const text = await callTool(\"profile\", {});\n // The membrane serves the compiled composite as plain text, OR (no compile\n // yet) the JSON of `{ facts: [...] }`. Detect the fallback by parsing.\n const facts = tryParseFacts(text);\n if (facts) return { composite: text, facts };\n return { composite: text };\n },\n\n // --- list_files / search_files (JSON array of FileMeta) --------------\n async listFiles(): Promise<FileMeta[]> {\n return parseFileList(await callTool(\"list_files\", {}));\n },\n async searchFiles(query: string): Promise<FileMeta[]> {\n if (typeof query !== \"string\") throw new UseMyContextConnectArgError(\"search query must be a string\");\n return parseFileList(await callTool(\"search_files\", { query }));\n },\n\n // --- get_file --------------------------------------------------------\n async getFile(fileId: string): Promise<GetFileResult> {\n if (typeof fileId !== \"string\" || !fileId) {\n throw new UseMyContextConnectArgError(\"fileId must be a non-empty string\");\n }\n const text = await callTool(\"get_file\", { fileId });\n return { text, downloadUrl: parseDownloadUrl(text) };\n },\n\n // --- ask_docs --------------------------------------------------------\n async ask(query: string, opts: AskOptions = {}): Promise<AskResult> {\n if (typeof query !== \"string\" || !query) {\n throw new UseMyContextConnectArgError(\"ask query must be a non-empty string\");\n }\n const args: Record<string, unknown> = { query };\n if (typeof opts.k === \"number\") args.k = opts.k;\n if (typeof opts.projectId === \"string\") args.projectId = opts.projectId;\n const text = await callTool(\"ask_docs\", args);\n return { passages: parseAskPassages(text), text };\n },\n\n // --- suggest_update (the one write) ----------------------------------\n async suggestUpdate(suggestion: string): Promise<SuggestUpdateResult> {\n if (typeof suggestion !== \"string\" || !suggestion.trim()) {\n throw new UseMyContextConnectArgError(\"suggestion must be a non-empty string\");\n }\n const text = await callTool(\"suggest_update\", { suggestion });\n const m = text.match(/\\(id:\\s*([^)]+)\\)/);\n return { id: m ? m[1].trim() : undefined, text };\n },\n\n // --- shared_context --------------------------------------------------\n async sharedContext(from?: string): Promise<SharedContextResult> {\n const args: Record<string, unknown> = {};\n if (typeof from === \"string\" && from) args.from = from;\n const text = await callTool(\"shared_context\", args);\n return from ? parseSharedRead(text) : parseSharedList(text);\n },\n };\n}\n\n/** Thrown for a bad SDK call argument (a developer error, not a state event). */\nexport class UseMyContextConnectArgError extends UseMyContextError {\n constructor(message = \"connect() requires a non-empty token string.\") {\n super(message);\n this.name = \"UseMyContextConnectArgError\";\n }\n}\n\n// --- parsers (decode the membrane's RENDERED text back to typed shapes) ---\n\n/** Parse `profile`'s JSON fallback (`{facts:[...]}`); null when it's prose. */\nfunction tryParseFacts(text: string): string[] | undefined {\n const trimmed = text.trimStart();\n if (!trimmed.startsWith(\"{\")) return undefined;\n try {\n const obj = JSON.parse(text) as { facts?: unknown };\n if (Array.isArray(obj.facts)) return obj.facts.filter((f): f is string => typeof f === \"string\");\n } catch {\n /* prose composite that happens to start with \"{\" - treat as composite */\n }\n return undefined;\n}\n\n/** Parse a list/search JSON array into FileMeta[]. */\nfunction parseFileList(text: string): FileMeta[] {\n try {\n const arr = JSON.parse(text) as unknown;\n if (!Array.isArray(arr)) return [];\n return arr.map((r) => {\n const o = (r ?? {}) as Record<string, unknown>;\n return {\n id: String(o.id ?? \"\"),\n name: String(o.name ?? \"\"),\n size: typeof o.size === \"number\" ? o.size : 0,\n contentType: String(o.contentType ?? \"\"),\n modified: String(o.modified ?? \"\"),\n ...(typeof o.status === \"string\" ? { status: o.status as FileMeta[\"status\"] } : {}),\n };\n });\n } catch {\n return [];\n }\n}\n\n/** Pull a `Download link ... : <url>` out of a get_file render. */\nfunction parseDownloadUrl(text: string): string | undefined {\n const m = text.match(/Download link[^:]*:\\s*(\\S+)/);\n return m ? m[1] : undefined;\n}\n\n/**\n * Parse `renderAskDocs` output: blocks separated by a blank line, each a\n * `[n] file · scope · score X.XXX` citation line then the passage text. An empty\n * result is the calm \"No relevant passages...\" sentence -> zero passages.\n */\nfunction parseAskPassages(text: string): AskPassage[] {\n if (/^No relevant passages/i.test(text.trimStart())) return [];\n const blocks = text.split(\"\\n\\n\");\n const out: AskPassage[] = [];\n for (const block of blocks) {\n const nl = block.indexOf(\"\\n\");\n const citation = nl === -1 ? block : block.slice(0, nl);\n const body = nl === -1 ? \"\" : block.slice(nl + 1);\n const m = citation.match(/^\\[(\\d+)\\]\\s*(.*)$/);\n if (!m) continue;\n const index = Number(m[1]);\n const rest = m[2];\n // rest = `file · scope · score N.NNN`\n const parts = rest.split(\" · \");\n const passage: AskPassage = { index, text: body };\n if (parts[0]) passage.file = parts[0].trim();\n if (parts[1]) passage.scope = parts[1].trim();\n const scoreM = rest.match(/score\\s+([\\d.]+)/);\n if (scoreM) passage.score = Number(scoreM[1]);\n out.push(passage);\n }\n return out;\n}\n\n/** Parse `renderSharedContext` LIST output (lines `- who (from: grantId)`). */\nfunction parseSharedList(text: string): SharedContextResult {\n if (/^No one has shared/i.test(text.trimStart())) {\n return { mode: \"list\", shares: [], composite: null, text };\n }\n const shares: SharedContextEntry[] = [];\n for (const line of text.split(\"\\n\")) {\n const m = line.match(/^-\\s*(.*?)\\s*\\(from:\\s*([^)]+)\\)\\s*$/);\n if (m) shares.push({ ownerLabel: m[1].trim(), grantId: m[2].trim() });\n }\n return { mode: \"list\", shares, composite: null, text };\n}\n\n/** Parse `renderSharedContext` READ output (`Shared context from X:\\n\\n<text>`). */\nfunction parseSharedRead(text: string): SharedContextResult {\n if (/not available/i.test(text)) {\n return { mode: \"read\", shares: [], composite: null, text };\n }\n const m = text.match(/^Shared context from [^:]*:\\n\\n([\\s\\S]*)$/);\n const composite = m ? m[1] : text;\n return { mode: \"read\", shares: [], composite, text };\n}\n","// The React surface: `useMyContextReact()` (a hook over the core client) and the\n// zero-config `<ConnectMyContext />` drop-in.\n//\n// React is an OPTIONAL peer dependency. This module lives behind the `./react`\n// export so importing the core `usemycontext` entry never pulls React in; tsup\n// marks `react` external so it is never bundled.\n\nimport * as React from \"react\";\nimport { useMyContext, type UseMyContextClient } from \"./client.js\";\nimport type { ClientOptions, ConnectState, ConnectArgs } from \"./types.js\";\n\n/** What the React hook returns: the live state + the client's bound methods. */\nexport interface UseMyContextReactValue {\n /** The current connect state (re-renders on change). */\n state: ConnectState;\n /** Convenience: true iff `state === \"connected\"`. */\n connected: boolean;\n /** The held token when connected, else null. */\n token: string | null;\n /** The underlying framework-free client (the 7 wrappers live here). */\n client: UseMyContextClient;\n /** v1 TOKEN-IN connect. */\n connect: (args: ConnectArgs) => Promise<ConnectState>;\n /** Clear the token; -> `disconnected`. */\n disconnect: () => void;\n}\n\n/**\n * The React hook. Creates ONE stable client per component instance and\n * subscribes to its state so the component re-renders on every transition.\n */\nexport function useMyContextReact(options: ClientOptions = {}): UseMyContextReactValue {\n // One stable client for the component's lifetime. options are read once on\n // first render (the typical usage passes a constant); a changing endpoint\n // mid-mount is out of v1 scope.\n const clientRef = React.useRef<UseMyContextClient | null>(null);\n if (clientRef.current === null) {\n clientRef.current = useMyContext(options);\n }\n const client = clientRef.current;\n\n const [state, setState] = React.useState<ConnectState>(client.state);\n\n React.useEffect(() => {\n // Subscribe AND sync once, in case the state changed between create + effect.\n setState(client.state);\n const unsub = client.subscribe(setState);\n return unsub;\n }, [client]);\n\n const connect = React.useCallback((args: ConnectArgs) => client.connect(args), [client]);\n const disconnect = React.useCallback(() => client.disconnect(), [client]);\n\n return {\n state,\n connected: state === \"connected\",\n token: client.token,\n client,\n connect,\n disconnect,\n };\n}\n\n/** Props for the drop-in button. */\nexport interface ConnectMyContextProps {\n /**\n * v1 is TOKEN-IN: supply the user's token (the full browser-OAuth popup is\n * v2). When given, the button calls `connect({ token })` on click.\n */\n token?: string;\n /** Forwarded to the underlying client (endpoint / transport / storage). */\n options?: ClientOptions;\n /** Called after a successful connect. */\n onConnect?: (state: ConnectState) => void;\n /** Called when a connect fails. */\n onError?: (error: unknown) => void;\n /** Override the button label per state. */\n label?: Partial<Record<ConnectState, string>>;\n /** Extra class name(s) for the button. */\n className?: string;\n}\n\nconst DEFAULT_LABELS: Record<ConnectState, string> = {\n idle: \"Connect my context\",\n connecting: \"Connecting...\",\n connected: \"Connected\",\n declined: \"Connect my context\",\n expired: \"Reconnect my context\",\n error: \"Retry connect\",\n disconnected: \"Connect my context\",\n};\n\n/**\n * A zero-config connect button. Renders a single <button> whose label tracks the\n * connect state; clicking it runs the v1 token-in connect. Unstyled beyond a\n * stable class name (`umc-connect-button`) so the host owns the look.\n */\nexport function ConnectMyContext(props: ConnectMyContextProps): React.ReactElement {\n const { token, options, onConnect, onError, label, className } = props;\n const { state, connect, disconnect } = useMyContextReact(options);\n\n const text = (label && label[state]) || DEFAULT_LABELS[state];\n const busy = state === \"connecting\";\n const isConnected = state === \"connected\";\n\n const onClick = React.useCallback(async () => {\n if (isConnected) {\n disconnect();\n return;\n }\n if (!token) {\n onError?.(new Error(\"ConnectMyContext: no `token` prop (v1 is token-in only).\"));\n return;\n }\n try {\n const next = await connect({ token });\n onConnect?.(next);\n } catch (e) {\n onError?.(e);\n }\n }, [isConnected, disconnect, token, connect, onConnect, onError]);\n\n return React.createElement(\n \"button\",\n {\n type: \"button\",\n className: [\"umc-connect-button\", className].filter(Boolean).join(\" \"),\n \"data-umc-state\": state,\n disabled: busy,\n \"aria-busy\": busy || undefined,\n onClick,\n },\n isConnected ? \"Disconnect\" : text,\n );\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/jsonrpc.ts","../src/machine.ts","../src/storage.ts","../src/transport.ts","../src/client.ts","../src/react.tsx"],"names":["React","isConnected"],"mappings":"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","file":"react.cjs","sourcesContent":["// JSON-RPC 2.0 framing for the membrane MCP wire, plus the SDK error taxonomy.\n//\n// The membrane speaks hand-rolled JSON-RPC over Streamable HTTP. The SDK only\n// ever sends `initialize` and `tools/call`. A tools/call comes back as a RESULT\n// shaped `{ content: [{ type:\"text\", text }], isError }`; a protocol-level\n// failure comes back as a JSON-RPC `error` object. This module owns the framing\n// + the parsing helpers; the wrappers in client.ts decode the text content.\n\n/** A JSON-RPC request envelope. */\nexport interface JsonRpcRequest {\n jsonrpc: \"2.0\";\n id: number;\n method: string;\n params?: unknown;\n}\n\n/** A JSON-RPC error object. */\nexport interface JsonRpcErrorObject {\n code: number;\n message: string;\n data?: unknown;\n}\n\n/** A parsed JSON-RPC response (success xor error). */\nexport interface JsonRpcResponse {\n jsonrpc: \"2.0\";\n id: number | null;\n result?: unknown;\n error?: JsonRpcErrorObject;\n}\n\n/** The MCP tools/call result shape (`content` blocks + an error flag). */\nexport interface ToolResult {\n content: Array<{ type: string; text?: string }>;\n isError?: boolean;\n}\n\n/** Base class for every error the SDK throws, so callers can `catch (e)`. */\nexport class UseMyContextError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"UseMyContextError\";\n // Restore the prototype chain (TS target < ES2015 / transpiled extends).\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\n/** Thrown when a tool wrapper is called before a successful `connect()`. */\nexport class NotConnectedError extends UseMyContextError {\n constructor(message = \"Not connected. Call connect({ token }) first.\") {\n super(message);\n this.name = \"NotConnectedError\";\n }\n}\n\n/**\n * Thrown when the membrane rejects the token (HTTP 401 + WWW-Authenticate).\n * The client also transitions to `expired` so the host can re-connect.\n */\nexport class TokenExpiredError extends UseMyContextError {\n /** The raw `WWW-Authenticate` header, when the server sent one. */\n readonly wwwAuthenticate?: string;\n constructor(message = \"The connection token was rejected (expired or revoked).\", wwwAuthenticate?: string) {\n super(message);\n this.name = \"TokenExpiredError\";\n this.wwwAuthenticate = wwwAuthenticate;\n }\n}\n\n/** Thrown when a tool call is refused for lack of scope (membrane -32604). */\nexport class ScopeDeniedError extends UseMyContextError {\n readonly code = -32604;\n constructor(message: string) {\n super(message);\n this.name = \"ScopeDeniedError\";\n }\n}\n\n/** Thrown for a JSON-RPC protocol error or a tool-level `isError` result. */\nexport class ToolCallError extends UseMyContextError {\n /** The JSON-RPC error code, when the failure was a protocol error. */\n readonly code?: number;\n constructor(message: string, code?: number) {\n super(message);\n this.name = \"ToolCallError\";\n this.code = code;\n }\n}\n\n/** Thrown for transport/parse failures (network down, non-JSON body, ...). */\nexport class TransportError extends UseMyContextError {\n constructor(message: string) {\n super(message);\n this.name = \"TransportError\";\n }\n}\n\nlet nextId = 1;\n\n/** Build an `initialize` request (the connect handshake). */\nexport function initializeRequest(): JsonRpcRequest {\n return {\n jsonrpc: \"2.0\",\n id: nextId++,\n method: \"initialize\",\n params: {\n protocolVersion: \"2025-06-18\",\n capabilities: {},\n clientInfo: { name: \"usemycontext-sdk\", version: \"0.1.0\" },\n },\n };\n}\n\n/** Build a `tools/call` request for a tool name + arguments. */\nexport function toolCallRequest(name: string, args: Record<string, unknown>): JsonRpcRequest {\n return {\n jsonrpc: \"2.0\",\n id: nextId++,\n method: \"tools/call\",\n params: { name, arguments: args },\n };\n}\n\n/**\n * Narrow an unknown body to a JSON-RPC response. Throws TransportError when the\n * body is not a well-formed JSON-RPC 2.0 envelope (a defensive guard against a\n * misbehaving transport or an HTML error page).\n */\nexport function asJsonRpcResponse(body: unknown): JsonRpcResponse {\n if (body === null || typeof body !== \"object\") {\n throw new TransportError(\"Membrane returned a non-object response body.\");\n }\n const b = body as Record<string, unknown>;\n if (b.jsonrpc !== \"2.0\") {\n throw new TransportError(\"Membrane response was not JSON-RPC 2.0.\");\n }\n return b as unknown as JsonRpcResponse;\n}\n\n/** True iff a JSON-RPC error code denotes a missing-scope denial (-32604). */\nexport function isScopeDenied(code: number): boolean {\n return code === -32604;\n}\n\n/**\n * Pull the single text block out of a tools/call RESULT. The membrane always\n * renders to ONE text content block, so this returns its `text` (or \"\" when a\n * result carried no text block).\n */\nexport function resultText(result: ToolResult): string {\n for (const block of result.content ?? []) {\n if (block.type === \"text\" && typeof block.text === \"string\") return block.text;\n }\n return \"\";\n}\n","// The connect state machine - a PURE reducer (no IO, no timers, no `this`).\n//\n// States (ConnectState):\n// idle -> connecting -> connected\n// \\-> declined (user/host refused; v2 OAuth path)\n// \\-> error (network/transport/parse failure)\n// connected -> expired (membrane 401 mid-session)\n// connected -> disconnected (explicit disconnect)\n// <any> -> disconnected (disconnect is always reachable)\n// <terminal>-> connecting (a fresh connect() retries)\n//\n// The reducer is the single source of truth for legality: an event that does\n// not apply to the current state is a NO-OP (returns the same state), so the\n// client can fire events without guarding, and tests can assert every legal AND\n// illegal transition deterministically.\n\nimport type { ConnectState } from \"./types.js\";\n\n/** The events that drive the machine. */\nexport type ConnectEvent =\n | { type: \"CONNECT\" } // begin a connect attempt\n | { type: \"CONNECT_SUCCESS\" } // membrane accepted the token\n | { type: \"CONNECT_DECLINED\" } // user/host refused (v2 OAuth path)\n | { type: \"TOKEN_EXPIRED\" } // membrane 401 (expired/revoked)\n | { type: \"ERROR\" } // a non-auth failure\n | { type: \"DISCONNECT\" }; // explicit disconnect / token cleared\n\n/** The initial state of a fresh client. */\nexport const INITIAL_STATE: ConnectState = \"idle\";\n\n/**\n * The pure transition function. Returns the NEXT state for `(state, event)`, or\n * the SAME state when the event is illegal in that state (a no-op).\n */\nexport function reduce(state: ConnectState, event: ConnectEvent): ConnectState {\n switch (event.type) {\n case \"CONNECT\":\n // A connect attempt is legal from any NON-in-flight state: a fresh client,\n // a terminal/failed state (retry), or an already-connected client\n // (re-connect with a new token). It is a no-op only while already\n // connecting (a second concurrent connect does nothing).\n return state === \"connecting\" ? state : \"connecting\";\n\n case \"CONNECT_SUCCESS\":\n // Only a connect IN FLIGHT can succeed. Any other state ignores it (a\n // stale/duplicate success after disconnect must not resurrect the client).\n return state === \"connecting\" ? \"connected\" : state;\n\n case \"CONNECT_DECLINED\":\n // Only a connect in flight can be declined.\n return state === \"connecting\" ? \"declined\" : state;\n\n case \"ERROR\":\n // A connect in flight can fail with a non-auth error. (A wrapper-call\n // failure while `connected` does NOT change the connect state - the\n // connection is still valid - so ERROR is a no-op when connected.)\n return state === \"connecting\" ? \"error\" : state;\n\n case \"TOKEN_EXPIRED\":\n // The membrane rejected the token. Legal from `connecting` (the token was\n // bad at connect time) or `connected` (it expired/was revoked mid-session).\n return state === \"connecting\" || state === \"connected\" ? \"expired\" : state;\n\n case \"DISCONNECT\":\n // Disconnect is ALWAYS reachable and idempotent: it moves any state to\n // `disconnected` (a no-op only when already there).\n return state === \"disconnected\" ? state : \"disconnected\";\n\n default: {\n // Exhaustiveness: a new event type must be handled above.\n const _never: never = event;\n return state;\n }\n }\n}\n\n/** Every state the machine can occupy (for reachability assertions). */\nexport const ALL_STATES: readonly ConnectState[] = [\n \"idle\",\n \"connecting\",\n \"connected\",\n \"declined\",\n \"expired\",\n \"error\",\n \"disconnected\",\n] as const;\n\n/** Whether the 7 tool wrappers may be called in this state. */\nexport function isConnected(state: ConnectState): boolean {\n return state === \"connected\";\n}\n","// Token persistence. SAFE BY DEFAULT: persistence is in-memory only, so the\n// token NEVER touches `localStorage` unless the host page opts in explicitly\n// (pass `storage: webStorage(localStorage)`). The v1 token-in credential is the\n// user's long-lived session JWT - writing it to `localStorage` would expose a\n// ~decade-long key to any script on the host page (one XSS = full context\n// theft), which the threat model forbids. So the default is memory; opt IN to\n// cross-reload persistence knowingly, never opt out. Pass `storage: null` to\n// disable persistence entirely (a no-op store).\n\nimport type { StorageAdapter } from \"./types.js\";\n\n/** The default storage key the token is persisted under. */\nexport const DEFAULT_STORAGE_KEY = \"usemycontext.token\";\n\n/** An in-memory storage adapter (SSR-safe; the DEFAULT - token never leaves JS memory). */\nexport function memoryStorage(): StorageAdapter {\n const map = new Map<string, string>();\n return {\n get: (k) => (map.has(k) ? (map.get(k) as string) : null),\n set: (k, v) => void map.set(k, v),\n remove: (k) => void map.delete(k),\n };\n}\n\n/** Wrap a Web Storage (localStorage/sessionStorage) as a StorageAdapter. */\nexport function webStorage(store: Storage): StorageAdapter {\n return {\n get: (k) => {\n try {\n return store.getItem(k);\n } catch {\n return null;\n }\n },\n set: (k, v) => {\n try {\n store.setItem(k, v);\n } catch {\n /* quota / privacy mode - degrade to no-persist, never throw */\n }\n },\n remove: (k) => {\n try {\n store.removeItem(k);\n } catch {\n /* ignore */\n }\n },\n };\n}\n\n/**\n * Resolve the storage adapter to use given the option:\n * - an explicit adapter -> use it (e.g. `webStorage(localStorage)` to opt IN\n * to cross-reload persistence, knowingly accepting host-page token exposure);\n * - `null` -> persistence disabled (a no-op adapter);\n * - `undefined` (the DEFAULT) -> in-memory. The token NEVER touches\n * `localStorage` unless the caller asks for it. Safe by default.\n */\nexport function resolveStorage(opt: StorageAdapter | null | undefined): StorageAdapter {\n if (opt === null) {\n return { get: () => null, set: () => {}, remove: () => {} };\n }\n if (opt) return opt;\n // DEFAULT: in-memory only. We deliberately do NOT auto-select localStorage -\n // persisting the long-lived session JWT to the host page is an opt-in choice.\n return memoryStorage();\n}\n","// The default `fetch`-based transport. Tests inject a mock transport instead, so\n// this module is never exercised by the (zero-network) test suite - it is the\n// production wiring that POSTs one JSON-RPC request to the membrane `/mcp`\n// endpoint with the user's bearer token.\n\nimport type { Transport, TransportResponse } from \"./types.js\";\n\n/** A `fetch`-backed Transport (the default when none is supplied). */\nexport const fetchTransport: Transport = async ({ url, token, body }): Promise<TransportResponse> => {\n const res = await fetch(url, {\n method: \"POST\",\n headers: {\n \"content-type\": \"application/json\",\n accept: \"application/json\",\n authorization: `Bearer ${token}`,\n },\n body: JSON.stringify(body),\n });\n let parsed: unknown = null;\n try {\n parsed = await res.json();\n } catch {\n parsed = null; // non-JSON / empty body (e.g. a 401 with no body)\n }\n return {\n status: res.status,\n body: parsed,\n wwwAuthenticate: res.headers.get(\"www-authenticate\"),\n };\n};\n","// The core client: `useMyContext()` (a framework-free factory) + the 7 tool\n// wrappers. It holds the user's OWN token and calls the membrane exactly like\n// Claude does - same trust model, new client shape. The service stays\n// structurally blind.\n//\n// v1 IS TOKEN-IN ONLY: `connect({ token })`. The full browser-OAuth-in-the-SDK\n// flow (a hosted popup on connect.usemycontext.ai) is v2, gated on the Phase 2\n// CORS landing - deliberately NOT built here.\n\nimport {\n initializeRequest,\n toolCallRequest,\n asJsonRpcResponse,\n resultText,\n isScopeDenied,\n NotConnectedError,\n TokenExpiredError,\n ScopeDeniedError,\n ToolCallError,\n TransportError,\n UseMyContextError,\n type ToolResult,\n} from \"./jsonrpc.js\";\nimport { reduce, INITIAL_STATE, isConnected } from \"./machine.js\";\nimport { resolveStorage, DEFAULT_STORAGE_KEY } from \"./storage.js\";\nimport { fetchTransport } from \"./transport.js\";\nimport type {\n ClientOptions,\n ConnectArgs,\n ConnectState,\n FileMeta,\n ProfileResult,\n AskOptions,\n AskResult,\n AskPassage,\n GetFileResult,\n SuggestUpdateResult,\n SharedContextResult,\n SharedContextEntry,\n StorageAdapter,\n Transport,\n} from \"./types.js\";\n\n/** The production membrane MCP endpoint. */\nexport const DEFAULT_ENDPOINT = \"https://mcp.usemycontext.ai/mcp\";\n\n/** The shape `useMyContext()` returns - the client handle. */\nexport interface UseMyContextClient {\n /** The current connect state. */\n readonly state: ConnectState;\n /** Convenience: true iff `state === \"connected\"`. */\n readonly connected: boolean;\n /** The held token, when connected (else null). */\n readonly token: string | null;\n\n /** Subscribe to state changes. Returns an unsubscribe fn. */\n subscribe(listener: (state: ConnectState) => void): () => void;\n\n /** v1 TOKEN-IN connect: validate the token against the membrane. */\n connect(args: ConnectArgs): Promise<ConnectState>;\n /** Clear the token + persisted storage; -> `disconnected`. */\n disconnect(): void;\n\n // --- the 7 MCP tool wrappers ---\n profile(): Promise<ProfileResult>;\n listFiles(): Promise<FileMeta[]>;\n searchFiles(query: string): Promise<FileMeta[]>;\n getFile(fileId: string): Promise<GetFileResult>;\n ask(query: string, opts?: AskOptions): Promise<AskResult>;\n suggestUpdate(suggestion: string): Promise<SuggestUpdateResult>;\n sharedContext(from?: string): Promise<SharedContextResult>;\n}\n\n/**\n * Create a UseMyContext client. Framework-free: the React hook wraps this.\n * Restores a persisted token (without revalidating) so a returning host page\n * starts `connected`; a stale token surfaces as `expired` on the first call.\n */\nexport function useMyContext(options: ClientOptions = {}): UseMyContextClient {\n const endpoint = options.endpoint ?? DEFAULT_ENDPOINT;\n const transport: Transport = options.transport ?? fetchTransport;\n const storage: StorageAdapter = resolveStorage(options.storage);\n const storageKey = options.storageKey ?? DEFAULT_STORAGE_KEY;\n\n const listeners = new Set<(state: ConnectState) => void>();\n let state: ConnectState = INITIAL_STATE;\n let token: string | null = null;\n\n // Restore a persisted token: a returning page is `connected` optimistically\n // (the membrane is the authority - a stale token -> `expired` on first call).\n const persisted = storage.get(storageKey);\n if (persisted) {\n token = persisted;\n state = \"connected\";\n }\n\n function setState(next: ConnectState): void {\n if (next === state) return;\n state = next;\n options.onStateChange?.(state);\n for (const l of listeners) l(state);\n }\n\n function dispatch(event: Parameters<typeof reduce>[1]): void {\n setState(reduce(state, event));\n }\n\n /** One JSON-RPC round-trip against the membrane with the held token. */\n async function rpc(body: unknown): Promise<unknown> {\n if (!token) throw new NotConnectedError();\n let res;\n try {\n res = await transport({ url: endpoint, token, body });\n } catch (e) {\n throw new TransportError(\n `Transport failed: ${e instanceof Error ? e.message : String(e)}`,\n );\n }\n // A 401 means the token is bad/expired/revoked. Drive the machine to\n // `expired` and throw - the host should re-connect.\n if (res.status === 401) {\n dispatch({ type: \"TOKEN_EXPIRED\" });\n throw new TokenExpiredError(undefined, res.wwwAuthenticate ?? undefined);\n }\n const parsed = asJsonRpcResponse(res.body);\n if (parsed.error) {\n if (isScopeDenied(parsed.error.code)) {\n throw new ScopeDeniedError(parsed.error.message);\n }\n throw new ToolCallError(parsed.error.message, parsed.error.code);\n }\n return parsed.result;\n }\n\n /** A tools/call that returns the single rendered text block. */\n async function callTool(name: string, args: Record<string, unknown>): Promise<string> {\n if (!isConnected(state)) throw new NotConnectedError();\n const result = (await rpc(toolCallRequest(name, args))) as ToolResult;\n if (result.isError) {\n throw new ToolCallError(resultText(result) || `${name} failed.`);\n }\n return resultText(result);\n }\n\n return {\n get state() {\n return state;\n },\n get connected() {\n return state === \"connected\";\n },\n get token() {\n return state === \"connected\" ? token : null;\n },\n\n subscribe(listener) {\n listeners.add(listener);\n return () => void listeners.delete(listener);\n },\n\n async connect({ token: t }: ConnectArgs): Promise<ConnectState> {\n if (typeof t !== \"string\" || t.length === 0) {\n // A bad arg is a developer error, not a state transition.\n throw new UseMyContextConnectArgError();\n }\n dispatch({ type: \"CONNECT\" });\n token = t;\n try {\n const res = await transport({ url: endpoint, token: t, body: initializeRequest() });\n if (res.status === 401) {\n token = null;\n dispatch({ type: \"TOKEN_EXPIRED\" });\n throw new TokenExpiredError(undefined, res.wwwAuthenticate ?? undefined);\n }\n // Validate the handshake came back as a well-formed JSON-RPC result.\n const parsed = asJsonRpcResponse(res.body);\n if (parsed.error) {\n token = null;\n dispatch({ type: \"ERROR\" });\n throw new ToolCallError(parsed.error.message, parsed.error.code);\n }\n dispatch({ type: \"CONNECT_SUCCESS\" });\n if (storage) storage.set(storageKey, t);\n return state;\n } catch (e) {\n token = null;\n // TokenExpiredError already drove the machine to `expired`; any other\n // failure is a non-auth `error`.\n if (!(e instanceof TokenExpiredError)) {\n dispatch({ type: \"ERROR\" });\n if (e instanceof TransportError || e instanceof ToolCallError) throw e;\n throw new TransportError(\n `Connect failed: ${e instanceof Error ? e.message : String(e)}`,\n );\n }\n throw e;\n }\n },\n\n disconnect(): void {\n token = null;\n storage.remove(storageKey);\n dispatch({ type: \"DISCONNECT\" });\n },\n\n // --- profile ---------------------------------------------------------\n async profile(): Promise<ProfileResult> {\n const text = await callTool(\"profile\", {});\n // The membrane serves the compiled composite as plain text, OR (no compile\n // yet) the JSON of `{ facts: [...] }`. Detect the fallback by parsing.\n const facts = tryParseFacts(text);\n if (facts) return { composite: text, facts };\n return { composite: text };\n },\n\n // --- list_files / search_files (JSON array of FileMeta) --------------\n async listFiles(): Promise<FileMeta[]> {\n return parseFileList(await callTool(\"list_files\", {}));\n },\n async searchFiles(query: string): Promise<FileMeta[]> {\n if (typeof query !== \"string\") throw new UseMyContextConnectArgError(\"search query must be a string\");\n return parseFileList(await callTool(\"search_files\", { query }));\n },\n\n // --- get_file --------------------------------------------------------\n async getFile(fileId: string): Promise<GetFileResult> {\n if (typeof fileId !== \"string\" || !fileId) {\n throw new UseMyContextConnectArgError(\"fileId must be a non-empty string\");\n }\n const text = await callTool(\"get_file\", { fileId });\n return { text, downloadUrl: parseDownloadUrl(text) };\n },\n\n // --- ask_docs --------------------------------------------------------\n async ask(query: string, opts: AskOptions = {}): Promise<AskResult> {\n if (typeof query !== \"string\" || !query) {\n throw new UseMyContextConnectArgError(\"ask query must be a non-empty string\");\n }\n const args: Record<string, unknown> = { query };\n if (typeof opts.k === \"number\") args.k = opts.k;\n if (typeof opts.projectId === \"string\") args.projectId = opts.projectId;\n const text = await callTool(\"ask_docs\", args);\n return { passages: parseAskPassages(text), text };\n },\n\n // --- suggest_update (the one write) ----------------------------------\n async suggestUpdate(suggestion: string): Promise<SuggestUpdateResult> {\n if (typeof suggestion !== \"string\" || !suggestion.trim()) {\n throw new UseMyContextConnectArgError(\"suggestion must be a non-empty string\");\n }\n const text = await callTool(\"suggest_update\", { suggestion });\n const m = text.match(/\\(id:\\s*([^)]+)\\)/);\n return { id: m ? m[1].trim() : undefined, text };\n },\n\n // --- shared_context --------------------------------------------------\n async sharedContext(from?: string): Promise<SharedContextResult> {\n const args: Record<string, unknown> = {};\n if (typeof from === \"string\" && from) args.from = from;\n const text = await callTool(\"shared_context\", args);\n return from ? parseSharedRead(text) : parseSharedList(text);\n },\n };\n}\n\n/** Thrown for a bad SDK call argument (a developer error, not a state event). */\nexport class UseMyContextConnectArgError extends UseMyContextError {\n constructor(message = \"connect() requires a non-empty token string.\") {\n super(message);\n this.name = \"UseMyContextConnectArgError\";\n }\n}\n\n// --- parsers (decode the membrane's RENDERED text back to typed shapes) ---\n\n/** Parse `profile`'s JSON fallback (`{facts:[...]}`); null when it's prose. */\nfunction tryParseFacts(text: string): string[] | undefined {\n const trimmed = text.trimStart();\n if (!trimmed.startsWith(\"{\")) return undefined;\n try {\n const obj = JSON.parse(text) as { facts?: unknown };\n if (Array.isArray(obj.facts)) return obj.facts.filter((f): f is string => typeof f === \"string\");\n } catch {\n /* prose composite that happens to start with \"{\" - treat as composite */\n }\n return undefined;\n}\n\n/** Parse a list/search JSON array into FileMeta[]. */\nfunction parseFileList(text: string): FileMeta[] {\n try {\n const arr = JSON.parse(text) as unknown;\n if (!Array.isArray(arr)) return [];\n return arr.map((r) => {\n const o = (r ?? {}) as Record<string, unknown>;\n return {\n id: String(o.id ?? \"\"),\n name: String(o.name ?? \"\"),\n size: typeof o.size === \"number\" ? o.size : 0,\n contentType: String(o.contentType ?? \"\"),\n modified: String(o.modified ?? \"\"),\n ...(typeof o.status === \"string\" ? { status: o.status as FileMeta[\"status\"] } : {}),\n };\n });\n } catch {\n return [];\n }\n}\n\n/** Pull a `Download link ... : <url>` out of a get_file render. */\nfunction parseDownloadUrl(text: string): string | undefined {\n const m = text.match(/Download link[^:]*:\\s*(\\S+)/);\n return m ? m[1] : undefined;\n}\n\n/**\n * Parse `renderAskDocs` output: blocks separated by a blank line, each a\n * `[n] file · scope · score X.XXX` citation line then the passage text. An empty\n * result is the calm \"No relevant passages...\" sentence -> zero passages.\n */\nfunction parseAskPassages(text: string): AskPassage[] {\n if (/^No relevant passages/i.test(text.trimStart())) return [];\n const blocks = text.split(\"\\n\\n\");\n const out: AskPassage[] = [];\n for (const block of blocks) {\n const nl = block.indexOf(\"\\n\");\n const citation = nl === -1 ? block : block.slice(0, nl);\n const body = nl === -1 ? \"\" : block.slice(nl + 1);\n const m = citation.match(/^\\[(\\d+)\\]\\s*(.*)$/);\n if (!m) continue;\n const index = Number(m[1]);\n const rest = m[2];\n // rest = `file · scope · score N.NNN`\n const parts = rest.split(\" · \");\n const passage: AskPassage = { index, text: body };\n if (parts[0]) passage.file = parts[0].trim();\n if (parts[1]) passage.scope = parts[1].trim();\n const scoreM = rest.match(/score\\s+([\\d.]+)/);\n if (scoreM) passage.score = Number(scoreM[1]);\n out.push(passage);\n }\n return out;\n}\n\n/** Parse `renderSharedContext` LIST output (lines `- who (from: grantId)`). */\nfunction parseSharedList(text: string): SharedContextResult {\n if (/^No one has shared/i.test(text.trimStart())) {\n return { mode: \"list\", shares: [], composite: null, text };\n }\n const shares: SharedContextEntry[] = [];\n for (const line of text.split(\"\\n\")) {\n const m = line.match(/^-\\s*(.*?)\\s*\\(from:\\s*([^)]+)\\)\\s*$/);\n if (m) shares.push({ ownerLabel: m[1].trim(), grantId: m[2].trim() });\n }\n return { mode: \"list\", shares, composite: null, text };\n}\n\n/** Parse `renderSharedContext` READ output (`Shared context from X:\\n\\n<text>`). */\nfunction parseSharedRead(text: string): SharedContextResult {\n if (/not available/i.test(text)) {\n return { mode: \"read\", shares: [], composite: null, text };\n }\n const m = text.match(/^Shared context from [^:]*:\\n\\n([\\s\\S]*)$/);\n const composite = m ? m[1] : text;\n return { mode: \"read\", shares: [], composite, text };\n}\n","// The React surface: `useMyContextReact()` (a hook over the core client) and the\n// zero-config `<ConnectMyContext />` drop-in.\n//\n// React is an OPTIONAL peer dependency. This module lives behind the `./react`\n// export so importing the core `usemycontext` entry never pulls React in; tsup\n// marks `react` external so it is never bundled.\n\nimport * as React from \"react\";\nimport { useMyContext, type UseMyContextClient } from \"./client.js\";\nimport type { ClientOptions, ConnectState, ConnectArgs } from \"./types.js\";\n\n/** What the React hook returns: the live state + the client's bound methods. */\nexport interface UseMyContextReactValue {\n /** The current connect state (re-renders on change). */\n state: ConnectState;\n /** Convenience: true iff `state === \"connected\"`. */\n connected: boolean;\n /** The held token when connected, else null. */\n token: string | null;\n /** The underlying framework-free client (the 7 wrappers live here). */\n client: UseMyContextClient;\n /** v1 TOKEN-IN connect. */\n connect: (args: ConnectArgs) => Promise<ConnectState>;\n /** Clear the token; -> `disconnected`. */\n disconnect: () => void;\n}\n\n/**\n * The React hook. Creates ONE stable client per component instance and\n * subscribes to its state so the component re-renders on every transition.\n */\nexport function useMyContextReact(options: ClientOptions = {}): UseMyContextReactValue {\n // One stable client for the component's lifetime. options are read once on\n // first render (the typical usage passes a constant); a changing endpoint\n // mid-mount is out of v1 scope.\n const clientRef = React.useRef<UseMyContextClient | null>(null);\n if (clientRef.current === null) {\n clientRef.current = useMyContext(options);\n }\n const client = clientRef.current;\n\n const [state, setState] = React.useState<ConnectState>(client.state);\n\n React.useEffect(() => {\n // Subscribe AND sync once, in case the state changed between create + effect.\n setState(client.state);\n const unsub = client.subscribe(setState);\n return unsub;\n }, [client]);\n\n const connect = React.useCallback((args: ConnectArgs) => client.connect(args), [client]);\n const disconnect = React.useCallback(() => client.disconnect(), [client]);\n\n return {\n state,\n connected: state === \"connected\",\n token: client.token,\n client,\n connect,\n disconnect,\n };\n}\n\n/** Props for the drop-in button. */\nexport interface ConnectMyContextProps {\n /**\n * v1 is TOKEN-IN: supply the user's token (the full browser-OAuth popup is\n * v2). When given, the button calls `connect({ token })` on click.\n */\n token?: string;\n /** Forwarded to the underlying client (endpoint / transport / storage). */\n options?: ClientOptions;\n /** Called after a successful connect. */\n onConnect?: (state: ConnectState) => void;\n /** Called when a connect fails. */\n onError?: (error: unknown) => void;\n /** Override the button label per state. */\n label?: Partial<Record<ConnectState, string>>;\n /** Extra class name(s) for the button. */\n className?: string;\n}\n\nconst DEFAULT_LABELS: Record<ConnectState, string> = {\n idle: \"Connect my context\",\n connecting: \"Connecting...\",\n connected: \"Connected\",\n declined: \"Connect my context\",\n expired: \"Reconnect my context\",\n error: \"Retry connect\",\n disconnected: \"Connect my context\",\n};\n\n/**\n * A zero-config connect button. Renders a single <button> whose label tracks the\n * connect state; clicking it runs the v1 token-in connect. Unstyled beyond a\n * stable class name (`umc-connect-button`) so the host owns the look.\n */\nexport function ConnectMyContext(props: ConnectMyContextProps): React.ReactElement {\n const { token, options, onConnect, onError, label, className } = props;\n const { state, connect, disconnect } = useMyContextReact(options);\n\n const text = (label && label[state]) || DEFAULT_LABELS[state];\n const busy = state === \"connecting\";\n const isConnected = state === \"connected\";\n\n const onClick = React.useCallback(async () => {\n if (isConnected) {\n disconnect();\n return;\n }\n if (!token) {\n onError?.(new Error(\"ConnectMyContext: no `token` prop (v1 is token-in only).\"));\n return;\n }\n try {\n const next = await connect({ token });\n onConnect?.(next);\n } catch (e) {\n onError?.(e);\n }\n }, [isConnected, disconnect, token, connect, onConnect, onError]);\n\n return React.createElement(\n \"button\",\n {\n type: \"button\",\n className: [\"umc-connect-button\", className].filter(Boolean).join(\" \"),\n \"data-umc-state\": state,\n disabled: busy,\n \"aria-busy\": busy || undefined,\n onClick,\n },\n isConnected ? \"Disconnect\" : text,\n );\n}\n"]}
|
package/dist/react.js
CHANGED
|
@@ -119,29 +119,6 @@ function memoryStorage() {
|
|
|
119
119
|
remove: (k) => void map.delete(k)
|
|
120
120
|
};
|
|
121
121
|
}
|
|
122
|
-
function webStorage(store) {
|
|
123
|
-
return {
|
|
124
|
-
get: (k) => {
|
|
125
|
-
try {
|
|
126
|
-
return store.getItem(k);
|
|
127
|
-
} catch {
|
|
128
|
-
return null;
|
|
129
|
-
}
|
|
130
|
-
},
|
|
131
|
-
set: (k, v) => {
|
|
132
|
-
try {
|
|
133
|
-
store.setItem(k, v);
|
|
134
|
-
} catch {
|
|
135
|
-
}
|
|
136
|
-
},
|
|
137
|
-
remove: (k) => {
|
|
138
|
-
try {
|
|
139
|
-
store.removeItem(k);
|
|
140
|
-
} catch {
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
};
|
|
144
|
-
}
|
|
145
122
|
function resolveStorage(opt) {
|
|
146
123
|
if (opt === null) {
|
|
147
124
|
return { get: () => null, set: () => {
|
|
@@ -149,18 +126,6 @@ function resolveStorage(opt) {
|
|
|
149
126
|
} };
|
|
150
127
|
}
|
|
151
128
|
if (opt) return opt;
|
|
152
|
-
try {
|
|
153
|
-
if (typeof globalThis !== "undefined") {
|
|
154
|
-
const ls = globalThis.localStorage;
|
|
155
|
-
if (ls) {
|
|
156
|
-
const probe = "__umc_probe__";
|
|
157
|
-
ls.setItem(probe, "1");
|
|
158
|
-
ls.removeItem(probe);
|
|
159
|
-
return webStorage(ls);
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
} catch {
|
|
163
|
-
}
|
|
164
129
|
return memoryStorage();
|
|
165
130
|
}
|
|
166
131
|
|
package/dist/react.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/jsonrpc.ts","../src/machine.ts","../src/storage.ts","../src/transport.ts","../src/client.ts","../src/react.tsx"],"names":["isConnected"],"mappings":"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","file":"react.js","sourcesContent":["// JSON-RPC 2.0 framing for the membrane MCP wire, plus the SDK error taxonomy.\n//\n// The membrane speaks hand-rolled JSON-RPC over Streamable HTTP. The SDK only\n// ever sends `initialize` and `tools/call`. A tools/call comes back as a RESULT\n// shaped `{ content: [{ type:\"text\", text }], isError }`; a protocol-level\n// failure comes back as a JSON-RPC `error` object. This module owns the framing\n// + the parsing helpers; the wrappers in client.ts decode the text content.\n\n/** A JSON-RPC request envelope. */\nexport interface JsonRpcRequest {\n jsonrpc: \"2.0\";\n id: number;\n method: string;\n params?: unknown;\n}\n\n/** A JSON-RPC error object. */\nexport interface JsonRpcErrorObject {\n code: number;\n message: string;\n data?: unknown;\n}\n\n/** A parsed JSON-RPC response (success xor error). */\nexport interface JsonRpcResponse {\n jsonrpc: \"2.0\";\n id: number | null;\n result?: unknown;\n error?: JsonRpcErrorObject;\n}\n\n/** The MCP tools/call result shape (`content` blocks + an error flag). */\nexport interface ToolResult {\n content: Array<{ type: string; text?: string }>;\n isError?: boolean;\n}\n\n/** Base class for every error the SDK throws, so callers can `catch (e)`. */\nexport class UseMyContextError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"UseMyContextError\";\n // Restore the prototype chain (TS target < ES2015 / transpiled extends).\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\n/** Thrown when a tool wrapper is called before a successful `connect()`. */\nexport class NotConnectedError extends UseMyContextError {\n constructor(message = \"Not connected. Call connect({ token }) first.\") {\n super(message);\n this.name = \"NotConnectedError\";\n }\n}\n\n/**\n * Thrown when the membrane rejects the token (HTTP 401 + WWW-Authenticate).\n * The client also transitions to `expired` so the host can re-connect.\n */\nexport class TokenExpiredError extends UseMyContextError {\n /** The raw `WWW-Authenticate` header, when the server sent one. */\n readonly wwwAuthenticate?: string;\n constructor(message = \"The connection token was rejected (expired or revoked).\", wwwAuthenticate?: string) {\n super(message);\n this.name = \"TokenExpiredError\";\n this.wwwAuthenticate = wwwAuthenticate;\n }\n}\n\n/** Thrown when a tool call is refused for lack of scope (membrane -32604). */\nexport class ScopeDeniedError extends UseMyContextError {\n readonly code = -32604;\n constructor(message: string) {\n super(message);\n this.name = \"ScopeDeniedError\";\n }\n}\n\n/** Thrown for a JSON-RPC protocol error or a tool-level `isError` result. */\nexport class ToolCallError extends UseMyContextError {\n /** The JSON-RPC error code, when the failure was a protocol error. */\n readonly code?: number;\n constructor(message: string, code?: number) {\n super(message);\n this.name = \"ToolCallError\";\n this.code = code;\n }\n}\n\n/** Thrown for transport/parse failures (network down, non-JSON body, ...). */\nexport class TransportError extends UseMyContextError {\n constructor(message: string) {\n super(message);\n this.name = \"TransportError\";\n }\n}\n\nlet nextId = 1;\n\n/** Build an `initialize` request (the connect handshake). */\nexport function initializeRequest(): JsonRpcRequest {\n return {\n jsonrpc: \"2.0\",\n id: nextId++,\n method: \"initialize\",\n params: {\n protocolVersion: \"2025-06-18\",\n capabilities: {},\n clientInfo: { name: \"usemycontext-sdk\", version: \"0.1.0\" },\n },\n };\n}\n\n/** Build a `tools/call` request for a tool name + arguments. */\nexport function toolCallRequest(name: string, args: Record<string, unknown>): JsonRpcRequest {\n return {\n jsonrpc: \"2.0\",\n id: nextId++,\n method: \"tools/call\",\n params: { name, arguments: args },\n };\n}\n\n/**\n * Narrow an unknown body to a JSON-RPC response. Throws TransportError when the\n * body is not a well-formed JSON-RPC 2.0 envelope (a defensive guard against a\n * misbehaving transport or an HTML error page).\n */\nexport function asJsonRpcResponse(body: unknown): JsonRpcResponse {\n if (body === null || typeof body !== \"object\") {\n throw new TransportError(\"Membrane returned a non-object response body.\");\n }\n const b = body as Record<string, unknown>;\n if (b.jsonrpc !== \"2.0\") {\n throw new TransportError(\"Membrane response was not JSON-RPC 2.0.\");\n }\n return b as unknown as JsonRpcResponse;\n}\n\n/** True iff a JSON-RPC error code denotes a missing-scope denial (-32604). */\nexport function isScopeDenied(code: number): boolean {\n return code === -32604;\n}\n\n/**\n * Pull the single text block out of a tools/call RESULT. The membrane always\n * renders to ONE text content block, so this returns its `text` (or \"\" when a\n * result carried no text block).\n */\nexport function resultText(result: ToolResult): string {\n for (const block of result.content ?? []) {\n if (block.type === \"text\" && typeof block.text === \"string\") return block.text;\n }\n return \"\";\n}\n","// The connect state machine - a PURE reducer (no IO, no timers, no `this`).\n//\n// States (ConnectState):\n// idle -> connecting -> connected\n// \\-> declined (user/host refused; v2 OAuth path)\n// \\-> error (network/transport/parse failure)\n// connected -> expired (membrane 401 mid-session)\n// connected -> disconnected (explicit disconnect)\n// <any> -> disconnected (disconnect is always reachable)\n// <terminal>-> connecting (a fresh connect() retries)\n//\n// The reducer is the single source of truth for legality: an event that does\n// not apply to the current state is a NO-OP (returns the same state), so the\n// client can fire events without guarding, and tests can assert every legal AND\n// illegal transition deterministically.\n\nimport type { ConnectState } from \"./types.js\";\n\n/** The events that drive the machine. */\nexport type ConnectEvent =\n | { type: \"CONNECT\" } // begin a connect attempt\n | { type: \"CONNECT_SUCCESS\" } // membrane accepted the token\n | { type: \"CONNECT_DECLINED\" } // user/host refused (v2 OAuth path)\n | { type: \"TOKEN_EXPIRED\" } // membrane 401 (expired/revoked)\n | { type: \"ERROR\" } // a non-auth failure\n | { type: \"DISCONNECT\" }; // explicit disconnect / token cleared\n\n/** The initial state of a fresh client. */\nexport const INITIAL_STATE: ConnectState = \"idle\";\n\n/**\n * The pure transition function. Returns the NEXT state for `(state, event)`, or\n * the SAME state when the event is illegal in that state (a no-op).\n */\nexport function reduce(state: ConnectState, event: ConnectEvent): ConnectState {\n switch (event.type) {\n case \"CONNECT\":\n // A connect attempt is legal from any NON-in-flight state: a fresh client,\n // a terminal/failed state (retry), or an already-connected client\n // (re-connect with a new token). It is a no-op only while already\n // connecting (a second concurrent connect does nothing).\n return state === \"connecting\" ? state : \"connecting\";\n\n case \"CONNECT_SUCCESS\":\n // Only a connect IN FLIGHT can succeed. Any other state ignores it (a\n // stale/duplicate success after disconnect must not resurrect the client).\n return state === \"connecting\" ? \"connected\" : state;\n\n case \"CONNECT_DECLINED\":\n // Only a connect in flight can be declined.\n return state === \"connecting\" ? \"declined\" : state;\n\n case \"ERROR\":\n // A connect in flight can fail with a non-auth error. (A wrapper-call\n // failure while `connected` does NOT change the connect state - the\n // connection is still valid - so ERROR is a no-op when connected.)\n return state === \"connecting\" ? \"error\" : state;\n\n case \"TOKEN_EXPIRED\":\n // The membrane rejected the token. Legal from `connecting` (the token was\n // bad at connect time) or `connected` (it expired/was revoked mid-session).\n return state === \"connecting\" || state === \"connected\" ? \"expired\" : state;\n\n case \"DISCONNECT\":\n // Disconnect is ALWAYS reachable and idempotent: it moves any state to\n // `disconnected` (a no-op only when already there).\n return state === \"disconnected\" ? state : \"disconnected\";\n\n default: {\n // Exhaustiveness: a new event type must be handled above.\n const _never: never = event;\n return state;\n }\n }\n}\n\n/** Every state the machine can occupy (for reachability assertions). */\nexport const ALL_STATES: readonly ConnectState[] = [\n \"idle\",\n \"connecting\",\n \"connected\",\n \"declined\",\n \"expired\",\n \"error\",\n \"disconnected\",\n] as const;\n\n/** Whether the 7 tool wrappers may be called in this state. */\nexport function isConnected(state: ConnectState): boolean {\n return state === \"connected\";\n}\n","// Token persistence. Defaults to `localStorage` when present (the browser host\n// page), falls back to an in-memory store (SSR / Node / tests), and can be\n// disabled entirely (pass `storage: null` to the client).\n\nimport type { StorageAdapter } from \"./types.js\";\n\n/** The default storage key the token is persisted under. */\nexport const DEFAULT_STORAGE_KEY = \"usemycontext.token\";\n\n/** An in-memory storage adapter (SSR-safe; the fallback when no localStorage). */\nexport function memoryStorage(): StorageAdapter {\n const map = new Map<string, string>();\n return {\n get: (k) => (map.has(k) ? (map.get(k) as string) : null),\n set: (k, v) => void map.set(k, v),\n remove: (k) => void map.delete(k),\n };\n}\n\n/** Wrap a Web Storage (localStorage/sessionStorage) as a StorageAdapter. */\nexport function webStorage(store: Storage): StorageAdapter {\n return {\n get: (k) => {\n try {\n return store.getItem(k);\n } catch {\n return null;\n }\n },\n set: (k, v) => {\n try {\n store.setItem(k, v);\n } catch {\n /* quota / privacy mode - degrade to no-persist, never throw */\n }\n },\n remove: (k) => {\n try {\n store.removeItem(k);\n } catch {\n /* ignore */\n }\n },\n };\n}\n\n/**\n * Resolve the storage adapter to use given the option:\n * - an explicit adapter -> use it;\n * - `null` -> persistence disabled (a no-op adapter);\n * - `undefined` -> localStorage when available, else in-memory.\n */\nexport function resolveStorage(opt: StorageAdapter | null | undefined): StorageAdapter {\n if (opt === null) {\n return { get: () => null, set: () => {}, remove: () => {} };\n }\n if (opt) return opt;\n // Browser: prefer localStorage. Guarded for SSR + privacy-mode throws.\n try {\n if (typeof globalThis !== \"undefined\") {\n const ls = (globalThis as { localStorage?: Storage }).localStorage;\n if (ls) {\n // Probe it - some environments expose a localStorage that throws on use.\n const probe = \"__umc_probe__\";\n ls.setItem(probe, \"1\");\n ls.removeItem(probe);\n return webStorage(ls);\n }\n }\n } catch {\n /* fall through to in-memory */\n }\n return memoryStorage();\n}\n","// The default `fetch`-based transport. Tests inject a mock transport instead, so\n// this module is never exercised by the (zero-network) test suite - it is the\n// production wiring that POSTs one JSON-RPC request to the membrane `/mcp`\n// endpoint with the user's bearer token.\n\nimport type { Transport, TransportResponse } from \"./types.js\";\n\n/** A `fetch`-backed Transport (the default when none is supplied). */\nexport const fetchTransport: Transport = async ({ url, token, body }): Promise<TransportResponse> => {\n const res = await fetch(url, {\n method: \"POST\",\n headers: {\n \"content-type\": \"application/json\",\n accept: \"application/json\",\n authorization: `Bearer ${token}`,\n },\n body: JSON.stringify(body),\n });\n let parsed: unknown = null;\n try {\n parsed = await res.json();\n } catch {\n parsed = null; // non-JSON / empty body (e.g. a 401 with no body)\n }\n return {\n status: res.status,\n body: parsed,\n wwwAuthenticate: res.headers.get(\"www-authenticate\"),\n };\n};\n","// The core client: `useMyContext()` (a framework-free factory) + the 7 tool\n// wrappers. It holds the user's OWN token and calls the membrane exactly like\n// Claude does - same trust model, new client shape. The service stays\n// structurally blind.\n//\n// v1 IS TOKEN-IN ONLY: `connect({ token })`. The full browser-OAuth-in-the-SDK\n// flow (a hosted popup on connect.usemycontext.ai) is v2, gated on the Phase 2\n// CORS landing - deliberately NOT built here.\n\nimport {\n initializeRequest,\n toolCallRequest,\n asJsonRpcResponse,\n resultText,\n isScopeDenied,\n NotConnectedError,\n TokenExpiredError,\n ScopeDeniedError,\n ToolCallError,\n TransportError,\n UseMyContextError,\n type ToolResult,\n} from \"./jsonrpc.js\";\nimport { reduce, INITIAL_STATE, isConnected } from \"./machine.js\";\nimport { resolveStorage, DEFAULT_STORAGE_KEY } from \"./storage.js\";\nimport { fetchTransport } from \"./transport.js\";\nimport type {\n ClientOptions,\n ConnectArgs,\n ConnectState,\n FileMeta,\n ProfileResult,\n AskOptions,\n AskResult,\n AskPassage,\n GetFileResult,\n SuggestUpdateResult,\n SharedContextResult,\n SharedContextEntry,\n StorageAdapter,\n Transport,\n} from \"./types.js\";\n\n/** The production membrane MCP endpoint. */\nexport const DEFAULT_ENDPOINT = \"https://mcp.usemycontext.ai/mcp\";\n\n/** The shape `useMyContext()` returns - the client handle. */\nexport interface UseMyContextClient {\n /** The current connect state. */\n readonly state: ConnectState;\n /** Convenience: true iff `state === \"connected\"`. */\n readonly connected: boolean;\n /** The held token, when connected (else null). */\n readonly token: string | null;\n\n /** Subscribe to state changes. Returns an unsubscribe fn. */\n subscribe(listener: (state: ConnectState) => void): () => void;\n\n /** v1 TOKEN-IN connect: validate the token against the membrane. */\n connect(args: ConnectArgs): Promise<ConnectState>;\n /** Clear the token + persisted storage; -> `disconnected`. */\n disconnect(): void;\n\n // --- the 7 MCP tool wrappers ---\n profile(): Promise<ProfileResult>;\n listFiles(): Promise<FileMeta[]>;\n searchFiles(query: string): Promise<FileMeta[]>;\n getFile(fileId: string): Promise<GetFileResult>;\n ask(query: string, opts?: AskOptions): Promise<AskResult>;\n suggestUpdate(suggestion: string): Promise<SuggestUpdateResult>;\n sharedContext(from?: string): Promise<SharedContextResult>;\n}\n\n/**\n * Create a UseMyContext client. Framework-free: the React hook wraps this.\n * Restores a persisted token (without revalidating) so a returning host page\n * starts `connected`; a stale token surfaces as `expired` on the first call.\n */\nexport function useMyContext(options: ClientOptions = {}): UseMyContextClient {\n const endpoint = options.endpoint ?? DEFAULT_ENDPOINT;\n const transport: Transport = options.transport ?? fetchTransport;\n const storage: StorageAdapter = resolveStorage(options.storage);\n const storageKey = options.storageKey ?? DEFAULT_STORAGE_KEY;\n\n const listeners = new Set<(state: ConnectState) => void>();\n let state: ConnectState = INITIAL_STATE;\n let token: string | null = null;\n\n // Restore a persisted token: a returning page is `connected` optimistically\n // (the membrane is the authority - a stale token -> `expired` on first call).\n const persisted = storage.get(storageKey);\n if (persisted) {\n token = persisted;\n state = \"connected\";\n }\n\n function setState(next: ConnectState): void {\n if (next === state) return;\n state = next;\n options.onStateChange?.(state);\n for (const l of listeners) l(state);\n }\n\n function dispatch(event: Parameters<typeof reduce>[1]): void {\n setState(reduce(state, event));\n }\n\n /** One JSON-RPC round-trip against the membrane with the held token. */\n async function rpc(body: unknown): Promise<unknown> {\n if (!token) throw new NotConnectedError();\n let res;\n try {\n res = await transport({ url: endpoint, token, body });\n } catch (e) {\n throw new TransportError(\n `Transport failed: ${e instanceof Error ? e.message : String(e)}`,\n );\n }\n // A 401 means the token is bad/expired/revoked. Drive the machine to\n // `expired` and throw - the host should re-connect.\n if (res.status === 401) {\n dispatch({ type: \"TOKEN_EXPIRED\" });\n throw new TokenExpiredError(undefined, res.wwwAuthenticate ?? undefined);\n }\n const parsed = asJsonRpcResponse(res.body);\n if (parsed.error) {\n if (isScopeDenied(parsed.error.code)) {\n throw new ScopeDeniedError(parsed.error.message);\n }\n throw new ToolCallError(parsed.error.message, parsed.error.code);\n }\n return parsed.result;\n }\n\n /** A tools/call that returns the single rendered text block. */\n async function callTool(name: string, args: Record<string, unknown>): Promise<string> {\n if (!isConnected(state)) throw new NotConnectedError();\n const result = (await rpc(toolCallRequest(name, args))) as ToolResult;\n if (result.isError) {\n throw new ToolCallError(resultText(result) || `${name} failed.`);\n }\n return resultText(result);\n }\n\n return {\n get state() {\n return state;\n },\n get connected() {\n return state === \"connected\";\n },\n get token() {\n return state === \"connected\" ? token : null;\n },\n\n subscribe(listener) {\n listeners.add(listener);\n return () => void listeners.delete(listener);\n },\n\n async connect({ token: t }: ConnectArgs): Promise<ConnectState> {\n if (typeof t !== \"string\" || t.length === 0) {\n // A bad arg is a developer error, not a state transition.\n throw new UseMyContextConnectArgError();\n }\n dispatch({ type: \"CONNECT\" });\n token = t;\n try {\n const res = await transport({ url: endpoint, token: t, body: initializeRequest() });\n if (res.status === 401) {\n token = null;\n dispatch({ type: \"TOKEN_EXPIRED\" });\n throw new TokenExpiredError(undefined, res.wwwAuthenticate ?? undefined);\n }\n // Validate the handshake came back as a well-formed JSON-RPC result.\n const parsed = asJsonRpcResponse(res.body);\n if (parsed.error) {\n token = null;\n dispatch({ type: \"ERROR\" });\n throw new ToolCallError(parsed.error.message, parsed.error.code);\n }\n dispatch({ type: \"CONNECT_SUCCESS\" });\n if (storage) storage.set(storageKey, t);\n return state;\n } catch (e) {\n token = null;\n // TokenExpiredError already drove the machine to `expired`; any other\n // failure is a non-auth `error`.\n if (!(e instanceof TokenExpiredError)) {\n dispatch({ type: \"ERROR\" });\n if (e instanceof TransportError || e instanceof ToolCallError) throw e;\n throw new TransportError(\n `Connect failed: ${e instanceof Error ? e.message : String(e)}`,\n );\n }\n throw e;\n }\n },\n\n disconnect(): void {\n token = null;\n storage.remove(storageKey);\n dispatch({ type: \"DISCONNECT\" });\n },\n\n // --- profile ---------------------------------------------------------\n async profile(): Promise<ProfileResult> {\n const text = await callTool(\"profile\", {});\n // The membrane serves the compiled composite as plain text, OR (no compile\n // yet) the JSON of `{ facts: [...] }`. Detect the fallback by parsing.\n const facts = tryParseFacts(text);\n if (facts) return { composite: text, facts };\n return { composite: text };\n },\n\n // --- list_files / search_files (JSON array of FileMeta) --------------\n async listFiles(): Promise<FileMeta[]> {\n return parseFileList(await callTool(\"list_files\", {}));\n },\n async searchFiles(query: string): Promise<FileMeta[]> {\n if (typeof query !== \"string\") throw new UseMyContextConnectArgError(\"search query must be a string\");\n return parseFileList(await callTool(\"search_files\", { query }));\n },\n\n // --- get_file --------------------------------------------------------\n async getFile(fileId: string): Promise<GetFileResult> {\n if (typeof fileId !== \"string\" || !fileId) {\n throw new UseMyContextConnectArgError(\"fileId must be a non-empty string\");\n }\n const text = await callTool(\"get_file\", { fileId });\n return { text, downloadUrl: parseDownloadUrl(text) };\n },\n\n // --- ask_docs --------------------------------------------------------\n async ask(query: string, opts: AskOptions = {}): Promise<AskResult> {\n if (typeof query !== \"string\" || !query) {\n throw new UseMyContextConnectArgError(\"ask query must be a non-empty string\");\n }\n const args: Record<string, unknown> = { query };\n if (typeof opts.k === \"number\") args.k = opts.k;\n if (typeof opts.projectId === \"string\") args.projectId = opts.projectId;\n const text = await callTool(\"ask_docs\", args);\n return { passages: parseAskPassages(text), text };\n },\n\n // --- suggest_update (the one write) ----------------------------------\n async suggestUpdate(suggestion: string): Promise<SuggestUpdateResult> {\n if (typeof suggestion !== \"string\" || !suggestion.trim()) {\n throw new UseMyContextConnectArgError(\"suggestion must be a non-empty string\");\n }\n const text = await callTool(\"suggest_update\", { suggestion });\n const m = text.match(/\\(id:\\s*([^)]+)\\)/);\n return { id: m ? m[1].trim() : undefined, text };\n },\n\n // --- shared_context --------------------------------------------------\n async sharedContext(from?: string): Promise<SharedContextResult> {\n const args: Record<string, unknown> = {};\n if (typeof from === \"string\" && from) args.from = from;\n const text = await callTool(\"shared_context\", args);\n return from ? parseSharedRead(text) : parseSharedList(text);\n },\n };\n}\n\n/** Thrown for a bad SDK call argument (a developer error, not a state event). */\nexport class UseMyContextConnectArgError extends UseMyContextError {\n constructor(message = \"connect() requires a non-empty token string.\") {\n super(message);\n this.name = \"UseMyContextConnectArgError\";\n }\n}\n\n// --- parsers (decode the membrane's RENDERED text back to typed shapes) ---\n\n/** Parse `profile`'s JSON fallback (`{facts:[...]}`); null when it's prose. */\nfunction tryParseFacts(text: string): string[] | undefined {\n const trimmed = text.trimStart();\n if (!trimmed.startsWith(\"{\")) return undefined;\n try {\n const obj = JSON.parse(text) as { facts?: unknown };\n if (Array.isArray(obj.facts)) return obj.facts.filter((f): f is string => typeof f === \"string\");\n } catch {\n /* prose composite that happens to start with \"{\" - treat as composite */\n }\n return undefined;\n}\n\n/** Parse a list/search JSON array into FileMeta[]. */\nfunction parseFileList(text: string): FileMeta[] {\n try {\n const arr = JSON.parse(text) as unknown;\n if (!Array.isArray(arr)) return [];\n return arr.map((r) => {\n const o = (r ?? {}) as Record<string, unknown>;\n return {\n id: String(o.id ?? \"\"),\n name: String(o.name ?? \"\"),\n size: typeof o.size === \"number\" ? o.size : 0,\n contentType: String(o.contentType ?? \"\"),\n modified: String(o.modified ?? \"\"),\n ...(typeof o.status === \"string\" ? { status: o.status as FileMeta[\"status\"] } : {}),\n };\n });\n } catch {\n return [];\n }\n}\n\n/** Pull a `Download link ... : <url>` out of a get_file render. */\nfunction parseDownloadUrl(text: string): string | undefined {\n const m = text.match(/Download link[^:]*:\\s*(\\S+)/);\n return m ? m[1] : undefined;\n}\n\n/**\n * Parse `renderAskDocs` output: blocks separated by a blank line, each a\n * `[n] file · scope · score X.XXX` citation line then the passage text. An empty\n * result is the calm \"No relevant passages...\" sentence -> zero passages.\n */\nfunction parseAskPassages(text: string): AskPassage[] {\n if (/^No relevant passages/i.test(text.trimStart())) return [];\n const blocks = text.split(\"\\n\\n\");\n const out: AskPassage[] = [];\n for (const block of blocks) {\n const nl = block.indexOf(\"\\n\");\n const citation = nl === -1 ? block : block.slice(0, nl);\n const body = nl === -1 ? \"\" : block.slice(nl + 1);\n const m = citation.match(/^\\[(\\d+)\\]\\s*(.*)$/);\n if (!m) continue;\n const index = Number(m[1]);\n const rest = m[2];\n // rest = `file · scope · score N.NNN`\n const parts = rest.split(\" · \");\n const passage: AskPassage = { index, text: body };\n if (parts[0]) passage.file = parts[0].trim();\n if (parts[1]) passage.scope = parts[1].trim();\n const scoreM = rest.match(/score\\s+([\\d.]+)/);\n if (scoreM) passage.score = Number(scoreM[1]);\n out.push(passage);\n }\n return out;\n}\n\n/** Parse `renderSharedContext` LIST output (lines `- who (from: grantId)`). */\nfunction parseSharedList(text: string): SharedContextResult {\n if (/^No one has shared/i.test(text.trimStart())) {\n return { mode: \"list\", shares: [], composite: null, text };\n }\n const shares: SharedContextEntry[] = [];\n for (const line of text.split(\"\\n\")) {\n const m = line.match(/^-\\s*(.*?)\\s*\\(from:\\s*([^)]+)\\)\\s*$/);\n if (m) shares.push({ ownerLabel: m[1].trim(), grantId: m[2].trim() });\n }\n return { mode: \"list\", shares, composite: null, text };\n}\n\n/** Parse `renderSharedContext` READ output (`Shared context from X:\\n\\n<text>`). */\nfunction parseSharedRead(text: string): SharedContextResult {\n if (/not available/i.test(text)) {\n return { mode: \"read\", shares: [], composite: null, text };\n }\n const m = text.match(/^Shared context from [^:]*:\\n\\n([\\s\\S]*)$/);\n const composite = m ? m[1] : text;\n return { mode: \"read\", shares: [], composite, text };\n}\n","// The React surface: `useMyContextReact()` (a hook over the core client) and the\n// zero-config `<ConnectMyContext />` drop-in.\n//\n// React is an OPTIONAL peer dependency. This module lives behind the `./react`\n// export so importing the core `usemycontext` entry never pulls React in; tsup\n// marks `react` external so it is never bundled.\n\nimport * as React from \"react\";\nimport { useMyContext, type UseMyContextClient } from \"./client.js\";\nimport type { ClientOptions, ConnectState, ConnectArgs } from \"./types.js\";\n\n/** What the React hook returns: the live state + the client's bound methods. */\nexport interface UseMyContextReactValue {\n /** The current connect state (re-renders on change). */\n state: ConnectState;\n /** Convenience: true iff `state === \"connected\"`. */\n connected: boolean;\n /** The held token when connected, else null. */\n token: string | null;\n /** The underlying framework-free client (the 7 wrappers live here). */\n client: UseMyContextClient;\n /** v1 TOKEN-IN connect. */\n connect: (args: ConnectArgs) => Promise<ConnectState>;\n /** Clear the token; -> `disconnected`. */\n disconnect: () => void;\n}\n\n/**\n * The React hook. Creates ONE stable client per component instance and\n * subscribes to its state so the component re-renders on every transition.\n */\nexport function useMyContextReact(options: ClientOptions = {}): UseMyContextReactValue {\n // One stable client for the component's lifetime. options are read once on\n // first render (the typical usage passes a constant); a changing endpoint\n // mid-mount is out of v1 scope.\n const clientRef = React.useRef<UseMyContextClient | null>(null);\n if (clientRef.current === null) {\n clientRef.current = useMyContext(options);\n }\n const client = clientRef.current;\n\n const [state, setState] = React.useState<ConnectState>(client.state);\n\n React.useEffect(() => {\n // Subscribe AND sync once, in case the state changed between create + effect.\n setState(client.state);\n const unsub = client.subscribe(setState);\n return unsub;\n }, [client]);\n\n const connect = React.useCallback((args: ConnectArgs) => client.connect(args), [client]);\n const disconnect = React.useCallback(() => client.disconnect(), [client]);\n\n return {\n state,\n connected: state === \"connected\",\n token: client.token,\n client,\n connect,\n disconnect,\n };\n}\n\n/** Props for the drop-in button. */\nexport interface ConnectMyContextProps {\n /**\n * v1 is TOKEN-IN: supply the user's token (the full browser-OAuth popup is\n * v2). When given, the button calls `connect({ token })` on click.\n */\n token?: string;\n /** Forwarded to the underlying client (endpoint / transport / storage). */\n options?: ClientOptions;\n /** Called after a successful connect. */\n onConnect?: (state: ConnectState) => void;\n /** Called when a connect fails. */\n onError?: (error: unknown) => void;\n /** Override the button label per state. */\n label?: Partial<Record<ConnectState, string>>;\n /** Extra class name(s) for the button. */\n className?: string;\n}\n\nconst DEFAULT_LABELS: Record<ConnectState, string> = {\n idle: \"Connect my context\",\n connecting: \"Connecting...\",\n connected: \"Connected\",\n declined: \"Connect my context\",\n expired: \"Reconnect my context\",\n error: \"Retry connect\",\n disconnected: \"Connect my context\",\n};\n\n/**\n * A zero-config connect button. Renders a single <button> whose label tracks the\n * connect state; clicking it runs the v1 token-in connect. Unstyled beyond a\n * stable class name (`umc-connect-button`) so the host owns the look.\n */\nexport function ConnectMyContext(props: ConnectMyContextProps): React.ReactElement {\n const { token, options, onConnect, onError, label, className } = props;\n const { state, connect, disconnect } = useMyContextReact(options);\n\n const text = (label && label[state]) || DEFAULT_LABELS[state];\n const busy = state === \"connecting\";\n const isConnected = state === \"connected\";\n\n const onClick = React.useCallback(async () => {\n if (isConnected) {\n disconnect();\n return;\n }\n if (!token) {\n onError?.(new Error(\"ConnectMyContext: no `token` prop (v1 is token-in only).\"));\n return;\n }\n try {\n const next = await connect({ token });\n onConnect?.(next);\n } catch (e) {\n onError?.(e);\n }\n }, [isConnected, disconnect, token, connect, onConnect, onError]);\n\n return React.createElement(\n \"button\",\n {\n type: \"button\",\n className: [\"umc-connect-button\", className].filter(Boolean).join(\" \"),\n \"data-umc-state\": state,\n disabled: busy,\n \"aria-busy\": busy || undefined,\n onClick,\n },\n isConnected ? \"Disconnect\" : text,\n );\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/jsonrpc.ts","../src/machine.ts","../src/storage.ts","../src/transport.ts","../src/client.ts","../src/react.tsx"],"names":["isConnected"],"mappings":";;;;;AAsCO,IAAM,iBAAA,GAAN,cAAgC,KAAA,CAAM;AAAA,EAC3C,YAAY,OAAA,EAAiB;AAC3B,IAAA,KAAA,CAAM,OAAO,CAAA;AACb,IAAA,IAAA,CAAK,IAAA,GAAO,mBAAA;AAEZ,IAAA,MAAA,CAAO,cAAA,CAAe,IAAA,EAAM,GAAA,CAAA,MAAA,CAAW,SAAS,CAAA;AAAA,EAClD;AACF,CAAA;AAGO,IAAM,iBAAA,GAAN,cAAgC,iBAAA,CAAkB;AAAA,EACvD,WAAA,CAAY,UAAU,+CAAA,EAAiD;AACrE,IAAA,KAAA,CAAM,OAAO,CAAA;AACb,IAAA,IAAA,CAAK,IAAA,GAAO,mBAAA;AAAA,EACd;AACF,CAAA;AAMO,IAAM,iBAAA,GAAN,cAAgC,iBAAA,CAAkB;AAAA,EAGvD,WAAA,CAAY,OAAA,GAAU,yDAAA,EAA2D,eAAA,EAA0B;AACzG,IAAA,KAAA,CAAM,OAAO,CAAA;AACb,IAAA,IAAA,CAAK,IAAA,GAAO,mBAAA;AACZ,IAAA,IAAA,CAAK,eAAA,GAAkB,eAAA;AAAA,EACzB;AACF,CAAA;AAGO,IAAM,gBAAA,GAAN,cAA+B,iBAAA,CAAkB;AAAA,EAEtD,YAAY,OAAA,EAAiB;AAC3B,IAAA,KAAA,CAAM,OAAO,CAAA;AAFf,IAAA,IAAA,CAAS,IAAA,GAAO,MAAA;AAGd,IAAA,IAAA,CAAK,IAAA,GAAO,kBAAA;AAAA,EACd;AACF,CAAA;AAGO,IAAM,aAAA,GAAN,cAA4B,iBAAA,CAAkB;AAAA,EAGnD,WAAA,CAAY,SAAiB,IAAA,EAAe;AAC1C,IAAA,KAAA,CAAM,OAAO,CAAA;AACb,IAAA,IAAA,CAAK,IAAA,GAAO,eAAA;AACZ,IAAA,IAAA,CAAK,IAAA,GAAO,IAAA;AAAA,EACd;AACF,CAAA;AAGO,IAAM,cAAA,GAAN,cAA6B,iBAAA,CAAkB;AAAA,EACpD,YAAY,OAAA,EAAiB;AAC3B,IAAA,KAAA,CAAM,OAAO,CAAA;AACb,IAAA,IAAA,CAAK,IAAA,GAAO,gBAAA;AAAA,EACd;AACF,CAAA;AAEA,IAAI,MAAA,GAAS,CAAA;AAGN,SAAS,iBAAA,GAAoC;AAClD,EAAA,OAAO;AAAA,IACL,OAAA,EAAS,KAAA;AAAA,IACT,EAAA,EAAI,MAAA,EAAA;AAAA,IACJ,MAAA,EAAQ,YAAA;AAAA,IACR,MAAA,EAAQ;AAAA,MACN,eAAA,EAAiB,YAAA;AAAA,MACjB,cAAc,EAAC;AAAA,MACf,UAAA,EAAY,EAAE,IAAA,EAAM,kBAAA,EAAoB,SAAS,OAAA;AAAQ;AAC3D,GACF;AACF;AAGO,SAAS,eAAA,CAAgB,MAAc,IAAA,EAA+C;AAC3F,EAAA,OAAO;AAAA,IACL,OAAA,EAAS,KAAA;AAAA,IACT,EAAA,EAAI,MAAA,EAAA;AAAA,IACJ,MAAA,EAAQ,YAAA;AAAA,IACR,MAAA,EAAQ,EAAE,IAAA,EAAM,SAAA,EAAW,IAAA;AAAK,GAClC;AACF;AAOO,SAAS,kBAAkB,IAAA,EAAgC;AAChE,EAAA,IAAI,IAAA,KAAS,IAAA,IAAQ,OAAO,IAAA,KAAS,QAAA,EAAU;AAC7C,IAAA,MAAM,IAAI,eAAe,+CAA+C,CAAA;AAAA,EAC1E;AACA,EAAA,MAAM,CAAA,GAAI,IAAA;AACV,EAAA,IAAI,CAAA,CAAE,YAAY,KAAA,EAAO;AACvB,IAAA,MAAM,IAAI,eAAe,yCAAyC,CAAA;AAAA,EACpE;AACA,EAAA,OAAO,CAAA;AACT;AAGO,SAAS,cAAc,IAAA,EAAuB;AACnD,EAAA,OAAO,IAAA,KAAS,MAAA;AAClB;AAOO,SAAS,WAAW,MAAA,EAA4B;AACrD,EAAA,KAAA,MAAW,KAAA,IAAS,MAAA,CAAO,OAAA,IAAW,EAAC,EAAG;AACxC,IAAA,IAAI,KAAA,CAAM,SAAS,MAAA,IAAU,OAAO,MAAM,IAAA,KAAS,QAAA,SAAiB,KAAA,CAAM,IAAA;AAAA,EAC5E;AACA,EAAA,OAAO,EAAA;AACT;;;AC9HO,IAAM,aAAA,GAA8B,MAAA;AAMpC,SAAS,MAAA,CAAO,OAAqB,KAAA,EAAmC;AAC7E,EAAA,QAAQ,MAAM,IAAA;AAAM,IAClB,KAAK,SAAA;AAKH,MAAA,OAAO,KAAA,KAAU,eAAe,KAAA,GAAQ,YAAA;AAAA,IAE1C,KAAK,iBAAA;AAGH,MAAA,OAAO,KAAA,KAAU,eAAe,WAAA,GAAc,KAAA;AAAA,IAEhD,KAAK,kBAAA;AAEH,MAAA,OAAO,KAAA,KAAU,eAAe,UAAA,GAAa,KAAA;AAAA,IAE/C,KAAK,OAAA;AAIH,MAAA,OAAO,KAAA,KAAU,eAAe,OAAA,GAAU,KAAA;AAAA,IAE5C,KAAK,eAAA;AAGH,MAAA,OAAO,KAAA,KAAU,YAAA,IAAgB,KAAA,KAAU,WAAA,GAAc,SAAA,GAAY,KAAA;AAAA,IAEvE,KAAK,YAAA;AAGH,MAAA,OAAO,KAAA,KAAU,iBAAiB,KAAA,GAAQ,cAAA;AAAA,IAE5C,SAAS;AAGP,MAAA,OAAO,KAAA;AAAA,IACT;AAAA;AAEJ;AAcO,SAAS,YAAY,KAAA,EAA8B;AACxD,EAAA,OAAO,KAAA,KAAU,WAAA;AACnB;;;AC9EO,IAAM,mBAAA,GAAsB,oBAAA;AAG5B,SAAS,aAAA,GAAgC;AAC9C,EAAA,MAAM,GAAA,uBAAU,GAAA,EAAoB;AACpC,EAAA,OAAO;AAAA,IACL,GAAA,EAAK,CAAC,CAAA,KAAO,GAAA,CAAI,GAAA,CAAI,CAAC,CAAA,GAAK,GAAA,CAAI,GAAA,CAAI,CAAC,CAAA,GAAe,IAAA;AAAA,IACnD,GAAA,EAAK,CAAC,CAAA,EAAG,CAAA,KAAM,KAAK,GAAA,CAAI,GAAA,CAAI,GAAG,CAAC,CAAA;AAAA,IAChC,QAAQ,CAAC,CAAA,KAAM,KAAK,GAAA,CAAI,OAAO,CAAC;AAAA,GAClC;AACF;AAqCO,SAAS,eAAe,GAAA,EAAwD;AACrF,EAAA,IAAI,QAAQ,IAAA,EAAM;AAChB,IAAA,OAAO,EAAE,GAAA,EAAK,MAAM,IAAA,EAAM,KAAK,MAAM;AAAA,IAAC,CAAA,EAAG,QAAQ,MAAM;AAAA,IAAC,CAAA,EAAE;AAAA,EAC5D;AACA,EAAA,IAAI,KAAK,OAAO,GAAA;AAGhB,EAAA,OAAO,aAAA,EAAc;AACvB;;;AC3DO,IAAM,iBAA4B,OAAO,EAAE,GAAA,EAAK,KAAA,EAAO,MAAK,KAAkC;AACnG,EAAA,MAAM,GAAA,GAAM,MAAM,KAAA,CAAM,GAAA,EAAK;AAAA,IAC3B,MAAA,EAAQ,MAAA;AAAA,IACR,OAAA,EAAS;AAAA,MACP,cAAA,EAAgB,kBAAA;AAAA,MAChB,MAAA,EAAQ,kBAAA;AAAA,MACR,aAAA,EAAe,UAAU,KAAK,CAAA;AAAA,KAChC;AAAA,IACA,IAAA,EAAM,IAAA,CAAK,SAAA,CAAU,IAAI;AAAA,GAC1B,CAAA;AACD,EAAA,IAAI,MAAA,GAAkB,IAAA;AACtB,EAAA,IAAI;AACF,IAAA,MAAA,GAAS,MAAM,IAAI,IAAA,EAAK;AAAA,EAC1B,CAAA,CAAA,MAAQ;AACN,IAAA,MAAA,GAAS,IAAA;AAAA,EACX;AACA,EAAA,OAAO;AAAA,IACL,QAAQ,GAAA,CAAI,MAAA;AAAA,IACZ,IAAA,EAAM,MAAA;AAAA,IACN,eAAA,EAAiB,GAAA,CAAI,OAAA,CAAQ,GAAA,CAAI,kBAAkB;AAAA,GACrD;AACF,CAAA;;;ACeO,IAAM,gBAAA,GAAmB,iCAAA;AAkCzB,SAAS,YAAA,CAAa,OAAA,GAAyB,EAAC,EAAuB;AAC5E,EAAA,MAAM,QAAA,GAAW,QAAQ,QAAA,IAAY,gBAAA;AACrC,EAAA,MAAM,SAAA,GAAuB,QAAQ,SAAA,IAAa,cAAA;AAClD,EAAA,MAAM,OAAA,GAA0B,cAAA,CAAe,OAAA,CAAQ,OAAO,CAAA;AAC9D,EAAA,MAAM,UAAA,GAAa,QAAQ,UAAA,IAAc,mBAAA;AAEzC,EAAA,MAAM,SAAA,uBAAgB,GAAA,EAAmC;AACzD,EAAA,IAAI,KAAA,GAAsB,aAAA;AAC1B,EAAA,IAAI,KAAA,GAAuB,IAAA;AAI3B,EAAA,MAAM,SAAA,GAAY,OAAA,CAAQ,GAAA,CAAI,UAAU,CAAA;AACxC,EAAA,IAAI,SAAA,EAAW;AACb,IAAA,KAAA,GAAQ,SAAA;AACR,IAAA,KAAA,GAAQ,WAAA;AAAA,EACV;AAEA,EAAA,SAAS,SAAS,IAAA,EAA0B;AAC1C,IAAA,IAAI,SAAS,KAAA,EAAO;AACpB,IAAA,KAAA,GAAQ,IAAA;AACR,IAAA,OAAA,CAAQ,gBAAgB,KAAK,CAAA;AAC7B,IAAA,KAAA,MAAW,CAAA,IAAK,SAAA,EAAW,CAAA,CAAE,KAAK,CAAA;AAAA,EACpC;AAEA,EAAA,SAAS,SAAS,KAAA,EAA2C;AAC3D,IAAA,QAAA,CAAS,MAAA,CAAO,KAAA,EAAO,KAAK,CAAC,CAAA;AAAA,EAC/B;AAGA,EAAA,eAAe,IAAI,IAAA,EAAiC;AAClD,IAAA,IAAI,CAAC,KAAA,EAAO,MAAM,IAAI,iBAAA,EAAkB;AACxC,IAAA,IAAI,GAAA;AACJ,IAAA,IAAI;AACF,MAAA,GAAA,GAAM,MAAM,SAAA,CAAU,EAAE,KAAK,QAAA,EAAU,KAAA,EAAO,MAAM,CAAA;AAAA,IACtD,SAAS,CAAA,EAAG;AACV,MAAA,MAAM,IAAI,cAAA;AAAA,QACR,qBAAqB,CAAA,YAAa,KAAA,GAAQ,EAAE,OAAA,GAAU,MAAA,CAAO,CAAC,CAAC,CAAA;AAAA,OACjE;AAAA,IACF;AAGA,IAAA,IAAI,GAAA,CAAI,WAAW,GAAA,EAAK;AACtB,MAAA,QAAA,CAAS,EAAE,IAAA,EAAM,eAAA,EAAiB,CAAA;AAClC,MAAA,MAAM,IAAI,iBAAA,CAAkB,MAAA,EAAW,GAAA,CAAI,mBAAmB,MAAS,CAAA;AAAA,IACzE;AACA,IAAA,MAAM,MAAA,GAAS,iBAAA,CAAkB,GAAA,CAAI,IAAI,CAAA;AACzC,IAAA,IAAI,OAAO,KAAA,EAAO;AAChB,MAAA,IAAI,aAAA,CAAc,MAAA,CAAO,KAAA,CAAM,IAAI,CAAA,EAAG;AACpC,QAAA,MAAM,IAAI,gBAAA,CAAiB,MAAA,CAAO,KAAA,CAAM,OAAO,CAAA;AAAA,MACjD;AACA,MAAA,MAAM,IAAI,aAAA,CAAc,MAAA,CAAO,MAAM,OAAA,EAAS,MAAA,CAAO,MAAM,IAAI,CAAA;AAAA,IACjE;AACA,IAAA,OAAO,MAAA,CAAO,MAAA;AAAA,EAChB;AAGA,EAAA,eAAe,QAAA,CAAS,MAAc,IAAA,EAAgD;AACpF,IAAA,IAAI,CAAC,WAAA,CAAY,KAAK,CAAA,EAAG,MAAM,IAAI,iBAAA,EAAkB;AACrD,IAAA,MAAM,SAAU,MAAM,GAAA,CAAI,eAAA,CAAgB,IAAA,EAAM,IAAI,CAAC,CAAA;AACrD,IAAA,IAAI,OAAO,OAAA,EAAS;AAClB,MAAA,MAAM,IAAI,aAAA,CAAc,UAAA,CAAW,MAAM,CAAA,IAAK,CAAA,EAAG,IAAI,CAAA,QAAA,CAAU,CAAA;AAAA,IACjE;AACA,IAAA,OAAO,WAAW,MAAM,CAAA;AAAA,EAC1B;AAEA,EAAA,OAAO;AAAA,IACL,IAAI,KAAA,GAAQ;AACV,MAAA,OAAO,KAAA;AAAA,IACT,CAAA;AAAA,IACA,IAAI,SAAA,GAAY;AACd,MAAA,OAAO,KAAA,KAAU,WAAA;AAAA,IACnB,CAAA;AAAA,IACA,IAAI,KAAA,GAAQ;AACV,MAAA,OAAO,KAAA,KAAU,cAAc,KAAA,GAAQ,IAAA;AAAA,IACzC,CAAA;AAAA,IAEA,UAAU,QAAA,EAAU;AAClB,MAAA,SAAA,CAAU,IAAI,QAAQ,CAAA;AACtB,MAAA,OAAO,MAAM,KAAK,SAAA,CAAU,MAAA,CAAO,QAAQ,CAAA;AAAA,IAC7C,CAAA;AAAA,IAEA,MAAM,OAAA,CAAQ,EAAE,KAAA,EAAO,GAAE,EAAuC;AAC9D,MAAA,IAAI,OAAO,CAAA,KAAM,QAAA,IAAY,CAAA,CAAE,WAAW,CAAA,EAAG;AAE3C,QAAA,MAAM,IAAI,2BAAA,EAA4B;AAAA,MACxC;AACA,MAAA,QAAA,CAAS,EAAE,IAAA,EAAM,SAAA,EAAW,CAAA;AAC5B,MAAA,KAAA,GAAQ,CAAA;AACR,MAAA,IAAI;AACF,QAAA,MAAM,GAAA,GAAM,MAAM,SAAA,CAAU,EAAE,GAAA,EAAK,QAAA,EAAU,KAAA,EAAO,CAAA,EAAG,IAAA,EAAM,iBAAA,EAAkB,EAAG,CAAA;AAClF,QAAA,IAAI,GAAA,CAAI,WAAW,GAAA,EAAK;AACtB,UAAA,KAAA,GAAQ,IAAA;AACR,UAAA,QAAA,CAAS,EAAE,IAAA,EAAM,eAAA,EAAiB,CAAA;AAClC,UAAA,MAAM,IAAI,iBAAA,CAAkB,KAAA,CAAA,EAAW,GAAA,CAAI,mBAAmB,KAAA,CAAS,CAAA;AAAA,QACzE;AAEA,QAAA,MAAM,MAAA,GAAS,iBAAA,CAAkB,GAAA,CAAI,IAAI,CAAA;AACzC,QAAA,IAAI,OAAO,KAAA,EAAO;AAChB,UAAA,KAAA,GAAQ,IAAA;AACR,UAAA,QAAA,CAAS,EAAE,IAAA,EAAM,OAAA,EAAS,CAAA;AAC1B,UAAA,MAAM,IAAI,aAAA,CAAc,MAAA,CAAO,MAAM,OAAA,EAAS,MAAA,CAAO,MAAM,IAAI,CAAA;AAAA,QACjE;AACA,QAAA,QAAA,CAAS,EAAE,IAAA,EAAM,iBAAA,EAAmB,CAAA;AACpC,QAAA,IAAI,OAAA,EAAS,OAAA,CAAQ,GAAA,CAAI,UAAA,EAAY,CAAC,CAAA;AACtC,QAAA,OAAO,KAAA;AAAA,MACT,SAAS,CAAA,EAAG;AACV,QAAA,KAAA,GAAQ,IAAA;AAGR,QAAA,IAAI,EAAE,aAAa,iBAAA,CAAA,EAAoB;AACrC,UAAA,QAAA,CAAS,EAAE,IAAA,EAAM,OAAA,EAAS,CAAA;AAC1B,UAAA,IAAI,CAAA,YAAa,cAAA,IAAkB,CAAA,YAAa,aAAA,EAAe,MAAM,CAAA;AACrE,UAAA,MAAM,IAAI,cAAA;AAAA,YACR,mBAAmB,CAAA,YAAa,KAAA,GAAQ,EAAE,OAAA,GAAU,MAAA,CAAO,CAAC,CAAC,CAAA;AAAA,WAC/D;AAAA,QACF;AACA,QAAA,MAAM,CAAA;AAAA,MACR;AAAA,IACF,CAAA;AAAA,IAEA,UAAA,GAAmB;AACjB,MAAA,KAAA,GAAQ,IAAA;AACR,MAAA,OAAA,CAAQ,OAAO,UAAU,CAAA;AACzB,MAAA,QAAA,CAAS,EAAE,IAAA,EAAM,YAAA,EAAc,CAAA;AAAA,IACjC,CAAA;AAAA;AAAA,IAGA,MAAM,OAAA,GAAkC;AACtC,MAAA,MAAM,IAAA,GAAO,MAAM,QAAA,CAAS,SAAA,EAAW,EAAE,CAAA;AAGzC,MAAA,MAAM,KAAA,GAAQ,cAAc,IAAI,CAAA;AAChC,MAAA,IAAI,KAAA,EAAO,OAAO,EAAE,SAAA,EAAW,MAAM,KAAA,EAAM;AAC3C,MAAA,OAAO,EAAE,WAAW,IAAA,EAAK;AAAA,IAC3B,CAAA;AAAA;AAAA,IAGA,MAAM,SAAA,GAAiC;AACrC,MAAA,OAAO,cAAc,MAAM,QAAA,CAAS,YAAA,EAAc,EAAE,CAAC,CAAA;AAAA,IACvD,CAAA;AAAA,IACA,MAAM,YAAY,KAAA,EAAoC;AACpD,MAAA,IAAI,OAAO,KAAA,KAAU,QAAA,EAAU,MAAM,IAAI,4BAA4B,+BAA+B,CAAA;AACpG,MAAA,OAAO,cAAc,MAAM,QAAA,CAAS,gBAAgB,EAAE,KAAA,EAAO,CAAC,CAAA;AAAA,IAChE,CAAA;AAAA;AAAA,IAGA,MAAM,QAAQ,MAAA,EAAwC;AACpD,MAAA,IAAI,OAAO,MAAA,KAAW,QAAA,IAAY,CAAC,MAAA,EAAQ;AACzC,QAAA,MAAM,IAAI,4BAA4B,mCAAmC,CAAA;AAAA,MAC3E;AACA,MAAA,MAAM,OAAO,MAAM,QAAA,CAAS,UAAA,EAAY,EAAE,QAAQ,CAAA;AAClD,MAAA,OAAO,EAAE,IAAA,EAAM,WAAA,EAAa,gBAAA,CAAiB,IAAI,CAAA,EAAE;AAAA,IACrD,CAAA;AAAA;AAAA,IAGA,MAAM,GAAA,CAAI,KAAA,EAAe,IAAA,GAAmB,EAAC,EAAuB;AAClE,MAAA,IAAI,OAAO,KAAA,KAAU,QAAA,IAAY,CAAC,KAAA,EAAO;AACvC,QAAA,MAAM,IAAI,4BAA4B,sCAAsC,CAAA;AAAA,MAC9E;AACA,MAAA,MAAM,IAAA,GAAgC,EAAE,KAAA,EAAM;AAC9C,MAAA,IAAI,OAAO,IAAA,CAAK,CAAA,KAAM,QAAA,EAAU,IAAA,CAAK,IAAI,IAAA,CAAK,CAAA;AAC9C,MAAA,IAAI,OAAO,IAAA,CAAK,SAAA,KAAc,QAAA,EAAU,IAAA,CAAK,YAAY,IAAA,CAAK,SAAA;AAC9D,MAAA,MAAM,IAAA,GAAO,MAAM,QAAA,CAAS,UAAA,EAAY,IAAI,CAAA;AAC5C,MAAA,OAAO,EAAE,QAAA,EAAU,gBAAA,CAAiB,IAAI,GAAG,IAAA,EAAK;AAAA,IAClD,CAAA;AAAA;AAAA,IAGA,MAAM,cAAc,UAAA,EAAkD;AACpE,MAAA,IAAI,OAAO,UAAA,KAAe,QAAA,IAAY,CAAC,UAAA,CAAW,MAAK,EAAG;AACxD,QAAA,MAAM,IAAI,4BAA4B,uCAAuC,CAAA;AAAA,MAC/E;AACA,MAAA,MAAM,OAAO,MAAM,QAAA,CAAS,gBAAA,EAAkB,EAAE,YAAY,CAAA;AAC5D,MAAA,MAAM,CAAA,GAAI,IAAA,CAAK,KAAA,CAAM,mBAAmB,CAAA;AACxC,MAAA,OAAO,EAAE,IAAI,CAAA,GAAI,CAAA,CAAE,CAAC,CAAA,CAAE,IAAA,EAAK,GAAI,MAAA,EAAW,IAAA,EAAK;AAAA,IACjD,CAAA;AAAA;AAAA,IAGA,MAAM,cAAc,IAAA,EAA6C;AAC/D,MAAA,MAAM,OAAgC,EAAC;AACvC,MAAA,IAAI,OAAO,IAAA,KAAS,QAAA,IAAY,IAAA,OAAW,IAAA,GAAO,IAAA;AAClD,MAAA,MAAM,IAAA,GAAO,MAAM,QAAA,CAAS,gBAAA,EAAkB,IAAI,CAAA;AAClD,MAAA,OAAO,IAAA,GAAO,eAAA,CAAgB,IAAI,CAAA,GAAI,gBAAgB,IAAI,CAAA;AAAA,IAC5D;AAAA,GACF;AACF;AAGO,IAAM,2BAAA,GAAN,cAA0C,iBAAA,CAAkB;AAAA,EACjE,WAAA,CAAY,UAAU,8CAAA,EAAgD;AACpE,IAAA,KAAA,CAAM,OAAO,CAAA;AACb,IAAA,IAAA,CAAK,IAAA,GAAO,6BAAA;AAAA,EACd;AACF,CAAA;AAKA,SAAS,cAAc,IAAA,EAAoC;AACzD,EAAA,MAAM,OAAA,GAAU,KAAK,SAAA,EAAU;AAC/B,EAAA,IAAI,CAAC,OAAA,CAAQ,UAAA,CAAW,GAAG,GAAG,OAAO,MAAA;AACrC,EAAA,IAAI;AACF,IAAA,MAAM,GAAA,GAAM,IAAA,CAAK,KAAA,CAAM,IAAI,CAAA;AAC3B,IAAA,IAAI,KAAA,CAAM,OAAA,CAAQ,GAAA,CAAI,KAAK,CAAA,EAAG,OAAO,GAAA,CAAI,KAAA,CAAM,MAAA,CAAO,CAAC,CAAA,KAAmB,OAAO,MAAM,QAAQ,CAAA;AAAA,EACjG,CAAA,CAAA,MAAQ;AAAA,EAER;AACA,EAAA,OAAO,MAAA;AACT;AAGA,SAAS,cAAc,IAAA,EAA0B;AAC/C,EAAA,IAAI;AACF,IAAA,MAAM,GAAA,GAAM,IAAA,CAAK,KAAA,CAAM,IAAI,CAAA;AAC3B,IAAA,IAAI,CAAC,KAAA,CAAM,OAAA,CAAQ,GAAG,CAAA,SAAU,EAAC;AACjC,IAAA,OAAO,GAAA,CAAI,GAAA,CAAI,CAAC,CAAA,KAAM;AACpB,MAAA,MAAM,CAAA,GAAK,KAAK,EAAC;AACjB,MAAA,OAAO;AAAA,QACL,EAAA,EAAI,MAAA,CAAO,CAAA,CAAE,EAAA,IAAM,EAAE,CAAA;AAAA,QACrB,IAAA,EAAM,MAAA,CAAO,CAAA,CAAE,IAAA,IAAQ,EAAE,CAAA;AAAA,QACzB,MAAM,OAAO,CAAA,CAAE,IAAA,KAAS,QAAA,GAAW,EAAE,IAAA,GAAO,CAAA;AAAA,QAC5C,WAAA,EAAa,MAAA,CAAO,CAAA,CAAE,WAAA,IAAe,EAAE,CAAA;AAAA,QACvC,QAAA,EAAU,MAAA,CAAO,CAAA,CAAE,QAAA,IAAY,EAAE,CAAA;AAAA,QACjC,GAAI,OAAO,CAAA,CAAE,MAAA,KAAW,QAAA,GAAW,EAAE,MAAA,EAAQ,CAAA,CAAE,MAAA,EAA6B,GAAI;AAAC,OACnF;AAAA,IACF,CAAC,CAAA;AAAA,EACH,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,EAAC;AAAA,EACV;AACF;AAGA,SAAS,iBAAiB,IAAA,EAAkC;AAC1D,EAAA,MAAM,CAAA,GAAI,IAAA,CAAK,KAAA,CAAM,6BAA6B,CAAA;AAClD,EAAA,OAAO,CAAA,GAAI,CAAA,CAAE,CAAC,CAAA,GAAI,MAAA;AACpB;AAOA,SAAS,iBAAiB,IAAA,EAA4B;AACpD,EAAA,IAAI,yBAAyB,IAAA,CAAK,IAAA,CAAK,WAAW,CAAA,SAAU,EAAC;AAC7D,EAAA,MAAM,MAAA,GAAS,IAAA,CAAK,KAAA,CAAM,MAAM,CAAA;AAChC,EAAA,MAAM,MAAoB,EAAC;AAC3B,EAAA,KAAA,MAAW,SAAS,MAAA,EAAQ;AAC1B,IAAA,MAAM,EAAA,GAAK,KAAA,CAAM,OAAA,CAAQ,IAAI,CAAA;AAC7B,IAAA,MAAM,WAAW,EAAA,KAAO,EAAA,GAAK,QAAQ,KAAA,CAAM,KAAA,CAAM,GAAG,EAAE,CAAA;AACtD,IAAA,MAAM,OAAO,EAAA,KAAO,EAAA,GAAK,KAAK,KAAA,CAAM,KAAA,CAAM,KAAK,CAAC,CAAA;AAChD,IAAA,MAAM,CAAA,GAAI,QAAA,CAAS,KAAA,CAAM,oBAAoB,CAAA;AAC7C,IAAA,IAAI,CAAC,CAAA,EAAG;AACR,IAAA,MAAM,KAAA,GAAQ,MAAA,CAAO,CAAA,CAAE,CAAC,CAAC,CAAA;AACzB,IAAA,MAAM,IAAA,GAAO,EAAE,CAAC,CAAA;AAEhB,IAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,KAAA,CAAM,QAAK,CAAA;AAC9B,IAAA,MAAM,OAAA,GAAsB,EAAE,KAAA,EAAO,IAAA,EAAM,IAAA,EAAK;AAChD,IAAA,IAAI,KAAA,CAAM,CAAC,CAAA,EAAG,OAAA,CAAQ,OAAO,KAAA,CAAM,CAAC,EAAE,IAAA,EAAK;AAC3C,IAAA,IAAI,KAAA,CAAM,CAAC,CAAA,EAAG,OAAA,CAAQ,QAAQ,KAAA,CAAM,CAAC,EAAE,IAAA,EAAK;AAC5C,IAAA,MAAM,MAAA,GAAS,IAAA,CAAK,KAAA,CAAM,kBAAkB,CAAA;AAC5C,IAAA,IAAI,QAAQ,OAAA,CAAQ,KAAA,GAAQ,MAAA,CAAO,MAAA,CAAO,CAAC,CAAC,CAAA;AAC5C,IAAA,GAAA,CAAI,KAAK,OAAO,CAAA;AAAA,EAClB;AACA,EAAA,OAAO,GAAA;AACT;AAGA,SAAS,gBAAgB,IAAA,EAAmC;AAC1D,EAAA,IAAI,qBAAA,CAAsB,IAAA,CAAK,IAAA,CAAK,SAAA,EAAW,CAAA,EAAG;AAChD,IAAA,OAAO,EAAE,MAAM,MAAA,EAAQ,MAAA,EAAQ,EAAC,EAAG,SAAA,EAAW,MAAM,IAAA,EAAK;AAAA,EAC3D;AACA,EAAA,MAAM,SAA+B,EAAC;AACtC,EAAA,KAAA,MAAW,IAAA,IAAQ,IAAA,CAAK,KAAA,CAAM,IAAI,CAAA,EAAG;AACnC,IAAA,MAAM,CAAA,GAAI,IAAA,CAAK,KAAA,CAAM,sCAAsC,CAAA;AAC3D,IAAA,IAAI,GAAG,MAAA,CAAO,IAAA,CAAK,EAAE,UAAA,EAAY,EAAE,CAAC,CAAA,CAAE,IAAA,EAAK,EAAG,SAAS,CAAA,CAAE,CAAC,CAAA,CAAE,IAAA,IAAQ,CAAA;AAAA,EACtE;AACA,EAAA,OAAO,EAAE,IAAA,EAAM,MAAA,EAAQ,MAAA,EAAQ,SAAA,EAAW,MAAM,IAAA,EAAK;AACvD;AAGA,SAAS,gBAAgB,IAAA,EAAmC;AAC1D,EAAA,IAAI,gBAAA,CAAiB,IAAA,CAAK,IAAI,CAAA,EAAG;AAC/B,IAAA,OAAO,EAAE,MAAM,MAAA,EAAQ,MAAA,EAAQ,EAAC,EAAG,SAAA,EAAW,MAAM,IAAA,EAAK;AAAA,EAC3D;AACA,EAAA,MAAM,CAAA,GAAI,IAAA,CAAK,KAAA,CAAM,2CAA2C,CAAA;AAChE,EAAA,MAAM,SAAA,GAAY,CAAA,GAAI,CAAA,CAAE,CAAC,CAAA,GAAI,IAAA;AAC7B,EAAA,OAAO,EAAE,IAAA,EAAM,MAAA,EAAQ,QAAQ,EAAC,EAAG,WAAW,IAAA,EAAK;AACrD;;;AC9UO,SAAS,iBAAA,CAAkB,OAAA,GAAyB,EAAC,EAA2B;AAIrF,EAAA,MAAM,SAAA,GAAkB,aAAkC,IAAI,CAAA;AAC9D,EAAA,IAAI,SAAA,CAAU,YAAY,IAAA,EAAM;AAC9B,IAAA,SAAA,CAAU,OAAA,GAAU,aAAa,OAAO,CAAA;AAAA,EAC1C;AACA,EAAA,MAAM,SAAS,SAAA,CAAU,OAAA;AAEzB,EAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,CAAA,GAAU,KAAA,CAAA,QAAA,CAAuB,OAAO,KAAK,CAAA;AAEnE,EAAM,gBAAU,MAAM;AAEpB,IAAA,QAAA,CAAS,OAAO,KAAK,CAAA;AACrB,IAAA,MAAM,KAAA,GAAQ,MAAA,CAAO,SAAA,CAAU,QAAQ,CAAA;AACvC,IAAA,OAAO,KAAA;AAAA,EACT,CAAA,EAAG,CAAC,MAAM,CAAC,CAAA;AAEX,EAAA,MAAM,OAAA,GAAgB,KAAA,CAAA,WAAA,CAAY,CAAC,IAAA,KAAsB,MAAA,CAAO,QAAQ,IAAI,CAAA,EAAG,CAAC,MAAM,CAAC,CAAA;AACvF,EAAA,MAAM,UAAA,GAAmB,kBAAY,MAAM,MAAA,CAAO,YAAW,EAAG,CAAC,MAAM,CAAC,CAAA;AAExE,EAAA,OAAO;AAAA,IACL,KAAA;AAAA,IACA,WAAW,KAAA,KAAU,WAAA;AAAA,IACrB,OAAO,MAAA,CAAO,KAAA;AAAA,IACd,MAAA;AAAA,IACA,OAAA;AAAA,IACA;AAAA,GACF;AACF;AAqBA,IAAM,cAAA,GAA+C;AAAA,EACnD,IAAA,EAAM,oBAAA;AAAA,EACN,UAAA,EAAY,eAAA;AAAA,EACZ,SAAA,EAAW,WAAA;AAAA,EACX,QAAA,EAAU,oBAAA;AAAA,EACV,OAAA,EAAS,sBAAA;AAAA,EACT,KAAA,EAAO,eAAA;AAAA,EACP,YAAA,EAAc;AAChB,CAAA;AAOO,SAAS,iBAAiB,KAAA,EAAkD;AACjF,EAAA,MAAM,EAAE,KAAA,EAAO,OAAA,EAAS,WAAW,OAAA,EAAS,KAAA,EAAO,WAAU,GAAI,KAAA;AACjE,EAAA,MAAM,EAAE,KAAA,EAAO,OAAA,EAAS,UAAA,EAAW,GAAI,kBAAkB,OAAO,CAAA;AAEhE,EAAA,MAAM,OAAQ,KAAA,IAAS,KAAA,CAAM,KAAK,CAAA,IAAM,eAAe,KAAK,CAAA;AAC5D,EAAA,MAAM,OAAO,KAAA,KAAU,YAAA;AACvB,EAAA,MAAMA,eAAc,KAAA,KAAU,WAAA;AAE9B,EAAA,MAAM,OAAA,GAAgB,kBAAY,YAAY;AAC5C,IAAA,IAAIA,YAAAA,EAAa;AACf,MAAA,UAAA,EAAW;AACX,MAAA;AAAA,IACF;AACA,IAAA,IAAI,CAAC,KAAA,EAAO;AACV,MAAA,OAAA,GAAU,IAAI,KAAA,CAAM,0DAA0D,CAAC,CAAA;AAC/E,MAAA;AAAA,IACF;AACA,IAAA,IAAI;AACF,MAAA,MAAM,IAAA,GAAO,MAAM,OAAA,CAAQ,EAAE,OAAO,CAAA;AACpC,MAAA,SAAA,GAAY,IAAI,CAAA;AAAA,IAClB,SAAS,CAAA,EAAG;AACV,MAAA,OAAA,GAAU,CAAC,CAAA;AAAA,IACb;AAAA,EACF,CAAA,EAAG,CAACA,YAAAA,EAAa,UAAA,EAAY,OAAO,OAAA,EAAS,SAAA,EAAW,OAAO,CAAC,CAAA;AAEhE,EAAA,OAAa,KAAA,CAAA,aAAA;AAAA,IACX,QAAA;AAAA,IACA;AAAA,MACE,IAAA,EAAM,QAAA;AAAA,MACN,SAAA,EAAW,CAAC,oBAAA,EAAsB,SAAS,EAAE,MAAA,CAAO,OAAO,CAAA,CAAE,IAAA,CAAK,GAAG,CAAA;AAAA,MACrE,gBAAA,EAAkB,KAAA;AAAA,MAClB,QAAA,EAAU,IAAA;AAAA,MACV,aAAa,IAAA,IAAQ,MAAA;AAAA,MACrB;AAAA,KACF;AAAA,IACAA,eAAc,YAAA,GAAe;AAAA,GAC/B;AACF","file":"react.js","sourcesContent":["// JSON-RPC 2.0 framing for the membrane MCP wire, plus the SDK error taxonomy.\n//\n// The membrane speaks hand-rolled JSON-RPC over Streamable HTTP. The SDK only\n// ever sends `initialize` and `tools/call`. A tools/call comes back as a RESULT\n// shaped `{ content: [{ type:\"text\", text }], isError }`; a protocol-level\n// failure comes back as a JSON-RPC `error` object. This module owns the framing\n// + the parsing helpers; the wrappers in client.ts decode the text content.\n\n/** A JSON-RPC request envelope. */\nexport interface JsonRpcRequest {\n jsonrpc: \"2.0\";\n id: number;\n method: string;\n params?: unknown;\n}\n\n/** A JSON-RPC error object. */\nexport interface JsonRpcErrorObject {\n code: number;\n message: string;\n data?: unknown;\n}\n\n/** A parsed JSON-RPC response (success xor error). */\nexport interface JsonRpcResponse {\n jsonrpc: \"2.0\";\n id: number | null;\n result?: unknown;\n error?: JsonRpcErrorObject;\n}\n\n/** The MCP tools/call result shape (`content` blocks + an error flag). */\nexport interface ToolResult {\n content: Array<{ type: string; text?: string }>;\n isError?: boolean;\n}\n\n/** Base class for every error the SDK throws, so callers can `catch (e)`. */\nexport class UseMyContextError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"UseMyContextError\";\n // Restore the prototype chain (TS target < ES2015 / transpiled extends).\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\n/** Thrown when a tool wrapper is called before a successful `connect()`. */\nexport class NotConnectedError extends UseMyContextError {\n constructor(message = \"Not connected. Call connect({ token }) first.\") {\n super(message);\n this.name = \"NotConnectedError\";\n }\n}\n\n/**\n * Thrown when the membrane rejects the token (HTTP 401 + WWW-Authenticate).\n * The client also transitions to `expired` so the host can re-connect.\n */\nexport class TokenExpiredError extends UseMyContextError {\n /** The raw `WWW-Authenticate` header, when the server sent one. */\n readonly wwwAuthenticate?: string;\n constructor(message = \"The connection token was rejected (expired or revoked).\", wwwAuthenticate?: string) {\n super(message);\n this.name = \"TokenExpiredError\";\n this.wwwAuthenticate = wwwAuthenticate;\n }\n}\n\n/** Thrown when a tool call is refused for lack of scope (membrane -32604). */\nexport class ScopeDeniedError extends UseMyContextError {\n readonly code = -32604;\n constructor(message: string) {\n super(message);\n this.name = \"ScopeDeniedError\";\n }\n}\n\n/** Thrown for a JSON-RPC protocol error or a tool-level `isError` result. */\nexport class ToolCallError extends UseMyContextError {\n /** The JSON-RPC error code, when the failure was a protocol error. */\n readonly code?: number;\n constructor(message: string, code?: number) {\n super(message);\n this.name = \"ToolCallError\";\n this.code = code;\n }\n}\n\n/** Thrown for transport/parse failures (network down, non-JSON body, ...). */\nexport class TransportError extends UseMyContextError {\n constructor(message: string) {\n super(message);\n this.name = \"TransportError\";\n }\n}\n\nlet nextId = 1;\n\n/** Build an `initialize` request (the connect handshake). */\nexport function initializeRequest(): JsonRpcRequest {\n return {\n jsonrpc: \"2.0\",\n id: nextId++,\n method: \"initialize\",\n params: {\n protocolVersion: \"2025-06-18\",\n capabilities: {},\n clientInfo: { name: \"usemycontext-sdk\", version: \"0.1.0\" },\n },\n };\n}\n\n/** Build a `tools/call` request for a tool name + arguments. */\nexport function toolCallRequest(name: string, args: Record<string, unknown>): JsonRpcRequest {\n return {\n jsonrpc: \"2.0\",\n id: nextId++,\n method: \"tools/call\",\n params: { name, arguments: args },\n };\n}\n\n/**\n * Narrow an unknown body to a JSON-RPC response. Throws TransportError when the\n * body is not a well-formed JSON-RPC 2.0 envelope (a defensive guard against a\n * misbehaving transport or an HTML error page).\n */\nexport function asJsonRpcResponse(body: unknown): JsonRpcResponse {\n if (body === null || typeof body !== \"object\") {\n throw new TransportError(\"Membrane returned a non-object response body.\");\n }\n const b = body as Record<string, unknown>;\n if (b.jsonrpc !== \"2.0\") {\n throw new TransportError(\"Membrane response was not JSON-RPC 2.0.\");\n }\n return b as unknown as JsonRpcResponse;\n}\n\n/** True iff a JSON-RPC error code denotes a missing-scope denial (-32604). */\nexport function isScopeDenied(code: number): boolean {\n return code === -32604;\n}\n\n/**\n * Pull the single text block out of a tools/call RESULT. The membrane always\n * renders to ONE text content block, so this returns its `text` (or \"\" when a\n * result carried no text block).\n */\nexport function resultText(result: ToolResult): string {\n for (const block of result.content ?? []) {\n if (block.type === \"text\" && typeof block.text === \"string\") return block.text;\n }\n return \"\";\n}\n","// The connect state machine - a PURE reducer (no IO, no timers, no `this`).\n//\n// States (ConnectState):\n// idle -> connecting -> connected\n// \\-> declined (user/host refused; v2 OAuth path)\n// \\-> error (network/transport/parse failure)\n// connected -> expired (membrane 401 mid-session)\n// connected -> disconnected (explicit disconnect)\n// <any> -> disconnected (disconnect is always reachable)\n// <terminal>-> connecting (a fresh connect() retries)\n//\n// The reducer is the single source of truth for legality: an event that does\n// not apply to the current state is a NO-OP (returns the same state), so the\n// client can fire events without guarding, and tests can assert every legal AND\n// illegal transition deterministically.\n\nimport type { ConnectState } from \"./types.js\";\n\n/** The events that drive the machine. */\nexport type ConnectEvent =\n | { type: \"CONNECT\" } // begin a connect attempt\n | { type: \"CONNECT_SUCCESS\" } // membrane accepted the token\n | { type: \"CONNECT_DECLINED\" } // user/host refused (v2 OAuth path)\n | { type: \"TOKEN_EXPIRED\" } // membrane 401 (expired/revoked)\n | { type: \"ERROR\" } // a non-auth failure\n | { type: \"DISCONNECT\" }; // explicit disconnect / token cleared\n\n/** The initial state of a fresh client. */\nexport const INITIAL_STATE: ConnectState = \"idle\";\n\n/**\n * The pure transition function. Returns the NEXT state for `(state, event)`, or\n * the SAME state when the event is illegal in that state (a no-op).\n */\nexport function reduce(state: ConnectState, event: ConnectEvent): ConnectState {\n switch (event.type) {\n case \"CONNECT\":\n // A connect attempt is legal from any NON-in-flight state: a fresh client,\n // a terminal/failed state (retry), or an already-connected client\n // (re-connect with a new token). It is a no-op only while already\n // connecting (a second concurrent connect does nothing).\n return state === \"connecting\" ? state : \"connecting\";\n\n case \"CONNECT_SUCCESS\":\n // Only a connect IN FLIGHT can succeed. Any other state ignores it (a\n // stale/duplicate success after disconnect must not resurrect the client).\n return state === \"connecting\" ? \"connected\" : state;\n\n case \"CONNECT_DECLINED\":\n // Only a connect in flight can be declined.\n return state === \"connecting\" ? \"declined\" : state;\n\n case \"ERROR\":\n // A connect in flight can fail with a non-auth error. (A wrapper-call\n // failure while `connected` does NOT change the connect state - the\n // connection is still valid - so ERROR is a no-op when connected.)\n return state === \"connecting\" ? \"error\" : state;\n\n case \"TOKEN_EXPIRED\":\n // The membrane rejected the token. Legal from `connecting` (the token was\n // bad at connect time) or `connected` (it expired/was revoked mid-session).\n return state === \"connecting\" || state === \"connected\" ? \"expired\" : state;\n\n case \"DISCONNECT\":\n // Disconnect is ALWAYS reachable and idempotent: it moves any state to\n // `disconnected` (a no-op only when already there).\n return state === \"disconnected\" ? state : \"disconnected\";\n\n default: {\n // Exhaustiveness: a new event type must be handled above.\n const _never: never = event;\n return state;\n }\n }\n}\n\n/** Every state the machine can occupy (for reachability assertions). */\nexport const ALL_STATES: readonly ConnectState[] = [\n \"idle\",\n \"connecting\",\n \"connected\",\n \"declined\",\n \"expired\",\n \"error\",\n \"disconnected\",\n] as const;\n\n/** Whether the 7 tool wrappers may be called in this state. */\nexport function isConnected(state: ConnectState): boolean {\n return state === \"connected\";\n}\n","// Token persistence. SAFE BY DEFAULT: persistence is in-memory only, so the\n// token NEVER touches `localStorage` unless the host page opts in explicitly\n// (pass `storage: webStorage(localStorage)`). The v1 token-in credential is the\n// user's long-lived session JWT - writing it to `localStorage` would expose a\n// ~decade-long key to any script on the host page (one XSS = full context\n// theft), which the threat model forbids. So the default is memory; opt IN to\n// cross-reload persistence knowingly, never opt out. Pass `storage: null` to\n// disable persistence entirely (a no-op store).\n\nimport type { StorageAdapter } from \"./types.js\";\n\n/** The default storage key the token is persisted under. */\nexport const DEFAULT_STORAGE_KEY = \"usemycontext.token\";\n\n/** An in-memory storage adapter (SSR-safe; the DEFAULT - token never leaves JS memory). */\nexport function memoryStorage(): StorageAdapter {\n const map = new Map<string, string>();\n return {\n get: (k) => (map.has(k) ? (map.get(k) as string) : null),\n set: (k, v) => void map.set(k, v),\n remove: (k) => void map.delete(k),\n };\n}\n\n/** Wrap a Web Storage (localStorage/sessionStorage) as a StorageAdapter. */\nexport function webStorage(store: Storage): StorageAdapter {\n return {\n get: (k) => {\n try {\n return store.getItem(k);\n } catch {\n return null;\n }\n },\n set: (k, v) => {\n try {\n store.setItem(k, v);\n } catch {\n /* quota / privacy mode - degrade to no-persist, never throw */\n }\n },\n remove: (k) => {\n try {\n store.removeItem(k);\n } catch {\n /* ignore */\n }\n },\n };\n}\n\n/**\n * Resolve the storage adapter to use given the option:\n * - an explicit adapter -> use it (e.g. `webStorage(localStorage)` to opt IN\n * to cross-reload persistence, knowingly accepting host-page token exposure);\n * - `null` -> persistence disabled (a no-op adapter);\n * - `undefined` (the DEFAULT) -> in-memory. The token NEVER touches\n * `localStorage` unless the caller asks for it. Safe by default.\n */\nexport function resolveStorage(opt: StorageAdapter | null | undefined): StorageAdapter {\n if (opt === null) {\n return { get: () => null, set: () => {}, remove: () => {} };\n }\n if (opt) return opt;\n // DEFAULT: in-memory only. We deliberately do NOT auto-select localStorage -\n // persisting the long-lived session JWT to the host page is an opt-in choice.\n return memoryStorage();\n}\n","// The default `fetch`-based transport. Tests inject a mock transport instead, so\n// this module is never exercised by the (zero-network) test suite - it is the\n// production wiring that POSTs one JSON-RPC request to the membrane `/mcp`\n// endpoint with the user's bearer token.\n\nimport type { Transport, TransportResponse } from \"./types.js\";\n\n/** A `fetch`-backed Transport (the default when none is supplied). */\nexport const fetchTransport: Transport = async ({ url, token, body }): Promise<TransportResponse> => {\n const res = await fetch(url, {\n method: \"POST\",\n headers: {\n \"content-type\": \"application/json\",\n accept: \"application/json\",\n authorization: `Bearer ${token}`,\n },\n body: JSON.stringify(body),\n });\n let parsed: unknown = null;\n try {\n parsed = await res.json();\n } catch {\n parsed = null; // non-JSON / empty body (e.g. a 401 with no body)\n }\n return {\n status: res.status,\n body: parsed,\n wwwAuthenticate: res.headers.get(\"www-authenticate\"),\n };\n};\n","// The core client: `useMyContext()` (a framework-free factory) + the 7 tool\n// wrappers. It holds the user's OWN token and calls the membrane exactly like\n// Claude does - same trust model, new client shape. The service stays\n// structurally blind.\n//\n// v1 IS TOKEN-IN ONLY: `connect({ token })`. The full browser-OAuth-in-the-SDK\n// flow (a hosted popup on connect.usemycontext.ai) is v2, gated on the Phase 2\n// CORS landing - deliberately NOT built here.\n\nimport {\n initializeRequest,\n toolCallRequest,\n asJsonRpcResponse,\n resultText,\n isScopeDenied,\n NotConnectedError,\n TokenExpiredError,\n ScopeDeniedError,\n ToolCallError,\n TransportError,\n UseMyContextError,\n type ToolResult,\n} from \"./jsonrpc.js\";\nimport { reduce, INITIAL_STATE, isConnected } from \"./machine.js\";\nimport { resolveStorage, DEFAULT_STORAGE_KEY } from \"./storage.js\";\nimport { fetchTransport } from \"./transport.js\";\nimport type {\n ClientOptions,\n ConnectArgs,\n ConnectState,\n FileMeta,\n ProfileResult,\n AskOptions,\n AskResult,\n AskPassage,\n GetFileResult,\n SuggestUpdateResult,\n SharedContextResult,\n SharedContextEntry,\n StorageAdapter,\n Transport,\n} from \"./types.js\";\n\n/** The production membrane MCP endpoint. */\nexport const DEFAULT_ENDPOINT = \"https://mcp.usemycontext.ai/mcp\";\n\n/** The shape `useMyContext()` returns - the client handle. */\nexport interface UseMyContextClient {\n /** The current connect state. */\n readonly state: ConnectState;\n /** Convenience: true iff `state === \"connected\"`. */\n readonly connected: boolean;\n /** The held token, when connected (else null). */\n readonly token: string | null;\n\n /** Subscribe to state changes. Returns an unsubscribe fn. */\n subscribe(listener: (state: ConnectState) => void): () => void;\n\n /** v1 TOKEN-IN connect: validate the token against the membrane. */\n connect(args: ConnectArgs): Promise<ConnectState>;\n /** Clear the token + persisted storage; -> `disconnected`. */\n disconnect(): void;\n\n // --- the 7 MCP tool wrappers ---\n profile(): Promise<ProfileResult>;\n listFiles(): Promise<FileMeta[]>;\n searchFiles(query: string): Promise<FileMeta[]>;\n getFile(fileId: string): Promise<GetFileResult>;\n ask(query: string, opts?: AskOptions): Promise<AskResult>;\n suggestUpdate(suggestion: string): Promise<SuggestUpdateResult>;\n sharedContext(from?: string): Promise<SharedContextResult>;\n}\n\n/**\n * Create a UseMyContext client. Framework-free: the React hook wraps this.\n * Restores a persisted token (without revalidating) so a returning host page\n * starts `connected`; a stale token surfaces as `expired` on the first call.\n */\nexport function useMyContext(options: ClientOptions = {}): UseMyContextClient {\n const endpoint = options.endpoint ?? DEFAULT_ENDPOINT;\n const transport: Transport = options.transport ?? fetchTransport;\n const storage: StorageAdapter = resolveStorage(options.storage);\n const storageKey = options.storageKey ?? DEFAULT_STORAGE_KEY;\n\n const listeners = new Set<(state: ConnectState) => void>();\n let state: ConnectState = INITIAL_STATE;\n let token: string | null = null;\n\n // Restore a persisted token: a returning page is `connected` optimistically\n // (the membrane is the authority - a stale token -> `expired` on first call).\n const persisted = storage.get(storageKey);\n if (persisted) {\n token = persisted;\n state = \"connected\";\n }\n\n function setState(next: ConnectState): void {\n if (next === state) return;\n state = next;\n options.onStateChange?.(state);\n for (const l of listeners) l(state);\n }\n\n function dispatch(event: Parameters<typeof reduce>[1]): void {\n setState(reduce(state, event));\n }\n\n /** One JSON-RPC round-trip against the membrane with the held token. */\n async function rpc(body: unknown): Promise<unknown> {\n if (!token) throw new NotConnectedError();\n let res;\n try {\n res = await transport({ url: endpoint, token, body });\n } catch (e) {\n throw new TransportError(\n `Transport failed: ${e instanceof Error ? e.message : String(e)}`,\n );\n }\n // A 401 means the token is bad/expired/revoked. Drive the machine to\n // `expired` and throw - the host should re-connect.\n if (res.status === 401) {\n dispatch({ type: \"TOKEN_EXPIRED\" });\n throw new TokenExpiredError(undefined, res.wwwAuthenticate ?? undefined);\n }\n const parsed = asJsonRpcResponse(res.body);\n if (parsed.error) {\n if (isScopeDenied(parsed.error.code)) {\n throw new ScopeDeniedError(parsed.error.message);\n }\n throw new ToolCallError(parsed.error.message, parsed.error.code);\n }\n return parsed.result;\n }\n\n /** A tools/call that returns the single rendered text block. */\n async function callTool(name: string, args: Record<string, unknown>): Promise<string> {\n if (!isConnected(state)) throw new NotConnectedError();\n const result = (await rpc(toolCallRequest(name, args))) as ToolResult;\n if (result.isError) {\n throw new ToolCallError(resultText(result) || `${name} failed.`);\n }\n return resultText(result);\n }\n\n return {\n get state() {\n return state;\n },\n get connected() {\n return state === \"connected\";\n },\n get token() {\n return state === \"connected\" ? token : null;\n },\n\n subscribe(listener) {\n listeners.add(listener);\n return () => void listeners.delete(listener);\n },\n\n async connect({ token: t }: ConnectArgs): Promise<ConnectState> {\n if (typeof t !== \"string\" || t.length === 0) {\n // A bad arg is a developer error, not a state transition.\n throw new UseMyContextConnectArgError();\n }\n dispatch({ type: \"CONNECT\" });\n token = t;\n try {\n const res = await transport({ url: endpoint, token: t, body: initializeRequest() });\n if (res.status === 401) {\n token = null;\n dispatch({ type: \"TOKEN_EXPIRED\" });\n throw new TokenExpiredError(undefined, res.wwwAuthenticate ?? undefined);\n }\n // Validate the handshake came back as a well-formed JSON-RPC result.\n const parsed = asJsonRpcResponse(res.body);\n if (parsed.error) {\n token = null;\n dispatch({ type: \"ERROR\" });\n throw new ToolCallError(parsed.error.message, parsed.error.code);\n }\n dispatch({ type: \"CONNECT_SUCCESS\" });\n if (storage) storage.set(storageKey, t);\n return state;\n } catch (e) {\n token = null;\n // TokenExpiredError already drove the machine to `expired`; any other\n // failure is a non-auth `error`.\n if (!(e instanceof TokenExpiredError)) {\n dispatch({ type: \"ERROR\" });\n if (e instanceof TransportError || e instanceof ToolCallError) throw e;\n throw new TransportError(\n `Connect failed: ${e instanceof Error ? e.message : String(e)}`,\n );\n }\n throw e;\n }\n },\n\n disconnect(): void {\n token = null;\n storage.remove(storageKey);\n dispatch({ type: \"DISCONNECT\" });\n },\n\n // --- profile ---------------------------------------------------------\n async profile(): Promise<ProfileResult> {\n const text = await callTool(\"profile\", {});\n // The membrane serves the compiled composite as plain text, OR (no compile\n // yet) the JSON of `{ facts: [...] }`. Detect the fallback by parsing.\n const facts = tryParseFacts(text);\n if (facts) return { composite: text, facts };\n return { composite: text };\n },\n\n // --- list_files / search_files (JSON array of FileMeta) --------------\n async listFiles(): Promise<FileMeta[]> {\n return parseFileList(await callTool(\"list_files\", {}));\n },\n async searchFiles(query: string): Promise<FileMeta[]> {\n if (typeof query !== \"string\") throw new UseMyContextConnectArgError(\"search query must be a string\");\n return parseFileList(await callTool(\"search_files\", { query }));\n },\n\n // --- get_file --------------------------------------------------------\n async getFile(fileId: string): Promise<GetFileResult> {\n if (typeof fileId !== \"string\" || !fileId) {\n throw new UseMyContextConnectArgError(\"fileId must be a non-empty string\");\n }\n const text = await callTool(\"get_file\", { fileId });\n return { text, downloadUrl: parseDownloadUrl(text) };\n },\n\n // --- ask_docs --------------------------------------------------------\n async ask(query: string, opts: AskOptions = {}): Promise<AskResult> {\n if (typeof query !== \"string\" || !query) {\n throw new UseMyContextConnectArgError(\"ask query must be a non-empty string\");\n }\n const args: Record<string, unknown> = { query };\n if (typeof opts.k === \"number\") args.k = opts.k;\n if (typeof opts.projectId === \"string\") args.projectId = opts.projectId;\n const text = await callTool(\"ask_docs\", args);\n return { passages: parseAskPassages(text), text };\n },\n\n // --- suggest_update (the one write) ----------------------------------\n async suggestUpdate(suggestion: string): Promise<SuggestUpdateResult> {\n if (typeof suggestion !== \"string\" || !suggestion.trim()) {\n throw new UseMyContextConnectArgError(\"suggestion must be a non-empty string\");\n }\n const text = await callTool(\"suggest_update\", { suggestion });\n const m = text.match(/\\(id:\\s*([^)]+)\\)/);\n return { id: m ? m[1].trim() : undefined, text };\n },\n\n // --- shared_context --------------------------------------------------\n async sharedContext(from?: string): Promise<SharedContextResult> {\n const args: Record<string, unknown> = {};\n if (typeof from === \"string\" && from) args.from = from;\n const text = await callTool(\"shared_context\", args);\n return from ? parseSharedRead(text) : parseSharedList(text);\n },\n };\n}\n\n/** Thrown for a bad SDK call argument (a developer error, not a state event). */\nexport class UseMyContextConnectArgError extends UseMyContextError {\n constructor(message = \"connect() requires a non-empty token string.\") {\n super(message);\n this.name = \"UseMyContextConnectArgError\";\n }\n}\n\n// --- parsers (decode the membrane's RENDERED text back to typed shapes) ---\n\n/** Parse `profile`'s JSON fallback (`{facts:[...]}`); null when it's prose. */\nfunction tryParseFacts(text: string): string[] | undefined {\n const trimmed = text.trimStart();\n if (!trimmed.startsWith(\"{\")) return undefined;\n try {\n const obj = JSON.parse(text) as { facts?: unknown };\n if (Array.isArray(obj.facts)) return obj.facts.filter((f): f is string => typeof f === \"string\");\n } catch {\n /* prose composite that happens to start with \"{\" - treat as composite */\n }\n return undefined;\n}\n\n/** Parse a list/search JSON array into FileMeta[]. */\nfunction parseFileList(text: string): FileMeta[] {\n try {\n const arr = JSON.parse(text) as unknown;\n if (!Array.isArray(arr)) return [];\n return arr.map((r) => {\n const o = (r ?? {}) as Record<string, unknown>;\n return {\n id: String(o.id ?? \"\"),\n name: String(o.name ?? \"\"),\n size: typeof o.size === \"number\" ? o.size : 0,\n contentType: String(o.contentType ?? \"\"),\n modified: String(o.modified ?? \"\"),\n ...(typeof o.status === \"string\" ? { status: o.status as FileMeta[\"status\"] } : {}),\n };\n });\n } catch {\n return [];\n }\n}\n\n/** Pull a `Download link ... : <url>` out of a get_file render. */\nfunction parseDownloadUrl(text: string): string | undefined {\n const m = text.match(/Download link[^:]*:\\s*(\\S+)/);\n return m ? m[1] : undefined;\n}\n\n/**\n * Parse `renderAskDocs` output: blocks separated by a blank line, each a\n * `[n] file · scope · score X.XXX` citation line then the passage text. An empty\n * result is the calm \"No relevant passages...\" sentence -> zero passages.\n */\nfunction parseAskPassages(text: string): AskPassage[] {\n if (/^No relevant passages/i.test(text.trimStart())) return [];\n const blocks = text.split(\"\\n\\n\");\n const out: AskPassage[] = [];\n for (const block of blocks) {\n const nl = block.indexOf(\"\\n\");\n const citation = nl === -1 ? block : block.slice(0, nl);\n const body = nl === -1 ? \"\" : block.slice(nl + 1);\n const m = citation.match(/^\\[(\\d+)\\]\\s*(.*)$/);\n if (!m) continue;\n const index = Number(m[1]);\n const rest = m[2];\n // rest = `file · scope · score N.NNN`\n const parts = rest.split(\" · \");\n const passage: AskPassage = { index, text: body };\n if (parts[0]) passage.file = parts[0].trim();\n if (parts[1]) passage.scope = parts[1].trim();\n const scoreM = rest.match(/score\\s+([\\d.]+)/);\n if (scoreM) passage.score = Number(scoreM[1]);\n out.push(passage);\n }\n return out;\n}\n\n/** Parse `renderSharedContext` LIST output (lines `- who (from: grantId)`). */\nfunction parseSharedList(text: string): SharedContextResult {\n if (/^No one has shared/i.test(text.trimStart())) {\n return { mode: \"list\", shares: [], composite: null, text };\n }\n const shares: SharedContextEntry[] = [];\n for (const line of text.split(\"\\n\")) {\n const m = line.match(/^-\\s*(.*?)\\s*\\(from:\\s*([^)]+)\\)\\s*$/);\n if (m) shares.push({ ownerLabel: m[1].trim(), grantId: m[2].trim() });\n }\n return { mode: \"list\", shares, composite: null, text };\n}\n\n/** Parse `renderSharedContext` READ output (`Shared context from X:\\n\\n<text>`). */\nfunction parseSharedRead(text: string): SharedContextResult {\n if (/not available/i.test(text)) {\n return { mode: \"read\", shares: [], composite: null, text };\n }\n const m = text.match(/^Shared context from [^:]*:\\n\\n([\\s\\S]*)$/);\n const composite = m ? m[1] : text;\n return { mode: \"read\", shares: [], composite, text };\n}\n","// The React surface: `useMyContextReact()` (a hook over the core client) and the\n// zero-config `<ConnectMyContext />` drop-in.\n//\n// React is an OPTIONAL peer dependency. This module lives behind the `./react`\n// export so importing the core `usemycontext` entry never pulls React in; tsup\n// marks `react` external so it is never bundled.\n\nimport * as React from \"react\";\nimport { useMyContext, type UseMyContextClient } from \"./client.js\";\nimport type { ClientOptions, ConnectState, ConnectArgs } from \"./types.js\";\n\n/** What the React hook returns: the live state + the client's bound methods. */\nexport interface UseMyContextReactValue {\n /** The current connect state (re-renders on change). */\n state: ConnectState;\n /** Convenience: true iff `state === \"connected\"`. */\n connected: boolean;\n /** The held token when connected, else null. */\n token: string | null;\n /** The underlying framework-free client (the 7 wrappers live here). */\n client: UseMyContextClient;\n /** v1 TOKEN-IN connect. */\n connect: (args: ConnectArgs) => Promise<ConnectState>;\n /** Clear the token; -> `disconnected`. */\n disconnect: () => void;\n}\n\n/**\n * The React hook. Creates ONE stable client per component instance and\n * subscribes to its state so the component re-renders on every transition.\n */\nexport function useMyContextReact(options: ClientOptions = {}): UseMyContextReactValue {\n // One stable client for the component's lifetime. options are read once on\n // first render (the typical usage passes a constant); a changing endpoint\n // mid-mount is out of v1 scope.\n const clientRef = React.useRef<UseMyContextClient | null>(null);\n if (clientRef.current === null) {\n clientRef.current = useMyContext(options);\n }\n const client = clientRef.current;\n\n const [state, setState] = React.useState<ConnectState>(client.state);\n\n React.useEffect(() => {\n // Subscribe AND sync once, in case the state changed between create + effect.\n setState(client.state);\n const unsub = client.subscribe(setState);\n return unsub;\n }, [client]);\n\n const connect = React.useCallback((args: ConnectArgs) => client.connect(args), [client]);\n const disconnect = React.useCallback(() => client.disconnect(), [client]);\n\n return {\n state,\n connected: state === \"connected\",\n token: client.token,\n client,\n connect,\n disconnect,\n };\n}\n\n/** Props for the drop-in button. */\nexport interface ConnectMyContextProps {\n /**\n * v1 is TOKEN-IN: supply the user's token (the full browser-OAuth popup is\n * v2). When given, the button calls `connect({ token })` on click.\n */\n token?: string;\n /** Forwarded to the underlying client (endpoint / transport / storage). */\n options?: ClientOptions;\n /** Called after a successful connect. */\n onConnect?: (state: ConnectState) => void;\n /** Called when a connect fails. */\n onError?: (error: unknown) => void;\n /** Override the button label per state. */\n label?: Partial<Record<ConnectState, string>>;\n /** Extra class name(s) for the button. */\n className?: string;\n}\n\nconst DEFAULT_LABELS: Record<ConnectState, string> = {\n idle: \"Connect my context\",\n connecting: \"Connecting...\",\n connected: \"Connected\",\n declined: \"Connect my context\",\n expired: \"Reconnect my context\",\n error: \"Retry connect\",\n disconnected: \"Connect my context\",\n};\n\n/**\n * A zero-config connect button. Renders a single <button> whose label tracks the\n * connect state; clicking it runs the v1 token-in connect. Unstyled beyond a\n * stable class name (`umc-connect-button`) so the host owns the look.\n */\nexport function ConnectMyContext(props: ConnectMyContextProps): React.ReactElement {\n const { token, options, onConnect, onError, label, className } = props;\n const { state, connect, disconnect } = useMyContextReact(options);\n\n const text = (label && label[state]) || DEFAULT_LABELS[state];\n const busy = state === \"connecting\";\n const isConnected = state === \"connected\";\n\n const onClick = React.useCallback(async () => {\n if (isConnected) {\n disconnect();\n return;\n }\n if (!token) {\n onError?.(new Error(\"ConnectMyContext: no `token` prop (v1 is token-in only).\"));\n return;\n }\n try {\n const next = await connect({ token });\n onConnect?.(next);\n } catch (e) {\n onError?.(e);\n }\n }, [isConnected, disconnect, token, connect, onConnect, onError]);\n\n return React.createElement(\n \"button\",\n {\n type: \"button\",\n className: [\"umc-connect-button\", className].filter(Boolean).join(\" \"),\n \"data-umc-state\": state,\n disabled: busy,\n \"aria-busy\": busy || undefined,\n onClick,\n },\n isConnected ? \"Disconnect\" : text,\n );\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "usemycontext",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.2",
|
|
4
4
|
"description": "The official UseMyContext SDK - a typed client + React hook for the structurally-blind personal-context MCP. npm i usemycontext, then drop the user's compiled context straight into any AI app.",
|
|
5
5
|
"private": false,
|
|
6
6
|
"license": "MIT",
|
|
@@ -58,5 +58,8 @@
|
|
|
58
58
|
"tsup": "^8.3.0",
|
|
59
59
|
"typescript": "^5.8.3",
|
|
60
60
|
"vitest": "^4.1.8"
|
|
61
|
+
},
|
|
62
|
+
"dependencies": {
|
|
63
|
+
"usemycontext": "^1.0.1"
|
|
61
64
|
}
|
|
62
65
|
}
|