@creature-ai/sdk 0.1.6 → 0.1.8
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/dist/server/index.d.ts +334 -39
- package/dist/server/index.js +375 -56
- package/dist/server/index.js.map +1 -1
- package/dist/vite/index.d.ts +12 -0
- package/dist/vite/index.js +28 -1
- package/dist/vite/index.js.map +1 -1
- package/package.json +1 -1
package/dist/server/index.js
CHANGED
|
@@ -13401,7 +13401,7 @@ import path from "path";
|
|
|
13401
13401
|
|
|
13402
13402
|
// src/vite/index.ts
|
|
13403
13403
|
import { resolve, join, relative } from "path";
|
|
13404
|
-
import { readdirSync, statSync, existsSync, writeFileSync, mkdirSync, rmSync } from "fs";
|
|
13404
|
+
import { readdirSync, statSync, existsSync, writeFileSync, mkdirSync, rmSync, readFileSync } from "fs";
|
|
13405
13405
|
import { createServer as createNetServer } from "net";
|
|
13406
13406
|
import { createServer as createHttpServer } from "http";
|
|
13407
13407
|
import { createHash } from "crypto";
|
|
@@ -13554,8 +13554,15 @@ function loadHtml(filePath, basePath) {
|
|
|
13554
13554
|
<p>Run <code>npm run build</code> to build the UI.</p>
|
|
13555
13555
|
</body></html>`;
|
|
13556
13556
|
}
|
|
13557
|
-
function
|
|
13558
|
-
|
|
13557
|
+
function isHtmlContent(str) {
|
|
13558
|
+
const trimmed = str.trimStart();
|
|
13559
|
+
return trimmed.startsWith("<") || trimmed.toLowerCase().startsWith("<!doctype");
|
|
13560
|
+
}
|
|
13561
|
+
function htmlLoader(htmlOrPath, basePath) {
|
|
13562
|
+
if (isHtmlContent(htmlOrPath)) {
|
|
13563
|
+
return () => htmlOrPath;
|
|
13564
|
+
}
|
|
13565
|
+
return () => loadHtml(htmlOrPath, basePath);
|
|
13559
13566
|
}
|
|
13560
13567
|
function isInitializeRequest2(body) {
|
|
13561
13568
|
if (typeof body !== "object" || body === null) return false;
|
|
@@ -13758,8 +13765,6 @@ var App = class {
|
|
|
13758
13765
|
callerDir;
|
|
13759
13766
|
shutdownRegistered = false;
|
|
13760
13767
|
isShuttingDown = false;
|
|
13761
|
-
resourceCache = /* @__PURE__ */ new Map();
|
|
13762
|
-
resourceCacheConfig;
|
|
13763
13768
|
/** Server-side instance state, keyed by instanceId. */
|
|
13764
13769
|
instanceState = /* @__PURE__ */ new Map();
|
|
13765
13770
|
/** Callbacks to invoke when an instance is destroyed. */
|
|
@@ -13775,11 +13780,6 @@ var App = class {
|
|
|
13775
13780
|
this.callerDir = callerDir || process.cwd();
|
|
13776
13781
|
this.config = config;
|
|
13777
13782
|
this.isDev = config.dev ?? process.env.NODE_ENV === "development";
|
|
13778
|
-
this.resourceCacheConfig = {
|
|
13779
|
-
maxSize: config.resourceCache?.maxSize ?? 100,
|
|
13780
|
-
ttlMs: config.resourceCache?.ttlMs ?? 0,
|
|
13781
|
-
enabled: config.resourceCache?.enabled ?? true
|
|
13782
|
-
};
|
|
13783
13783
|
if (this.isDev && config.hmrPort) {
|
|
13784
13784
|
this.hmrPort = config.hmrPort;
|
|
13785
13785
|
}
|
|
@@ -13977,6 +13977,46 @@ var App = class {
|
|
|
13977
13977
|
getTransportSessionCount() {
|
|
13978
13978
|
return this.transports.size;
|
|
13979
13979
|
}
|
|
13980
|
+
// ==========================================================================
|
|
13981
|
+
// Public API: Serverless Adapters
|
|
13982
|
+
// ==========================================================================
|
|
13983
|
+
/**
|
|
13984
|
+
* Get the app configuration.
|
|
13985
|
+
*/
|
|
13986
|
+
getConfig() {
|
|
13987
|
+
return this.config;
|
|
13988
|
+
}
|
|
13989
|
+
/**
|
|
13990
|
+
* Get all tool definitions.
|
|
13991
|
+
*/
|
|
13992
|
+
getToolDefinitions() {
|
|
13993
|
+
return this.tools;
|
|
13994
|
+
}
|
|
13995
|
+
/**
|
|
13996
|
+
* Get all resource definitions.
|
|
13997
|
+
*/
|
|
13998
|
+
getResourceDefinitions() {
|
|
13999
|
+
return this.resources;
|
|
14000
|
+
}
|
|
14001
|
+
/**
|
|
14002
|
+
* Create a Vercel MCP adapter configuration.
|
|
14003
|
+
* For use with Vercel's `mcp-handler` package.
|
|
14004
|
+
*
|
|
14005
|
+
* Note: This returns a configuration callback. The implementation
|
|
14006
|
+
* is inline to avoid circular dependencies.
|
|
14007
|
+
*/
|
|
14008
|
+
toVercelMcp(options) {
|
|
14009
|
+
return this.createServerlessConfig(options);
|
|
14010
|
+
}
|
|
14011
|
+
/**
|
|
14012
|
+
* Create an AWS Lambda handler.
|
|
14013
|
+
*
|
|
14014
|
+
* Note: This returns a Lambda handler function. The implementation
|
|
14015
|
+
* is inline to avoid circular dependencies.
|
|
14016
|
+
*/
|
|
14017
|
+
toAwsLambda(options) {
|
|
14018
|
+
return this.createLambdaHandler(options);
|
|
14019
|
+
}
|
|
13980
14020
|
/**
|
|
13981
14021
|
* Close a specific transport session.
|
|
13982
14022
|
*/
|
|
@@ -13993,36 +14033,245 @@ var App = class {
|
|
|
13993
14033
|
// ==========================================================================
|
|
13994
14034
|
// Public API: Resource Cache
|
|
13995
14035
|
// ==========================================================================
|
|
14036
|
+
// Private: Configuration Helpers
|
|
14037
|
+
// ==========================================================================
|
|
14038
|
+
getPort() {
|
|
14039
|
+
return this.config.port || parseInt(process.env.MCP_PORT || process.env.PORT || "3000", 10);
|
|
14040
|
+
}
|
|
14041
|
+
getCallerDir() {
|
|
14042
|
+
return this.callerDir;
|
|
14043
|
+
}
|
|
14044
|
+
// ==========================================================================
|
|
14045
|
+
// Private: Serverless Adapter Helpers
|
|
14046
|
+
// ==========================================================================
|
|
13996
14047
|
/**
|
|
13997
|
-
*
|
|
14048
|
+
* Create a ToolContext for serverless environments.
|
|
14049
|
+
* Shared between Vercel and Lambda adapters to avoid duplication.
|
|
13998
14050
|
*/
|
|
13999
|
-
clearResourceCache() {
|
|
14000
|
-
this.resourceCache.clear();
|
|
14001
|
-
}
|
|
14002
14051
|
/**
|
|
14003
|
-
*
|
|
14052
|
+
* In-memory state for serverless when no external adapter provided.
|
|
14053
|
+
* Only useful for local development - won't persist across invocations in production.
|
|
14004
14054
|
*/
|
|
14005
|
-
|
|
14006
|
-
|
|
14055
|
+
serverlessMemoryState = /* @__PURE__ */ new Map();
|
|
14056
|
+
serverlessStateWarningLogged = false;
|
|
14057
|
+
serverlessRealtimeWarningLogged = false;
|
|
14058
|
+
createServerlessContext({
|
|
14059
|
+
instanceId,
|
|
14060
|
+
creatureToken,
|
|
14061
|
+
stateAdapter,
|
|
14062
|
+
realtimeAdapter
|
|
14063
|
+
}) {
|
|
14064
|
+
const websocketUrl = realtimeAdapter?.getWebSocketUrl?.(instanceId);
|
|
14065
|
+
const app = this;
|
|
14066
|
+
return {
|
|
14067
|
+
instanceId,
|
|
14068
|
+
creatureToken,
|
|
14069
|
+
getState: () => {
|
|
14070
|
+
if (stateAdapter) {
|
|
14071
|
+
return void 0;
|
|
14072
|
+
}
|
|
14073
|
+
if (!app.serverlessStateWarningLogged) {
|
|
14074
|
+
console.warn("[MCP] Using in-memory state - won't persist in production serverless");
|
|
14075
|
+
app.serverlessStateWarningLogged = true;
|
|
14076
|
+
}
|
|
14077
|
+
return app.serverlessMemoryState.get(instanceId);
|
|
14078
|
+
},
|
|
14079
|
+
setState: (state) => {
|
|
14080
|
+
if (stateAdapter) {
|
|
14081
|
+
stateAdapter.set(instanceId, state);
|
|
14082
|
+
return;
|
|
14083
|
+
}
|
|
14084
|
+
if (!app.serverlessStateWarningLogged) {
|
|
14085
|
+
console.warn("[MCP] Using in-memory state - won't persist in production serverless");
|
|
14086
|
+
app.serverlessStateWarningLogged = true;
|
|
14087
|
+
}
|
|
14088
|
+
app.serverlessMemoryState.set(instanceId, state);
|
|
14089
|
+
},
|
|
14090
|
+
send: (message) => {
|
|
14091
|
+
if (realtimeAdapter) {
|
|
14092
|
+
realtimeAdapter.send(instanceId, message);
|
|
14093
|
+
return;
|
|
14094
|
+
}
|
|
14095
|
+
if (!app.serverlessRealtimeWarningLogged) {
|
|
14096
|
+
console.warn("[MCP] Realtime disabled - provide realtimeAdapter for production");
|
|
14097
|
+
app.serverlessRealtimeWarningLogged = true;
|
|
14098
|
+
}
|
|
14099
|
+
},
|
|
14100
|
+
onMessage: (_handler) => {
|
|
14101
|
+
if (realtimeAdapter) {
|
|
14102
|
+
realtimeAdapter.subscribe(instanceId, _handler);
|
|
14103
|
+
return;
|
|
14104
|
+
}
|
|
14105
|
+
if (!app.serverlessRealtimeWarningLogged) {
|
|
14106
|
+
console.warn("[MCP] Realtime disabled - provide realtimeAdapter for production");
|
|
14107
|
+
app.serverlessRealtimeWarningLogged = true;
|
|
14108
|
+
}
|
|
14109
|
+
},
|
|
14110
|
+
onConnect: (_handler) => {
|
|
14111
|
+
if (realtimeAdapter) {
|
|
14112
|
+
return;
|
|
14113
|
+
}
|
|
14114
|
+
},
|
|
14115
|
+
websocketUrl
|
|
14116
|
+
};
|
|
14007
14117
|
}
|
|
14008
14118
|
/**
|
|
14009
|
-
*
|
|
14119
|
+
* Format tool result for serverless response.
|
|
14120
|
+
* Shared between Vercel and Lambda adapters.
|
|
14010
14121
|
*/
|
|
14011
|
-
|
|
14122
|
+
formatServerlessResult(result, instanceId, websocketUrl) {
|
|
14123
|
+
const text = result.text || JSON.stringify(result.data || {});
|
|
14012
14124
|
return {
|
|
14013
|
-
|
|
14014
|
-
|
|
14015
|
-
|
|
14125
|
+
content: [{ type: "text", text }],
|
|
14126
|
+
structuredContent: {
|
|
14127
|
+
...result.data,
|
|
14128
|
+
instanceId,
|
|
14129
|
+
...websocketUrl && { websocketUrl }
|
|
14130
|
+
},
|
|
14131
|
+
_meta: { "openai/widgetSessionId": instanceId },
|
|
14132
|
+
...result.isError && { isError: true }
|
|
14016
14133
|
};
|
|
14017
14134
|
}
|
|
14018
|
-
|
|
14019
|
-
|
|
14020
|
-
|
|
14021
|
-
|
|
14022
|
-
|
|
14135
|
+
/**
|
|
14136
|
+
* Create a Vercel MCP configuration callback.
|
|
14137
|
+
* Returns a function compatible with Vercel's mcp-handler createMcpHandler.
|
|
14138
|
+
*/
|
|
14139
|
+
createServerlessConfig(options) {
|
|
14140
|
+
const { stateAdapter, realtimeAdapter } = options || {};
|
|
14141
|
+
const app = this;
|
|
14142
|
+
return function mcpConfig(server, _context) {
|
|
14143
|
+
for (const [name, definition] of app.tools) {
|
|
14144
|
+
const { config: toolConfig, handler } = definition;
|
|
14145
|
+
const inputSchema = toolConfig.input || z2.object({});
|
|
14146
|
+
const hasUi = !!toolConfig.ui;
|
|
14147
|
+
server.registerTool(
|
|
14148
|
+
name,
|
|
14149
|
+
{
|
|
14150
|
+
title: name,
|
|
14151
|
+
description: toolConfig.description + (hasUi ? " Returns instanceId for the widget." : ""),
|
|
14152
|
+
inputSchema
|
|
14153
|
+
},
|
|
14154
|
+
async (args) => {
|
|
14155
|
+
try {
|
|
14156
|
+
const creatureToken = args._creatureToken;
|
|
14157
|
+
const { _creatureToken: _, ...cleanArgs } = args;
|
|
14158
|
+
const input = toolConfig.input ? toolConfig.input.parse(cleanArgs) : cleanArgs;
|
|
14159
|
+
const instanceId = cleanArgs.instanceId || app.generateInstanceId();
|
|
14160
|
+
const context = app.createServerlessContext({ instanceId, creatureToken, stateAdapter, realtimeAdapter });
|
|
14161
|
+
const result = await handler(input, context);
|
|
14162
|
+
return app.formatServerlessResult(result, instanceId, context.websocketUrl);
|
|
14163
|
+
} catch (error) {
|
|
14164
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
14165
|
+
return { content: [{ type: "text", text: err.message }], isError: true };
|
|
14166
|
+
}
|
|
14167
|
+
}
|
|
14168
|
+
);
|
|
14169
|
+
}
|
|
14170
|
+
};
|
|
14023
14171
|
}
|
|
14024
|
-
|
|
14025
|
-
|
|
14172
|
+
/**
|
|
14173
|
+
* Create an AWS Lambda handler function.
|
|
14174
|
+
*/
|
|
14175
|
+
createLambdaHandler(options) {
|
|
14176
|
+
const { stateAdapter, realtimeAdapter } = options || {};
|
|
14177
|
+
const app = this;
|
|
14178
|
+
return async (event, _lambdaContext) => {
|
|
14179
|
+
const corsHeaders = {
|
|
14180
|
+
"Access-Control-Allow-Origin": "*",
|
|
14181
|
+
"Access-Control-Allow-Methods": "GET, POST, DELETE, OPTIONS",
|
|
14182
|
+
"Access-Control-Allow-Headers": "Content-Type, Accept, Mcp-Session-Id",
|
|
14183
|
+
"Content-Type": "application/json"
|
|
14184
|
+
};
|
|
14185
|
+
if (event.httpMethod === "OPTIONS") {
|
|
14186
|
+
return { statusCode: 204, headers: corsHeaders, body: "" };
|
|
14187
|
+
}
|
|
14188
|
+
let body = {};
|
|
14189
|
+
if (event.body) {
|
|
14190
|
+
try {
|
|
14191
|
+
body = JSON.parse(
|
|
14192
|
+
event.isBase64Encoded ? Buffer.from(event.body, "base64").toString() : event.body
|
|
14193
|
+
);
|
|
14194
|
+
} catch {
|
|
14195
|
+
return {
|
|
14196
|
+
statusCode: 400,
|
|
14197
|
+
headers: corsHeaders,
|
|
14198
|
+
body: JSON.stringify({ jsonrpc: "2.0", error: { code: -32700, message: "Parse error" }, id: null })
|
|
14199
|
+
};
|
|
14200
|
+
}
|
|
14201
|
+
}
|
|
14202
|
+
try {
|
|
14203
|
+
const method = body.method;
|
|
14204
|
+
const params = body.params;
|
|
14205
|
+
const id = body.id;
|
|
14206
|
+
if (method === "initialize") {
|
|
14207
|
+
return {
|
|
14208
|
+
statusCode: 200,
|
|
14209
|
+
headers: corsHeaders,
|
|
14210
|
+
body: JSON.stringify({
|
|
14211
|
+
jsonrpc: "2.0",
|
|
14212
|
+
result: {
|
|
14213
|
+
protocolVersion: "2024-11-05",
|
|
14214
|
+
serverInfo: { name: app.config.name, version: app.config.version },
|
|
14215
|
+
capabilities: { tools: {}, resources: {} }
|
|
14216
|
+
},
|
|
14217
|
+
id
|
|
14218
|
+
})
|
|
14219
|
+
};
|
|
14220
|
+
}
|
|
14221
|
+
if (method === "tools/list") {
|
|
14222
|
+
const tools = [];
|
|
14223
|
+
for (const [name, definition] of app.tools) {
|
|
14224
|
+
tools.push({
|
|
14225
|
+
name,
|
|
14226
|
+
description: definition.config.description,
|
|
14227
|
+
inputSchema: { type: "object" }
|
|
14228
|
+
});
|
|
14229
|
+
}
|
|
14230
|
+
return {
|
|
14231
|
+
statusCode: 200,
|
|
14232
|
+
headers: corsHeaders,
|
|
14233
|
+
body: JSON.stringify({ jsonrpc: "2.0", result: { tools }, id })
|
|
14234
|
+
};
|
|
14235
|
+
}
|
|
14236
|
+
if (method === "tools/call") {
|
|
14237
|
+
const toolName = params?.name;
|
|
14238
|
+
const args = params?.arguments || {};
|
|
14239
|
+
const definition = app.tools.get(toolName);
|
|
14240
|
+
if (!definition) {
|
|
14241
|
+
return {
|
|
14242
|
+
statusCode: 200,
|
|
14243
|
+
headers: corsHeaders,
|
|
14244
|
+
body: JSON.stringify({ jsonrpc: "2.0", error: { code: -32601, message: `Tool not found: ${toolName}` }, id })
|
|
14245
|
+
};
|
|
14246
|
+
}
|
|
14247
|
+
const { config: toolConfig, handler } = definition;
|
|
14248
|
+
const creatureToken = args._creatureToken;
|
|
14249
|
+
const { _creatureToken: _, ...cleanArgs } = args;
|
|
14250
|
+
const input = toolConfig.input ? toolConfig.input.parse(cleanArgs) : cleanArgs;
|
|
14251
|
+
const instanceId = cleanArgs.instanceId || app.generateInstanceId();
|
|
14252
|
+
const context = app.createServerlessContext({ instanceId, creatureToken, stateAdapter, realtimeAdapter });
|
|
14253
|
+
const result = await handler(input, context);
|
|
14254
|
+
const formatted = app.formatServerlessResult(result, instanceId, context.websocketUrl);
|
|
14255
|
+
return {
|
|
14256
|
+
statusCode: 200,
|
|
14257
|
+
headers: corsHeaders,
|
|
14258
|
+
body: JSON.stringify({ jsonrpc: "2.0", result: formatted, id })
|
|
14259
|
+
};
|
|
14260
|
+
}
|
|
14261
|
+
return {
|
|
14262
|
+
statusCode: 200,
|
|
14263
|
+
headers: corsHeaders,
|
|
14264
|
+
body: JSON.stringify({ jsonrpc: "2.0", error: { code: -32601, message: `Method not found: ${method}` }, id })
|
|
14265
|
+
};
|
|
14266
|
+
} catch (error) {
|
|
14267
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
14268
|
+
return {
|
|
14269
|
+
statusCode: 500,
|
|
14270
|
+
headers: corsHeaders,
|
|
14271
|
+
body: JSON.stringify({ jsonrpc: "2.0", error: { code: -32603, message: err.message }, id: body.id ?? null })
|
|
14272
|
+
};
|
|
14273
|
+
}
|
|
14274
|
+
};
|
|
14026
14275
|
}
|
|
14027
14276
|
getHmrPort() {
|
|
14028
14277
|
if (!this.isDev) return null;
|
|
@@ -14091,31 +14340,6 @@ var App = class {
|
|
|
14091
14340
|
return true;
|
|
14092
14341
|
}
|
|
14093
14342
|
// ==========================================================================
|
|
14094
|
-
// Private: Resource Cache
|
|
14095
|
-
// ==========================================================================
|
|
14096
|
-
getCachedResource(uri) {
|
|
14097
|
-
if (!this.resourceCacheConfig.enabled) return null;
|
|
14098
|
-
const cached = this.resourceCache.get(uri);
|
|
14099
|
-
if (!cached) return null;
|
|
14100
|
-
const { ttlMs } = this.resourceCacheConfig;
|
|
14101
|
-
if (ttlMs > 0 && Date.now() - cached.timestamp > ttlMs) {
|
|
14102
|
-
this.resourceCache.delete(uri);
|
|
14103
|
-
return null;
|
|
14104
|
-
}
|
|
14105
|
-
return cached.html;
|
|
14106
|
-
}
|
|
14107
|
-
setCachedResource(uri, html) {
|
|
14108
|
-
if (!this.resourceCacheConfig.enabled) return;
|
|
14109
|
-
const { maxSize } = this.resourceCacheConfig;
|
|
14110
|
-
if (this.resourceCache.size >= maxSize) {
|
|
14111
|
-
const oldestKey = this.resourceCache.keys().next().value;
|
|
14112
|
-
if (oldestKey) {
|
|
14113
|
-
this.resourceCache.delete(oldestKey);
|
|
14114
|
-
}
|
|
14115
|
-
}
|
|
14116
|
-
this.resourceCache.set(uri, { html, timestamp: Date.now() });
|
|
14117
|
-
}
|
|
14118
|
-
// ==========================================================================
|
|
14119
14343
|
// Private: Express Server
|
|
14120
14344
|
// ==========================================================================
|
|
14121
14345
|
createExpressApp() {
|
|
@@ -14314,10 +14538,12 @@ var App = class {
|
|
|
14314
14538
|
},
|
|
14315
14539
|
async (args) => {
|
|
14316
14540
|
try {
|
|
14317
|
-
const
|
|
14541
|
+
const creatureToken = args._creatureToken;
|
|
14542
|
+
const { _creatureToken: _, ...cleanArgs } = args;
|
|
14543
|
+
const input = config.input ? config.input.parse(cleanArgs) : cleanArgs;
|
|
14318
14544
|
let instanceId;
|
|
14319
14545
|
if (hasUi && config.ui) {
|
|
14320
|
-
instanceId = this.resolveInstanceId(config.ui,
|
|
14546
|
+
instanceId = this.resolveInstanceId(config.ui, cleanArgs.instanceId);
|
|
14321
14547
|
}
|
|
14322
14548
|
const resource = config.ui ? this.resources.get(config.ui) : void 0;
|
|
14323
14549
|
const hasWebSocket = resource?.config.websocket === true;
|
|
@@ -14329,6 +14555,7 @@ var App = class {
|
|
|
14329
14555
|
}
|
|
14330
14556
|
const context = {
|
|
14331
14557
|
instanceId: instanceId || "",
|
|
14558
|
+
creatureToken,
|
|
14332
14559
|
getState: () => instanceId ? this.instanceState.get(instanceId) : void 0,
|
|
14333
14560
|
setState: (state) => {
|
|
14334
14561
|
if (instanceId) {
|
|
@@ -14398,6 +14625,11 @@ var App = class {
|
|
|
14398
14625
|
if (config.completedMessage) {
|
|
14399
14626
|
toolMeta["openai/toolInvocation/invoked"] = config.completedMessage;
|
|
14400
14627
|
}
|
|
14628
|
+
if (this.config.auth?.creatureManaged) {
|
|
14629
|
+
toolMeta.creature = {
|
|
14630
|
+
auth: { managed: true }
|
|
14631
|
+
};
|
|
14632
|
+
}
|
|
14401
14633
|
return toolMeta;
|
|
14402
14634
|
}
|
|
14403
14635
|
buildToolDescription(config, inputSchema) {
|
|
@@ -14541,13 +14773,100 @@ function wrapServer(server) {
|
|
|
14541
14773
|
};
|
|
14542
14774
|
return server;
|
|
14543
14775
|
}
|
|
14776
|
+
|
|
14777
|
+
// src/server/auth.ts
|
|
14778
|
+
var CreatureTokenError = class extends Error {
|
|
14779
|
+
/** Error code from the verification API */
|
|
14780
|
+
code;
|
|
14781
|
+
constructor({ code, message }) {
|
|
14782
|
+
super(message);
|
|
14783
|
+
this.name = "CreatureTokenError";
|
|
14784
|
+
this.code = code;
|
|
14785
|
+
}
|
|
14786
|
+
};
|
|
14787
|
+
var DEFAULT_API_URL = "https://api.creature.run";
|
|
14788
|
+
var extractToken = (tokenOrHeader) => {
|
|
14789
|
+
const trimmed = tokenOrHeader.trim();
|
|
14790
|
+
if (trimmed.toLowerCase().startsWith("bearer ")) {
|
|
14791
|
+
return trimmed.slice(7).trim();
|
|
14792
|
+
}
|
|
14793
|
+
return trimmed;
|
|
14794
|
+
};
|
|
14795
|
+
var verifyCreatureToken = async (tokenOrHeader, config) => {
|
|
14796
|
+
if (!tokenOrHeader) {
|
|
14797
|
+
throw new CreatureTokenError({
|
|
14798
|
+
code: "missing_token",
|
|
14799
|
+
message: "No token provided. Expected Authorization header or raw token."
|
|
14800
|
+
});
|
|
14801
|
+
}
|
|
14802
|
+
const token = extractToken(tokenOrHeader);
|
|
14803
|
+
if (!token) {
|
|
14804
|
+
throw new CreatureTokenError({
|
|
14805
|
+
code: "missing_token",
|
|
14806
|
+
message: "Empty token after extraction from Authorization header."
|
|
14807
|
+
});
|
|
14808
|
+
}
|
|
14809
|
+
const apiUrl = config?.apiUrl || DEFAULT_API_URL;
|
|
14810
|
+
const verifyUrl = `${apiUrl}/apps/v1/token/verify`;
|
|
14811
|
+
let response;
|
|
14812
|
+
try {
|
|
14813
|
+
response = await fetch(verifyUrl, {
|
|
14814
|
+
method: "POST",
|
|
14815
|
+
headers: {
|
|
14816
|
+
Authorization: `Bearer ${token}`,
|
|
14817
|
+
"Content-Type": "application/json"
|
|
14818
|
+
}
|
|
14819
|
+
});
|
|
14820
|
+
} catch (err) {
|
|
14821
|
+
throw new CreatureTokenError({
|
|
14822
|
+
code: "network_error",
|
|
14823
|
+
message: `Failed to reach Creature API: ${err instanceof Error ? err.message : "Unknown error"}`
|
|
14824
|
+
});
|
|
14825
|
+
}
|
|
14826
|
+
if (!response.ok) {
|
|
14827
|
+
let errorData = {};
|
|
14828
|
+
try {
|
|
14829
|
+
errorData = await response.json();
|
|
14830
|
+
} catch {
|
|
14831
|
+
}
|
|
14832
|
+
throw new CreatureTokenError({
|
|
14833
|
+
code: errorData.error || "verification_failed",
|
|
14834
|
+
message: errorData.error_description || `Token verification failed (HTTP ${response.status})`
|
|
14835
|
+
});
|
|
14836
|
+
}
|
|
14837
|
+
let data;
|
|
14838
|
+
try {
|
|
14839
|
+
data = await response.json();
|
|
14840
|
+
} catch {
|
|
14841
|
+
throw new CreatureTokenError({
|
|
14842
|
+
code: "invalid_response",
|
|
14843
|
+
message: "Invalid JSON response from Creature API"
|
|
14844
|
+
});
|
|
14845
|
+
}
|
|
14846
|
+
if (!data.valid || !data.claims?.user) {
|
|
14847
|
+
throw new CreatureTokenError({
|
|
14848
|
+
code: "invalid_token",
|
|
14849
|
+
message: "Token is not valid"
|
|
14850
|
+
});
|
|
14851
|
+
}
|
|
14852
|
+
return {
|
|
14853
|
+
user: data.claims.user,
|
|
14854
|
+
organization: data.claims.organization,
|
|
14855
|
+
project: data.claims.project,
|
|
14856
|
+
session: data.claims.session,
|
|
14857
|
+
expiresAt: data.expires_at
|
|
14858
|
+
};
|
|
14859
|
+
};
|
|
14544
14860
|
export {
|
|
14545
14861
|
App,
|
|
14862
|
+
CreatureTokenError,
|
|
14546
14863
|
MIME_TYPES,
|
|
14547
14864
|
createApp,
|
|
14548
14865
|
htmlLoader,
|
|
14866
|
+
isHtmlContent,
|
|
14549
14867
|
loadHtml,
|
|
14550
14868
|
svgToDataUri,
|
|
14869
|
+
verifyCreatureToken,
|
|
14551
14870
|
wrapServer
|
|
14552
14871
|
};
|
|
14553
14872
|
//# sourceMappingURL=index.js.map
|