@buun_group/plotwork-mcp 0.1.0-beta.9 → 0.2.0-beta.1

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/plotwork-mcp.mjs CHANGED
@@ -65,7 +65,7 @@ var init_icon_art_folder = __esm({
65
65
  var package_default;
66
66
  var init_package = __esm({
67
67
  "package.json"() {
68
- package_default = { version: "0.1.0-beta.9" };
68
+ package_default = { version: "0.2.0-beta.1" };
69
69
  }
70
70
  });
71
71
 
@@ -609,7 +609,7 @@ var init_auto_icons = __esm({
609
609
  webhook: "lucide:webhook",
610
610
  webhooks: "lucide:webhook"
611
611
  };
612
- BRAND_SUFFIXES = /* @__PURE__ */ new Set(["api", "sdk", "service", "server", "cache", "db", "database", "cluster", "instance"]);
612
+ BRAND_SUFFIXES = /* @__PURE__ */ new Set(["api", "sdk", "service", "server", "cache", "db", "database", "cluster", "instance", "cmdb", "itsm", "tenant"]);
613
613
  ROLE_ICON_MAX_WORDS = 3;
614
614
  }
615
615
  });
@@ -722,12 +722,26 @@ var init_view_links = __esm({
722
722
  };
723
723
  CLI_RELEASE = {
724
724
  packageName: "@buun_group/plotwork",
725
- version: "0.1.0-beta.10",
725
+ version: "0.1.0",
726
726
  onNpm: true
727
727
  };
728
728
  }
729
729
  });
730
730
 
731
+ // ../../packages/diagrams/src/constants/action-release.ts
732
+ var ACTION_REPOSITORY, ACTION_RELEASE, PINNED_ACTION_LINE;
733
+ var init_action_release = __esm({
734
+ "../../packages/diagrams/src/constants/action-release.ts"() {
735
+ "use strict";
736
+ ACTION_REPOSITORY = "plotwork-official/plotwork-action";
737
+ ACTION_RELEASE = {
738
+ version: "1.0.0",
739
+ sha: "78d7acaf4b673e10187eb9174a60a3da6949ee8a"
740
+ };
741
+ PINNED_ACTION_LINE = `uses: ${ACTION_REPOSITORY}@${ACTION_RELEASE.sha} # v${ACTION_RELEASE.version}`;
742
+ }
743
+ });
744
+
731
745
  // ../../packages/diagrams/src/constants/mcp-release.ts
732
746
  function mcpPackagePin(release = MCP_RELEASE) {
733
747
  return `${release.packageName}@${release.version}`;
@@ -741,7 +755,7 @@ var init_mcp_release = __esm({
741
755
  "use strict";
742
756
  MCP_RELEASE = {
743
757
  packageName: "@buun_group/plotwork-mcp",
744
- version: "0.1.0-beta.8"
758
+ version: "0.1.0"
745
759
  };
746
760
  }
747
761
  });
@@ -787,6 +801,55 @@ var init_lint_limits = __esm({
787
801
  }
788
802
  });
789
803
 
804
+ // ../../packages/diagrams/src/constants/secret-scan.ts
805
+ function hostPatternProblem(pattern3) {
806
+ if (pattern3.length === 0 || pattern3.length > SECRET_SCAN_LIMITS.maxHostPatternLength) return `A hostname pattern is 1 to ${SECRET_SCAN_LIMITS.maxHostPatternLength} characters.`;
807
+ if (!HOST_PATTERN.test(pattern3)) return "A hostname pattern is a DNS name in lower case, such as corp.example or *.corp.example, with * only as its first label.";
808
+ return null;
809
+ }
810
+ var SECRET_SCAN_LIMITS, HOST_PATTERN, SECRET_KIND_NAMES;
811
+ var init_secret_scan = __esm({
812
+ "../../packages/diagrams/src/constants/secret-scan.ts"() {
813
+ "use strict";
814
+ SECRET_SCAN_LIMITS = {
815
+ /** A generic assigned value shorter than this is not reported: too short to be a key, and most short values are words. */
816
+ minAssignedLength: 10,
817
+ /** The Shannon entropy, in bits a character, a generic assigned value must reach. Ten different characters reach 3.32. */
818
+ minAssignedEntropy: 3.2,
819
+ /** How many characters of a finding a warning shows before the mask; a value shorter than four times this shows a quarter of itself. */
820
+ shownCharacters: 4,
821
+ /** What follows the shown characters, whatever the value's length, so the mask says nothing about it. */
822
+ mask: "********",
823
+ /** The most internal hostname patterns an organisation may give. */
824
+ maxHostPatterns: 20,
825
+ /** The longest internal hostname pattern, the length of a DNS name. */
826
+ maxHostPatternLength: 253,
827
+ /** A run of this many ascending characters (`123456`, `abcdef`) marks a made-up example value. */
828
+ ascendingRun: 6
829
+ };
830
+ HOST_PATTERN = /^(?:\*|[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?)(?:\.[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?)+$/;
831
+ SECRET_KIND_NAMES = {
832
+ "aws-access-key": "an AWS access key id",
833
+ "aws-secret-key": "an AWS secret access key",
834
+ "gcp-api-key": "a Google Cloud API key",
835
+ "gcp-service-account": "a Google Cloud service account key",
836
+ "azure-storage-key": "an Azure storage account key",
837
+ "azure-sas-token": "an Azure shared access signature",
838
+ "github-token": "a GitHub token",
839
+ "slack-token": "a Slack token",
840
+ "slack-webhook": "a Slack webhook address",
841
+ "stripe-key": "a Stripe secret key",
842
+ jwt: "a JSON Web Token",
843
+ "private-key": "a private key",
844
+ "assigned-secret": "a password or secret value",
845
+ "connection-string": "a connection string with a password",
846
+ "plotwork-key": "a Plotwork API key",
847
+ "private-ip": "a private IP address",
848
+ "internal-host": "an internal hostname"
849
+ };
850
+ }
851
+ });
852
+
790
853
  // ../../packages/diagrams/src/constants/style-rules.ts
791
854
  var STYLE_RULES, STYLE_RULE_LEVELS, SETTINGS_FILE;
792
855
  var init_style_rules = __esm({
@@ -3294,6 +3357,9 @@ var init_brand_aliases = __esm({
3294
3357
  // Business, payments, and collaboration
3295
3358
  "simple:googledrive": ["gdrive"],
3296
3359
  "simple:confluence": ["atlassian confluence"],
3360
+ // Jira Service Management is part of Jira and has no mark of its own in the bundled sets.
3361
+ "simple:jira": ["jira service management", "jira service desk", "jsm", "atlassian jira"],
3362
+ "simple:sap": ["sap erp", "sap s4hana"],
3297
3363
  // Analytics
3298
3364
  "simple:googleanalytics": ["ga4"],
3299
3365
  "simple:plausibleanalytics": ["plausible"],
@@ -3319,7 +3385,9 @@ var init_brand_aliases = __esm({
3319
3385
  // Security
3320
3386
  "simple:1password": ["one password"],
3321
3387
  "simple:sonarqubeserver": ["sonarqube"],
3388
+ "simple:okta": ["okta sso", "okta workforce identity"],
3322
3389
  // Developer tools, frameworks, and languages
3390
+ "simple:github": ["github app", "github apps", "github enterprise"],
3323
3391
  "simple:rollupdotjs": ["rollup"],
3324
3392
  "simple:alpinedotjs": ["alpine js", "alpinejs"],
3325
3393
  "simple:reactquery": ["tanstack query"],
@@ -3340,6 +3408,21 @@ var init_brand_aliases = __esm({
3340
3408
  }
3341
3409
  });
3342
3410
 
3411
+ // ../../packages/diagrams/src/constants/brand-stand-ins.ts
3412
+ var BRAND_STAND_INS, BRAND_STAND_IN_NAMES;
3413
+ var init_brand_stand_ins = __esm({
3414
+ "../../packages/diagrams/src/constants/brand-stand-ins.ts"() {
3415
+ "use strict";
3416
+ BRAND_STAND_INS = [
3417
+ { slug: "servicenow", title: "ServiceNow", glyph: "lucide:ticket", aliases: ["service now", "snow", "cmdb", "servicenow cmdb", "servicenow itsm", "now platform"] },
3418
+ { slug: "workday", title: "Workday", glyph: "lucide:id-card", aliases: ["workday hcm"] },
3419
+ { slug: "zscaler", title: "Zscaler", glyph: "lucide:shield-check", aliases: ["zscaler internet access", "zscaler private access"] },
3420
+ { slug: "crowdstrike", title: "CrowdStrike", glyph: "lucide:shield-alert", aliases: ["crowdstrike falcon", "crowd strike"] }
3421
+ ];
3422
+ BRAND_STAND_IN_NAMES = Object.fromEntries(BRAND_STAND_INS.map((brand) => [`simple:${brand.slug}`, brand.glyph]));
3423
+ }
3424
+ });
3425
+
3343
3426
  // ../../packages/diagrams/src/constants/icon-name-aliases.ts
3344
3427
  function aliasWords(alias) {
3345
3428
  return alias.slice(alias.indexOf(":") + 1).replace(/-/g, " ");
@@ -3468,6 +3551,10 @@ function withNameAliases() {
3468
3551
  const words2 = merged[ref] ??= [];
3469
3552
  if (!words2.includes(aliasWords(alias))) words2.push(aliasWords(alias));
3470
3553
  }
3554
+ for (const brand of BRAND_STAND_INS) {
3555
+ const words2 = merged[brand.glyph] ??= [];
3556
+ for (const word2 of [brand.slug, brand.title.toLowerCase(), ...brand.aliases]) if (!words2.includes(word2)) words2.push(word2);
3557
+ }
3471
3558
  return merged;
3472
3559
  }
3473
3560
  var WRITTEN_ALIASES, ICON_ALIASES;
@@ -3475,6 +3562,7 @@ var init_icon_aliases = __esm({
3475
3562
  "../../packages/diagrams/src/constants/icon-aliases.ts"() {
3476
3563
  "use strict";
3477
3564
  init_brand_aliases();
3565
+ init_brand_stand_ins();
3478
3566
  init_icon_name_aliases();
3479
3567
  WRITTEN_ALIASES = {
3480
3568
  ...BRAND_ALIASES,
@@ -3497,7 +3585,11 @@ var init_icon_aliases = __esm({
3497
3585
  "simple:elasticsearch": ["elk", "elastic search"],
3498
3586
  "lucide:mail": ["email", "e mail"],
3499
3587
  "lucide:database": ["db", "datastore"],
3500
- "lucide:key-round": ["api key"]
3588
+ "lucide:key-round": ["api key"],
3589
+ // Microsoft's own names for the Azure pack's security and device products, which the pack files under shorter titles.
3590
+ "azure:defender-for-cloud": ["microsoft defender", "defender", "microsoft defender for cloud"],
3591
+ "azure:sentinel": ["microsoft sentinel"],
3592
+ "azure:intune": ["microsoft intune"]
3501
3593
  };
3502
3594
  ICON_ALIASES = withNameAliases();
3503
3595
  }
@@ -3633,7 +3725,7 @@ var init_label_vocabulary = __esm({
3633
3725
  patches: { icon: "lucide:replace", role: null }
3634
3726
  };
3635
3727
  LABEL_VERB_PHRASES = {
3636
- reads: ["reads", "read", "reading", "reads from", "read from", "queries", "query", "querying", "looks up", "look up", "selects", "select from", "loads from", "fetches from"],
3728
+ reads: ["reads", "read", "reading", "reads from", "read from", "queries", "query", "querying", "looks up", "look up", "selects", "select from", "loads from", "fetches from", "read by", "queried by", "looked up by", "loaded from", "fetched from"],
3637
3729
  writes: [
3638
3730
  "writes",
3639
3731
  "write",
@@ -3657,10 +3749,22 @@ var init_label_vocabulary = __esm({
3657
3749
  "uploads",
3658
3750
  "upload",
3659
3751
  "uploads to",
3660
- "upload to"
3752
+ "upload to",
3753
+ "written to",
3754
+ "written by",
3755
+ "written into",
3756
+ "inserted into",
3757
+ "updated by",
3758
+ "saved to",
3759
+ "saved in",
3760
+ "persisted to",
3761
+ "persisted in",
3762
+ "deleted from",
3763
+ "uploaded to",
3764
+ "uploaded by"
3661
3765
  ],
3662
- stores: ["stores", "store", "stores in", "store in", "caches", "caches in", "reads and writes", "reads writes", "read write", "read and write"],
3663
- mounts: ["mounts", "mount"],
3766
+ stores: ["stores", "store", "stores in", "store in", "caches", "caches in", "reads and writes", "reads writes", "read write", "read and write", "stored in", "stored by", "cached in", "cached by"],
3767
+ mounts: ["mounts", "mount", "mounted by", "mounted at", "mounted in", "mounted on"],
3664
3768
  sends: [
3665
3769
  "sends",
3666
3770
  "send",
@@ -3679,15 +3783,27 @@ var init_label_vocabulary = __esm({
3679
3783
  "pushes to",
3680
3784
  "notifies",
3681
3785
  "notify",
3682
- "fires"
3786
+ "fires",
3787
+ "sent to",
3788
+ "sent by",
3789
+ "published to",
3790
+ "published by",
3791
+ "emitted to",
3792
+ "emitted by",
3793
+ "produced to",
3794
+ "enqueued to",
3795
+ "enqueued in",
3796
+ "enqueued on",
3797
+ "pushed to",
3798
+ "notified by"
3683
3799
  ],
3684
- receives: ["receives", "receive", "consumes", "consume", "consumes from", "subscribes", "subscribes to", "subscribe to", "listens to", "listens on", "polls", "dequeues"],
3685
- calls: ["calls", "call", "invokes", "invoke", "requests", "request", "fetches", "fetch", "queries api", "http", "https", "grpc", "rest", "graphql"],
3686
- routes: ["routes", "routes to", "route to", "forwards", "forwards to", "forward to", "proxies", "proxies to", "redirects to", "load balances"],
3687
- "depends-on": ["depends on", "depend on", "requires", "needs"],
3688
- provides: ["provides", "exposes", "serves"],
3689
- triggers: ["triggers", "trigger", "starts", "kicks off", "schedules", "wakes"],
3690
- deploys: ["deploys", "deploy", "deploys to", "deploy to", "releases to", "ships to", "promotes to", "rolls out", "rolls out to"],
3800
+ receives: ["receives", "receive", "consumes", "consume", "consumes from", "subscribes", "subscribes to", "subscribe to", "listens to", "listens on", "polls", "dequeues", "received by", "received from", "consumed by", "consumed from", "subscribed to", "polled by", "polled from", "dequeued by"],
3801
+ calls: ["calls", "call", "invokes", "invoke", "requests", "request", "fetches", "fetch", "queries api", "http", "https", "grpc", "rest", "graphql", "called by", "invoked by", "requested by", "requested from", "fetched by"],
3802
+ routes: ["routes", "routes to", "route to", "forwards", "forwards to", "forward to", "proxies", "proxies to", "redirects to", "load balances", "routed to", "routed by", "routed through", "forwarded to", "forwarded by", "proxied to", "proxied by", "proxied through", "redirected to", "load balanced by"],
3803
+ "depends-on": ["depends on", "depend on", "requires", "needs", "required by", "needed by", "depended on by"],
3804
+ provides: ["provides", "exposes", "serves", "provided by", "exposed by", "served by", "served from"],
3805
+ triggers: ["triggers", "trigger", "starts", "kicks off", "schedules", "wakes", "triggered by", "started by", "kicked off by", "scheduled by", "woken by"],
3806
+ deploys: ["deploys", "deploy", "deploys to", "deploy to", "releases to", "ships to", "promotes to", "rolls out", "rolls out to", "deployed to", "deployed by", "deployed on", "released to", "shipped to", "promoted to", "rolled out to", "rolled out by"],
3691
3807
  grants: [
3692
3808
  "authenticates",
3693
3809
  "authenticate",
@@ -3715,7 +3831,16 @@ var init_label_vocabulary = __esm({
3715
3831
  "logs out",
3716
3832
  "log out",
3717
3833
  "signs out",
3718
- "sign out"
3834
+ "sign out",
3835
+ "authenticated by",
3836
+ "authenticated with",
3837
+ "authenticated against",
3838
+ "authorized by",
3839
+ "authorised by",
3840
+ "granted by",
3841
+ "granted to",
3842
+ "assumed by",
3843
+ "issued by"
3719
3844
  ],
3720
3845
  secret: ["reads secret", "reads secrets", "read secret", "read secrets", "read credentials", "fetches secret", "fetches secrets", "reads credentials", "gets secret", "gets secrets"],
3721
3846
  reports: [
@@ -3738,9 +3863,12 @@ var init_label_vocabulary = __esm({
3738
3863
  "exports metrics",
3739
3864
  "exports traces",
3740
3865
  "emits metrics",
3741
- "emits logs"
3866
+ "emits logs",
3867
+ "reported to",
3868
+ "reported by",
3869
+ "logged to"
3742
3870
  ],
3743
- pulls: ["pulls image", "pulls images", "pulls images from", "pulls image from"]
3871
+ pulls: ["pulls image", "pulls images", "pulls images from", "pulls image from", "pulled from"]
3744
3872
  };
3745
3873
  LABEL_VERB_MAX_WORDS = 5;
3746
3874
  NOT_VERB_PHRASES = [
@@ -3830,9 +3958,11 @@ var init_constants = __esm({
3830
3958
  init_editing();
3831
3959
  init_diagram_links();
3832
3960
  init_view_links();
3961
+ init_action_release();
3833
3962
  init_mcp_release();
3834
3963
  init_layout_limits();
3835
3964
  init_lint_limits();
3965
+ init_secret_scan();
3836
3966
  init_style_rules();
3837
3967
  init_generate();
3838
3968
  init_workflow_limits();
@@ -3840,6 +3970,7 @@ var init_constants = __esm({
3840
3970
  init_vendor_icons();
3841
3971
  init_icon_catalog();
3842
3972
  init_brand_aliases();
3973
+ init_brand_stand_ins();
3843
3974
  init_icon_aliases();
3844
3975
  init_icon_name_aliases();
3845
3976
  init_icon_concepts();
@@ -3891,6 +4022,185 @@ var init_ids = __esm({
3891
4022
  }
3892
4023
  });
3893
4024
 
4025
+ // ../../packages/diagrams/src/secrets/placeholders.ts
4026
+ function hasAscendingRun(value) {
4027
+ let run3 = 1;
4028
+ for (let index2 = 1; index2 < value.length; index2 += 1) {
4029
+ run3 = value.charCodeAt(index2) === value.charCodeAt(index2 - 1) + 1 ? run3 + 1 : 1;
4030
+ if (run3 >= SECRET_SCAN_LIMITS.ascendingRun) return true;
4031
+ }
4032
+ return false;
4033
+ }
4034
+ function distinctCharacters(value) {
4035
+ return new Set(value).size;
4036
+ }
4037
+ function isPlaceholder(value) {
4038
+ if (PUBLISHED_EXAMPLES.has(value)) return true;
4039
+ const lower = value.toLowerCase();
4040
+ if (PLACEHOLDER_WORDS.some((word2) => lower.includes(word2))) return true;
4041
+ if (REFERENCE_MARKS.some((mark) => value.includes(mark))) return true;
4042
+ if (value.startsWith("$") || value.startsWith("@") || value.startsWith(":")) return true;
4043
+ if (distinctCharacters(value) <= Math.max(3, Math.floor(value.length / 8))) return true;
4044
+ return hasAscendingRun(lower);
4045
+ }
4046
+ function entropyOf(value) {
4047
+ const counts = /* @__PURE__ */ new Map();
4048
+ for (const char of value) counts.set(char, (counts.get(char) ?? 0) + 1);
4049
+ let bits = 0;
4050
+ for (const count3 of counts.values()) {
4051
+ const share = count3 / value.length;
4052
+ bits -= share * Math.log2(share);
4053
+ }
4054
+ return bits;
4055
+ }
4056
+ var PLACEHOLDER_WORDS, REFERENCE_MARKS, PUBLISHED_EXAMPLES;
4057
+ var init_placeholders = __esm({
4058
+ "../../packages/diagrams/src/secrets/placeholders.ts"() {
4059
+ "use strict";
4060
+ init_constants();
4061
+ PLACEHOLDER_WORDS = [
4062
+ "example",
4063
+ "sample",
4064
+ "placeholder",
4065
+ "dummy",
4066
+ "fake",
4067
+ "redacted",
4068
+ "changeme",
4069
+ "change_me",
4070
+ "change-me",
4071
+ "replace",
4072
+ "insert",
4073
+ "your_",
4074
+ "your-",
4075
+ "yourkey",
4076
+ "yourtoken",
4077
+ "yoursecret",
4078
+ "mysecret",
4079
+ "secret_here",
4080
+ "key_here",
4081
+ "token_here",
4082
+ "todo",
4083
+ "notreal",
4084
+ "not_real"
4085
+ ];
4086
+ REFERENCE_MARKS = ["${", "$(", "{{", "<", ">", "%", "***", "...", "\u2026", "[", "]"];
4087
+ PUBLISHED_EXAMPLES = /* @__PURE__ */ new Set(["SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c"]);
4088
+ }
4089
+ });
4090
+
4091
+ // ../../packages/diagrams/src/secrets/detectors.ts
4092
+ function realAfter(prefixLength) {
4093
+ return (value) => !isPlaceholder(value.slice(prefixLength));
4094
+ }
4095
+ function isJwtHeader(segment) {
4096
+ try {
4097
+ const base643 = segment.replace(/-/g, "+").replace(/_/g, "/");
4098
+ const decoded = atob(base643 + "=".repeat((4 - base643.length % 4) % 4));
4099
+ const header = JSON.parse(decoded);
4100
+ return typeof header === "object" && header !== null && "alg" in header;
4101
+ } catch {
4102
+ return false;
4103
+ }
4104
+ }
4105
+ function isRealJwt(value) {
4106
+ const [header = "", , signature = ""] = value.split(".");
4107
+ return isJwtHeader(header) && !isPlaceholder(signature);
4108
+ }
4109
+ function isRealSas(value, line3) {
4110
+ if (!/[?&]sv=\d{4}-\d{2}-\d{2}/.test(line3)) return false;
4111
+ try {
4112
+ return !isPlaceholder(decodeURIComponent(value));
4113
+ } catch {
4114
+ return false;
4115
+ }
4116
+ }
4117
+ function isRealPassword(value) {
4118
+ return !STAND_IN_PASSWORDS.has(value.toLowerCase()) && !isPlaceholder(value);
4119
+ }
4120
+ function isRandomAssigned(value) {
4121
+ if (value.length < SECRET_SCAN_LIMITS.minAssignedLength) return false;
4122
+ if (!/[A-Za-z]/.test(value) || !/\d/.test(value)) return false;
4123
+ if (value.includes("://")) return false;
4124
+ return entropyOf(value) >= SECRET_SCAN_LIMITS.minAssignedEntropy && !isPlaceholder(value);
4125
+ }
4126
+ function isAddress(value) {
4127
+ return value.split(".").every((part) => Number(part) <= 255);
4128
+ }
4129
+ function internalHostDetector(patterns) {
4130
+ const usable = patterns.filter((pattern3) => hostPatternProblem(pattern3) === null).slice(0, SECRET_SCAN_LIMITS.maxHostPatterns);
4131
+ if (usable.length === 0) return null;
4132
+ const parts = usable.map((pattern3) => pattern3.split(".").map((label) => label === "*" ? "[a-z0-9-]{1,63}(?:\\.[a-z0-9-]{1,63}){0,8}" : label.replace(/-/g, "\\-")).join("\\."));
4133
+ return { kind: "internal-host", pattern: new RegExp(`()(?<![A-Za-z0-9.-])((?:${parts.join("|")}))(?![A-Za-z0-9-]|\\.[A-Za-z0-9])`, "gi") };
4134
+ }
4135
+ var STAND_IN_PASSWORDS, DETECTORS, PRIVATE_IP_DETECTOR;
4136
+ var init_detectors = __esm({
4137
+ "../../packages/diagrams/src/secrets/detectors.ts"() {
4138
+ "use strict";
4139
+ init_constants();
4140
+ init_placeholders();
4141
+ STAND_IN_PASSWORDS = /* @__PURE__ */ new Set(["password", "passwd", "pass", "pwd", "secret", "user", "username", "root", "admin"]);
4142
+ DETECTORS = [
4143
+ { kind: "plotwork-key", pattern: /()\b(pw_[0-9a-f]{64})(?![0-9a-z])/g },
4144
+ { kind: "aws-access-key", pattern: /()\b((?:AKIA|ASIA|ABIA|ACCA)[A-Z0-9]{16})(?![A-Z0-9])/g, accept: realAfter(4) },
4145
+ { kind: "aws-secret-key", pattern: /(\baws_?secret_?(?:access_?)?key\\?["']?\s{0,4}[:=]\s{0,4}\\?["']?)([A-Za-z0-9/+]{40})(?![A-Za-z0-9/+])/gi, accept: realAfter(0) },
4146
+ { kind: "gcp-api-key", pattern: /()\b(AIza[0-9A-Za-z_-]{35})(?![0-9A-Za-z_-])/g, accept: realAfter(4) },
4147
+ { kind: "gcp-service-account", pattern: /(\\?"private_key_id\\?"\s{0,4}:\s{0,4}\\?")([0-9a-f]{40})(?![0-9a-f])/g, accept: realAfter(0) },
4148
+ { kind: "azure-storage-key", pattern: /(\b(?:AccountKey|SharedAccessKey)=)([A-Za-z0-9+/]{40,120}={0,2})/g, accept: realAfter(0) },
4149
+ { kind: "azure-sas-token", pattern: /([?&]sig=)([A-Za-z0-9%+/]{30,200})/g, accept: isRealSas },
4150
+ { kind: "github-token", pattern: /()\b(gh[pousr]_[A-Za-z0-9]{36}|github_pat_[A-Za-z0-9]{22}_[A-Za-z0-9]{59})(?![A-Za-z0-9_])/g, accept: (value) => realAfter(value.startsWith("github_pat_") ? 11 : 4)(value) },
4151
+ { kind: "slack-token", pattern: /()\b(xox[abposr]-[0-9A-Za-z-]{10,250}|xapp-\d-[0-9A-Za-z-]{10,250})/g, accept: realAfter(5) },
4152
+ { kind: "slack-webhook", pattern: /()(https:\/\/hooks\.slack\.com\/(?:services|workflows|triggers)\/[A-Za-z0-9_/-]{20,200})/g, accept: realAfter(30) },
4153
+ { kind: "stripe-key", pattern: /()\b((?:sk|rk)_live_[0-9A-Za-z]{20,250}|whsec_[0-9A-Za-z]{24,250})(?![0-9A-Za-z])/g, accept: (value) => realAfter(value.indexOf("_", 3) + 1)(value) },
4154
+ { kind: "jwt", pattern: /()\b(eyJ[A-Za-z0-9_-]{8,2000}\.eyJ[A-Za-z0-9_-]{8,4000}\.[A-Za-z0-9_-]{16,1000})(?![A-Za-z0-9_-])/g, accept: isRealJwt },
4155
+ { kind: "private-key", pattern: /()(-----BEGIN (?:RSA |EC |DSA |OPENSSH |ENCRYPTED |PGP )?PRIVATE KEY(?: BLOCK)?-----)/g },
4156
+ {
4157
+ kind: "connection-string",
4158
+ pattern: /(\b[a-zA-Z][a-zA-Z0-9+.-]{1,30}:\/\/[^\s:/@"'<>]{1,100}:)([^\s@/"'<>]{1,200})(?=@[^\s"'@])/g,
4159
+ accept: isRealPassword
4160
+ },
4161
+ {
4162
+ kind: "assigned-secret",
4163
+ pattern: /((?<![A-Za-z0-9_.-])[A-Za-z0-9_.-]{0,40}(?:password|passwd|pwd|pass|secret(?:[_-]?key)?|client[_-]?secret|token|api[_-]?key|apikey|access[_-]?key|private[_-]?key|auth[_-]?key)\b\\?["']?\s{0,4}[:=]\s{0,4}\\?["']?)([^\s"'\\,;&]{1,500})/gi,
4164
+ accept: isRandomAssigned
4165
+ }
4166
+ ];
4167
+ PRIVATE_IP_DETECTOR = {
4168
+ kind: "private-ip",
4169
+ pattern: /()(?<![0-9.])((?:10\.\d{1,3}|172\.(?:1[6-9]|2\d|3[01])|192\.168)\.\d{1,3}\.\d{1,3})(?![0-9]|\.\d)/g,
4170
+ accept: isAddress
4171
+ };
4172
+ }
4173
+ });
4174
+
4175
+ // ../../packages/diagrams/src/secrets/find-spans.ts
4176
+ function secretSpans(text3, detectors = DETECTORS) {
4177
+ const found = [];
4178
+ for (const detector of detectors) {
4179
+ const pattern3 = new RegExp(detector.pattern.source, detector.pattern.flags);
4180
+ for (let match = pattern3.exec(text3); match !== null; match = pattern3.exec(text3)) {
4181
+ const value = match[2] ?? "";
4182
+ if (value === "") continue;
4183
+ const start2 = match.index + (match[1] ?? "").length;
4184
+ const end = start2 + value.length;
4185
+ if (found.some((other) => start2 < other.end && other.start < end)) continue;
4186
+ if (detector.accept !== void 0 && !detector.accept(value, text3)) continue;
4187
+ found.push({ kind: detector.kind, start: start2, end, value });
4188
+ }
4189
+ }
4190
+ return found.sort((a, b) => a.start - b.start);
4191
+ }
4192
+ function maskSecretSpans(text3) {
4193
+ let out = text3;
4194
+ for (const span of secretSpans(text3)) out = out.slice(0, span.start) + "*".repeat(span.end - span.start) + out.slice(span.end);
4195
+ return out;
4196
+ }
4197
+ var init_find_spans = __esm({
4198
+ "../../packages/diagrams/src/secrets/find-spans.ts"() {
4199
+ "use strict";
4200
+ init_detectors();
4201
+ }
4202
+ });
4203
+
3894
4204
  // ../../packages/diagrams/src/core/diagnostics.ts
3895
4205
  function severityOfCode(code) {
3896
4206
  return code.startsWith("W") || code.startsWith("M2") || code.startsWith("I2") || code.startsWith("S2") ? "warning" : "error";
@@ -3903,7 +4213,8 @@ function warningAt(code, message2, position, hint2 = null) {
3903
4213
  }
3904
4214
  function formatDiagnostic(diagnostic, source) {
3905
4215
  const lines = source.split("\n");
3906
- const sourceLine = lines[diagnostic.line - 1] ?? "";
4216
+ const shown = maskSecretSpans(lines[diagnostic.line - 1] ?? "");
4217
+ const sourceLine = diagnostic.code.startsWith("W7") ? shown.slice(0, diagnostic.column - 1) + "*".repeat(diagnostic.length) + shown.slice(diagnostic.column - 1 + diagnostic.length) : shown;
3907
4218
  const gutter = String(diagnostic.line).padStart(4, " ");
3908
4219
  const caret = `${" ".repeat(diagnostic.column - 1)}${"^".repeat(Math.max(1, diagnostic.length))}`;
3909
4220
  const parts = [
@@ -3918,6 +4229,7 @@ var DIAGNOSTIC_CODES, STYLE_HINT_CODES;
3918
4229
  var init_diagnostics = __esm({
3919
4230
  "../../packages/diagrams/src/core/diagnostics.ts"() {
3920
4231
  "use strict";
4232
+ init_find_spans();
3921
4233
  DIAGNOSTIC_CODES = {
3922
4234
  syntax: "E100",
3923
4235
  unterminatedString: "E101",
@@ -3925,7 +4237,6 @@ var init_diagnostics = __esm({
3925
4237
  missingHeader: "E111",
3926
4238
  unknownNodeType: "E120",
3927
4239
  unknownTone: "E121",
3928
- unknownIcon: "E122",
3929
4240
  unknownDirection: "E123",
3930
4241
  unknownGroupType: "E124",
3931
4242
  unknownProvider: "E125",
@@ -3948,9 +4259,32 @@ var init_diagnostics = __esm({
3948
4259
  suggestGroupType: "W205",
3949
4260
  overlayCovers: "W206",
3950
4261
  iconArtMissing: "W207",
4262
+ // An icon= name that is not bundled. A warning since 2026-10-20 (it was error E122): the item draws its default icon, so a missing
4263
+ // brand never stops a drawing, and the hint names the closest icons.
4264
+ unknownIcon: "W208",
3951
4265
  // Style suggestions. W5xx says how a valid diagram would look more finished; like W204 and W205 it is a suggestion, not a problem
3952
4266
  // (`isStyleHint`), so a check that fails on warnings passes it.
3953
4267
  suggestLineRole: "W500",
4268
+ // Hosted service. W6xx comes from the hosted service, never from the engine: W600 says an organisation's "Agents publish every
4269
+ // diagram they draw" could not keep this drawing (the library is at its limit, the diagram of that title is locked), which never
4270
+ // stops the drawing. W601 says the organisation's "Publishing needs approval" held the diagram until an approver decides: it is
4271
+ // stored, and only its publisher and the approvers can see it.
4272
+ notPublished: "W600",
4273
+ heldForApproval: "W601",
4274
+ // Secrets (src/secrets). W7xx says the source holds something that looks like a credential. It is a warning everywhere, so a
4275
+ // drawing is never stopped, and not a style hint, so a check that fails on warnings fails on it. An organisation may refuse a
4276
+ // publish that has one. W709 and W710 run only when asked for, because private addresses and internal names are often meant.
4277
+ secretCloudKey: "W700",
4278
+ secretSourceToken: "W701",
4279
+ secretChatToken: "W702",
4280
+ secretPaymentKey: "W703",
4281
+ secretJwt: "W704",
4282
+ secretPrivateKey: "W705",
4283
+ secretAssigned: "W706",
4284
+ secretConnectionString: "W707",
4285
+ secretPlotworkKey: "W708",
4286
+ secretPrivateIp: "W709",
4287
+ secretInternalHost: "W710",
3954
4288
  // Mermaid import. M1xx stops a conversion; M2xx reports something dropped or changed and never stops it.
3955
4289
  // They point into the Mermaid source that was submitted, not into the Plotwork source.
3956
4290
  mermaidNotDiagram: "M100",
@@ -4750,6 +5084,7 @@ var init_simple_catalog_generated = __esm({
4750
5084
  "xero": { viewBox: "0 0 24 24", brandHex: "13B5EA" },
4751
5085
  "hubspot": { viewBox: "0 0 24 24", brandHex: "FF7A59" },
4752
5086
  "zendesk": { viewBox: "0 0 24 24", brandHex: "03363D" },
5087
+ "sap": { viewBox: "0 0 24 24", brandHex: "0FAAFF" },
4753
5088
  "intercom": { viewBox: "0 0 24 24", brandHex: "6AFDEF" },
4754
5089
  "atlassian": { viewBox: "0 0 24 24", brandHex: "0052CC" },
4755
5090
  "confluence": { viewBox: "0 0 24 24", brandHex: "172B4D" },
@@ -4935,6 +5270,7 @@ var init_simple_catalog_generated = __esm({
4935
5270
  "springboot": '<path d="m23.693 10.7058-4.73-8.1844c-.4094-.7106-1.4166-1.2942-2.2402-1.2942H7.2725c-.819 0-1.8308.5836-2.2402 1.2942L.307 10.7058c-.4095.7106-.4095 1.873 0 2.5837l4.7252 8.189c.4094.7107 1.4166 1.2943 2.2402 1.2943h9.455c.819 0 1.826-.5836 2.2402-1.2942l4.7252-8.189c.4095-.7107.4095-1.8732 0-2.5838zM10.9763 5.7547c0-.5365.4377-.9742.9742-.9742s.9742.4377.9742.9742v5.8217c0 .5366-.4377.9742-.9742.9742s-.9742-.4376-.9742-.9742zm.9742 12.4294c-3.6427 0-6.6077-2.965-6.6077-6.6077.0047-2.0896.993-4.0521 2.6685-5.304a.8657.8657 0 0 1 1.2142.1788.8657.8657 0 0 1-.1788 1.2143c-2.1602 1.6048-2.612 4.6592-1.0072 6.8194 1.6049 2.1603 4.6593 2.612 6.8195 1.0072 1.2378-.9177 1.9673-2.372 1.9673-3.9157a4.8972 4.8972 0 0 0-1.9861-3.925c-.386-.2824-.466-.8284-.1836-1.2143.2824-.386.8283-.466 1.2143-.1835 1.6895 1.2471 2.6826 3.2238 2.6873 5.3228 0 3.6474-2.965 6.6077-6.6077 6.6077z"/>',
4936
5271
  "php": '<path d="M7.01 10.207h-.944l-.515 2.648h.838c.556 0 .97-.105 1.242-.314.272-.21.455-.559.55-1.049.092-.47.05-.802-.124-.995-.175-.193-.523-.29-1.047-.29zM12 5.688C5.373 5.688 0 8.514 0 12s5.373 6.313 12 6.313S24 15.486 24 12c0-3.486-5.373-6.312-12-6.312zm-3.26 7.451c-.261.25-.575.438-.917.551-.336.108-.765.164-1.285.164H5.357l-.327 1.681H3.652l1.23-6.326h2.65c.797 0 1.378.209 1.744.628.366.418.476 1.002.33 1.752a2.836 2.836 0 0 1-.305.847c-.143.255-.33.49-.561.703zm4.024.715l.543-2.799c.063-.318.039-.536-.068-.651-.107-.116-.336-.174-.687-.174H11.46l-.704 3.625H9.388l1.23-6.327h1.367l-.327 1.682h1.218c.767 0 1.295.134 1.586.401s.378.7.263 1.299l-.572 2.944h-1.389zm7.597-2.265a2.782 2.782 0 0 1-.305.847c-.143.255-.33.49-.561.703a2.44 2.44 0 0 1-.917.551c-.336.108-.765.164-1.286.164h-1.18l-.327 1.682h-1.378l1.23-6.326h2.649c.797 0 1.378.209 1.744.628.366.417.477 1.001.331 1.751zM17.766 10.207h-.943l-.516 2.648h.838c.557 0 .971-.105 1.242-.314.272-.21.455-.559.551-1.049.092-.47.049-.802-.125-.995s-.524-.29-1.047-.29z"/>',
4937
5272
  "opentelemetry": '<path d="M12.6974 13.1173c-1.0224 1.0224-1.0224 2.68 0 3.7024 1.0224 1.0224 2.68 1.0224 3.7024 0 1.0224-1.0223 1.0224-2.68 0-3.7024-1.0223-1.0223-2.68-1.0223-3.7024 0zm2.7677 2.7701c-.5063.5063-1.3267.5063-1.833 0s-.5063-1.3266 0-1.833c.5063-.5062 1.3267-.5062 1.833 0 .5063.504.5063 1.3267 0 1.833zM16.356.2355l-1.6041 1.6042c-.314.314-.314.83 0 1.144L21.015 9.247c.314.314.83.314 1.144 0l1.6042-1.6041c.314-.314.314-.83 0-1.144L17.4976.2354c-.314-.314-.8276-.314-1.1416 0zM5.1173 20.734c.2848-.2848.2848-.7497 0-1.0345l-.8155-.8155c-.2848-.2848-.7497-.2848-1.0345 0l-1.6845 1.6845-.0024.0024-.4625-.4625c-.2556-.2556-.6718-.2556-.925 0-.2556.2556-.2556.6718 0 .925l2.775 2.775c.2556.2556.6718.2556.925 0 .2532-.2556.2556-.6718 0-.925l-.4625-.4625.0024-.0024zm8.4856-15.893-3.5637 3.5637c-.3164.3164-.3164.8374 0 1.1538l2.2006 2.2005c1.5554-1.1197 3.7365-.981 5.1361.4187l1.7819-1.7818c.3164-.3165.3164-.8374 0-1.1538l-4.401-4.401c-.3165-.319-.8374-.319-1.1539 0zm-2.2881 7.8455-1.2999-1.2999c-.3043-.3043-.8033-.3043-1.1076 0l-4.5836 4.586c-.3042.3043-.3042.8033 0 1.1076l2.5973 2.5973c.3043.3043.8033.3043 1.1076 0l2.9478-2.9527c-.6231-1.2877-.5112-2.8431.3384-4.0383z"/>',
5273
+ "jira": '<path d="M11.571 11.513H0a5.218 5.218 0 0 0 5.232 5.215h2.13v2.057A5.215 5.215 0 0 0 12.575 24V12.518a1.005 1.005 0 0 0-1.005-1.005zm5.723-5.756H5.736a5.215 5.215 0 0 0 5.215 5.214h2.129v2.058a5.218 5.218 0 0 0 5.215 5.214V6.758a1.001 1.001 0 0 0-1.001-1.001zM23.013 0H11.455a5.215 5.215 0 0 0 5.215 5.215h2.129v2.057A5.215 5.215 0 0 0 24 12.483V1.005A1.001 1.001 0 0 0 23.013 0Z"/>',
4938
5274
  "googlebigquery": '<path d="M5.676 10.595h2.052v5.244a5.892 5.892 0 0 1-2.052-2.088v-3.156zm18.179 10.836a.504.504 0 0 1 0 .708l-1.716 1.716a.504.504 0 0 1-.708 0l-4.248-4.248a.206.206 0 0 1-.007-.007c-.02-.02-.028-.045-.043-.066a10.736 10.736 0 0 1-6.334 2.065C4.835 21.599 0 16.764 0 10.799S4.835 0 10.8 0s10.799 4.835 10.799 10.8c0 2.369-.772 4.553-2.066 6.333.025.017.052.028.074.05l4.248 4.248zm-5.028-10.632a8.015 8.015 0 1 0-8.028 8.028h.024a8.016 8.016 0 0 0 8.004-8.028zm-4.86 4.98a6.002 6.002 0 0 0 2.04-2.184v-1.764h-2.04v3.948zm-4.5.948c.442.057.887.08 1.332.072.4.025.8.025 1.2 0V7.692H9.468v9.035z"/>',
4939
5275
  "googlebigtable": '<path d="M10.511.278s0-.4.456-.24c.267.094 3.728 2.243 5.88 3.533l.006.003.364.217c.004.003.007.009.011.011.322.2.656.42 1.006.673.27.165.43.463.42.78l-.06 7.566a.42.42 0 0 1-.192.396l-1.2.815V5.436c-.042-.034-.083-.07-.131-.098l-5.06-3.01c-.744-.466-1.5-1.642-1.5-2.05zm-2.89 12.171 4.39 2.614 4.388-2.566v-1.079L12.25 13.84a.78.78 0 0 1-.24.072.43.43 0 0 1-.24-.072l-4.149-2.47v1.08zm0 1.943c0 .17.086.327.228.42l3.933 2.398c.123.06.162.07.228.064.088-.003.173-.074.252-.112l3.933-2.398a.468.468 0 0 0 .228-.42v-.791L12.25 16.07a.432.432 0 0 1-.48 0L7.621 13.6v.79zm8.778-4.137v-.516a.467.467 0 0 0-.228-.408l-3.933-2.398a.444.444 0 0 0-.456 0L7.85 9.331a.492.492 0 0 0-.228.408v.516l4.39 2.614 4.388-2.614zm-4.473 11.332L6.95 18.625c-.041-.025-.06-.07-.096-.1v-8.63l-1.2.708a.491.491 0 0 0-.227.395v7.867a.9.9 0 0 0 .407.72l1.272.79c-.002 0-.003-.003-.005-.004l6.024 3.59a.216.216 0 0 0 .336-.216 3.262 3.262 0 0 0-1.535-2.158zM8.891 4.097a.845.845 0 0 1 .859.009L16.41 8.06V6.645a.444.444 0 0 0-.24-.371l-6.38-3.778a.81.81 0 0 0-.85-.012l-1.433.856C5.56 4.498 1.525 6.893 1.36 6.975a.276.276 0 0 0 0 .48 3.154 3.154 0 0 0 2.495-.312L8.89 4.097zM22.635 16.49a3.154 3.154 0 0 0-2.519.3l-5.036 2.986a.875.875 0 0 1-.887 0l-.018-.006-6.554-3.867v1.39c.021.152.093.292.204.397l6.356 3.765a.84.84 0 0 0 .887 0l1.415-.863h-.004l6.156-3.646a.252.252 0 0 0 0-.456zM10.967 6.13l-1.2-.708a.407.407 0 0 0-.431 0L3.688 8.756a.863.863 0 0 0-.456.767v8.862a.216.216 0 0 0 .36.156 3.297 3.297 0 0 0 1.043-2.398v-5.996a.9.9 0 0 1 .098-.367l6.234-3.65zm2.11 11.728 1.2.683a.42.42 0 0 0 .443 0l5.684-3.418c.335-.207.442-.408.442-.706l.002-.001V12.665c0 .006-.004.01-.004.017-.006-2.494-.013-6.831.004-7.104.024-.384-.372-.252-.372-.252a3.37 3.37 0 0 0-1.007 2.399v5.995a.97.97 0 0 1-.191.413l-6.2 3.725z"/>',
4940
5276
  "googlecloudspanner": '<path d="M12 9.06 7.944 6.864V2.388L10.38.924v3.66l1.62.744 1.62-.744V.924l2.436 1.464v4.476L12 9.06zm-8.124 4.752L0 16.056v2.988l3.228-1.86 1.404.912.096 1.632-3.24 1.872 2.616 1.476 3.828-2.268-.132-4.596-3.924-2.4zm9.732-.9V8.758l-1.37.742-.238.129-.238-.13-1.37-.741v4.154l-3.613 2.09 1.282.783.231.142.008.27.046 1.612L12 15.696l3.595 2.079.045-1.59.008-.27.231-.142 1.301-.795-3.572-2.066zm7.164 4.272L24 19.044v-2.988L20.064 13.8l-3.924 2.4-.132 4.596 3.888 2.244 2.616-1.44-3.24-1.836.096-1.668 1.404-.912z"/>',
@@ -4962,6 +5298,7 @@ var init_simple_catalog_generated = __esm({
4962
5298
  "flydotio": '<path d="M11.987 0c-2.45-.01-5.002.925-6.541 2.897-1.17 1.502-1.664 3.474-1.49 5.356.29 2.112 1.476 3.96 2.676 5.672a41.5 41.5 0 0 0 4.216 4.831c-1.063.832-1.943 2.286-1.357 3.644.821 2.32 4.665 2.05 5.122-.372.39-1.288-.694-2.533-1.428-3.309 2.388-2.431 4.706-5.036 6.17-8.145.595-1.32.902-2.802.614-4.24-.28-2.341-1.823-4.473-3.967-5.46C14.76.266 13.364.016 11.987 0m-.236 1.577v15.534C9.881 13.483 7.724 9.266 8.73 5.069c.35-1.539 1.253-3.309 3.02-3.492m1.996.04c1.534.357 3.031 1.096 3.906 2.48 1.3 1.93 1.318 4.55.1 6.521-1.268 2.395-3.06 4.463-4.916 6.415 1.472-2.974 3.074-6.106 3.182-9.5-.043-2.08-.438-4.612-2.272-5.916M11.97 20.103c.848.342 1.597 1.983.153 2.173-.664.15-1.367-.599-.995-1.222.213-.355.488-.73.842-.95"/>',
4963
5299
  "openstack": '<path d="M18.575 9.29h5.418v5.42h-5.418zM0 9.29h5.419v5.42H0zm18.575 7.827a1.207 1.207 0 0 1-1.206 1.206H6.623a1.207 1.207 0 0 1-1.205-1.206v-.858H0v5.252a2.236 2.236 0 0 0 2.229 2.23h19.53A2.237 2.237 0 0 0 24 21.512V16.26h-5.425zM21.763.258H2.233a2.236 2.236 0 0 0-2.23 2.23V7.74h5.419v-.858a1.206 1.206 0 0 1 1.205-1.206h10.746a1.206 1.206 0 0 1 1.205 1.206v.858H24V2.487A2.237 2.237 0 0 0 21.763.258Z"/>',
4964
5300
  "wordpress": '<path d="M21.469 6.825c.84 1.537 1.318 3.3 1.318 5.175 0 3.979-2.156 7.456-5.363 9.325l3.295-9.527c.615-1.54.82-2.771.82-3.864 0-.405-.026-.78-.07-1.11m-7.981.105c.647-.03 1.232-.105 1.232-.105.582-.075.514-.93-.067-.899 0 0-1.755.135-2.88.135-1.064 0-2.85-.15-2.85-.15-.585-.03-.661.855-.075.885 0 0 .54.061 1.125.09l1.68 4.605-2.37 7.08L5.354 6.9c.649-.03 1.234-.1 1.234-.1.585-.075.516-.93-.065-.896 0 0-1.746.138-2.874.138-.2 0-.438-.008-.69-.015C4.911 3.15 8.235 1.215 12 1.215c2.809 0 5.365 1.072 7.286 2.833-.046-.003-.091-.009-.141-.009-1.06 0-1.812.923-1.812 1.914 0 .89.513 1.643 1.06 2.531.411.72.89 1.643.89 2.977 0 .915-.354 1.994-.821 3.479l-1.075 3.585-3.9-11.61.001.014zM12 22.784c-1.059 0-2.081-.153-3.048-.437l3.237-9.406 3.315 9.087c.024.053.05.101.078.149-1.12.393-2.325.609-3.582.609M1.211 12c0-1.564.336-3.05.935-4.39L7.29 21.709C3.694 19.96 1.212 16.271 1.211 12M12 0C5.385 0 0 5.385 0 12s5.385 12 12 12 12-5.385 12-12S18.615 0 12 0"/>',
5301
+ "sap": '<path d="M0 6.064v11.872h12.13L24 6.064zm3.264 2.208h.005c.863.001 1.915.245 2.676.633l-.82 1.43c-.835-.404-1.255-.442-1.73-.467-.708-.038-1.064.215-1.069.488-.007.332.669.633 1.305.838.964.306 2.19.715 2.377 1.9L7.77 8.437h2.046l2.064 5.576-.007-5.575h2.37c2.257 0 3.318.764 3.318 2.519 0 1.575-1.09 2.514-2.936 2.514h-.763l-.01 2.094-3.588-.003-.25-.908c-.37.122-.787.189-1.23.189-.456 0-.885-.071-1.263-.2l-.358.919-2 .006.09-.462c-.029.025-.057.05-.087.074-.535.43-1.208.629-2.037.644l-.213.002a5.075 5.075 0 0 1-2.581-.675l.73-1.448c.79.467 1.286.572 1.956.558.347-.007.598-.07.761-.239a.557.557 0 0 0 .156-.369c.007-.376-.53-.553-1.185-.756-.531-.164-1.135-.389-1.606-.735-.559-.41-.825-.924-.812-1.65a1.99 1.99 0 0 1 .566-1.377c.519-.537 1.357-.863 2.363-.863zm10.597 1.67v1.904h.521c.694 0 1.247-.23 1.248-.964 0-.709-.554-.94-1.248-.94zm-5.087.767l-.748 2.362c.223.085.481.133.757.133.268 0 .52-.047.742-.126l-.736-2.37z"/>',
4965
5302
  "confluence": '<path d="M.87 18.257c-.248.382-.53.875-.763 1.245a.764.764 0 0 0 .255 1.04l4.965 3.054a.764.764 0 0 0 1.058-.26c.199-.332.454-.763.733-1.221 1.967-3.247 3.945-2.853 7.508-1.146l4.957 2.337a.764.764 0 0 0 1.028-.382l2.364-5.346a.764.764 0 0 0-.382-1 599.851 599.851 0 0 1-4.965-2.361C10.911 10.97 5.224 11.185.87 18.257zM23.131 5.743c.249-.405.531-.875.764-1.25a.764.764 0 0 0-.256-1.034L18.675.404a.764.764 0 0 0-1.058.26c-.195.335-.451.763-.734 1.225-1.966 3.246-3.945 2.85-7.508 1.146L4.437.694a.764.764 0 0 0-1.027.382L1.046 6.422a.764.764 0 0 0 .382 1c1.039.49 3.105 1.467 4.965 2.361 6.698 3.246 12.392 3.029 16.738-4.04z"/>',
4966
5303
  "zapier": '<path d="M4.157 0A4.151 4.151 0 0 0 0 4.161v15.678A4.151 4.151 0 0 0 4.157 24h15.682A4.152 4.152 0 0 0 24 19.839V4.161A4.152 4.152 0 0 0 19.839 0H4.157Zm10.61 8.761h.03a.577.577 0 0 1 .23.038.585.585 0 0 1 .201.124.63.63 0 0 1 .162.431.612.612 0 0 1-.162.435.58.58 0 0 1-.201.128.58.58 0 0 1-.23.042.529.529 0 0 1-.235-.042.585.585 0 0 1-.332-.328.559.559 0 0 1-.038-.235.613.613 0 0 1 .17-.431.59.59 0 0 1 .405-.162Zm2.853 1.572c.03.004.061.004.095.004.325-.011.646.064.937.219.238.144.431.355.552.609.128.279.189.582.185.888v.193a2 2 0 0 1 0 .219h-2.498c.003.227.075.45.204.642a.78.78 0 0 0 .646.265.714.714 0 0 0 .484-.136.642.642 0 0 0 .23-.318l.915.257a1.398 1.398 0 0 1-.28.537c-.14.159-.321.284-.521.355a2.234 2.234 0 0 1-.836.136 1.923 1.923 0 0 1-1.001-.245 1.618 1.618 0 0 1-.665-.703 2.221 2.221 0 0 1-.227-1.036 1.95 1.95 0 0 1 .48-1.398 1.9 1.9 0 0 1 1.3-.488Zm-9.607.023c.162.004.325.026.48.079.207.065.4.174.563.314.26.302.393.692.366 1.088v2.276H8.53l-.109-.711h-.065c-.064.163-.155.31-.272.439a1.122 1.122 0 0 1-.374.264 1.023 1.023 0 0 1-.453.083 1.334 1.334 0 0 1-.866-.264.965.965 0 0 1-.329-.801.993.993 0 0 1 .076-.431 1.02 1.02 0 0 1 .242-.363 1.478 1.478 0 0 1 1.043-.303h.952v-.181a.696.696 0 0 0-.136-.454.553.553 0 0 0-.438-.154.695.695 0 0 0-.378.086.48.48 0 0 0-.193.254l-.99-.144a1.26 1.26 0 0 1 .257-.563c.14-.174.321-.302.533-.378.261-.091.54-.136.82-.129.053-.003.106-.007.163-.007Zm4.384.007c.174 0 .347.038.506.114.182.083.34.211.458.374.257.423.377.911.351 1.406a2.53 2.53 0 0 1-.355 1.448 1.148 1.148 0 0 1-1.009.517c-.204 0-.401-.045-.582-.136a1.052 1.052 0 0 1-.48-.457 1.298 1.298 0 0 1-.114-.234h-.045l.004 1.784h-1.059v-4.713h.904l.117.805h.057c.068-.208.177-.401.328-.56a1.129 1.129 0 0 1 .843-.344h.076v-.004Zm7.559.084h.903l.113.805h.053a1.37 1.37 0 0 1 .235-.484.813.813 0 0 1 .313-.242.82.82 0 0 1 .39-.076h.234v1.051h-.401a.662.662 0 0 0-.313.008.623.623 0 0 0-.272.155.663.663 0 0 0-.174.26.683.683 0 0 0-.027.314v1.875h-1.054v-3.666Zm-17.515.003h3.262v.896L3.73 13.104l.034.113h1.973l.042.9H2.4v-.9l1.931-1.754-.045-.117H2.441v-.896Zm11.815 0h1.055v3.659h-1.055V10.45Zm3.443.684.019.016a.69.69 0 0 0-.351.045.756.756 0 0 0-.287.204c-.11.155-.174.336-.189.522h1.545c-.034-.526-.257-.787-.74-.787h.003Zm-5.718.163c-.026 0-.057 0-.083.004a.78.78 0 0 0-.31.053.746.746 0 0 0-.257.189 1.016 1.016 0 0 0-.204.695v.064c-.015.257.057.507.204.711a.634.634 0 0 0 .253.196.638.638 0 0 0 .314.061.644.644 0 0 0 .578-.265c.14-.223.204-.48.189-.74a1.216 1.216 0 0 0-.181-.711.677.677 0 0 0-.503-.257Zm-4.509 1.266a.464.464 0 0 0-.268.102.373.373 0 0 0-.114.276c0 .053.008.106.027.155a.375.375 0 0 0 .087.132.576.576 0 0 0 .397.11v.004a.863.863 0 0 0 .563-.182.573.573 0 0 0 .211-.457v-.14h-.903Z"/>',
4967
5304
  "googledrive": '<path d="M12.01 1.485c-2.082 0-3.754.02-3.743.047.01.02 1.708 3.001 3.774 6.62l3.76 6.574h3.76c2.081 0 3.753-.02 3.742-.047-.005-.02-1.708-3.001-3.775-6.62l-3.76-6.574zm-4.76 1.73a789.828 789.861 0 0 0-3.63 6.319L0 15.868l1.89 3.298 1.885 3.297 3.62-6.335 3.618-6.33-1.88-3.287C8.1 4.704 7.255 3.22 7.25 3.214zm2.259 12.653-.203.348c-.114.198-.96 1.672-1.88 3.287a423.93 423.948 0 0 1-1.698 2.97c-.01.026 3.24.042 7.222.042h7.244l1.796-3.157c.992-1.734 1.85-3.23 1.906-3.323l.104-.167h-7.249z"/>',
@@ -5152,6 +5489,7 @@ var init_core_art_generated = __esm({
5152
5489
  "712b426f54f0fc50d0816dc79df709daa7ac5f93ccaf4e9b3527f627f6e9ad97": '<svg id="bc93169a-24c4-4686-9f37-c7e4f53b3d34" xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 18 18"><defs><radialGradient id="fb114c93-7c16-4540-899a-0796041629e6" cx="9" cy="9" r="8.5" gradientUnits="userSpaceOnUse"><stop offset="0.18" stop-color="#5ea0ef" /><stop offset="0.56" stop-color="#5c9fee" /><stop offset="0.69" stop-color="#559ced" /><stop offset="0.78" stop-color="#4a97e9" /><stop offset="0.86" stop-color="#3990e4" /><stop offset="0.93" stop-color="#2387de" /><stop offset="0.99" stop-color="#087bd6" /><stop offset="1" stop-color="#0078d4" /></radialGradient><radialGradient id="ec478bd3-5b38-4e7f-b661-11f355578bff" cx="38.95" cy="182.07" r="9.88" gradientTransform="translate(-28.71 -163.24) scale(0.94 0.94)" gradientUnits="userSpaceOnUse"><stop offset="0.27" stop-color="#ffd70f" /><stop offset="0.49" stop-color="#ffcb12" /><stop offset="0.88" stop-color="#feac19" /><stop offset="1" stop-color="#fea11b" /></radialGradient></defs><title>Icon-security-245</title><path id="aacf8311-a317-400f-b613-74bd00da5ce3" d="M9,.5A8.5,8.5,0,1,0,17.5,9,8.51,8.51,0,0,0,9,.5ZM9,16.34A7.34,7.34,0,1,1,16.34,9,7.34,7.34,0,0,1,9,16.34Z" fill="url(#fb114c93-7c16-4540-899a-0796041629e6)" /><circle cx="9" cy="9" r="7.34" fill="#fff" /><g><path id="bd983c41-db73-40ec-a4f4-da1213fc9924" d="M13.44,7.33a1.84,1.84,0,0,0,0-2.59h0L10.29,1.58a1.83,1.83,0,0,0-2.58,0h0L4.56,4.74a1.84,1.84,0,0,0,0,2.59L7.18,10a.51.51,0,0,1,.15.36v4.88a.63.63,0,0,0,.18.44l1.2,1.2a.41.41,0,0,0,.58,0l1.16-1.16h0l.68-.68a.25.25,0,0,0,0-.34l-.49-.49a.27.27,0,0,1,0-.37l.49-.49a.25.25,0,0,0,0-.34l-.49-.49a.27.27,0,0,1,0-.37l.49-.49a.25.25,0,0,0,0-.34l-.68-.69v-.25ZM9,2.35A1,1,0,0,1,9,4.42,1,1,0,1,1,9,2.35Z" fill="url(#ec478bd3-5b38-4e7f-b661-11f355578bff)" /><path id="ad2e7e44-9bfd-4775-8bf4-8ef26a544921" d="M8.18,15.3h0a.23.23,0,0,0,.38-.17v-4a.24.24,0,0,0-.11-.2h0a.22.22,0,0,0-.34.2v4A.28.28,0,0,0,8.18,15.3Z" fill="#ff9300" opacity="0.75" /><rect id="a996fbff-3936-4b24-b407-369336c143ba" x="6.48" y="5.79" width="5.17" height="0.61" rx="0.28" fill="#ff9300" opacity="0.75" /><rect id="bb12d31c-3352-4a18-87dd-a169a4a8721d" x="6.48" y="6.78" width="5.17" height="0.61" rx="0.28" fill="#ff9300" opacity="0.75" /></g></svg>',
5153
5490
  "7190d3bb14ce30ce74bd0af873915830fe821e8c5f6ef6f3149e6f7cfb2aa4f7": '<svg id="f2f04349-8aee-4413-84c9-a9053611b319" xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 18 18"><defs><linearGradient id="ad4c4f96-09aa-4f91-ba10-5cb8ad530f74" x1="9" y1="15.83" x2="9" y2="5.79" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#b3b3b3" /><stop offset="0.26" stop-color="#c1c1c1" /><stop offset="1" stop-color="#e6e6e6" /></linearGradient></defs><title>Icon-storage-86</title><path d="M.5,5.79h17a0,0,0,0,1,0,0v9.48a.57.57,0,0,1-.57.57H1.07a.57.57,0,0,1-.57-.57V5.79A0,0,0,0,1,.5,5.79Z" fill="url(#ad4c4f96-09aa-4f91-ba10-5cb8ad530f74)" /><path d="M1.07,2.17H16.93a.57.57,0,0,1,.57.57V5.79a0,0,0,0,1,0,0H.5a0,0,0,0,1,0,0V2.73A.57.57,0,0,1,1.07,2.17Z" fill="#37c2b1" /><path d="M2.81,6.89H15.18a.27.27,0,0,1,.26.27v1.4a.27.27,0,0,1-.26.27H2.81a.27.27,0,0,1-.26-.27V7.16A.27.27,0,0,1,2.81,6.89Z" fill="#fff" /><path d="M2.82,9.68H15.19a.27.27,0,0,1,.26.27v1.41a.27.27,0,0,1-.26.27H2.82a.27.27,0,0,1-.26-.27V10A.27.27,0,0,1,2.82,9.68Z" fill="#37c2b1" /><path d="M2.82,12.5H15.19a.27.27,0,0,1,.26.27v1.41a.27.27,0,0,1-.26.27H2.82a.27.27,0,0,1-.26-.27V12.77A.27.27,0,0,1,2.82,12.5Z" fill="#258277" /></svg>',
5154
5491
  "72c6104c5f2199f6eaebbc215c5cb78dea9c1d571b95f470341ca7f83eee5be8": '<svg id="b1cfe86c-f00b-4507-bce2-50d07e45fe96" xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 18 18"><defs><linearGradient id="b39dcf83-187e-4c64-98df-431bb60809d2" x1="0.5" y1="10.04" x2="13.18" y2="10.04" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#005ba1" /><stop offset="0.07" stop-color="#0060a9" /><stop offset="0.36" stop-color="#0071c8" /><stop offset="0.52" stop-color="#0078d4" /><stop offset="0.64" stop-color="#0074cd" /><stop offset="0.82" stop-color="#006abb" /><stop offset="1" stop-color="#005ba1" /></linearGradient></defs><title>Icon-databases-132</title><path d="M6.84,5.09c-3.5,0-6.34-1-6.34-2.3V15c0,1.26,2.79,2.28,6.25,2.3h.09c3.5,0,6.34-1,6.34-2.3V2.79C13.18,4.06,10.34,5.09,6.84,5.09Z" fill="url(#b39dcf83-187e-4c64-98df-431bb60809d2)" /><path d="M13.18,2.79c0,1.27-2.84,2.3-6.34,2.3S.5,4.06.5,2.79,3.34.49,6.84.49s6.34,1,6.34,2.3" fill="#e8e8e8" /><path d="M11.7,2.6c0,.81-2.18,1.46-4.86,1.46S2,3.41,2,2.6,4.16,1.14,6.84,1.14,11.7,1.8,11.7,2.6" fill="#50e6ff" /><path d="M6.84,2.94A12,12,0,0,0,3,3.49a11.25,11.25,0,0,0,3.85.57,11.25,11.25,0,0,0,3.85-.57A12,12,0,0,0,6.84,2.94Z" fill="#198ab3" /><path d="M10.74,11.1V7.72H9.81v4.14h2.46V11.1ZM3.59,9.43a1.92,1.92,0,0,1-.51-.31A.44.44,0,0,1,3,8.8a.38.38,0,0,1,.16-.31.72.72,0,0,1,.42-.11,1.67,1.67,0,0,1,1,.29V7.81a2.67,2.67,0,0,0-1-.16A1.74,1.74,0,0,0,2.38,8a1.13,1.13,0,0,0-.41.9c0,.51.32.91,1,1.21a2.9,2.9,0,0,1,.61.36.4.4,0,0,1,.16.32.38.38,0,0,1-.16.31.75.75,0,0,1-.45.12A1.6,1.6,0,0,1,2,10.77v.93a2.29,2.29,0,0,0,1.07.23,2,2,0,0,0,1.18-.32,1.1,1.1,0,0,0,.43-.92,1,1,0,0,0-.25-.7A2.42,2.42,0,0,0,3.59,9.43ZM8.79,11a2.4,2.4,0,0,0,.33-1.27,2.32,2.32,0,0,0-.25-1.1,1.81,1.81,0,0,0-.7-.75,2,2,0,0,0-1-.26,2.18,2.18,0,0,0-1.09.27,1.87,1.87,0,0,0-.73.77,2.41,2.41,0,0,0-.26,1.15,2.26,2.26,0,0,0,.24,1.05,1.83,1.83,0,0,0,.68.75,2,2,0,0,0,1,.29l.85,1H9.05l-1.2-1.11A1.81,1.81,0,0,0,8.79,11Zm-.93-.26a1,1,0,0,1-1.53,0,1.51,1.51,0,0,1-.28-1,1.48,1.48,0,0,1,.29-1,.92.92,0,0,1,.78-.37.89.89,0,0,1,.75.37,1.62,1.62,0,0,1,.27,1A1.46,1.46,0,0,1,7.86,10.77Z" fill="#f2f2f2" /><path d="M14.81,17.49l.24-.79.47-.27.81.36.52-.53V16.2l-.37-.71.22-.5.81-.29.09,0v-.73l-.1,0-.8-.24-.26-.46.35-.82-.53-.51H16.2l-.71.36L15,12l-.32-.89h-.74l0,.11-.24.79-.51.22-.87-.4-.51.53.05.1.38.74-.2.51L11.1,14v.74l.11,0,.79.24.22.51-.39.86.53.52.09-.05.74-.38.51.2.34.89h.73Zm-1.2-2.36a1.06,1.06,0,1,1,1.49-1.52,1.06,1.06,0,0,1-1.49,1.52Z" fill="#949494" /></svg>',
5492
+ "754537541da48fd4957180d452bd64dfc4a9bbe4de4cbfdfa833ef8af556d16f": '<svg id="a75e3f3a-2661-410b-82fb-d300d37dea2d" xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 18 18"><defs><linearGradient id="aff60ddf-eec1-40bf-8bf5-f3e3b50e8818" x1="9" y1="16.21" x2="9" y2="0.62" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#1b93eb" /><stop offset="0.21" stop-color="#2095eb" /><stop offset="0.44" stop-color="#2e9ced" /><stop offset="0.69" stop-color="#45a7ef" /><stop offset="0.95" stop-color="#64b6f1" /><stop offset="1" stop-color="#6bb9f2" /></linearGradient></defs><title>Icon-security-248</title><path d="M16,8.44c0,4.57-5.53,8.25-6.73,9a.43.43,0,0,1-.46,0C7.57,16.69,2,13,2,8.44V2.94a.44.44,0,0,1,.43-.44C6.77,2.39,5.78.5,9,.5s2.23,1.89,6.53,2a.44.44,0,0,1,.43.44Z" fill="#1b93eb" /><path d="M15.38,8.48c0,4.2-5.07,7.57-6.17,8.25a.4.4,0,0,1-.42,0c-1.1-.68-6.17-4.05-6.17-8.25v-5A.41.41,0,0,1,3,3c3.94-.11,3-1.83,6-1.83S11.05,2.93,15,3a.41.41,0,0,1,.39.4Z" fill="url(#aff60ddf-eec1-40bf-8bf5-f3e3b50e8818)" /><path d="M9,6.53A2.88,2.88,0,0,1,11.84,9a.49.49,0,0,0,.49.4h1.4a.49.49,0,0,0,.5-.53,5.26,5.26,0,0,0-10.46,0,.49.49,0,0,0,.5.53h1.4A.49.49,0,0,0,6.16,9,2.88,2.88,0,0,1,9,6.53Z" fill="#c3f1ff" /><circle cx="9" cy="9.4" r="1.91" fill="#fff" /></svg>',
5155
5493
  "7602c24ecbcefe06bc16605f9ae2ba37aa1bca534cc2f1752a5b2926a1695d0a": '<svg id="b7c2a418-e983-45bb-8b22-a3ab53d9ffdb" xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 18 18"><defs><linearGradient id="ecfac9f9-2ace-451a-aef4-4aae90523bfb" x1="9" y1="15.83" x2="9" y2="5.79" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#32bedd" /><stop offset="0.18" stop-color="#32caea" /><stop offset="0.41" stop-color="#32d2f2" /><stop offset="0.78" stop-color="#32d4f5" /></linearGradient></defs><title>Icon-storage-96</title><path d="M.5,5.79h17a0,0,0,0,1,0,0v9.48a.57.57,0,0,1-.57.57H1.07a.57.57,0,0,1-.57-.57V5.79A0,0,0,0,1,.5,5.79Z" fill="url(#ecfac9f9-2ace-451a-aef4-4aae90523bfb)" /><path d="M1.07,2.17H16.93a.57.57,0,0,1,.57.57V5.79a0,0,0,0,1,0,0H.5a0,0,0,0,1,0,0V2.73A.57.57,0,0,1,1.07,2.17Z" fill="#198ab3" /><path d="M2.81,6.89H15.17a.27.27,0,0,1,.27.27v1.4a.27.27,0,0,1-.27.27H2.81a.27.27,0,0,1-.26-.27V7.16A.27.27,0,0,1,2.81,6.89Z" fill="#fff" /><path d="M2.82,9.68H15.18a.27.27,0,0,1,.27.27v1.41a.27.27,0,0,1-.27.27H2.82a.26.26,0,0,1-.26-.27V10A.26.26,0,0,1,2.82,9.68Z" fill="#9cebff" /><path d="M2.82,12.5H15.18a.27.27,0,0,1,.27.27v1.41a.27.27,0,0,1-.27.27H2.82a.26.26,0,0,1-.26-.27V12.77A.26.26,0,0,1,2.82,12.5Z" fill="#9cebff" /><path id="ae090ab3-6849-4f1b-8ada-ca4d90aafe4f" d="M5.11,7.86v5.59a.28.28,0,0,0,.28.28H7.74A.28.28,0,0,0,8,13.45V10.13a.27.27,0,0,1,.28-.28H9.69a.27.27,0,0,1,.28.28v3.32a.28.28,0,0,0,.29.28h2.35a.28.28,0,0,0,.28-.28V7.86a.28.28,0,0,0-.28-.28H5.39A.28.28,0,0,0,5.11,7.86Z" fill="#0078d4" /></svg>',
5156
5494
  "76763e2d29dc7315305c578af6f7ca19310670805749ca3b332a1e8cfe45ddd3": '<svg id="fca2105f-c039-4f34-bd65-8ab95d4ecdb9" xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 18 18"><defs><linearGradient id="a773af38-43e4-4fd2-9485-f8aac63ca91b" x1="5.57" y1="17.5" x2="5.57" y2="0.5" gradientUnits="userSpaceOnUse"><stop offset="0.05" stop-color="#949494" /><stop offset="0.36" stop-color="#979797" /><stop offset="0.54" stop-color="#9f9f9f" /><stop offset="0.69" stop-color="#adadad" /><stop offset="0.73" stop-color="#b3b3b3" /></linearGradient><linearGradient id="b4779ae6-74a5-486d-8aad-cd011859785a" x1="10.56" y1="6.02" x2="10.56" y2="19.71" gradientUnits="userSpaceOnUse"><stop offset="0.18" stop-color="#5ea0ef" /><stop offset="1" stop-color="#0078d4" /></linearGradient></defs><title>Icon-web-46</title><path d="M10.56,16.93a.56.56,0,0,1-.57.57H1.14a.56.56,0,0,1-.56-.57V1.07A.56.56,0,0,1,1.14.5H10a.56.56,0,0,1,.57.57Z" fill="url(#a773af38-43e4-4fd2-9485-f8aac63ca91b)" /><path d="M2,6.46A1.08,1.08,0,0,1,3.13,5.38h5A1.08,1.08,0,0,1,9.18,6.46h0A1.08,1.08,0,0,1,8.1,7.55h-5A1.09,1.09,0,0,1,2,6.46Z" fill="#003067" /><path d="M2,3.24A1.09,1.09,0,0,1,3.13,2.15h5A1.08,1.08,0,0,1,9.18,3.24h0A1.08,1.08,0,0,1,8.1,4.32h-5A1.08,1.08,0,0,1,2,3.24Z" fill="#003067" /><circle cx="3.17" cy="3.24" r="0.73" fill="#50e6ff" /><circle cx="3.17" cy="6.46" r="0.73" fill="#50e6ff" /><path d="M17.42,14.38a3.12,3.12,0,0,0-2.67-3,3.93,3.93,0,0,0-4-3.8,4,4,0,0,0-3.83,2.66A3.7,3.7,0,0,0,3.7,13.83,3.77,3.77,0,0,0,7.56,17.5l.34,0h6.26l.17,0A3.15,3.15,0,0,0,17.42,14.38Z" fill="url(#b4779ae6-74a5-486d-8aad-cd011859785a)" /><rect width="18" height="18" fill="none" /></svg>',
5157
5495
  "7a244a8d7260e84be5c904185db7b04994fe6ed345e2b224163bc5f7e3d97ce0": '<svg id="b388e944-5509-49c9-84d7-f38bffa995b2" xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 18 18"><defs><linearGradient id="a997e203-1d7d-4cb9-b131-5dc44e029b46" x1="5.23" y1="17.45" x2="5.23" y2="8.09" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#1988d9" /><stop offset="0.9" stop-color="#54aef0" /></linearGradient><linearGradient id="e122e9d8-aee5-4f1a-a60e-b1eae355daa5" x1="11.5" y1="12.45" x2="11.5" y2="0.55" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#198ab3" /><stop offset="0.01" stop-color="#198bb4" /><stop offset="0.44" stop-color="#27b2d7" /><stop offset="0.79" stop-color="#2fcbed" /><stop offset="1" stop-color="#32d4f5" /></linearGradient></defs><title>Icon-manage-307</title><path d="M5.59,13.13H9.91v4.32H5.59ZM1.15,17.45H4.87V13.13H.55v3.72A.6.6,0,0,0,1.15,17.45Zm-.6-5H4.87V8.09H.55Z" fill="url(#a997e203-1d7d-4cb9-b131-5dc44e029b46)" /><path d="M11.5.55a5.89,5.89,0,0,1,5.95,6,5.89,5.89,0,0,1-5.95,5.95H5.55V6.5A5.89,5.89,0,0,1,11.5.55Z" fill-rule="evenodd" fill="url(#e122e9d8-aee5-4f1a-a60e-b1eae355daa5)" /><rect x="7.59" y="5.65" width="1.36" height="4.08" fill="#fff" /><rect x="10.31" y="7.01" width="1.36" height="2.72" fill="#fff" /><rect x="13.03" y="4.29" width="1.36" height="5.44" fill="#fff" /></svg>',
@@ -5175,6 +5513,7 @@ var init_core_art_generated = __esm({
5175
5513
  "a26124a2b188ccf910520c935c726f7364e0f5935d7a4319ebcab9c80a40e475": '<svg id="a96792b7-ce28-4ca3-9767-4e065ef4820f" xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 18 18"><defs><linearGradient id="ef16bf9d-a8b6-4181-b6cd-66fc5203f956" x1="2.59" y1="10.16" x2="15.41" y2="10.16" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#005ba1" /><stop offset="0.07" stop-color="#0060a9" /><stop offset="0.36" stop-color="#0071c8" /><stop offset="0.52" stop-color="#0078d4" /><stop offset="0.64" stop-color="#0074cd" /><stop offset="0.82" stop-color="#006abb" /><stop offset="1" stop-color="#005ba1" /></linearGradient><radialGradient id="bf3846c3-4d74-4743-ab9a-f334c248bd92" cx="9.36" cy="10.57" r="7.07" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#f2f2f2" /><stop offset="0.58" stop-color="#eee" /><stop offset="1" stop-color="#e6e6e6" /></radialGradient></defs><title>Icon-databases-130</title><path d="M9,5.14c-3.54,0-6.41-1-6.41-2.32V15.18c0,1.27,2.82,2.3,6.32,2.32H9c3.54,0,6.41-1,6.41-2.32V2.82C15.41,4.11,12.54,5.14,9,5.14Z" fill="url(#ef16bf9d-a8b6-4181-b6cd-66fc5203f956)" /><path d="M15.41,2.82c0,1.29-2.87,2.32-6.41,2.32s-6.41-1-6.41-2.32S5.46.5,9,.5s6.41,1,6.41,2.32" fill="#e8e8e8" /><path d="M13.92,2.63c0,.82-2.21,1.48-4.92,1.48S4.08,3.45,4.08,2.63,6.29,1.16,9,1.16s4.92.66,4.92,1.47" fill="#50e6ff" /><path d="M9,3a11.55,11.55,0,0,0-3.89.57A11.42,11.42,0,0,0,9,4.11a11.15,11.15,0,0,0,3.89-.58A11.84,11.84,0,0,0,9,3Z" fill="#198ab3" /><path d="M12.9,11.4V8H12v4.13h2.46V11.4ZM5.76,9.73a1.83,1.83,0,0,1-.51-.31.44.44,0,0,1-.12-.32.34.34,0,0,1,.15-.3.68.68,0,0,1,.42-.12,1.62,1.62,0,0,1,1,.29V8.11a2.58,2.58,0,0,0-1-.16,1.64,1.64,0,0,0-1.09.34,1.08,1.08,0,0,0-.42.89c0,.51.32.91,1,1.21a2.88,2.88,0,0,1,.62.36.42.42,0,0,1,.15.32.38.38,0,0,1-.16.31.81.81,0,0,1-.45.11,1.66,1.66,0,0,1-1.09-.42V12a2.17,2.17,0,0,0,1.07.24,1.88,1.88,0,0,0,1.18-.33A1.08,1.08,0,0,0,6.84,11a1.05,1.05,0,0,0-.25-.7A2.42,2.42,0,0,0,5.76,9.73ZM11,11.32a2.34,2.34,0,0,0,.33-1.26A2.32,2.32,0,0,0,11,9a1.81,1.81,0,0,0-.7-.75,2,2,0,0,0-1-.26,2.11,2.11,0,0,0-1.08.27A1.86,1.86,0,0,0,7.49,9a2.46,2.46,0,0,0-.26,1.14,2.26,2.26,0,0,0,.24,1,1.76,1.76,0,0,0,.69.74,2.06,2.06,0,0,0,1,.3l.86,1h1.21L10,12.08A1.79,1.79,0,0,0,11,11.32ZM10,11.07a.94.94,0,0,1-.76.35.92.92,0,0,1-.76-.36,1.52,1.52,0,0,1-.29-1,1.53,1.53,0,0,1,.29-1,1,1,0,0,1,.78-.37.87.87,0,0,1,.75.37,1.62,1.62,0,0,1,.27,1A1.46,1.46,0,0,1,10,11.07Z" fill="url(#bf3846c3-4d74-4743-ab9a-f334c248bd92)" /></svg>',
5176
5514
  "a2b134ba1ea7e774a0e493b3e4e4a8d4b72e5dfc6e1b350960360e1f0c26243a": '<svg id="a12d75ea-cbb6-44fa-832a-e54cce009101" xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 18 18"><defs><linearGradient id="e2b13d81-97e0-465a-b9ed-b7f57e1b3f8c" x1="9" y1="16.79" x2="9" y2="1.21" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#0078d4" /><stop offset="0.06" stop-color="#0a7cd7" /><stop offset="0.34" stop-color="#2e8ce1" /><stop offset="0.59" stop-color="#4897e9" /><stop offset="0.82" stop-color="#589eed" /><stop offset="1" stop-color="#5ea0ef" /></linearGradient></defs><title>Icon-identity-233</title><path d="M16.08,8.44c0,4.57-5.62,8.25-6.85,9a.43.43,0,0,1-.46,0c-1.23-.74-6.85-4.42-6.85-9V2.94a.44.44,0,0,1,.43-.44C6.73,2.39,5.72.5,9,.5s2.27,1.89,6.65,2a.44.44,0,0,1,.43.44Z" fill="#0078d4" /><path d="M15.5,8.48c0,4.2-5.16,7.57-6.29,8.25a.4.4,0,0,1-.42,0C7.66,16.05,2.5,12.68,2.5,8.48v-5A.41.41,0,0,1,2.9,3C6.92,2.93,6,1.21,9,1.21S11.08,2.93,15.1,3a.41.41,0,0,1,.4.4Z" fill="url(#e2b13d81-97e0-465a-b9ed-b7f57e1b3f8c)" /><path d="M11.85,7.66h-.4V6.24a2.62,2.62,0,0,0-.7-1.81,2.37,2.37,0,0,0-3.48,0,2.61,2.61,0,0,0-.7,1.81V7.66h-.4A.32.32,0,0,0,5.82,8v3.68a.32.32,0,0,0,.33.32h5.7a.32.32,0,0,0,.33-.32V8A.32.32,0,0,0,11.85,7.66Zm-1.55,0H7.7V6.22a1.43,1.43,0,0,1,.41-1,1.19,1.19,0,0,1,1.78,0,1.56,1.56,0,0,1,.16.2h0a1.4,1.4,0,0,1,.25.79Z" fill="#ffbd02" /><path d="M6.15,7.66h5.7a.32.32,0,0,1,.21.08L5.94,11.9a.33.33,0,0,1-.12-.24V8A.32.32,0,0,1,6.15,7.66Z" fill="#ffe452" /><path d="M11.85,7.66H6.15a.32.32,0,0,0-.21.08l6.12,4.16a.3.3,0,0,0,.12-.24V8A.32.32,0,0,0,11.85,7.66Z" fill="#ffd400" opacity="0.5" /></svg>',
5177
5515
  "a53772c07fe89cdbb876ce77e22dba0863c1459173b77a1eec73fbdd2048637f": '<svg id="a2157f88-f641-4f7d-abc7-f40ccf5cf69a" xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 18 18"><defs><linearGradient id="b816c8ea-05a2-41fb-ba99-96d84599c9f4" x1="12.74" y1="15.28" x2="12.74" y2="8.52" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#0078d4" /><stop offset="0.82" stop-color="#5ea0ef" /></linearGradient><linearGradient id="ab373d88-41af-4fc3-b172-d4489f9107a0" x1="12.74" y1="17.89" x2="12.74" y2="15.28" gradientUnits="userSpaceOnUse"><stop offset="0.15" stop-color="#ccc" /><stop offset="1" stop-color="#707070" /></linearGradient></defs><title>Icon-compute-34</title><rect x="0.79" y="0.89" width="10.11" height="6.75" rx="0.34" fill="#005ba1" /><polygon points="7.53 3.28 7.53 5.25 5.85 6.23 5.85 4.27 7.53 3.28" fill="#50e6ff" /><polygon points="7.53 3.28 5.85 4.27 4.16 3.28 5.85 2.29 7.53 3.28" fill="#c3f1ff" /><polygon points="5.85 4.27 5.85 6.23 4.16 5.25 4.16 3.28 5.85 4.27" fill="#9cebff" /><rect x="4.76" y="4.76" width="10.11" height="6.75" rx="0.34" fill="#0078d4" /><polygon points="11.5 7.16 11.5 9.12 9.82 10.11 9.82 8.14 11.5 7.16" fill="#50e6ff" /><polygon points="11.5 7.16 9.82 8.14 8.13 7.16 9.82 6.17 11.5 7.16" fill="#c3f1ff" /><polygon points="9.82 8.14 9.82 10.11 8.13 9.12 8.13 7.16 9.82 8.14" fill="#9cebff" /><rect x="7.68" y="8.52" width="10.11" height="6.75" rx="0.34" fill="url(#b816c8ea-05a2-41fb-ba99-96d84599c9f4)" /><polygon points="14.42 10.92 14.42 12.88 12.74 13.87 12.74 11.9 14.42 10.92" fill="#50e6ff" /><polygon points="14.42 10.92 12.74 11.91 11.05 10.92 12.74 9.93 14.42 10.92" fill="#c3f1ff" /><polygon points="12.74 11.91 12.74 13.87 11.05 12.88 11.05 10.92 12.74 11.91" fill="#9cebff" /><polygon points="11.05 12.88 12.74 11.9 12.74 13.87 11.05 12.88" fill="#c3f1ff" /><polygon points="14.42 12.88 12.74 11.9 12.74 13.87 14.42 12.88" fill="#9cebff" /><path d="M14.76,17.32c-1-.16-1-.88-1-2h-2c0,1.16,0,1.88-1,2a.59.59,0,0,0-.5.57h5A.59.59,0,0,0,14.76,17.32Z" fill="url(#ab373d88-41af-4fc3-b172-d4489f9107a0)" /></svg>',
5516
+ "a90c553f57031340c6ef44e3773c0a49249f9783eb26d83a6590b95c5370fb04": '<svg id="a9ed4d43-c916-4b9a-b9ca-be76fbdc694c" xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 18 18"><defs><linearGradient id="aaede26b-698f-4a65-b6db-859d207e2da6" x1="8.05" y1="11.32" x2="8.05" y2="1.26" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#0078d4" /><stop offset="0.82" stop-color="#5ea0ef" /></linearGradient><linearGradient id="bc54987f-34ba-4701-8ce4-6eca10aff9e9" x1="8.05" y1="15.21" x2="8.05" y2="11.32" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#1490df" /><stop offset="0.98" stop-color="#1f56a3" /></linearGradient><linearGradient id="a5434fd8-c18c-472c-be91-f2aa070858b7" x1="8.05" y1="7.87" x2="8.05" y2="4.94" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#d2ebff" /><stop offset="1" stop-color="#f0fffd" /></linearGradient></defs><title>Icon-intune-329</title><rect x="0.5" y="1.26" width="15.1" height="10.06" rx="0.5" fill="url(#aaede26b-698f-4a65-b6db-859d207e2da6)" /><rect x="1.34" y="2.1" width="13.42" height="8.39" rx="0.28" fill="#fff" /><path d="M11.08,14.37c-1.5-.23-1.56-1.31-1.55-3h-3c0,1.74-.06,2.82-1.55,3a.87.87,0,0,0-.74.84h7.54A.88.88,0,0,0,11.08,14.37Z" fill="url(#bc54987f-34ba-4701-8ce4-6eca10aff9e9)" /><path d="M17.17,5.91H10.29a2.31,2.31,0,1,0,0,.92H11v9.58a.33.33,0,0,0,.33.33h5.83a.33.33,0,0,0,.33-.33V6.24A.33.33,0,0,0,17.17,5.91Z" fill="#32bedd" /><rect x="11.62" y="6.82" width="5.27" height="8.7" rx="0.12" fill="#fff" /><circle cx="8.05" cy="6.41" r="1.46" opacity="0.9" fill="url(#a5434fd8-c18c-472c-be91-f2aa070858b7)" /><path d="M14.88,10.82,13.76,9.7a.06.06,0,0,0-.1.05v.68a.06.06,0,0,1-.06.06H11v.83H13.6a.06.06,0,0,1,.06.06v.69a.06.06,0,0,0,.1,0L14.88,11A.12.12,0,0,0,14.88,10.82Z" fill="#0078d4" /></svg>',
5178
5517
  "ab242068f3af6c01d88fcaeac7e029bcda39e9b062a415048c6f02f779052b57": '<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 18 18"><defs><linearGradient id="fc9e0ce2-d7de-4412-bda8-f01e2cc4e66a" x1="9" y1="12.48" x2="9" y2="1.147" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#003067" /><stop offset="0.037" stop-color="#00346c" /><stop offset="0.239" stop-color="#004583" /><stop offset="0.456" stop-color="#005194" /><stop offset="0.695" stop-color="#00599e" /><stop offset="1" stop-color="#005ba1" /></linearGradient><linearGradient id="e9e87259-0875-41e6-886b-2024b496a772" x1="9" y1="684.663" x2="9" y2="689.036" gradientTransform="matrix(1, 0, 0, -1, 0, 701.516)" gradientUnits="userSpaceOnUse"><stop offset="0.15" stop-color="#ccc" /><stop offset="1" stop-color="#707070" /></linearGradient><linearGradient id="bf7ae98c-3eed-4cf6-9bb1-28dc4026a25b" x1="0.003" y1="-27.428" x2="0.003" y2="-28.757" gradientTransform="matrix(5, 0, 0, -5, 9.126, -133.758)" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#00aeef" /><stop offset="0.212" stop-color="#0097dc" /><stop offset="0.519" stop-color="#007cc5" /><stop offset="0.792" stop-color="#006cb8" /><stop offset="1" stop-color="#0066b3" /></linearGradient></defs><g id="bc45d939-cf3c-4c56-98de-8197264505ae"><g><rect x="0.5" y="1.147" width="17" height="11.333" rx="0.567" fill="url(#fc9e0ce2-d7de-4412-bda8-f01e2cc4e66a)" /><path d="M12.409,15.909c-1.681-.265-1.747-1.474-1.747-3.429H7.328c0,1.955-.056,3.164-1.737,3.429a.944.944,0,0,0-.841.944h8.5A.944.944,0,0,0,12.409,15.909Z" fill="url(#e9e87259-0875-41e6-886b-2024b496a772)" /><g><path d="M2.427,10.028H9.215l6.643-6.644H2.427v6.644" fill-rule="evenodd" fill="url(#bf7ae98c-3eed-4cf6-9bb1-28dc4026a25b)" /><path d="M10.4,4.713H9.071l.005,3.119L7.921,4.711H6.775L5.79,7.318C5.685,6.654,5,6.426,4.46,6.254c-.357-.114-.735-.283-.731-.469,0-.152.2-.294.6-.273a2.171,2.171,0,0,1,.968.262l.459-.8a3.589,3.589,0,0,0-1.5-.354h0A1.822,1.822,0,0,0,2.931,5.1a1.119,1.119,0,0,0-.316.771,1.036,1.036,0,0,0,.454.923,3.107,3.107,0,0,0,.9.412c.367.113.667.212.663.423a.314.314,0,0,1-.087.206.581.581,0,0,1-.426.134,1.825,1.825,0,0,1-1.1-.313l-.408.811a2.842,2.842,0,0,0,1.444.377h.12a1.8,1.8,0,0,0,1.139-.36l.049-.041L5.316,8.7l1.12,0,.2-.514a2.287,2.287,0,0,0,1.4.006l.14.508,2.008,0,0-1.172h.427c1.033,0,1.644-.526,1.644-1.407,0-.982-.594-1.41-1.857-1.41ZM7.342,7.379a1.2,1.2,0,0,1-.423-.074l.419-1.322h.008l.412,1.326a1.251,1.251,0,0,1-.416.07Zm3.133-.759h-.291V5.554h.291c.389,0,.7.129.7.526s-.31.54-.7.54" fill="#fff" fill-rule="evenodd" /></g></g></g></svg>',
5179
5518
  "b1bdd74c980623b7524b6ef43f9c2f8704ec0ad84bb1ea35b235ee4aadf5c61e": '<svg id="e628f514-cf24-48e8-9bd9-b0847bc224d0" xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 18 18"><defs><linearGradient id="b01f2302-385e-4b49-a7e9-dac023c15293" x1="9" y1="11.84" x2="9" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#0078d4" /><stop offset="0.16" stop-color="#1380da" /><stop offset="0.53" stop-color="#3c91e5" /><stop offset="0.82" stop-color="#559cec" /><stop offset="1" stop-color="#5ea0ef" /></linearGradient><linearGradient id="f7246c3f-62d1-41c6-a3d3-d69183d80ba0" x1="4.62" y1="13.54" x2="13.47" y2="13.54" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#32bedd" /><stop offset="0.06" stop-color="#37c5e3" /><stop offset="0.3" stop-color="#49ddf7" /><stop offset="0.45" stop-color="#50e6ff" /><stop offset="0.55" stop-color="#50e6ff" /><stop offset="0.7" stop-color="#49ddf7" /><stop offset="0.94" stop-color="#37c5e3" /><stop offset="1" stop-color="#32bedd" /></linearGradient></defs><title>Icon-databases-133</title><path d="M17.35,8.13a3.74,3.74,0,0,0-3.25-3.6A4.74,4.74,0,0,0,9.22,0,4.87,4.87,0,0,0,4.58,3.16,4.48,4.48,0,0,0,.65,7.47a4.54,4.54,0,0,0,4.7,4.37h8a1.2,1.2,0,0,0,.2,0A3.81,3.81,0,0,0,17.35,8.13Z" fill="url(#b01f2302-385e-4b49-a7e9-dac023c15293)" /><path d="M9.05,10.49c-2.45,0-4.43-.63-4.43-1.41v7.51c0,.77,2,1.4,4.37,1.41h.06c2.44,0,4.42-.63,4.42-1.41V9.08C13.47,9.86,11.49,10.49,9.05,10.49Z" fill="url(#f7246c3f-62d1-41c6-a3d3-d69183d80ba0)" /><path d="M13.47,9.08c0,.78-2,1.41-4.42,1.41S4.62,9.86,4.62,9.08s2-1.41,4.43-1.41,4.42.63,4.42,1.41" fill="#e8e8e8" /><path d="M12.44,9c0,.49-1.52.9-3.39.9s-3.4-.41-3.4-.9,1.52-.9,3.4-.9,3.39.4,3.39.9" fill="#50e6ff" /><path d="M9.05,9.18a9.13,9.13,0,0,0-2.69.34,9,9,0,0,0,2.69.35,9.09,9.09,0,0,0,2.69-.35A9.23,9.23,0,0,0,9.05,9.18Z" fill="#32bedd" /><path d="M6.29,5,8.88,2.38a.3.3,0,0,1,.43,0L11.9,5a.13.13,0,0,1-.1.23H10.21a.14.14,0,0,0-.14.14V8.58a.1.1,0,0,1-.11.11H8.22a.11.11,0,0,1-.11-.11V5.34A.13.13,0,0,0,8,5.2H6.38A.13.13,0,0,1,6.29,5Z" fill="#f2f2f2" /></svg>',
5180
5519
  "b2e9c9a8b091a0694532257354dea94bb8c65b33876826e44dbc9b2aae01cf17": '<svg id="b9c24df5-e0dd-4838-a385-7c11c2d34304" xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 18 18"><defs><linearGradient id="aa2ee697-e8d1-4da1-a8c5-64c8ebbb74cf" x1="9" y1="13.83" x2="9" y2="1.07" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#0078d4" /><stop offset="0.82" stop-color="#5ea0ef" /></linearGradient></defs><title>Icon-networking-73</title><path d="M18,9.83A4,4,0,0,0,14.49,6,5.1,5.1,0,0,0,9.24,1.07a5.23,5.23,0,0,0-5,3.41A4.83,4.83,0,0,0,0,9.12a4.9,4.9,0,0,0,5.07,4.71l.44,0h8.21a.78.78,0,0,0,.22,0A4.09,4.09,0,0,0,18,9.83Z" fill="url(#aa2ee697-e8d1-4da1-a8c5-64c8ebbb74cf)" /><path id="f0276135-0079-4897-a518-21eb63472c16" d="M6.63,6.82h5.06v7H6.63Z" fill="#f2f2f2" /><path id="e528878d-2ed7-4392-94e6-99c6fc971bcb" d="M12.61,6.37l-3.49-2a.25.25,0,0,0-.31.15s0,.06,0,.08V16.68a.25.25,0,0,0,.24.25h.08l3.49-2.06a.25.25,0,0,0,.17-.23v-8A.26.26,0,0,0,12.61,6.37Z" fill="#50e6ff" /></svg>',
@@ -5259,7 +5598,7 @@ var init_manifest_generated = __esm({
5259
5598
  aws: ["69da81b985927d64", "5282404e5c2d99f3", "173849580e0137b7", "401a550dc39d50cf", "32dd530bf1b2ffda", "9970bc0e154f7fa6", "fd381aeadf455c41", "b2fe0d79a4e5c5b3", "6cc34b07d2641648", "fef6457d55700680", "f492bb7f146528a5"],
5260
5599
  azure: ["57ba8eac0bfb7533", "856438a822c39df9", "2d8d2317e80dc9bd", "c39bff2b4ff90c6e", "f7d2aab6a79e32bf", "37258764cc0b855f", "d83610362ccf5cd7", "22e285c6f3a73de1"],
5261
5600
  gcp: ["a2cb5378fdc60c38"],
5262
- simple: ["942feade1a617706", "064605c4cd54fe1f", "599e4f55f34773c6", "eb01a5aab17c87e3"]
5601
+ simple: ["942feade1a617706", "064605c4cd54fe1f", "599e4f55f34773c6", "89462c0e565c9125"]
5263
5602
  };
5264
5603
  }
5265
5604
  });
@@ -5899,7 +6238,7 @@ function isColorIcon(ref) {
5899
6238
  }
5900
6239
  function iconAliasTarget(ref) {
5901
6240
  if (findIcon(ref) !== null) return null;
5902
- const target = ICON_NAME_ALIASES[ref];
6241
+ const target = ICON_NAME_ALIASES[ref] ?? BRAND_STAND_IN_NAMES[ref];
5903
6242
  return target !== void 0 && findIcon(target) !== null ? target : null;
5904
6243
  }
5905
6244
  function isKnownIcon(ref) {
@@ -26529,8 +26868,13 @@ function brandPhrases() {
26529
26868
  return [...phrases2].map((phrase2) => ({ phrase: phrase2, words: phrase2.split(" ").length, ref, set: "simple", isGeneric: false, isBrand: true }));
26530
26869
  });
26531
26870
  }
26871
+ function standInPhrases() {
26872
+ return BRAND_STAND_INS.flatMap(
26873
+ (brand) => [.../* @__PURE__ */ new Set([brand.slug, ...[brand.title, ...brand.aliases].map(normalizePhrase)])].map((phrase2) => ({ phrase: phrase2, words: phrase2.split(" ").length, ref: brand.glyph, set: "lucide", isGeneric: false, isBrand: true }))
26874
+ );
26875
+ }
26532
26876
  function listProductPhrases() {
26533
- cached2 ??= [...cloudPhrases(genericPhrases()), ...brandPhrases()];
26877
+ cached2 ??= [...cloudPhrases(genericPhrases()), ...brandPhrases(), ...standInPhrases()];
26534
26878
  return cached2;
26535
26879
  }
26536
26880
  function providerOf(ref) {
@@ -121600,6 +121944,10 @@ var init_metrics = __esm({
121600
121944
  blockBranchHeader: 30,
121601
121945
  blockBottomPadding: 10,
121602
121946
  blockRadius: 10,
121947
+ /** Room from the frame's left edge to its operator ("alt", "else"), and the least room after its condition to the right edge. */
121948
+ blockHeaderInset: 12,
121949
+ /** Room between the operator and its condition. */
121950
+ blockKeywordGap: 8,
121603
121951
  lifelineDash: "4 5",
121604
121952
  lifelineOvershoot: 22
121605
121953
  };
@@ -121737,7 +122085,7 @@ function bareGlyphColor(theme, tone) {
121737
122085
  function getTheme(name2) {
121738
122086
  return name2 === "dark" ? DARK_THEME : LIGHT_THEME;
121739
122087
  }
121740
- var THEME_NAMES, PICTURE_SCHEMES, GRAPHIC_CONTRAST, SCHEME_INPUTS, LIGHT_THEME, DARK_THEME, BARE_GLYPH_CONTRAST;
122088
+ var THEME_NAMES, PICTURE_SCHEMES, PICTURE_FILE_SCHEMES, GRAPHIC_CONTRAST, SCHEME_INPUTS, LIGHT_THEME, DARK_THEME, BARE_GLYPH_CONTRAST;
121741
122089
  var init_themes = __esm({
121742
122090
  "../../packages/diagrams/src/theme/themes.ts"() {
121743
122091
  "use strict";
@@ -121746,6 +122094,7 @@ var init_themes = __esm({
121746
122094
  init_palette();
121747
122095
  THEME_NAMES = ["light", "dark"];
121748
122096
  PICTURE_SCHEMES = [...THEME_NAMES, "auto"];
122097
+ PICTURE_FILE_SCHEMES = ["light-and-dark", "auto"];
121749
122098
  GRAPHIC_CONTRAST = 3;
121750
122099
  SCHEME_INPUTS = {
121751
122100
  light: { name: "light", surfaces: LIGHT_SURFACES, tones: LIGHT_TONES, tint: 0.12, pushToward: "#000000" },
@@ -121771,7 +122120,7 @@ function hueDistance(a, b) {
121771
122120
  }
121772
122121
  function fitToScheme(color, scheme) {
121773
122122
  const input2 = SCHEME_INPUTS[scheme];
121774
- return ensureContrast(color, input2.surfaces.surface, GRAPHIC_CONTRAST2, input2.pushToward);
122123
+ return ensureContrast(color, input2.surfaces.surface, GRAPHIC_CONTRAST, input2.pushToward);
121775
122124
  }
121776
122125
  function checkBrand(input2) {
121777
122126
  const issues = [];
@@ -121836,7 +122185,7 @@ function brandTheme(scheme, brand) {
121836
122185
  const input2 = SCHEME_INPUTS[scheme];
121837
122186
  const wash = NEUTRAL_WASH[scheme];
121838
122187
  const surfaces = input2.surfaces;
121839
- const edge = ensureContrast(mix(brand.primary, surfaces.edge, wash.edge), surfaces.surface, GRAPHIC_CONTRAST2, input2.pushToward);
122188
+ const edge = ensureContrast(mix(brand.primary, surfaces.edge, wash.edge), surfaces.surface, GRAPHIC_CONTRAST, input2.pushToward);
121840
122189
  return buildTheme({
121841
122190
  ...input2,
121842
122191
  tones: brandTones(scheme, brand),
@@ -121860,7 +122209,7 @@ function themeFor(scheme, brand) {
121860
122209
  CACHE.set(key, theme);
121861
122210
  return theme;
121862
122211
  }
121863
- var BRAND_ROLES, HUE_STEP, TONE_OF_ROLE, STATUS_HUES, STATUS_HUE_DISTANCE, STATUS_SATURATION, DISTINCT_CONTRAST, GRAPHIC_CONTRAST2, NEUTRAL_WASH, CACHE, CACHE_LIMIT;
122212
+ var BRAND_ROLES, HUE_STEP, TONE_OF_ROLE, STATUS_HUES, STATUS_HUE_DISTANCE, STATUS_SATURATION, DISTINCT_CONTRAST, NEUTRAL_WASH, CACHE, CACHE_LIMIT;
121864
122213
  var init_brand = __esm({
121865
122214
  "../../packages/diagrams/src/theme/brand.ts"() {
121866
122215
  "use strict";
@@ -121876,7 +122225,6 @@ var init_brand = __esm({
121876
122225
  STATUS_HUE_DISTANCE = 16;
121877
122226
  STATUS_SATURATION = 0.45;
121878
122227
  DISTINCT_CONTRAST = 1.15;
121879
- GRAPHIC_CONTRAST2 = 3;
121880
122228
  NEUTRAL_WASH = {
121881
122229
  light: { group: 0.035, border: 0.1, edge: 0.3 },
121882
122230
  dark: { group: 0.05, border: 0.12, edge: 0.3 }
@@ -123115,9 +123463,9 @@ function sceneOf(shapes2, input2) {
123115
123463
  const source = diagram.edges[Number(route.id.slice(1))];
123116
123464
  return source === void 0 ? [] : [{ id: route.id, from: source.from, to: source.to, points: route.points, label: route.label?.rect ?? null }];
123117
123465
  });
123118
- const bounds = boundsOf([...shapes2.nodes.map((node3) => node3.rect), ...shapes2.groups.map((group2) => group2.rect), ...shapes2.overlays.map((overlay) => overlay.rect)]) ?? { x: 0, y: 0, width: 0, height: 0 };
123466
+ const bounds2 = boundsOf([...shapes2.nodes.map((node3) => node3.rect), ...shapes2.groups.map((group2) => group2.rect), ...shapes2.overlays.map((overlay) => overlay.rect)]) ?? { x: 0, y: 0, width: 0, height: 0 };
123119
123467
  const finish = (points, label, boxes2) => giveEndRoom(points, EDGE_METRICS.endRun, boxes2, label === null ? null : centerOf(label));
123120
- const scene = { isVertical: direction === "down" || direction === "up", alongSign: ALONG_SIGN[direction], nodes, frames, edges, bounds, finish };
123468
+ const scene = { isVertical: direction === "down" || direction === "up", alongSign: ALONG_SIGN[direction], nodes, frames, edges, bounds: bounds2, finish };
123121
123469
  return scene;
123122
123470
  }
123123
123471
  function balanceFlow(shapes2, input2) {
@@ -124722,6 +125070,235 @@ var init_suggest = __esm({
124722
125070
  }
124723
125071
  });
124724
125072
 
125073
+ // ../../packages/diagrams/src/parse/statement-helpers.ts
125074
+ function rejectTrailing(cursor, ctx, hint2) {
125075
+ const span = cursor.remainingSpan();
125076
+ if (span === null) return;
125077
+ ctx.report.push(errorAt(DIAGNOSTIC_CODES.syntax, "Unexpected text after the end of the statement", span, hint2));
125078
+ }
125079
+ function declareId(cursor, ctx, kind, line3) {
125080
+ const token = cursor.next();
125081
+ if (token?.kind !== "word") {
125082
+ ctx.report.push(
125083
+ errorAt(DIAGNOSTIC_CODES.syntax, `Expected an id after "${kind}"`, token ?? cursor.endPosition(line3), `Write: ${kind} my-id ...`)
125084
+ );
125085
+ return null;
125086
+ }
125087
+ if (!isValidId(token.text)) {
125088
+ ctx.report.push(
125089
+ errorAt(DIAGNOSTIC_CODES.syntax, `"${token.text}" is not a valid id`, token, 'Ids start with a letter or "_" and use letters, digits, "_" and "-".')
125090
+ );
125091
+ return null;
125092
+ }
125093
+ const previous = ctx.declared.get(token.text);
125094
+ if (previous !== void 0) {
125095
+ ctx.report.push(
125096
+ errorAt(DIAGNOSTIC_CODES.duplicateId, `Id "${token.text}" is already used by a ${previous.kind} on line ${previous.line}`, token, "Pick a different id.")
125097
+ );
125098
+ return null;
125099
+ }
125100
+ ctx.declared.set(token.text, { kind, line: line3 });
125101
+ return token;
125102
+ }
125103
+ function readLabel(cursor, ctx, line3, what, form) {
125104
+ const token = cursor.peek();
125105
+ if (token?.kind === "string") {
125106
+ cursor.next();
125107
+ return token.text;
125108
+ }
125109
+ if (!(token?.kind === "word" && cursor.peek(1)?.kind === "equals") && !(token?.kind === "lbrace")) cursor.next();
125110
+ const hint2 = `Labels are always in double quotes, for example "Auth server".${form === void 0 ? "" : ` The statement is: ${form}`}`;
125111
+ ctx.report.push(errorAt(DIAGNOSTIC_CODES.syntax, `Expected a quoted ${what}`, token ?? cursor.endPosition(line3), hint2));
125112
+ return null;
125113
+ }
125114
+ function resolveTone(option, fallback, ctx) {
125115
+ if (option === void 0) return fallback;
125116
+ const tone = TONES.find((candidate2) => candidate2 === option.value);
125117
+ if (tone !== void 0) return tone;
125118
+ ctx.report.push(errorAt(DIAGNOSTIC_CODES.unknownTone, `Unknown tone "${option.value}"`, option.valueToken, didYouMean(option.value, TONES)));
125119
+ return fallback;
125120
+ }
125121
+ function resolveIcon(option, fallback, _ctx) {
125122
+ if (option === void 0) return fallback;
125123
+ if (option.value === "none") return null;
125124
+ if (isKnownIcon(option.value)) return option.value;
125125
+ return iconAliasTarget(option.value) ?? fallback;
125126
+ }
125127
+ var init_statement_helpers = __esm({
125128
+ "../../packages/diagrams/src/parse/statement-helpers.ts"() {
125129
+ "use strict";
125130
+ init_constants();
125131
+ init_core();
125132
+ init_icons();
125133
+ init_suggest();
125134
+ }
125135
+ });
125136
+
125137
+ // ../../packages/diagrams/src/parse/lexer.ts
125138
+ function readWord(text3, start2) {
125139
+ let end = start2;
125140
+ while (end < text3.length) {
125141
+ const char = text3.charAt(end);
125142
+ const next = text3.charAt(end + 1);
125143
+ if (isWordPart(char)) end += 1;
125144
+ else if (char === "-" && isWordPart(next)) end += 1;
125145
+ else if (char === "." && isWordPart(next)) end += 1;
125146
+ else if (char === ":" && /[A-Za-z_]/.test(next)) end += 1;
125147
+ else break;
125148
+ }
125149
+ return text3.slice(start2, end);
125150
+ }
125151
+ function readString(text3, start2) {
125152
+ let value = "";
125153
+ let index2 = start2 + 1;
125154
+ while (index2 < text3.length) {
125155
+ const char = text3.charAt(index2);
125156
+ if (char === '"') return { value, end: index2 + 1 };
125157
+ if (char === "\\") {
125158
+ const escaped = STRING_ESCAPES[text3.charAt(index2 + 1)];
125159
+ value += escaped ?? text3.charAt(index2 + 1);
125160
+ index2 += 2;
125161
+ } else {
125162
+ value += char;
125163
+ index2 += 1;
125164
+ }
125165
+ }
125166
+ return null;
125167
+ }
125168
+ function matchArrow(text3, index2) {
125169
+ return ARROW_TOKENS.find((arrow) => text3.startsWith(arrow, index2)) ?? null;
125170
+ }
125171
+ function lexLine(text3, line3, diagnostics) {
125172
+ const tokens = [];
125173
+ let index2 = 0;
125174
+ while (index2 < text3.length) {
125175
+ const char = text3.charAt(index2);
125176
+ const column = index2 + 1;
125177
+ if (char === " " || char === " " || char === "\r") {
125178
+ index2 += 1;
125179
+ } else if (char === "#") {
125180
+ break;
125181
+ } else if (char === '"') {
125182
+ const read = readString(text3, index2);
125183
+ if (read === null) {
125184
+ diagnostics.push(
125185
+ errorAt(
125186
+ DIAGNOSTIC_CODES.unterminatedString,
125187
+ "String is missing its closing quote",
125188
+ { line: line3, column, length: text3.length - index2 },
125189
+ "Close the label with a double quote on the same line."
125190
+ )
125191
+ );
125192
+ break;
125193
+ }
125194
+ tokens.push({ kind: "string", text: read.value, line: line3, column, length: read.end - index2 });
125195
+ index2 = read.end;
125196
+ } else if (matchArrow(text3, index2) !== null) {
125197
+ const arrow = matchArrow(text3, index2);
125198
+ tokens.push({ kind: "arrow", text: arrow, line: line3, column, length: arrow.length });
125199
+ index2 += arrow.length;
125200
+ } else if (char === ":") {
125201
+ tokens.push({ kind: "colon", line: line3, column, length: 1 });
125202
+ index2 += 1;
125203
+ } else if (char === "=") {
125204
+ tokens.push({ kind: "equals", line: line3, column, length: 1 });
125205
+ index2 += 1;
125206
+ } else if (char === ",") {
125207
+ tokens.push({ kind: "comma", line: line3, column, length: 1 });
125208
+ index2 += 1;
125209
+ } else if (char === "{") {
125210
+ tokens.push({ kind: "lbrace", line: line3, column, length: 1 });
125211
+ index2 += 1;
125212
+ } else if (char === "}") {
125213
+ tokens.push({ kind: "rbrace", line: line3, column, length: 1 });
125214
+ index2 += 1;
125215
+ } else if (isWordStart(char)) {
125216
+ const word2 = readWord(text3, index2);
125217
+ tokens.push({ kind: "word", text: word2, line: line3, column, length: word2.length });
125218
+ index2 += word2.length;
125219
+ } else {
125220
+ diagnostics.push(errorAt(DIAGNOSTIC_CODES.syntax, `Unexpected character "${char}"`, { line: line3, column, length: 1 }, unexpectedCharacterHint(char, tokens[tokens.length - 1], text3[index2 + 1])));
125221
+ index2 += 1;
125222
+ }
125223
+ }
125224
+ return tokens;
125225
+ }
125226
+ function unexpectedCharacterHint(char, previous, following) {
125227
+ if (char === "\\" && following === '"') return 'The source has \\" where a plain " belongs: a label is written "Label" in the source. In JSON, escape that quote once, as \\", never as \\\\\\".';
125228
+ if (char === "\\" && following === "u" || char === "-" && following === "\\") return "The source has a JSON escape written out, such as \\u003e: write the character it stands for instead (\\u003e is >, \\u003c is <, \\u0026 is &), so an arrow is -> and not -\\u003e.";
125229
+ if (char === "\\" && following === "n") return "The source has a written \\n where a line should end: each statement goes on its own line. In JSON, write a line break inside the string as \\n, not \\\\n.";
125230
+ if (previous?.kind === "arrow" || char === ">" || char === "<") return ARROW_HINT;
125231
+ return 'Labels go in double quotes; ids use letters, digits, "_" and "-".';
125232
+ }
125233
+ function lex(source) {
125234
+ const diagnostics = [];
125235
+ const lines = [];
125236
+ source.split("\n").forEach((text3, offset) => {
125237
+ const line3 = offset + 1;
125238
+ const tokens = lexLine(text3, line3, diagnostics);
125239
+ if (tokens.length > 0) lines.push({ line: line3, tokens });
125240
+ });
125241
+ return { lines, diagnostics };
125242
+ }
125243
+ var STRING_ESCAPES, isWordStart, isWordPart, ARROW_HINT;
125244
+ var init_lexer = __esm({
125245
+ "../../packages/diagrams/src/parse/lexer.ts"() {
125246
+ "use strict";
125247
+ init_constants();
125248
+ init_core();
125249
+ STRING_ESCAPES = { '"': '"', "\\": "\\", n: "\n", t: " " };
125250
+ isWordStart = (char) => /[A-Za-z0-9_]/.test(char);
125251
+ isWordPart = (char) => /[A-Za-z0-9_]/.test(char);
125252
+ ARROW_HINT = "An arrow is one of ->, -->, ..>, <->, <-->, or --, written from the sender to the receiver (a -> b). Mermaid's ->> and -->> are -> and --> here, and a reply is b --> a, never a <-- b.";
125253
+ }
125254
+ });
125255
+
125256
+ // ../../packages/diagrams/src/parse/icon-alias-notes.ts
125257
+ function iconValues(tokens) {
125258
+ const values = [];
125259
+ for (let index2 = 0; index2 + 2 < tokens.length; index2 += 1) {
125260
+ const key = tokens[index2];
125261
+ if (key?.kind !== "word" || key.text !== "icon" && key.text !== "stack" || tokens[index2 + 1]?.kind !== "equals") continue;
125262
+ const option = key.text;
125263
+ let at3 = index2 + 2;
125264
+ for (let value = tokens[at3]; isValue(value); value = tokens[at3]) {
125265
+ values.push({ ...value, option });
125266
+ if (key.text !== "stack" || tokens[at3 + 1]?.kind !== "comma") break;
125267
+ at3 += 2;
125268
+ }
125269
+ }
125270
+ return values;
125271
+ }
125272
+ function iconAliasNotes(source) {
125273
+ const notes = [];
125274
+ for (const line3 of lex(source).lines) {
125275
+ for (const value of iconValues(line3.tokens)) {
125276
+ const target = iconAliasTarget(value.text);
125277
+ if (target === null) continue;
125278
+ notes.push({
125279
+ code: ICON_ALIAS_NOTE,
125280
+ severity: "info",
125281
+ message: `"${value.text}" is not a bundled icon name, so ${target} was drawn`,
125282
+ line: value.line,
125283
+ column: value.column,
125284
+ length: value.length,
125285
+ hint: `Write ${target} to say so in the source.`
125286
+ });
125287
+ }
125288
+ }
125289
+ return notes;
125290
+ }
125291
+ var ICON_ALIAS_NOTE, isValue;
125292
+ var init_icon_alias_notes = __esm({
125293
+ "../../packages/diagrams/src/parse/icon-alias-notes.ts"() {
125294
+ "use strict";
125295
+ init_icons();
125296
+ init_lexer();
125297
+ ICON_ALIAS_NOTE = "I122";
125298
+ isValue = (token) => token?.kind === "word" || token?.kind === "string";
125299
+ }
125300
+ });
125301
+
124725
125302
  // ../../packages/diagrams/src/parse/icon-hint.ts
124726
125303
  function providerSetFor(guess) {
124727
125304
  const lowered = guess.toLowerCase();
@@ -124790,70 +125367,47 @@ var init_icon_hint = __esm({
124790
125367
  }
124791
125368
  });
124792
125369
 
124793
- // ../../packages/diagrams/src/parse/statement-helpers.ts
124794
- function rejectTrailing(cursor, ctx, hint2) {
124795
- const span = cursor.remainingSpan();
124796
- if (span === null) return;
124797
- ctx.report.push(errorAt(DIAGNOSTIC_CODES.syntax, "Unexpected text after the end of the statement", span, hint2));
125370
+ // ../../packages/diagrams/src/parse/unknown-icons.ts
125371
+ function isUnknownIcon(value) {
125372
+ return value !== "none" && !isKnownIcon(value) && iconAliasTarget(value) === null;
124798
125373
  }
124799
- function declareId(cursor, ctx, kind, line3) {
124800
- const token = cursor.next();
124801
- if (token?.kind !== "word") {
124802
- ctx.report.push(
124803
- errorAt(DIAGNOSTIC_CODES.syntax, `Expected an id after "${kind}"`, token ?? cursor.endPosition(line3), `Write: ${kind} my-id ...`)
124804
- );
124805
- return null;
124806
- }
124807
- if (!isValidId(token.text)) {
124808
- ctx.report.push(
124809
- errorAt(DIAGNOSTIC_CODES.syntax, `"${token.text}" is not a valid id`, token, 'Ids start with a letter or "_" and use letters, digits, "_" and "-".')
124810
- );
124811
- return null;
124812
- }
124813
- const previous = ctx.declared.get(token.text);
124814
- if (previous !== void 0) {
124815
- ctx.report.push(
124816
- errorAt(DIAGNOSTIC_CODES.duplicateId, `Id "${token.text}" is already used by a ${previous.kind} on line ${previous.line}`, token, "Pick a different id.")
124817
- );
124818
- return null;
124819
- }
124820
- ctx.declared.set(token.text, { kind, line: line3 });
124821
- return token;
124822
- }
124823
- function readLabel(cursor, ctx, line3, what) {
124824
- const token = cursor.next();
124825
- if (token?.kind === "string") return token.text;
124826
- ctx.report.push(
124827
- errorAt(DIAGNOSTIC_CODES.syntax, `Expected a quoted ${what}`, token ?? cursor.endPosition(line3), 'Labels are always in double quotes, for example "Auth server".')
124828
- );
124829
- return null;
125374
+ function closestIcons(value) {
125375
+ const words2 = value.replace(/[:\-_]+/g, " ");
125376
+ const name2 = value.includes(":") ? value.slice(value.indexOf(":") + 1).replace(/[-_]+/g, " ") : words2;
125377
+ const found = [...searchIcons(name2, CLOSEST_SHOWN), ...searchIcons(words2, CLOSEST_SHOWN)];
125378
+ return [...new Set(found)].slice(0, CLOSEST_SHOWN);
124830
125379
  }
124831
- function resolveTone(option, fallback, ctx) {
124832
- if (option === void 0) return fallback;
124833
- const tone = TONES.find((candidate2) => candidate2 === option.value);
124834
- if (tone !== void 0) return tone;
124835
- ctx.report.push(errorAt(DIAGNOSTIC_CODES.unknownTone, `Unknown tone "${option.value}"`, option.valueToken, didYouMean(option.value, TONES)));
124836
- return fallback;
125380
+ function unknownIconHint(value, option = "icon") {
125381
+ const near3 = iconHint(value);
125382
+ const others = closestIcons(value).filter((ref) => !near3.includes(`"${ref}"`));
125383
+ const closest = others.length === 0 ? "" : ` Closest icons: ${others.join(", ")}.`;
125384
+ return `${near3}${closest} ${DRAWN_INSTEAD[option].hint}`;
124837
125385
  }
124838
- function resolveIcon(option, fallback, ctx) {
124839
- if (option === void 0) return fallback;
124840
- if (option.value === "none") return null;
124841
- if (isKnownIcon(option.value)) return option.value;
124842
- const alias = iconAliasTarget(option.value);
124843
- if (alias !== null) return alias;
124844
- ctx.report.push(
124845
- errorAt(DIAGNOSTIC_CODES.unknownIcon, `Unknown icon "${option.value}"`, option.valueToken, iconHint(option.value))
124846
- );
124847
- return fallback;
125386
+ function unknownIconWarnings(source) {
125387
+ const warnings = [];
125388
+ for (const line3 of lex(source).lines) {
125389
+ for (const value of iconValues(line3.tokens)) {
125390
+ if (!isUnknownIcon(value.text)) continue;
125391
+ const at3 = { line: value.line, column: value.column, length: value.length };
125392
+ warnings.push(warningAt(DIAGNOSTIC_CODES.unknownIcon, `Unknown icon "${value.text}", ${DRAWN_INSTEAD[value.option].message}`, at3, unknownIconHint(value.text, value.option)));
125393
+ }
125394
+ }
125395
+ return warnings;
124848
125396
  }
124849
- var init_statement_helpers = __esm({
124850
- "../../packages/diagrams/src/parse/statement-helpers.ts"() {
125397
+ var CLOSEST_SHOWN, DRAWN_INSTEAD;
125398
+ var init_unknown_icons = __esm({
125399
+ "../../packages/diagrams/src/parse/unknown-icons.ts"() {
124851
125400
  "use strict";
124852
- init_constants();
124853
125401
  init_core();
124854
125402
  init_icons();
125403
+ init_icon_alias_notes();
124855
125404
  init_icon_hint();
124856
- init_suggest();
125405
+ init_lexer();
125406
+ CLOSEST_SHOWN = 3;
125407
+ DRAWN_INSTEAD = {
125408
+ icon: { message: "so the item draws its default icon", hint: "Meanwhile the item draws its default icon (the one its label names, else its type's); icon=none keeps it plain." },
125409
+ stack: { message: "so the mark is left out", hint: "Meanwhile the mark is left out and the node draws without it." }
125410
+ };
124857
125411
  }
124858
125412
  });
124859
125413
 
@@ -124890,7 +125444,7 @@ function brandBeforeSuffix(normalized) {
124890
125444
  const name2 = words2.slice(0, -1).join(" ");
124891
125445
  if (PLAIN_WORD_NAMES.has(name2)) return null;
124892
125446
  const brand = iconNamedBy(name2, null);
124893
- return brand !== null && brand.startsWith("simple:") ? brand : null;
125447
+ return brand !== null && (brand.startsWith("simple:") || brand.startsWith("lucide:")) ? brand : null;
124894
125448
  }
124895
125449
  function roleIconFor(text3) {
124896
125450
  const words2 = normalizePhrase(text3).split(" ");
@@ -124924,8 +125478,9 @@ function iconsAreOff(ctx) {
124924
125478
  return (ctx.iconMode ?? DEFAULT_ICON_MODE) === "off";
124925
125479
  }
124926
125480
  function resolveAutoIcon(option, fallback, ctx, ask) {
124927
- if (option !== void 0 || iconsAreOff(ctx)) return resolveIcon(option, fallback, ctx);
124928
- return autoIconFor(ask) ?? fallback;
125481
+ if (iconsAreOff(ctx)) return resolveIcon(option, fallback, ctx);
125482
+ if (option === void 0 || isUnknownIcon(option.value)) return autoIconFor(ask) ?? fallback;
125483
+ return resolveIcon(option, fallback, ctx);
124929
125484
  }
124930
125485
  var doubtful;
124931
125486
  var init_auto_icon = __esm({
@@ -124936,6 +125491,7 @@ var init_auto_icon = __esm({
124936
125491
  init_icons();
124937
125492
  init_suggest_icons();
124938
125493
  init_statement_helpers();
125494
+ init_unknown_icons();
124939
125495
  }
124940
125496
  });
124941
125497
 
@@ -129029,30 +129585,29 @@ function paintNote(note, theme) {
129029
129585
  ]);
129030
129586
  }
129031
129587
  function paintHeader2(keyword, label, x, bandTop, bandHeight, theme) {
129032
- const chipWidth2 = measureRole(keyword, "groupLabel") + CHIP_PADDING * 2;
129033
- const chipY = bandTop + (bandHeight - CHIP_HEIGHT) / 2;
129034
- const textTop4 = chipY + (CHIP_HEIGHT - TYPE_ROLES.groupLabel.lineHeight) / 2;
129035
- return [
129036
- el("rect", { x, y: chipY, width: chipWidth2, height: CHIP_HEIGHT, rx: CHIP_RADIUS, fill: theme.surfaceGroup, stroke: theme.borderGroup, "stroke-width": 1 }),
129037
- paintTextBlock({ x: x + CHIP_PADDING, top: textTop4, lines: [keyword], role: "groupLabel", color: theme.ink }),
129038
- paintTextBlock({ x: x + chipWidth2 + HEADER_TEXT_GAP, top: textTop4, lines: [label], role: "edgeLabel", color: theme.inkSecondary })
129039
- ];
129588
+ const textTop4 = bandTop + (bandHeight - TYPE_ROLES.groupLabel.lineHeight) / 2;
129589
+ const parts = [paintTextBlock({ x, top: textTop4, lines: [keyword], role: "groupLabel", color: theme.inkSecondary })];
129590
+ if (label !== "") {
129591
+ const labelX = x + measureRole(keyword, "groupLabel") + SEQUENCE_METRICS.blockKeywordGap;
129592
+ parts.push(paintTextBlock({ x: labelX, top: textTop4, lines: [label], role: "edgeLabel", color: theme.inkSecondary }));
129593
+ }
129594
+ return parts;
129040
129595
  }
129041
129596
  function paintBlock(block, theme) {
129042
129597
  const { x, y, width, height } = block.rect;
129043
129598
  const parts = [
129044
129599
  el("rect", { x, y, width, height, rx: SEQUENCE_METRICS.blockRadius, fill: "none", stroke: theme.borderGroup, "stroke-width": 1 }),
129045
- ...paintHeader2(block.blockType, block.label, x + HEADER_LEFT, y, SEQUENCE_METRICS.blockHeader, theme)
129600
+ ...paintHeader2(block.blockType, block.label, x + SEQUENCE_METRICS.blockHeaderInset, y, SEQUENCE_METRICS.blockHeader, theme)
129046
129601
  ];
129047
129602
  for (const divider of block.dividers) {
129048
129603
  parts.push(
129049
129604
  el("line", { x1: x, y1: divider.y, x2: x + width, y2: divider.y, stroke: theme.borderGroup, "stroke-width": 1, "stroke-dasharray": "5 4" }),
129050
- ...paintHeader2(divider.keyword, divider.label, x + HEADER_LEFT, divider.y, SEQUENCE_METRICS.blockBranchHeader, theme)
129605
+ ...paintHeader2(divider.keyword, divider.label, x + SEQUENCE_METRICS.blockHeaderInset, divider.y, SEQUENCE_METRICS.blockBranchHeader, theme)
129051
129606
  );
129052
129607
  }
129053
129608
  return el("g", { "data-block": block.blockType }, parts);
129054
129609
  }
129055
- var NOTE_FILL_TINT, NOTE_BORDER_TINT, CHIP_HEIGHT, CHIP_PADDING, CHIP_RADIUS, HEADER_TEXT_GAP, HEADER_LEFT;
129610
+ var NOTE_FILL_TINT, NOTE_BORDER_TINT;
129056
129611
  var init_paint_parts = __esm({
129057
129612
  "../../packages/diagrams/src/render/sequence/paint-parts.ts"() {
129058
129613
  "use strict";
@@ -129061,11 +129616,6 @@ var init_paint_parts = __esm({
129061
129616
  init_svg2();
129062
129617
  NOTE_FILL_TINT = 0.12;
129063
129618
  NOTE_BORDER_TINT = 0.5;
129064
- CHIP_HEIGHT = 20;
129065
- CHIP_PADDING = 8;
129066
- CHIP_RADIUS = 6;
129067
- HEADER_TEXT_GAP = 10;
129068
- HEADER_LEFT = 12;
129069
129619
  }
129070
129620
  });
129071
129621
 
@@ -130297,9 +130847,8 @@ function resolveStack(option, ctx, canCarry) {
130297
130847
  const marks = [];
130298
130848
  for (const { text: written3, token } of optionValues(option)) {
130299
130849
  const text3 = iconAliasTarget(written3) ?? written3;
130300
- if (!isKnownIcon(text3)) {
130301
- ctx.report.push(errorAt(DIAGNOSTIC_CODES.unknownIcon, `Unknown icon "${text3}"`, token, iconHint(text3)));
130302
- } else if (marks.includes(text3)) {
130850
+ if (!isKnownIcon(text3)) continue;
130851
+ if (marks.includes(text3)) {
130303
130852
  ctx.report.push(errorAt(DIAGNOSTIC_CODES.badOptionValue, `The mark "${text3}" is listed twice`, token, "List each technology once."));
130304
130853
  } else if (marks.length >= STACK_LIMIT) {
130305
130854
  ctx.report.push(errorAt(DIAGNOSTIC_CODES.badOptionValue, `A node carries at most ${STACK_LIMIT} marks in stack=`, token, `Keep the ${STACK_LIMIT} that matter, or name the others in sub=.`));
@@ -130315,7 +130864,6 @@ var init_stack_option = __esm({
130315
130864
  init_constants();
130316
130865
  init_core();
130317
130866
  init_icons();
130318
- init_icon_hint();
130319
130867
  init_options();
130320
130868
  }
130321
130869
  });
@@ -130370,7 +130918,7 @@ function parseNodeStatement(cursor, state, line3, group2) {
130370
130918
  state.report.push(errorAt(DIAGNOSTIC_CODES.unknownNodeType, `Unknown node type "${typeToken.text}"`, typeToken, didYouMean(typeToken.text, FLOW_NODE_TYPES)));
130371
130919
  }
130372
130920
  const labelToken = cursor.peek();
130373
- const label = readLabel(cursor, state, line3, "label");
130921
+ const label = readLabel(cursor, state, line3, "label", 'node <id> <type> "Label" icon=<set:name>.');
130374
130922
  const options3 = readOptions(cursor, NODE_OPTIONS, state.report, { lists: ["stack"] });
130375
130923
  rejectTrailing(cursor, state, 'A node is: node id type "Label" sub="..." icon=lucide:name tone=blue stack=simple:angular,simple:typescript change=update');
130376
130924
  if (id === null || type === void 0 || label === null) return;
@@ -130411,7 +130959,7 @@ function parseGroupStatement(cursor, state, line3, parent) {
130411
130959
  cursor.next();
130412
130960
  const id = declareId(cursor, state, "group", line3);
130413
130961
  const labelToken = cursor.peek();
130414
- const label = readLabel(cursor, state, line3, "label");
130962
+ const label = readLabel(cursor, state, line3, "label", 'group <id> "Label" type=<group type> {, then its nodes, then } on its own line.');
130415
130963
  const options3 = readOptions(cursor, GROUP_OPTIONS, state.report, { lists: ["stack"], moved: MOVED_GROUP_OPTIONS });
130416
130964
  const brace = cursor.next();
130417
130965
  if (brace?.kind !== "lbrace") {
@@ -130605,7 +131153,7 @@ function dispatchStatement(line3, state, scopes) {
130605
131153
  DIAGNOSTIC_CODES.unknownStatement,
130606
131154
  `Unknown statement "${first.text}"`,
130607
131155
  first,
130608
- `${didYouMean(first.text, STATEMENT_KEYWORDS2)} Edges look like: from -> to : "label"`
131156
+ first.text === "flow" ? 'The header is one line, the first: put the title and every header option on it together, such as flow "Checkout" direction=right.' : first.text === "title" ? `There is no title statement: the title is the quoted text after the kind on the first line, such as flow "Checkout".` : line3.tokens[1]?.kind === "equals" ? `An option such as ${first.text}= goes at the end of the line of the node or edge it sets, not on a line of its own: node cdn service "CloudFront" ${first.text}=...` : FLOW_NODE_TYPES.includes(first.text) ? `A box is declared with node and its type comes after the id: node <id> ${first.text} "Label". Edges look like: from -> to : "label"` : `${didYouMean(first.text, STATEMENT_KEYWORDS2)} Edges look like: from -> to : "label"`
130609
131157
  )
130610
131158
  );
130611
131159
  } else {
@@ -131152,16 +131700,26 @@ function shortenedIds3(diagram) {
131152
131700
  const groups = diagram.groups.filter((group2) => sizeGroupTab(group2).isShortened).map((group2) => group2.id);
131153
131701
  return [...nodes, ...groups];
131154
131702
  }
131703
+ function widthHint(diagram) {
131704
+ const counts = /* @__PURE__ */ new Map();
131705
+ for (const node3 of diagram.nodes) if (node3.group !== null) counts.set(node3.group, (counts.get(node3.group) ?? 0) + 1);
131706
+ const [biggest] = [...counts].sort((a, b) => b[1] - a[1] || a[0].localeCompare(b[0]));
131707
+ const split = biggest !== void 0 && biggest[1] >= SPLIT_GROUP_NODES ? `split group ${biggest[0]} (${biggest[1]} nodes) into its own diagram` : "split the diagram in two along a group";
131708
+ const sideways = diagram.direction === "right" || diagram.direction === "left";
131709
+ const fix = sideways ? `Add direction=down to the header line so the diagram grows downwards, ${split}, or shorten labels.` : `It is already as narrow as the layout can draw it, so ${split}, or shorten the longest labels.`;
131710
+ return `${fix} On a page wider than ${CANVAS_METRICS.targetWidth}px it draws at full size, so its text stays 12px there.`;
131711
+ }
131155
131712
  function lintFlow(diagram, measure) {
131156
131713
  const general = present([
131157
131714
  densityWarning3(diagram),
131158
131715
  numberedWarning(diagram),
131159
131716
  orphanWarning3(diagram),
131160
131717
  shortenedWarning(shortenedIds3(diagram)),
131161
- widthWarning(measure.size, "Use direction=down, shorten labels, or split the diagram.")
131718
+ widthWarning(measure.size, widthHint(diagram))
131162
131719
  ]);
131163
131720
  return [...general, ...overlayWarnings(diagram, measure.overlayCovers), ...suggestGroupTypes(diagram), ...suggestIcons(diagram), ...suggestLineRoles(diagram)];
131164
131721
  }
131722
+ var SPLIT_GROUP_NODES;
131165
131723
  var init_lint3 = __esm({
131166
131724
  "../../packages/diagrams/src/kinds/flow/lint.ts"() {
131167
131725
  "use strict";
@@ -131175,6 +131733,8 @@ var init_lint3 = __esm({
131175
131733
  init_suggest_group_types();
131176
131734
  init_suggest_icons();
131177
131735
  init_suggest_line_roles();
131736
+ init_theme();
131737
+ SPLIT_GROUP_NODES = 4;
131178
131738
  }
131179
131739
  });
131180
131740
 
@@ -135852,14 +136412,14 @@ function cutNames(diagram) {
135852
136412
  }
135853
136413
  function lintGit(diagram, measure) {
135854
136414
  const history = buildHistory(diagram);
135855
- const widthHint = diagram.direction === "down" ? "Shorten the commit messages and branch names, or split the history into parts." : "Set direction=down, which grows downward instead of sideways, shorten the commit messages, or split the history into parts.";
136415
+ const widthHint2 = diagram.direction === "down" ? "Shorten the commit messages and branch names, or split the history into parts." : "Set direction=down, which grows downward instead of sideways, shorten the commit messages, or split the history into parts.";
135856
136416
  return [
135857
136417
  ...redundantMerges(diagram),
135858
136418
  ...emptyBranches(diagram, history.commitsByBranch),
135859
136419
  ...repeatedTags(diagram),
135860
136420
  ...longLinks(diagram),
135861
136421
  ...densityWarnings(diagram),
135862
- ...present([shortenedWarning(cutNames(diagram)), widthWarning(measure.size, widthHint)])
136422
+ ...present([shortenedWarning(cutNames(diagram)), widthWarning(measure.size, widthHint2)])
135863
136423
  ];
135864
136424
  }
135865
136425
  var init_lint5 = __esm({
@@ -138746,19 +139306,19 @@ function separatePorts(plans) {
138746
139306
  if (!moved3) return;
138747
139307
  }
138748
139308
  }
138749
- function placeRuns(plan, bounds) {
139309
+ function placeRuns(plan, bounds2) {
138750
139310
  const runs = runsOf3(plan);
138751
139311
  const length = (run3) => run3 === void 0 ? 0 : Math.abs(run3.a - run3.b);
138752
139312
  plan.labelLeg = length(runs[0]) > length(runs[1]) ? 0 : runs.length - 1;
138753
139313
  const labelRun = runs[plan.labelLeg];
138754
139314
  const half = (plan.label?.width ?? 0) / 2;
138755
- plan.labelCenter = clamp4((labelRun.a + labelRun.b) / 2, bounds.left + half + 8, bounds.right - half - 8);
139315
+ plan.labelCenter = clamp4((labelRun.a + labelRun.b) / 2, bounds2.left + half + 8, bounds2.right - half - 8);
138756
139316
  plan.legs = runs.map((run3, position) => {
138757
139317
  const reach2 = position === plan.labelLeg && plan.label !== null ? [plan.labelCenter - half - 6, plan.labelCenter + half + 6] : [];
138758
139318
  return { band: run3.band, use: useBand(run3.band, Math.min(run3.a, run3.b, ...reach2), Math.max(run3.a, run3.b, ...reach2), run3.ups.map((tip) => tip.x), run3.downs.map((tip) => tip.x)) };
138759
139319
  });
138760
139320
  }
138761
- function planLinks(links, where, bounds) {
139321
+ function planLinks(links, where, bounds2) {
138762
139322
  let lanes = 0;
138763
139323
  const plans = [];
138764
139324
  links.forEach((link2, index2) => {
@@ -138767,7 +139327,7 @@ function planLinks(links, where, bounds) {
138767
139327
  if (from === void 0 || to === void 0) return;
138768
139328
  const kind = from.row === to.row ? "under" : Math.abs(from.row - to.row) === 1 ? "step" : "lane";
138769
139329
  const down = to.row > from.row;
138770
- const laneX = kind === "lane" ? bounds.right + (LAYERS_METRICS.laneOffsets[lanes++ % LAYERS_METRICS.laneOffsets.length] ?? 0) : null;
139330
+ const laneX = kind === "lane" ? bounds2.right + (LAYERS_METRICS.laneOffsets[lanes++ % LAYERS_METRICS.laneOffsets.length] ?? 0) : null;
138771
139331
  const one = link2.label?.replace(/\s+/g, " ").trim();
138772
139332
  const fitted = one === void 0 ? null : fitLine(one.slice(0, 400), "edgeLabel", LAYERS_METRICS.maxLabelText);
138773
139333
  const label = one === void 0 || fitted === null ? null : { text: fitted, width: Math.ceil(measureRole(fitted, "edgeLabel")) + 2 * EDGE_METRICS.labelPaddingX, isShortened: fitted !== one };
@@ -138775,7 +139335,7 @@ function planLinks(links, where, bounds) {
138775
139335
  });
138776
139336
  placePorts(plans);
138777
139337
  separatePorts(plans);
138778
- for (const plan of plans) placeRuns(plan, bounds);
139338
+ for (const plan of plans) placeRuns(plan, bounds2);
138779
139339
  return plans;
138780
139340
  }
138781
139341
  function pointsOf(plan) {
@@ -143749,17 +144309,17 @@ var init_paint_hole = __esm({
143749
144309
  // ../../packages/diagrams/src/kinds/pie/look.ts
143750
144310
  function sliceLook(theme, tone) {
143751
144311
  const outline2 = theme.tones[tone].outline;
143752
- const segment = tone === "neutral" ? ensureContrast(mix(outline2, theme.surface, NEUTRAL_SHARE), theme.surface, GRAPHIC_CONTRAST3, theme.ink) : outline2;
144312
+ const segment = tone === "neutral" ? ensureContrast(mix(outline2, theme.surface, NEUTRAL_SHARE), theme.surface, GRAPHIC_CONTRAST2, theme.ink) : outline2;
143753
144313
  return { segment, leader: mix(segment, theme.surface, LEADER_SHARE), icon: bareGlyphColor(theme, tone) };
143754
144314
  }
143755
- var LEADER_SHARE, NEUTRAL_SHARE, GRAPHIC_CONTRAST3;
144315
+ var LEADER_SHARE, NEUTRAL_SHARE, GRAPHIC_CONTRAST2;
143756
144316
  var init_look4 = __esm({
143757
144317
  "../../packages/diagrams/src/kinds/pie/look.ts"() {
143758
144318
  "use strict";
143759
144319
  init_theme();
143760
144320
  LEADER_SHARE = 0.92;
143761
144321
  NEUTRAL_SHARE = 0.62;
143762
- GRAPHIC_CONTRAST3 = 3;
144322
+ GRAPHIC_CONTRAST2 = 3;
143763
144323
  }
143764
144324
  });
143765
144325
 
@@ -148060,8 +148620,26 @@ function labelGap(message2) {
148060
148620
  y2: Math.max(message2.labelY, badge === void 0 ? Number.NEGATIVE_INFINITY : badge.y + badge.height) + LABEL_CLEARANCE2
148061
148621
  };
148062
148622
  }
148063
- function buildLifelines(actors, messages, top, bottom) {
148064
- const gaps = messages.map(labelGap);
148623
+ function headerGap(x, bandTop, bandHeight, keyword, label) {
148624
+ const left = x + SEQUENCE_METRICS.blockHeaderInset;
148625
+ const condition = label === "" ? 0 : SEQUENCE_METRICS.blockKeywordGap + measureRole(label, "edgeLabel");
148626
+ const top = bandTop + (bandHeight - TYPE_ROLES.groupLabel.lineHeight) / 2;
148627
+ return {
148628
+ x1: left - LABEL_CLEARANCE2,
148629
+ x2: left + measureRole(keyword, "groupLabel") + condition + LABEL_CLEARANCE2,
148630
+ y1: top - LABEL_CLEARANCE2 / 2,
148631
+ y2: top + TYPE_ROLES.groupLabel.lineHeight + LABEL_CLEARANCE2 / 2
148632
+ };
148633
+ }
148634
+ function blockGaps(block) {
148635
+ const { x, y } = block.rect;
148636
+ return [
148637
+ headerGap(x, y, SEQUENCE_METRICS.blockHeader, block.blockType, block.label),
148638
+ ...block.dividers.map((divider) => headerGap(x, divider.y, SEQUENCE_METRICS.blockBranchHeader, divider.keyword, divider.label))
148639
+ ];
148640
+ }
148641
+ function buildLifelines(actors, messages, blocks2, top, bottom) {
148642
+ const gaps = [...messages.map(labelGap), ...blocks2.flatMap(blockGaps)];
148065
148643
  return actors.map((actor) => {
148066
148644
  const crossing = gaps.filter((gap2) => gap2.x1 < actor.centerX && actor.centerX < gap2.x2).sort((a, b) => a.y1 - b.y1);
148067
148645
  const segments = [];
@@ -148154,6 +148732,10 @@ function placeNote(item, ctx, y) {
148154
148732
  ctx.notes.push({ rect: { x, y, width, height }, lines });
148155
148733
  return { y: y + height + SEQUENCE_METRICS.noteGap, extent: { minX: x, maxX: x + width } };
148156
148734
  }
148735
+ function blockHeaderWidth(keyword, label) {
148736
+ const condition = label === "" ? 0 : SEQUENCE_METRICS.blockKeywordGap + measureRole(label, "edgeLabel");
148737
+ return SEQUENCE_METRICS.blockHeaderInset * 2 + measureRole(keyword, "groupLabel") + condition;
148738
+ }
148157
148739
  function placeBlock2(item, ctx, y) {
148158
148740
  const first = item.branches[0];
148159
148741
  const dividers = [];
@@ -148171,9 +148753,9 @@ function placeBlock2(item, ctx, y) {
148171
148753
  cursor += SEQUENCE_METRICS.blockBottomPadding;
148172
148754
  const reach2 = extent2 ?? { minX: ctx.centers[0] ?? 0, maxX: ctx.centers[ctx.centers.length - 1] ?? 0 };
148173
148755
  const label = first?.label ?? "";
148174
- const tabWidth2 = measureRole(`${item.blockType} ${label}`, "groupLabel") + TAB_PADDING;
148756
+ const headerWidth = Math.max(blockHeaderWidth(item.blockType, label), ...dividers.map((divider) => blockHeaderWidth(divider.keyword, divider.label)));
148175
148757
  const x = reach2.minX - SEQUENCE_METRICS.blockPadding;
148176
- const width = Math.max(reach2.maxX - reach2.minX + SEQUENCE_METRICS.blockPadding * 2, tabWidth2);
148758
+ const width = Math.max(reach2.maxX - reach2.minX + SEQUENCE_METRICS.blockPadding * 2, headerWidth);
148177
148759
  ctx.blocks.push({ blockType: item.blockType, rect: { x, y, width, height: cursor - y }, label, dividers });
148178
148760
  return { y: cursor + SEQUENCE_METRICS.noteGap, extent: { minX: x, maxX: x + width } };
148179
148761
  }
@@ -148187,7 +148769,7 @@ function placeItems3(items2, ctx, startY) {
148187
148769
  }
148188
148770
  return { y, extent: extent2 };
148189
148771
  }
148190
- var HOP_LABEL_MARGIN, NOTE_OVERHANG, TAB_PADDING, leadOf2;
148772
+ var HOP_LABEL_MARGIN, NOTE_OVERHANG, leadOf2;
148191
148773
  var init_rows2 = __esm({
148192
148774
  "../../packages/diagrams/src/layout/sequence/rows.ts"() {
148193
148775
  "use strict";
@@ -148197,7 +148779,6 @@ var init_rows2 = __esm({
148197
148779
  init_columns();
148198
148780
  HOP_LABEL_MARGIN = 4;
148199
148781
  NOTE_OVERHANG = 16;
148200
- TAB_PADDING = 28;
148201
148782
  leadOf2 = (step) => stepBadgeWidth(step) + STEP_METRICS.labelGap;
148202
148783
  }
148203
148784
  });
@@ -148237,7 +148818,7 @@ function layoutSequence(diagram) {
148237
148818
  return {
148238
148819
  size: { width: Math.ceil(right + CANVAS_METRICS.padding), height: Math.ceil(lifelineBottom + CANVAS_METRICS.padding) },
148239
148820
  actors,
148240
- lifelines: buildLifelines(actors, messages, lifelineTop, lifelineBottom),
148821
+ lifelines: buildLifelines(actors, messages, blocks2, lifelineTop, lifelineBottom),
148241
148822
  blocks: blocks2,
148242
148823
  notes,
148243
148824
  messages
@@ -148357,7 +148938,7 @@ function parseActorStatement2(cursor, state, line3) {
148357
148938
  if (type === void 0) {
148358
148939
  state.report.push(errorAt(DIAGNOSTIC_CODES.unknownNodeType, `Unknown actor type "${typeToken.text}"`, typeToken, didYouMean(typeToken.text, ACTOR_TYPES)));
148359
148940
  }
148360
- const label = readLabel(cursor, state, line3, "label");
148941
+ const label = readLabel(cursor, state, line3, "label", 'actor <id> <type> "Label", such as actor db database "Users DB".');
148361
148942
  const options3 = readOptions(cursor, ACTOR_OPTIONS, state.report);
148362
148943
  rejectTrailing(cursor, state, 'An actor is: actor id type "Label" sub="..." icon=lucide:name tone=blue');
148363
148944
  if (id === null || type === void 0 || label === null) return;
@@ -148499,7 +149080,7 @@ function dispatchStatement4(line3, state) {
148499
149080
  DIAGNOSTIC_CODES.unknownStatement,
148500
149081
  `Unknown statement "${first.text}"`,
148501
149082
  first,
148502
- `${didYouMean(first.text, STATEMENT_KEYWORDS5)} Messages look like: from -> to : "label"`
149083
+ first.text === "sequence" ? 'The header is one line, the first: put the title and every header option on it together, such as sequence "Checkout" direction=right.' : first.text === "title" ? `There is no title statement: the title is the quoted text after the kind on the first line, such as sequence "Checkout".` : line3.tokens[1]?.kind === "equals" ? `An option such as ${first.text}= goes at the end of the line of the actor or message it sets, not on a line of its own: actor api service "API" ${first.text}=...` : FLOW_NODE_TYPES.includes(first.text) ? `A participant is declared with actor and its type comes after the id: actor <id> ${first.text} "Label". Messages look like: from -> to : "label"` : `${didYouMean(first.text, STATEMENT_KEYWORDS5)} Messages look like: from -> to : "label"`
148503
149084
  )
148504
149085
  );
148505
149086
  }
@@ -153550,7 +154131,7 @@ function cutText(diagram) {
153550
154131
  return cut.length <= MAX_LISTED ? cut : [...cut.slice(0, MAX_LISTED), `and ${cut.length - MAX_LISTED} more`];
153551
154132
  }
153552
154133
  function lintTimeline(diagram, measure) {
153553
- const widthHint = diagram.direction === "right" ? "Set direction=down, shorten the event labels, or split the timeline by era." : "Shorten the event labels, or split the timeline by era.";
154134
+ const widthHint2 = diagram.direction === "right" ? "Set direction=down, shorten the event labels, or split the timeline by era." : "Shorten the event labels, or split the timeline by era.";
153554
154135
  return [
153555
154136
  ...present([periodsWarning(diagram), eventsWarning(diagram)]),
153556
154137
  ...crowdedWarnings(diagram),
@@ -153558,7 +154139,7 @@ function lintTimeline(diagram, measure) {
153558
154139
  ...emptyWarnings(diagram),
153559
154140
  ...orderWarnings(diagram),
153560
154141
  ...duplicateWarnings2(diagram),
153561
- ...present([shortenedWarning(cutText(diagram)), widthWarning(measure.size, widthHint)])
154142
+ ...present([shortenedWarning(cutText(diagram)), widthWarning(measure.size, widthHint2)])
153562
154143
  ];
153563
154144
  }
153564
154145
  var MAX_LISTED, SPLIT_HINT4;
@@ -154783,12 +155364,12 @@ function place({ diagram, flat: flat3, cards, hang: hang2 }) {
154783
155364
  top += sized.height + TREE_METRICS.hangGap;
154784
155365
  }
154785
155366
  }
154786
- const bounds = rects.reduce((box, rect) => ({ left: Math.min(box.left, rect.x), top: Math.min(box.top, rect.y), right: Math.max(box.right, rect.x + rect.width), bottom: Math.max(box.bottom, rect.y + rect.height) }), { left: Number.POSITIVE_INFINITY, top: Number.POSITIVE_INFINITY, right: Number.NEGATIVE_INFINITY, bottom: Number.NEGATIVE_INFINITY });
154787
- const shift2 = { x: TREE_METRICS.canvasPadding - bounds.left, y: TREE_METRICS.canvasPadding - bounds.top };
155367
+ const bounds2 = rects.reduce((box, rect) => ({ left: Math.min(box.left, rect.x), top: Math.min(box.top, rect.y), right: Math.max(box.right, rect.x + rect.width), bottom: Math.max(box.bottom, rect.y + rect.height) }), { left: Number.POSITIVE_INFINITY, top: Number.POSITIVE_INFINITY, right: Number.NEGATIVE_INFINITY, bottom: Number.NEGATIVE_INFINITY });
155368
+ const shift2 = { x: TREE_METRICS.canvasPadding - bounds2.left, y: TREE_METRICS.canvasPadding - bounds2.top };
154788
155369
  const moved3 = rects.map((rect) => ({ x: rect.x + shift2.x, y: rect.y + shift2.y, width: rect.width, height: rect.height }));
154789
155370
  return {
154790
155371
  kind: "org",
154791
- size: { width: Math.ceil(bounds.right - bounds.left + 2 * TREE_METRICS.canvasPadding), height: Math.ceil(bounds.bottom - bounds.top + 2 * TREE_METRICS.canvasPadding) },
155372
+ size: { width: Math.ceil(bounds2.right - bounds2.left + 2 * TREE_METRICS.canvasPadding), height: Math.ceil(bounds2.bottom - bounds2.top + 2 * TREE_METRICS.canvasPadding) },
154792
155373
  cards: flat3.map((entry2) => cardOf(entry2, size(entry2.index), moved3[entry2.index], isHung[entry2.index] === true)),
154793
155374
  links: flat3.flatMap((entry2) => linksOf2(entry2, moved3, isDown, isHanging, isHung)),
154794
155375
  facts: { cut: flat3.flatMap((entry2) => size(entry2.index).name.isCut || size(entry2.index).note?.isCut === true ? [`"${entry2.path}"`] : []), rows: flat3.length }
@@ -155091,11 +155672,11 @@ function duplicateWarnings3(flat3) {
155091
155672
  function lintTree(diagram, measure) {
155092
155673
  const flat3 = flattenTree(diagram);
155093
155674
  const { facts } = placeTree(diagram);
155094
- const widthHint = diagram.style === "org" && diagram.direction === "down" ? "Set direction=right, which grows the chart down the page instead of across it, or split the chart by branch." : "Shorten the names and notes, or split the tree by branch.";
155675
+ const widthHint2 = diagram.style === "org" && diagram.direction === "down" ? "Set direction=right, which grows the chart down the page instead of across it, or split the chart by branch." : "Shorten the names and notes, or split the tree by branch.";
155095
155676
  return [
155096
155677
  ...present([depthWarning2(depthOf3(flat3)), rowsWarning(facts.rows, diagram.style)]),
155097
155678
  ...diagram.style === "files" ? duplicateWarnings3(flat3) : [],
155098
- ...present([shortenedWarning(facts.cut), widthWarning(measure.size, widthHint)])
155679
+ ...present([shortenedWarning(facts.cut), widthWarning(measure.size, widthHint2)])
155099
155680
  ];
155100
155681
  }
155101
155682
  var init_lint18 = __esm({
@@ -157440,7 +158021,7 @@ function valueAxisTitle(title, unit3) {
157440
158021
  if (!isWordUnit(unit3)) return title === null ? null : oneLine9(title);
157441
158022
  return title === null ? unit3 : `${oneLine9(title)} (${unit3})`;
157442
158023
  }
157443
- function fitPlaces(labels2, slot, centerOf3, bounds) {
158024
+ function fitPlaces(labels2, slot, centerOf3, bounds2) {
157444
158025
  const longest = Math.max(0, ...labels2.flatMap((label) => label.split(" ").map((word2) => measureRole(word2, "sub"))));
157445
158026
  let step = 1;
157446
158027
  while (step < labels2.length && step * slot - XYCHART_METRICS.pill.gap < longest) step += 1;
@@ -157448,7 +158029,7 @@ function fitPlaces(labels2, slot, centerOf3, bounds) {
157448
158029
  const room = Math.max(8, step * slot - XYCHART_METRICS.pill.gap);
157449
158030
  const fitted = labels2.map((label) => fitText(label, "sub", room, room, 2));
157450
158031
  const half = fitted.map((entry2) => Math.max(...entry2.lines.map((line3) => measureRole(line3, "sub"))) / 2);
157451
- const x = fitted.map((_, index2) => Math.min(Math.max(centerOf3(index2), bounds.left + (half[index2] ?? 0)), Math.max(bounds.left + (half[index2] ?? 0), bounds.right - (half[index2] ?? 0))));
158032
+ const x = fitted.map((_, index2) => Math.min(Math.max(centerOf3(index2), bounds2.left + (half[index2] ?? 0)), Math.max(bounds2.left + (half[index2] ?? 0), bounds2.right - (half[index2] ?? 0))));
157452
158033
  const shown = fitted.flatMap((_, index2) => index2 % step === 0 ? [index2] : []);
157453
158034
  const isApart = shown.every((index2, at3) => {
157454
158035
  const before = shown[at3 - 1];
@@ -158526,16 +159107,16 @@ var init_parse19 = __esm({
158526
159107
 
158527
159108
  // ../../packages/diagrams/src/kinds/xychart/look.ts
158528
159109
  function seriesLook(theme, tone) {
158529
- const outline2 = ensureContrast(theme.tones[tone].outline, theme.surfaceGroup, GRAPHIC_CONTRAST4, theme.ink);
158530
- const mark = tone === "neutral" ? ensureContrast(mix(outline2, theme.surfaceGroup, 0.62), theme.surfaceGroup, GRAPHIC_CONTRAST4, theme.ink) : outline2;
159110
+ const outline2 = ensureContrast(theme.tones[tone].outline, theme.surfaceGroup, GRAPHIC_CONTRAST3, theme.ink);
159111
+ const mark = tone === "neutral" ? ensureContrast(mix(outline2, theme.surfaceGroup, 0.62), theme.surfaceGroup, GRAPHIC_CONTRAST3, theme.ink) : outline2;
158531
159112
  return { mark, rim: mix(mark, theme.ink, 0.86), leader: mix(mark, theme.surfaceGroup, 0.55), washOpacity: 0.16 };
158532
159113
  }
158533
- var GRAPHIC_CONTRAST4, chartLook;
159114
+ var GRAPHIC_CONTRAST3, chartLook;
158534
159115
  var init_look9 = __esm({
158535
159116
  "../../packages/diagrams/src/kinds/xychart/look.ts"() {
158536
159117
  "use strict";
158537
159118
  init_theme();
158538
- GRAPHIC_CONTRAST4 = 3;
159119
+ GRAPHIC_CONTRAST3 = 3;
158539
159120
  chartLook = (theme) => ({
158540
159121
  plate: theme.surfaceGroup,
158541
159122
  grid: mix(theme.border, theme.surfaceGroup, 0.55),
@@ -159214,124 +159795,6 @@ var init_prose = __esm({
159214
159795
  }
159215
159796
  });
159216
159797
 
159217
- // ../../packages/diagrams/src/parse/lexer.ts
159218
- function readWord(text3, start2) {
159219
- let end = start2;
159220
- while (end < text3.length) {
159221
- const char = text3.charAt(end);
159222
- const next = text3.charAt(end + 1);
159223
- if (isWordPart(char)) end += 1;
159224
- else if (char === "-" && isWordPart(next)) end += 1;
159225
- else if (char === "." && isWordPart(next)) end += 1;
159226
- else if (char === ":" && /[A-Za-z_]/.test(next)) end += 1;
159227
- else break;
159228
- }
159229
- return text3.slice(start2, end);
159230
- }
159231
- function readString(text3, start2) {
159232
- let value = "";
159233
- let index2 = start2 + 1;
159234
- while (index2 < text3.length) {
159235
- const char = text3.charAt(index2);
159236
- if (char === '"') return { value, end: index2 + 1 };
159237
- if (char === "\\") {
159238
- const escaped = STRING_ESCAPES[text3.charAt(index2 + 1)];
159239
- value += escaped ?? text3.charAt(index2 + 1);
159240
- index2 += 2;
159241
- } else {
159242
- value += char;
159243
- index2 += 1;
159244
- }
159245
- }
159246
- return null;
159247
- }
159248
- function matchArrow(text3, index2) {
159249
- return ARROW_TOKENS.find((arrow) => text3.startsWith(arrow, index2)) ?? null;
159250
- }
159251
- function lexLine(text3, line3, diagnostics) {
159252
- const tokens = [];
159253
- let index2 = 0;
159254
- while (index2 < text3.length) {
159255
- const char = text3.charAt(index2);
159256
- const column = index2 + 1;
159257
- if (char === " " || char === " " || char === "\r") {
159258
- index2 += 1;
159259
- } else if (char === "#") {
159260
- break;
159261
- } else if (char === '"') {
159262
- const read = readString(text3, index2);
159263
- if (read === null) {
159264
- diagnostics.push(
159265
- errorAt(
159266
- DIAGNOSTIC_CODES.unterminatedString,
159267
- "String is missing its closing quote",
159268
- { line: line3, column, length: text3.length - index2 },
159269
- "Close the label with a double quote on the same line."
159270
- )
159271
- );
159272
- break;
159273
- }
159274
- tokens.push({ kind: "string", text: read.value, line: line3, column, length: read.end - index2 });
159275
- index2 = read.end;
159276
- } else if (matchArrow(text3, index2) !== null) {
159277
- const arrow = matchArrow(text3, index2);
159278
- tokens.push({ kind: "arrow", text: arrow, line: line3, column, length: arrow.length });
159279
- index2 += arrow.length;
159280
- } else if (char === ":") {
159281
- tokens.push({ kind: "colon", line: line3, column, length: 1 });
159282
- index2 += 1;
159283
- } else if (char === "=") {
159284
- tokens.push({ kind: "equals", line: line3, column, length: 1 });
159285
- index2 += 1;
159286
- } else if (char === ",") {
159287
- tokens.push({ kind: "comma", line: line3, column, length: 1 });
159288
- index2 += 1;
159289
- } else if (char === "{") {
159290
- tokens.push({ kind: "lbrace", line: line3, column, length: 1 });
159291
- index2 += 1;
159292
- } else if (char === "}") {
159293
- tokens.push({ kind: "rbrace", line: line3, column, length: 1 });
159294
- index2 += 1;
159295
- } else if (isWordStart(char)) {
159296
- const word2 = readWord(text3, index2);
159297
- tokens.push({ kind: "word", text: word2, line: line3, column, length: word2.length });
159298
- index2 += word2.length;
159299
- } else {
159300
- diagnostics.push(
159301
- errorAt(
159302
- DIAGNOSTIC_CODES.syntax,
159303
- `Unexpected character "${char}"`,
159304
- { line: line3, column, length: 1 },
159305
- 'Labels go in double quotes; ids use letters, digits, "_" and "-".'
159306
- )
159307
- );
159308
- index2 += 1;
159309
- }
159310
- }
159311
- return tokens;
159312
- }
159313
- function lex(source) {
159314
- const diagnostics = [];
159315
- const lines = [];
159316
- source.split("\n").forEach((text3, offset) => {
159317
- const line3 = offset + 1;
159318
- const tokens = lexLine(text3, line3, diagnostics);
159319
- if (tokens.length > 0) lines.push({ line: line3, tokens });
159320
- });
159321
- return { lines, diagnostics };
159322
- }
159323
- var STRING_ESCAPES, isWordStart, isWordPart;
159324
- var init_lexer = __esm({
159325
- "../../packages/diagrams/src/parse/lexer.ts"() {
159326
- "use strict";
159327
- init_constants();
159328
- init_core();
159329
- STRING_ESCAPES = { '"': '"', "\\": "\\", n: "\n", t: " " };
159330
- isWordStart = (char) => /[A-Za-z0-9_]/.test(char);
159331
- isWordPart = (char) => /[A-Za-z0-9_]/.test(char);
159332
- }
159333
- });
159334
-
159335
159798
  // ../../packages/diagrams/src/parse/parse-diagram.ts
159336
159799
  function parseDiagram(source) {
159337
159800
  const lexed = lex(source);
@@ -159350,7 +159813,7 @@ function parseDiagram(source) {
159350
159813
  DIAGNOSTIC_CODES.missingHeader,
159351
159814
  `The first line must name the diagram kind, found "${text3}"`,
159352
159815
  header,
159353
- `${didYouMean(text3, implementedKinds())} Start with: ${headerHint()}`
159816
+ text3 === "title" ? 'There is no title statement: the title is the quoted text after the kind on the first line, such as flow "Checkout" or sequence "Sign in".' : `${didYouMean(text3, implementedKinds())} Start with: ${headerHint()}`
159354
159817
  )
159355
159818
  );
159356
159819
  return err(report3);
@@ -159377,6 +159840,7 @@ var init_parse20 = __esm({
159377
159840
  "../../packages/diagrams/src/parse/index.ts"() {
159378
159841
  "use strict";
159379
159842
  init_parse_diagram();
159843
+ init_unknown_icons();
159380
159844
  init_lexer();
159381
159845
  }
159382
159846
  });
@@ -159528,7 +159992,7 @@ async function readCapped(response, maxBytes) {
159528
159992
  }
159529
159993
  return new TextDecoder().decode(bytes);
159530
159994
  }
159531
- async function fetchDiagramLink(text3, fetchLink = (url2, init) => fetch(url2, init)) {
159995
+ async function fetchDiagramLink(text3, fetchLink = (url2, init) => fetch(url2, { ...init, signal: init.signal })) {
159532
159996
  const refusal = refusalOfLink(text3);
159533
159997
  if (refusal !== null) return REFUSED(refusal);
159534
159998
  const seconds = READ_LIMITS.timeoutMs / 1e3;
@@ -160151,6 +160615,16 @@ var init_compare_diagrams2 = __esm({
160151
160615
  }
160152
160616
  });
160153
160617
 
160618
+ // ../../packages/diagrams/src/services/classification-stamp.ts
160619
+ var CLASSIFICATION_ATTRIBUTE, ELEMENT_PATTERN;
160620
+ var init_classification_stamp = __esm({
160621
+ "../../packages/diagrams/src/services/classification-stamp.ts"() {
160622
+ "use strict";
160623
+ CLASSIFICATION_ATTRIBUTE = "data-classification";
160624
+ ELEMENT_PATTERN = new RegExp(`<metadata ${CLASSIFICATION_ATTRIBUTE}="[^"]*"/>`, "g");
160625
+ }
160626
+ });
160627
+
160154
160628
  // ../../packages/diagrams/src/services/outline-diagram-source.ts
160155
160629
  function outlineDiagramSource(source) {
160156
160630
  const parsed = parseDiagram(source);
@@ -160373,6 +160847,84 @@ var init_render15 = __esm({
160373
160847
  }
160374
160848
  });
160375
160849
 
160850
+ // ../../packages/diagrams/src/secrets/scan-secrets.ts
160851
+ function maskSecret(value) {
160852
+ const shown = Math.min(SECRET_SCAN_LIMITS.shownCharacters, Math.floor(value.length / 4));
160853
+ return value.slice(0, shown) + SECRET_SCAN_LIMITS.mask;
160854
+ }
160855
+ function detectorsFor(options3) {
160856
+ const hosts = internalHostDetector(options3.internalHosts ?? []);
160857
+ return [...DETECTORS, ...options3.privateIps === true ? [PRIVATE_IP_DETECTOR] : [], ...hosts === null ? [] : [hosts]];
160858
+ }
160859
+ function scanLine(text3, line3, detectors) {
160860
+ return secretSpans(text3, detectors).map((span) => ({
160861
+ code: CODE_OF_KIND[span.kind],
160862
+ kind: span.kind,
160863
+ line: line3,
160864
+ column: span.start + 1,
160865
+ length: span.end - span.start,
160866
+ masked: maskSecret(span.value)
160867
+ }));
160868
+ }
160869
+ function scanSecrets(source, options3 = {}) {
160870
+ const detectors = detectorsFor(options3);
160871
+ return source.split("\n").flatMap((text3, index2) => scanLine(text3.endsWith("\r") ? text3.slice(0, -1) : text3, index2 + 1, detectors)).sort((a, b) => a.line - b.line || a.column - b.column);
160872
+ }
160873
+ function hintFor(kind) {
160874
+ if (kind === "private-ip" || kind === "internal-host") {
160875
+ return "Your organisation asked for these to be found. Name the part by its role (the database, the internal API) instead. The scan matches patterns, so it can miss one or name one that is fine.";
160876
+ }
160877
+ return `Put a placeholder such as <${kind}> or a reference such as \${NAME} in its place, and rotate the value if it was ever shared. The scan matches patterns, so it can miss a secret or name a value that is not one.`;
160878
+ }
160879
+ function secretWarning(finding2) {
160880
+ const at3 = { line: finding2.line, column: finding2.column, length: finding2.length };
160881
+ return warningAt(finding2.code, `This looks like ${SECRET_KIND_NAMES[finding2.kind]} (${finding2.masked}); remove it before you publish or commit.`, at3, hintFor(finding2.kind));
160882
+ }
160883
+ function secretWarnings(source, options3 = {}) {
160884
+ return scanSecrets(source, options3).map(secretWarning);
160885
+ }
160886
+ var CODE_OF_KIND, SECRET_CODES;
160887
+ var init_scan_secrets = __esm({
160888
+ "../../packages/diagrams/src/secrets/scan-secrets.ts"() {
160889
+ "use strict";
160890
+ init_constants();
160891
+ init_core();
160892
+ init_detectors();
160893
+ init_find_spans();
160894
+ CODE_OF_KIND = {
160895
+ "aws-access-key": DIAGNOSTIC_CODES.secretCloudKey,
160896
+ "aws-secret-key": DIAGNOSTIC_CODES.secretCloudKey,
160897
+ "gcp-api-key": DIAGNOSTIC_CODES.secretCloudKey,
160898
+ "gcp-service-account": DIAGNOSTIC_CODES.secretCloudKey,
160899
+ "azure-storage-key": DIAGNOSTIC_CODES.secretCloudKey,
160900
+ "azure-sas-token": DIAGNOSTIC_CODES.secretCloudKey,
160901
+ "github-token": DIAGNOSTIC_CODES.secretSourceToken,
160902
+ "slack-token": DIAGNOSTIC_CODES.secretChatToken,
160903
+ "slack-webhook": DIAGNOSTIC_CODES.secretChatToken,
160904
+ "stripe-key": DIAGNOSTIC_CODES.secretPaymentKey,
160905
+ jwt: DIAGNOSTIC_CODES.secretJwt,
160906
+ "private-key": DIAGNOSTIC_CODES.secretPrivateKey,
160907
+ "assigned-secret": DIAGNOSTIC_CODES.secretAssigned,
160908
+ "connection-string": DIAGNOSTIC_CODES.secretConnectionString,
160909
+ "plotwork-key": DIAGNOSTIC_CODES.secretPlotworkKey,
160910
+ "private-ip": DIAGNOSTIC_CODES.secretPrivateIp,
160911
+ "internal-host": DIAGNOSTIC_CODES.secretInternalHost
160912
+ };
160913
+ SECRET_CODES = new Set(Object.values(CODE_OF_KIND));
160914
+ }
160915
+ });
160916
+
160917
+ // ../../packages/diagrams/src/secrets/index.ts
160918
+ var init_secrets = __esm({
160919
+ "../../packages/diagrams/src/secrets/index.ts"() {
160920
+ "use strict";
160921
+ init_detectors();
160922
+ init_find_spans();
160923
+ init_placeholders();
160924
+ init_scan_secrets();
160925
+ }
160926
+ });
160927
+
160376
160928
  // ../../packages/diagrams/src/services/render-pair.ts
160377
160929
  async function renderPairDetailed(source, idPrefix, brand = null) {
160378
160930
  const parsed = parseDiagram(source);
@@ -160392,7 +160944,12 @@ async function renderPairDetailed(source, idPrefix, brand = null) {
160392
160944
  }
160393
160945
  },
160394
160946
  kind: parsed.value.kind,
160395
- warnings: [...lintDiagram(parsed.value, light.size, light.overlayCovers), ...iconArtWarnings([.../* @__PURE__ */ new Set([...light.missingIcons, ...dark.missingIcons])].sort(), source)]
160947
+ warnings: [
160948
+ ...unknownIconWarnings(source),
160949
+ ...secretWarnings(source),
160950
+ ...lintDiagram(parsed.value, light.size, light.overlayCovers),
160951
+ ...iconArtWarnings([.../* @__PURE__ */ new Set([...light.missingIcons, ...dark.missingIcons])].sort(), source)
160952
+ ]
160396
160953
  };
160397
160954
  }
160398
160955
  var init_render_pair = __esm({
@@ -160402,6 +160959,14 @@ var init_render_pair = __esm({
160402
160959
  init_outline18();
160403
160960
  init_parse20();
160404
160961
  init_render15();
160962
+ init_secrets();
160963
+ }
160964
+ });
160965
+
160966
+ // ../../packages/diagrams/src/markdown/dark-pictures.ts
160967
+ var init_dark_pictures = __esm({
160968
+ "../../packages/diagrams/src/markdown/dark-pictures.ts"() {
160969
+ "use strict";
160405
160970
  }
160406
160971
  });
160407
160972
 
@@ -160415,7 +160980,7 @@ async function renderDiagramSource(input2, brand = null) {
160415
160980
  ...input2.idPrefix === void 0 ? {} : { idPrefix: input2.idPrefix },
160416
160981
  ...input2.embedSource ? { source: input2.source } : {}
160417
160982
  });
160418
- return ok({ svg, theme: input2.theme, size, warnings: [...lintDiagram(parsed.value, size, overlayCovers), ...iconArtWarnings(missingIcons, input2.source)].map(diagnosticToDto) });
160983
+ return ok({ svg, theme: input2.theme, size, warnings: [...unknownIconWarnings(input2.source), ...secretWarnings(input2.source), ...lintDiagram(parsed.value, size, overlayCovers), ...iconArtWarnings(missingIcons, input2.source)].map(diagnosticToDto) });
160419
160984
  }
160420
160985
  var init_render_diagram_svg = __esm({
160421
160986
  "../../packages/diagrams/src/services/render-diagram-svg.ts"() {
@@ -160424,6 +160989,7 @@ var init_render_diagram_svg = __esm({
160424
160989
  init_lint21();
160425
160990
  init_parse20();
160426
160991
  init_render15();
160992
+ init_secrets();
160427
160993
  init_to_dto();
160428
160994
  }
160429
160995
  });
@@ -160828,12 +161394,11 @@ function attr(text3) {
160828
161394
  function buildBlock(content) {
160829
161395
  const isListLine = (line3) => line3.startsWith("- ") || line3.startsWith(" ");
160830
161396
  const outline2 = content.outline.flatMap((line3) => isListLine(line3) ? [line3] : ["", `**${line3}**`, ""]);
161397
+ const image = `<img alt="${attr(content.alt)}" src="${attr(content.lightSrc)}">`;
161398
+ const picture2 = content.darkSrc === null ? [image] : ["<picture>", ` <source media="(prefers-color-scheme: dark)" srcset="${attr(content.darkSrc)}">`, ` ${image}`, "</picture>"];
160831
161399
  return [
160832
161400
  `${BLOCK_START} id="${content.id}" hash="${content.hash}" -->`,
160833
- "<picture>",
160834
- ` <source media="(prefers-color-scheme: dark)" srcset="${attr(content.darkSrc)}">`,
160835
- ` <img alt="${attr(content.alt)}" src="${attr(content.lightSrc)}">`,
160836
- "</picture>",
161401
+ ...picture2,
160837
161402
  "",
160838
161403
  "<details>",
160839
161404
  "<summary>Text description</summary>",
@@ -160927,11 +161492,11 @@ var init_locate_block = __esm({
160927
161492
 
160928
161493
  // ../../packages/diagrams/src/markdown/sync-markdown.ts
160929
161494
  import { createHash } from "node:crypto";
160930
- function hashBlock(source, pair2) {
161495
+ function hashBlock(source, pair2, schemes = "light-and-dark") {
160931
161496
  return createHash("sha256").update(`${BLOCK_FORMAT_VERSION}
160932
161497
  ${source}
160933
161498
  ${pair2.light}
160934
- ${pair2.dark}`).digest("hex").slice(0, 12);
161499
+ ${pair2.dark}${schemes === "auto" ? "\nauto" : ""}`).digest("hex").slice(0, 12);
160935
161500
  }
160936
161501
  function slugify2(text3) {
160937
161502
  const slug = text3.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
@@ -160974,7 +161539,8 @@ async function syncMarkdown(markdown, stem2, hooks) {
160974
161539
  continue;
160975
161540
  }
160976
161541
  const { pair: pair2 } = outcome;
160977
- const hash2 = hashBlock(fence.source, pair2);
161542
+ const merged = hooks.schemes === "auto" ? mergeSchemes(pair2.light, pair2.dark, id) : null;
161543
+ const hash2 = hashBlock(fence.source, pair2, merged === null ? "light-and-dark" : "auto");
160978
161544
  const isFresh = place2.block !== null && readBlockHash(lines[place2.block.start] ?? "") === hash2;
160979
161545
  if (isFresh && !needsWrap) {
160980
161546
  unchangedCount += 1;
@@ -160982,8 +161548,8 @@ async function syncMarkdown(markdown, stem2, hooks) {
160982
161548
  }
160983
161549
  stale.push({ fenceLine: fence.openLine + 1, reason: place2.block === null ? "missing" : isFresh ? "unwrapped" : "changed" });
160984
161550
  const lightSrc = `${hooks.assetDir}/${id}.svg`;
160985
- const darkSrc = `${hooks.assetDir}/${id}.dark.svg`;
160986
- assets.push({ path: lightSrc, content: pair2.light }, { path: darkSrc, content: pair2.dark });
161551
+ const darkSrc = merged === null ? `${hooks.assetDir}/${id}.dark.svg` : null;
161552
+ assets.push({ path: lightSrc, content: merged ?? pair2.light }, ...darkSrc === null ? [] : [{ path: darkSrc, content: pair2.dark }]);
160987
161553
  const block = buildBlock({ id, hash: hash2, alt: pair2.summary, outline: pair2.outline, lightSrc, darkSrc }).split("\n");
160988
161554
  if (needsWrap) {
160989
161555
  const source = lines.slice(fence.openLine, fence.closeLine + 1);
@@ -161008,6 +161574,7 @@ var BLOCK_FORMAT_VERSION;
161008
161574
  var init_sync_markdown = __esm({
161009
161575
  "../../packages/diagrams/src/markdown/sync-markdown.ts"() {
161010
161576
  "use strict";
161577
+ init_merge_schemes();
161011
161578
  init_diagram_block();
161012
161579
  init_extract_fences();
161013
161580
  init_locate_block();
@@ -161021,6 +161588,7 @@ var init_markdown = __esm({
161021
161588
  "use strict";
161022
161589
  init_diagram_block();
161023
161590
  init_extract_fences();
161591
+ init_dark_pictures();
161024
161592
  init_sync_markdown();
161025
161593
  }
161026
161594
  });
@@ -161302,6 +161870,7 @@ async function runSync(document2, settings, ops, cache, limit) {
161302
161870
  const result = await syncMarkdown(document2, settings.stem, {
161303
161871
  render,
161304
161872
  assetDir: settings.assetDir,
161873
+ ...settings.defaults?.schemes === void 0 ? {} : { schemes: settings.defaults.schemes },
161305
161874
  ...settings.prefix === void 0 ? {} : { idPrefix: settings.prefix }
161306
161875
  });
161307
161876
  return { result, calls };
@@ -161479,68 +162048,40 @@ var init_layout18 = __esm({
161479
162048
  }
161480
162049
  });
161481
162050
 
161482
- // ../../packages/diagrams/src/parse/icon-alias-notes.ts
161483
- function iconValues(tokens) {
161484
- const values = [];
161485
- for (let index2 = 0; index2 + 2 < tokens.length; index2 += 1) {
161486
- const key = tokens[index2];
161487
- if (key?.kind !== "word" || key.text !== "icon" && key.text !== "stack" || tokens[index2 + 1]?.kind !== "equals") continue;
161488
- let at3 = index2 + 2;
161489
- for (let value = tokens[at3]; isValue(value); value = tokens[at3]) {
161490
- values.push(value);
161491
- if (key.text !== "stack" || tokens[at3 + 1]?.kind !== "comma") break;
161492
- at3 += 2;
161493
- }
161494
- }
161495
- return values;
161496
- }
161497
- function iconAliasNotes(source) {
161498
- const notes = [];
161499
- for (const line3 of lex(source).lines) {
161500
- for (const value of iconValues(line3.tokens)) {
161501
- const target = iconAliasTarget(value.text);
161502
- if (target === null) continue;
161503
- notes.push({
161504
- code: ICON_ALIAS_NOTE,
161505
- severity: "info",
161506
- message: `"${value.text}" is not a bundled icon name, so ${target} was drawn`,
161507
- line: value.line,
161508
- column: value.column,
161509
- length: value.length,
161510
- hint: `Write ${target} to say so in the source.`
161511
- });
161512
- }
161513
- }
161514
- return notes;
161515
- }
161516
- var ICON_ALIAS_NOTE, isValue;
161517
- var init_icon_alias_notes = __esm({
161518
- "../../packages/diagrams/src/parse/icon-alias-notes.ts"() {
161519
- "use strict";
161520
- init_icons();
161521
- init_lexer();
161522
- ICON_ALIAS_NOTE = "I122";
161523
- isValue = (token) => token?.kind === "word" || token?.kind === "string";
161524
- }
161525
- });
161526
-
161527
162051
  // ../../packages/diagrams/src/quality/findings.ts
161528
- function turnHint(direction, wantsTaller) {
162052
+ function turnOption(direction, wantsTaller) {
161529
162053
  if (direction === null) return null;
161530
162054
  const isAcross = direction === "right" || direction === "left";
161531
162055
  const isDown = direction === "down" || direction === "up";
161532
- if (wantsTaller && !isDown) return "add direction=down to the header line";
161533
- if (!wantsTaller && !isAcross) return "add direction=right to the header line";
162056
+ if (wantsTaller && !isDown) return "direction=down";
162057
+ if (!wantsTaller && !isAcross) return "direction=right";
161534
162058
  return null;
161535
162059
  }
162060
+ function turnHint(direction, wantsTaller) {
162061
+ const option = turnOption(direction, wantsTaller);
162062
+ return option === null ? null : `add ${option} to the header line`;
162063
+ }
161536
162064
  function quote2(text3) {
161537
162065
  return text3.length > 32 ? `"${text3.slice(0, 30)}.."` : `"${text3}"`;
161538
162066
  }
162067
+ function namedCrossing(pair2) {
162068
+ if (pair2 === null) return { lines: null, ends: null };
162069
+ const [a, b] = pair2;
162070
+ const named = (line3) => line3.from !== null && line3.from !== "" && line3.to !== null && line3.to !== "" ? `${line3.from} -> ${line3.to}` : null;
162071
+ const first = named(a);
162072
+ const second = named(b);
162073
+ const lines = first === null || second === null ? null : `${first} and ${second}`;
162074
+ const ends = a.to !== null && b.to !== null && a.to !== "" && b.to !== "" && a.to !== b.to ? [a.to, b.to] : null;
162075
+ return { lines, ends };
162076
+ }
161539
162077
  function crossingFinding(m, context) {
161540
162078
  if (m.crossings === 0) return null;
161541
- const turn = turnHint(context.direction, true) ?? turnHint(context.direction, false);
161542
- const fix = turn === null ? "declare the nodes of each path next to each other so the layout keeps them in order" : `${turn}, or declare connected nodes next to each other`;
161543
- return { measure: "crossings", penalty: cap(m.crossings * 5, 30), hint: `${m.crossings === 1 ? "Two lines cross" : `Lines cross ${m.crossings} times`}: ${fix}.` };
162079
+ const turn = turnOption(context.direction, true) ?? turnOption(context.direction, false);
162080
+ const { lines, ends } = namedCrossing(context.measured.crossingPair);
162081
+ const group2 = ends === null ? "declare connected nodes next to each other" : `put ${ends[0]} and ${ends[1]} in one group so they sit side by side`;
162082
+ const fix = turn === null ? ends === null ? "declare the nodes of each path next to each other so the layout keeps them in order" : group2 : `try ${turn} on the header line, or ${group2}`;
162083
+ const count3 = m.crossings === 1 ? "Two lines cross" : `Lines cross ${m.crossings} times`;
162084
+ return { measure: "crossings", penalty: cap(m.crossings * 5, 30), hint: `${count3}${lines === null ? "" : ` (first ${lines})`}: ${fix}.` };
161544
162085
  }
161545
162086
  function detourFinding(m, context) {
161546
162087
  if (m.detour <= DETOUR_LIMIT) return null;
@@ -161723,23 +162264,26 @@ function shareAnEnd(a, b) {
161723
162264
  return ends.some((end) => end === b.from || end === b.to);
161724
162265
  }
161725
162266
  function countCrossings(lines) {
161726
- const bounds = lines.map((line3) => boundsOf2(line3.points));
162267
+ const bounds2 = lines.map((line3) => boundsOf2(line3.points));
161727
162268
  const segments = lines.map(segmentsOf2);
161728
162269
  let crossings2 = 0;
162270
+ let first = null;
161729
162271
  for (let i = 0; i < lines.length; i += 1) {
161730
162272
  for (let j = i + 1; j < lines.length; j += 1) {
161731
162273
  if (shareAnEnd(lines[i], lines[j])) continue;
161732
- if (!rectsCollide(inflate(bounds[i], 3), inflate(bounds[j], 3))) continue;
162274
+ if (!rectsCollide(inflate(bounds2[i], 3), inflate(bounds2[j], 3))) continue;
161733
162275
  const ends = [...endsOf2(lines[i]), ...endsOf2(lines[j])];
161734
162276
  for (const [a, b] of segments[i]) {
161735
162277
  for (const [c, d] of segments[j]) {
161736
162278
  const at3 = segmentCrossing(a, b, c, d);
161737
- if (at3 !== null && !ends.some((end) => near2(end, at3, END_CLEARANCE_PX))) crossings2 += 1;
162279
+ if (at3 === null || ends.some((end) => near2(end, at3, END_CLEARANCE_PX))) continue;
162280
+ crossings2 += 1;
162281
+ first ??= [lines[i], lines[j]];
161738
162282
  }
161739
162283
  }
161740
162284
  }
161741
162285
  }
161742
- return crossings2;
162286
+ return { count: crossings2, first };
161743
162287
  }
161744
162288
  function solidBoxes(boxes2) {
161745
162289
  return boxes2.filter((box) => !boxes2.some((other) => other !== box && encloses(box.rect, other.rect)));
@@ -161831,10 +162375,11 @@ function measureScene(scene) {
161831
162375
  const boxes2 = solidBoxes(scene.boxes);
161832
162376
  const over = linesOverBoxes(scene.lines, boxes2);
161833
162377
  const overlaps8 = overlappingLabels(scene.labels, boxes2);
162378
+ const crossings2 = countCrossings(scene.lines);
161834
162379
  const biggest = [...scene.groups].sort((a, b) => b.boxes - a.boxes || a.id.localeCompare(b.id))[0];
161835
162380
  return {
161836
162381
  measures: {
161837
- crossings: countCrossings(scene.lines),
162382
+ crossings: crossings2.count,
161838
162383
  lineOverBox: over.count,
161839
162384
  labelOverlaps: overlaps8.count,
161840
162385
  smallestTextPx: round(smallestText(scene), 1),
@@ -161849,6 +162394,7 @@ function measureScene(scene) {
161849
162394
  slices: scene.slices
161850
162395
  },
161851
162396
  lineOverBox: over.first,
162397
+ crossingPair: crossings2.first,
161852
162398
  labelPair: overlaps8.first,
161853
162399
  biggestGroup: biggest === void 0 || biggest.boxes === 0 ? null : { id: biggest.id, boxes: biggest.boxes }
161854
162400
  };
@@ -162263,16 +162809,17 @@ function toQualityDto(report3) {
162263
162809
  async function validateDiagramSource(source) {
162264
162810
  const notes = iconAliasNotes(source);
162265
162811
  const withNotes = notes.length === 0 ? {} : { notices: notes.map((note) => ({ ...note })) };
162812
+ const unknownIcons = [...unknownIconWarnings(source), ...secretWarnings(source)].map(diagnosticToDto);
162266
162813
  const parsed = parseDiagram(source);
162267
162814
  if (!parsed.ok) {
162268
- return { valid: false, kind: guessKind(source), errors: parsed.error.map(diagnosticToDto), warnings: [], summary: null, size: null, ...withNotes };
162815
+ return { valid: false, kind: guessKind(source), errors: parsed.error.map(diagnosticToDto), warnings: unknownIcons, summary: null, size: null, ...withNotes };
162269
162816
  }
162270
162817
  const { size, overlayCovers } = await diagramMeasure(parsed.value);
162271
162818
  return {
162272
162819
  valid: true,
162273
162820
  kind: parsed.value.kind,
162274
162821
  errors: [],
162275
- warnings: lintDiagram(parsed.value, size, overlayCovers).map(diagnosticToDto),
162822
+ warnings: [...unknownIcons, ...lintDiagram(parsed.value, size, overlayCovers).map(diagnosticToDto)],
162276
162823
  summary: summarizeDiagram(parsed.value),
162277
162824
  size,
162278
162825
  quality: toQualityDto(await assessQuality(parsed.value)),
@@ -162289,6 +162836,7 @@ var init_validate_diagram = __esm({
162289
162836
  init_guess_kind();
162290
162837
  init_icon_alias_notes();
162291
162838
  init_quality();
162839
+ init_secrets();
162292
162840
  init_to_dto();
162293
162841
  }
162294
162842
  });
@@ -162300,6 +162848,7 @@ var init_services = __esm({
162300
162848
  init_build_vocabulary();
162301
162849
  init_compare_diagrams2();
162302
162850
  init_diagram_id();
162851
+ init_classification_stamp();
162303
162852
  init_to_dto();
162304
162853
  init_prose();
162305
162854
  init_registry2();
@@ -162309,10 +162858,12 @@ var init_services = __esm({
162309
162858
  init_render_pair();
162310
162859
  init_source_metadata();
162311
162860
  init_picture_facts();
162861
+ init_dark_pictures();
162312
162862
  init_render_diagram_svg();
162313
162863
  init_search_icon_names();
162314
162864
  init_sync_document();
162315
162865
  init_validate_diagram();
162866
+ init_secrets();
162316
162867
  }
162317
162868
  });
162318
162869
 
@@ -166038,8 +166589,8 @@ function enforceDeletedFields(method, result) {
166038
166589
  }
166039
166590
  return next;
166040
166591
  };
166041
- const tools = result.tools;
166042
- if (method === "tools/list" && Array.isArray(tools) && tools.some((tool) => isPlainObject$4(tool) && "execution" in tool)) copy().tools = tools.map((tool) => {
166592
+ const tools2 = result.tools;
166593
+ if (method === "tools/list" && Array.isArray(tools2) && tools2.some((tool) => isPlainObject$4(tool) && "execution" in tool)) copy().tools = tools2.map((tool) => {
166043
166594
  if (!isPlainObject$4(tool) || !("execution" in tool)) return tool;
166044
166595
  const rest = { ...tool };
166045
166596
  delete rest["execution"];
@@ -166894,11 +167445,11 @@ var init_src_BHSMhZ_W = __esm({
166894
167445
  },
166895
167446
  encodeResult(method, result) {
166896
167447
  if (method !== "tools/list") return result;
166897
- const tools = result.tools;
166898
- if (!Array.isArray(tools) || !tools.some((t) => toolNeedsLegacyWrap(t))) return result;
167448
+ const tools2 = result.tools;
167449
+ if (!Array.isArray(tools2) || !tools2.some((t) => toolNeedsLegacyWrap(t))) return result;
166899
167450
  return {
166900
167451
  ...result,
166901
- tools: tools.map((t) => toolNeedsLegacyWrap(t) ? {
167452
+ tools: tools2.map((t) => toolNeedsLegacyWrap(t) ? {
166902
167453
  ...t,
166903
167454
  outputSchema: wrapOutputSchemaForLegacy(t.outputSchema)
166904
167455
  } : t)
@@ -177809,6 +178360,7 @@ var init_sources2 = __esm({
177809
178360
  options: SourceOptionsSchema.optional(),
177810
178361
  overrides: repositoryPath.refine((path) => path.endsWith(".json"), { message: "An overrides file is a .json file" }).optional().describe("The overrides file, applied after every import. Left out: the out path with .overrides.json in place of .diagram, or <file>.<fence id>.overrides.json beside a Markdown file."),
177811
178362
  pictures: external_exports.boolean().optional().describe("For a .diagram out: also write its light and dark SVG beside it. On when left out."),
178363
+ schemes: external_exports.enum(PICTURE_FILE_SCHEMES).optional().describe("The pictures this source writes: light-and-dark writes <name>.svg and <name>.dark.svg; auto writes one <name>.svg that follows the reader's light or dark setting. defaults.schemes, then light-and-dark, when left out."),
177812
178364
  publish: SourcePublishSchema.optional()
177813
178365
  }).meta({ id: "Source", description: "One diagram generated from files of the repository and kept in step with them." });
177814
178366
  }
@@ -177834,6 +178386,7 @@ var init_schema4 = __esm({
177834
178386
  numbered: external_exports.enum(SWITCH_VALUES).optional().describe("numbered= on every header that takes it: on numbers every line in the order written."),
177835
178387
  theme: external_exports.enum(PICTURE_SCHEMES).optional().describe("The color scheme the command line and the GitHub Action draw a single picture in."),
177836
178388
  embedSource: external_exports.boolean().optional().describe("Write the source into every SVG the command line, the GitHub Action, and the drawing tools save."),
178389
+ schemes: external_exports.enum(PICTURE_FILE_SCHEMES).optional().describe("The pictures generate and sync write: light-and-dark (the default) writes <name>.svg and <name>.dark.svg; auto writes one <name>.svg that holds both and follows the reader's light or dark setting, so GitHub shows it right in either theme."),
177837
178390
  kinds: external_exports.partialRecord(external_exports.enum(DIAGRAM_KINDS), external_exports.record(optionKey, optionValue)).optional().describe('Header options for one kind, such as { "mindmap": { "layout": "radial" } }. A value the kind refuses is left out with warning S200.')
177838
178391
  }).meta({ id: "SettingsDefaults", description: "Header options a diagram gets when its header does not set them." });
177839
178392
  SettingsBrandSchema = external_exports.strictObject({
@@ -177968,7 +178521,7 @@ var init_workflows = __esm({
177968
178521
  why: external_exports.string().describe("Why they were left out, and what to do.")
177969
178522
  }).describe("Present only when pictures were left out because the answer would have been too big for an AI client to read in one piece.");
177970
178523
  ViewUrlSchema = external_exports.string().describe(
177971
- "A link that shows a valid diagram in a browser; give it to the person who wants to look. The source is in the part after #, never sent to a server, but anyone with the link can read it. Absent when too long; next says so."
178524
+ "A link that shows a valid diagram in a browser; give it to the person who wants to look. It holds the drawing itself: the source is in the part after #, never sent to a server, so nothing is saved on Plotwork and it appears in no Diagrams list; anyone with the link can read it. Absent when too long; next says so."
177972
178525
  );
177973
178526
  PngUrlSchema = external_exports.string().describe(
177974
178527
  "The viewUrl with &download=png: opening it in a browser saves the diagram as a PNG for Slack, email, or a wiki. The PNG is drawn in the person's browser, not on a server, so it is a link to open, not an image address to embed. Absent when too long."
@@ -178724,7 +179277,9 @@ var init_patterns2 = __esm({
178724
179277
  kind: KindNameSchema,
178725
179278
  tags: external_exports.array(external_exports.string()),
178726
179279
  providers: external_exports.array(FlavourSchema).describe("The flavours the pattern comes in."),
178727
- score: external_exports.number().describe("How well it matches; only the order of the results is meaningful.")
179280
+ score: external_exports.number().describe("How well it matches; only the order of the results is meaningful."),
179281
+ origin: external_exports.literal("organisation").optional().describe("Present on a pattern of your organisation's own, which it approved and which comes first. Absent on the built-in patterns."),
179282
+ label: external_exports.literal("Your organisation's pattern").optional().describe("Present, with origin, on a pattern of your organisation: the words to show beside it.")
178728
179283
  });
178729
179284
  FindPatternResponseSchema = external_exports.object({
178730
179285
  query: external_exports.string().describe("The query that was searched."),
@@ -179033,6 +179588,182 @@ var init_tool_settings = __esm({
179033
179588
  }
179034
179589
  });
179035
179590
 
179591
+ // ../../packages/diagrams/src/tools/json-schema.ts
179592
+ function referencedDefs(node3) {
179593
+ return [...JSON.stringify(node3).matchAll(DEF_REF)].map((match) => match[1] ?? "");
179594
+ }
179595
+ function reachableDefs(root, defs) {
179596
+ const reached = /* @__PURE__ */ new Set();
179597
+ const pending = referencedDefs(root);
179598
+ for (let name2 = pending.pop(); name2 !== void 0; name2 = pending.pop()) {
179599
+ const def = defs[name2];
179600
+ if (def === void 0 || reached.has(name2)) continue;
179601
+ reached.add(name2);
179602
+ pending.push(...referencedDefs(def));
179603
+ }
179604
+ return Object.fromEntries(Object.entries(defs).filter(([name2]) => reached.has(name2)));
179605
+ }
179606
+ function inlineRootRef(schema) {
179607
+ const ref = schema["$ref"];
179608
+ const defs = schema["$defs"];
179609
+ if (typeof ref !== "string" || typeof defs !== "object" || defs === null) return schema;
179610
+ const target = defs[ref.replace("#/$defs/", "")];
179611
+ if (target === void 0) return schema;
179612
+ const { $ref: _removed, $defs: _defs, ...header } = schema;
179613
+ const root = { ...header, ...target };
179614
+ const kept2 = reachableDefs(root, defs);
179615
+ return Object.keys(kept2).length === 0 ? root : { ...root, $defs: kept2 };
179616
+ }
179617
+ function remembered(cache, key, make) {
179618
+ const known3 = cache.get(key);
179619
+ if (known3 !== void 0) return known3;
179620
+ const made = make();
179621
+ cache.set(key, made);
179622
+ return made;
179623
+ }
179624
+ function inputJsonSchema(tool) {
179625
+ return inputJsonSchemaOf(tool.inputSchema);
179626
+ }
179627
+ function inputJsonSchemaOf(schema) {
179628
+ return remembered(inputSchemas, schema, () => portable(withoutSafeBounds(inlineRootRef(external_exports.toJSONSchema(schema, { target: TARGET, io: "input" })))));
179629
+ }
179630
+ function portable(node3) {
179631
+ if (Array.isArray(node3)) return node3.map(portable);
179632
+ if (typeof node3 !== "object" || node3 === null) return node3;
179633
+ return Object.fromEntries(
179634
+ Object.entries(node3).filter(([key, value]) => !(key === "propertyNames" && JSON.stringify(value) === '{"type":"string"}')).map(([key, value]) => [key, key === "additionalProperties" && JSON.stringify(value) === "{}" ? true : portable(value)])
179635
+ );
179636
+ }
179637
+ function withoutSafeBounds(node3) {
179638
+ if (Array.isArray(node3)) return node3.map(withoutSafeBounds);
179639
+ if (typeof node3 !== "object" || node3 === null) return node3;
179640
+ return Object.fromEntries(
179641
+ Object.entries(node3).filter(([key, value]) => !(key === "minimum" && value === Number.MIN_SAFE_INTEGER || key === "maximum" && value === Number.MAX_SAFE_INTEGER)).map(([key, value]) => [key, withoutSafeBounds(value)])
179642
+ );
179643
+ }
179644
+ function openObjects(node3) {
179645
+ if (Array.isArray(node3)) return node3.map(openObjects);
179646
+ if (typeof node3 !== "object" || node3 === null) return node3;
179647
+ return Object.fromEntries(
179648
+ Object.entries(node3).filter(([key, value]) => !(key === "additionalProperties" && value === false)).map(([key, value]) => [key, openObjects(value)])
179649
+ );
179650
+ }
179651
+ function outputJsonSchema(tool) {
179652
+ return remembered(outputSchemas, tool.outputSchema, () => withoutSafeBounds(openObjects(inlineRootRef(external_exports.toJSONSchema(tool.outputSchema, { target: TARGET, io: "output" })))));
179653
+ }
179654
+ function withoutProse(node3, isProperties = false) {
179655
+ if (Array.isArray(node3)) return node3.map((item) => withoutProse(item));
179656
+ if (typeof node3 !== "object" || node3 === null) return node3;
179657
+ return Object.fromEntries(
179658
+ Object.entries(node3).filter(([key]) => isProperties || !LEFT_OUT.has(key)).map(([key, value]) => [key, withoutProse(value, !isProperties && (key === "properties" || key === "$defs"))])
179659
+ );
179660
+ }
179661
+ function listedOutputSchema(schema) {
179662
+ return remembered(listedSchemas, schema, () => withoutProse(withoutSafeBounds(schema)));
179663
+ }
179664
+ function listedOutputJsonSchema(tool) {
179665
+ return listedOutputSchema(outputJsonSchema(tool));
179666
+ }
179667
+ var TARGET, DEF_REF, inputSchemas, outputSchemas, listedSchemas, LEFT_OUT;
179668
+ var init_json_schema2 = __esm({
179669
+ "../../packages/diagrams/src/tools/json-schema.ts"() {
179670
+ "use strict";
179671
+ init_zod();
179672
+ TARGET = "draft-2020-12";
179673
+ DEF_REF = /"\$ref":"#\/\$defs\/([^"]+)"/g;
179674
+ inputSchemas = /* @__PURE__ */ new WeakMap();
179675
+ outputSchemas = /* @__PURE__ */ new WeakMap();
179676
+ listedSchemas = /* @__PURE__ */ new WeakMap();
179677
+ LEFT_OUT = /* @__PURE__ */ new Set(["description", "$schema", "title", "enum"]);
179678
+ }
179679
+ });
179680
+
179681
+ // ../../packages/diagrams/src/tools/input-hint.ts
179682
+ function asObject(value) {
179683
+ return typeof value === "object" && value !== null && !Array.isArray(value) ? value : null;
179684
+ }
179685
+ function bounds(schema) {
179686
+ const low = schema["minimum"] ?? schema["minLength"] ?? schema["minItems"];
179687
+ const high = schema["maximum"] ?? schema["maxLength"] ?? schema["maxItems"];
179688
+ const unit3 = schema["type"] === "string" ? " characters" : schema["type"] === "array" ? " items" : "";
179689
+ if (typeof high === "number" && low === 1 && unit3 !== "") return `, at most ${high}${unit3}`;
179690
+ if (typeof low === "number" && typeof high === "number") return `, ${low} to ${high}${unit3}`;
179691
+ if (typeof high === "number") return `, at most ${high}${unit3}`;
179692
+ if (typeof low === "number" && low > 0) return `, at least ${low}${unit3}`;
179693
+ return "";
179694
+ }
179695
+ function fieldType(node3) {
179696
+ const schema = asObject(node3);
179697
+ if (schema === null) return "any value";
179698
+ const values = schema["enum"];
179699
+ if (Array.isArray(values)) {
179700
+ const listed2 = values.slice(0, ENUM_LISTED).map((value) => JSON.stringify(value));
179701
+ return `one of ${listed2.join(", ")}${values.length > ENUM_LISTED ? `, and ${values.length - ENUM_LISTED} more` : ""}`;
179702
+ }
179703
+ if ("const" in schema) return JSON.stringify(schema["const"]);
179704
+ const union2 = schema["anyOf"] ?? schema["oneOf"];
179705
+ if (Array.isArray(union2)) return [...new Set(union2.map(fieldType))].join(" or ");
179706
+ const type = schema["type"];
179707
+ if (Array.isArray(type)) return type.join(" or ");
179708
+ if (type === "array") return `array of ${fieldType(schema["items"])}${bounds(schema)}`;
179709
+ if (type === "object") {
179710
+ const properties = Object.keys(asObject(schema["properties"]) ?? {});
179711
+ return properties.length === 0 ? "object" : `object with ${properties.join(", ")}`;
179712
+ }
179713
+ return typeof type === "string" ? `${type}${bounds(schema)}` : "any value";
179714
+ }
179715
+ function shortExample(example, required2) {
179716
+ const call = asObject(example);
179717
+ if (call === null) return null;
179718
+ const full = JSON.stringify(call);
179719
+ if (full.length <= EXAMPLE_CHARACTERS) return full;
179720
+ return JSON.stringify(Object.fromEntries(Object.entries(call).filter(([key]) => required2.includes(key))));
179721
+ }
179722
+ function namedFields(issues) {
179723
+ return [...new Set(issues.map((issue3) => issue3.path[0]).filter((key) => typeof key === "string"))];
179724
+ }
179725
+ function unknownKeys(issues) {
179726
+ return issues.flatMap((issue3) => issue3.code === "unrecognized_keys" && issue3.path.length === 0 ? issue3.keys : []);
179727
+ }
179728
+ function wrapperOf(args, properties) {
179729
+ const call = asObject(args);
179730
+ if (call === null) return null;
179731
+ const keys = Object.keys(call);
179732
+ const only = keys.length === 1 ? keys[0] : void 0;
179733
+ if (only === void 0 || !WRAPPER_KEYS.includes(only) || Object.hasOwn(properties, only)) return null;
179734
+ const inner = call[only];
179735
+ if (typeof inner === "string") return only;
179736
+ const wrapped2 = asObject(inner);
179737
+ return wrapped2 !== null && (Object.keys(wrapped2).length === 0 || Object.keys(wrapped2).some((key) => Object.hasOwn(properties, key))) ? only : null;
179738
+ }
179739
+ function inputHint(tool, args, issues) {
179740
+ const schema = inputJsonSchemaOf(tool.inputSchema);
179741
+ const properties = asObject(schema["properties"]) ?? {};
179742
+ const required2 = Array.isArray(schema["required"]) ? schema["required"] : [];
179743
+ const sentences = [];
179744
+ const wrapper = wrapperOf(args, properties);
179745
+ if (asObject(args) === null) sentences.push(`Pass the arguments as a JSON object, not ${args === null || args === void 0 ? "nothing" : typeof args}.`);
179746
+ if (wrapper !== null) sentences.push(`Put the fields at the top level of the arguments, not inside "${wrapper}".`);
179747
+ if (required2.length > 0) sentences.push(`${tool.name} needs ${required2.map((key) => `${key} (${fieldType(properties[key])})`).join(", ")}.`);
179748
+ const wrong = namedFields(issues).filter((key) => !required2.includes(key) && Object.hasOwn(properties, key));
179749
+ if (wrong.length > 0) sentences.push(`${wrong.map((key) => `${key} takes ${fieldType(properties[key])}`).join("; ")}.`);
179750
+ const unknown2 = unknownKeys(issues).filter((key) => key !== wrapper);
179751
+ if (unknown2.length > 0) sentences.push(`It does not take ${unknown2.join(", ")}; its fields are ${Object.keys(properties).join(", ")}.`);
179752
+ const example = shortExample(tool.callExample, required2);
179753
+ if (example !== null) sentences.push(`Example call: ${tool.name} ${example}`);
179754
+ return sentences.join(" ");
179755
+ }
179756
+ var WRAPPER_KEYS, ENUM_LISTED, EXAMPLE_CHARACTERS;
179757
+ var init_input_hint = __esm({
179758
+ "../../packages/diagrams/src/tools/input-hint.ts"() {
179759
+ "use strict";
179760
+ init_json_schema2();
179761
+ WRAPPER_KEYS = ["arguments", "args", "input", "params", "parameters", "kwargs"];
179762
+ ENUM_LISTED = 8;
179763
+ EXAMPLE_CHARACTERS = 320;
179764
+ }
179765
+ });
179766
+
179036
179767
  // ../../packages/diagrams/src/tools/settings-ops.ts
179037
179768
  function defaultedOps(ops, defaults) {
179038
179769
  if (defaults === void 0) return ops;
@@ -180695,11 +181426,14 @@ function scoreOf(pattern3, query, phrase2) {
180695
181426
  return score;
180696
181427
  }
180697
181428
  function findPatterns(query, filters = {}) {
181429
+ return findPatternsIn(listPatterns(), query, filters);
181430
+ }
181431
+ function findPatternsIn(patterns, query, filters = {}) {
180698
181432
  const wanted2 = words(query);
180699
181433
  const phrase2 = wanted2.join(" ");
180700
181434
  const tags = (filters.tags ?? []).map((tag) => tag.toLowerCase());
180701
181435
  const limit = Math.max(1, Math.min(filters.limit ?? PATTERN_RESULT_LIMIT, 20));
180702
- return listPatterns().filter((pattern3) => filters.provider === void 0 || flavoursOf(pattern3).includes(filters.provider)).filter((pattern3) => filters.kind === void 0 || pattern3.kind === filters.kind).filter((pattern3) => tags.every((tag) => pattern3.tags.some((candidate2) => candidate2.toLowerCase() === tag))).map((pattern3, index2) => ({ pattern: pattern3, index: index2, score: scoreOf(pattern3, wanted2, phrase2) })).filter((entry2) => wanted2.length === 0 || entry2.score > 0).sort((a, b) => b.score - a.score || a.index - b.index).slice(0, limit).map(({ pattern: pattern3, score }) => ({
181436
+ return patterns.filter((pattern3) => filters.provider === void 0 || flavoursOf(pattern3).includes(filters.provider)).filter((pattern3) => filters.kind === void 0 || pattern3.kind === filters.kind).filter((pattern3) => tags.every((tag) => pattern3.tags.some((candidate2) => candidate2.toLowerCase() === tag))).map((pattern3, index2) => ({ pattern: pattern3, index: index2, score: scoreOf(pattern3, wanted2, phrase2) })).filter((entry2) => wanted2.length === 0 || entry2.score > 0).sort((a, b) => b.score - a.score || a.index - b.index).slice(0, limit).map(({ pattern: pattern3, score }) => ({
180703
181437
  id: pattern3.id,
180704
181438
  title: pattern3.title,
180705
181439
  summary: pattern3.summary,
@@ -180758,9 +181492,14 @@ var init_slots = __esm({
180758
181492
  // ../../packages/diagrams/src/patterns/fill-pattern.ts
180759
181493
  function fillPattern(id, flavour, values = {}) {
180760
181494
  const pattern3 = getPattern(id);
180761
- if (pattern3 === void 0) {
180762
- return err([{ code: "unknown-pattern", message: `Unknown pattern "${id}"`, hint: `${didYouMean(id, listPatternIds())} Search with find_pattern.` }]);
180763
- }
181495
+ if (pattern3 === void 0) return unknownPattern(id, listPatternIds());
181496
+ return fillPatternFrom(pattern3, flavour, values);
181497
+ }
181498
+ function unknownPattern(id, known3) {
181499
+ return err([{ code: "unknown-pattern", message: `Unknown pattern "${id}"`, hint: `${didYouMean(id, known3)} Search with find_pattern.` }]);
181500
+ }
181501
+ function fillPatternFrom(pattern3, flavour, values = {}) {
181502
+ const id = pattern3.id;
180764
181503
  const chosen = PATTERN_FLAVOURS.find((candidate2) => candidate2 === flavour);
180765
181504
  const template = chosen === void 0 ? void 0 : pattern3.templates[chosen];
180766
181505
  if (chosen === void 0 || template === void 0) {
@@ -180814,12 +181553,27 @@ var init_fill_pattern = __esm({
180814
181553
  }
180815
181554
  });
180816
181555
 
181556
+ // ../../packages/diagrams/src/patterns/org-patterns.ts
181557
+ var init_org_patterns = __esm({
181558
+ "../../packages/diagrams/src/patterns/org-patterns.ts"() {
181559
+ "use strict";
181560
+ init_core();
181561
+ init_parse20();
181562
+ init_fill_pattern();
181563
+ init_find_patterns();
181564
+ init_registry3();
181565
+ init_slots();
181566
+ init_types4();
181567
+ }
181568
+ });
181569
+
180817
181570
  // ../../packages/diagrams/src/patterns/index.ts
180818
181571
  var init_patterns3 = __esm({
180819
181572
  "../../packages/diagrams/src/patterns/index.ts"() {
180820
181573
  "use strict";
180821
181574
  init_find_patterns();
180822
181575
  init_fill_pattern();
181576
+ init_org_patterns();
180823
181577
  init_pattern_tree();
180824
181578
  init_registry3();
180825
181579
  init_slots();
@@ -191566,7 +192320,7 @@ function readColumn(text3) {
191566
192320
  const chain2 = readChain(value, close2 + 1);
191567
192321
  const has = (method) => chain2.some((entry2) => entry2.name === method);
191568
192322
  const references2 = chain2.find((entry2) => entry2.name === "references");
191569
- const target = references2 === void 0 ? null : TARGET.exec(references2.args);
192323
+ const target = references2 === void 0 ? null : TARGET2.exec(references2.args);
191570
192324
  return {
191571
192325
  key,
191572
192326
  name: name2 ?? key,
@@ -191594,13 +192348,13 @@ function callsOf(text3, name2) {
191594
192348
  }
191595
192349
  return calls;
191596
192350
  }
191597
- var BUILDER, TARGET, SERIALS;
192351
+ var BUILDER, TARGET2, SERIALS;
191598
192352
  var init_columns2 = __esm({
191599
192353
  "../../packages/diagrams/src/importers/drizzle/columns.ts"() {
191600
192354
  "use strict";
191601
192355
  init_scan3();
191602
192356
  BUILDER = /^([A-Za-z_$][\w$]*(?:\.[A-Za-z_$][\w$]*)*)\s*\(/;
191603
- TARGET = /=>\s*([A-Za-z_$][\w$]*)\.([A-Za-z_$][\w$]*)/;
192357
+ TARGET2 = /=>\s*([A-Za-z_$][\w$]*)\.([A-Za-z_$][\w$]*)/;
191604
192358
  SERIALS = /* @__PURE__ */ new Set(["serial", "bigserial", "smallserial"]);
191605
192359
  }
191606
192360
  });
@@ -196727,17 +197481,22 @@ var init_ops = __esm({
196727
197481
  function settingsOf(input2) {
196728
197482
  return input2?.settings;
196729
197483
  }
196730
- function invalidInput(issues) {
197484
+ function invalidInput(tool, args, issues) {
196731
197485
  return {
196732
197486
  kind: "invalid-input",
196733
- message: "The arguments did not match the input schema.",
196734
- issues: issues.map((issue3) => ({ path: issue3.path.join("."), message: issue3.message }))
197487
+ message: `The arguments did not match the input schema of ${tool.name}.`,
197488
+ issues: issues.map((issue3) => ({ path: issue3.path.join("."), message: issue3.message })),
197489
+ hint: inputHint({ name: tool.name, inputSchema: tool.input, callExample: tool.callExample }, args, issues)
196735
197490
  };
196736
197491
  }
197492
+ function checkToolInput(tool, args) {
197493
+ const parsed = tool.inputSchema.safeParse(args);
197494
+ return parsed.success ? null : invalidInput({ name: tool.name, input: tool.inputSchema, callExample: tool.callExample }, args, parsed.error.issues);
197495
+ }
196737
197496
  function defineTool(spec) {
196738
197497
  const runWith = async (args, ops) => {
196739
197498
  const parsed = spec.input.safeParse(args);
196740
- if (!parsed.success) return err(invalidInput(parsed.error.issues));
197499
+ if (!parsed.success) return err(invalidInput({ ...spec, callExample: spec.callExample ?? null }, args, parsed.error.issues));
196741
197500
  const settled = settleToolInput(parsed.data);
196742
197501
  const answer = await spec.execute(settled.input, defaultedOps(ops, settingsOf(parsed.data)?.defaults));
196743
197502
  return answer.ok ? ok(settled.finish(answer.value)) : answer;
@@ -196754,6 +197513,8 @@ function defineTool(spec) {
196754
197513
  maxCalls: 1,
196755
197514
  example: null,
196756
197515
  prompts: [],
197516
+ callExample: spec.callExample ?? null,
197517
+ compact: spec.compact ?? null,
196757
197518
  run: (args) => runWith(args, ENGINE_OPS),
196758
197519
  runWith
196759
197520
  };
@@ -196761,7 +197522,7 @@ function defineTool(spec) {
196761
197522
  function defineWorkflow(spec) {
196762
197523
  const runWith = async (args, ops) => {
196763
197524
  const parsed = spec.input.safeParse(args);
196764
- if (!parsed.success) return err(invalidInput(parsed.error.issues));
197525
+ if (!parsed.success) return err(invalidInput({ ...spec, callExample: spec.callExample ?? spec.example }, args, parsed.error.issues));
196765
197526
  const settled = settleToolInput(parsed.data, { rewriteSource: false });
196766
197527
  return ok(settled.finish(await spec.execute(settled.input, defaultedOps(ops, settingsOf(parsed.data)?.defaults))));
196767
197528
  };
@@ -196777,6 +197538,8 @@ function defineWorkflow(spec) {
196777
197538
  maxCalls: spec.maxCalls,
196778
197539
  example: spec.example,
196779
197540
  prompts: spec.prompts,
197541
+ callExample: spec.callExample ?? spec.example,
197542
+ compact: spec.compact ?? null,
196780
197543
  run: (args) => runWith(args, ENGINE_OPS),
196781
197544
  runWith
196782
197545
  };
@@ -196787,6 +197550,7 @@ var init_define_tool = __esm({
196787
197550
  "use strict";
196788
197551
  init_core();
196789
197552
  init_tool_settings();
197553
+ init_input_hint();
196790
197554
  init_settings_ops();
196791
197555
  init_ops();
196792
197556
  READ_ONLY_ANNOTATIONS = {
@@ -196819,6 +197583,7 @@ var init_definitions = __esm({
196819
197583
  name: "validate_diagram",
196820
197584
  title: "Validate diagram",
196821
197585
  description: "Check diagram source without drawing it: every error in one pass, each with line, column, and a fix hint, plus quality warnings. An icon a label names for certain is drawn already; W204 gives the exact icon=provider:name for a node whose label names a product it does not draw (a brand whose name is also an everyday word, or every match under icons=off), W205 the type= for a group whose name matches a group type, and W206 flags an overlay framing a node that is not its member. These suggestions are not applied for you: add one, or icon=none to keep a node plain, and validate again. Prefer draw_diagram, which checks, describes, and draws in one call.",
197586
+ callExample: { source: 'flow\nnode api service "API"\nnode db database "DB"\napi -> db : "reads"' },
196822
197587
  input: DiagramSourceInputSchema,
196823
197588
  output: ValidateResponseSchema,
196824
197589
  execute: async (input2) => ok(await validateDiagramSource(input2.source))
@@ -196827,6 +197592,7 @@ var init_definitions = __esm({
196827
197592
  name: "render_diagram",
196828
197593
  title: "Render diagram",
196829
197594
  description: "Render valid source to a self-contained, accessible SVG in the light or dark theme, with its pixel size and quality warnings. Source with errors fails with its diagnostics. Set embedSource true to save the SVG in a repository, so read_diagram can give the source back. Prefer draw_diagram, which validates, outlines, and renders in one call.",
197595
+ callExample: { source: 'flow\nnode api service "API"\nnode db database "DB"\napi -> db : "reads"' },
196830
197596
  input: RenderInputSchema,
196831
197597
  output: RenderResponseSchema,
196832
197598
  execute: async (input2, ops) => {
@@ -196838,6 +197604,7 @@ var init_definitions = __esm({
196838
197604
  name: "outline_diagram",
196839
197605
  title: "Outline diagram",
196840
197606
  description: "Describe valid diagram source as plain text: participants, steps, tables, and connections in reading order, to check the diagram says what you meant or to use as alt text. Source with errors fails with diagnostics. Does not render. Prefer draw_diagram, which returns the outline with the check and the pictures.",
197607
+ callExample: { source: 'flow\nnode api service "API"\nnode db database "DB"\napi -> db : "reads"' },
196841
197608
  input: DiagramSourceInputSchema,
196842
197609
  output: OutlineResponseSchema,
196843
197610
  execute: async (input2) => {
@@ -196849,6 +197616,7 @@ var init_definitions = __esm({
196849
197616
  name: "search_icons",
196850
197617
  title: "Search icons",
196851
197618
  description: 'Find bundled icon names by keyword, idea, product, or abbreviation ("postgres", "token exchange", "s3", "cosmos db"). Returns set:name references, best first, at most 100, such as lucide:database, simple:postgresql, aws:lambda. Cloud products are in one set per provider (aws, gcp, azure, alibaba, oci, ibm, cloudflare, digitalocean, vercel), with every official aws, azure, and gcp icon; <provider>:cloud is the provider, for a group. Use it before setting icon= or a name in stack=. Search with the product name exactly as the user wrote it and take the first result; never invent a name, because an unknown icon is an error. For several names prefer map_icons: up to 40 in one call, and it never guesses. Hosted calls also find the organisation icons, as org:name.',
197619
+ callExample: { q: "postgres" },
196852
197620
  input: IconSearchQuerySchema,
196853
197621
  output: IconSearchResponseSchema,
196854
197622
  execute: async (input2) => ok(searchIconNames(input2))
@@ -196857,6 +197625,11 @@ var init_definitions = __esm({
196857
197625
  name: "get_diagram_syntax",
196858
197626
  title: "Get diagram syntax",
196859
197627
  description: "Read the diagram language as data. Call it once with no kind before your first diagram: the overview, the tables every kind shares (node types, arrows including dotted ..> for asynchronous calls, animated and numbered lines, icon sets, size limits, how to edit an existing SVG), and one line about each kind. For one kind in full, call it again with kind set to it: its statements, limits, and a tested example. kind flow adds the group types (type=), overlays, stack= marks, and a complete cloud architecture example; build the group tree top-down with type=, one node per service, and icons from map_icons or search_icons. For a common architecture, find_pattern gives a checked diagram to adapt. topic import-formats lists what import_source reads.",
197628
+ callExample: { kind: "sequence" },
197629
+ compact: {
197630
+ description: "Returns the diagram language as data. Call it with kind set to the kind you draw (such as sequence or flow): its statements, limits, and a tested example to copy. With no kind it returns the shared overview, which is long.",
197631
+ inputs: { kind: "The kind to read in full, such as sequence or flow." }
197632
+ },
196860
197633
  input: SyntaxInputSchema,
196861
197634
  output: SyntaxResponseSchema,
196862
197635
  execute: async (input2) => ok(buildSyntax(input2.kind, input2.topic))
@@ -196865,6 +197638,7 @@ var init_definitions = __esm({
196865
197638
  name: "read_diagram",
196866
197639
  title: "Read diagram",
196867
197640
  description: "Read the source of an existing Plotwork SVG so you can edit the diagram. Send the text of an .svg file as svg, or a hosted link (https://cdn.plotwork.dev/d/<22 characters>.svg) as url. Returns the exact source, its kind, the stored diagram id if it was published, and a parse check. Call it first when asked to change a diagram that already exists, then edit the source and call draw_diagram (or edit_diagram); next says how to save or publish it again. Only a picture saved with embedSource true (or by sync_markdown) carries its source; otherwise status is no-source, with the title, outline, and labels to rebuild it from. A text that is not an SVG and a refused or unreachable link come back as data. Only cdn.plotwork.dev and cdn-preview.plotwork.dev are fetched (https, no redirects, 5 seconds, 1 MB); svg reads nothing from the network.",
197641
+ callExample: { svg: '<svg xmlns="http://www.w3.org/2000/svg">...</svg>' },
196868
197642
  input: ReadDiagramInputSchema,
196869
197643
  output: ReadDiagramResponseSchema,
196870
197644
  annotations: { openWorldHint: true },
@@ -197397,6 +198171,7 @@ var init_compare_diagrams3 = __esm({
197397
198171
  name: "compare_diagrams",
197398
198172
  title: "Compare diagrams",
197399
198173
  description: "Compare two versions of a diagram by meaning, for a pull request review. Send before and after, each as source, the text of a Plotwork SVG that carries its source, or a cdn.plotwork.dev link. Returns every statement added, removed, renamed (by id or label), moved to another block, or changed (options, type, edge arrow or label), with counts and a plain-language summary; markdown true adds a block ready to paste as a comment. Reordered or reformatted lines are no change. A side with no source is reported, not an error. Lays nothing out; fetches only a link.",
198174
+ callExample: { before: 'flow\nnode a service "API"', after: 'flow\nnode a service "API"\nnode b database "DB"\na -> b' },
197400
198175
  input: CompareDiagramsInputSchema,
197401
198176
  output: CompareDiagramsResponseSchema,
197402
198177
  annotations: { openWorldHint: true },
@@ -197495,6 +198270,10 @@ var init_convert_mermaid2 = __esm({
197495
198270
  name: "convert_mermaid",
197496
198271
  title: "Convert Mermaid",
197497
198272
  description: "Workflow. Converts one Mermaid diagram (" + mermaidTypesList() + ") to Plotwork source. Returns the source, a diagnostic with a hint for everything dropped or changed (styling, links, activations), the check of the result with its icon and group-type suggestions, and an outline; render true also draws it, with picturesOmitted, viewUrl, pngUrl, and saveCommand as in draw_diagram. A Mermaid type Plotwork does not draw comes back as one diagnostic saying what to do instead. Deterministic: never throws on bad input, does not fetch URLs or read files. For a whole Markdown document use sync_markdown with convertMermaid true. Replaces the convert, validate_diagram, outline_diagram and render_diagram calls.",
198273
+ compact: {
198274
+ description: "Converts one Mermaid diagram (flowchart, sequenceDiagram, erDiagram, and more) to Plotwork source and checks it. When ok is true its source is valid: save it as it is, and check any change you make with draw_diagram before saving.",
198275
+ inputs: { lenient: "true skips a line it cannot read, with a warning.", render: "Also draw the converted diagram." }
198276
+ },
197498
198277
  input: ConvertMermaidInputSchema,
197499
198278
  output: ConvertMermaidResponseSchema,
197500
198279
  steps: [{ call: "convertMermaid" }, { call: "validate", optional: true }, { call: "outline", optional: true }, { call: "render", optional: true }],
@@ -197569,7 +198348,11 @@ var init_draw_diagram2 = __esm({
197569
198348
  drawDiagramWorkflow = defineWorkflow({
197570
198349
  name: "draw_diagram",
197571
198350
  title: "Draw diagram",
197572
- description: 'Workflow. Checks, describes, and draws a diagram. With errors it returns each one with line, column, and a fix hint and draws nothing: fix the source and call again. When valid it returns the quality warnings (take the icon and group-type suggestions), an outline to check the meaning, the size, and the SVG for light, dark, or both. The pictures are most of an answer and you cannot see them: pass svg "never" to check, and draw only to save, show, or publish. Give viewUrl to the person, even after svg "never"; pngUrl and svgUrl download it; saveCommand, when given, saves it in a repository. A big drawing (about 30 nodes) loses its SVGs, dark first, and picturesOmitted says so; svg "always" forces them. Set embedSource true to save an SVG in a repository or publish one to edit later, so read_diagram gives the source back (anyone with the file can read it). detail "full" adds the whole outline. To change an existing diagram use edit_diagram, or read_diagram for a picture. Saves no file; never throws on bad source. Replaces the validate_diagram, outline_diagram and render_diagram calls.',
198351
+ description: 'Workflow. Checks, describes, and draws a diagram. With errors it returns each one with line, column, and a fix hint and draws nothing: fix the source and call again. When valid it returns the quality warnings (take the icon and group-type suggestions), an outline to check the meaning, the size, and the SVG for light, dark, or both. The pictures are most of an answer and you cannot see them: pass svg "never" to check, and draw only to save, show, or publish. Give viewUrl to the person, even after svg "never": the drawing lives in the link and nothing is saved on Plotwork; pngUrl and svgUrl download it; saveCommand, when given, saves it in a repository. A big drawing (about 30 nodes) loses its SVGs, dark first, and picturesOmitted says so; svg "always" forces them. Set embedSource true to save an SVG in a repository or publish one to edit later, so read_diagram gives the source back (anyone with the file can read it). detail "full" adds the whole outline. To change an existing diagram use edit_diagram, or read_diagram for a picture. Saves no file; never throws on bad source. Replaces the validate_diagram, outline_diagram and render_diagram calls.',
198352
+ compact: {
198353
+ description: 'Checks diagram source and draws it in one call. Returns every error with line, column, and hint, and draws nothing until the source is valid, so fix each error and call again. svg "never" only checks and keeps the answer small; "always" returns the light and dark SVG to save.',
198354
+ inputs: { svg: "never: check only. always: return the SVGs.", themes: "", embedSource: "Write the source into the SVG, for a file saved in a repository." }
198355
+ },
197573
198356
  input: DrawDiagramInputSchema,
197574
198357
  output: DrawDiagramResponseSchema,
197575
198358
  steps: [{ call: "validate" }, { call: "outline", optional: true }, { call: "render", optional: true }],
@@ -197731,6 +198514,10 @@ var init_edit_diagram2 = __esm({
197731
198514
  name: "edit_diagram",
197732
198515
  title: "Edit diagram",
197733
198516
  description: 'Workflow. Changes diagram source with typed operations, on every kind, and checks the result. Each op and its fields: rename (target, to: an id everywhere it is used, or a label), set (target, or from and to for an edge, or target "header"; option, value, null removes it), add_node (id, label, type, options; into a block or after a statement; statement for a whole line), remove (target, with its block and edges), add_edge (from, to, label, arrow, options), remove_edge (from, to, label), move (target, into: a block, or null for the top level), replace_text (find, replace, all). Untouched lines keep their comments and layout. Each op reports applied, or why not with a hint, and a failed one is skipped. svg "never" (the default) lays nothing out; auto or always draws as draw_diagram does, with viewUrl and saveCommand. Replaces rewriting the source by hand and the draw_diagram check.',
198517
+ compact: {
198518
+ description: "Changes diagram source with typed operations and checks the result, without rewriting it by hand. Each operation is an object with op and its own fields: rename (target, to), set (target, option, value), add_node (id, type, label), remove (target), add_edge (from, to, label), remove_edge (from, to), move (target, into), replace_text (find, replace).",
198519
+ inputs: { svg: "never (default) draws nothing; auto or always draws." }
198520
+ },
197734
198521
  input: EditDiagramInputSchema,
197735
198522
  output: EditDiagramResponseSchema,
197736
198523
  steps: [{ call: "parse", optional: true }, { call: "outline", optional: true }, { call: "validate", optional: true }, { call: "render", optional: true }],
@@ -197744,6 +198531,7 @@ var init_edit_diagram2 = __esm({
197744
198531
  { op: "add_edge", from: "gateway", to: "cache", label: "store session" }
197745
198532
  ]
197746
198533
  },
198534
+ callExample: { source: 'flow\nnode api service "API"', operations: [{ op: "rename", target: "api", to: "gateway" }] },
197747
198535
  prompts: ["Rename the Auth API node to gateway and add a session cache it writes to.", "Move the database into the data group and remove the old queue."],
197748
198536
  execute: editDiagram
197749
198537
  });
@@ -197751,11 +198539,12 @@ var init_edit_diagram2 = __esm({
197751
198539
  });
197752
198540
 
197753
198541
  // ../../packages/diagrams/src/tools/workflows/find-pattern.ts
197754
- function nextFor(count3, firstId) {
198542
+ function nextFor(count3, firstId, own2) {
197755
198543
  if (count3 === 0 || firstId === void 0) {
197756
198544
  return "Nothing fits. Try fewer or more general words, drop the provider or tag filter, or draw the diagram from nothing with get_diagram_syntax and draw_diagram.";
197757
198545
  }
197758
- return `Read the summaries and choose one. Call get_pattern with its id (the best match is ${firstId}) to see its source, slots, and advice, or draw_from_pattern to check and draw it in one call.`;
198546
+ const prefer = own2 === 0 ? "" : " The matches with origin organisation are your organisation's own approved patterns: prefer them.";
198547
+ return `Read the summaries and choose one. Call get_pattern with its id (the best match is ${firstId}) to see its source, slots, and advice, or draw_from_pattern to check and draw it in one call.${prefer}`;
197759
198548
  }
197760
198549
  async function findPattern(input2, ops = ENGINE_OPS) {
197761
198550
  const matches3 = ops.findPatterns(input2.query, {
@@ -197764,7 +198553,8 @@ async function findPattern(input2, ops = ENGINE_OPS) {
197764
198553
  ...input2.kind === void 0 ? {} : { kind: input2.kind },
197765
198554
  limit: input2.limit
197766
198555
  });
197767
- return { query: input2.query, matches: matches3.map((match) => ({ ...match, tags: [...match.tags], providers: [...match.providers] })), next: nextFor(matches3.length, matches3[0]?.id) };
198556
+ const own2 = matches3.filter((match) => match.origin === "organisation").length;
198557
+ return { query: input2.query, matches: matches3.map((match) => ({ ...match, tags: [...match.tags], providers: [...match.providers] })), next: nextFor(matches3.length, matches3[0]?.id, own2) };
197768
198558
  }
197769
198559
  var findPatternWorkflow;
197770
198560
  var init_find_pattern = __esm({
@@ -197958,6 +198748,10 @@ var init_import_source3 = __esm({
197958
198748
  name: "import_source",
197959
198749
  title: "Import source",
197960
198750
  description: "Workflow. Turns a file into a finished diagram in one call: a database schema, an API spec, infrastructure as code, manifests, a software catalog, a CI workflow, CSV or JSON data, a folder listing, or a git log. get_diagram_syntax with topic import-formats says what each format reads, draws, and takes. Prefer it to drawing by hand whenever the person has such a file: send its text, never a path, or every file of a folder in files. Returns the source, diagnostics pointing into the file for anything left out, coverage, parts (every diagram of a split file), the validation, an outline, viewUrl, and saveCommand. It runs no code and reads no file or URL. Replaces validate_diagram and outline_diagram.",
198751
+ compact: {
198752
+ description: "Builds a whole diagram from a file in one call: SQL, Prisma, OpenAPI, Terraform, docker-compose, Kubernetes, GitHub Actions, CSV, a folder listing, a git log, and more. Send the file content as text and its format. When ok is true its source is valid: save it as it is. The diagnostics say what was left out.",
198753
+ inputs: { text: "The file content.", title: "" }
198754
+ },
197961
198755
  input: ImportSourceInputSchema,
197962
198756
  output: ImportSourceResponseSchema,
197963
198757
  steps: [{ call: "importSource" }, { call: "validate", optional: true }, { call: "outline", optional: true }],
@@ -198080,6 +198874,10 @@ var init_map_icons2 = __esm({
198080
198874
  name: "map_icons",
198081
198875
  title: "Map icons",
198082
198876
  description: `Workflow. Finds an icon for each of up to 40 service or product names in one call, such as the services of an architecture. For every name it returns the best provider:name icon with a confidence (exact, strong, or ambiguous) and up to 3 alternatives. It never guesses: a name that could mean several icons (a kind of service several clouds offer, or a match by idea only) comes back with resolved false and candidates to choose from, and a name that matches nothing is listed in gaps with a neutral fallback icon. Set provider to the cloud the architecture runs on, so "queue" finds that cloud's product first. Reads the bundled icons and, when hosted, the organisation icons (org:name). Replaces up to 40 search_icons calls.`,
198877
+ compact: {
198878
+ description: 'Finds the icon for each of up to 40 service or product names in one call ("S3", "Postgres", "load balancer"), for icon= on a node. It never guesses: for an ambiguous name choose from its candidates, and never invent an icon name.',
198879
+ inputs: { provider: "The cloud the names belong to, such as aws." }
198880
+ },
198083
198881
  input: MapIconsInputSchema,
198084
198882
  output: MapIconsResponseSchema,
198085
198883
  steps: [{ call: "searchIcons" }],
@@ -199923,6 +200721,7 @@ var init_plan_document_diagrams = __esm({
199923
200721
  steps: [{ call: "parse", optional: true }],
199924
200722
  maxCalls: WORKFLOW_MAX_CALLS.plan_document_diagrams,
199925
200723
  example: { document: EXAMPLE_DOCUMENT },
200724
+ callExample: { document: "# Refunds\n\n## Process\n\nCustomer: asks for a refund\nSupport: checks the order" },
199926
200725
  prompts: ["Which parts of this design doc need a diagram?", "Add pictures to this Confluence page.", "Plan the diagrams for our onboarding guide."],
199927
200726
  execute: planDocumentDiagrams
199928
200727
  });
@@ -199946,6 +200745,10 @@ var init_suggest_diagram = __esm({
199946
200745
  name: "suggest_diagram",
199947
200746
  title: "Suggest diagram",
199948
200747
  description: 'Workflow. Picks the kind of diagram for a request in plain words, such as "permission matrix for these endpoints and roles" or "where our cloud spend goes", with optional pasted data (a table, a list, numbers by period). Returns up to 3 kinds, best first, each with a one-sentence reason, a confidence, the statements to use, and a short starter source that parses, built from the names and numbers in the request and data. Call it when you are unsure which kind fits, then edit the starter and call draw_diagram. Replaces reading every kind in get_diagram_syntax to choose one.',
200748
+ compact: {
200749
+ description: "Ranks the diagram kinds for a request in plain words, with a starter source for each that already parses. Call it first when unsure which kind fits, then pass the starter to draw_diagram.",
200750
+ inputs: { request: "What the picture is for, in plain words.", data: "Optional table, list, or notes to draw from." }
200751
+ },
199949
200752
  input: SuggestDiagramInputSchema,
199950
200753
  output: SuggestDiagramResponseSchema,
199951
200754
  steps: [{ call: "parse", optional: true }],
@@ -199974,6 +200777,10 @@ var init_sync_markdown3 = __esm({
199974
200777
  name: "sync_markdown",
199975
200778
  title: "Sync Markdown",
199976
200779
  description: `Workflow. Turns the diagram fences of a Markdown document into pictures, as data. Send the whole document and its path. Returns the rewritten document (each fence folded into a "Diagram source" section with the picture and a text description, the rest byte for byte unchanged), the light and dark SVG files to write (paths from the repository root), and a report per fence with errors at lines of your document. convertMermaid true first turns each convertible mermaid fence into a diagram fence; one that cannot convert or has errors is left as it was and reported. Then write markdown to documentPath and each file to its path, and review the diff. mode "check" only reports. The SVGs can be large: files "none" returns each file's path, bytes, sha256, and viewUrl instead, and page with pageSize returns the files a page at a time. Writes no file itself. Limits: ${WORKFLOW_LIMITS.maxMarkdownLength} characters, ${WORKFLOW_LIMITS.maxDiagrams} diagrams, ${WORKFLOW_LIMITS.maxOutputBytes} bytes of output; caps says when one stopped work. Replaces the convert, validate, render and sync steps for every fence in a document.`,
200780
+ compact: {
200781
+ description: "Draws every diagram fence of a Markdown document: returns the rewritten document and the SVG files to write. convertMermaid true also turns mermaid fences into diagram fences first.",
200782
+ inputs: { convertMermaid: "", mode: "sync writes; check only reports stale pictures.", files: "inline returns each SVG; none keeps the answer small." }
200783
+ },
199977
200784
  input: SyncMarkdownInputSchema,
199978
200785
  output: SyncMarkdownResponseSchema,
199979
200786
  steps: [{ call: "convertMermaidFences", optional: true }, { call: "renderPair" }],
@@ -200034,83 +200841,66 @@ var init_workflows2 = __esm({
200034
200841
  }
200035
200842
  });
200036
200843
 
200037
- // ../../packages/diagrams/src/tools/json-schema.ts
200038
- function referencedDefs(node3) {
200039
- return [...JSON.stringify(node3).matchAll(DEF_REF)].map((match) => match[1] ?? "");
200040
- }
200041
- function reachableDefs(root, defs) {
200042
- const reached = /* @__PURE__ */ new Set();
200043
- const pending = referencedDefs(root);
200044
- for (let name2 = pending.pop(); name2 !== void 0; name2 = pending.pop()) {
200045
- const def = defs[name2];
200046
- if (def === void 0 || reached.has(name2)) continue;
200047
- reached.add(name2);
200048
- pending.push(...referencedDefs(def));
200049
- }
200050
- return Object.fromEntries(Object.entries(defs).filter(([name2]) => reached.has(name2)));
200051
- }
200052
- function inlineRootRef(schema) {
200053
- const ref = schema["$ref"];
200054
- const defs = schema["$defs"];
200055
- if (typeof ref !== "string" || typeof defs !== "object" || defs === null) return schema;
200056
- const target = defs[ref.replace("#/$defs/", "")];
200057
- if (target === void 0) return schema;
200058
- const { $ref: _removed, $defs: _defs, ...header } = schema;
200059
- const root = { ...header, ...target };
200060
- const kept2 = reachableDefs(root, defs);
200061
- return Object.keys(kept2).length === 0 ? root : { ...root, $defs: kept2 };
200062
- }
200063
- function remembered(cache, key, make) {
200064
- const known3 = cache.get(key);
200065
- if (known3 !== void 0) return known3;
200066
- const made = make();
200067
- cache.set(key, made);
200068
- return made;
200069
- }
200070
- function inputJsonSchema(tool) {
200071
- return remembered(inputSchemas, tool.inputSchema, () => withoutSafeBounds(inlineRootRef(external_exports.toJSONSchema(tool.inputSchema, { target: TARGET2, io: "input" }))));
200072
- }
200073
- function withoutSafeBounds(node3) {
200074
- if (Array.isArray(node3)) return node3.map(withoutSafeBounds);
200075
- if (typeof node3 !== "object" || node3 === null) return node3;
200076
- return Object.fromEntries(
200077
- Object.entries(node3).filter(([key, value]) => !(key === "minimum" && value === Number.MIN_SAFE_INTEGER || key === "maximum" && value === Number.MAX_SAFE_INTEGER)).map(([key, value]) => [key, withoutSafeBounds(value)])
200078
- );
200844
+ // ../../packages/diagrams/src/tools/profiles.ts
200845
+ function readToolProfile(value) {
200846
+ const name2 = value?.trim().toLowerCase() ?? "";
200847
+ if (name2 === "") return "full";
200848
+ return TOOL_PROFILES.includes(name2) ? name2 : null;
200079
200849
  }
200080
- function openObjects(node3) {
200081
- if (Array.isArray(node3)) return node3.map(openObjects);
200082
- if (typeof node3 !== "object" || node3 === null) return node3;
200083
- return Object.fromEntries(
200084
- Object.entries(node3).filter(([key, value]) => !(key === "additionalProperties" && value === false)).map(([key, value]) => [key, openObjects(value)])
200085
- );
200086
- }
200087
- function outputJsonSchema(tool) {
200088
- return remembered(outputSchemas, tool.outputSchema, () => withoutSafeBounds(openObjects(inlineRootRef(external_exports.toJSONSchema(tool.outputSchema, { target: TARGET2, io: "output" })))));
200850
+ function toolsForProfile(tools2, profile) {
200851
+ if (profile === "full") return tools2;
200852
+ return CORE_TOOLS.flatMap((name2) => tools2.filter((tool) => tool.name === name2));
200089
200853
  }
200090
- function withoutProse(node3, isProperties = false) {
200091
- if (Array.isArray(node3)) return node3.map((item) => withoutProse(item));
200854
+ function withoutProse2(node3, isProperties = false) {
200855
+ if (Array.isArray(node3)) return node3.map((item) => withoutProse2(item));
200092
200856
  if (typeof node3 !== "object" || node3 === null) return node3;
200093
200857
  return Object.fromEntries(
200094
- Object.entries(node3).filter(([key]) => isProperties || !LEFT_OUT.has(key)).map(([key, value]) => [key, withoutProse(value, !isProperties && (key === "properties" || key === "$defs"))])
200858
+ Object.entries(node3).filter(([key]) => isProperties || !COMPACT_LEFT_OUT.has(key)).map(([key, value]) => [key, withoutProse2(value, !isProperties && (key === "properties" || key === "$defs"))])
200095
200859
  );
200096
200860
  }
200097
- function listedOutputSchema(schema) {
200098
- return remembered(listedSchemas, schema, () => withoutProse(withoutSafeBounds(schema)));
200861
+ function compactInputJsonSchema(tool) {
200862
+ const known3 = compactSchemas.get(tool);
200863
+ if (known3 !== void 0) return known3;
200864
+ const full = inputJsonSchema(tool);
200865
+ const properties = full["properties"] ?? {};
200866
+ const required2 = Array.isArray(full["required"]) ? full["required"] : [];
200867
+ const described2 = tool.compact?.inputs ?? {};
200868
+ const kept2 = Object.keys(properties).filter((key) => required2.includes(key) || Object.hasOwn(described2, key));
200869
+ const schema = {
200870
+ type: "object",
200871
+ properties: Object.fromEntries(
200872
+ kept2.map((key) => {
200873
+ const field = withoutProse2(properties[key]);
200874
+ const text3 = described2[key];
200875
+ return [key, text3 === void 0 || text3 === "" ? field : { ...field, description: text3 }];
200876
+ })
200877
+ ),
200878
+ ...required2.length > 0 ? { required: required2 } : {},
200879
+ ..."additionalProperties" in full ? { additionalProperties: full["additionalProperties"] } : {}
200880
+ };
200881
+ compactSchemas.set(tool, schema);
200882
+ return schema;
200099
200883
  }
200100
- function listedOutputJsonSchema(tool) {
200101
- return listedOutputSchema(outputJsonSchema(tool));
200884
+ function listedFor(tool, profile) {
200885
+ if (profile === "core" && tool.compact !== null) return { description: tool.compact.description, inputSchema: compactInputJsonSchema(tool), withOutputSchema: false };
200886
+ return { description: tool.description, inputSchema: inputJsonSchema(tool), withOutputSchema: true };
200102
200887
  }
200103
- var TARGET2, DEF_REF, inputSchemas, outputSchemas, listedSchemas, LEFT_OUT;
200104
- var init_json_schema2 = __esm({
200105
- "../../packages/diagrams/src/tools/json-schema.ts"() {
200888
+ var TOOL_PROFILES, CORE_TOOLS, CORE_INSTRUCTIONS, COMPACT_LEFT_OUT, compactSchemas;
200889
+ var init_profiles = __esm({
200890
+ "../../packages/diagrams/src/tools/profiles.ts"() {
200106
200891
  "use strict";
200107
- init_zod();
200108
- TARGET2 = "draft-2020-12";
200109
- DEF_REF = /"\$ref":"#\/\$defs\/([^"]+)"/g;
200110
- inputSchemas = /* @__PURE__ */ new WeakMap();
200111
- outputSchemas = /* @__PURE__ */ new WeakMap();
200112
- listedSchemas = /* @__PURE__ */ new WeakMap();
200113
- LEFT_OUT = /* @__PURE__ */ new Set(["description", "$schema", "title", "enum"]);
200892
+ init_json_schema2();
200893
+ TOOL_PROFILES = ["full", "core"];
200894
+ CORE_TOOLS = ["suggest_diagram", "get_diagram_syntax", "draw_diagram", "edit_diagram", "import_source", "convert_mermaid", "sync_markdown", "map_icons"];
200895
+ CORE_INSTRUCTIONS = [
200896
+ "Draws flow, sequence, schema, state, class, and other diagrams from a small line-oriented text language.",
200897
+ 'To draw: if unsure which kind fits, call suggest_diagram; call get_diagram_syntax once with kind set to the kind you draw; write the source and call draw_diagram with svg "never" to check it, fix every error by its line, column, and hint, and call again until it is valid; call draw_diagram with svg "always" only when the SVG will be saved.',
200898
+ "To change a diagram, call edit_diagram. From a file (SQL, OpenAPI, Terraform, docker-compose, Kubernetes, CSV, and more), call import_source; from Mermaid, convert_mermaid; for every diagram fence of a Markdown file, sync_markdown.",
200899
+ "Save or hand over only source that a tool has said is valid, and check it again with draw_diagram after any change. A viewUrl holds the drawing in the link: nothing is saved on Plotwork.",
200900
+ "Use map_icons for icon names and never invent one. Pass the arguments as one JSON object with the fields at the top level."
200901
+ ].join(" ");
200902
+ COMPACT_LEFT_OUT = /* @__PURE__ */ new Set(["description", "$schema", "title", "default", "examples", "minLength", "maxLength", "minItems", "maxItems", "pattern", "propertyNames"]);
200903
+ compactSchemas = /* @__PURE__ */ new WeakMap();
200114
200904
  }
200115
200905
  });
200116
200906
 
@@ -200197,9 +200987,19 @@ var init_view2 = __esm({
200197
200987
  function isRecord6(value) {
200198
200988
  return typeof value === "object" && value !== null && !Array.isArray(value);
200199
200989
  }
200200
- function pictureFileName(source) {
200990
+ function drawnSourceOf(tool, args, answer) {
200991
+ const pick3 = SOURCE_OF[tool];
200992
+ if (pick3 === void 0 || !isRecord6(args) || !isRecord6(answer)) return null;
200993
+ const picked = pick3(args, answer);
200994
+ return typeof picked === "string" && picked.length > 0 ? picked : null;
200995
+ }
200996
+ function sourceTitle(source) {
200201
200997
  const header = source.split("\n").find((line3) => line3.trim() !== "" && !line3.trim().startsWith("#")) ?? "";
200202
- const title = /^\s*[a-z][\w-]*\s+"([^"]*)"/i.exec(header)?.[1] ?? "";
200998
+ const title = (/^\s*[a-z][\w-]*\s+"([^"]*)"/i.exec(header)?.[1] ?? "").trim();
200999
+ return title === "" ? null : title;
201000
+ }
201001
+ function pictureFileName(source) {
201002
+ const title = sourceTitle(source) ?? "";
200203
201003
  const slug = title.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 60).replace(/-+$/, "");
200204
201004
  return `${slug === "" ? "diagram" : slug}.svg`;
200205
201005
  }
@@ -200217,10 +201017,8 @@ function savingSentence(hasCommand, release = CLI_RELEASE) {
200217
201017
  }
200218
201018
  async function attachViewUrl(tool, args, value, base, release = CLI_RELEASE) {
200219
201019
  if (tool === "sync_markdown") return rebaseFileLinks(value, base);
200220
- const pick3 = SOURCE_OF[tool];
200221
- if (pick3 === void 0 || !isRecord6(value) || !isRecord6(args)) return value;
200222
- const picked = pick3(args, value);
200223
- if (typeof picked !== "string" || picked.length === 0) return value;
201020
+ const picked = drawnSourceOf(tool, args, value);
201021
+ if (picked === null || !isRecord6(value) || !isRecord6(args)) return value;
200224
201022
  const settings = SettingsSchema.safeParse(args["settings"]);
200225
201023
  const source = settings.success ? applyDefaults(picked, settings.data.defaults).source : picked;
200226
201024
  const link2 = await viewLinkFor(source, base);
@@ -200235,7 +201033,7 @@ async function attachViewUrl(tool, args, value, base, release = CLI_RELEASE) {
200235
201033
  ...pngUrl.length <= VIEW_LINKS.maxLength ? { pngUrl } : {},
200236
201034
  ...svgUrl.length <= VIEW_LINKS.maxLength ? { svgUrl } : {},
200237
201035
  ...saveCommand === null ? {} : { saveCommand },
200238
- next: `${next}${savingSentence(saveCommand !== null, release)}`
201036
+ next: `${next}${VIEW_LINK_NOT_SAVED} ${savingSentence(saveCommand !== null, release)}`
200239
201037
  };
200240
201038
  }
200241
201039
  return { ...value, next: `${next}There is no viewUrl: the link would be ${link2.length} characters, over the ${VIEW_LINKS.maxLength} a link may have. ${savingSentence(false, release)}` };
@@ -200261,7 +201059,7 @@ function stripViewLinks(value) {
200261
201059
  }
200262
201060
  return kept2;
200263
201061
  }
200264
- var SOURCE_OF, VIEW_LINK_TOOLS, VIEW_LINK_FIELDS;
201062
+ var SOURCE_OF, VIEW_LINK_TOOLS, VIEW_LINK_NOT_SAVED, VIEW_LINK_FIELDS;
200265
201063
  var init_view_link = __esm({
200266
201064
  "../../packages/diagrams/src/tools/view-link.ts"() {
200267
201065
  "use strict";
@@ -200277,6 +201075,7 @@ var init_view_link = __esm({
200277
201075
  import_source: (_args, answer) => answer["validation"]?.["valid"] === true ? answer["source"] : null
200278
201076
  };
200279
201077
  VIEW_LINK_TOOLS = Object.keys(SOURCE_OF);
201078
+ VIEW_LINK_NOT_SAVED = "viewUrl holds the drawing itself in the link: nothing is saved on Plotwork, and it will not appear in any Diagrams list.";
200280
201079
  VIEW_LINK_FIELDS = ["viewUrl", "pngUrl", "svgUrl", "saveCommand"];
200281
201080
  }
200282
201081
  });
@@ -200290,6 +201089,8 @@ var init_tools = __esm({
200290
201089
  init_compare_diagrams3();
200291
201090
  init_workflows2();
200292
201091
  init_define_tool();
201092
+ init_input_hint();
201093
+ init_profiles();
200293
201094
  init_json_schema2();
200294
201095
  init_fit_answer();
200295
201096
  init_layout_tools();
@@ -200486,6 +201287,33 @@ var init_icon_scope = __esm({
200486
201287
  }
200487
201288
  });
200488
201289
 
201290
+ // src/constants.ts
201291
+ var MAX_BODY_BYTES2;
201292
+ var init_constants15 = __esm({
201293
+ "src/constants.ts"() {
201294
+ "use strict";
201295
+ MAX_BODY_BYTES2 = 10 * 1024 * 1024;
201296
+ }
201297
+ });
201298
+
201299
+ // src/org-patterns.ts
201300
+ function patternInstructions(library) {
201301
+ if (library.only) {
201302
+ return "This connection's organisation asks its agents to start from its approved patterns: call find_pattern first for every diagram a pattern could fit, and start from the one it returns with draw_from_pattern or get_pattern. find_pattern answers with the organisation's own patterns only. When none fits, draw the diagram from nothing with draw_diagram: that is allowed.";
201303
+ }
201304
+ return "This connection's organisation has its own approved patterns: find_pattern lists them first, each with origin organisation, and you should prefer them over the built-in ones.";
201305
+ }
201306
+ function findPatternNote(library) {
201307
+ return library.only ? " Through this connection it searches only your organisation's approved patterns (ids start with org:), which your organisation asks you to start from; when none fits, draw from nothing." : " Through this connection it lists your organisation's own patterns first (ids start with org:, origin organisation); prefer them.";
201308
+ }
201309
+ var init_org_patterns2 = __esm({
201310
+ "src/org-patterns.ts"() {
201311
+ "use strict";
201312
+ init_patterns3();
201313
+ init_constants15();
201314
+ }
201315
+ });
201316
+
200489
201317
  // src/engine-runner.ts
200490
201318
  var runInPlace, runLocally;
200491
201319
  var init_engine_runner = __esm({
@@ -200494,6 +201322,7 @@ var init_engine_runner = __esm({
200494
201322
  init_icons();
200495
201323
  init_tools();
200496
201324
  init_icon_scope();
201325
+ init_org_patterns2();
200497
201326
  runInPlace = (tool, args) => tool.run(args);
200498
201327
  runLocally = (tool, args) => tool.kind === "workflow" && "runWith" in tool ? tool.runWith(args, LOCAL_ENGINE_OPS) : tool.run(args);
200499
201328
  }
@@ -200656,7 +201485,7 @@ function libraryInstructions(library) {
200656
201485
  function librarySaveStep(library) {
200657
201486
  return `When the diagram is finished, save it to the private library of ${JSON.stringify(library.name)} with publish_diagram (no need to ask: only members can open it).`;
200658
201487
  }
200659
- var SERVER_INFO, SAVING_INSTRUCTIONS, SERVER_INSTRUCTIONS, HOSTED_INSTRUCTIONS;
201488
+ var SERVER_INFO, SAVING_INSTRUCTIONS, SERVER_INSTRUCTIONS, KEEP_IN_LIBRARY_STEP, HOSTED_INSTRUCTIONS;
200660
201489
  var init_server_info = __esm({
200661
201490
  "src/server-info.ts"() {
200662
201491
  "use strict";
@@ -200688,7 +201517,8 @@ var init_server_info = __esm({
200688
201517
  "Use validate_diagram, outline_diagram, render_diagram, and search_icons only for one fine-grained step.",
200689
201518
  "Choose node types and tones for meaning; colors are chosen by the theme and cannot be set."
200690
201519
  ].join(" ");
200691
- HOSTED_INSTRUCTIONS = "When the person asks to share a finished diagram or wants a link to it, call publish_diagram with the valid source: it returns a public link and a Markdown image to paste, and publishing the same diagram again returns the same link. Publish only when asked, because anyone with the link can see the picture. After you edit a published diagram, call publish_diagram again: an edited diagram is a new picture with a new link, so replace the old link wherever it is used. Set embedSource true on publish_diagram when someone may want to edit the diagram later, and tell the person that the source is then part of the public picture. A drawing too big to return in an answer is also the case for publish_diagram: it gives a link in place of the picture. To keep a diagram inside a team instead, pass organization with the slug or id of an organisation, but only when the person names an organisation or asks for a team diagram: it is stored in that organisation's private library and the answer has a viewUrl for members in place of a public link, so there is no Markdown image. Never guess an organisation, and if it is not found, ask the person which one they mean. An organisation can also send its members' diagrams to its library when organization is left out: the answer then names it and says why, and the person must be told the diagram is in that library, not at a public link. Pass personal true only when the person asks for a public link anyway; an organisation that requires its library refuses it, and then tell the person. An owner may restrict a folder, and a reader may not publish: when the answer says the folder is restricted or the role does not allow it, ask the person which folder they may use instead of trying others or publishing elsewhere. Call list_diagrams when the person asks what they have published or to get a diagram id; it changes nothing. Call delete_diagram only after the person has said which diagram to delete, by name, and tell them what you deleted; never delete on a guess, in bulk, or to make room for a publish unless they asked, and a locked diagram cannot be deleted until the owner unlocks it.";
201520
+ KEEP_IN_LIBRARY_STEP = "To keep it in an organisation's library, or in the person's own Diagrams, call publish_diagram when they ask.";
201521
+ HOSTED_INSTRUCTIONS = "A viewUrl from a drawing tool holds the drawing itself in the link: nothing is saved on Plotwork, and it will not appear in any Diagrams list; when the person wants a diagram kept in an organisation's library or their own Diagrams, call publish_diagram. When the person asks to share a finished diagram or wants a link to it, call publish_diagram with the valid source: it returns a public link and a Markdown image to paste, and publishing the same diagram again returns the same link. Publish only when asked, because anyone with the link can see the picture. After you edit a published diagram, call publish_diagram again: an edited diagram is a new picture with a new link, so replace the old link wherever it is used. Set embedSource true on publish_diagram when someone may want to edit the diagram later, and tell the person that the source is then part of the public picture. A drawing too big to return in an answer is also the case for publish_diagram: it gives a link in place of the picture. To keep a diagram inside a team instead, pass organization with the slug or id of an organisation, but only when the person names an organisation or asks for a team diagram: it is stored in that organisation's private library and the answer has a viewUrl for members in place of a public link, so there is no Markdown image. Never guess an organisation, and if it is not found, ask the person which one they mean. An organisation can also send its members' diagrams to its library when organization is left out: the answer then names it and says why, and the person must be told the diagram is in that library, not at a public link. Pass personal true only when the person asks for a public link anyway; an organisation that requires its library refuses it, and then tell the person. An organisation can also keep every diagram its agents draw: a drawing's answer then has autoPublished, and its next names the library; tell the person where the diagram is, and do not publish it again. An organisation can also hold a publish for approval: the answer then has approval and warning W601, held for approval by your organisation; tell the person it is stored and waits for an approver, and do not publish it again. An owner may restrict a folder, and a reader may not publish: when the answer says the folder is restricted or the role does not allow it, ask the person which folder they may use instead of trying others or publishing elsewhere. Call list_diagrams when the person asks what they have published or to get a diagram id; it changes nothing. Call delete_diagram only after the person has said which diagram to delete, by name, and tell them what you deleted; never delete on a guess, in bulk, or to make room for a publish unless they asked, and a locked diagram cannot be deleted until the owner unlocks it.";
200692
201522
  }
200693
201523
  });
200694
201524
 
@@ -200699,7 +201529,8 @@ function failureLines(failure3) {
200699
201529
  (diagnostic) => `${diagnostic.code} at line ${diagnostic.line}, column ${diagnostic.column}: ${diagnostic.message}${diagnostic.hint === null ? "" : ` (${diagnostic.hint})`}`
200700
201530
  );
200701
201531
  }
200702
- return failure3.issues.map((issue3) => `${issue3.path === "" ? "arguments" : issue3.path}: ${issue3.message}`);
201532
+ const issues = failure3.issues.map((issue3) => `${issue3.path === "" ? "arguments" : issue3.path}: ${issue3.message}`);
201533
+ return failure3.hint === void 0 || failure3.hint === "" ? issues : [...issues, failure3.hint];
200703
201534
  }
200704
201535
  function toCallToolResult(outcome) {
200705
201536
  if (outcome.ok) {
@@ -200958,9 +201789,14 @@ async function callTool(tool, args, log, caller, activity, run3, budget2, answer
200958
201789
  const started = performance.now();
200959
201790
  const inputBytes = inputSize(args);
200960
201791
  try {
201792
+ const refused4 = checkToolInput(tool, args);
201793
+ if (refused4 !== null) {
201794
+ logToolCall({ tool: tool.name, outcome: refused4.kind, durationMs: performance.now() - started, inputBytes, caller }, log);
201795
+ return toCallToolResult({ ok: false, error: refused4 });
201796
+ }
200961
201797
  const ran = await run3(tool, args);
200962
201798
  const linked = !ran.ok ? null : answers2.viewLinks === false ? stripViewLinks(ran.value) : await attachViewUrl(tool.name, args, ran.value, answers2.viewBase);
200963
- const saving = linked === null || answers2.library === void 0 || answers2.library === null ? linked : withSaveStep(tool.name, linked, answers2.library);
201799
+ const saving = linked === null ? null : answers2.library !== void 0 && answers2.library !== null ? withSaveStep(tool.name, linked, answers2.library) : answers2.canPublish ? withKeepStep(tool.name, linked) : linked;
200964
201800
  const fitted = saving === null ? null : fitAnswer(saving, args, budget2);
200965
201801
  const shown = fitted === null || answers2.open === void 0 ? fitted : await answers2.open(tool.name, fitted);
200966
201802
  const outcome = ran.ok ? { ok: true, value: shown } : ran;
@@ -200975,13 +201811,24 @@ async function callTool(tool, args, log, caller, activity, run3, budget2, answer
200975
201811
  return internalErrorResult();
200976
201812
  }
200977
201813
  }
201814
+ function keptByPolicy(answer) {
201815
+ const kept2 = answer["autoPublished"];
201816
+ return typeof kept2 === "object" && kept2 !== null && kept2["published"] === true;
201817
+ }
200978
201818
  function withSaveStep(tool, value, library) {
200979
201819
  if (!SAVABLE_TOOLS.has(tool) || typeof value !== "object" || value === null) return value;
200980
201820
  const answer = value;
200981
- if (answer["valid"] === false) return value;
201821
+ if (answer["valid"] === false || keptByPolicy(answer)) return value;
200982
201822
  const next = typeof answer["next"] === "string" && answer["next"] !== "" ? `${answer["next"]} ` : "";
200983
201823
  return { ...answer, next: `${next}${librarySaveStep(library)}` };
200984
201824
  }
201825
+ function withKeepStep(tool, value) {
201826
+ if (!SAVABLE_TOOLS.has(tool) || typeof value !== "object" || value === null) return value;
201827
+ const answer = value;
201828
+ if (typeof answer["viewUrl"] !== "string" || keptByPolicy(answer)) return value;
201829
+ const next = typeof answer["next"] === "string" && answer["next"] !== "" ? `${answer["next"]} ` : "";
201830
+ return { ...answer, next: `${next}${KEEP_IN_LIBRARY_STEP}` };
201831
+ }
200985
201832
  async function callHostedTool(tool, args, log, caller) {
200986
201833
  const started = performance.now();
200987
201834
  const inputBytes = inputSize(args);
@@ -200995,6 +201842,14 @@ async function callHostedTool(tool, args, log, caller) {
200995
201842
  return internalErrorResult();
200996
201843
  }
200997
201844
  }
201845
+ function listedInput(schema) {
201846
+ let wrapper = listedInputs.get(schema);
201847
+ if (wrapper === void 0) {
201848
+ wrapper = { "~standard": { version: 1, vendor: "plotwork", jsonSchema: { input: () => schema, output: () => schema }, validate: (value) => ({ value }) } };
201849
+ listedInputs.set(schema, wrapper);
201850
+ }
201851
+ return wrapper;
201852
+ }
200998
201853
  function wrapped(schema, validator) {
200999
201854
  const key = validator ?? DEFAULT_VALIDATOR2;
201000
201855
  let bySchema = wrappers2.get(key);
@@ -201009,15 +201864,18 @@ function wrapped(schema, validator) {
201009
201864
  }
201010
201865
  return wrapper;
201011
201866
  }
201012
- function createDiagramsServer(options3 = {}, log = logToConsole, caller, hostedTools = [], activity, run3 = runInPlace, budget2 = ANSWER_BUDGET_CHARACTERS, answers2 = {}) {
201013
- const finish = { ...answers2, viewBase: answers2.viewBase ?? viewBaseFor() };
201867
+ function createDiagramsServer(options3 = {}, log = logToConsole, caller, hostedTools = [], activity, run3 = runInPlace, budget2 = ANSWER_BUDGET_CHARACTERS, answers2 = {}, profile = "full") {
201868
+ const finish = { ...answers2, viewBase: answers2.viewBase ?? viewBaseFor(), canPublish: hostedTools.some((tool) => tool.name === "publish_diagram") };
201014
201869
  const taken = new Set(TOOLS.map((tool) => tool.name));
201015
201870
  for (const tool of hostedTools) {
201016
201871
  if (taken.has(tool.name)) throw new TypeError(`A tool named ${tool.name} is already registered`);
201017
201872
  taken.add(tool.name);
201018
201873
  }
201019
- const hosted = hostedTools.length === 0 ? SERVER_INSTRUCTIONS : `${SERVER_INSTRUCTIONS} ${HOSTED_INSTRUCTIONS}`;
201020
- const instructions = hostedTools.length > 0 && answers2.library !== void 0 && answers2.library !== null ? `${hosted} ${libraryInstructions(answers2.library)}` : hosted;
201874
+ const base = profile === "core" ? CORE_INSTRUCTIONS : SERVER_INSTRUCTIONS;
201875
+ const hosted = hostedTools.length === 0 ? base : `${base} ${HOSTED_INSTRUCTIONS}`;
201876
+ const saved = hostedTools.length > 0 && answers2.library !== void 0 && answers2.library !== null ? `${hosted} ${libraryInstructions(answers2.library)}` : hosted;
201877
+ const patterns = answers2.patterns ?? null;
201878
+ const instructions = patterns === null ? saved : `${saved} ${patternInstructions(patterns)}`;
201021
201879
  const server = new McpServer(SERVER_INFO, { instructions, ...options3 });
201022
201880
  for (const tool of hostedTools) {
201023
201881
  server.registerTool(
@@ -201032,14 +201890,15 @@ function createDiagramsServer(options3 = {}, log = logToConsole, caller, hostedT
201032
201890
  (args) => callHostedTool(tool, args, log, caller)
201033
201891
  );
201034
201892
  }
201035
- for (const tool of TOOLS) {
201893
+ for (const tool of toolsForProfile(TOOLS, profile)) {
201894
+ const listed2 = listedFor(tool, profile);
201036
201895
  server.registerTool(
201037
201896
  tool.name,
201038
201897
  {
201039
201898
  title: tool.title,
201040
- description: tool.description,
201041
- inputSchema: wrapped(inputJsonSchema(tool), options3.jsonSchemaValidator),
201042
- outputSchema: wrapped(listedOutputJsonSchema(tool), options3.jsonSchemaValidator),
201899
+ description: patterns !== null && tool.name === "find_pattern" ? `${listed2.description}${findPatternNote(patterns)}` : listed2.description,
201900
+ inputSchema: listedInput(listed2.inputSchema),
201901
+ ...listed2.withOutputSchema ? { outputSchema: wrapped(listedOutputJsonSchema(tool), options3.jsonSchemaValidator) } : {},
201043
201902
  annotations: tool.annotations,
201044
201903
  ...VIEWER_APP_TOOLS.includes(tool.name) ? { _meta: VIEWER_APP_TOOL_META } : {}
201045
201904
  },
@@ -201052,7 +201911,7 @@ function createDiagramsServer(options3 = {}, log = logToConsole, caller, hostedT
201052
201911
  registerDiagramPrompts(server, options3.jsonSchemaValidator);
201053
201912
  return server;
201054
201913
  }
201055
- var SAVABLE_TOOLS, DEFAULT_VALIDATOR2, wrappers2;
201914
+ var SAVABLE_TOOLS, listedInputs, DEFAULT_VALIDATOR2, wrappers2;
201056
201915
  var init_create_server = __esm({
201057
201916
  "src/create-server.ts"() {
201058
201917
  "use strict";
@@ -201062,11 +201921,13 @@ var init_create_server = __esm({
201062
201921
  init_activity();
201063
201922
  init_audit();
201064
201923
  init_engine_runner();
201924
+ init_org_patterns2();
201065
201925
  init_prompts();
201066
201926
  init_server_info();
201067
201927
  init_tool_result();
201068
201928
  init_viewer_app();
201069
201929
  SAVABLE_TOOLS = new Set(VIEW_LINK_TOOLS.filter((name2) => name2 !== "sync_markdown"));
201930
+ listedInputs = /* @__PURE__ */ new WeakMap();
201070
201931
  DEFAULT_VALIDATOR2 = {};
201071
201932
  wrappers2 = /* @__PURE__ */ new WeakMap();
201072
201933
  }
@@ -201507,6 +202368,22 @@ var init_start = __esm({
201507
202368
  }
201508
202369
  });
201509
202370
 
202371
+ // src/tool-profile.ts
202372
+ function chooseToolProfile(env, argv) {
202373
+ const flagAt = argv.findIndex((arg) => arg === "--tools" || arg.startsWith("--tools="));
202374
+ const flag = flagAt === -1 ? void 0 : argv[flagAt]?.startsWith("--tools=") === true ? argv[flagAt]?.slice("--tools=".length) : argv[flagAt + 1];
202375
+ const asked = flag ?? env["PLOTWORK_TOOLS"];
202376
+ const profile = readToolProfile(asked);
202377
+ if (profile !== null) return { profile, problem: null };
202378
+ return { profile: "full", problem: `Plotwork tool profile "${asked ?? ""}" is not one of ${TOOL_PROFILES.join(", ")}; listing the full set.` };
202379
+ }
202380
+ var init_tool_profile = __esm({
202381
+ "src/tool-profile.ts"() {
202382
+ "use strict";
202383
+ init_tools();
202384
+ }
202385
+ });
202386
+
201510
202387
  // src/viewer-address.ts
201511
202388
  function viewerAddress(env = {}) {
201512
202389
  const raw = env[VIEWER_URL_VARIABLE]?.trim();
@@ -201529,7 +202406,7 @@ var init_viewer_address = __esm({
201529
202406
 
201530
202407
  // src/stdio.ts
201531
202408
  var stdio_exports = {};
201532
- var usage, budget, answers, local;
202409
+ var usage, budget, answers, local, tools;
201533
202410
  var init_stdio2 = __esm({
201534
202411
  "src/stdio.ts"() {
201535
202412
  "use strict";
@@ -201543,6 +202420,7 @@ var init_stdio2 = __esm({
201543
202420
  init_local_open();
201544
202421
  init_local_settings();
201545
202422
  init_start();
202423
+ init_tool_profile();
201546
202424
  init_viewer_address();
201547
202425
  useIconArtFolder(iconArtFolder());
201548
202426
  usage = startLocalUsage();
@@ -201551,7 +202429,9 @@ var init_stdio2 = __esm({
201551
202429
  local = readLocalSettings(process.cwd(), process.env);
201552
202430
  if (local.problem !== null) console.error(`Plotwork settings in ${local.path ?? ""} were not applied:
201553
202431
  ${local.problem}`);
201554
- serveStdio(() => createDiagramsServer({}, logToStderr, void 0, [], usage.sink, withLocalSettings(runLocally, local.settings), budget, answers));
202432
+ tools = chooseToolProfile(process.env, process.argv.slice(2));
202433
+ if (tools.problem !== null) console.error(tools.problem);
202434
+ serveStdio(() => createDiagramsServer({}, logToStderr, void 0, [], usage.sink, withLocalSettings(runLocally, local.settings), budget, answers, tools.profile));
201555
202435
  }
201556
202436
  });
201557
202437
 
@@ -201597,6 +202477,10 @@ Usage
201597
202477
  ${BIN} --version Print the version and exit.
201598
202478
  ${BIN} --help Print this text and exit.
201599
202479
 
202480
+ Tool profile
202481
+ ${BIN} --tools core List only the eight workflow tools, with short descriptions, for an open
202482
+ or self-hosted model with a small context. PLOTWORK_TOOLS=core does the same.
202483
+
201600
202484
  Usage counts (off unless you turn them on)
201601
202485
  PLOTWORK_USAGE=local Count calls on this device, in one file. Nothing is sent.
201602
202486
  PLOTWORK_USAGE=share Also send pseudonymous daily totals to Plotwork: tool, diagram kind,
@@ -201627,7 +202511,7 @@ async function main(args) {
201627
202511
  process.stdout.write(HELP);
201628
202512
  return;
201629
202513
  }
201630
- if (first !== void 0 && first !== "usage") {
202514
+ if (first !== void 0 && first !== "usage" && first !== "--tools" && !first.startsWith("--tools=")) {
201631
202515
  process.stderr.write(`${BIN}: unknown argument "${first}". Run ${BIN} --help.
201632
202516
  `);
201633
202517
  process.exitCode = 2;