feat(sprites): add sprites-url-get and sprites-url-set tools
New tools for managing sprite URL access settings: - sprites-url-get: Get the public URL and auth settings for a sprite - sprites-url-set: Set URL auth to 'public' or 'sprite' (private) Both published as @tpmjs/tools-sprites-url-get and @tpmjs/tools-sprites-url-set v0.1.0
This commit is contained in:
parent
e4c09a475f
commit
27e7d45646
9 changed files with 455 additions and 0 deletions
70
packages/tools/official/sprites-url-get/package.json
Normal file
70
packages/tools/official/sprites-url-get/package.json
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
{
|
||||
"name": "@tpmjs/tools-sprites-url-get",
|
||||
"version": "0.1.0",
|
||||
"description": "Get the public URL and access settings for a sprite",
|
||||
"type": "module",
|
||||
"keywords": [
|
||||
"tpmjs",
|
||||
"sprites",
|
||||
"sandbox",
|
||||
"code-execution",
|
||||
"ai"
|
||||
],
|
||||
"exports": {
|
||||
".": {
|
||||
"types": "./dist/index.d.ts",
|
||||
"default": "./dist/index.js"
|
||||
}
|
||||
},
|
||||
"files": [
|
||||
"dist"
|
||||
],
|
||||
"scripts": {
|
||||
"build": "tsup",
|
||||
"dev": "tsup --watch",
|
||||
"type-check": "tsc --noEmit",
|
||||
"clean": "rm -rf dist .turbo"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@tpmjs/tsconfig": "workspace:*",
|
||||
"tsup": "^8.5.1",
|
||||
"typescript": "^5.9.3"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/anthropics/tpmjs.git",
|
||||
"directory": "packages/tools/official/sprites-url-get"
|
||||
},
|
||||
"homepage": "https://tpmjs.com",
|
||||
"license": "MIT",
|
||||
"tpmjs": {
|
||||
"category": "sandbox",
|
||||
"frameworks": [
|
||||
"vercel-ai"
|
||||
],
|
||||
"tools": [
|
||||
{
|
||||
"name": "spritesUrlGetTool",
|
||||
"description": "Get the public URL and access settings for a sprite. Returns the URL that can be used to access web servers running on port 8080 in the sprite.",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "name",
|
||||
"type": "string",
|
||||
"description": "Name of the sprite to get URL for",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"returns": {
|
||||
"type": "SpriteUrl",
|
||||
"description": "Sprite URL and auth settings"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"dependencies": {
|
||||
"ai": "6.0.23"
|
||||
}
|
||||
}
|
||||
110
packages/tools/official/sprites-url-get/src/index.ts
Normal file
110
packages/tools/official/sprites-url-get/src/index.ts
Normal file
|
|
@ -0,0 +1,110 @@
|
|||
/**
|
||||
* Sprites URL Get Tool for TPMJS
|
||||
* Retrieves the public URL and access settings for a sprite.
|
||||
*
|
||||
* @requires SPRITES_TOKEN environment variable
|
||||
*/
|
||||
|
||||
import { jsonSchema, tool } from 'ai';
|
||||
|
||||
const SPRITES_API_BASE = 'https://api.sprites.dev/v1';
|
||||
|
||||
export interface SpriteUrl {
|
||||
url: string;
|
||||
auth: 'sprite' | 'public';
|
||||
name: string;
|
||||
status: string;
|
||||
}
|
||||
|
||||
type SpritesUrlGetInput = {
|
||||
name: string;
|
||||
};
|
||||
|
||||
function getSpritesToken(): string {
|
||||
const token = process.env.SPRITES_TOKEN;
|
||||
if (!token) {
|
||||
throw new Error(
|
||||
'SPRITES_TOKEN environment variable is required. Get your token from https://sprites.dev'
|
||||
);
|
||||
}
|
||||
return token;
|
||||
}
|
||||
|
||||
export const spritesUrlGetTool = tool({
|
||||
description:
|
||||
'Get the public URL and access settings for a sprite. Returns the URL that can be used to access web servers running on port 8080 in the sprite. The URL format is https://{name}-{id}.sprites.app',
|
||||
inputSchema: jsonSchema<SpritesUrlGetInput>({
|
||||
type: 'object',
|
||||
properties: {
|
||||
name: {
|
||||
type: 'string',
|
||||
description: 'Name of the sprite to get URL for',
|
||||
},
|
||||
},
|
||||
required: ['name'],
|
||||
additionalProperties: false,
|
||||
}),
|
||||
async execute({ name }): Promise<SpriteUrl> {
|
||||
if (!name || typeof name !== 'string') {
|
||||
throw new Error('Sprite name is required and must be a string');
|
||||
}
|
||||
|
||||
const token = getSpritesToken();
|
||||
|
||||
let response: Response;
|
||||
try {
|
||||
const controller = new AbortController();
|
||||
const timeoutId = setTimeout(() => controller.abort(), 30000);
|
||||
|
||||
response = await fetch(`${SPRITES_API_BASE}/sprites/${encodeURIComponent(name)}`, {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
Authorization: `Bearer ${token}`,
|
||||
'User-Agent': 'TPMJS/1.0',
|
||||
},
|
||||
signal: controller.signal,
|
||||
});
|
||||
|
||||
clearTimeout(timeoutId);
|
||||
} catch (error) {
|
||||
if (error instanceof Error) {
|
||||
if (error.name === 'AbortError') {
|
||||
throw new Error(`Request to get URL for sprite "${name}" timed out`);
|
||||
}
|
||||
throw new Error(`Failed to get URL for sprite "${name}": ${error.message}`);
|
||||
}
|
||||
throw new Error(`Failed to get URL for sprite "${name}": Unknown network error`);
|
||||
}
|
||||
|
||||
if (!response.ok) {
|
||||
if (response.status === 404) {
|
||||
throw new Error(`Sprite "${name}" not found`);
|
||||
}
|
||||
if (response.status === 401) {
|
||||
throw new Error('Invalid SPRITES_TOKEN. Check your API token at https://sprites.dev');
|
||||
}
|
||||
const errorText = await response.text().catch(() => 'Unknown error');
|
||||
throw new Error(
|
||||
`Failed to get URL for sprite "${name}": HTTP ${response.status} - ${errorText}`
|
||||
);
|
||||
}
|
||||
|
||||
let data: Record<string, unknown>;
|
||||
try {
|
||||
data = (await response.json()) as Record<string, unknown>;
|
||||
} catch {
|
||||
throw new Error('Failed to parse response from Sprites API');
|
||||
}
|
||||
|
||||
const urlSettings = data.url_settings as Record<string, unknown> | undefined;
|
||||
|
||||
return {
|
||||
url: (data.url as string) || '',
|
||||
auth: (urlSettings?.auth as 'sprite' | 'public') || 'sprite',
|
||||
name: (data.name as string) || name,
|
||||
status: (data.status as string) || 'unknown',
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
export default spritesUrlGetTool;
|
||||
11
packages/tools/official/sprites-url-get/tsconfig.json
Normal file
11
packages/tools/official/sprites-url-get/tsconfig.json
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
"extends": "@tpmjs/tsconfig/base.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "dist",
|
||||
"rootDir": "src",
|
||||
"incremental": false,
|
||||
"composite": false
|
||||
},
|
||||
"include": ["src"],
|
||||
"exclude": ["node_modules", "dist"]
|
||||
}
|
||||
10
packages/tools/official/sprites-url-get/tsup.config.ts
Normal file
10
packages/tools/official/sprites-url-get/tsup.config.ts
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
import { defineConfig } from 'tsup';
|
||||
|
||||
export default defineConfig({
|
||||
entry: ['src/index.ts'],
|
||||
format: ['esm'],
|
||||
dts: true,
|
||||
clean: true,
|
||||
treeshake: true,
|
||||
splitting: false,
|
||||
});
|
||||
76
packages/tools/official/sprites-url-set/package.json
Normal file
76
packages/tools/official/sprites-url-set/package.json
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
{
|
||||
"name": "@tpmjs/tools-sprites-url-set",
|
||||
"version": "0.1.0",
|
||||
"description": "Set the access settings for a sprite URL (public or private)",
|
||||
"type": "module",
|
||||
"keywords": [
|
||||
"tpmjs",
|
||||
"sprites",
|
||||
"sandbox",
|
||||
"code-execution",
|
||||
"ai"
|
||||
],
|
||||
"exports": {
|
||||
".": {
|
||||
"types": "./dist/index.d.ts",
|
||||
"default": "./dist/index.js"
|
||||
}
|
||||
},
|
||||
"files": [
|
||||
"dist"
|
||||
],
|
||||
"scripts": {
|
||||
"build": "tsup",
|
||||
"dev": "tsup --watch",
|
||||
"type-check": "tsc --noEmit",
|
||||
"clean": "rm -rf dist .turbo"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@tpmjs/tsconfig": "workspace:*",
|
||||
"tsup": "^8.5.1",
|
||||
"typescript": "^5.9.3"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/anthropics/tpmjs.git",
|
||||
"directory": "packages/tools/official/sprites-url-set"
|
||||
},
|
||||
"homepage": "https://tpmjs.com",
|
||||
"license": "MIT",
|
||||
"tpmjs": {
|
||||
"category": "sandbox",
|
||||
"frameworks": [
|
||||
"vercel-ai"
|
||||
],
|
||||
"tools": [
|
||||
{
|
||||
"name": "spritesUrlSetTool",
|
||||
"description": "Set the access settings for a sprite URL. Use 'public' to allow anyone to access the sprite URL, or 'sprite' to require authentication.",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "name",
|
||||
"type": "string",
|
||||
"description": "Name of the sprite to update",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "auth",
|
||||
"type": "string",
|
||||
"description": "Access mode - 'public' for public access, 'sprite' for authenticated access only",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"returns": {
|
||||
"type": "SpriteUrlResult",
|
||||
"description": "Updated sprite URL and settings"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"dependencies": {
|
||||
"ai": "6.0.23"
|
||||
}
|
||||
}
|
||||
125
packages/tools/official/sprites-url-set/src/index.ts
Normal file
125
packages/tools/official/sprites-url-set/src/index.ts
Normal file
|
|
@ -0,0 +1,125 @@
|
|||
/**
|
||||
* Sprites URL Set Tool for TPMJS
|
||||
* Sets the access settings for a sprite URL (public or private).
|
||||
*
|
||||
* @requires SPRITES_TOKEN environment variable
|
||||
*/
|
||||
|
||||
import { jsonSchema, tool } from 'ai';
|
||||
|
||||
const SPRITES_API_BASE = 'https://api.sprites.dev/v1';
|
||||
|
||||
export interface SpriteUrlResult {
|
||||
url: string;
|
||||
auth: 'sprite' | 'public';
|
||||
name: string;
|
||||
updated: boolean;
|
||||
}
|
||||
|
||||
type SpritesUrlSetInput = {
|
||||
name: string;
|
||||
auth: 'sprite' | 'public';
|
||||
};
|
||||
|
||||
function getSpritesToken(): string {
|
||||
const token = process.env.SPRITES_TOKEN;
|
||||
if (!token) {
|
||||
throw new Error(
|
||||
'SPRITES_TOKEN environment variable is required. Get your token from https://sprites.dev'
|
||||
);
|
||||
}
|
||||
return token;
|
||||
}
|
||||
|
||||
export const spritesUrlSetTool = tool({
|
||||
description:
|
||||
"Set the access settings for a sprite URL. Use 'public' to allow anyone to access the sprite URL (for web servers, APIs, webhooks), or 'sprite' to require authentication. The sprite must have a server listening on port 8080 for the URL to work.",
|
||||
inputSchema: jsonSchema<SpritesUrlSetInput>({
|
||||
type: 'object',
|
||||
properties: {
|
||||
name: {
|
||||
type: 'string',
|
||||
description: 'Name of the sprite to update',
|
||||
},
|
||||
auth: {
|
||||
type: 'string',
|
||||
enum: ['sprite', 'public'],
|
||||
description:
|
||||
"Access mode - 'public' for public access, 'sprite' for authenticated access only",
|
||||
},
|
||||
},
|
||||
required: ['name', 'auth'],
|
||||
additionalProperties: false,
|
||||
}),
|
||||
async execute({ name, auth }): Promise<SpriteUrlResult> {
|
||||
if (!name || typeof name !== 'string') {
|
||||
throw new Error('Sprite name is required and must be a string');
|
||||
}
|
||||
if (auth !== 'sprite' && auth !== 'public') {
|
||||
throw new Error("Auth must be 'sprite' or 'public'");
|
||||
}
|
||||
|
||||
const token = getSpritesToken();
|
||||
|
||||
let response: Response;
|
||||
try {
|
||||
const controller = new AbortController();
|
||||
const timeoutId = setTimeout(() => controller.abort(), 30000);
|
||||
|
||||
// PUT /v1/sprites/{name} with url_settings
|
||||
response = await fetch(`${SPRITES_API_BASE}/sprites/${encodeURIComponent(name)}`, {
|
||||
method: 'PUT',
|
||||
headers: {
|
||||
Authorization: `Bearer ${token}`,
|
||||
'Content-Type': 'application/json',
|
||||
'User-Agent': 'TPMJS/1.0',
|
||||
},
|
||||
body: JSON.stringify({
|
||||
url_settings: { auth },
|
||||
}),
|
||||
signal: controller.signal,
|
||||
});
|
||||
|
||||
clearTimeout(timeoutId);
|
||||
} catch (error) {
|
||||
if (error instanceof Error) {
|
||||
if (error.name === 'AbortError') {
|
||||
throw new Error(`Request to set URL auth for sprite "${name}" timed out`);
|
||||
}
|
||||
throw new Error(`Failed to set URL auth for sprite "${name}": ${error.message}`);
|
||||
}
|
||||
throw new Error(`Failed to set URL auth for sprite "${name}": Unknown network error`);
|
||||
}
|
||||
|
||||
if (!response.ok) {
|
||||
if (response.status === 404) {
|
||||
throw new Error(`Sprite "${name}" not found`);
|
||||
}
|
||||
if (response.status === 401) {
|
||||
throw new Error('Invalid SPRITES_TOKEN. Check your API token at https://sprites.dev');
|
||||
}
|
||||
const errorText = await response.text().catch(() => 'Unknown error');
|
||||
throw new Error(
|
||||
`Failed to set URL auth for sprite "${name}": HTTP ${response.status} - ${errorText}`
|
||||
);
|
||||
}
|
||||
|
||||
let data: Record<string, unknown>;
|
||||
try {
|
||||
data = (await response.json()) as Record<string, unknown>;
|
||||
} catch {
|
||||
throw new Error('Failed to parse response from Sprites API');
|
||||
}
|
||||
|
||||
const urlSettings = data.url_settings as Record<string, unknown> | undefined;
|
||||
|
||||
return {
|
||||
url: (data.url as string) || '',
|
||||
auth: (urlSettings?.auth as 'sprite' | 'public') || auth,
|
||||
name: (data.name as string) || name,
|
||||
updated: true,
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
export default spritesUrlSetTool;
|
||||
11
packages/tools/official/sprites-url-set/tsconfig.json
Normal file
11
packages/tools/official/sprites-url-set/tsconfig.json
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
"extends": "@tpmjs/tsconfig/base.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "dist",
|
||||
"rootDir": "src",
|
||||
"incremental": false,
|
||||
"composite": false
|
||||
},
|
||||
"include": ["src"],
|
||||
"exclude": ["node_modules", "dist"]
|
||||
}
|
||||
10
packages/tools/official/sprites-url-set/tsup.config.ts
Normal file
10
packages/tools/official/sprites-url-set/tsup.config.ts
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
import { defineConfig } from 'tsup';
|
||||
|
||||
export default defineConfig({
|
||||
entry: ['src/index.ts'],
|
||||
format: ['esm'],
|
||||
dts: true,
|
||||
clean: true,
|
||||
treeshake: true,
|
||||
splitting: false,
|
||||
});
|
||||
32
pnpm-lock.yaml
generated
32
pnpm-lock.yaml
generated
|
|
@ -3187,6 +3187,38 @@ importers:
|
|||
specifier: ^5.9.3
|
||||
version: 5.9.3
|
||||
|
||||
packages/tools/official/sprites-url-get:
|
||||
dependencies:
|
||||
ai:
|
||||
specifier: 6.0.23
|
||||
version: 6.0.23(zod@4.3.5)
|
||||
devDependencies:
|
||||
'@tpmjs/tsconfig':
|
||||
specifier: workspace:*
|
||||
version: link:../../../config/tsconfig
|
||||
tsup:
|
||||
specifier: ^8.5.1
|
||||
version: 8.5.1(jiti@2.6.1)(postcss@8.5.6)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.8.2)
|
||||
typescript:
|
||||
specifier: ^5.9.3
|
||||
version: 5.9.3
|
||||
|
||||
packages/tools/official/sprites-url-set:
|
||||
dependencies:
|
||||
ai:
|
||||
specifier: 6.0.23
|
||||
version: 6.0.23(zod@4.3.5)
|
||||
devDependencies:
|
||||
'@tpmjs/tsconfig':
|
||||
specifier: workspace:*
|
||||
version: link:../../../config/tsconfig
|
||||
tsup:
|
||||
specifier: ^8.5.1
|
||||
version: 8.5.1(jiti@2.6.1)(postcss@8.5.6)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.8.2)
|
||||
typescript:
|
||||
specifier: ^5.9.3
|
||||
version: 5.9.3
|
||||
|
||||
packages/tools/official/stacktrace-parse:
|
||||
dependencies:
|
||||
ai:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue