rewind-mcp-server 0.1.1 → 0.4.0

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.
Files changed (53) hide show
  1. package/README.md +84 -11
  2. package/dist/__tests__/helpers.test.d.ts +1 -0
  3. package/dist/__tests__/helpers.test.js +131 -0
  4. package/dist/__tests__/helpers.test.js.map +1 -0
  5. package/dist/__tests__/image-block.live.d.ts +1 -0
  6. package/dist/__tests__/image-block.live.js +41 -0
  7. package/dist/__tests__/image-block.live.js.map +1 -0
  8. package/dist/__tests__/server.test.js +713 -16
  9. package/dist/__tests__/server.test.js.map +1 -1
  10. package/dist/__tests__/stdio-e2e.live.d.ts +1 -0
  11. package/dist/__tests__/stdio-e2e.live.js +60 -0
  12. package/dist/__tests__/stdio-e2e.live.js.map +1 -0
  13. package/dist/__tests__/ui-resource.live.d.ts +1 -0
  14. package/dist/__tests__/ui-resource.live.js +71 -0
  15. package/dist/__tests__/ui-resource.live.js.map +1 -0
  16. package/dist/client.d.ts +9 -0
  17. package/dist/client.js +15 -0
  18. package/dist/client.js.map +1 -1
  19. package/dist/index.js +0 -0
  20. package/dist/prompts.js +132 -0
  21. package/dist/prompts.js.map +1 -1
  22. package/dist/resources/ui.d.ts +33 -0
  23. package/dist/resources/ui.js +14 -0
  24. package/dist/resources/ui.js.map +1 -0
  25. package/dist/resources.js +144 -0
  26. package/dist/resources.js.map +1 -1
  27. package/dist/server.js +55 -1
  28. package/dist/server.js.map +1 -1
  29. package/dist/tools/collecting.js +78 -37
  30. package/dist/tools/collecting.js.map +1 -1
  31. package/dist/tools/cross-domain.js +147 -19
  32. package/dist/tools/cross-domain.js.map +1 -1
  33. package/dist/tools/debug.d.ts +6 -0
  34. package/dist/tools/debug.js +26 -0
  35. package/dist/tools/debug.js.map +1 -0
  36. package/dist/tools/helpers.d.ts +81 -5
  37. package/dist/tools/helpers.js +138 -4
  38. package/dist/tools/helpers.js.map +1 -1
  39. package/dist/tools/listening.js +223 -52
  40. package/dist/tools/listening.js.map +1 -1
  41. package/dist/tools/reading.js +122 -22
  42. package/dist/tools/reading.js.map +1 -1
  43. package/dist/tools/running.js +87 -43
  44. package/dist/tools/running.js.map +1 -1
  45. package/dist/tools/watching.js +199 -32
  46. package/dist/tools/watching.js.map +1 -1
  47. package/dist/ui-bundles.d.ts +3 -0
  48. package/dist/ui-bundles.js +8 -0
  49. package/dist/ui-bundles.js.map +1 -0
  50. package/dist/worker.d.ts +2 -1
  51. package/dist/worker.js +55 -30
  52. package/dist/worker.js.map +1 -1
  53. package/package.json +13 -2
@@ -1,13 +1,40 @@
1
1
  import { z } from 'zod';
2
- import { withErrorHandling, timeAgo, fmt, READ_ONLY_ANNOTATIONS, } from './helpers.js';
2
+ import { withRichResponse, text, resourceLink, imageBlock, timeAgo, fmt, READ_ONLY_ANNOTATIONS, LIST_IMAGE_PX, } from './helpers.js';
3
+ const SEARCH_TOP_N = 5;
4
+ /**
5
+ * Map a cross-domain entity reference to a Rewind resource URI.
6
+ * Returns null when the entity type has no registered resource template.
7
+ */
8
+ function rewindUri(domain, entityType, entityId) {
9
+ if (!entityId)
10
+ return null;
11
+ const map = {
12
+ 'listening:artist': 'artist',
13
+ 'listening:album': 'album',
14
+ 'watching:movie': 'movie',
15
+ 'watching:show': 'show',
16
+ 'collecting:vinyl': 'vinyl',
17
+ 'collecting:release': 'vinyl',
18
+ 'collecting:media': 'physical-media',
19
+ 'reading:article': 'article',
20
+ 'reading:highlight': 'highlight',
21
+ 'running:activity': 'activity',
22
+ };
23
+ const kind = map[`${domain}:${entityType}`];
24
+ return kind ? `rewind://${kind}/${entityId}` : null;
25
+ }
3
26
  export function registerCrossDomainTools(server, client) {
4
- // search
5
- server.tool('search', 'Search across all domains (listening, running, watching, collecting, reading) using full-text search. Returns matching artists, albums, movies, articles, runs, and more.', {
27
+ // search ─────────────────────────────────────────────────────────
28
+ server.tool('search', 'Search across all domains (listening, running, watching, collecting, reading). Three ranking modes: keyword (default) uses FTS5 full-text search across all domains; semantic uses Voyage AI embeddings for paraphrased / meaning-based recall (reading domain only); hybrid fuses both (reading domain only). Use semantic or hybrid when the user describes what an article was ABOUT rather than quoting its words.', {
6
29
  query: z.string().describe('Search query text'),
7
30
  domain: z
8
31
  .enum(['listening', 'running', 'watching', 'collecting', 'reading'])
9
32
  .optional()
10
33
  .describe('Optional: filter results to a single domain'),
34
+ mode: z
35
+ .enum(['keyword', 'semantic', 'hybrid'])
36
+ .optional()
37
+ .describe('Ranking mode. keyword = FTS (default). semantic = cosine-similarity over article embeddings (reading only). hybrid = FTS + semantic via reciprocal rank fusion (reading only).'),
11
38
  limit: z
12
39
  .number()
13
40
  .min(1)
@@ -15,7 +42,7 @@ export function registerCrossDomainTools(server, client) {
15
42
  .default(10)
16
43
  .describe('Number of results to return'),
17
44
  page: z.number().min(1).default(1).describe('Page number for pagination'),
18
- }, READ_ONLY_ANNOTATIONS, async ({ query, domain, limit, page }) => withErrorHandling(async () => {
45
+ }, READ_ONLY_ANNOTATIONS, async ({ query, domain, mode, limit, page }) => withRichResponse(async () => {
19
46
  const params = {
20
47
  q: query,
21
48
  limit,
@@ -23,19 +50,106 @@ export function registerCrossDomainTools(server, client) {
23
50
  };
24
51
  if (domain)
25
52
  params.domain = domain;
53
+ if (mode)
54
+ params.mode = mode;
26
55
  const data = await client.get('/search', params);
27
- if (!data.data.length)
28
- return `No results found for "${query}"${domain ? ` in ${domain}` : ''}.`;
56
+ if (!data.data.length) {
57
+ return {
58
+ content: [
59
+ text(`No results found for "${query}"${domain ? ` in ${domain}` : ''}.`),
60
+ ],
61
+ structuredContent: { items: [], pagination: data.pagination },
62
+ };
63
+ }
64
+ const modeLabel = mode && mode !== 'keyword' ? ` [${mode}]` : '';
65
+ const lines = [
66
+ `Search results for "${query}"${modeLabel} (${fmt(data.pagination.total)} total):`,
67
+ ];
68
+ for (const [i, r] of data.data.entries()) {
69
+ const sub = r.subtitle ? ` -- ${r.subtitle}` : '';
70
+ const score = typeof r.score === 'number' ? ` (score=${r.score.toFixed(2)})` : '';
71
+ lines.push(`${i + 1}. [${r.domain}/${r.entity_type}] ${r.title}${sub}${score}`);
72
+ }
73
+ // Emit one resource_link per result that maps to a known entity.
74
+ const links = data.data
75
+ .map((r) => {
76
+ const uri = rewindUri(r.domain, r.entity_type, r.entity_id);
77
+ if (!uri)
78
+ return null;
79
+ return resourceLink(uri, r.title, {
80
+ mimeType: 'application/json',
81
+ description: r.subtitle ?? undefined,
82
+ });
83
+ })
84
+ .filter((b) => b !== null);
85
+ // Emit image blocks for the top-N results that carry an image.
86
+ const topN = data.data.slice(0, SEARCH_TOP_N);
87
+ const images = await Promise.all(topN.map((r) => imageBlock(client, r.image, LIST_IMAGE_PX)));
88
+ const imageBlocks = images.filter((b) => b !== null);
89
+ const content = [
90
+ text(lines.join('\n')),
91
+ ...imageBlocks,
92
+ ...links,
93
+ ];
94
+ return {
95
+ content,
96
+ structuredContent: { items: data.data, pagination: data.pagination },
97
+ };
98
+ }));
99
+ // semantic_search ────────────────────────────────────────────────
100
+ server.tool('semantic_search', 'Semantic search over the reading domain using Voyage AI embeddings. Use when the user describes the gist or topic of an article they remember rather than quoting exact words — e.g. "article about a former SNL writer" or "piece about tech layoffs". Returns articles ranked by cosine similarity with a score in [0,1]. Reading domain only.', {
101
+ query: z.string().describe('Natural-language description of the article'),
102
+ limit: z
103
+ .number()
104
+ .min(1)
105
+ .max(25)
106
+ .default(10)
107
+ .describe('Number of matches to return'),
108
+ }, READ_ONLY_ANNOTATIONS, async ({ query, limit }) => withRichResponse(async () => {
109
+ const data = await client.get('/search', {
110
+ q: query,
111
+ domain: 'reading',
112
+ mode: 'semantic',
113
+ limit,
114
+ });
115
+ if (!data.data.length) {
116
+ return {
117
+ content: [text(`No semantic matches found for "${query}".`)],
118
+ structuredContent: { items: [], pagination: data.pagination },
119
+ };
120
+ }
29
121
  const lines = [
30
- `Search results for "${query}" (${fmt(data.pagination.total)} total):`,
122
+ `Semantic matches for "${query}" (${fmt(data.data.length)} shown):`,
31
123
  ];
32
124
  for (const [i, r] of data.data.entries()) {
33
125
  const sub = r.subtitle ? ` -- ${r.subtitle}` : '';
34
- lines.push(`${i + 1}. [${r.domain}/${r.entity_type}] ${r.title}${sub}`);
126
+ lines.push(`${i + 1}. ${r.title}${sub} (score=${r.score.toFixed(2)})`);
35
127
  }
36
- return lines.join('\n');
128
+ const links = data.data
129
+ .map((r) => {
130
+ const uri = rewindUri(r.domain, r.entity_type, r.entity_id);
131
+ if (!uri)
132
+ return null;
133
+ return resourceLink(uri, r.title, {
134
+ mimeType: 'application/json',
135
+ description: r.subtitle ?? undefined,
136
+ });
137
+ })
138
+ .filter((b) => b !== null);
139
+ const topN = data.data.slice(0, SEARCH_TOP_N);
140
+ const images = await Promise.all(topN.map((r) => imageBlock(client, r.image, LIST_IMAGE_PX)));
141
+ const imageBlocks = images.filter((b) => b !== null);
142
+ const content = [
143
+ text(lines.join('\n')),
144
+ ...imageBlocks,
145
+ ...links,
146
+ ];
147
+ return {
148
+ content,
149
+ structuredContent: { items: data.data, pagination: data.pagination },
150
+ };
37
151
  }));
38
- // get_feed
152
+ // get_feed ───────────────────────────────────────────────────────
39
153
  server.tool('get_feed', 'Get the unified activity feed across all domains. Returns a chronological list of recent activities (listens, runs, watches, reads, collection adds). Supports date filtering.', {
40
154
  limit: z
41
155
  .number()
@@ -59,7 +173,7 @@ export function registerCrossDomainTools(server, client) {
59
173
  .string()
60
174
  .optional()
61
175
  .describe('Optional: end of date range (ISO 8601)'),
62
- }, READ_ONLY_ANNOTATIONS, async ({ limit, domain, date, from, to }) => withErrorHandling(async () => {
176
+ }, READ_ONLY_ANNOTATIONS, async ({ limit, domain, date, from, to }) => withRichResponse(async () => {
63
177
  const params = {
64
178
  limit,
65
179
  date,
@@ -68,8 +182,12 @@ export function registerCrossDomainTools(server, client) {
68
182
  };
69
183
  const path = domain ? `/feed/domain/${domain}` : '/feed';
70
184
  const data = await client.get(path, params);
71
- if (!data.data.length)
72
- return 'No feed activity found for the given filters.';
185
+ if (!data.data.length) {
186
+ return {
187
+ content: [text('No feed activity found for the given filters.')],
188
+ structuredContent: { items: [], pagination: data.pagination },
189
+ };
190
+ }
73
191
  const lines = ['Activity Feed:'];
74
192
  for (const item of data.data) {
75
193
  const sub = item.subtitle ? ` -- ${item.subtitle}` : '';
@@ -78,9 +196,12 @@ export function registerCrossDomainTools(server, client) {
78
196
  if (data.pagination.has_more) {
79
197
  lines.push('\nMore items available. Increase limit or narrow date range.');
80
198
  }
81
- return lines.join('\n');
199
+ return {
200
+ content: [text(lines.join('\n'))],
201
+ structuredContent: { items: data.data, pagination: data.pagination },
202
+ };
82
203
  }));
83
- // get_on_this_day
204
+ // get_on_this_day ────────────────────────────────────────────────
84
205
  server.tool('get_on_this_day', "Get historical 'on this day' items -- what happened on a given date in previous years across all domains. Defaults to today. Great for nostalgia and reflection.", {
85
206
  month: z
86
207
  .number()
@@ -94,11 +215,15 @@ export function registerCrossDomainTools(server, client) {
94
215
  .max(31)
95
216
  .optional()
96
217
  .describe('Optional: day (1-31). Defaults to current day.'),
97
- }, READ_ONLY_ANNOTATIONS, async ({ month, day }) => withErrorHandling(async () => {
218
+ }, READ_ONLY_ANNOTATIONS, async ({ month, day }) => withRichResponse(async () => {
98
219
  const params = { month, day };
99
220
  const data = await client.get('/feed/on-this-day', params);
100
- if (!data.years.length)
101
- return "No 'on this day' history found.";
221
+ if (!data.years.length) {
222
+ return {
223
+ content: [text("No 'on this day' history found.")],
224
+ structuredContent: data,
225
+ };
226
+ }
102
227
  const lines = [`On This Day (${data.month}/${data.day}):`];
103
228
  for (const yearGroup of data.years) {
104
229
  lines.push('');
@@ -108,7 +233,10 @@ export function registerCrossDomainTools(server, client) {
108
233
  lines.push(` - [${item.domain}] ${item.title}${sub}`);
109
234
  }
110
235
  }
111
- return lines.join('\n');
236
+ return {
237
+ content: [text(lines.join('\n'))],
238
+ structuredContent: data,
239
+ };
112
240
  }));
113
241
  }
114
242
  //# sourceMappingURL=cross-domain.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"cross-domain.js","sourceRoot":"","sources":["../../src/tools/cross-domain.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"cross-domain.js","sourceRoot":"","sources":["../../src/tools/cross-domain.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Debug tools for MCP Apps pipeline verification. Throwaway -- will be
3
+ * removed once Phase 2 stabilizes.
4
+ */
5
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
6
+ export declare function registerDebugTools(server: McpServer): void;
@@ -0,0 +1,26 @@
1
+ import { READ_ONLY_ANNOTATIONS } from './helpers.js';
2
+ export function registerDebugTools(server) {
3
+ server.registerTool('ui_hello_debug', {
4
+ title: 'UI Hello (debug)',
5
+ description: 'Show the Rewind MCP Apps diagnostic UI. Invoke this to verify the MCP Apps pipeline end-to-end against a known-working minimal React app.',
6
+ inputSchema: {},
7
+ annotations: READ_ONLY_ANNOTATIONS,
8
+ _meta: {
9
+ ui: { resourceUri: 'ui://rewind/hello.html' },
10
+ 'ui/resourceUri': 'ui://rewind/hello.html',
11
+ },
12
+ }, async () => ({
13
+ content: [
14
+ {
15
+ type: 'text',
16
+ text: 'Rewind MCP Apps diagnostic. If the UI renders inline, the MCP Apps pipeline is working; if it fails with "Failed to set up MCP app", the issue is client-side (Anthropic sandbox).',
17
+ },
18
+ ],
19
+ structuredContent: {
20
+ greeting: 'hello',
21
+ server_time: new Date().toISOString(),
22
+ app: 'rewind-hello',
23
+ },
24
+ }));
25
+ }
26
+ //# sourceMappingURL=debug.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"debug.js","sourceRoot":"","sources":["../../src/tools/debug.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,qBAAqB,EAAE,MAAM,cAAc,CAAC;AAErD,MAAM,UAAU,kBAAkB,CAAC,MAAiB;IAClD,MAAM,CAAC,YAAY,CACjB,gBAAgB,EAChB;QACE,KAAK,EAAE,kBAAkB;QACzB,WAAW,EACT,2IAA2I;QAC7I,WAAW,EAAE,EAAE;QACf,WAAW,EAAE,qBAAqB;QAClC,KAAK,EAAE;YACL,EAAE,EAAE,EAAE,WAAW,EAAE,wBAAwB,EAAE;YAC7C,gBAAgB,EAAE,wBAAwB;SAC3C;KACF,EACD,KAAK,IAAI,EAAE,CAAC,CAAC;QACX,OAAO,EAAE;YACP;gBACE,IAAI,EAAE,MAAe;gBACrB,IAAI,EAAE,oLAAoL;aAC3L;SACF;QACD,iBAAiB,EAAE;YACjB,QAAQ,EAAE,OAAO;YACjB,WAAW,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;YACrC,GAAG,EAAE,cAAc;SACpB;KACF,CAAC,CACH,CAAC;AACJ,CAAC"}
@@ -1,32 +1,108 @@
1
1
  import { z } from 'zod';
2
2
  import type { RewindClient } from '../client.js';
3
+ export type TextBlock = {
4
+ type: 'text';
5
+ text: string;
6
+ };
7
+ export type ImageBlock = {
8
+ type: 'image';
9
+ data: string;
10
+ mimeType: string;
11
+ };
12
+ export type ResourceLinkBlock = {
13
+ type: 'resource_link';
14
+ uri: string;
15
+ name: string;
16
+ mimeType?: string;
17
+ description?: string;
18
+ };
19
+ export type ContentBlock = TextBlock | ImageBlock | ResourceLinkBlock;
20
+ export type ToolResult<S = unknown> = {
21
+ content: ContentBlock[];
22
+ structuredContent?: S;
23
+ isError?: boolean;
24
+ };
25
+ /** Build a text content block. */
26
+ export declare function text(value: string): TextBlock;
27
+ /**
28
+ * Build a resource_link content block.
29
+ * Returns null if the URI is missing/empty so callers can `.filter(Boolean)`.
30
+ */
31
+ export declare function resourceLink(uri: string | null | undefined, name: string, opts?: {
32
+ mimeType?: string;
33
+ description?: string;
34
+ }): ResourceLinkBlock | null;
35
+ /**
36
+ * An image attachment as returned by Rewind entity responses.
37
+ * Accepts both `cdn_url` (live API) and `url` (OpenAPI-schema-example field).
38
+ */
39
+ export type ImageAttachment = {
40
+ cdn_url?: string | null;
41
+ url?: string | null;
42
+ thumbhash?: string | null;
43
+ dominant_color?: string | null;
44
+ accent_color?: string | null;
45
+ } | null | undefined;
46
+ /**
47
+ * Build an image content block from an entity's image attachment by fetching
48
+ * the public CDN URL directly. Returns null on any failure or missing URL --
49
+ * never throws. Image blocks are best-effort; we always want to return
50
+ * text/data even if the image fetch breaks.
51
+ *
52
+ * Pass `targetPx` to request a smaller transform -- overrides the `width` and
53
+ * `height` query params on the CDN URL. Useful for list tools that must stay
54
+ * under the client's per-response size budget. Omit for full-size (typically
55
+ * 300x300) detail-tool posters.
56
+ */
57
+ export declare function imageBlock(client: RewindClient, image: ImageAttachment, targetPx?: number): Promise<ImageBlock | null>;
58
+ /** Target pixel size for list-tool image blocks. Keeps responses under ~250KB. */
59
+ export declare const LIST_IMAGE_PX = 150;
3
60
  /**
4
- * Wrap a tool handler with standard error handling.
61
+ * Wrap a tool handler that returns only text.
5
62
  * Returns { content, isError: true } on failure.
6
63
  */
7
64
  export declare function withErrorHandling(fn: () => Promise<string>): Promise<{
8
- content: {
9
- type: 'text';
10
- text: string;
11
- }[];
65
+ content: TextBlock[];
12
66
  isError?: boolean;
13
67
  }>;
68
+ /**
69
+ * Wrap a tool handler that returns a rich response (text + images + resource_links + structuredContent).
70
+ * Returns a well-formed error ToolResult on failure.
71
+ *
72
+ * Callers should construct content arrays via the builders above and filter nulls:
73
+ * return {
74
+ * content: [text(summary), ...blocks.filter(Boolean)],
75
+ * structuredContent: data,
76
+ * };
77
+ */
78
+ export declare function withRichResponse<S = unknown>(fn: () => Promise<ToolResult<S>>): Promise<ToolResult<S>>;
14
79
  /** Format a date string as "Jan 15, 2025" */
15
80
  export declare function formatDate(iso: string | null | undefined): string;
16
81
  /** Format a date string as relative time like "2h ago" */
17
82
  export declare function timeAgo(iso: string): string;
18
83
  /** Format a number with commas */
19
84
  export declare function fmt(n: number | null | undefined): string;
85
+ /**
86
+ * Format a Letterboxd-style 0-5 star user rating. The Rewind API stores
87
+ * these in the 0-5 half-star range (e.g. 4.5 = four and a half stars).
88
+ * Renders as "4.5★" or "4★" -- never "4/10", which is a different scale.
89
+ */
90
+ export declare function formatStars(r: number | null | undefined): string;
20
91
  /** Common date filter params reused across tools. */
21
92
  export declare const dateFilterParams: {
22
93
  date: z.ZodOptional<z.ZodString>;
23
94
  from: z.ZodOptional<z.ZodString>;
24
95
  to: z.ZodOptional<z.ZodString>;
25
96
  };
97
+ /** Shared optional input for tools that return image content blocks. */
98
+ export declare const includeImagesParam: {
99
+ include_images: z.ZodDefault<z.ZodBoolean>;
100
+ };
26
101
  /** Standard annotations for all Rewind tools (read-only, open-world). */
27
102
  export declare const READ_ONLY_ANNOTATIONS: {
28
103
  readOnlyHint: true;
29
104
  destructiveHint: false;
105
+ idempotentHint: true;
30
106
  openWorldHint: true;
31
107
  };
32
108
  export type { RewindClient };
@@ -1,21 +1,136 @@
1
1
  import { z } from 'zod';
2
+ // ─── Content block builders ──────────────────────────────────────────
3
+ /** Build a text content block. */
4
+ export function text(value) {
5
+ return { type: 'text', text: value };
6
+ }
7
+ /**
8
+ * Build a resource_link content block.
9
+ * Returns null if the URI is missing/empty so callers can `.filter(Boolean)`.
10
+ */
11
+ export function resourceLink(uri, name, opts) {
12
+ if (!uri)
13
+ return null;
14
+ const block = { type: 'resource_link', uri, name };
15
+ if (opts?.mimeType)
16
+ block.mimeType = opts.mimeType;
17
+ if (opts?.description)
18
+ block.description = opts.description;
19
+ return block;
20
+ }
21
+ /**
22
+ * Build an image content block from an entity's image attachment by fetching
23
+ * the public CDN URL directly. Returns null on any failure or missing URL --
24
+ * never throws. Image blocks are best-effort; we always want to return
25
+ * text/data even if the image fetch breaks.
26
+ *
27
+ * Pass `targetPx` to request a smaller transform -- overrides the `width` and
28
+ * `height` query params on the CDN URL. Useful for list tools that must stay
29
+ * under the client's per-response size budget. Omit for full-size (typically
30
+ * 300x300) detail-tool posters.
31
+ */
32
+ export async function imageBlock(client, image, targetPx) {
33
+ if (!image)
34
+ return null;
35
+ let url = image.cdn_url ?? image.url ?? null;
36
+ if (!url)
37
+ return null;
38
+ if (targetPx)
39
+ url = resizeCdnUrl(url, targetPx);
40
+ try {
41
+ const { bytes, mimeType } = await client.getBinaryFromUrl(url);
42
+ return {
43
+ type: 'image',
44
+ data: bytesToBase64(bytes),
45
+ mimeType,
46
+ };
47
+ }
48
+ catch {
49
+ return null;
50
+ }
51
+ }
52
+ /**
53
+ * Rewrite a Rewind CDN URL to use the Cloudflare Images transform path
54
+ * (`/cdn-cgi/image/<opts>/<asset>`) at the requested pixel size. The raw
55
+ * `cdn_url` field returned by the API points at the original (full-res) R2
56
+ * object and does not honor width/height query params. Transform URLs do.
57
+ *
58
+ * Input: https://cdn.rewind.rest/watching/movies/707/original.jpg?width=300&height=300&...&v=1
59
+ * Output: https://cdn.rewind.rest/cdn-cgi/image/width=150,height=150,fit=cover,format=auto,quality=85/watching/movies/707/original.jpg?v=1
60
+ *
61
+ * Returns the input unchanged if it is not a valid URL or is already a
62
+ * transform URL.
63
+ */
64
+ function resizeCdnUrl(url, targetPx) {
65
+ try {
66
+ const u = new URL(url);
67
+ if (u.pathname.startsWith('/cdn-cgi/image/'))
68
+ return url;
69
+ const opts = `width=${targetPx},height=${targetPx},fit=cover,format=auto,quality=85`;
70
+ const version = u.searchParams.get('v');
71
+ const versionSuffix = version ? `?v=${version}` : '';
72
+ return `${u.origin}/cdn-cgi/image/${opts}${u.pathname}${versionSuffix}`;
73
+ }
74
+ catch {
75
+ return url;
76
+ }
77
+ }
78
+ /** Target pixel size for list-tool image blocks. Keeps responses under ~250KB. */
79
+ export const LIST_IMAGE_PX = 150;
2
80
  /**
3
- * Wrap a tool handler with standard error handling.
81
+ * Convert bytes to base64. Uses globalThis.Buffer when available (Node / Workers),
82
+ * falls back to a manual encoding that works in any JS runtime.
83
+ */
84
+ function bytesToBase64(bytes) {
85
+ const g = globalThis;
86
+ if (g.Buffer)
87
+ return g.Buffer.from(bytes).toString('base64');
88
+ let binary = '';
89
+ for (let i = 0; i < bytes.length; i++)
90
+ binary += String.fromCharCode(bytes[i]);
91
+ return btoa(binary);
92
+ }
93
+ // ─── Response wrappers ───────────────────────────────────────────────
94
+ /**
95
+ * Wrap a tool handler that returns only text.
4
96
  * Returns { content, isError: true } on failure.
5
97
  */
6
98
  export async function withErrorHandling(fn) {
7
99
  try {
8
- const text = await fn();
9
- return { content: [{ type: 'text', text }] };
100
+ const textValue = await fn();
101
+ return { content: [text(textValue)] };
102
+ }
103
+ catch (error) {
104
+ const message = error instanceof Error ? error.message : String(error);
105
+ return {
106
+ content: [text(`Error: ${message}`)],
107
+ isError: true,
108
+ };
109
+ }
110
+ }
111
+ /**
112
+ * Wrap a tool handler that returns a rich response (text + images + resource_links + structuredContent).
113
+ * Returns a well-formed error ToolResult on failure.
114
+ *
115
+ * Callers should construct content arrays via the builders above and filter nulls:
116
+ * return {
117
+ * content: [text(summary), ...blocks.filter(Boolean)],
118
+ * structuredContent: data,
119
+ * };
120
+ */
121
+ export async function withRichResponse(fn) {
122
+ try {
123
+ return await fn();
10
124
  }
11
125
  catch (error) {
12
126
  const message = error instanceof Error ? error.message : String(error);
13
127
  return {
14
- content: [{ type: 'text', text: `Error: ${message}` }],
128
+ content: [text(`Error: ${message}`)],
15
129
  isError: true,
16
130
  };
17
131
  }
18
132
  }
133
+ // ─── Existing utilities (unchanged) ──────────────────────────────────
19
134
  /** Format a date string as "Jan 15, 2025" */
20
135
  export function formatDate(iso) {
21
136
  if (!iso)
@@ -48,6 +163,17 @@ export function fmt(n) {
48
163
  return '0';
49
164
  return n.toLocaleString('en-US');
50
165
  }
166
+ /**
167
+ * Format a Letterboxd-style 0-5 star user rating. The Rewind API stores
168
+ * these in the 0-5 half-star range (e.g. 4.5 = four and a half stars).
169
+ * Renders as "4.5★" or "4★" -- never "4/10", which is a different scale.
170
+ */
171
+ export function formatStars(r) {
172
+ if (r === null || r === undefined)
173
+ return '';
174
+ const display = r % 1 === 0 ? r.toFixed(0) : r.toFixed(1);
175
+ return `${display}★`;
176
+ }
51
177
  /** Common date filter params reused across tools. */
52
178
  export const dateFilterParams = {
53
179
  date: z
@@ -60,10 +186,18 @@ export const dateFilterParams = {
60
186
  .describe('Optional: start of date range (ISO 8601)'),
61
187
  to: z.string().optional().describe('Optional: end of date range (ISO 8601)'),
62
188
  };
189
+ /** Shared optional input for tools that return image content blocks. */
190
+ export const includeImagesParam = {
191
+ include_images: z
192
+ .boolean()
193
+ .default(true)
194
+ .describe('Include artwork/poster image content blocks in the response. Default true. Set false to keep responses small.'),
195
+ };
63
196
  /** Standard annotations for all Rewind tools (read-only, open-world). */
64
197
  export const READ_ONLY_ANNOTATIONS = {
65
198
  readOnlyHint: true,
66
199
  destructiveHint: false,
200
+ idempotentHint: true,
67
201
  openWorldHint: true,
68
202
  };
69
203
  //# sourceMappingURL=helpers.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"helpers.js","sourceRoot":"","sources":["../../src/tools/helpers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,EAAyB;IAEzB,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,MAAM,EAAE,EAAE,CAAC;QACxB,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC;IAC/C,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACvE,OAAO;YACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,OAAO,EAAE,EAAE,CAAC;YACtD,OAAO,EAAE,IAAI;SACd,CAAC;IACJ,CAAC;AACH,CAAC;AAED,6CAA6C;AAC7C,MAAM,UAAU,UAAU,CAAC,GAA8B;IACvD,IAAI,CAAC,GAAG;QAAE,OAAO,SAAS,CAAC;IAC3B,OAAO,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,kBAAkB,CAAC,OAAO,EAAE;QAC/C,KAAK,EAAE,OAAO;QACd,GAAG,EAAE,SAAS;QACd,IAAI,EAAE,SAAS;KAChB,CAAC,CAAC;AACL,CAAC;AAED,0DAA0D;AAC1D,MAAM,UAAU,OAAO,CAAC,GAAW;IACjC,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,CAAC;IAClD,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,GAAG,MAAM,CAAC,CAAC;IAC1C,IAAI,OAAO,GAAG,CAAC;QAAE,OAAO,UAAU,CAAC;IACnC,IAAI,OAAO,GAAG,EAAE;QAAE,OAAO,GAAG,OAAO,OAAO,CAAC;IAC3C,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,EAAE,CAAC,CAAC;IACvC,IAAI,KAAK,GAAG,EAAE;QAAE,OAAO,GAAG,KAAK,OAAO,CAAC;IACvC,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,EAAE,CAAC,CAAC;IACpC,IAAI,IAAI,GAAG,CAAC;QAAE,OAAO,GAAG,IAAI,OAAO,CAAC;IACpC,OAAO,UAAU,CAAC,GAAG,CAAC,CAAC;AACzB,CAAC;AAED,kCAAkC;AAClC,MAAM,UAAU,GAAG,CAAC,CAA4B;IAC9C,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,SAAS;QAAE,OAAO,GAAG,CAAC;IAC9C,OAAO,CAAC,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;AACnC,CAAC;AAED,qDAAqD;AACrD,MAAM,CAAC,MAAM,gBAAgB,GAAG;IAC9B,IAAI,EAAE,CAAC;SACJ,MAAM,EAAE;SACR,QAAQ,EAAE;SACV,QAAQ,CAAC,kDAAkD,CAAC;IAC/D,IAAI,EAAE,CAAC;SACJ,MAAM,EAAE;SACR,QAAQ,EAAE;SACV,QAAQ,CAAC,0CAA0C,CAAC;IACvD,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,wCAAwC,CAAC;CAC7E,CAAC;AAEF,yEAAyE;AACzE,MAAM,CAAC,MAAM,qBAAqB,GAAG;IACnC,YAAY,EAAE,IAAa;IAC3B,eAAe,EAAE,KAAc;IAC/B,aAAa,EAAE,IAAa;CAC7B,CAAC"}
1
+ {"version":3,"file":"helpers.js","sourceRoot":"","sources":["../../src/tools/helpers.ts"],"names":[],"mappings":"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"}