Tone collections
A tone collection groups tones into a
named bundle (e.g. "Friendly voices"). Collections are
non-versioned, scoped per building block, and reachable through
client.tones.collections. The platform exposes them at
/api/v1/tones/collections; visibility is set inline via
update(). Membership is managed by the uniform
listItems(id) / setItems(id, itemIds) pair.
client.collections.* namespace has been
removed - it pointed at /api/v1/collections/*, which does
not exist on the platform and always returned 404. Use
client.tones.collections for tone collections and
client.constraints.collections
for constraint collections. See the project
CHANGELOG
for the full migration note.
list
client.tones.collections.list(params?: ListParams): Promise<Page<CollectionSummary>>
Each CollectionSummary carries id,
name, description, tags,
itemCount, and the standard engagement fields.
const page = await client.tones.collections.list({ scope: "public", pageSize: 12 });
return {
total: page.total,
items: page.items.map((c) => ({
id: c.id,
name: c.name,
itemCount: c.itemCount,
tags: c.tags,
})),
};
listAll
client.tones.collections.listAll(params?: ListParams): AsyncIterable<CollectionSummary>
const names = [];
for await (const collection of client.tones.collections.listAll({ scope: "public", pageSize: 12 })) {
names.push(collection.name);
if (names.length >= 12) break;
}
return names;
get
client.tones.collections.get(id: string): Promise<ToneCollection>
Detail responses include the tone members inline as items:
an array of ToneCollectionItem objects, each carrying the
join-row id, the underlying toneId, and the
tone label.
const page = await client.tones.collections.list({ scope: "public", pageSize: 6 });
const first = page.items[0];
if (!first) return { empty: true };
const collection = await client.tones.collections.get(first.id);
return {
id: collection.id,
name: collection.name,
description: collection.description,
tags: collection.tags,
itemCount: collection.items.length,
items: collection.items.map((it) => ({ toneId: it.toneId, label: it.label })),
};
create
client.tones.collections.create(input: CollectionCreateInput): Promise<CollectionCreateResponse>
Pass itemIds to seed the collection with tones. The
previous separate toneIds field has been removed;
itemIds is the single, uniform input across both tone and
constraint collections.
const created = await client.tones.collections.create({
name: `docs-demo-tone-coll-${Date.now()}`,
description: "Created from the docs site.",
isPublic: false,
tags: ["demo"],
});
await client.tones.collections.delete(created.id);
return created;
update
client.tones.collections.update(id: string, input: CollectionUpdateInput): Promise<void>
Updates name, description, tags, or visibility. There is no separate
visibility endpoint - pass isPublic here.
const created = await client.tones.collections.create({
name: `docs-demo-${Date.now()}`,
description: "original",
isPublic: false,
});
await client.tones.collections.update(created.id, {
name: `docs-demo-updated-${Date.now()}`,
description: "updated",
tags: ["updated"],
isPublic: true,
});
const detail = await client.tones.collections.get(created.id);
await client.tones.collections.delete(created.id);
return {
name: detail.name,
description: detail.description,
tags: detail.tags,
isPublic: detail.isPublic,
};
delete
client.tones.collections.delete(id: string): Promise<void>
const created = await client.tones.collections.create({ name: `docs-demo-${Date.now()}` });
await client.tones.collections.delete(created.id);
try {
await client.tones.collections.get(created.id);
return { deleted: false };
} catch (err) {
if (err instanceof PromptyNotFoundError) return { deleted: true };
throw err;
}
vote
client.tones.collections.vote(id: string, value: 1 | -1): Promise<void>
const created = await client.tones.collections.create({ name: `docs-demo-vote-${Date.now()}` });
await client.tones.collections.vote(created.id, 1);
const detail = await client.tones.collections.get(created.id);
await client.tones.collections.delete(created.id);
return { upvotes: detail.upvotes, userVote: detail.userVote };
unvote
client.tones.collections.unvote(id: string): Promise<void>
const created = await client.tones.collections.create({ name: `docs-demo-unvote-${Date.now()}` });
await client.tones.collections.vote(created.id, -1);
await client.tones.collections.unvote(created.id);
const detail = await client.tones.collections.get(created.id);
await client.tones.collections.delete(created.id);
return { downvotes: detail.downvotes, userVote: detail.userVote };
toggleFavorite
client.tones.collections.toggleFavorite(id: string): Promise<{ favorited: boolean }>
const created = await client.tones.collections.create({ name: `docs-demo-fav-${Date.now()}` });
const a = await client.tones.collections.toggleFavorite(created.id);
const b = await client.tones.collections.toggleFavorite(created.id);
await client.tones.collections.delete(created.id);
return { firstToggle: a.favorited, secondToggle: b.favorited };
listItems
client.tones.collections.listItems(id: string): Promise<readonly ToneCollectionItem[]>
Returns the tones currently in the collection. Each item carries the
join-row id, the underlying toneId, and the
tone label.
const tone = await client.tones.create({
label: `docs-tone-${Date.now()}`,
isPublic: false,
});
const collection = await client.tones.collections.create({
name: `docs-coll-${Date.now()}`,
isPublic: false,
itemIds: [tone.id],
});
const items = await client.tones.collections.listItems(collection.id);
await client.tones.collections.delete(collection.id);
await client.tones.delete(tone.id);
return items;
setItems
client.tones.collections.setItems(id: string, itemIds: readonly string[]): Promise<void>
Replaces the entire tone set for the collection - pass an empty array
to clear it. This single method replaces the previous
setTones on the legacy flat namespace.
const t1 = await client.tones.create({ label: `docs-t1-${Date.now()}`, isPublic: false });
const t2 = await client.tones.create({ label: `docs-t2-${Date.now()}`, isPublic: false });
const collection = await client.tones.collections.create({ name: `docs-coll-${Date.now()}`, isPublic: false });
await client.tones.collections.setItems(collection.id, [t1.id]);
const after1 = (await client.tones.collections.listItems(collection.id)).length;
await client.tones.collections.setItems(collection.id, [t1.id, t2.id]);
const after2 = (await client.tones.collections.listItems(collection.id)).length;
await client.tones.collections.setItems(collection.id, []);
const after3 = (await client.tones.collections.listItems(collection.id)).length;
await client.tones.collections.delete(collection.id);
await client.tones.delete(t1.id);
await client.tones.delete(t2.id);
return { afterFirstSet: after1, afterSecondSet: after2, afterClear: after3 };