@buzzni/saycode-cli 0.9.1 → 0.9.3

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.
@@ -48,6 +48,18 @@ function contributionList(value, path2, allowedKeys, parse) {
48
48
  return parse(entry, entryPath);
49
49
  });
50
50
  }
51
+ function parseExtensionFileViewers(value, apiVersion) {
52
+ if (apiVersion < 4) fail$5("manifest.contributes.fileViewers", "requires Extension API version 4");
53
+ return contributionList(value, "manifest.contributes.fileViewers", ["id", "title", "extensions", "panelId"], (entry, path2) => {
54
+ if (!Array.isArray(entry.extensions) || !entry.extensions.length || entry.extensions.length > 30 || entry.extensions.some((extension) => typeof extension !== "string" || !/^[a-z0-9]{1,12}$/.test(extension)) || new Set(entry.extensions).size !== entry.extensions.length) fail$5(`${path2}.extensions`, "expected unique lowercase file extensions");
55
+ return { id: id(entry.id, `${path2}.id`), title: string(entry.title, `${path2}.title`), extensions: entry.extensions, panelId: id(entry.panelId, `${path2}.panelId`) };
56
+ });
57
+ }
58
+ function assertExtensionFileViewers(extensionId2, viewers, panels, permissions) {
59
+ for (const viewer of viewers) {
60
+ if (!permissions.includes("filePreviews.read") || !viewer.id.startsWith(`${extensionId2}.`) || !viewer.panelId.startsWith(`${extensionId2}.`) || !panels.some((panel) => panel.id === viewer.panelId)) fail$5("manifest.contributes.fileViewers", "requires filePreviews.read and an owned panel");
61
+ }
62
+ }
51
63
  function parseMachineCommands(value, extensionId2, apiVersion) {
52
64
  if (apiVersion < 3) fail$5("manifest.machineCommands", "requires Extension API version 3");
53
65
  const root = record$1(value, "manifest.machineCommands");
@@ -240,6 +252,23 @@ const EXTENSION_PANEL_SURFACE_SIZES = ["compact", "standard", "wide"];
240
252
  function isExtensionPanelSurfaceSize(value) {
241
253
  return EXTENSION_PANEL_SURFACE_SIZES.some((size) => size === value);
242
254
  }
255
+ function parseExtensionProjectTools(value, apiVersion) {
256
+ if (apiVersion < 3) fail$5("manifest.contributes.projectTools", "requires Extension API version 3");
257
+ return contributionList(value, "manifest.contributes.projectTools", ["id", "title", "command"], (entry, path2) => ({
258
+ id: id(entry.id, `${path2}.id`),
259
+ title: string(entry.title, `${path2}.title`),
260
+ command: id(entry.command, `${path2}.command`)
261
+ }));
262
+ }
263
+ function assertExtensionProjectToolTargets(extensionId2, tools, commands) {
264
+ for (const [index, tool] of tools.entries()) {
265
+ const path2 = `manifest.contributes.projectTools[${index}]`;
266
+ if (!tool.id.startsWith(`${extensionId2}.`)) fail$5(`${path2}.id`, "expected an id declared by the same extension");
267
+ const command = tool.command.startsWith(`${extensionId2}.`) ? commands.find((candidate) => candidate.id === tool.command) : void 0;
268
+ if (!command) fail$5(`${path2}.command`, "expected a command declared by the same extension");
269
+ if (!command.panelId) fail$5(`${path2}.command`, "expected a command that opens a panel");
270
+ }
271
+ }
243
272
  const EXTENSION_ARTIFACT_ACTION_OPERATIONS = ["publishPublic"];
244
273
  const EXTENSION_ARTIFACT_SOURCE_TYPES = ["project-file", "personal-chat-file"];
245
274
  const ID_PATTERN$1 = /^[a-z0-9](?:[a-z0-9.-]*[a-z0-9])?$/;
@@ -484,6 +513,7 @@ const EXTENSION_PERMISSIONS = [
484
513
  "browserViewer.install",
485
514
  "browserViewer.installChrome",
486
515
  "artifacts.publishPublic",
516
+ "filePreviews.read",
487
517
  // One permission per channel wire method (`src/domain/channelProtocol.ts`), deliberately not a
488
518
  // single adapter grant. Receiving and acking messages is transport work; reading a session,
489
519
  // driving it, or approving a tool call once are three larger and separately-refusable
@@ -498,10 +528,10 @@ const EXTENSION_PERMISSIONS = [
498
528
  "sessions.control",
499
529
  "sessions.approveOnce"
500
530
  ];
501
- const SAYCODE_EXTENSION_API_VERSION = 3;
531
+ const SAYCODE_EXTENSION_API_VERSION = 4;
502
532
  const SAYCODE_EXTENSION_MINIMUM_API_VERSION = 2;
503
533
  const MAX_EXTENSION_API_WINDOW_WIDTH = 2;
504
- const SAYCODE_EXTENSION_ENGINE_VERSION = "1.1.0";
534
+ const SAYCODE_EXTENSION_ENGINE_VERSION = "1.2.0";
505
535
  const SAYCODE_CHANNEL_API_VERSION = CHANNEL_API_VERSION;
506
536
  const SAYCODE_CHANNEL_MINIMUM_API_VERSION = CHANNEL_MINIMUM_API_VERSION;
507
537
  class UnsupportedChannelApiVersionError extends Error {
@@ -524,7 +554,7 @@ const SEMVER_PATTERN = /^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?$
524
554
  const ENGINE_RANGE_PATTERN = /^(?:\^|~|>=|<=|>|<)?\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/;
525
555
  const ENTRYPOINT_PATTERN = /\.(?:cjs|mjs|js)$/;
526
556
  const LOCALE_PATTERN = /^[a-z]{2,3}(?:-[A-Z]{2})?$/;
527
- const CONTRIBUTION_KEYS = /* @__PURE__ */ new Set(["commands", "settings", "panels", "projectTemplates", "machineActions", "artifactActions", "channels"]);
557
+ const CONTRIBUTION_KEYS = /* @__PURE__ */ new Set(["commands", "settings", "panels", "projectTemplates", "machineActions", "projectTools", "artifactActions", "channels", "fileViewers"]);
528
558
  const V2_PERMISSIONS = /* @__PURE__ */ new Set([
529
559
  "browserViewer.open",
530
560
  "browserViewer.install",
@@ -585,7 +615,7 @@ function engineSupports(range, version) {
585
615
  function parseApiVersion(value, options) {
586
616
  const current = options.supportedApiVersion;
587
617
  const floor = options.minimumSupportedApiVersion ?? current;
588
- if (floor > current || current - floor + 1 > MAX_EXTENSION_API_WINDOW_WIDTH) {
618
+ if (floor > current || current - floor + 1 > (current === 4 && floor === 2 ? 3 : MAX_EXTENSION_API_WINDOW_WIDTH)) {
589
619
  fail$5(
590
620
  "manifest.apiVersion",
591
621
  `invalid Desktop API support window [${floor}, ${current}]`
@@ -626,6 +656,7 @@ function parseContributions(value, apiVersion, channelApiVersion) {
626
656
  fail$5("manifest.contributes.artifactActions", "requires Extension API version 3");
627
657
  }
628
658
  const result = {};
659
+ if (parsed.fileViewers !== void 0) result.fileViewers = parseExtensionFileViewers(parsed.fileViewers, apiVersion);
629
660
  if (parsed.commands !== void 0) {
630
661
  result.commands = contributionList(
631
662
  parsed.commands,
@@ -731,6 +762,7 @@ function parseContributions(value, apiVersion, channelApiVersion) {
731
762
  }
732
763
  );
733
764
  }
765
+ if (parsed.projectTools !== void 0) result.projectTools = parseExtensionProjectTools(parsed.projectTools, apiVersion);
734
766
  if (parsed.artifactActions !== void 0) {
735
767
  result.artifactActions = parseExtensionArtifactActions(parsed.artifactActions);
736
768
  }
@@ -743,6 +775,7 @@ function parseContributions(value, apiVersion, channelApiVersion) {
743
775
  ...result.panels ?? [],
744
776
  ...result.projectTemplates ?? [],
745
777
  ...result.machineActions ?? [],
778
+ ...result.projectTools ?? [],
746
779
  ...result.artifactActions ?? [],
747
780
  ...result.channels ?? []
748
781
  ].map((entry) => entry.id);
@@ -775,6 +808,7 @@ function parseExtensionManifest(value, options) {
775
808
  fail$5("manifest.permissions", `unknown permission ${parsed}`);
776
809
  }
777
810
  const typed = parsed;
811
+ if (typed === "filePreviews.read" && apiVersion < 4) fail$5("manifest.permissions", "filePreviews.read requires Extension API version 4");
778
812
  if (apiVersion < 2 && V2_PERMISSIONS.has(typed)) {
779
813
  fail$5(`manifest.permissions[${index}]`, "requires Extension API version 2");
780
814
  }
@@ -846,6 +880,8 @@ function parseExtensionManifest(value, options) {
846
880
  );
847
881
  }
848
882
  }
883
+ assertExtensionFileViewers(parsedId, contributes.fileViewers ?? [], contributes.panels ?? [], permissions);
884
+ assertExtensionProjectToolTargets(parsedId, contributes.projectTools ?? [], contributes.commands ?? []);
849
885
  return {
850
886
  id: parsedId,
851
887
  version,