ottoport 1.12.0 → 1.13.1
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/.claude-plugin/plugin.json +1 -1
- package/cli/ottoport.mjs +12 -6
- package/mcp/server.mjs +8 -3
- package/package.json +1 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ottoport",
|
|
3
3
|
"description": "One API for every model. Call chat, image, video, speech and music models through the OttoPort gateway — as MCP tools, slash commands, or the bundled CLI.",
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.13.1",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "LITBOX LLC",
|
|
7
7
|
"email": "support@ottoport.ai"
|
package/cli/ottoport.mjs
CHANGED
|
@@ -153,7 +153,7 @@ async function cmdChat(prompt, flags) {
|
|
|
153
153
|
if (!prompt) die("chat requires a prompt: ottoport chat \"hello\"");
|
|
154
154
|
const { baseUrl, apiKey } = config(flags);
|
|
155
155
|
const messages = [];
|
|
156
|
-
if (flags.system) messages.push({ role: "system", content: flags.system });
|
|
156
|
+
if (last(flags.system)) messages.push({ role: "system", content: last(flags.system) });
|
|
157
157
|
const videos = await videoParts(flags);
|
|
158
158
|
messages.push({ role: "user", content: videos.length ? [{ type: "text", text: prompt }, ...videos] : prompt });
|
|
159
159
|
|
|
@@ -274,10 +274,10 @@ async function cmdImage(prompt, flags) {
|
|
|
274
274
|
...(last(flags.size) ? { size: last(flags.size) } : {}),
|
|
275
275
|
...(last(flags.resolution) ? { resolution: last(flags.resolution) } : {}),
|
|
276
276
|
...(last(flags.quality) ? { quality: last(flags.quality) } : {}),
|
|
277
|
-
...(last(flags["aspect-ratio"]) ? { aspect_ratio: flags["aspect-ratio"] } : {}),
|
|
277
|
+
...(last(flags["aspect-ratio"]) ? { aspect_ratio: last(flags["aspect-ratio"]) } : {}),
|
|
278
278
|
...(last(flags.n) ? { n: Number(last(flags.n)) } : {}),
|
|
279
279
|
...(last(flags.seed) ? { seed: Number(last(flags.seed)) } : {}),
|
|
280
|
-
...(last(flags.image) ? { image_url: flags.image } : {}),
|
|
280
|
+
...(last(flags.image) ? { image_url: last(flags.image) } : {}),
|
|
281
281
|
...(references(flags) ? { reference_image_urls: references(flags) } : {}),
|
|
282
282
|
...collection(flags),
|
|
283
283
|
};
|
|
@@ -305,10 +305,10 @@ async function cmdVideo(prompt, flags) {
|
|
|
305
305
|
...(last(flags.video) ? { video_url: last(flags.video) } : {}),
|
|
306
306
|
...(last(flags.duration) ? { duration: Number(last(flags.duration)) } : {}),
|
|
307
307
|
...(last(flags.resolution) ? { resolution: last(flags.resolution) } : {}),
|
|
308
|
-
...(last(flags["aspect-ratio"]) ? { aspect_ratio: flags["aspect-ratio"] } : {}),
|
|
308
|
+
...(last(flags["aspect-ratio"]) ? { aspect_ratio: last(flags["aspect-ratio"]) } : {}),
|
|
309
309
|
...(last(flags.seed) ? { seed: Number(last(flags.seed)) } : {}),
|
|
310
|
-
...(last(flags.image) ? { image_url: flags.image } : {}),
|
|
311
|
-
...(last(flags["last-frame"]) ? { last_frame_url: flags["last-frame"] } : {}),
|
|
310
|
+
...(last(flags.image) ? { image_url: last(flags.image) } : {}),
|
|
311
|
+
...(last(flags["last-frame"]) ? { last_frame_url: last(flags["last-frame"]) } : {}),
|
|
312
312
|
...(references(flags) ? { reference_image_urls: references(flags) } : {}),
|
|
313
313
|
...(references(flags, "ref-video") ? { reference_video_urls: references(flags, "ref-video") } : {}),
|
|
314
314
|
...(references(flags, "ref-audio") ? { reference_audio_urls: references(flags, "ref-audio") } : {}),
|
|
@@ -448,6 +448,12 @@ async function cmdCollections(action, name, flags) {
|
|
|
448
448
|
? "collections are disabled for this account"
|
|
449
449
|
: `collections are locked: top up $${(access.threshold_cents / 100).toFixed(2)} in total to unlock ($${(access.remaining_cents / 100).toFixed(2)} to go)`);
|
|
450
450
|
}
|
|
451
|
+
if (access.enabled) {
|
|
452
|
+
const gb = (bytes) => `${+(bytes / 1024 ** 3).toFixed(2)} GB`;
|
|
453
|
+
const tier = access.tier && access.quota_source !== "account" ? ` · ${access.tier.id} tier` : "";
|
|
454
|
+
const next = access.quota_source !== "account" && access.next_tier ? ` · $${(access.next_tier.remaining_cents / 100).toFixed(2)} more for ${gb(access.next_tier.quota_bytes)}` : "";
|
|
455
|
+
console.error(`storage: ${gb(access.used_bytes)} of ${gb(access.quota_bytes)}${tier}${next}`);
|
|
456
|
+
}
|
|
451
457
|
for (const c of body.data) console.log(`${c.id} ${c.name} (${c.asset_count ?? 0} asset${c.asset_count === 1 ? "" : "s"})`);
|
|
452
458
|
if (!body.data.length) console.error("no collections in this project yet");
|
|
453
459
|
}
|
package/mcp/server.mjs
CHANGED
|
@@ -84,12 +84,17 @@ function outputLine(item, label = "") {
|
|
|
84
84
|
const withCollection = (id) => (id ? { collection: id } : {});
|
|
85
85
|
|
|
86
86
|
const dollars = (cents) => `$${(cents / 100).toFixed(2)}`;
|
|
87
|
-
const megabytes = (bytes) =>
|
|
87
|
+
const megabytes = (bytes) =>
|
|
88
|
+
bytes >= 1024 ** 4 ? `${+(bytes / 1024 ** 4).toFixed(2)} TB` : bytes >= 1024 ** 3 ? `${+(bytes / 1024 ** 3).toFixed(2)} GB` : `${+(bytes / 1_048_576).toFixed(1)} MB`;
|
|
88
89
|
|
|
89
90
|
async function listCollections() {
|
|
90
91
|
const { data, access } = await api("/api/v1/collections?limit=200");
|
|
92
|
+
const tier = access.tier && access.quota_source !== "account" ? ` (${access.tier.id} tier)` : "";
|
|
93
|
+
const upgrade = access.quota_source !== "account" && access.next_tier
|
|
94
|
+
? ` Topping up ${dollars(access.next_tier.remaining_cents)} more raises the allowance to ${megabytes(access.next_tier.quota_bytes)}.`
|
|
95
|
+
: "";
|
|
91
96
|
const state = access.enabled
|
|
92
|
-
? `Collections are on: ${megabytes(access.used_bytes)} of ${megabytes(access.quota_bytes)} used
|
|
97
|
+
? `Collections are on: ${megabytes(access.used_bytes)} of ${megabytes(access.quota_bytes)} used${tier}.${upgrade}`
|
|
93
98
|
: access.override === false
|
|
94
99
|
? "Collections are disabled for this account; nothing can be saved."
|
|
95
100
|
: `Collections are locked: they unlock once the account has topped up ${dollars(access.threshold_cents)} in total (${dollars(access.remaining_cents)} to go, at ${BASE}/dashboard). Existing collections can still be read.`;
|
|
@@ -532,7 +537,7 @@ const TOOLS = [
|
|
|
532
537
|
},
|
|
533
538
|
{
|
|
534
539
|
name: "ottoport_list_collections",
|
|
535
|
-
description: "Collections in this API key's project — where generated files are kept for good instead of expiring after a few days — with each one's id and asset count, and whether this account may save (collections unlock once the account has topped up $10 in total). Read it before saving, to find the collection the user means.",
|
|
540
|
+
description: "Collections in this API key's project — where generated files are kept for good instead of expiring after a few days — with each one's id and asset count, and whether this account may save (collections unlock once the account has topped up $10 in total), and its storage allowance, which grows with what the account has paid in. Read it before saving, to find the collection the user means.",
|
|
536
541
|
inputSchema: { type: "object", properties: {} },
|
|
537
542
|
handler: listCollections,
|
|
538
543
|
},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ottoport",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.13.1",
|
|
4
4
|
"description": "Claude Code plugin, CLI and MCP server for OttoPort — one OpenAI-compatible API for every LLM, image, video, and speech model.",
|
|
5
5
|
"homepage": "https://ottoport.ai",
|
|
6
6
|
"repository": {
|