@yuiseki/gyazocli 0.5.1 → 0.5.2

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/dist/api.js CHANGED
@@ -119,7 +119,11 @@ async function listCollectionImages(collectionId, page = 1, per = 100) {
119
119
  */
120
120
  async function fetchImageRendition(imageId, width, format = 'webp') {
121
121
  const extension = format === 'jpeg' ? 'jpg' : 'webp';
122
- const url = `${imageOrigin()}/thumb/${width}_w/${imageId}.${extension}`;
122
+ // The `-jpg` before the extension is a source-type marker, and it has to be
123
+ // there: without it the route answers 404 for any capture whose derivative
124
+ // is not already stored, which is most of them. Its value is ignored, and
125
+ // the extension alone decides what comes back, so a constant will do.
126
+ const url = `${imageOrigin()}/thumb/${width}_w/${imageId}-jpg.${extension}`;
123
127
  const response = await axios_1.default.get(url, { responseType: 'arraybuffer' });
124
128
  const data = Buffer.from(response.data);
125
129
  const contentType = String(response.headers['content-type'] || '').split(';')[0].trim();
package/dist/index.js CHANGED
@@ -26,7 +26,7 @@ program
26
26
  .name('gyazo')
27
27
  .description('Gyazo Memory CLI for AI Secretary')
28
28
  .option('--mcp-server', 'run as a Model Context Protocol server over stdio')
29
- .version('0.5.1');
29
+ .version('0.5.2');
30
30
  (0, config_1.registerConfigCommand)(program);
31
31
  (0, list_1.registerListCommand)(program);
32
32
  (0, get_1.registerGetCommand)(program);
package/dist/mcp.js CHANGED
@@ -193,16 +193,35 @@ const INCLUDE_LOCATION = zod_1.z
193
193
  .boolean()
194
194
  .default(true)
195
195
  .describe('Fill in the location, which the listing and search endpoints leave out. Costs one ' +
196
- 'extra lookup per capture the local cache does not already hold. Set false when the ' +
197
- 'coordinates do not matter');
196
+ 'extra lookup per capture the local cache does not already hold, so a page of 40 ' +
197
+ 'uncached captures adds a few seconds; the next look at the same captures is free. ' +
198
+ 'Set false when the coordinates do not matter');
199
+ /**
200
+ * Fill in the locations, and say so when the per-call limit stopped it part
201
+ * way: past that point a capture without a location is indistinguishable from
202
+ * one that has none, which is exactly the sort of silence worth breaking.
203
+ */
198
204
  async function withLocations(images, includeLocation) {
199
- return includeLocation ? (0, memory_1.enrichImageLocations)(images) : images;
205
+ if (!includeLocation)
206
+ return { images };
207
+ const result = await (0, memory_1.enrichImageLocations)(images);
208
+ if (result.skipped === 0)
209
+ return { images: result.images };
210
+ return {
211
+ images: result.images,
212
+ note: `The location was filled in for ${result.considered} captures; ${result.skipped} were ` +
213
+ 'left as the listing returned them, so their missing location means "not looked up" ' +
214
+ 'rather than "no location". Ask for fewer at a time to cover them all.',
215
+ };
200
216
  }
201
- function asMetadataListResult(images) {
217
+ function asMetadataListResult(images, note) {
202
218
  if (!images || images.length === 0) {
203
219
  return NO_IMAGES;
204
220
  }
205
- return asJsonResult(images.map(toMetadata));
221
+ const json = asJsonResult(images.map(toMetadata));
222
+ if (!note)
223
+ return json;
224
+ return { content: [...json.content, { type: 'text', text: note }] };
206
225
  }
207
226
  /**
208
227
  * A date argument, refused by throwing. The CLI reports and exits here, which
@@ -249,7 +268,8 @@ function createMcpServer() {
249
268
  if (!images || images.length === 0) {
250
269
  return NO_IMAGES;
251
270
  }
252
- return asMetadataListResult(await withLocations(images, includeLocation));
271
+ const withLocation = await withLocations(images, includeLocation);
272
+ return asMetadataListResult(withLocation.images, withLocation.note);
253
273
  }));
254
274
  server.registerTool('gyazo_image', {
255
275
  title: 'Describe one Gyazo capture',
@@ -365,7 +385,8 @@ function createMcpServer() {
365
385
  hour: hour || undefined,
366
386
  alias,
367
387
  });
368
- return asMetadataListResult(await withLocations(images, args.include_location));
388
+ const withLocation = await withLocations(images, args.include_location);
389
+ return asMetadataListResult(withLocation.images, withLocation.note);
369
390
  }));
370
391
  server.registerTool('gyazo_summary', {
371
392
  title: 'Summarise a stretch of Gyazo captures',
@@ -535,7 +556,8 @@ function createMcpServer() {
535
556
  'recent pages of captures. It may be older than that, or belong to another ' +
536
557
  'account. Ask for a window in minutes instead, or raise max_pages.');
537
558
  }
538
- return asMetadataListResult(await withLocations(result.images, args.include_location));
559
+ const withLocation = await withLocations(result.images, args.include_location);
560
+ return asMetadataListResult(withLocation.images, withLocation.note);
539
561
  }));
540
562
  server.registerTool('gyazo_collections', {
541
563
  title: 'Find a Gyazo collection by name',
@@ -416,26 +416,23 @@ async function listCapturesSince(options) {
416
416
  }
417
417
  return { images: collected.slice(0, limit), pagesWalked };
418
418
  }
419
- /**
420
- * Fill in what the lean endpoints leave out.
421
- *
422
- * The listing and the search endpoints return an image without its
423
- * coordinates or its address, whatever the capture actually carries; only the
424
- * detail endpoint has them. So a caller that needs a location has to ask again
425
- * per image, which is what this does: the cache first, the API for the rest,
426
- * a few at a time, writing what it fetches back to the cache so the next look
427
- * is free.
428
- */
429
419
  async function enrichImageLocations(images, options = {}) {
430
420
  const useCache = options.useCache !== false;
431
421
  const limit = options.limit ?? 40;
432
- const concurrency = Math.max(1, options.concurrency ?? 5);
422
+ const concurrency = Math.max(1, options.concurrency ?? 10);
433
423
  const enriched = [...images];
434
424
  const pending = [];
435
- for (let index = 0; index < enriched.length && pending.length < limit; index++) {
425
+ let considered = 0;
426
+ let skipped = 0;
427
+ for (let index = 0; index < enriched.length; index++) {
436
428
  const image = enriched[index];
437
429
  if (image?.metadata?.exif_normalized || image?.metadata?.exif_address)
438
430
  continue;
431
+ if (considered >= limit) {
432
+ skipped++;
433
+ continue;
434
+ }
435
+ considered++;
439
436
  if (useCache) {
440
437
  const cached = (0, storage_1.loadImageCache)(image?.image_id);
441
438
  if (cached) {
@@ -459,5 +456,5 @@ async function enrichImageLocations(images, options = {}) {
459
456
  }
460
457
  }));
461
458
  }
462
- return enriched;
459
+ return { images: enriched, considered, skipped };
463
460
  }
@@ -13,7 +13,7 @@ Adopt and document the existing top-level command structure.
13
13
 
14
14
  ### 1. Program Metadata
15
15
  - Binary name: `gyazo`
16
- - Version: `0.5.1`
16
+ - Version: `0.5.2`
17
17
  - Description: `Gyazo Memory CLI for AI Secretary`
18
18
 
19
19
  ### 2. Commands
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yuiseki/gyazocli",
3
- "version": "0.5.1",
3
+ "version": "0.5.2",
4
4
  "description": "Gyazo Memory CLI for AI Secretary",
5
5
  "repository": {
6
6
  "type": "git",