@slicemachine/manager 0.25.7-alpha.jp-figma-to-prismic.6 → 0.25.7-alpha.jp-figma-to-prismic.7

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.
@@ -1,4 +1,7 @@
1
1
  "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
4
+ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
2
5
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
6
  const t = require("io-ts");
4
7
  const prismicCustomTypesClient = require("@prismicio/custom-types-client");
@@ -36,6 +39,10 @@ function _interopNamespaceDefault(e) {
36
39
  const t__namespace = /* @__PURE__ */ _interopNamespaceDefault(t);
37
40
  const prismicCustomTypesClient__namespace = /* @__PURE__ */ _interopNamespaceDefault(prismicCustomTypesClient);
38
41
  class CustomTypesManager extends BaseManager.BaseManager {
42
+ constructor() {
43
+ super(...arguments);
44
+ __publicField(this, "inferSliceAbortControllers", /* @__PURE__ */ new Map());
45
+ }
39
46
  async readCustomTypeLibrary() {
40
47
  var _a;
41
48
  assertPluginsInitialized.assertPluginsInitialized(this.sliceMachinePluginRunner);
@@ -299,276 +306,298 @@ class CustomTypesManager extends BaseManager.BaseManager {
299
306
  }
300
307
  async inferSlice(args) {
301
308
  var _a;
302
- const { source, imageUrl } = args;
303
- const exp = await this.telemetry.getExperimentVariant("llm-proxy-access");
304
- if ((exp == null ? void 0 : exp.value) !== "on") {
305
- throw new Error("LLM proxy access is not enabled.");
306
- }
307
- const { llmProxyUrl } = index.default.object({ llmProxyUrl: index.default.string() }).parse(exp.payload);
309
+ const { source, imageUrl, requestId } = args;
308
310
  const authToken = await this.user.getAuthenticationToken();
309
311
  const repository = await this.project.getResolvedRepositoryName();
310
- if (source === "figma") {
311
- const { libraryID } = args;
312
- console.log(`inferSlice started`);
313
- const startTime = Date.now();
314
- let tmpDir;
315
- try {
316
- const config = await this.project.getSliceMachineConfig();
317
- let framework;
318
- if (config.adapter === "@slicemachine/adapter-next") {
319
- framework = { type: "nextjs", label: "Next.js (React)" };
320
- } else if (config.adapter === "@slicemachine/adapter-nuxt" || config.adapter === "@slicemachine/adapter-nuxt2") {
321
- framework = { type: "nuxt", label: "Nuxt (Vue)" };
322
- } else if (config.adapter === "@slicemachine/adapter-sveltekit") {
323
- framework = { type: "sveltekit", label: "SvelteKit (Svelte)" };
324
- }
325
- if (!framework) {
326
- throw new Error("Could not determine framework from Slice Machine config.");
327
- }
328
- let frameworkFileExtension;
329
- if (framework.type === "nextjs") {
330
- frameworkFileExtension = "tsx";
331
- } else if (framework.type === "nuxt") {
332
- frameworkFileExtension = "vue";
333
- } else if (framework.type === "sveltekit") {
334
- frameworkFileExtension = "svelte";
335
- }
336
- if (!frameworkFileExtension) {
337
- throw new Error("Could not determine framework from Slice Machine config.");
338
- }
339
- const projectRoot = await this.project.getRoot();
340
- const libraryAbsPath = path.join(projectRoot, libraryID);
341
- tmpDir = await promises.mkdtemp(path.join(os.tmpdir(), "slice-machine-infer-slice-tmp-"));
342
- const tmpImagePath = path.join(tmpDir, `${crypto.randomUUID()}.png`);
343
- const response = await fetch.default(imageUrl);
344
- if (!response.ok) {
345
- throw new Error(`Failed to download image: ${response.status} ${response.statusText}`);
312
+ let abortController;
313
+ if (requestId) {
314
+ abortController = new AbortController();
315
+ abortController.signal.addEventListener("abort", () => {
316
+ console.warn(`inferSlice (${source}) request ${requestId} was aborted`);
317
+ });
318
+ this.inferSliceAbortControllers.set(requestId, abortController);
319
+ }
320
+ console.info(`inferSlice (${source}) started${requestId ? ` for request ${requestId}` : ""}`);
321
+ const startTime = Date.now();
322
+ try {
323
+ if (source === "figma") {
324
+ const { libraryID } = args;
325
+ const exp = await this.telemetry.getExperimentVariant("llm-proxy-access");
326
+ if ((exp == null ? void 0 : exp.value) !== "on") {
327
+ throw new Error("User does not have access to the LLM proxy.");
346
328
  }
347
- await promises.writeFile(tmpImagePath, Buffer.from(await response.arrayBuffer()));
348
- const queries = claudeAgentSdk.query({
349
- prompt: `CRITICAL INSTRUCTIONS - READ FIRST:
350
- - You MUST start immediately with Step 1.1. DO NOT read, analyze, or explore any project files first.
351
- - Work step-by-step through the numbered tasks below.
352
- - DO NOT present any summary, explanation, or completion message after finishing.
353
- - DO NOT create TODO lists while performing tasks.
354
- - Keep responses minimal - only show necessary tool calls and brief progress notes.
355
-
356
- # CONTEXT
357
-
358
- The user wants to build a new Prismic Slice based on a design image they provided.
359
- Your goal is to analyze the design image and generate the JSON model data and boilerplate code for the slice following Prismic requirements.
360
-
361
- You will work under the slice library at <slice_library_path>, where all the slices are stored.
362
-
363
- # AVAILABLE RESOURCES
364
-
365
- <design_image_path>
366
- ${tmpImagePath}
367
- </design_image_path>
368
-
369
- <slice_library_path>
370
- ${libraryAbsPath}
371
- </slice_library_path>
372
-
373
- <framework>
374
- ${framework.label}
375
- </framework>
376
-
377
- # AVAILABLE TOOLS
378
-
379
- You have access to specialized Prismic MCP tools for this task:
380
-
381
- <tool name="mcp__prismic__how_to_model_slice">
382
- <description>
383
- Provides detailed guidance on creating Prismic slice models, including field types, naming conventions, and best practices.
384
- </description>
385
- <when_to_use>
386
- Call this tool in Step 2.1 to learn how to structure the slice model data for the design you analysed.
387
- </when_to_use>
388
- </tool>
389
-
390
- <tool name="mcp__prismic__how_to_code_slice">
391
- <description>
392
- Provides guidance on implementing Prismic slice components, including how to use Prismic field components, props structure, and best practices.
393
- </description>
394
- <when_to_use>
395
- Call this tool in Step 2.1 to learn how to properly structure the slice component with Prismic fields.
396
- </when_to_use>
397
- </tool>
398
-
399
- <tool name="mcp__prismic__save_slice_data">
400
- <description>
401
- Validates and saves the slice model data to model.json. This is the ONLY way to create the model file.
402
- </description>
403
- <when_to_use>
404
- Call this tool in Step 2.3 after you have built the complete slice model structure in memory.
405
- </when_to_use>
406
- </tool>
407
-
408
- # TASK REQUIREMENTS
409
-
410
- ## Step 1: Gather information from the design image
411
- 1.1. Analyse the design image at <design_image_path>.
412
- 1.2. Identify all elements in the image that should be dynamically editable (e.g., headings, paragraphs, images, links, buttons, etc.).
413
- 1.3. List the slice directories under <slice_library_path>.
414
- 1.4. Come up with a unique name for the new slice based on the content of the image and the slice directories.
415
-
416
- ## Step 2: Model the Prismic slice
417
- 2.1. Call mcp__prismic__how_to_model_slice to learn how to structure the model for this design.
418
- - Make sure the name you use for the new slice does not yet exist in the slice library at <slice_library_path>. If it does, use a different name.
419
- 2.2. Build the complete slice JSON model data in memory based on the guidance received and the information extracted from the image.
420
- 2.3. Call mcp__prismic__save_slice_data to save the model (DO NOT manually write model.json) in the slice library at <slice_library_path>.
421
-
422
- ## Step 3: Code a boilerplate slice component based on the model
423
- 3.1. Call mcp__prismic__how_to_code_slice to learn how to properly structure the slice component with Prismic fields.
424
- 3.2. Update the slice component code at <slice_library_path>/index.${frameworkFileExtension}, replacing the placeholder code with boilerplate code with the following requirements:
425
- - Must NOT be based on existing slices or components from the codebase.
426
- - Must render all the Prismic components to display the fields of the slice model created at <slice_model_path>.
427
- - Must be a valid ${framework.label} component.
428
- - Must NOT have any styling/CSS. No inlines styles or classNames. Just the skeleton component structure.
429
- - Must NOT use any other custom component or functions from the user's codebase.
430
- - Avoid creating unnecessary wrapper elements, like if they only wrap a single component (e.g., <div><PrismicRichText /></div>).
431
-
432
- ## Step 4: Present the newly created slice path
433
- 4.1. Present the path to the newly created slice in the following format: <new_slice_path>${libraryAbsPath}/MyNewSlice</new_slice_path>.
434
- - "MyNewSlice" must be the name of the directory of the newly created slice.
435
-
436
- # EXAMPLE OF CORRECT EXECUTION
437
-
438
- <example>
439
- Assistant: Step 1.1: Analysing design image...
440
- [reads <design_image_path>]
441
-
442
- Step 1.2: Identifying editable content elements...
443
- [identifies: title field, description field, buttonText field, buttonLink field, backgroundImage field]
444
-
445
- Step 1.3: Listing slice directories under <slice_library_path>...
446
- [lists slice directories: Hero, Hero2, Hero3]
447
-
448
- Step 1.4: Coming up with a unique name for the new slice...
449
- [comes up with a unique name for the new slice: Hero4]
450
-
451
- Step 2.1: Getting Prismic modeling guidance...
452
- [calls mcp__prismic__how_to_model_slice]
453
-
454
- Step 2.2: Building slice model based on guidance and the information extracted...
455
- [creates model with title field, description field, buttonText field, buttonLink field, backgroundImage field]
456
-
457
- Step 2.3: Saving slice model...
458
- [calls mcp__prismic__save_slice_data]
459
-
460
- Step 3.1: Learning Prismic slice coding requirements...
461
- [calls mcp__prismic__how_to_code_slice]
462
-
463
- Step 3.2: Coding boilerplate slice component based on the model...
464
- [updates component with Prismic field components, no styling, no other components]
465
-
466
- Step 4.1: Presenting the path to the newly created slice...
467
- [presents <new_slice_path>${path.join(libraryAbsPath, "MyNewSlice")}</new_slice_path>]
468
-
469
- # DELIVERABLES
470
- - Slice model saved to <slice_library_path>/model.json using mcp__prismic__save_slice_data
471
- - Slice component at <slice_library_path>/index.${frameworkFileExtension} updated with boilerplate code
472
- - New slice path presented in the format mentioned in Step 3.1
473
-
474
- YOU ARE NOT FINISHED UNTIL YOU HAVE THESE DELIVERABLES.
475
-
476
- ---
477
-
478
- FINAL REMINDERS:
479
- - You MUST use mcp__prismic__save_slice_data to save the model
480
- - You MUST call mcp__prismic__how_to_code_slice in Step 3.1
481
- - DO NOT ATTEMPT TO BUILD THE APPLICATION
482
- - START IMMEDIATELY WITH STEP 1.1 - NO PRELIMINARY ANALYSIS;`,
483
- options: {
484
- cwd: libraryAbsPath,
485
- stderr: (data) => console.error(data),
486
- model: "claude-haiku-4-5",
487
- permissionMode: "bypassPermissions",
488
- allowedTools: [
489
- "Bash",
490
- "Read",
491
- "FileSearch",
492
- "Grep",
493
- "Glob",
494
- "Task",
495
- "Edit",
496
- "Write",
497
- "MultiEdit",
498
- "mcp__prismic__how_to_model_slice",
499
- "mcp__prismic__how_to_code_slice",
500
- "mcp__prismic__save_slice_data"
501
- ],
502
- disallowedTools: [
503
- `Edit(**/model.json)`,
504
- `Write(**/model.json)`,
505
- "Edit(**/mocks.json)",
506
- "Write(**/mocks.json)"
507
- ],
508
- env: {
509
- ...process.env,
510
- ANTHROPIC_BASE_URL: llmProxyUrl,
511
- ANTHROPIC_CUSTOM_HEADERS: `x-prismic-token: ${authToken}
329
+ const { llmProxyUrl } = index.default.object({ llmProxyUrl: index.default.string().url() }).parse(exp.payload);
330
+ let tmpDir;
331
+ try {
332
+ const config = await this.project.getSliceMachineConfig();
333
+ let framework;
334
+ if (config.adapter === "@slicemachine/adapter-next") {
335
+ framework = { type: "nextjs", label: "Next.js (React)" };
336
+ } else if (config.adapter === "@slicemachine/adapter-nuxt" || config.adapter === "@slicemachine/adapter-nuxt2") {
337
+ framework = { type: "nuxt", label: "Nuxt (Vue)" };
338
+ } else if (config.adapter === "@slicemachine/adapter-sveltekit") {
339
+ framework = { type: "sveltekit", label: "SvelteKit (Svelte)" };
340
+ }
341
+ if (!framework) {
342
+ throw new Error("Could not determine framework from Slice Machine config.");
343
+ }
344
+ let frameworkFileExtension;
345
+ if (framework.type === "nextjs") {
346
+ frameworkFileExtension = "tsx";
347
+ } else if (framework.type === "nuxt") {
348
+ frameworkFileExtension = "vue";
349
+ } else if (framework.type === "sveltekit") {
350
+ frameworkFileExtension = "svelte";
351
+ }
352
+ if (!frameworkFileExtension) {
353
+ throw new Error("Could not determine framework from Slice Machine config.");
354
+ }
355
+ const projectRoot = await this.project.getRoot();
356
+ const libraryAbsPath = path.join(projectRoot, libraryID);
357
+ tmpDir = await promises.mkdtemp(path.join(os.tmpdir(), "slice-machine-infer-slice-tmp-"));
358
+ const tmpImagePath = path.join(tmpDir, `${crypto.randomUUID()}.png`);
359
+ const response = await fetch.default(imageUrl);
360
+ if (!response.ok) {
361
+ throw new Error(`Failed to download image: ${response.status} ${response.statusText}`);
362
+ }
363
+ await promises.writeFile(tmpImagePath, Buffer.from(await response.arrayBuffer()));
364
+ const queries = claudeAgentSdk.query({
365
+ prompt: `CRITICAL INSTRUCTIONS - READ FIRST:
366
+ - You MUST start immediately with Step 1.1. DO NOT read, analyze, or explore any project files first.
367
+ - Work step-by-step through the numbered tasks below.
368
+ - DO NOT present any summary, explanation, or completion message after finishing.
369
+ - DO NOT create TODO lists while performing tasks.
370
+ - Keep responses minimal - only show necessary tool calls and brief progress notes.
371
+
372
+ # CONTEXT
373
+
374
+ The user wants to build a new Prismic Slice based on a design image they provided.
375
+ Your goal is to analyze the design image and generate the JSON model data and boilerplate code for the slice following Prismic requirements.
376
+
377
+ You will work under the slice library at <slice_library_path>, where all the slices are stored.
378
+
379
+ # AVAILABLE RESOURCES
380
+
381
+ <design_image_path>
382
+ ${tmpImagePath}
383
+ </design_image_path>
384
+
385
+ <slice_library_path>
386
+ ${libraryAbsPath}
387
+ </slice_library_path>
388
+
389
+ <framework>
390
+ ${framework.label}
391
+ </framework>
392
+
393
+ # AVAILABLE TOOLS
394
+
395
+ You have access to specialized Prismic MCP tools for this task:
396
+
397
+ <tool name="mcp__prismic__how_to_model_slice">
398
+ <description>
399
+ Provides detailed guidance on creating Prismic slice models, including field types, naming conventions, and best practices.
400
+ </description>
401
+ <when_to_use>
402
+ Call this tool in Step 2.1 to learn how to structure the slice model data for the design you analysed.
403
+ </when_to_use>
404
+ </tool>
405
+
406
+ <tool name="mcp__prismic__how_to_code_slice">
407
+ <description>
408
+ Provides guidance on implementing Prismic slice components, including how to use Prismic field components, props structure, and best practices.
409
+ </description>
410
+ <when_to_use>
411
+ Call this tool in Step 2.1 to learn how to properly structure the slice component with Prismic fields.
412
+ </when_to_use>
413
+ </tool>
414
+
415
+ <tool name="mcp__prismic__save_slice_data">
416
+ <description>
417
+ Validates and saves the slice model data to model.json. This is the ONLY way to create the model file.
418
+ </description>
419
+ <when_to_use>
420
+ Call this tool in Step 2.3 after you have built the complete slice model structure in memory.
421
+ </when_to_use>
422
+ </tool>
423
+
424
+ # TASK REQUIREMENTS
425
+
426
+ ## Step 1: Gather information from the design image
427
+ 1.1. Analyse the design image at <design_image_path>.
428
+ 1.2. Identify all elements in the image that should be dynamically editable (e.g., headings, paragraphs, images, links, buttons, etc.).
429
+ 1.3. List the slice directories under <slice_library_path>.
430
+ 1.4. Come up with a unique name for the new slice based on the content of the image and the slice directories.
431
+
432
+ ## Step 2: Model the Prismic slice
433
+ 2.1. Call mcp__prismic__how_to_model_slice to learn how to structure the model for this design.
434
+ - Make sure the name you use for the new slice does not yet exist in the slice library at <slice_library_path>. If it does, use a different name.
435
+ 2.2. Build the complete slice JSON model data in memory based on the guidance received and the information extracted from the image.
436
+ 2.3. Call mcp__prismic__save_slice_data to save the model (DO NOT manually write model.json) in the slice library at <slice_library_path>.
437
+
438
+ ## Step 3: Code a boilerplate slice component based on the model
439
+ 3.1. Call mcp__prismic__how_to_code_slice to learn how to properly structure the slice component with Prismic fields.
440
+ 3.2. Update the slice component code at <slice_library_path>/index.${frameworkFileExtension}, replacing the placeholder code with boilerplate code with the following requirements:
441
+ - Must NOT be based on existing slices or components from the codebase.
442
+ - Must render all the Prismic components to display the fields of the slice model created at <slice_model_path>.
443
+ - Must be a valid ${framework.label} component.
444
+ - Must NOT have any styling/CSS. No inlines styles or classNames. Just the skeleton component structure.
445
+ - Must NOT use any other custom component or functions from the user's codebase.
446
+ - Avoid creating unnecessary wrapper elements, like if they only wrap a single component (e.g., <div><PrismicRichText /></div>).
447
+
448
+ ## Step 4: Present the newly created slice path
449
+ 4.1. Present the path to the newly created slice in the following format: <new_slice_path>${libraryAbsPath}/MyNewSlice</new_slice_path>.
450
+ - "MyNewSlice" must be the name of the directory of the newly created slice.
451
+
452
+ # EXAMPLE OF CORRECT EXECUTION
453
+
454
+ <example>
455
+ Assistant: Step 1.1: Analysing design image...
456
+ [reads <design_image_path>]
457
+
458
+ Step 1.2: Identifying editable content elements...
459
+ [identifies: title field, description field, buttonText field, buttonLink field, backgroundImage field]
460
+
461
+ Step 1.3: Listing slice directories under <slice_library_path>...
462
+ [lists slice directories: Hero, Hero2, Hero3]
463
+
464
+ Step 1.4: Coming up with a unique name for the new slice...
465
+ [comes up with a unique name for the new slice: Hero4]
466
+
467
+ Step 2.1: Getting Prismic modeling guidance...
468
+ [calls mcp__prismic__how_to_model_slice]
469
+
470
+ Step 2.2: Building slice model based on guidance and the information extracted...
471
+ [creates model with title field, description field, buttonText field, buttonLink field, backgroundImage field]
472
+
473
+ Step 2.3: Saving slice model...
474
+ [calls mcp__prismic__save_slice_data]
475
+
476
+ Step 3.1: Learning Prismic slice coding requirements...
477
+ [calls mcp__prismic__how_to_code_slice]
478
+
479
+ Step 3.2: Coding boilerplate slice component based on the model...
480
+ [updates component with Prismic field components, no styling, no other components]
481
+
482
+ Step 4.1: Presenting the path to the newly created slice...
483
+ [presents <new_slice_path>${path.join(libraryAbsPath, "MyNewSlice")}</new_slice_path>]
484
+
485
+ # DELIVERABLES
486
+ - Slice model saved to <slice_library_path>/model.json using mcp__prismic__save_slice_data
487
+ - Slice component at <slice_library_path>/index.${frameworkFileExtension} updated with boilerplate code
488
+ - New slice path presented in the format mentioned in Step 3.1
489
+
490
+ YOU ARE NOT FINISHED UNTIL YOU HAVE THESE DELIVERABLES.
491
+
492
+ ---
493
+
494
+ FINAL REMINDERS:
495
+ - You MUST use mcp__prismic__save_slice_data to save the model
496
+ - You MUST call mcp__prismic__how_to_code_slice in Step 3.1
497
+ - DO NOT ATTEMPT TO BUILD THE APPLICATION
498
+ - START IMMEDIATELY WITH STEP 1.1 - NO PRELIMINARY ANALYSIS;`,
499
+ options: {
500
+ cwd: libraryAbsPath,
501
+ stderr: (data) => console.error("inferSlice error:" + data),
502
+ model: "claude-haiku-4-5",
503
+ permissionMode: "bypassPermissions",
504
+ allowedTools: [
505
+ "Bash",
506
+ "Read",
507
+ "FileSearch",
508
+ "Grep",
509
+ "Glob",
510
+ "Task",
511
+ "Edit",
512
+ "Write",
513
+ "MultiEdit",
514
+ "mcp__prismic__how_to_model_slice",
515
+ "mcp__prismic__how_to_code_slice",
516
+ "mcp__prismic__save_slice_data"
517
+ ],
518
+ disallowedTools: [
519
+ `Edit(**/model.json)`,
520
+ `Write(**/model.json)`,
521
+ "Edit(**/mocks.json)",
522
+ "Write(**/mocks.json)"
523
+ ],
524
+ env: {
525
+ ...process.env,
526
+ ANTHROPIC_BASE_URL: llmProxyUrl,
527
+ ANTHROPIC_CUSTOM_HEADERS: `x-prismic-token: ${authToken}
512
528
  x-prismic-repository: ${repository}
513
529
  `
514
- },
515
- mcpServers: {
516
- prismic: {
517
- type: "stdio",
518
- command: "npx",
519
- args: ["-y", "@prismicio/mcp-server@0.0.20-alpha.6"]
520
- }
530
+ },
531
+ mcpServers: {
532
+ prismic: {
533
+ type: "stdio",
534
+ command: "npx",
535
+ args: ["-y", "@prismicio/mcp-server@0.0.20-alpha.6"]
536
+ }
537
+ },
538
+ ...abortController && { abortController }
539
+ }
540
+ });
541
+ let newSliceAbsPath;
542
+ for await (const query of queries) {
543
+ switch (query.type) {
544
+ case "result":
545
+ if (query.subtype === "success") {
546
+ newSliceAbsPath = (_a = query.result.match(/<new_slice_path>(.*)<\/new_slice_path>/s)) == null ? void 0 : _a[1];
547
+ }
548
+ break;
521
549
  }
522
550
  }
523
- });
524
- let newSliceAbsPath;
525
- for await (const query of queries) {
526
- switch (query.type) {
527
- case "result":
528
- if (query.subtype === "success") {
529
- newSliceAbsPath = (_a = query.result.match(/<new_slice_path>(.*)<\/new_slice_path>/s)) == null ? void 0 : _a[1];
530
- }
531
- break;
551
+ if (!newSliceAbsPath) {
552
+ throw new Error("Could not find path for the newly created slice.");
553
+ }
554
+ const model = await promises.readFile(path.join(newSliceAbsPath, "model.json"), "utf8");
555
+ if (!model) {
556
+ throw new Error("Could not find model for the newly created slice.");
557
+ }
558
+ await promises.rename(tmpImagePath, path.join(newSliceAbsPath, "screenshot-default.png"));
559
+ return InferSliceResponse.parse({ slice: JSON.parse(model) });
560
+ } finally {
561
+ if (tmpDir && require$$0.existsSync(tmpDir)) {
562
+ await promises.rm(tmpDir, { recursive: true });
532
563
  }
533
564
  }
534
- if (!newSliceAbsPath) {
535
- throw new Error("Could not find path for the newly created slice.");
536
- }
537
- const model = await promises.readFile(path.join(newSliceAbsPath, "model.json"), "utf8");
538
- if (!model) {
539
- throw new Error("Could not find model for the newly created slice.");
540
- }
541
- await promises.rename(tmpImagePath, path.join(newSliceAbsPath, "screenshot-default.png"));
542
- await promises.rm(tmpDir, { recursive: true });
543
- const elapsedTimeSeconds = (Date.now() - startTime) / 1e3;
544
- console.log(`inferSlice took ${elapsedTimeSeconds}s`);
545
- return InferSliceResponse.parse({ slice: JSON.parse(model) });
546
- } catch (error) {
547
- if (tmpDir && require$$0.existsSync(tmpDir)) {
548
- await promises.rm(tmpDir, { recursive: true });
565
+ } else {
566
+ const searchParams = new URLSearchParams({ repository });
567
+ const url = new URL("./slices/infer", API_ENDPOINTS.API_ENDPOINTS.CustomTypeService);
568
+ url.search = searchParams.toString();
569
+ const response = await fetch.default(url.toString(), {
570
+ method: "POST",
571
+ headers: { Authorization: `Bearer ${authToken}` },
572
+ body: JSON.stringify({ imageUrl }),
573
+ ...abortController && { signal: abortController.signal }
574
+ });
575
+ if (!response.ok) {
576
+ throw new Error(`Failed to infer slice: ${response.statusText}`);
549
577
  }
550
- throw error;
578
+ const json = await response.json();
579
+ return InferSliceResponse.parse(json);
551
580
  }
552
- } else {
553
- const headers = {
554
- Authorization: `Bearer ${authToken}`
555
- };
556
- const searchParams = new URLSearchParams({
557
- repository
558
- });
559
- const url = new URL("./slices/infer", API_ENDPOINTS.API_ENDPOINTS.CustomTypeService);
560
- url.search = searchParams.toString();
561
- const response = await fetch.default(url.toString(), {
562
- method: "POST",
563
- headers,
564
- body: JSON.stringify({ imageUrl })
565
- });
566
- if (!response.ok) {
567
- throw new Error(`Failed to infer slice: ${response.statusText}`);
581
+ } catch (error) {
582
+ console.error(`inferSlice (${source}) failed${requestId ? ` for request ${requestId}` : ""}`, error);
583
+ throw error;
584
+ } finally {
585
+ if (requestId) {
586
+ this.inferSliceAbortControllers.delete(requestId);
568
587
  }
569
- const json = await response.json();
570
- return InferSliceResponse.parse(json);
588
+ const elapsedTimeSeconds = (Date.now() - startTime) / 1e3;
589
+ console.info(`inferSlice took ${elapsedTimeSeconds}s${requestId ? ` for request ${requestId}` : ""}`);
590
+ }
591
+ }
592
+ async cancelInferSlice(args) {
593
+ const { requestId } = args;
594
+ const abortController = this.inferSliceAbortControllers.get(requestId);
595
+ if (abortController) {
596
+ abortController.abort();
597
+ this.inferSliceAbortControllers.delete(requestId);
598
+ return { cancelled: true };
571
599
  }
600
+ return { cancelled: false };
572
601
  }
573
602
  }
574
603
  const InferSliceResponse = index.default.object({