feat(tlon): add image upload support via @tloncorp/api

- Import configureClient and uploadFile from @tloncorp/api
- Implement uploadImageFromUrl using uploadFile
- Configure API client before media uploads
- Update dependency to github:tloncorp/api-beta#main
This commit is contained in:
Hunter Miller
2026-02-19 09:26:42 -06:00
committed by Josh Lehman
parent 7bbf711302
commit 0995118ec6
2 changed files with 38 additions and 16 deletions

View File

@@ -1,11 +1,10 @@
import { configureClient } from "@tloncorp/api";
import type {
ChannelOutboundAdapter,
ChannelPlugin,
ChannelSetupInput,
OpenClawConfig,
} from "openclaw/plugin-sdk";
// NOTE: configureClient not available in current @tloncorp/api-beta version
// import { configureClient } from "@tloncorp/api";
import {
applyAccountNameToChannelSection,
DEFAULT_ACCOUNT_ID,
@@ -213,13 +212,13 @@ const tlonOutbound: ChannelOutboundAdapter = {
throw new Error(`Invalid Tlon target. Use ${formatTargetHint()}`);
}
// NOTE: configureClient not available in current @tloncorp/api-beta version
// configureClient({
// shipUrl: account.url,
// shipName: account.ship.replace(/^~/, ""),
// verbose: false,
// getCode: async () => account.code!,
// });
// Configure the API client for uploads
configureClient({
shipUrl: account.url,
shipName: account.ship.replace(/^~/, ""),
verbose: false,
getCode: async () => account.code!,
});
const uploadedUrl = mediaUrl ? await uploadImageFromUrl(mediaUrl) : undefined;

View File

@@ -1,17 +1,40 @@
/**
* Upload an image from a URL to Tlon storage.
*
* NOTE: uploadFile is not yet available in @tloncorp/api-beta.
* For now, this returns the original URL. Once the API supports uploads,
* we can implement proper Tlon storage uploads.
*/
import { uploadFile } from "@tloncorp/api";
/**
* Fetch an image from a URL and upload it to Tlon storage.
* Returns the uploaded URL, or falls back to the original URL on error.
*
* Note: configureClient must be called before using this function.
*/
export async function uploadImageFromUrl(imageUrl: string): Promise<string> {
// TODO: Implement once @tloncorp/api exports uploadFile
// For now, just return the original URL
return imageUrl;
try {
// Fetch the image
const response = await fetch(imageUrl);
if (!response.ok) {
console.warn(`[tlon] Failed to fetch image from ${imageUrl}: ${response.status}`);
return imageUrl;
}
const contentType = response.headers.get("content-type") || "image/png";
const blob = await response.blob();
// Extract filename from URL or use a default
const urlPath = new URL(imageUrl).pathname;
const fileName = urlPath.split("/").pop() || `upload-${Date.now()}.png`;
// Upload to Tlon storage
const result = await uploadFile({
blob,
fileName,
contentType,
});
return result.url;
} catch (err) {
console.warn(`[tlon] Failed to upload image, using original URL: ${err}`);
return imageUrl;
}
}