@wakeshift/sdk 0.2.0 → 0.3.0
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/CHANGELOG.md +29 -0
- package/README.md +13 -22
- package/dist/events.d.ts +7 -3
- package/dist/events.js +46 -11
- package/dist/events.js.map +1 -1
- package/dist/harness.js +1 -1
- package/dist/harness.js.map +1 -1
- package/dist/index.d.ts +0 -1
- package/dist/index.js +0 -1
- package/dist/index.js.map +1 -1
- package/dist/key.d.ts +1 -1
- package/dist/key.js.map +1 -1
- package/dist/retry.js.map +1 -1
- package/dist/wakeshift.d.ts +16 -4
- package/dist/wakeshift.js +7 -9
- package/dist/wakeshift.js.map +1 -1
- package/package.json +2 -2
- package/dist/guest.d.ts +0 -119
- package/dist/guest.js +0 -506
- package/dist/guest.js.map +0 -1
- package/dist/limits.d.ts +0 -19
- package/dist/limits.js +0 -105
- package/dist/limits.js.map +0 -1
- package/dist/sealed.d.ts +0 -4
- package/dist/sealed.js +0 -38
- package/dist/sealed.js.map +0 -1
package/dist/harness.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"harness.js","sourceRoot":"","sources":["../src/harness.ts"],"names":[],"mappings":"AAAA,
|
|
1
|
+
{"version":3,"file":"harness.js","sourceRoot":"","sources":["../src/harness.ts"],"names":[],"mappings":"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","sourcesContent":["// harnessAgent names the agent an MCP client signs in as: its\n// harness's ID (\"copilot-cli\" → copilot, \"Claude Code\" → claude-code), as\n// topics name it, else its name as an ID. A port\n// of the core's harnesses.AgentID: test/agent-ids.json is the Go\n// function's output, and both sides' tests check it.\n\ninterface Known {\n id: string;\n clients: string[];\n /** Its client name is one others send too (Hermes Agent's \"mcp\"): it keeps its own ID. */\n unsure?: boolean;\n}\n\n// The core's harness table (internal/harnesses): only what naming needs.\nconst known: Known[] = [\n { id: \"codex\", clients: [\"codex-mcp-client\"] },\n { id: \"claude-code\", clients: [\"claude-code\"] },\n { id: \"cursor\", clients: [\"Cursor\", \"cursor-vscode\"] },\n { id: \"cursor-cloud\", clients: [] },\n { id: \"grok-bot\", clients: [] },\n { id: \"copilot\", clients: [\"copilot-cli\"] },\n { id: \"opencode\", clients: [\"opencode\"] },\n { id: \"antigravity\", clients: [\"antigravity-client\"] },\n { id: \"openclaw\", clients: [\"openclaw-bundle-mcp\"] },\n { id: \"hermes\", clients: [\"mcp\"], unsure: true },\n { id: \"chatgpt\", clients: [\"openai-mcp\"] },\n { id: \"gemini\", clients: [\"gemini-cli-mcp-client\"] },\n { id: \"goose\", clients: [\"goose-cli\", \"goose-desktop\"] },\n { id: \"cline\", clients: [\"Cline\"] },\n { id: \"amp\", clients: [] },\n { id: \"devin\", clients: [] },\n { id: \"vscode\", clients: [\"Visual Studio Code\", \"Visual Studio Code - Insiders\"] },\n];\n\n/**\n * The agent ID an MCP client's name maps to: its harness's ID, else the\n * name as an ID (2–40 lowercase letters, digits and dashes; \"agent\" if\n * nothing's left).\n */\nexport function harnessAgent(client: string): string {\n const name = client.trim().toLowerCase();\n if (name) {\n for (const h of known) {\n if (h.clients.some((c) => c.toLowerCase() === name)) {\n if (!h.unsure) return h.id;\n break;\n }\n }\n }\n const id = slug(client);\n for (const h of known) {\n if (h.unsure) continue;\n if (id === h.id || id.startsWith(h.id + \"-\")) return h.id;\n if (h.clients.some((c) => id === slug(c))) return h.id;\n }\n return id;\n}\n\n// slug is a name as an agent ID: lowercase letters, digits and dashes, up\n// to 40 characters, without anything in parentheses (\"agent\" if fewer than\n// 2 are left).\nfunction slug(name: string): string {\n let n = name.toLowerCase();\n const i = n.indexOf(\"(\");\n if (i > 0) n = n.slice(0, i);\n let out = \"\";\n let dash = false;\n for (const r of n.trim()) {\n if ((r >= \"a\" && r <= \"z\") || (r >= \"0\" && r <= \"9\")) {\n out += r;\n dash = false;\n } else if (!dash && out.length > 0) {\n out += \"-\";\n dash = true;\n }\n }\n let id = out.replace(/^-+|-+$/g, \"\");\n if (id.length > 40) id = id.slice(0, 40).replace(/^-+|-+$/g, \"\");\n return id.length < 2 ? \"agent\" : id;\n}\n"]}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
export { Wakeshift, DEFAULT_CORE, SESSION_ARG, HARNESS_ARG, CONVERSATION_ARG, UNKNOWN_CLIENT_WARNING, type WakeshiftOptions, type AppInfo, type Call, type CallOptions, type ClientInfoSource, type Duration, type SubscribeOptions, type Subscription, type Addition, type Recognised, type TopicEvent, type Published, type SendStatus, type Via, type TopicStatus, type SubscriptionStatus, type PublishUrl, type ToolExtra, type Manifest, type AgentScope, type ScopeEvent, } from "./wakeshift.js";
|
|
2
|
-
export { GuestAuth, guestOf, type Guest, type GuestAuthOptions, type GuestAuthInfo } from "./guest.js";
|
|
3
2
|
export { harnessAgent } from "./harness.js";
|
|
4
3
|
export { WakeshiftError, isCode } from "./errors.js";
|
|
5
4
|
export { parseKey, signAssertion, type AppKey } from "./key.js";
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
export { Wakeshift, DEFAULT_CORE, SESSION_ARG, HARNESS_ARG, CONVERSATION_ARG, UNKNOWN_CLIENT_WARNING, } from "./wakeshift.js";
|
|
2
|
-
export { GuestAuth, guestOf } from "./guest.js";
|
|
3
2
|
export { harnessAgent } from "./harness.js";
|
|
4
3
|
export { WakeshiftError, isCode } from "./errors.js";
|
|
5
4
|
export { parseKey, signAssertion } from "./key.js";
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,SAAS,EACT,YAAY,EACZ,WAAW,EACX,WAAW,EACX,gBAAgB,EAChB,sBAAsB,GAsBvB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,SAAS,EACT,YAAY,EACZ,WAAW,EACX,WAAW,EACX,gBAAgB,EAChB,sBAAsB,GAsBvB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAE,cAAc,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrD,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAe,MAAM,UAAU,CAAC;AAChE,OAAO,EACL,SAAS,EACT,SAAS,EACT,YAAY,EACZ,eAAe,EACf,0BAA0B,EAC1B,4BAA4B,EAC5B,qBAAqB,GAQtB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,SAAS,EAAE,QAAQ,IAAI,eAAe,EAAE,MAAM,WAAW,CAAC","sourcesContent":["export {\n Wakeshift,\n DEFAULT_CORE,\n SESSION_ARG,\n HARNESS_ARG,\n CONVERSATION_ARG,\n UNKNOWN_CLIENT_WARNING,\n type WakeshiftOptions,\n type AppInfo,\n type Call,\n type CallOptions,\n type ClientInfoSource,\n type Duration,\n type SubscribeOptions,\n type Subscription,\n type Addition,\n type Recognised,\n type TopicEvent,\n type Published,\n type SendStatus,\n type Via,\n type TopicStatus,\n type SubscriptionStatus,\n type PublishUrl,\n type ToolExtra,\n type Manifest,\n type AgentScope,\n type ScopeEvent,\n} from \"./wakeshift.js\";\nexport { harnessAgent } from \"./harness.js\";\nexport { WakeshiftError, isCode } from \"./errors.js\";\nexport { parseKey, signAssertion, type AppKey } from \"./key.js\";\nexport {\n WakeEvent,\n ArgsError,\n speaksEvents,\n EVENT_TOOL_TEXT,\n SUBSCRIBE_TOOL_DESCRIPTION,\n UNSUBSCRIBE_TOOL_DESCRIPTION,\n LIST_TOOL_DESCRIPTION,\n type EventOptions,\n type EmitOptions,\n type CallerSubscription,\n type EventTypeManifest,\n type AttachOptions,\n type Identity,\n type Subscriber,\n} from \"./events.js\";\nexport { EXTENSION_KEY, LEGACY_KEY, TEXT_META, REVISION as EVENTS_REVISION } from \"./spec.js\";\n"]}
|
package/dist/key.d.ts
CHANGED
|
@@ -8,7 +8,7 @@ export interface AppKey {
|
|
|
8
8
|
/** The app's ID, for an older key that names it; null for a current key (ask Wakeshift: `wake.app()`). */
|
|
9
9
|
appId: string | null;
|
|
10
10
|
privateKey: KeyObject;
|
|
11
|
-
/** The 32-byte seed
|
|
11
|
+
/** The 32-byte seed the private key is made from. Never send or log it. */
|
|
12
12
|
seed: Buffer;
|
|
13
13
|
/** The key's ID in assertions' headers: base64url of the first 16 bytes of the public key's SHA-256. */
|
|
14
14
|
kid: string;
|
package/dist/key.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"key.js","sourceRoot":"","sources":["../src/key.ts"],"names":[],"mappings":"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","sourcesContent":["import { createHash, createPrivateKey, createPublicKey, randomBytes, sign, type KeyObject } from \"node:crypto\";\n\n// An app key from the Wakeshift console is the app's Ed25519 private key.\n// Current keys are\n//\n// wst_<50 base58 characters>\n//\n// 36 bytes, the 32-byte seed then the CRC32 (IEEE, big-endian) of the\n// seed, read as one big-endian integer and written in base58 (Bitcoin's\n// alphabet), left-padded with \"1\". They name no app: Wakeshift finds the\n// app by the key's kid, which every assertion's header carries, and says\n// which it is (GET /api/apps/v1/app). Older keys, which keep working, are\n//\n// wst_<test|live>_<app id>_<seed, base64url>\n//\n// The two can't be confused: base58 has no \"_\". The key never goes over\n// the wire: it signs short-lived assertions, and Wakeshift keeps only the\n// public half.\n\nexport interface AppKey {\n /**\n * An older key's mode; null for a current key.\n * @deprecated Modes mean nothing now, and current keys have none.\n */\n mode: \"test\" | \"live\" | null;\n /** The app's ID, for an older key that names it; null for a current key (ask Wakeshift: `wake.app()`). */\n appId: string | null;\n privateKey: KeyObject;\n /** The 32-byte seed: what the SDK's own signed values (guest sign-in) are keyed from. */\n seed: Buffer;\n /** The key's ID in assertions' headers: base64url of the first 16 bytes of the public key's SHA-256. */\n kid: string;\n}\n\nconst appIdRE = /^[a-z][a-z0-9-]{1,39}$/;\nconst seedRE = /^[A-Za-z0-9_-]{43}$/;\nconst alphabet = \"123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz\";\nconst LEN = 50;\nconst LIMIT = 1n << 288n;\n// PKCS #8 for an Ed25519 key, before its 32-byte seed (RFC 8410).\nconst pkcs8Prefix = Buffer.from(\"302e020100300506032b657004220420\", \"hex\");\n\n// Errors never include the key.\nconst errFormat = \"wakeshift: an app key is wst_ followed by 50 letters and digits (or an older wst_test_… or wst_live_… key)\";\nconst errMistyped = \"wakeshift: the app key is cut short or mistyped\";\n\n// CRC32 (IEEE). zlib.crc32 needs Node 22.2; the package supports 22.0.\nconst crcTable = (() => {\n const t = new Uint32Array(256);\n for (let n = 0; n < 256; n++) {\n let c = n;\n for (let k = 0; k < 8; k++) c = c & 1 ? 0xedb88320 ^ (c >>> 1) : c >>> 1;\n t[n] = c >>> 0;\n }\n return t;\n})();\n\nfunction crc32(b: Uint8Array): number {\n let c = 0xffffffff;\n for (const x of b) c = crcTable[(c ^ x) & 0xff] ^ (c >>> 8);\n return (c ^ 0xffffffff) >>> 0;\n}\n\n/** Reads an app key from the console, either format. Throws on anything else. */\nexport function parseKey(key: string): AppKey {\n const s = String(key ?? \"\").trim();\n if (!s.startsWith(\"wst_\")) throw new Error(\"wakeshift: an app key starts with wst_\");\n const rest = s.slice(4);\n const i = rest.indexOf(\"_\");\n if (i >= 0) return parseOld(rest.slice(0, i), rest.slice(i + 1));\n if (rest.length !== LEN) throw new Error(errMistyped);\n let n = 0n;\n for (const ch of rest) {\n const d = alphabet.indexOf(ch);\n if (d < 0) throw new Error(errMistyped);\n n = n * 58n + BigInt(d);\n }\n if (n >= LIMIT) throw new Error(errMistyped);\n const b = Buffer.from(n.toString(16).padStart(72, \"0\"), \"hex\");\n const seed = Buffer.from(b.subarray(0, 32));\n if (crc32(seed) !== b.readUInt32BE(32)) throw new Error(errMistyped);\n return fromSeed(null, null, seed);\n}\n\n// An older key: wst_<mode>_<app id>_<seed>. App IDs have no \"_\"; the seed\n// (base64url) may.\nfunction parseOld(mode: string, after: string): AppKey {\n if (mode !== \"test\" && mode !== \"live\") throw new Error(errFormat);\n const j = after.indexOf(\"_\");\n const appId = j < 0 ? \"\" : after.slice(0, j);\n if (!appIdRE.test(appId)) throw new Error(\"wakeshift: the app key has no app ID\");\n const seed = after.slice(j + 1);\n const raw = seedRE.test(seed) ? Buffer.from(seed, \"base64url\") : Buffer.alloc(0);\n if (raw.length !== 32) throw new Error(errMistyped);\n return fromSeed(mode, appId, raw);\n}\n\nfunction fromSeed(mode: AppKey[\"mode\"], appId: string | null, seed: Buffer): AppKey {\n const privateKey = createPrivateKey({ key: Buffer.concat([pkcs8Prefix, seed]), format: \"der\", type: \"pkcs8\" });\n return { mode, appId, privateKey, seed, kid: keyIdOf(rawPublicKey(privateKey)) };\n}\n\nfunction rawPublicKey(k: KeyObject): Buffer {\n return Buffer.from(createPublicKey(k).export({ format: \"jwk\" }).x as string, \"base64url\");\n}\n\n/** A raw 32-byte Ed25519 public key's kid: base64url of the first 16 bytes of its SHA-256. */\nexport function keyIdOf(publicKey: Uint8Array): string {\n return createHash(\"sha256\").update(publicKey).digest().subarray(0, 16).toString(\"base64url\");\n}\n\n/** The app's public key, base64url (what the console stores). */\nexport function publicKeyOf(k: AppKey): string {\n return rawPublicKey(k.privateKey).toString(\"base64url\");\n}\n\nconst b64 = (v: unknown) => Buffer.from(typeof v === \"string\" ? v : JSON.stringify(v)).toString(\"base64url\");\n\n/**\n * Signs a fresh assertion of the app's identity for core (its base URL,\n * without a trailing slash): a compact JWS, alg EdDSA, typ app+jwt, with\n * the key's kid, living two minutes. iss and sub are the app's ID when\n * it's known (an older key names it; pass appId once Wakeshift has said\n * it), else the kid.\n */\nexport function signAssertion(k: AppKey, core: string, now = Date.now(), appId?: string | null): string {\n const iat = Math.floor(now / 1000);\n const who = appId || k.appId || k.kid;\n const claims = {\n iss: who,\n sub: who,\n aud: core + \"/api/apps\",\n iat,\n exp: iat + 120,\n jti: randomBytes(16).toString(\"base64url\"),\n };\n const input = b64({ alg: \"EdDSA\", typ: \"app+jwt\", kid: k.kid }) + \".\" + b64(claims);\n return input + \".\" + sign(null, Buffer.from(input), k.privateKey).toString(\"base64url\");\n}\n"]}
|
|
1
|
+
{"version":3,"file":"key.js","sourceRoot":"","sources":["../src/key.ts"],"names":[],"mappings":"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","sourcesContent":["import { createHash, createPrivateKey, createPublicKey, randomBytes, sign, type KeyObject } from \"node:crypto\";\n\n// An app key from the Wakeshift console is the app's Ed25519 private key.\n// Current keys are\n//\n// wst_<50 base58 characters>\n//\n// 36 bytes, the 32-byte seed then the CRC32 (IEEE, big-endian) of the\n// seed, read as one big-endian integer and written in base58 (Bitcoin's\n// alphabet), left-padded with \"1\". They name no app: Wakeshift finds the\n// app by the key's kid, which every assertion's header carries, and says\n// which it is (GET /api/apps/v1/app). Older keys, which keep working, are\n//\n// wst_<test|live>_<app id>_<seed, base64url>\n//\n// The two can't be confused: base58 has no \"_\". The key never goes over\n// the wire: it signs short-lived assertions, and Wakeshift keeps only the\n// public half.\n\nexport interface AppKey {\n /**\n * An older key's mode; null for a current key.\n * @deprecated Modes mean nothing now, and current keys have none.\n */\n mode: \"test\" | \"live\" | null;\n /** The app's ID, for an older key that names it; null for a current key (ask Wakeshift: `wake.app()`). */\n appId: string | null;\n privateKey: KeyObject;\n /** The 32-byte seed the private key is made from. Never send or log it. */\n seed: Buffer;\n /** The key's ID in assertions' headers: base64url of the first 16 bytes of the public key's SHA-256. */\n kid: string;\n}\n\nconst appIdRE = /^[a-z][a-z0-9-]{1,39}$/;\nconst seedRE = /^[A-Za-z0-9_-]{43}$/;\nconst alphabet = \"123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz\";\nconst LEN = 50;\nconst LIMIT = 1n << 288n;\n// PKCS #8 for an Ed25519 key, before its 32-byte seed (RFC 8410).\nconst pkcs8Prefix = Buffer.from(\"302e020100300506032b657004220420\", \"hex\");\n\n// Errors never include the key.\nconst errFormat = \"wakeshift: an app key is wst_ followed by 50 letters and digits (or an older wst_test_… or wst_live_… key)\";\nconst errMistyped = \"wakeshift: the app key is cut short or mistyped\";\n\n// CRC32 (IEEE). zlib.crc32 needs Node 22.2; the package supports 22.0.\nconst crcTable = (() => {\n const t = new Uint32Array(256);\n for (let n = 0; n < 256; n++) {\n let c = n;\n for (let k = 0; k < 8; k++) c = c & 1 ? 0xedb88320 ^ (c >>> 1) : c >>> 1;\n t[n] = c >>> 0;\n }\n return t;\n})();\n\nfunction crc32(b: Uint8Array): number {\n let c = 0xffffffff;\n for (const x of b) c = crcTable[(c ^ x) & 0xff] ^ (c >>> 8);\n return (c ^ 0xffffffff) >>> 0;\n}\n\n/** Reads an app key from the console, either format. Throws on anything else. */\nexport function parseKey(key: string): AppKey {\n const s = String(key ?? \"\").trim();\n if (!s.startsWith(\"wst_\")) throw new Error(\"wakeshift: an app key starts with wst_\");\n const rest = s.slice(4);\n const i = rest.indexOf(\"_\");\n if (i >= 0) return parseOld(rest.slice(0, i), rest.slice(i + 1));\n if (rest.length !== LEN) throw new Error(errMistyped);\n let n = 0n;\n for (const ch of rest) {\n const d = alphabet.indexOf(ch);\n if (d < 0) throw new Error(errMistyped);\n n = n * 58n + BigInt(d);\n }\n if (n >= LIMIT) throw new Error(errMistyped);\n const b = Buffer.from(n.toString(16).padStart(72, \"0\"), \"hex\");\n const seed = Buffer.from(b.subarray(0, 32));\n if (crc32(seed) !== b.readUInt32BE(32)) throw new Error(errMistyped);\n return fromSeed(null, null, seed);\n}\n\n// An older key: wst_<mode>_<app id>_<seed>. App IDs have no \"_\"; the seed\n// (base64url) may.\nfunction parseOld(mode: string, after: string): AppKey {\n if (mode !== \"test\" && mode !== \"live\") throw new Error(errFormat);\n const j = after.indexOf(\"_\");\n const appId = j < 0 ? \"\" : after.slice(0, j);\n if (!appIdRE.test(appId)) throw new Error(\"wakeshift: the app key has no app ID\");\n const seed = after.slice(j + 1);\n const raw = seedRE.test(seed) ? Buffer.from(seed, \"base64url\") : Buffer.alloc(0);\n if (raw.length !== 32) throw new Error(errMistyped);\n return fromSeed(mode, appId, raw);\n}\n\nfunction fromSeed(mode: AppKey[\"mode\"], appId: string | null, seed: Buffer): AppKey {\n const privateKey = createPrivateKey({ key: Buffer.concat([pkcs8Prefix, seed]), format: \"der\", type: \"pkcs8\" });\n return { mode, appId, privateKey, seed, kid: keyIdOf(rawPublicKey(privateKey)) };\n}\n\nfunction rawPublicKey(k: KeyObject): Buffer {\n return Buffer.from(createPublicKey(k).export({ format: \"jwk\" }).x as string, \"base64url\");\n}\n\n/** A raw 32-byte Ed25519 public key's kid: base64url of the first 16 bytes of its SHA-256. */\nexport function keyIdOf(publicKey: Uint8Array): string {\n return createHash(\"sha256\").update(publicKey).digest().subarray(0, 16).toString(\"base64url\");\n}\n\n/** The app's public key, base64url (what the console stores). */\nexport function publicKeyOf(k: AppKey): string {\n return rawPublicKey(k.privateKey).toString(\"base64url\");\n}\n\nconst b64 = (v: unknown) => Buffer.from(typeof v === \"string\" ? v : JSON.stringify(v)).toString(\"base64url\");\n\n/**\n * Signs a fresh assertion of the app's identity for core (its base URL,\n * without a trailing slash): a compact JWS, alg EdDSA, typ app+jwt, with\n * the key's kid, living two minutes. iss and sub are the app's ID when\n * it's known (an older key names it; pass appId once Wakeshift has said\n * it), else the kid.\n */\nexport function signAssertion(k: AppKey, core: string, now = Date.now(), appId?: string | null): string {\n const iat = Math.floor(now / 1000);\n const who = appId || k.appId || k.kid;\n const claims = {\n iss: who,\n sub: who,\n aud: core + \"/api/apps\",\n iat,\n exp: iat + 120,\n jti: randomBytes(16).toString(\"base64url\"),\n };\n const input = b64({ alg: \"EdDSA\", typ: \"app+jwt\", kid: k.kid }) + \".\" + b64(claims);\n return input + \".\" + sign(null, Buffer.from(input), k.privateKey).toString(\"base64url\");\n}\n"]}
|
package/dist/retry.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"retry.js","sourceRoot":"","sources":["../src/retry.ts"],"names":[],"mappings":"AAAA,sEAAsE;AACtE,6EAA6E;AAC7E,2EAA2E;AAC3E,yEAAyE;AACzE,2EAA2E;AAC3E,iCAAiC;AAEjC,gGAAgG;AAChG,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;AAE3C;;;;;;GAMG;AACH,MAAM,UAAU,YAAY,CAAC,OAAqB,EAAE,
|
|
1
|
+
{"version":3,"file":"retry.js","sourceRoot":"","sources":["../src/retry.ts"],"names":[],"mappings":"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","sourcesContent":["// Wakeshift runs behind Google's load balancer on Cloud Run. For some\n// minutes after a rollout, the load balancer sends a small share of requests\n// to a retired revision, which answers at once with Google's own HTML \"500\n// Server Error\" page: the request never reached a Wakeshift instance. It\n// happens to every client alike (new connections included), so retrying is\n// what gets the request through.\n\n/** @internal Pauses before each retry of a refused request (so at most length + 1 attempts). */\nexport const RETRY_PAUSES_MS = [250, 1000];\n\n/**\n * @internal fetchFn, retrying a request the load balancer refused before it\n * reached Wakeshift: Google's HTML 500 page, for any request (it never ran),\n * and a 502, 503 or 504 not from Wakeshift for a GET or HEAD. Wakeshift's own\n * errors (JSON) are never retried, nor is a request whose body can't be sent\n * again (a stream).\n */\nexport function retryRefused(fetchFn: typeof fetch, pauses: number[] = RETRY_PAUSES_MS): typeof fetch {\n return (async (input: string | URL | Request, init?: RequestInit): Promise<Response> => {\n const method = (init?.method ?? (input instanceof Request ? input.method : \"GET\")).toUpperCase();\n const resendable = !(input instanceof Request) && (init?.body == null || typeof init.body === \"string\" || init.body instanceof URLSearchParams);\n for (let attempt = 0; ; attempt++) {\n const resp = await fetchFn(input, init);\n if (!resendable || attempt >= pauses.length || !(await refused(method, resp))) return resp;\n await resp.body?.cancel().catch(() => {});\n await pause(pauses[attempt]!, init?.signal ?? undefined);\n }\n }) as typeof fetch;\n}\n\n/** @internal Whether resp is the load balancer's refusal, not the service's answer. */\nexport async function refused(method: string, resp: Response): Promise<boolean> {\n const type = (resp.headers.get(\"Content-Type\") ?? \"\").split(\";\")[0]!.trim().toLowerCase();\n if (resp.status === 500) {\n if (type !== \"text/html\") return false;\n const text = await resp.clone().text().catch(() => \"\");\n return text.includes(\"Server Error\");\n }\n if (resp.status === 502 || resp.status === 503 || resp.status === 504) {\n return (method === \"GET\" || method === \"HEAD\") && type !== \"application/json\";\n }\n return false;\n}\n\nfunction pause(ms: number, signal?: AbortSignal): Promise<void> {\n return new Promise((resolve, reject) => {\n if (signal?.aborted) return reject(signal.reason);\n const t = setTimeout(() => {\n signal?.removeEventListener(\"abort\", stop);\n resolve();\n }, ms);\n const stop = () => {\n clearTimeout(t);\n reject(signal!.reason);\n };\n signal?.addEventListener(\"abort\", stop, { once: true });\n });\n}\n"]}
|
package/dist/wakeshift.d.ts
CHANGED
|
@@ -64,6 +64,12 @@ export interface Call {
|
|
|
64
64
|
conversation?: string;
|
|
65
65
|
/** The program the agent says it runs in (harness): a hint, never a credential. */
|
|
66
66
|
harness?: string;
|
|
67
|
+
/**
|
|
68
|
+
* The name of the tool being called. A connector beacon in its result
|
|
69
|
+
* names it, and Wakeshift's hooks act on the beacon only from that
|
|
70
|
+
* tool's result: put the addition in the result of the tool you name.
|
|
71
|
+
*/
|
|
72
|
+
tool?: string;
|
|
67
73
|
}
|
|
68
74
|
/**
|
|
69
75
|
* What Wakeshift recognised the calling conversation's harness as, and by
|
|
@@ -235,6 +241,12 @@ export interface CallOptions {
|
|
|
235
241
|
harness?: string;
|
|
236
242
|
/** The conversation's ID the agent passed (conversation_id), if you read it yourself. */
|
|
237
243
|
conversation?: string;
|
|
244
|
+
/**
|
|
245
|
+
* The name of the tool being called (the MCP SDK doesn't hand callbacks
|
|
246
|
+
* it, so pass it): Wakeshift's hooks act on a connector beacon only from
|
|
247
|
+
* the result of the tool it names.
|
|
248
|
+
*/
|
|
249
|
+
tool?: string;
|
|
238
250
|
}
|
|
239
251
|
export declare function clientNameOf(s: ClientInfoSource): string;
|
|
240
252
|
/** Adds Wakeshift's text and _meta to a tool result (a copy). */
|
|
@@ -303,6 +315,7 @@ export declare class Wakeshift {
|
|
|
303
315
|
userAgent?: string;
|
|
304
316
|
harness?: string;
|
|
305
317
|
conversation?: string;
|
|
318
|
+
tool?: string;
|
|
306
319
|
}): Call;
|
|
307
320
|
private recognised;
|
|
308
321
|
/**
|
|
@@ -391,14 +404,13 @@ export declare class Wakeshift {
|
|
|
391
404
|
* unsubscribe_events and list_subscriptions for every client, so a person
|
|
392
405
|
* can always see and stop what they're subscribed to.
|
|
393
406
|
*
|
|
394
|
-
* wake.attach(server, { identify: (extra) => ({ user:
|
|
407
|
+
* wake.attach(server, { identify: (extra) => ({ user: myUser(extra) }) })
|
|
395
408
|
*/
|
|
396
409
|
attach(server: McpServer, opts?: AttachOptions): void;
|
|
397
410
|
/**
|
|
398
411
|
* The workspace Wakeshift keeps for one of the app's users (user: the
|
|
399
|
-
* app's own ID for them, as in wake.call's user),
|
|
400
|
-
* Topics keep that user's conversations there
|
|
401
|
-
* most apps never need to.
|
|
412
|
+
* app's own ID for them, as in wake.call's user), created on first use.
|
|
413
|
+
* Topics keep that user's conversations there.
|
|
402
414
|
*/
|
|
403
415
|
workspace(user: string, name: string): Promise<string>;
|
|
404
416
|
/** Creates an agent in one of the app's workspaces (if new), and its grant for the app's manifest scope. Returns the grant's ID. */
|
package/dist/wakeshift.js
CHANGED
|
@@ -185,6 +185,7 @@ export class Wakeshift {
|
|
|
185
185
|
userAgent: userAgentOf(extra),
|
|
186
186
|
harness: opts.harness ?? str(args, HARNESS_ARG),
|
|
187
187
|
conversation: opts.conversation ?? str(args, CONVERSATION_ARG),
|
|
188
|
+
tool: opts.tool,
|
|
188
189
|
});
|
|
189
190
|
}
|
|
190
191
|
/** Packs a tool call without an MCP framework. */
|
|
@@ -202,6 +203,8 @@ export class Wakeshift {
|
|
|
202
203
|
out.harness = c.harness.trim();
|
|
203
204
|
if (c.conversation?.trim())
|
|
204
205
|
out.conversation = c.conversation.trim();
|
|
206
|
+
if (c.tool?.trim())
|
|
207
|
+
out.tool = c.tool.trim();
|
|
205
208
|
return out;
|
|
206
209
|
}
|
|
207
210
|
// recognised reads what the core recognised the caller as, and warns
|
|
@@ -372,7 +375,7 @@ export class Wakeshift {
|
|
|
372
375
|
* unsubscribe_events and list_subscriptions for every client, so a person
|
|
373
376
|
* can always see and stop what they're subscribed to.
|
|
374
377
|
*
|
|
375
|
-
* wake.attach(server, { identify: (extra) => ({ user:
|
|
378
|
+
* wake.attach(server, { identify: (extra) => ({ user: myUser(extra) }) })
|
|
376
379
|
*/
|
|
377
380
|
attach(server, opts = {}) {
|
|
378
381
|
attachEvents(this, server, [...this.events.values()], opts);
|
|
@@ -405,12 +408,11 @@ export class Wakeshift {
|
|
|
405
408
|
await this.ensureEvents();
|
|
406
409
|
return this.request(method, path, body);
|
|
407
410
|
}
|
|
408
|
-
// ──
|
|
411
|
+
// ── Users' workspaces ──────────────────────────────────────────────────
|
|
409
412
|
/**
|
|
410
413
|
* The workspace Wakeshift keeps for one of the app's users (user: the
|
|
411
|
-
* app's own ID for them, as in wake.call's user),
|
|
412
|
-
* Topics keep that user's conversations there
|
|
413
|
-
* most apps never need to.
|
|
414
|
+
* app's own ID for them, as in wake.call's user), created on first use.
|
|
415
|
+
* Topics keep that user's conversations there.
|
|
414
416
|
*/
|
|
415
417
|
async workspace(user, name) {
|
|
416
418
|
return (await this.request("POST", "/workspaces", { external_id: user, name })).workspace;
|
|
@@ -427,10 +429,6 @@ export class Wakeshift {
|
|
|
427
429
|
async checkAgent(workspace, agent) {
|
|
428
430
|
await this.request("POST", `/workspaces/${encodeURIComponent(workspace)}/agents/${encodeURIComponent(agent)}/token`);
|
|
429
431
|
}
|
|
430
|
-
/** @internal The app key's seed: what GuestAuth keys its signed values from. Never send or log it. */
|
|
431
|
-
secretSeed() {
|
|
432
|
-
return this.key.seed;
|
|
433
|
-
}
|
|
434
432
|
async request(method, path, body) {
|
|
435
433
|
const headers = { Authorization: "Bearer " + this.assertion() };
|
|
436
434
|
if (body !== undefined)
|
package/dist/wakeshift.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"wakeshift.js","sourceRoot":"","sources":["../src/wakeshift.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAIxB,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAE,SAAS,EAAE,YAAY,EAAiE,MAAM,aAAa,CAAC;AACrH,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAe,MAAM,UAAU,CAAC;AAChE,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE1C,iIAAiI;AACjI,MAAM,CAAC,MAAM,YAAY,GAAG,0BAA0B,CAAC;AAEvD,oFAAoF;AACpF,MAAM,CAAC,MAAM,WAAW,GAAG,aAAa,CAAC;AAEzC,qEAAqE;AACrE,MAAM,CAAC,MAAM,WAAW,GAAG,SAAS,CAAC;AAErC;;;GAGG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,iBAAiB,CAAC;AAElD,iEAAiE;AACjE,sDAAsD;AACtD,MAAM,mBAAmB,GAAG,2HAA2H,CAAC;AACxJ,MAAM,mBAAmB,GACvB,6QAA6Q,CAAC;AAChR,MAAM,wBAAwB,GAC5B,4MAA4M,CAAC;AA6B/M,oFAAoF;AACpF,MAAM,CAAC,MAAM,sBAAsB,GACjC,+GAA+G;IAC/G,2HAA2H;IAC3H,0HAA0H;IAC1H,2HAA2H;IAC3H,wHAAwH;IACxH,uGAAuG;IACvG,8DAA8D,CAAC;AAiLjE,wEAAwE;AACxE,yCAAyC;AACzC,SAAS,WAAW,CAAC,KAA4B;IAC/C,MAAM,OAAO,GAAG,KAAK,EAAE,WAAW,EAAE,OAAO,CAAC;IAC5C,IAAI,CAAC,OAAO;QAAE,OAAO,EAAE,CAAC;IACxB,MAAM,CAAC,GAAG,OAAO,CAAC,YAAY,CAAC,IAAI,OAAO,CAAC,YAAY,CAAC,CAAC;IACzD,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;AAC7C,CAAC;AAwBD,MAAM,UAAU,YAAY,CAAC,CAAmB;IAC9C,MAAM,IAAI,GAAG,kBAAkB,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,gBAAgB,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,gBAAgB,EAAE,CAAC;IAC1F,OAAO,IAAI,EAAE,IAAI,IAAI,EAAE,CAAC;AAC1B,CAAC;AAED,iEAAiE;AACjE,MAAM,UAAU,aAAa,CAAC,CAAW,EAAE,IAA6B;IACtE,IAAI,GAAmB,CAAC;IACxB,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE,CAAC;QAC7B,MAAM,IAAI,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,MAAM,GAAG,CAAC,CAAC,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QAC5D,GAAG,GAAG,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;IAC1D,CAAC;SAAM,CAAC;QACN,GAAG,GAAG,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC;QACtD,IAAI,CAAC,CAAC,IAAI;YAAE,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;IAC/D,CAAC;IACD,IAAI,CAAC,CAAC,IAAI,IAAI,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC;QAAE,GAAG,CAAC,KAAK,GAAG,EAAE,GAAG,CAAC,GAAG,CAAC,KAAK,IAAI,EAAE,CAAC,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;IAC9F,OAAO,GAAG,CAAC;AACb,CAAC;AAED,MAAM,SAAS,GAAG;IAChB,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,mBAAmB,CAAC;IAClE,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,mBAAmB,CAAC;IAClE,CAAC,gBAAgB,CAAC,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,wBAAwB,CAAC;CAC7E,CAAC;AAEF,mDAAmD;AACnD,SAAS,GAAG,CAAC,IAAyC,EAAE,IAAY;IAClE,OAAO,OAAO,IAAI,EAAE,CAAC,IAAI,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAE,IAAI,CAAC,IAAI,CAAY,CAAC,CAAC,CAAC,SAAS,CAAC;AAC/E,CAAC;AAED;;;GAGG;AACH,MAAM,OAAO,SAAS;IACpB;;;OAGG;IACM,IAAI,CAAyB;IAC7B,IAAI,CAAS;IACL,GAAG,CAAS;IAC7B,uEAAuE;IAC/D,UAAU,CAAgB;IAC1B,OAAO,CAAoB;IAClB,OAAO,CAAe;IACtB,SAAS,CAAS;IAClB,MAAM,CAA4B;IAClC,MAAM,GAAG,IAAI,GAAG,EAAU,CAAC;IAE5C,YAAY,IAAsB;QAChC,IAAI,CAAC,IAAI,EAAE,GAAG;YAAE,MAAM,IAAI,KAAK,CAAC,wCAAwC,CAAC,CAAC;QAC1E,IAAI,CAAC,GAAG,GAAG,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC9B,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC;QACjC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC;QAC1B,kEAAkE;QAClE,mEAAmE;QACnE,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,IAAI,OAAO,CAAC,GAAG,CAAC,cAAc,IAAI,CAAC,IAAI,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC;QACnG,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,MAAM,IAAI,KAAK,CACb,gLAAgL,CACjL,CAAC;QACJ,CAAC;QACD,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;QACrC,iFAAiF;QACjF,IAAI,CAAC,OAAO,GAAG,YAAY,CAAC,IAAI,CAAC,KAAK,IAAI,UAAU,CAAC,KAAK,CAAC,CAAC;QAC5D,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,SAAS,IAAI,MAAM,CAAC;QAC1C,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,SAAS,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;IAC3D,CAAC;IAED;;;;OAIG;IACH,IAAI,KAAK;QACP,IAAI,CAAC,IAAI,CAAC,UAAU;YAAE,MAAM,IAAI,KAAK,CAAC,uEAAuE,CAAC,CAAC;QAC/G,OAAO,IAAI,CAAC,UAAU,CAAC;IACzB,CAAC;IAED;;;;OAIG;IACH,GAAG;QACD,IAAI,CAAC,OAAO,KAAK,IAAI,CAAC,OAAO,CAAmC,KAAK,EAAE,MAAM,CAAC;aAC3E,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE;YACV,IAAI,OAAO,CAAC,CAAC,EAAE,KAAK,QAAQ,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;gBACtC,MAAM,IAAI,cAAc,CAAC,GAAG,EAAE,cAAc,EAAE,gBAAgB,IAAI,CAAC,IAAI,mCAAmC,CAAC,CAAC;YAC9G,CAAC;YACD,MAAM,EAAE,GAAG,IAAI,CAAC,UAAU,IAAI,CAAC,CAAC,EAAE,CAAC;YACnC,IAAI,CAAC,UAAU,GAAG,EAAE,CAAC;YACrB,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;QAChE,CAAC,CAAC;aACD,KAAK,CAAC,CAAC,GAAY,EAAE,EAAE;YACtB,IAAI,CAAC,OAAO,GAAG,SAAS,CAAC,CAAC,0BAA0B;YACpD,MAAM,GAAG,CAAC;QACZ,CAAC,CAAC,CAAC;QACL,OAAO,IAAI,CAAC,OAAO,CAAC;IACtB,CAAC;IAED,qGAAqG;IACrG,QAAQ;QACN,OAAO,IAAI,CAAC,UAAU,CAAC;IACzB,CAAC;IAED,2EAA2E;IACnE,SAAS;QACf,OAAO,aAAa,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC;IACzE,CAAC;IAED,iEAAiE;IACjE,IAAI,CAAC,OAAe;QAClB,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IACvB,CAAC;IAED,wCAAwC;IAChC,QAAQ,CAAC,IAAY,EAAE,OAAe;QAC5C,IAAI,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC;YAAE,OAAO;QAClC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACtB,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IACvB,CAAC;IAED;;;;;;;;OAQG;IACH,IAAI,IAAI;QACN,OAAO,SAAS,CAAC;IACnB,CAAC;IAED;;;;OAIG;IACH,IAAI,CAAC,KAA4B,EAAE,OAAoB,EAAE;QACvD,IAAI,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;QACzB,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;YACzB,IAAI,CAAC,IAAI,CAAC,MAAM;gBAAE,MAAM,IAAI,KAAK,CAAC,mGAAmG,CAAC,CAAC;YACvI,MAAM,GAAG,YAAY,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACrC,CAAC;QACD,MAAM,IAAI,GAAG,IAAI,CAAC,IAA2C,CAAC;QAC9D,OAAO,IAAI,CAAC,MAAM,CAAC;YACjB,IAAI,EAAE,KAAK,EAAE,KAAK;YAClB,UAAU,EAAE,MAAM;YAClB,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,OAAO,EAAE,IAAI,CAAC,OAAO,IAAI,GAAG,CAAC,IAAI,EAAE,WAAW,CAAC;YAC/C,SAAS,EAAE,WAAW,CAAC,KAAK,CAAC;YAC7B,OAAO,EAAE,IAAI,CAAC,OAAO,IAAI,GAAG,CAAC,IAAI,EAAE,WAAW,CAAC;YAC/C,YAAY,EAAE,IAAI,CAAC,YAAY,IAAI,GAAG,CAAC,IAAI,EAAE,gBAAgB,CAAC;SAC/D,CAAC,CAAC;IACL,CAAC;IAED,kDAAkD;IAClD,MAAM,CAAC,CAQN;QACC,MAAM,GAAG,GAAS,EAAE,MAAM,EAAE,CAAC,CAAC,UAAU,IAAI,EAAE,EAAE,CAAC;QACjD,IAAI,CAAC,CAAC,IAAI;YAAE,GAAG,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC;QAC9B,IAAI,CAAC,CAAC,IAAI,IAAI,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC;YAAE,GAAG,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC;QAChE,IAAI,CAAC,CAAC,OAAO;YAAE,GAAG,CAAC,OAAO,GAAG,CAAC,CAAC,OAAO,CAAC;QACvC,IAAI,CAAC,CAAC,SAAS;YAAE,GAAG,CAAC,UAAU,GAAG,CAAC,CAAC,SAAS,CAAC;QAC9C,IAAI,CAAC,CAAC,OAAO,EAAE,IAAI,EAAE;YAAE,GAAG,CAAC,OAAO,GAAG,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;QACtD,IAAI,CAAC,CAAC,YAAY,EAAE,IAAI,EAAE;YAAE,GAAG,CAAC,YAAY,GAAG,CAAC,CAAC,YAAY,CAAC,IAAI,EAAE,CAAC;QACrE,OAAO,GAAG,CAAC;IACb,CAAC;IAED,qEAAqE;IACrE,sEAAsE;IACtE,4BAA4B;IACpB,UAAU,CAAC,KAAsC;QACvD,IAAI,KAAK,IAAI,CAAC,KAAK,CAAC,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO;YAAE,IAAI,CAAC,QAAQ,CAAC,gBAAgB,EAAE,sBAAsB,CAAC,CAAC;QACvG,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,IAAI,IAAI,EAAE,GAAG,EAAE,KAAK,EAAE,GAAG,IAAI,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,IAAI,IAAI,EAAE,CAAC;IACvG,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,SAAS,CAAC,IAAU,EAAE,KAAa,EAAE,OAAyB,EAAE;QACpE,MAAM,IAAI,GAA4B,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;QACzE,IAAI,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,MAAM,GAAG,CAAC;YAAE,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;QAClF,IAAI,IAAI,CAAC,MAAM,KAAK,SAAS;YAAE,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;QACzD,IAAI,IAAI,CAAC,GAAG,KAAK,SAAS;YAAE,IAAI,CAAC,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC;QAChD,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,OAAO,CAK3B,MAAM,EAAE,mBAAmB,EAAE,IAAI,CAAC,CAAC;QACtC,MAAM,KAAK,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QACzC,MAAM,QAAQ,GAAG,GAAG,CAAC,QAAQ,IAAI,EAAE,CAAC;QACpC,MAAM,CAAC,GAAG,GAAG,CAAC,YAAY,CAAC;QAC3B,OAAO;YACL,EAAE,EAAE,CAAC,CAAC,EAAE;YACR,KAAK,EAAE,CAAC,CAAC,KAAK;YACd,MAAM,EAAE,CAAC,CAAC,MAAM;YAChB,IAAI,EAAE,CAAC,CAAC,IAAI;YACZ,SAAS,EAAE,IAAI,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC;YACjC,OAAO,EAAE,GAAG,CAAC,OAAO;YACpB,QAAQ;YACR,KAAK;YACL,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,aAAa,CAAC,QAAQ,EAAE,IAAI,CAAC;SAChD,CAAC;IACJ,CAAC;IAED,yGAAyG;IACzG,KAAK,CAAC,WAAW,CAAC,IAAU,EAAE,KAAc;QAC1C,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,OAAO,CAA2B,MAAM,EAAE,qBAAqB,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC;QAC5H,OAAO,GAAG,CAAC,YAAY,CAAC;IAC1B,CAAC;IAED,sGAAsG;IACtG,KAAK,CAAC,OAAO,CAAC,MAAyB,EAAE,KAAiB;QACxD,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,OAAO,CAAY,MAAM,EAAE,iBAAiB,EAAE,EAAE,MAAM,EAAE,OAAO,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;QACxI,OAAO,EAAE,OAAO,EAAE,GAAG,CAAC,OAAO,EAAE,SAAS,EAAE,CAAC,CAAC,GAAG,CAAC,SAAS,EAAE,CAAC;IAC9D,CAAC;IAED,0EAA0E;IAC1E,KAAK,CAAC,IAAI,CAAC,cAAsB,EAAE,KAAiB;QAClD,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,OAAO,CAAyB,MAAM,EAAE,kBAAkB,kBAAkB,CAAC,cAAc,CAAC,OAAO,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;QACvI,OAAO,GAAG,CAAC,MAAM,CAAC;IACpB,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,WAAW,CAAC,KAAa;QAC7B,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,OAAO,CAAoE,KAAK,EAAE,wBAAwB,kBAAkB,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAC9J,OAAO,EAAE,KAAK,EAAE,GAAG,CAAC,KAAK,EAAE,aAAa,EAAE,GAAG,CAAC,aAAa,EAAE,SAAS,EAAE,GAAG,CAAC,SAAS,EAAE,GAAG,EAAE,EAAE,MAAM,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,GAAG,GAAG,CAAC,GAAG,EAAE,EAAE,CAAC;IACzJ,CAAC;IAED,gGAAgG;IAChG,KAAK,CAAC,kBAAkB,CAAC,cAAsB;QAC7C,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,OAAO,CAC5B,KAAK,EACL,kBAAkB,kBAAkB,CAAC,cAAc,CAAC,EAAE,CACvD,CAAC;QACF,MAAM,CAAC,GAAuB,EAAE,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,KAAK,EAAE,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,SAAS,EAAE,GAAG,CAAC,SAAS,EAAE,CAAC;QAC7G,IAAI,GAAG,CAAC,GAAG;YAAE,CAAC,CAAC,GAAG,GAAG,GAAG,CAAC,GAAG,CAAC;QAC7B,IAAI,GAAG,CAAC,UAAU;YAAE,CAAC,CAAC,SAAS,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;QAC3D,OAAO,CAAC,CAAC;IACX,CAAC;IAED,gFAAgF;IAChF,KAAK,CAAC,UAAU,CAAC,KAAa;QAC5B,OAAO,IAAI,CAAC,OAAO,CAAa,MAAM,EAAE,sBAAsB,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;IAC7E,CAAC;IAED,+EAA+E;IAC/E,KAAK,CAAC,gBAAgB,CAAC,EAAU;QAC/B,MAAM,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,wBAAwB,kBAAkB,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;IACjF,CAAC;IAED,iGAAiG;IACjG,KAAK,CAAC,QAAQ,CAAC,IAAU;QACvB,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,OAAO,CAAW,MAAM,EAAE,kBAAkB,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;QAC/E,OAAO,EAAE,GAAG,GAAG,EAAE,KAAK,EAAE,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;IACvD,CAAC;IAED;;;;;OAKG;IACH,KAAK,CAAC,QAAQ,CAAC,IAAU,EAAE,MAAsB;QAC/C,OAAO,aAAa,CAAC,MAAM,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC,CAAC;IAC1D,CAAC;IAED,2FAA2F;IAC3F,KAAK,CAAC,UAAU,CAAC,KAAa;QAC5B,OAAO,CAAC,MAAM,IAAI,CAAC,OAAO,CAAqB,MAAM,EAAE,eAAe,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC;IAC7F,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,eAAe,CAAC,cAAsB;QAC1C,OAAO,CAAC,MAAM,IAAI,CAAC,OAAO,CAAqB,MAAM,EAAE,kBAAkB,kBAAkB,CAAC,cAAc,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC;IAChI,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,eAAe,CAAC,IAAY,EAAE,KAAc;QAChD,OAAO,CAAC,MAAM,IAAI,CAAC,OAAO,CAA2B,MAAM,EAAE,qBAAqB,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,YAAY,CAAC;IACxI,CAAC;IAED;;;;;OAKG;IACH,KAAK,CAAC,UAAU,CAAC,IAAY;QAC3B,OAAO,CAAC,MAAM,IAAI,CAAC,OAAO,CAAyB,MAAM,EAAE,eAAe,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;IACnG,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,eAAe,CAAC,CAAW;QAC/B,MAAM,IAAI,GAAa,CAAC,CAAC,MAAM,KAAK,SAAS,IAAI,IAAI,CAAC,MAAM,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,MAAM,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;QAC/I,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,OAAO,CAAW,KAAK,EAAE,WAAW,EAAE,IAAI,CAAC,CAAC;QACnE,IAAI,CAAC,YAAY,GAAG,CAAC,CAAC;QACtB,IAAI,CAAC,SAAS,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;QACnC,OAAO,GAAG,CAAC;IACb,CAAC;IAED,yEAAyE;IAExD,MAAM,GAAG,IAAI,GAAG,EAAqB,CAAC;IAC/C,YAAY,GAAa,EAAE,CAAC;IAC5B,SAAS,GAAyB,IAAI,CAAC;IAE/C;;;;;;;;;;;;;OAaG;IACH,WAAW,CAA2C,IAAY,EAAE,IAAwB;QAC1F,IAAI,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,oBAAoB,IAAI,mBAAmB,CAAC,CAAC;QACxF,MAAM,EAAE,GAAG,IAAI,SAAS,CAAO,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;QACjD,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,EAAE,EAA0B,CAAC,CAAC;QAClD,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,CAAC,uBAAuB;QAC9C,OAAO,EAAE,CAAC;IACZ,CAAC;IAED;;;;;;;;;;OAUG;IACH,MAAM,CAAC,MAAiB,EAAE,OAAsB,EAAE;QAChD,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,IAAI,CAAC,CAAC;IAC9D,CAAC;IAED,kGAAkG;IAClG,YAAY;QACV,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC;YACpB,MAAM,CAAC,GAAG,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;YACxE,IAAI,CAAC,SAAS,GAAG,CAAC,CAAC;YACnB,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE;gBACX,IAAI,IAAI,CAAC,SAAS,KAAK,CAAC;oBAAE,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,CAAC,sBAAsB;YACzE,CAAC,CAAC,CAAC;QACL,CAAC;QACD,OAAO,IAAI,CAAC,SAAS,CAAC;IACxB,CAAC;IAED,iCAAiC;IACjC,KAAK,CAAC,SAAS,CAAC,CAAiG;QAC/G,MAAM,IAAI,CAAC,YAAY,EAAE,CAAC;QAC1B,MAAM,IAAI,GAA4B,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,SAAS,EAAE,CAAC,CAAC,SAAS,EAAE,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;QACjH,IAAI,CAAC,CAAC,EAAE;YAAE,IAAI,CAAC,EAAE,GAAG,CAAC,CAAC,EAAE,CAAC;QACzB,IAAI,CAAC,CAAC,EAAE;YAAE,IAAI,CAAC,EAAE,GAAG,CAAC,CAAC,EAAE,CAAC;QACzB,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,OAAO,CAAY,MAAM,EAAE,cAAc,EAAE,IAAI,CAAC,CAAC;QACxE,OAAO,EAAE,OAAO,EAAE,GAAG,CAAC,OAAO,EAAE,SAAS,EAAE,CAAC,CAAC,GAAG,CAAC,SAAS,EAAE,CAAC;IAC9D,CAAC;IAED,yHAAyH;IACzH,KAAK,CAAC,UAAU,CAAI,MAAc,EAAE,IAAY,EAAE,IAAc;QAC9D,MAAM,IAAI,CAAC,YAAY,EAAE,CAAC;QAC1B,OAAO,IAAI,CAAC,OAAO,CAAI,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;IAC7C,CAAC;IAED,0EAA0E;IAE1E;;;;;OAKG;IACH,KAAK,CAAC,SAAS,CAAC,IAAY,EAAE,IAAY;QACxC,OAAO,CAAC,MAAM,IAAI,CAAC,OAAO,CAAwB,MAAM,EAAE,aAAa,EAAE,EAAE,WAAW,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;IACnH,CAAC;IAED,oIAAoI;IACpI,KAAK,CAAC,QAAQ,CAAC,SAAiB,EAAE,KAAa,EAAE,WAAmB;QAClE,OAAO,CAAC,MAAM,IAAI,CAAC,OAAO,CAAoB,MAAM,EAAE,eAAe,kBAAkB,CAAC,SAAS,CAAC,SAAS,EAAE,EAAE,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC;IAC5J,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,UAAU,CAAC,SAAiB,EAAE,KAAa;QAC/C,MAAM,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,eAAe,kBAAkB,CAAC,SAAS,CAAC,WAAW,kBAAkB,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IACvH,CAAC;IAED,sGAAsG;IACtG,UAAU;QACR,OAAO,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC;IACvB,CAAC;IAEO,KAAK,CAAC,OAAO,CAAI,MAAc,EAAE,IAAY,EAAE,IAAc;QACnE,MAAM,OAAO,GAA2B,EAAE,aAAa,EAAE,SAAS,GAAG,IAAI,CAAC,SAAS,EAAE,EAAE,CAAC;QACxF,IAAI,IAAI,KAAK,SAAS;YAAE,OAAO,CAAC,cAAc,CAAC,GAAG,kBAAkB,CAAC;QACrE,IAAI,IAAc,CAAC;QACnB,IAAI,IAAY,CAAC;QACjB,IAAI,CAAC;YACH,IAAI,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,GAAG,cAAc,GAAG,IAAI,EAAE;gBAC3D,MAAM;gBACN,OAAO;gBACP,IAAI,EAAE,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;gBAC3D,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC;aAC5C,CAAC,CAAC;YACH,IAAI,GAAG,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC;QAC3B,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;QAC9B,CAAC;QACD,IAAI,IAAS,CAAC;QACd,IAAI,CAAC;YACH,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QAC7C,CAAC;QAAC,MAAM,CAAC;YACP,IAAI,GAAG,SAAS,CAAC;QACnB,CAAC;QACD,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC;YACb,MAAM,CAAC,GAAG,IAAI,EAAE,KAAK,IAAI,EAAE,CAAC;YAC5B,MAAM,IAAI,cAAc,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,IAAI,EAAE,EAAE,CAAC,CAAC,OAAO,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,IAAI,IAAI,CAAC,UAAU,CAAC,EAAE;gBACxG,MAAM,EAAE,OAAO,CAAC,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS;aAC5D,CAAC,CAAC;QACL,CAAC;QACD,sEAAsE;QACtE,IAAI,IAAI,KAAK,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE,CAAC;YAC9C,MAAM,IAAI,cAAc,CACtB,IAAI,CAAC,MAAM,EACX,cAAc,EACd,gBAAgB,IAAI,CAAC,IAAI,aAAa,IAAI,CAAC,MAAM,yHAAyH,CAC3K,CAAC;QACJ,CAAC;QACD,OAAO,IAAS,CAAC;IACnB,CAAC;IAED,qEAAqE;IACrE,6CAA6C;IACrC,WAAW,CAAC,GAAY;QAC9B,MAAM,CAAC,GAAG,GAAmG,CAAC;QAC9G,MAAM,GAAG,GACP,CAAC,EAAE,IAAI,KAAK,cAAc,IAAI,CAAC,EAAE,IAAI,KAAK,YAAY;YACpD,CAAC,CAAC,oBAAoB,IAAI,CAAC,SAAS,GAAG,IAAI,GAAG;YAC9C,CAAC,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,KAAK,EAAE,IAAI,IAAI,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC;QAClG,OAAO,IAAI,cAAc,CACvB,CAAC,EACD,aAAa,EACb,4BAA4B,IAAI,CAAC,IAAI,KAAK,GAAG,oGAAoG,EACjJ,EAAE,KAAK,EAAE,GAAG,EAAE,CACf,CAAC;IACJ,CAAC;CACF","sourcesContent":["import { z } from \"zod\";\nimport type { CallToolResult } from \"@modelcontextprotocol/sdk/types.js\";\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport type { AnySchema } from \"@modelcontextprotocol/sdk/server/zod-compat.js\";\nimport { WakeshiftError } from \"./errors.js\";\nimport { WakeEvent, attachEvents, type AttachOptions, type EventOptions, type EventTypeManifest } from \"./events.js\";\nimport { parseKey, signAssertion, type AppKey } from \"./key.js\";\nimport { retryRefused } from \"./retry.js\";\n\n/** Wakeshift's production core, the default for every key but an older wst_test_ one. Override with `core` or WAKESHIFT_CORE. */\nexport const DEFAULT_CORE = \"https://app.wakeshift.ai\";\n\n/** The tool argument an agent passes its session key in (a result gives it one). */\nexport const SESSION_ARG = \"session_key\";\n\n/** The tool argument an agent says which program it runs in with. */\nexport const HARNESS_ARG = \"harness\";\n\n/**\n * The tool argument an agent passes its own ID for the conversation in,\n * when its program gives it one (Cursor and Grok Bot: CURSOR_CONVERSATION_ID).\n */\nexport const CONVERSATION_ARG = \"conversation_id\";\n\n// What the agent is told each argument is (the core's own words:\n// internal/harnesses, whose tests check these match).\nconst SESSION_DESCRIPTION = \"The session key an earlier result gave you, if it did. It's a secret: keep it to this conversation; don't share or log it\";\nconst HARNESS_DESCRIPTION =\n \"The program you're running in: codex, claude-code, cursor (local CLI or IDE), cursor-cloud (Cursor cloud agent), grok-bot, copilot-cli, opencode, antigravity, openclaw (even when it runs your turns in Codex), hermes, chatgpt, or your program's name if it isn't listed\";\nconst CONVERSATION_DESCRIPTION =\n \"Your own ID for this conversation, if your program gives you one. Cursor and Grok Bot: the output of `printenv CURSOR_CONVERSATION_ID`. Codex and Antigravity send it automatically; others leave it empty\";\n\nexport interface WakeshiftOptions {\n /** The app key from the console: wst_ and 50 characters (or an older wst_test_… or wst_live_… key). */\n key: string;\n /**\n * Wakeshift's base URL: the console you got the key from. Default:\n * WAKESHIFT_CORE from the environment, else https://app.wakeshift.ai.\n * An older wst_test_… key has no default: it needs one of the two.\n */\n core?: string;\n /** Default: the global fetch. */\n fetch?: typeof fetch;\n /** Per-request timeout in milliseconds. Default 20000. */\n timeoutMs?: number;\n /**\n * Called with a problem that doesn't fail the call but makes it work less\n * well, for example a tool call Wakeshift recognised no harness in. Each kind is\n * reported once. Default: console.warn.\n */\n onWarning?: (message: string) => void;\n}\n\n/** Which app a key is, as Wakeshift says (wake.app()). */\nexport interface AppInfo {\n id: string;\n name: string;\n}\n\n/** What the SDK says, once, when Wakeshift recognised no harness in a tool call. */\nexport const UNKNOWN_CLIENT_WARNING =\n \"wakeshift: Wakeshift couldn't tell which agent made a tool call (no MCP client name, nothing it knows in the \" +\n \"call's _meta or User-Agent, and no harness argument), so it treats the agent as one it can't wake (its messages are held \" +\n \"for its next call to the tool). The name comes from the client's initialize request, which a server created per request \" +\n \"(stateless Streamable HTTP) never sees; Claude Code, Codex, Antigravity, Copilot CLI, opencode and Cursor are recognised \" +\n \"without it. Spread ...wake.args into the tool's input and pass args to wake.call, so the agent can say (harness); for \" +\n \"other clients, keep one McpServer per MCP session (a stateful transport), or pass the name yourself: \" +\n \"wake.call(extra, { client }) or wake.callOf({ clientName }).\";\n\n/**\n * Who called one of the app's tools, as Wakeshift needs it. Make one with\n * `wake.call(extra, …)` inside an MCP tool callback, or `wake.callOf(…)`.\n */\nexport interface Call {\n /** The app's own ID for the person (optional). */\n user?: string;\n /**\n * The MCP client's name (initialize's clientInfo.name). A stateless\n * server has none; Wakeshift then tells the harness from meta, else\n * user_agent.\n */\n client: string;\n /** The tool call's _meta (Codex sends its thread there). */\n meta?: Record<string, unknown>;\n /** The session handle an earlier result gave the agent. */\n session?: string;\n /** The MCP request's HTTP User-Agent. */\n user_agent?: string;\n /** The conversation's ID as the agent passed it (conversation_id: Cursor's CURSOR_CONVERSATION_ID). */\n conversation?: string;\n /** The program the agent says it runs in (harness): a hint, never a credential. */\n harness?: string;\n}\n\n/**\n * What Wakeshift recognised the calling conversation's harness as, and by\n * which signal (\"claim\": only the agent's harness argument named it); both\n * null when nothing named one. claimed is what the agent said (normalized:\n * \"Grok Bot\" is grok-bot), null if it didn't; a claimed that differs from\n * harness was ignored, since it contradicted what the call was recognised\n * as (the claim only refines it: Cursor's calls may be Grok Bot's).\n */\nexport interface Recognised {\n harness: string | null;\n via: \"client\" | \"meta\" | \"user_agent\" | \"claim\" | null;\n claimed: string | null;\n}\n\n/**\n * Seconds, or a string like \"90s\", \"5m\", \"2h\", \"30d\". Wakeshift checks the\n * value: days must be whole (\"1.5d\" is a bad_request; use \"36h\").\n */\nexport type Duration = number | `${number}${\"s\" | \"m\" | \"h\" | \"d\"}`;\n\nexport interface SubscribeOptions {\n /** Wake only for events whose data has these top-level fields equal to these values. */\n filter?: Record<string, string | number | boolean | null>;\n /** End after the first delivery. */\n once?: boolean;\n /** Deliver the latest event published within this long before subscribing (at most 24 hours). */\n replay?: Duration;\n /** End after this long without a delivery or a fresh subscribe (1 minute to 365 days; default 30 days). */\n ttl?: Duration;\n}\n\n/** What Wakeshift adds to a tool result: text for the agent, _meta for its harness. */\nexport interface Addition {\n text?: string;\n meta?: Record<string, unknown>;\n /** What Wakeshift recognised the caller's harness as (not added to the result). */\n agent?: Recognised;\n}\n\nexport interface Subscription {\n /** For `send`. */\n id: string;\n topic: string;\n filter?: Record<string, unknown>;\n once: boolean;\n expiresAt: Date;\n /**\n * The conversation's session key (the agent passes it back as session_key;\n * the result says so). It's a secret that acts as the conversation: don't\n * show, store or log it. To name the conversation, use id, or an HMAC of it.\n */\n session: string;\n /** What the tool result must carry for the caller's harness. */\n addition: Addition;\n /** What Wakeshift recognised the caller's harness as. */\n agent: Recognised;\n /**\n * The tool result to return: your text (or result) followed by\n * Wakeshift's, with its _meta.\n */\n result(text: string | CallToolResult): CallToolResult;\n}\n\nexport interface TopicEvent {\n /** What the agent reads first (at most 1000 bytes). */\n text: string;\n /** A JSON object, within the 64 KB request limit; filters match its top-level fields. */\n data?: Record<string, unknown>;\n /** Makes retries publish once for a day (at most 200 characters); after a day, the same id publishes again. */\n id?: string;\n}\n\nexport interface Published {\n /** Conversations it woke (or will). */\n matched: number;\n /** An earlier publish had this event's id. */\n duplicate: boolean;\n}\n\n/** delivered: on its way to a connected conversation; queued: waits for it; closed: the subscription ended. */\nexport type SendStatus = \"delivered\" | \"queued\" | \"closed\";\n\n/**\n * How a conversation is connected: stream (a stream held open, e.g.\n * Cursor's background command), poll (long polls or waits, e.g. Claude\n * Code's Monitor, in the last minute) or hooks (Wakeshift's hooks or\n * connector on the user's machine).\n */\nexport type Via = \"stream\" | \"poll\" | \"hooks\" | \"webhook\";\n\nexport interface TopicStatus {\n topic: string;\n /** Conversations subscribed (ended or expired subscriptions don't count). */\n subscriptions: number;\n /** Of those, connected now. */\n connected: number;\n /** How many are connected each way. */\n via: Record<Via, number>;\n}\n\nexport interface SubscriptionStatus {\n id: string;\n topic: string;\n status: \"active\" | \"closed\";\n connected: boolean;\n via?: Via;\n expiresAt?: Date;\n}\n\n/** A publish URL: `topic` for a topic's (`wake.publishUrl`), `event` for an event's (`event.publishUrl`). */\nexport interface PublishUrl {\n id: string;\n topic?: string;\n event?: string;\n url: string;\n}\n\n/** An event pattern a manifest asks for, and what the person is told it's for. */\nexport interface ScopeEvent {\n pattern: string;\n description: string;\n}\n\n/** What the app may do with the agents in the workspaces it keeps (manifest.agent). */\nexport interface AgentScope {\n wake: ScopeEvent[];\n post: ScopeEvent[];\n /** Days the person's consent lasts. */\n ttl_days: number;\n /** At most max wake-ups in any seconds, on top of Wakeshift's own limits. */\n wake_limits?: { seconds: number; max: number }[];\n /** What the person should say to their agent once it's connected; at most 120 characters. */\n start_prompt?: string;\n groups?: boolean;\n}\n\n/** What the app tells Wakeshift it may do (see wake.publishManifest). */\nexport interface Manifest {\n description?: string;\n agent?: AgentScope;\n /** The app's event types: defineEvent fills this in for you. */\n events?: EventTypeManifest[];\n}\n\n/** The parts of an MCP tool callback's `extra` that Wakeshift reads. */\nexport interface ToolExtra {\n _meta?: Record<string, unknown>;\n requestInfo?: { headers?: Record<string, string | string[] | undefined> };\n}\n\n// userAgentOf is the User-Agent of the HTTP request a tool call came in\n// (\"\" if there's none, e.g. over stdio).\nfunction userAgentOf(extra: ToolExtra | undefined): string {\n const headers = extra?.requestInfo?.headers;\n if (!headers) return \"\";\n const v = headers[\"user-agent\"] ?? headers[\"User-Agent\"];\n return (Array.isArray(v) ? v[0] : v) ?? \"\";\n}\n\n/** An McpServer or a low-level Server: anything that knows its client's name. */\nexport type ClientInfoSource =\n | { getClientVersion(): { name: string } | undefined }\n | { server: { getClientVersion(): { name: string } | undefined } };\n\nexport interface CallOptions {\n /** The MCP server the call came to, for the client's name (or pass client). */\n server?: ClientInfoSource;\n /** The client's name, if you know it (instead of server). */\n client?: string;\n /** The app's own ID for the person. */\n user?: string;\n /** The tool's arguments: session_key, harness and conversation_id (wake.args) are read from them. */\n args?: { [SESSION_ARG]?: string; [HARNESS_ARG]?: string; [CONVERSATION_ARG]?: string } | Record<string, unknown>;\n /** The session key, if you read it yourself. */\n session?: string;\n /** The program the agent says it runs in (harness), if you read it yourself. */\n harness?: string;\n /** The conversation's ID the agent passed (conversation_id), if you read it yourself. */\n conversation?: string;\n}\n\nexport function clientNameOf(s: ClientInfoSource): string {\n const info = \"getClientVersion\" in s ? s.getClientVersion() : s.server.getClientVersion();\n return info?.name ?? \"\";\n}\n\n/** Adds Wakeshift's text and _meta to a tool result (a copy). */\nexport function applyAddition(a: Addition, base: string | CallToolResult): CallToolResult {\n let out: CallToolResult;\n if (typeof base === \"string\") {\n const text = (base.trim() + \"\\n\\n\" + (a.text ?? \"\")).trim();\n out = { content: text ? [{ type: \"text\", text }] : [] };\n } else {\n out = { ...base, content: [...(base.content ?? [])] };\n if (a.text) out.content.push({ type: \"text\", text: a.text });\n }\n if (a.meta && Object.keys(a.meta).length > 0) out._meta = { ...(out._meta ?? {}), ...a.meta };\n return out;\n}\n\nconst argsShape = {\n [SESSION_ARG]: z.string().optional().describe(SESSION_DESCRIPTION),\n [HARNESS_ARG]: z.string().optional().describe(HARNESS_DESCRIPTION),\n [CONVERSATION_ARG]: z.string().optional().describe(CONVERSATION_DESCRIPTION),\n};\n\n// str is a tool argument's value if it's a string.\nfunction str(args: Record<string, unknown> | undefined, name: string): string | undefined {\n return typeof args?.[name] === \"string\" ? (args[name] as string) : undefined;\n}\n\n/**\n * The Wakeshift client for an app: subscribe the conversations that call\n * your tools to topics, and publish to them.\n */\nexport class Wakeshift {\n /**\n * An older key's mode (wst_test_…, wst_live_…); null for a current key.\n * @deprecated Modes mean nothing now, and current keys have none.\n */\n readonly mode: \"test\" | \"live\" | null;\n readonly core: string;\n private readonly key: AppKey;\n // The app's ID: from the key, if it names the app, or else from app().\n private knownAppId: string | null;\n private appInfo?: Promise<AppInfo>;\n private readonly fetchFn: typeof fetch;\n private readonly timeoutMs: number;\n private readonly warnFn: (message: string) => void;\n private readonly warned = new Set<string>();\n\n constructor(opts: WakeshiftOptions) {\n if (!opts?.key) throw new Error(\"wakeshift: no app key (WAKESHIFT_KEY?)\");\n this.key = parseKey(opts.key);\n this.knownAppId = this.key.appId;\n this.mode = this.key.mode;\n // Test keys come from staging and local consoles, and one sent to\n // production fails in a way that's hard to read: ask for the core.\n const core = opts.core || process.env.WAKESHIFT_CORE || (this.mode === \"test\" ? \"\" : DEFAULT_CORE);\n if (!core) {\n throw new Error(\n \"wakeshift: no core URL for this test key: set WAKESHIFT_CORE, or pass { core }, to the address of the console the key came from (for example https://app.staging.wakeshift.ai)\",\n );\n }\n this.core = core.replace(/\\/+$/, \"\");\n // A request the load balancer refused during a rollout is sent again (retry.ts).\n this.fetchFn = retryRefused(opts.fetch ?? globalThis.fetch);\n this.timeoutMs = opts.timeoutMs ?? 20_000;\n this.warnFn = opts.onWarning ?? ((m) => console.warn(m));\n }\n\n /**\n * The app's ID. An older key (wst_test_…, wst_live_…) names it; for a\n * current key, which doesn't, this throws until `await wake.app()` has\n * asked Wakeshift.\n */\n get appId(): string {\n if (!this.knownAppId) throw new Error(\"wakeshift: call await wake.app() first: this key doesn't name its app\");\n return this.knownAppId;\n }\n\n /**\n * Which app the key is, as Wakeshift says: its ID and name. Asks once\n * (GET /api/apps/v1/app) and remembers the answer; afterwards\n * `wake.appId` works for any key.\n */\n app(): Promise<AppInfo> {\n this.appInfo ??= this.request<{ id?: unknown; name?: unknown }>(\"GET\", \"/app\")\n .then((r) => {\n if (typeof r.id !== \"string\" || !r.id) {\n throw new WakeshiftError(200, \"bad_response\", `Wakeshift at ${this.core} didn't say which app this key is`);\n }\n const id = this.knownAppId ?? r.id;\n this.knownAppId = id;\n return { id, name: typeof r.name === \"string\" ? r.name : \"\" };\n })\n .catch((err: unknown) => {\n this.appInfo = undefined; // a later call asks again\n throw err;\n });\n return this.appInfo;\n }\n\n /** @internal The app's ID if it's known yet (the key names it, or app() has answered), else null. */\n knownApp(): string | null {\n return this.knownAppId;\n }\n\n // A fresh assertion of the app's identity, naming the app once it's known.\n private assertion(): string {\n return signAssertion(this.key, this.core, Date.now(), this.knownAppId);\n }\n\n /** @internal Reports a problem through onWarning, every time. */\n warn(message: string): void {\n this.warnFn(message);\n }\n\n /** Reports a warning, once per kind. */\n private warnOnce(kind: string, message: string): void {\n if (this.warned.has(kind)) return;\n this.warned.add(kind);\n this.warnFn(message);\n }\n\n /**\n * The arguments the agent passes Wakeshift's part of the call in, as a\n * zod shape for your subscribe tool's input (and any other tool whose\n * results you annotate): `inputSchema: { repo: z.string(), ...wake.args }`.\n * session_key (the key a result gives the conversation), harness (the\n * program the agent runs in) and conversation_id (its own ID for the\n * conversation, where its program gives one). Wakeshift adds nothing to\n * tools you don't spread it into.\n */\n get args(): typeof argsShape {\n return argsShape;\n }\n\n /**\n * Packs the tool call from an MCP tool callback's `extra`: its _meta and\n * User-Agent, the client's name (from `server`, or pass `client`), the\n * user, and session_key, harness and conversation_id from `args`.\n */\n call(extra: ToolExtra | undefined, opts: CallOptions = {}): Call {\n let client = opts.client;\n if (client === undefined) {\n if (!opts.server) throw new Error(\"wakeshift: wake.call needs the MCP client's name: pass { server } (your McpServer), or { client }\");\n client = clientNameOf(opts.server);\n }\n const args = opts.args as Record<string, unknown> | undefined;\n return this.callOf({\n meta: extra?._meta,\n clientName: client,\n user: opts.user,\n session: opts.session ?? str(args, SESSION_ARG),\n userAgent: userAgentOf(extra),\n harness: opts.harness ?? str(args, HARNESS_ARG),\n conversation: opts.conversation ?? str(args, CONVERSATION_ARG),\n });\n }\n\n /** Packs a tool call without an MCP framework. */\n callOf(c: {\n meta?: Record<string, unknown>;\n clientName: string;\n user?: string;\n session?: string;\n userAgent?: string;\n harness?: string;\n conversation?: string;\n }): Call {\n const out: Call = { client: c.clientName ?? \"\" };\n if (c.user) out.user = c.user;\n if (c.meta && Object.keys(c.meta).length > 0) out.meta = c.meta;\n if (c.session) out.session = c.session;\n if (c.userAgent) out.user_agent = c.userAgent;\n if (c.harness?.trim()) out.harness = c.harness.trim();\n if (c.conversation?.trim()) out.conversation = c.conversation.trim();\n return out;\n }\n\n // recognised reads what the core recognised the caller as, and warns\n // once if it was nothing and the agent didn't say (an older core that\n // doesn't say: no warning).\n private recognised(agent: Partial<Recognised> | undefined): Recognised {\n if (agent && !agent.harness && !agent.claimed) this.warnOnce(\"unknown_client\", UNKNOWN_CLIENT_WARNING);\n return { harness: agent?.harness ?? null, via: agent?.via ?? null, claimed: agent?.claimed ?? null };\n }\n\n /**\n * Subscribes the calling conversation to topic (again: refreshes it).\n * Check the caller may see the topic first: Wakeshift only refuses another\n * user's u/<user>/… topics.\n */\n async subscribe(call: Call, topic: string, opts: SubscribeOptions = {}): Promise<Subscription> {\n const body: Record<string, unknown> = { call, topic, once: !!opts.once };\n if (opts.filter && Object.keys(opts.filter).length > 0) body.filter = opts.filter;\n if (opts.replay !== undefined) body.replay = opts.replay;\n if (opts.ttl !== undefined) body.ttl = opts.ttl;\n const out = await this.request<{\n subscription: { id: string; topic: string; filter?: Record<string, unknown>; once: boolean; expires_at: string };\n session: string;\n addition: Addition;\n agent?: Recognised;\n }>(\"POST\", \"/topics/subscribe\", body);\n const agent = this.recognised(out.agent);\n const addition = out.addition ?? {};\n const s = out.subscription;\n return {\n id: s.id,\n topic: s.topic,\n filter: s.filter,\n once: s.once,\n expiresAt: new Date(s.expires_at),\n session: out.session,\n addition,\n agent,\n result: (text) => applyAddition(addition, text),\n };\n }\n\n /** Ends the conversation's subscription to topic, or to all the app's topics. Returns how many ended. */\n async unsubscribe(call: Call, topic?: string): Promise<number> {\n const out = await this.request<{ unsubscribed: number }>(\"POST\", \"/topics/unsubscribe\", topic ? { call, topic } : { call });\n return out.unsubscribed;\n }\n\n /** Wakes every conversation subscribed to one of topics whose filter the event passes (each once). */\n async publish(topics: string | string[], event: TopicEvent): Promise<Published> {\n const out = await this.request<Published>(\"POST\", \"/topics/publish\", { topics: typeof topics === \"string\" ? [topics] : topics, event });\n return { matched: out.matched, duplicate: !!out.duplicate };\n }\n\n /** Wakes exactly one subscription's conversation, whatever its filter. */\n async send(subscriptionId: string, event: TopicEvent): Promise<SendStatus> {\n const out = await this.request<{ status: SendStatus }>(\"POST\", `/subscriptions/${encodeURIComponent(subscriptionId)}/send`, { event });\n return out.status;\n }\n\n /**\n * How many conversations are subscribed to topic, and how many are\n * connected now, and how. Only reads: nothing is delivered, minted or ended.\n */\n async topicStatus(topic: string): Promise<TopicStatus> {\n const out = await this.request<Omit<TopicStatus, \"via\"> & { via?: Partial<Record<Via, number>> }>(\"GET\", `/topics/status?topic=${encodeURIComponent(topic)}`);\n return { topic: out.topic, subscriptions: out.subscriptions, connected: out.connected, via: { stream: 0, poll: 0, hooks: 0, webhook: 0, ...out.via } };\n }\n\n /** Whether a subscription is active and its conversation connected now, and how. Only reads. */\n async subscriptionStatus(subscriptionId: string): Promise<SubscriptionStatus> {\n const out = await this.request<{ id: string; topic: string; status: \"active\" | \"closed\"; connected: boolean; via?: Via; expires_at?: string }>(\n \"GET\",\n `/subscriptions/${encodeURIComponent(subscriptionId)}`,\n );\n const s: SubscriptionStatus = { id: out.id, topic: out.topic, status: out.status, connected: out.connected };\n if (out.via) s.via = out.via;\n if (out.expires_at) s.expiresAt = new Date(out.expires_at);\n return s;\n }\n\n /** A capability URL that publishes to topic: a POST's body becomes an event. */\n async publishUrl(topic: string): Promise<PublishUrl> {\n return this.request<PublishUrl>(\"POST\", \"/topics/publish-urls\", { topic });\n }\n\n /** Stops a publish URL working, a topic's or an event's (410 from then on). */\n async revokePublishUrl(id: string): Promise<void> {\n await this.request(\"DELETE\", `/events/publish-urls/${encodeURIComponent(id)}`);\n }\n\n /** What Wakeshift would add to any other tool result for this conversation (creates nothing). */\n async addition(call: Call): Promise<Addition> {\n const out = await this.request<Addition>(\"POST\", \"/topics/annotate\", { call });\n return { ...out, agent: this.recognised(out.agent) };\n }\n\n /**\n * Adds what Wakeshift has for the calling conversation to a tool result\n * of yours (a copy): what's waiting for a harness that can't be woken, a\n * fresh connector beacon while a Codex thread's connector isn't running.\n * Only results you pass here (and a subscription's result()) change.\n */\n async annotate(call: Call, result: CallToolResult): Promise<CallToolResult> {\n return applyAddition(await this.addition(call), result);\n }\n\n /** Ends every subscription to topic; each conversation is told. Returns how many ended. */\n async closeTopic(topic: string): Promise<number> {\n return (await this.request<{ closed: number }>(\"POST\", \"/topics/close\", { topic })).closed;\n }\n\n /**\n * Ends one subscription by its id, telling its conversation that the app\n * ended it. Returns false if it had already ended (or there's no such\n * subscription of the app's).\n */\n async endSubscription(subscriptionId: string): Promise<boolean> {\n return (await this.request<{ ended: boolean }>(\"POST\", `/subscriptions/${encodeURIComponent(subscriptionId)}/end`, {})).ended;\n }\n\n /**\n * Ends the subscriptions of every conversation of one of the app's users\n * to topic, or to all of the app's topics (they lost access to something),\n * telling each conversation. Returns how many ended.\n */\n async unsubscribeUser(user: string, topic?: string): Promise<number> {\n return (await this.request<{ unsubscribed: number }>(\"POST\", \"/topics/unsubscribe\", topic ? { user, topic } : { user })).unsubscribed;\n }\n\n /**\n * Deletes everything Wakeshift keeps for one of the app's users: their\n * conversations, subscriptions, events and deliveries, recent publishes to\n * their u/<user>/… topics and publish URLs for them, and their ID. Open\n * streams close. Returns false if there was nothing to forget.\n */\n async forgetUser(user: string): Promise<boolean> {\n return (await this.request<{ forgotten: boolean }>(\"POST\", \"/users/forget\", { user })).forgotten;\n }\n\n /**\n * Tells Wakeshift what the app may do, replacing what it said before.\n * The events you defined (defineEvent) are added unless m has events of\n * its own. Returns the manifest as Wakeshift keeps it.\n */\n async publishManifest(m: Manifest): Promise<Manifest> {\n const body: Manifest = m.events === undefined && this.events.size > 0 ? { ...m, events: [...this.events.values()].map((e) => e.manifest) } : m;\n const out = await this.request<Manifest>(\"PUT\", \"/manifest\", body);\n this.manifestBase = m;\n this.published = Promise.resolve();\n return out;\n }\n\n // ── Events (MCP Events, natively or bridged) ──────────────────────────\n\n private readonly events = new Map<string, WakeEvent>();\n private manifestBase: Manifest = {};\n private published: Promise<void> | null = null;\n\n /**\n * Defines one of the app's event types: what a subscriber picks (args),\n * what each occurrence carries (payload), and the line an agent reads\n * first (text). Returns the event, whose emit sends occurrences. Define\n * every event before attach.\n *\n * const message = wake.defineEvent(\"chat.message\", {\n * description: \"A new message in a channel\",\n * args: z.object({ channel: z.string() }),\n * payload: z.object({ from: z.string(), text: z.string() }),\n * text: (m) => `${m.from}: ${m.text}`,\n * })\n * await message.emit({ channel: \"eng\" }, { from: \"ada\", text: \"shipped\" })\n */\n defineEvent<A extends AnySchema, P extends AnySchema>(name: string, opts: EventOptions<A, P>): WakeEvent<A, P> {\n if (this.events.has(name)) throw new Error(`wakeshift: event ${name} is defined twice`);\n const ev = new WakeEvent<A, P>(this, name, opts);\n this.events.set(name, ev as unknown as WakeEvent);\n this.published = null; // the manifest changed\n return ev;\n }\n\n /**\n * Attaches Wakeshift to your MCP server, before you connect it: the one\n * call that connects the two. Today it serves the defined events: MCP\n * Events (events/list, events/subscribe, events/unsubscribe) for clients\n * that speak it, such as ChatGPT, and the subscribe_events tool for\n * everyone else, whom Wakeshift wakes its own ways; plus\n * unsubscribe_events and list_subscriptions for every client, so a person\n * can always see and stop what they're subscribed to.\n *\n * wake.attach(server, { identify: (extra) => ({ user: guestOf(extra)?.user }) })\n */\n attach(server: McpServer, opts: AttachOptions = {}): void {\n attachEvents(this, server, [...this.events.values()], opts);\n }\n\n /** @internal Publishes the manifest with the defined events, once (again after a defineEvent). */\n ensureEvents(): Promise<void> {\n if (!this.published) {\n const p = this.publishManifest(this.manifestBase).then(() => undefined);\n this.published = p;\n p.catch(() => {\n if (this.published === p) this.published = null; // try again next time\n });\n }\n return this.published;\n }\n\n /** @internal An event's emit. */\n async emitEvent(e: { name: string; arguments: unknown; payload: unknown; text: string; id?: string; to?: string }): Promise<Published> {\n await this.ensureEvents();\n const body: Record<string, unknown> = { name: e.name, arguments: e.arguments, payload: e.payload, text: e.text };\n if (e.id) body.id = e.id;\n if (e.to) body.to = e.to;\n const out = await this.request<Published>(\"POST\", \"/events/emit\", body);\n return { matched: out.matched, duplicate: !!out.duplicate };\n }\n\n /** @internal A call to the app API (the events machinery's), after the manifest with the defined events is published. */\n async requestApp<T>(method: string, path: string, body?: unknown): Promise<T> {\n await this.ensureEvents();\n return this.request<T>(method, path, body);\n }\n\n // ── Guests' workspaces (GuestAuth) ─────────────────────────────────────\n\n /**\n * The workspace Wakeshift keeps for one of the app's users (user: the\n * app's own ID for them, as in wake.call's user), creating it on first use.\n * Topics keep that user's conversations there too. GuestAuth calls this;\n * most apps never need to.\n */\n async workspace(user: string, name: string): Promise<string> {\n return (await this.request<{ workspace: string }>(\"POST\", \"/workspaces\", { external_id: user, name })).workspace;\n }\n\n /** Creates an agent in one of the app's workspaces (if new), and its grant for the app's manifest scope. Returns the grant's ID. */\n async addAgent(workspace: string, agent: string, displayName: string): Promise<string> {\n return (await this.request<{ grant: string }>(\"POST\", `/workspaces/${encodeURIComponent(workspace)}/agents`, { agent, display_name: displayName })).grant;\n }\n\n /**\n * Checks that one of the app's agents still has a live grant, asking\n * Wakeshift each time. Throws a WakeshiftError: no_grant once the grant is\n * revoked, unknown_workspace once the workspace is forgotten.\n */\n async checkAgent(workspace: string, agent: string): Promise<void> {\n await this.request(\"POST\", `/workspaces/${encodeURIComponent(workspace)}/agents/${encodeURIComponent(agent)}/token`);\n }\n\n /** @internal The app key's seed: what GuestAuth keys its signed values from. Never send or log it. */\n secretSeed(): Buffer {\n return this.key.seed;\n }\n\n private async request<T>(method: string, path: string, body?: unknown): Promise<T> {\n const headers: Record<string, string> = { Authorization: \"Bearer \" + this.assertion() };\n if (body !== undefined) headers[\"Content-Type\"] = \"application/json\";\n let resp: Response;\n let text: string;\n try {\n resp = await this.fetchFn(this.core + \"/api/apps/v1\" + path, {\n method,\n headers,\n body: body === undefined ? undefined : JSON.stringify(body),\n signal: AbortSignal.timeout(this.timeoutMs),\n });\n text = await resp.text();\n } catch (err) {\n throw this.unreachable(err);\n }\n let json: any;\n try {\n json = text ? JSON.parse(text) : undefined;\n } catch {\n json = undefined;\n }\n if (!resp.ok) {\n const e = json?.error ?? {};\n throw new WakeshiftError(resp.status, e.code ?? \"\", e.message ?? (text.slice(0, 200) || resp.statusText), {\n reason: typeof e.reason === \"string\" ? e.reason : undefined,\n });\n }\n // A 2xx that isn't Wakeshift's JSON: a proxy's page, or a wrong core.\n if (json === null || typeof json !== \"object\") {\n throw new WakeshiftError(\n resp.status,\n \"bad_response\",\n `Wakeshift at ${this.core} answered ${resp.status} without a JSON object. Check that WAKESHIFT_CORE, or the core option, is the address of the console your key came from`,\n );\n }\n return json as T;\n }\n\n // A request that got no answer. Name the core it went to: a wrong or\n // missing WAKESHIFT_CORE is the usual cause.\n private unreachable(err: unknown): WakeshiftError {\n const e = err as { name?: string; message?: string; cause?: { code?: string; message?: string } } | undefined;\n const why =\n e?.name === \"TimeoutError\" || e?.name === \"AbortError\"\n ? `no answer within ${this.timeoutMs / 1000}s`\n : [e?.message, e?.cause?.code ?? e?.cause?.message].filter(Boolean).join(\": \") || String(err);\n return new WakeshiftError(\n 0,\n \"unreachable\",\n `can't reach Wakeshift at ${this.core} (${why}). Check that WAKESHIFT_CORE, or the core option, is the address of the console your key came from`,\n { cause: err },\n );\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"wakeshift.js","sourceRoot":"","sources":["../src/wakeshift.ts"],"names":[],"mappings":"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","sourcesContent":["import { z } from \"zod\";\nimport type { CallToolResult } from \"@modelcontextprotocol/sdk/types.js\";\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport type { AnySchema } from \"@modelcontextprotocol/sdk/server/zod-compat.js\";\nimport { WakeshiftError } from \"./errors.js\";\nimport { WakeEvent, attachEvents, type AttachOptions, type EventOptions, type EventTypeManifest } from \"./events.js\";\nimport { parseKey, signAssertion, type AppKey } from \"./key.js\";\nimport { retryRefused } from \"./retry.js\";\n\n/** Wakeshift's production core, the default for every key but an older wst_test_ one. Override with `core` or WAKESHIFT_CORE. */\nexport const DEFAULT_CORE = \"https://app.wakeshift.ai\";\n\n/** The tool argument an agent passes its session key in (a result gives it one). */\nexport const SESSION_ARG = \"session_key\";\n\n/** The tool argument an agent says which program it runs in with. */\nexport const HARNESS_ARG = \"harness\";\n\n/**\n * The tool argument an agent passes its own ID for the conversation in,\n * when its program gives it one (Cursor and Grok Bot: CURSOR_CONVERSATION_ID).\n */\nexport const CONVERSATION_ARG = \"conversation_id\";\n\n// What the agent is told each argument is (the core's own words:\n// internal/harnesses, whose tests check these match).\nconst SESSION_DESCRIPTION = \"The session key an earlier result gave you, if it did. It's a secret: keep it to this conversation; don't share or log it\";\nconst HARNESS_DESCRIPTION =\n \"The program you're running in: codex, claude-code, cursor (local CLI or IDE), cursor-cloud (Cursor cloud agent), grok-bot, copilot-cli, opencode, antigravity, openclaw (even when it runs your turns in Codex), hermes, chatgpt, or your program's name if it isn't listed\";\nconst CONVERSATION_DESCRIPTION =\n \"Your own ID for this conversation, if your program gives you one. Cursor and Grok Bot: the output of `printenv CURSOR_CONVERSATION_ID`. Codex and Antigravity send it automatically; others leave it empty\";\n\nexport interface WakeshiftOptions {\n /** The app key from the console: wst_ and 50 characters (or an older wst_test_… or wst_live_… key). */\n key: string;\n /**\n * Wakeshift's base URL: the console you got the key from. Default:\n * WAKESHIFT_CORE from the environment, else https://app.wakeshift.ai.\n * An older wst_test_… key has no default: it needs one of the two.\n */\n core?: string;\n /** Default: the global fetch. */\n fetch?: typeof fetch;\n /** Per-request timeout in milliseconds. Default 20000. */\n timeoutMs?: number;\n /**\n * Called with a problem that doesn't fail the call but makes it work less\n * well, for example a tool call Wakeshift recognised no harness in. Each kind is\n * reported once. Default: console.warn.\n */\n onWarning?: (message: string) => void;\n}\n\n/** Which app a key is, as Wakeshift says (wake.app()). */\nexport interface AppInfo {\n id: string;\n name: string;\n}\n\n/** What the SDK says, once, when Wakeshift recognised no harness in a tool call. */\nexport const UNKNOWN_CLIENT_WARNING =\n \"wakeshift: Wakeshift couldn't tell which agent made a tool call (no MCP client name, nothing it knows in the \" +\n \"call's _meta or User-Agent, and no harness argument), so it treats the agent as one it can't wake (its messages are held \" +\n \"for its next call to the tool). The name comes from the client's initialize request, which a server created per request \" +\n \"(stateless Streamable HTTP) never sees; Claude Code, Codex, Antigravity, Copilot CLI, opencode and Cursor are recognised \" +\n \"without it. Spread ...wake.args into the tool's input and pass args to wake.call, so the agent can say (harness); for \" +\n \"other clients, keep one McpServer per MCP session (a stateful transport), or pass the name yourself: \" +\n \"wake.call(extra, { client }) or wake.callOf({ clientName }).\";\n\n/**\n * Who called one of the app's tools, as Wakeshift needs it. Make one with\n * `wake.call(extra, …)` inside an MCP tool callback, or `wake.callOf(…)`.\n */\nexport interface Call {\n /** The app's own ID for the person (optional). */\n user?: string;\n /**\n * The MCP client's name (initialize's clientInfo.name). A stateless\n * server has none; Wakeshift then tells the harness from meta, else\n * user_agent.\n */\n client: string;\n /** The tool call's _meta (Codex sends its thread there). */\n meta?: Record<string, unknown>;\n /** The session handle an earlier result gave the agent. */\n session?: string;\n /** The MCP request's HTTP User-Agent. */\n user_agent?: string;\n /** The conversation's ID as the agent passed it (conversation_id: Cursor's CURSOR_CONVERSATION_ID). */\n conversation?: string;\n /** The program the agent says it runs in (harness): a hint, never a credential. */\n harness?: string;\n /**\n * The name of the tool being called. A connector beacon in its result\n * names it, and Wakeshift's hooks act on the beacon only from that\n * tool's result: put the addition in the result of the tool you name.\n */\n tool?: string;\n}\n\n/**\n * What Wakeshift recognised the calling conversation's harness as, and by\n * which signal (\"claim\": only the agent's harness argument named it); both\n * null when nothing named one. claimed is what the agent said (normalized:\n * \"Grok Bot\" is grok-bot), null if it didn't; a claimed that differs from\n * harness was ignored, since it contradicted what the call was recognised\n * as (the claim only refines it: Cursor's calls may be Grok Bot's).\n */\nexport interface Recognised {\n harness: string | null;\n via: \"client\" | \"meta\" | \"user_agent\" | \"claim\" | null;\n claimed: string | null;\n}\n\n/**\n * Seconds, or a string like \"90s\", \"5m\", \"2h\", \"30d\". Wakeshift checks the\n * value: days must be whole (\"1.5d\" is a bad_request; use \"36h\").\n */\nexport type Duration = number | `${number}${\"s\" | \"m\" | \"h\" | \"d\"}`;\n\nexport interface SubscribeOptions {\n /** Wake only for events whose data has these top-level fields equal to these values. */\n filter?: Record<string, string | number | boolean | null>;\n /** End after the first delivery. */\n once?: boolean;\n /** Deliver the latest event published within this long before subscribing (at most 24 hours). */\n replay?: Duration;\n /** End after this long without a delivery or a fresh subscribe (1 minute to 365 days; default 30 days). */\n ttl?: Duration;\n}\n\n/** What Wakeshift adds to a tool result: text for the agent, _meta for its harness. */\nexport interface Addition {\n text?: string;\n meta?: Record<string, unknown>;\n /** What Wakeshift recognised the caller's harness as (not added to the result). */\n agent?: Recognised;\n}\n\nexport interface Subscription {\n /** For `send`. */\n id: string;\n topic: string;\n filter?: Record<string, unknown>;\n once: boolean;\n expiresAt: Date;\n /**\n * The conversation's session key (the agent passes it back as session_key;\n * the result says so). It's a secret that acts as the conversation: don't\n * show, store or log it. To name the conversation, use id, or an HMAC of it.\n */\n session: string;\n /** What the tool result must carry for the caller's harness. */\n addition: Addition;\n /** What Wakeshift recognised the caller's harness as. */\n agent: Recognised;\n /**\n * The tool result to return: your text (or result) followed by\n * Wakeshift's, with its _meta.\n */\n result(text: string | CallToolResult): CallToolResult;\n}\n\nexport interface TopicEvent {\n /** What the agent reads first (at most 1000 bytes). */\n text: string;\n /** A JSON object, within the 64 KB request limit; filters match its top-level fields. */\n data?: Record<string, unknown>;\n /** Makes retries publish once for a day (at most 200 characters); after a day, the same id publishes again. */\n id?: string;\n}\n\nexport interface Published {\n /** Conversations it woke (or will). */\n matched: number;\n /** An earlier publish had this event's id. */\n duplicate: boolean;\n}\n\n/** delivered: on its way to a connected conversation; queued: waits for it; closed: the subscription ended. */\nexport type SendStatus = \"delivered\" | \"queued\" | \"closed\";\n\n/**\n * How a conversation is connected: stream (a stream held open, e.g.\n * Cursor's background command), poll (long polls or waits, e.g. Claude\n * Code's Monitor, in the last minute) or hooks (Wakeshift's hooks or\n * connector on the user's machine).\n */\nexport type Via = \"stream\" | \"poll\" | \"hooks\" | \"webhook\";\n\nexport interface TopicStatus {\n topic: string;\n /** Conversations subscribed (ended or expired subscriptions don't count). */\n subscriptions: number;\n /** Of those, connected now. */\n connected: number;\n /** How many are connected each way. */\n via: Record<Via, number>;\n}\n\nexport interface SubscriptionStatus {\n id: string;\n topic: string;\n status: \"active\" | \"closed\";\n connected: boolean;\n via?: Via;\n expiresAt?: Date;\n}\n\n/** A publish URL: `topic` for a topic's (`wake.publishUrl`), `event` for an event's (`event.publishUrl`). */\nexport interface PublishUrl {\n id: string;\n topic?: string;\n event?: string;\n url: string;\n}\n\n/** An event pattern a manifest asks for, and what the person is told it's for. */\nexport interface ScopeEvent {\n pattern: string;\n description: string;\n}\n\n/** What the app may do with the agents in the workspaces it keeps (manifest.agent). */\nexport interface AgentScope {\n wake: ScopeEvent[];\n post: ScopeEvent[];\n /** Days the person's consent lasts. */\n ttl_days: number;\n /** At most max wake-ups in any seconds, on top of Wakeshift's own limits. */\n wake_limits?: { seconds: number; max: number }[];\n /** What the person should say to their agent once it's connected; at most 120 characters. */\n start_prompt?: string;\n groups?: boolean;\n}\n\n/** What the app tells Wakeshift it may do (see wake.publishManifest). */\nexport interface Manifest {\n description?: string;\n agent?: AgentScope;\n /** The app's event types: defineEvent fills this in for you. */\n events?: EventTypeManifest[];\n}\n\n/** The parts of an MCP tool callback's `extra` that Wakeshift reads. */\nexport interface ToolExtra {\n _meta?: Record<string, unknown>;\n requestInfo?: { headers?: Record<string, string | string[] | undefined> };\n}\n\n// userAgentOf is the User-Agent of the HTTP request a tool call came in\n// (\"\" if there's none, e.g. over stdio).\nfunction userAgentOf(extra: ToolExtra | undefined): string {\n const headers = extra?.requestInfo?.headers;\n if (!headers) return \"\";\n const v = headers[\"user-agent\"] ?? headers[\"User-Agent\"];\n return (Array.isArray(v) ? v[0] : v) ?? \"\";\n}\n\n/** An McpServer or a low-level Server: anything that knows its client's name. */\nexport type ClientInfoSource =\n | { getClientVersion(): { name: string } | undefined }\n | { server: { getClientVersion(): { name: string } | undefined } };\n\nexport interface CallOptions {\n /** The MCP server the call came to, for the client's name (or pass client). */\n server?: ClientInfoSource;\n /** The client's name, if you know it (instead of server). */\n client?: string;\n /** The app's own ID for the person. */\n user?: string;\n /** The tool's arguments: session_key, harness and conversation_id (wake.args) are read from them. */\n args?: { [SESSION_ARG]?: string; [HARNESS_ARG]?: string; [CONVERSATION_ARG]?: string } | Record<string, unknown>;\n /** The session key, if you read it yourself. */\n session?: string;\n /** The program the agent says it runs in (harness), if you read it yourself. */\n harness?: string;\n /** The conversation's ID the agent passed (conversation_id), if you read it yourself. */\n conversation?: string;\n /**\n * The name of the tool being called (the MCP SDK doesn't hand callbacks\n * it, so pass it): Wakeshift's hooks act on a connector beacon only from\n * the result of the tool it names.\n */\n tool?: string;\n}\n\nexport function clientNameOf(s: ClientInfoSource): string {\n const info = \"getClientVersion\" in s ? s.getClientVersion() : s.server.getClientVersion();\n return info?.name ?? \"\";\n}\n\n/** Adds Wakeshift's text and _meta to a tool result (a copy). */\nexport function applyAddition(a: Addition, base: string | CallToolResult): CallToolResult {\n let out: CallToolResult;\n if (typeof base === \"string\") {\n const text = (base.trim() + \"\\n\\n\" + (a.text ?? \"\")).trim();\n out = { content: text ? [{ type: \"text\", text }] : [] };\n } else {\n out = { ...base, content: [...(base.content ?? [])] };\n if (a.text) out.content.push({ type: \"text\", text: a.text });\n }\n if (a.meta && Object.keys(a.meta).length > 0) out._meta = { ...(out._meta ?? {}), ...a.meta };\n return out;\n}\n\nconst argsShape = {\n [SESSION_ARG]: z.string().optional().describe(SESSION_DESCRIPTION),\n [HARNESS_ARG]: z.string().optional().describe(HARNESS_DESCRIPTION),\n [CONVERSATION_ARG]: z.string().optional().describe(CONVERSATION_DESCRIPTION),\n};\n\n// str is a tool argument's value if it's a string.\nfunction str(args: Record<string, unknown> | undefined, name: string): string | undefined {\n return typeof args?.[name] === \"string\" ? (args[name] as string) : undefined;\n}\n\n/**\n * The Wakeshift client for an app: subscribe the conversations that call\n * your tools to topics, and publish to them.\n */\nexport class Wakeshift {\n /**\n * An older key's mode (wst_test_…, wst_live_…); null for a current key.\n * @deprecated Modes mean nothing now, and current keys have none.\n */\n readonly mode: \"test\" | \"live\" | null;\n readonly core: string;\n private readonly key: AppKey;\n // The app's ID: from the key, if it names the app, or else from app().\n private knownAppId: string | null;\n private appInfo?: Promise<AppInfo>;\n private readonly fetchFn: typeof fetch;\n private readonly timeoutMs: number;\n private readonly warnFn: (message: string) => void;\n private readonly warned = new Set<string>();\n\n constructor(opts: WakeshiftOptions) {\n if (!opts?.key) throw new Error(\"wakeshift: no app key (WAKESHIFT_KEY?)\");\n this.key = parseKey(opts.key);\n this.knownAppId = this.key.appId;\n this.mode = this.key.mode;\n // Test keys come from staging and local consoles, and one sent to\n // production fails in a way that's hard to read: ask for the core.\n const core = opts.core || process.env.WAKESHIFT_CORE || (this.mode === \"test\" ? \"\" : DEFAULT_CORE);\n if (!core) {\n throw new Error(\n \"wakeshift: no core URL for this test key: set WAKESHIFT_CORE, or pass { core }, to the address of the console the key came from (for example https://app.staging.wakeshift.ai)\",\n );\n }\n this.core = core.replace(/\\/+$/, \"\");\n // A request the load balancer refused during a rollout is sent again (retry.ts).\n this.fetchFn = retryRefused(opts.fetch ?? globalThis.fetch);\n this.timeoutMs = opts.timeoutMs ?? 20_000;\n this.warnFn = opts.onWarning ?? ((m) => console.warn(m));\n }\n\n /**\n * The app's ID. An older key (wst_test_…, wst_live_…) names it; for a\n * current key, which doesn't, this throws until `await wake.app()` has\n * asked Wakeshift.\n */\n get appId(): string {\n if (!this.knownAppId) throw new Error(\"wakeshift: call await wake.app() first: this key doesn't name its app\");\n return this.knownAppId;\n }\n\n /**\n * Which app the key is, as Wakeshift says: its ID and name. Asks once\n * (GET /api/apps/v1/app) and remembers the answer; afterwards\n * `wake.appId` works for any key.\n */\n app(): Promise<AppInfo> {\n this.appInfo ??= this.request<{ id?: unknown; name?: unknown }>(\"GET\", \"/app\")\n .then((r) => {\n if (typeof r.id !== \"string\" || !r.id) {\n throw new WakeshiftError(200, \"bad_response\", `Wakeshift at ${this.core} didn't say which app this key is`);\n }\n const id = this.knownAppId ?? r.id;\n this.knownAppId = id;\n return { id, name: typeof r.name === \"string\" ? r.name : \"\" };\n })\n .catch((err: unknown) => {\n this.appInfo = undefined; // a later call asks again\n throw err;\n });\n return this.appInfo;\n }\n\n /** @internal The app's ID if it's known yet (the key names it, or app() has answered), else null. */\n knownApp(): string | null {\n return this.knownAppId;\n }\n\n // A fresh assertion of the app's identity, naming the app once it's known.\n private assertion(): string {\n return signAssertion(this.key, this.core, Date.now(), this.knownAppId);\n }\n\n /** @internal Reports a problem through onWarning, every time. */\n warn(message: string): void {\n this.warnFn(message);\n }\n\n /** Reports a warning, once per kind. */\n private warnOnce(kind: string, message: string): void {\n if (this.warned.has(kind)) return;\n this.warned.add(kind);\n this.warnFn(message);\n }\n\n /**\n * The arguments the agent passes Wakeshift's part of the call in, as a\n * zod shape for your subscribe tool's input (and any other tool whose\n * results you annotate): `inputSchema: { repo: z.string(), ...wake.args }`.\n * session_key (the key a result gives the conversation), harness (the\n * program the agent runs in) and conversation_id (its own ID for the\n * conversation, where its program gives one). Wakeshift adds nothing to\n * tools you don't spread it into.\n */\n get args(): typeof argsShape {\n return argsShape;\n }\n\n /**\n * Packs the tool call from an MCP tool callback's `extra`: its _meta and\n * User-Agent, the client's name (from `server`, or pass `client`), the\n * user, and session_key, harness and conversation_id from `args`.\n */\n call(extra: ToolExtra | undefined, opts: CallOptions = {}): Call {\n let client = opts.client;\n if (client === undefined) {\n if (!opts.server) throw new Error(\"wakeshift: wake.call needs the MCP client's name: pass { server } (your McpServer), or { client }\");\n client = clientNameOf(opts.server);\n }\n const args = opts.args as Record<string, unknown> | undefined;\n return this.callOf({\n meta: extra?._meta,\n clientName: client,\n user: opts.user,\n session: opts.session ?? str(args, SESSION_ARG),\n userAgent: userAgentOf(extra),\n harness: opts.harness ?? str(args, HARNESS_ARG),\n conversation: opts.conversation ?? str(args, CONVERSATION_ARG),\n tool: opts.tool,\n });\n }\n\n /** Packs a tool call without an MCP framework. */\n callOf(c: {\n meta?: Record<string, unknown>;\n clientName: string;\n user?: string;\n session?: string;\n userAgent?: string;\n harness?: string;\n conversation?: string;\n tool?: string;\n }): Call {\n const out: Call = { client: c.clientName ?? \"\" };\n if (c.user) out.user = c.user;\n if (c.meta && Object.keys(c.meta).length > 0) out.meta = c.meta;\n if (c.session) out.session = c.session;\n if (c.userAgent) out.user_agent = c.userAgent;\n if (c.harness?.trim()) out.harness = c.harness.trim();\n if (c.conversation?.trim()) out.conversation = c.conversation.trim();\n if (c.tool?.trim()) out.tool = c.tool.trim();\n return out;\n }\n\n // recognised reads what the core recognised the caller as, and warns\n // once if it was nothing and the agent didn't say (an older core that\n // doesn't say: no warning).\n private recognised(agent: Partial<Recognised> | undefined): Recognised {\n if (agent && !agent.harness && !agent.claimed) this.warnOnce(\"unknown_client\", UNKNOWN_CLIENT_WARNING);\n return { harness: agent?.harness ?? null, via: agent?.via ?? null, claimed: agent?.claimed ?? null };\n }\n\n /**\n * Subscribes the calling conversation to topic (again: refreshes it).\n * Check the caller may see the topic first: Wakeshift only refuses another\n * user's u/<user>/… topics.\n */\n async subscribe(call: Call, topic: string, opts: SubscribeOptions = {}): Promise<Subscription> {\n const body: Record<string, unknown> = { call, topic, once: !!opts.once };\n if (opts.filter && Object.keys(opts.filter).length > 0) body.filter = opts.filter;\n if (opts.replay !== undefined) body.replay = opts.replay;\n if (opts.ttl !== undefined) body.ttl = opts.ttl;\n const out = await this.request<{\n subscription: { id: string; topic: string; filter?: Record<string, unknown>; once: boolean; expires_at: string };\n session: string;\n addition: Addition;\n agent?: Recognised;\n }>(\"POST\", \"/topics/subscribe\", body);\n const agent = this.recognised(out.agent);\n const addition = out.addition ?? {};\n const s = out.subscription;\n return {\n id: s.id,\n topic: s.topic,\n filter: s.filter,\n once: s.once,\n expiresAt: new Date(s.expires_at),\n session: out.session,\n addition,\n agent,\n result: (text) => applyAddition(addition, text),\n };\n }\n\n /** Ends the conversation's subscription to topic, or to all the app's topics. Returns how many ended. */\n async unsubscribe(call: Call, topic?: string): Promise<number> {\n const out = await this.request<{ unsubscribed: number }>(\"POST\", \"/topics/unsubscribe\", topic ? { call, topic } : { call });\n return out.unsubscribed;\n }\n\n /** Wakes every conversation subscribed to one of topics whose filter the event passes (each once). */\n async publish(topics: string | string[], event: TopicEvent): Promise<Published> {\n const out = await this.request<Published>(\"POST\", \"/topics/publish\", { topics: typeof topics === \"string\" ? [topics] : topics, event });\n return { matched: out.matched, duplicate: !!out.duplicate };\n }\n\n /** Wakes exactly one subscription's conversation, whatever its filter. */\n async send(subscriptionId: string, event: TopicEvent): Promise<SendStatus> {\n const out = await this.request<{ status: SendStatus }>(\"POST\", `/subscriptions/${encodeURIComponent(subscriptionId)}/send`, { event });\n return out.status;\n }\n\n /**\n * How many conversations are subscribed to topic, and how many are\n * connected now, and how. Only reads: nothing is delivered, minted or ended.\n */\n async topicStatus(topic: string): Promise<TopicStatus> {\n const out = await this.request<Omit<TopicStatus, \"via\"> & { via?: Partial<Record<Via, number>> }>(\"GET\", `/topics/status?topic=${encodeURIComponent(topic)}`);\n return { topic: out.topic, subscriptions: out.subscriptions, connected: out.connected, via: { stream: 0, poll: 0, hooks: 0, webhook: 0, ...out.via } };\n }\n\n /** Whether a subscription is active and its conversation connected now, and how. Only reads. */\n async subscriptionStatus(subscriptionId: string): Promise<SubscriptionStatus> {\n const out = await this.request<{ id: string; topic: string; status: \"active\" | \"closed\"; connected: boolean; via?: Via; expires_at?: string }>(\n \"GET\",\n `/subscriptions/${encodeURIComponent(subscriptionId)}`,\n );\n const s: SubscriptionStatus = { id: out.id, topic: out.topic, status: out.status, connected: out.connected };\n if (out.via) s.via = out.via;\n if (out.expires_at) s.expiresAt = new Date(out.expires_at);\n return s;\n }\n\n /** A capability URL that publishes to topic: a POST's body becomes an event. */\n async publishUrl(topic: string): Promise<PublishUrl> {\n return this.request<PublishUrl>(\"POST\", \"/topics/publish-urls\", { topic });\n }\n\n /** Stops a publish URL working, a topic's or an event's (410 from then on). */\n async revokePublishUrl(id: string): Promise<void> {\n await this.request(\"DELETE\", `/events/publish-urls/${encodeURIComponent(id)}`);\n }\n\n /** What Wakeshift would add to any other tool result for this conversation (creates nothing). */\n async addition(call: Call): Promise<Addition> {\n const out = await this.request<Addition>(\"POST\", \"/topics/annotate\", { call });\n return { ...out, agent: this.recognised(out.agent) };\n }\n\n /**\n * Adds what Wakeshift has for the calling conversation to a tool result\n * of yours (a copy): what's waiting for a harness that can't be woken, a\n * fresh connector beacon while a Codex thread's connector isn't running.\n * Only results you pass here (and a subscription's result()) change.\n */\n async annotate(call: Call, result: CallToolResult): Promise<CallToolResult> {\n return applyAddition(await this.addition(call), result);\n }\n\n /** Ends every subscription to topic; each conversation is told. Returns how many ended. */\n async closeTopic(topic: string): Promise<number> {\n return (await this.request<{ closed: number }>(\"POST\", \"/topics/close\", { topic })).closed;\n }\n\n /**\n * Ends one subscription by its id, telling its conversation that the app\n * ended it. Returns false if it had already ended (or there's no such\n * subscription of the app's).\n */\n async endSubscription(subscriptionId: string): Promise<boolean> {\n return (await this.request<{ ended: boolean }>(\"POST\", `/subscriptions/${encodeURIComponent(subscriptionId)}/end`, {})).ended;\n }\n\n /**\n * Ends the subscriptions of every conversation of one of the app's users\n * to topic, or to all of the app's topics (they lost access to something),\n * telling each conversation. Returns how many ended.\n */\n async unsubscribeUser(user: string, topic?: string): Promise<number> {\n return (await this.request<{ unsubscribed: number }>(\"POST\", \"/topics/unsubscribe\", topic ? { user, topic } : { user })).unsubscribed;\n }\n\n /**\n * Deletes everything Wakeshift keeps for one of the app's users: their\n * conversations, subscriptions, events and deliveries, recent publishes to\n * their u/<user>/… topics and publish URLs for them, and their ID. Open\n * streams close. Returns false if there was nothing to forget.\n */\n async forgetUser(user: string): Promise<boolean> {\n return (await this.request<{ forgotten: boolean }>(\"POST\", \"/users/forget\", { user })).forgotten;\n }\n\n /**\n * Tells Wakeshift what the app may do, replacing what it said before.\n * The events you defined (defineEvent) are added unless m has events of\n * its own. Returns the manifest as Wakeshift keeps it.\n */\n async publishManifest(m: Manifest): Promise<Manifest> {\n const body: Manifest = m.events === undefined && this.events.size > 0 ? { ...m, events: [...this.events.values()].map((e) => e.manifest) } : m;\n const out = await this.request<Manifest>(\"PUT\", \"/manifest\", body);\n this.manifestBase = m;\n this.published = Promise.resolve();\n return out;\n }\n\n // ── Events (MCP Events, natively or bridged) ──────────────────────────\n\n private readonly events = new Map<string, WakeEvent>();\n private manifestBase: Manifest = {};\n private published: Promise<void> | null = null;\n\n /**\n * Defines one of the app's event types: what a subscriber picks (args),\n * what each occurrence carries (payload), and the line an agent reads\n * first (text). Returns the event, whose emit sends occurrences. Define\n * every event before attach.\n *\n * const message = wake.defineEvent(\"chat.message\", {\n * description: \"A new message in a channel\",\n * args: z.object({ channel: z.string() }),\n * payload: z.object({ from: z.string(), text: z.string() }),\n * text: (m) => `${m.from}: ${m.text}`,\n * })\n * await message.emit({ channel: \"eng\" }, { from: \"ada\", text: \"shipped\" })\n */\n defineEvent<A extends AnySchema, P extends AnySchema>(name: string, opts: EventOptions<A, P>): WakeEvent<A, P> {\n if (this.events.has(name)) throw new Error(`wakeshift: event ${name} is defined twice`);\n const ev = new WakeEvent<A, P>(this, name, opts);\n this.events.set(name, ev as unknown as WakeEvent);\n this.published = null; // the manifest changed\n return ev;\n }\n\n /**\n * Attaches Wakeshift to your MCP server, before you connect it: the one\n * call that connects the two. Today it serves the defined events: MCP\n * Events (events/list, events/subscribe, events/unsubscribe) for clients\n * that speak it, such as ChatGPT, and the subscribe_events tool for\n * everyone else, whom Wakeshift wakes its own ways; plus\n * unsubscribe_events and list_subscriptions for every client, so a person\n * can always see and stop what they're subscribed to.\n *\n * wake.attach(server, { identify: (extra) => ({ user: myUser(extra) }) })\n */\n attach(server: McpServer, opts: AttachOptions = {}): void {\n attachEvents(this, server, [...this.events.values()], opts);\n }\n\n /** @internal Publishes the manifest with the defined events, once (again after a defineEvent). */\n ensureEvents(): Promise<void> {\n if (!this.published) {\n const p = this.publishManifest(this.manifestBase).then(() => undefined);\n this.published = p;\n p.catch(() => {\n if (this.published === p) this.published = null; // try again next time\n });\n }\n return this.published;\n }\n\n /** @internal An event's emit. */\n async emitEvent(e: { name: string; arguments: unknown; payload: unknown; text: string; id?: string; to?: string }): Promise<Published> {\n await this.ensureEvents();\n const body: Record<string, unknown> = { name: e.name, arguments: e.arguments, payload: e.payload, text: e.text };\n if (e.id) body.id = e.id;\n if (e.to) body.to = e.to;\n const out = await this.request<Published>(\"POST\", \"/events/emit\", body);\n return { matched: out.matched, duplicate: !!out.duplicate };\n }\n\n /** @internal A call to the app API (the events machinery's), after the manifest with the defined events is published. */\n async requestApp<T>(method: string, path: string, body?: unknown): Promise<T> {\n await this.ensureEvents();\n return this.request<T>(method, path, body);\n }\n\n // ── Users' workspaces ──────────────────────────────────────────────────\n\n /**\n * The workspace Wakeshift keeps for one of the app's users (user: the\n * app's own ID for them, as in wake.call's user), created on first use.\n * Topics keep that user's conversations there.\n */\n async workspace(user: string, name: string): Promise<string> {\n return (await this.request<{ workspace: string }>(\"POST\", \"/workspaces\", { external_id: user, name })).workspace;\n }\n\n /** Creates an agent in one of the app's workspaces (if new), and its grant for the app's manifest scope. Returns the grant's ID. */\n async addAgent(workspace: string, agent: string, displayName: string): Promise<string> {\n return (await this.request<{ grant: string }>(\"POST\", `/workspaces/${encodeURIComponent(workspace)}/agents`, { agent, display_name: displayName })).grant;\n }\n\n /**\n * Checks that one of the app's agents still has a live grant, asking\n * Wakeshift each time. Throws a WakeshiftError: no_grant once the grant is\n * revoked, unknown_workspace once the workspace is forgotten.\n */\n async checkAgent(workspace: string, agent: string): Promise<void> {\n await this.request(\"POST\", `/workspaces/${encodeURIComponent(workspace)}/agents/${encodeURIComponent(agent)}/token`);\n }\n\n private async request<T>(method: string, path: string, body?: unknown): Promise<T> {\n const headers: Record<string, string> = { Authorization: \"Bearer \" + this.assertion() };\n if (body !== undefined) headers[\"Content-Type\"] = \"application/json\";\n let resp: Response;\n let text: string;\n try {\n resp = await this.fetchFn(this.core + \"/api/apps/v1\" + path, {\n method,\n headers,\n body: body === undefined ? undefined : JSON.stringify(body),\n signal: AbortSignal.timeout(this.timeoutMs),\n });\n text = await resp.text();\n } catch (err) {\n throw this.unreachable(err);\n }\n let json: any;\n try {\n json = text ? JSON.parse(text) : undefined;\n } catch {\n json = undefined;\n }\n if (!resp.ok) {\n const e = json?.error ?? {};\n throw new WakeshiftError(resp.status, e.code ?? \"\", e.message ?? (text.slice(0, 200) || resp.statusText), {\n reason: typeof e.reason === \"string\" ? e.reason : undefined,\n });\n }\n // A 2xx that isn't Wakeshift's JSON: a proxy's page, or a wrong core.\n if (json === null || typeof json !== \"object\") {\n throw new WakeshiftError(\n resp.status,\n \"bad_response\",\n `Wakeshift at ${this.core} answered ${resp.status} without a JSON object. Check that WAKESHIFT_CORE, or the core option, is the address of the console your key came from`,\n );\n }\n return json as T;\n }\n\n // A request that got no answer. Name the core it went to: a wrong or\n // missing WAKESHIFT_CORE is the usual cause.\n private unreachable(err: unknown): WakeshiftError {\n const e = err as { name?: string; message?: string; cause?: { code?: string; message?: string } } | undefined;\n const why =\n e?.name === \"TimeoutError\" || e?.name === \"AbortError\"\n ? `no answer within ${this.timeoutMs / 1000}s`\n : [e?.message, e?.cause?.code ?? e?.cause?.message].filter(Boolean).join(\": \") || String(err);\n return new WakeshiftError(\n 0,\n \"unreachable\",\n `can't reach Wakeshift at ${this.core} (${why}). Check that WAKESHIFT_CORE, or the core option, is the address of the console your key came from`,\n { cause: err },\n );\n }\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wakeshift/sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Let agents subscribe to things in your app: Wakeshift wakes them when you publish.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"homepage": "https://github.com/wakeshift/wakeshift-node#readme",
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
"devDependencies": {
|
|
45
45
|
"@modelcontextprotocol/sdk": "^1.32.1",
|
|
46
46
|
"@types/node": "^22.20.5",
|
|
47
|
-
"typescript": "^
|
|
47
|
+
"typescript": "^7.0.2",
|
|
48
48
|
"zod": "^4.6.7"
|
|
49
49
|
}
|
|
50
50
|
}
|