@workflow-code/cli 0.2.4-20261013004.codex-studio-integration → 0.2.4-20261013006.codex-studio-integration

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.
@@ -12607,6 +12607,45 @@
12607
12607
  "{0}{1} \xB7 {2} items": "\u5DF2{0}{1} \xB7 {2} \u9879",
12608
12608
  "{1} in {0}": "{0} \u4E2D {1}",
12609
12609
  "Account balance ${0}": "\u8D26\u6237\u4F59\u989D ${0}",
12610
+ "Account balance": "\u8D26\u6237\u4F59\u989D",
12611
+ "Account changed. Refresh usage.": "\u8D26\u53F7\u5DF2\u5207\u6362\uFF0C\u8BF7\u91CD\u65B0\u83B7\u53D6\u7528\u91CF\u3002",
12612
+ "AI usage": "AI \u7528\u91CF",
12613
+ All: "\u5168\u90E8",
12614
+ "Basic information": "\u57FA\u672C\u4FE1\u606F",
12615
+ Declarations: "\u58F0\u660E",
12616
+ "Default name": "\u9ED8\u8BA4\u540D\u79F0",
12617
+ "Entrypoints granted": "\u5165\u53E3\u8C03\u7528\u6388\u6743",
12618
+ "Knowledge read granted": "\u77E5\u8BC6\u5E93\u8BFB\u53D6\u6388\u6743",
12619
+ "Knowledge write granted": "\u77E5\u8BC6\u5E93\u5199\u5165\u6388\u6743",
12620
+ "KV read granted": "KV \u8BFB\u53D6\u6388\u6743",
12621
+ "KV write granted": "KV \u5199\u5165\u6388\u6743",
12622
+ "Limit reached": "\u989D\u5EA6\u5DF2\u7528\u5C3D",
12623
+ "Loading usage...": "\u6B63\u5728\u52A0\u8F7D\u7528\u91CF...",
12624
+ Local: "\u672C\u5730",
12625
+ "Local and server": "\u672C\u5730\u4E0E\u670D\u52A1\u5668",
12626
+ "Local path": "\u672C\u5730\u8DEF\u5F84",
12627
+ "Localized names": "\u591A\u8BED\u8A00\u540D\u79F0",
12628
+ "Multiple languages": "\u591A\u8BED\u8A00",
12629
+ "Multiple platforms": "\u591A\u5E73\u53F0",
12630
+ "Not allowed": "\u4E0D\u5141\u8BB8",
12631
+ "Not available": "\u6682\u65E0\u6570\u636E",
12632
+ "Not declared": "\u672A\u58F0\u660E",
12633
+ "Platform independent": "\u5E73\u53F0\u65E0\u5173",
12634
+ "Platform support": "\u5E73\u53F0\u652F\u6301",
12635
+ Prefixes: "\u524D\u7F00",
12636
+ "Project declarations": "\u9879\u76EE\u58F0\u660E",
12637
+ "Project information": "\u9879\u76EE\u4FE1\u606F",
12638
+ "Project type": "\u9879\u76EE\u7C7B\u578B",
12639
+ "Project UUID": "\u9879\u76EE UUID",
12640
+ "Related project: {0}": "\u5173\u8054\u9879\u76EE\uFF1A{0}",
12641
+ "Storage location": "\u5B58\u50A8\u4F4D\u7F6E",
12642
+ "Usage unavailable": "\u6682\u65F6\u65E0\u6CD5\u83B7\u53D6\u7528\u91CF",
12643
+ Used: "\u5DF2\u4F7F\u7528",
12644
+ Version: "\u7248\u672C",
12645
+ "Working directory": "\u5DE5\u4F5C\u76EE\u5F55",
12646
+ "{0} (default)": "{0}\uFF08\u9ED8\u8BA4\uFF09",
12647
+ "{0} remaining": "\u5269\u4F59 {0}",
12648
+ "{0} usage": "{0}\u7528\u91CF",
12610
12649
  "Add attachment": "\u6DFB\u52A0\u9644\u4EF6",
12611
12650
  "Agent run": "Agent \u8FD0\u884C",
12612
12651
  "All chats": "\u5168\u90E8\u804A\u5929",
@@ -16070,6 +16109,17 @@ ${state2.user?.avatarUrl ?? ""}`;
16070
16109
  }
16071
16110
 
16072
16111
  // src/web/workflow-types.ts
16112
+ var projectTypeLabels = {
16113
+ get conversation() {
16114
+ return t2("Conversation");
16115
+ },
16116
+ get workflow() {
16117
+ return t2("Workflow");
16118
+ },
16119
+ get kanban() {
16120
+ return t2("Kanban");
16121
+ }
16122
+ };
16073
16123
  function workflowParamValue(field, value = field.defaultValue ?? "") {
16074
16124
  if (field.type === "file" || field.control === "audio" || !(field.multiple || field.control === "checkboxes") || Array.isArray(value)) {
16075
16125
  return value;
@@ -16171,11 +16221,20 @@ ${state2.user?.avatarUrl ?? ""}`;
16171
16221
  const label = document.createElement("span");
16172
16222
  label.className = "param-action-label";
16173
16223
  const view = { action: action2, button, label };
16224
+ if (action2.kind === "quick" && action2.id === "ai") {
16225
+ button.classList.add("param-action-ai");
16226
+ button.append(icon("sparkle"));
16227
+ }
16174
16228
  if (action2.kind === "auxiliary") {
16175
16229
  button.append(icon("settings"));
16176
16230
  view.count = document.createElement("small");
16177
16231
  }
16178
16232
  button.append(label);
16233
+ if (action2.kind === "quick") {
16234
+ view.summary = document.createElement("span");
16235
+ view.summary.className = "param-action-summary";
16236
+ button.append(view.summary);
16237
+ }
16179
16238
  if (view.count) {
16180
16239
  button.append(view.count);
16181
16240
  }
@@ -16232,14 +16291,17 @@ ${state2.user?.avatarUrl ?? ""}`;
16232
16291
  view.button.hidden = fields2.length === 0;
16233
16292
  view.button.disabled = disabled || (action2.kind === "auxiliary" ? loading : fields2.every((field) => states[field.name]?.disabled === true || this.visibleOptions(field).length === 0));
16234
16293
  const summaries = action2.summary?.map((name) => fields2.find((field) => field.name === name)).filter((field) => !!field && !!values2[field.name]?.length).map((field) => parameterSelectionLabel(field, values2[field.name], states[field.name])) ?? [];
16235
- view.label.textContent = action2.kind === "quick" && summaries.length ? `${action2.label}: ${summaries.join(" \xB7 ")}` : action2.label;
16294
+ view.label.textContent = action2.label;
16295
+ if (view.summary) {
16296
+ view.summary.textContent = summaries.join(" \xB7 ");
16297
+ view.summary.hidden = !summaries.length;
16298
+ }
16236
16299
  if (view.count) {
16237
16300
  view.count.textContent = String(fields2.length);
16238
16301
  }
16239
16302
  view.button.setAttribute("aria-busy", String(loading));
16240
16303
  }
16241
- view.button.title = view.label.textContent || "";
16242
- view.button.ariaLabel = view.label.textContent || "";
16304
+ view.button.title = view.button.ariaLabel = [view.label.textContent, view.summary?.textContent].filter(Boolean).join(": ");
16243
16305
  }
16244
16306
  if (this.active) {
16245
16307
  if (disabled || this.active.button.hidden) {
@@ -16676,15 +16738,101 @@ ${state2.user?.avatarUrl ?? ""}`;
16676
16738
  }
16677
16739
  };
16678
16740
 
16741
+ // src/web/ui/project-information.ts
16742
+ function access(rule) {
16743
+ if (rule?.mode === "all") {
16744
+ return t2("All");
16745
+ }
16746
+ if (rule?.mode === "none") {
16747
+ return t2("Not allowed");
16748
+ }
16749
+ if (rule?.mode === "prefixes") {
16750
+ return `${t2("Prefixes")}: ${rule.prefixes.join(", ")}`;
16751
+ }
16752
+ return t2("Not declared");
16753
+ }
16754
+ function projectInformation(project2) {
16755
+ const info = project2.projectInfo;
16756
+ const storage = { local: t2("Local"), server: t2("Server"), both: t2("Local and server") };
16757
+ const declarations = { multilingual: t2("Multiple languages"), multiplatform: t2("Multiple platforms") };
16758
+ const platforms = { macos: "macOS", windows: "Windows", web: "Web" };
16759
+ const sections = [{
16760
+ title: t2("Basic information"),
16761
+ expanded: true,
16762
+ rows: [
16763
+ { label: t2("Default name"), value: project2.manifest?.name || project2.name },
16764
+ { label: t2("Project type"), value: projectTypeLabels[project2.projectType] },
16765
+ { label: t2("Version"), value: project2.manifest?.version || t2("Not declared") },
16766
+ { label: t2("Project UUID"), value: project2.id },
16767
+ { label: project2.assistant ? t2("Working directory") : t2("Local path"), value: project2.assistant?.workdir || project2.folderPath }
16768
+ ]
16769
+ }, {
16770
+ title: t2("Project declarations"),
16771
+ expanded: true,
16772
+ rows: [
16773
+ { label: t2("Storage location"), value: info?.dataStorage ? storage[info.dataStorage.mode] : t2("Not declared") },
16774
+ { label: t2("Platform support"), value: info?.platformSupport.mode === "specific" ? info.platformSupport.platforms.map((id) => platforms[id] || id).join(", ") : t2("Platform independent") },
16775
+ { label: t2("Declarations"), value: info?.declarations.map((id) => declarations[id] || id).join(", ") || t2("Not declared") }
16776
+ ]
16777
+ }];
16778
+ if (info && Object.keys(info.localizedNames).length) {
16779
+ sections.push({ title: t2("Localized names"), rows: Object.entries(info.localizedNames).map(([label, value]) => ({ label, value })) });
16780
+ }
16781
+ for (const relation of info?.relatedProjects ?? []) {
16782
+ const grant = relation.grantToRelatedProject;
16783
+ sections.push({ title: t2("Related project: {0}", relation.alias), rows: [
16784
+ { label: t2("Project UUID"), value: relation.projectId },
16785
+ { label: t2("KV read granted"), value: access(grant.read) },
16786
+ { label: t2("KV write granted"), value: access(grant.write) },
16787
+ { label: t2("Knowledge read granted"), value: access(grant.knowledge?.read) },
16788
+ { label: t2("Knowledge write granted"), value: access(grant.knowledge?.write) },
16789
+ { label: t2("Entrypoints granted"), value: access(grant.entrypoints) }
16790
+ ] });
16791
+ }
16792
+ if (project2.entrypoints.length) {
16793
+ sections.push({ title: t2("Entrypoints"), rows: project2.entrypoints.map((entry) => ({
16794
+ label: entry.title || entry.id,
16795
+ value: entry.id === project2.defaultEntrypoint ? t2("{0} (default)", entry.id) : entry.id
16796
+ })) });
16797
+ }
16798
+ return sections;
16799
+ }
16800
+
16801
+ // src/web/ui/ai-usage.ts
16802
+ function usageAmount(value) {
16803
+ return value != null && Number.isFinite(Number(value)) ? `$${Math.max(0, Number(value)).toFixed(2)}` : t2("Not available");
16804
+ }
16805
+ function usagePeriods(subscription) {
16806
+ const labels = { daily: t2("Daily"), weekly: t2("Weekly"), monthly: t2("Monthly") };
16807
+ return ["daily", "weekly", "monthly"].map((period) => {
16808
+ const rawUsed = subscription[`${period}UsageUsd`], rawLimit = subscription[`${period}LimitUsd`];
16809
+ const used = Number.isFinite(Number(rawUsed)) && rawUsed != null ? Math.max(0, Number(rawUsed)) : void 0;
16810
+ const limit = rawLimit === null ? null : Number.isFinite(Number(rawLimit)) && rawLimit !== void 0 ? Math.max(0, Number(rawLimit)) : void 0;
16811
+ const ratio = used !== void 0 && limit !== null && limit !== void 0 ? limit > 0 ? used / limit : 1 : void 0;
16812
+ return {
16813
+ period,
16814
+ label: labels[period],
16815
+ used,
16816
+ limit,
16817
+ ratio,
16818
+ status: ratio === void 0 ? "" : ratio >= 1 ? "exhausted" : ratio >= 0.8 ? "near-limit" : "",
16819
+ remaining: used !== void 0 && limit !== null && limit !== void 0 ? Math.max(0, limit - used) : void 0
16820
+ };
16821
+ });
16822
+ }
16823
+
16679
16824
  // src/web/ui/conversation-tools.ts
16680
16825
  var ConversationTools = class {
16681
16826
  dialog = document.createElement("dialog");
16682
16827
  body = document.createElement("div");
16683
16828
  title = document.createElement("h2");
16684
16829
  usageOpen = false;
16830
+ usageRequestId;
16685
16831
  refresh;
16686
16832
  constructor() {
16687
16833
  this.dialog.className = "conversation-dialog";
16834
+ this.title.id = "conversation-dialog-title";
16835
+ this.dialog.setAttribute("aria-labelledby", this.title.id);
16688
16836
  const header = document.createElement("header");
16689
16837
  header.append(this.title, iconButton("close", t2("Close"), () => this.close()));
16690
16838
  this.body.className = "dialog-body";
@@ -16698,6 +16846,7 @@ ${state2.user?.avatarUrl ?? ""}`;
16698
16846
  }
16699
16847
  }
16700
16848
  });
16849
+ this.dialog.addEventListener("cancel", () => this.close());
16701
16850
  }
16702
16851
  get open() {
16703
16852
  return this.dialog.open;
@@ -16705,13 +16854,20 @@ ${state2.user?.avatarUrl ?? ""}`;
16705
16854
  close() {
16706
16855
  this.dialog.close();
16707
16856
  this.usageOpen = false;
16857
+ this.usageRequestId = void 0;
16708
16858
  this.refresh?.remove();
16709
16859
  this.refresh = void 0;
16710
16860
  }
16861
+ closeUsage() {
16862
+ if (this.usageOpen) {
16863
+ this.close();
16864
+ }
16865
+ }
16711
16866
  show(title) {
16712
16867
  this.close();
16713
16868
  this.title.textContent = title;
16714
16869
  this.body.replaceChildren();
16870
+ this.body.setAttribute("aria-busy", "false");
16715
16871
  this.dialog.showModal();
16716
16872
  }
16717
16873
  plan(content) {
@@ -16729,6 +16885,35 @@ ${state2.user?.avatarUrl ?? ""}`;
16729
16885
  image.className = "image-preview";
16730
16886
  this.body.append(image);
16731
16887
  }
16888
+ projectInfo(project2) {
16889
+ this.show(t2("Project information"));
16890
+ const heading = document.createElement("h3");
16891
+ heading.className = "project-information-name";
16892
+ heading.textContent = project2.name;
16893
+ this.body.append(heading);
16894
+ if (project2.manifest?.description) {
16895
+ const description = document.createElement("p");
16896
+ description.className = "project-information-description";
16897
+ description.textContent = project2.manifest.description;
16898
+ this.body.append(description);
16899
+ }
16900
+ for (const section of projectInformation(project2)) {
16901
+ const details = document.createElement("details");
16902
+ details.className = "project-information-section";
16903
+ details.open = !!section.expanded;
16904
+ const summary = document.createElement("summary");
16905
+ summary.innerHTML = `${iconHtml("chevron-right")}<span>${escapeHtml(section.title)}</span>`;
16906
+ const list = document.createElement("dl");
16907
+ for (const row of section.rows) {
16908
+ const label = document.createElement("dt"), value = document.createElement("dd");
16909
+ label.textContent = row.label;
16910
+ value.textContent = row.value;
16911
+ list.append(label, value);
16912
+ }
16913
+ details.append(summary, list);
16914
+ this.body.append(details);
16915
+ }
16916
+ }
16732
16917
  permissions(parameters, policies, changed) {
16733
16918
  this.show(t2("Tool permissions"));
16734
16919
  const tools = parameters.tools ?? [];
@@ -16772,35 +16957,46 @@ ${state2.user?.avatarUrl ?? ""}`;
16772
16957
  }
16773
16958
  }
16774
16959
  usage(load) {
16775
- this.show(t2("System AI"));
16960
+ this.show(t2("AI usage"));
16776
16961
  this.usageOpen = true;
16777
- const refresh = this.refresh = iconButton("refresh", t2("Refresh usage"), () => {
16778
- this.body.textContent = t2("Loading...");
16779
- load();
16780
- });
16962
+ const refresh = this.refresh = iconButton("refresh", t2("Refresh usage"), () => this.loadUsage(load));
16781
16963
  this.dialog.querySelector("header").insertBefore(refresh, this.dialog.querySelector("header > button:last-child"));
16782
- this.body.textContent = t2("Loading...");
16783
- load();
16964
+ this.loadUsage(load);
16784
16965
  }
16785
- usageResult(data, error) {
16786
- if (!this.usageOpen) {
16787
- return;
16966
+ loadUsage(load) {
16967
+ this.body.innerHTML = `<div class="usage-status" role="status">${iconHtml("loading")}<span>${t2("Loading usage...")}</span></div>`;
16968
+ this.body.setAttribute("aria-busy", "true");
16969
+ if (this.refresh) {
16970
+ this.refresh.disabled = true;
16788
16971
  }
16789
- this.body.replaceChildren();
16790
- if (error) {
16791
- this.body.textContent = error;
16972
+ this.usageRequestId = crypto.randomUUID();
16973
+ load(this.usageRequestId);
16974
+ }
16975
+ usageResult(requestId, data, error) {
16976
+ if (!this.usageOpen || requestId !== this.usageRequestId) {
16792
16977
  return;
16793
16978
  }
16794
- if (!data) {
16979
+ this.body.replaceChildren();
16980
+ this.body.setAttribute("aria-busy", "false");
16981
+ if (this.refresh) {
16982
+ this.refresh.disabled = false;
16983
+ }
16984
+ if (error || !data) {
16985
+ const status = document.createElement("p");
16986
+ status.className = error ? "error usage-status" : "usage-status";
16987
+ status.setAttribute("role", error ? "alert" : "status");
16988
+ status.textContent = error || t2("Usage unavailable");
16989
+ this.body.append(status);
16795
16990
  return;
16796
16991
  }
16797
- const balance = document.createElement("p");
16798
- balance.textContent = t2("Account balance ${0}", Number(data.balance ?? 0).toFixed(2));
16992
+ const balance = document.createElement("div");
16993
+ balance.className = "usage-balance";
16994
+ balance.innerHTML = `<span>${t2("Account balance")}</span><strong>${escapeHtml(usageAmount(data.balance))}</strong><small>USD</small>`;
16799
16995
  this.body.append(balance);
16800
- const labels = { daily: t2("Daily"), weekly: t2("Weekly"), monthly: t2("Monthly") };
16801
16996
  const plans = data.groups.filter((group) => group.subscriptionType === "subscription" && group.subscription?.status === "active");
16802
16997
  if (!plans.length) {
16803
16998
  const empty = document.createElement("p");
16999
+ empty.className = "usage-status";
16804
17000
  empty.textContent = t2("No active subscriptions");
16805
17001
  this.body.append(empty);
16806
17002
  }
@@ -16810,19 +17006,24 @@ ${state2.user?.avatarUrl ?? ""}`;
16810
17006
  const title = document.createElement("h3");
16811
17007
  title.textContent = plan.name;
16812
17008
  section.append(title);
16813
- for (const period of ["daily", "weekly", "monthly"]) {
16814
- const limit = plan.subscription[`${period}LimitUsd`];
16815
- const used = Number(plan.subscription[`${period}UsageUsd`] ?? 0);
17009
+ for (const period of usagePeriods(plan.subscription)) {
16816
17010
  const row = document.createElement("div");
16817
- const label = document.createElement("span");
16818
- label.textContent = `${labels[period]} $${used.toFixed(2)} / ${limit === null ? t2("Unlimited") : `$${Number(limit).toFixed(2)}`}`;
16819
- row.append(label);
16820
- if (limit !== null && limit > 0) {
17011
+ row.className = "usage-period";
17012
+ row.dataset.status = period.status;
17013
+ const used = period.used === void 0 ? t2("Not available") : usageAmount(period.used);
17014
+ const limit = period.limit === null ? t2("Unlimited") : period.limit === void 0 ? t2("Not available") : usageAmount(period.limit);
17015
+ row.innerHTML = `<div class="usage-period-heading"><span>${period.label}</span><strong>${period.ratio === void 0 ? escapeHtml(limit) : `${Math.round(period.ratio * 100)}%`}</strong></div><div class="usage-period-amount"><strong>${escapeHtml(used)}</strong><span>/ ${escapeHtml(limit)}</span></div>`;
17016
+ if (period.ratio !== void 0) {
16821
17017
  const progress = document.createElement("progress");
16822
- progress.max = limit;
16823
- progress.value = used;
17018
+ progress.max = 1;
17019
+ progress.value = Math.min(1, period.ratio);
17020
+ progress.ariaLabel = t2("{0} usage", period.label);
16824
17021
  row.append(progress);
16825
17022
  }
17023
+ const remaining = document.createElement("span");
17024
+ remaining.className = "usage-period-remaining";
17025
+ remaining.textContent = period.status === "exhausted" ? t2("Limit reached") : period.remaining === void 0 ? t2("Used") : t2("{0} remaining", usageAmount(period.remaining));
17026
+ row.append(remaining);
16826
17027
  section.append(row);
16827
17028
  }
16828
17029
  this.body.append(section);
@@ -17243,7 +17444,7 @@ ${state2.user?.avatarUrl ?? ""}`;
17243
17444
  var host = acquireWorkflowHost();
17244
17445
  app.classList.add("kanban-app");
17245
17446
  app.innerHTML = `
17246
- <header class="toolbar"><div class="project-title"><button id="menu-toggle" class="icon-button" aria-label="${t2("Show Kanban configurations")}" title="${t2("Show Kanban configurations")}">${iconHtml("layout-sidebar-left")}</button><span class="project-icon">${iconHtml("layout")}</span><h1 id="kanban-title">Kanban</h1></div><div class="toolbar-actions"><div id="preview-modes" class="kanban-modes" role="group" aria-label="${t2("Preview size")}"></div><button id="dimensions" class="icon-button" title="${t2("Resize preview")}" aria-label="${t2("Resize preview")}" hidden>${iconHtml("settings")}</button><button id="refresh" class="icon-button" title="${t2("Refresh Kanban")}" aria-label="${t2("Refresh Kanban")}">${iconHtml("refresh")}</button><button id="usage" class="icon-button" title="${t2("System AI usage")}" aria-label="${t2("System AI usage")}" hidden>${iconHtml("dashboard")}</button><button id="methods" class="icon-button" title="${t2("Page methods")}" aria-label="${t2("Page methods")}">${iconHtml("tools")}</button></div></header>
17447
+ <header class="toolbar"><div class="project-title"><button id="menu-toggle" class="icon-button" aria-label="${t2("Show Kanban configurations")}" title="${t2("Show Kanban configurations")}">${iconHtml("layout-sidebar-left")}</button><button id="project-info" class="icon-button" title="${t2("Project information")}" aria-label="${t2("Project information")}" aria-haspopup="dialog">${iconHtml("info")}</button><span class="project-icon">${iconHtml("layout")}</span><h1 id="kanban-title">Kanban</h1></div><div class="toolbar-actions"><div id="preview-modes" class="kanban-modes" role="group" aria-label="${t2("Preview size")}"></div><button id="dimensions" class="icon-button" title="${t2("Resize preview")}" aria-label="${t2("Resize preview")}" hidden>${iconHtml("settings")}</button><button id="refresh" class="icon-button" title="${t2("Refresh Kanban")}" aria-label="${t2("Refresh Kanban")}">${iconHtml("refresh")}</button><button id="usage" class="icon-button usage-button" title="${t2("System AI usage")}" aria-label="${t2("System AI usage")}" aria-haspopup="dialog" hidden>${iconHtml("dashboard")}<span>${t2("AI usage")}</span></button><button id="methods" class="icon-button" title="${t2("Page methods")}" aria-label="${t2("Page methods")}">${iconHtml("tools")}</button></div></header>
17247
17448
  <aside id="project-menu" class="project-menu" aria-label="${t2("Kanban configurations")}"><div class="menu-heading"><span>${t2("Kanban configurations")}</span><button id="hide-menu" class="icon-button" title="${t2("Hide Kanban configurations")}" aria-label="${t2("Hide Kanban configurations")}">${iconHtml("chevron-left")}</button></div><div id="configuration-editor"><div class="kanban-configuration-controls"><select id="configuration" aria-label="${t2("Current configuration")}"></select><button id="create" class="icon-button" title="${t2("New configuration")}" aria-label="${t2("New configuration")}">${iconHtml("add")}</button><button id="configuration-actions" class="icon-button" title="${t2("Configuration actions")}" aria-label="${t2("Configuration actions")}">${iconHtml("ellipsis")}</button></div><div id="save-error" class="error" hidden role="alert"><span></span><button id="retry-save" class="icon-button" title="${t2("Retry save")}" aria-label="${t2("Retry save")}">${iconHtml("refresh")}</button></div><div id="kanban-fields"></div><div id="parameter-actions"></div></div></aside>
17248
17449
  <main><div id="error" class="error" hidden role="alert"></div><div id="related-warning" class="kanban-warning" hidden role="status"></div><div id="preview-stage"><div id="preview-viewport"><iframe id="kanban-preview" title="Kanban" sandbox="allow-scripts"></iframe><button id="resize-preview" class="kanban-resize" title="${t2("Resize preview")}" aria-label="${t2("Resize preview")}" hidden>${iconHtml("arrow-both")}</button></div><div id="preview-status" class="kanban-status" role="status"><span class="codicon codicon-loading"></span><span>${t2("Loading Kanban")}</span><button id="retry-preview" class="icon-button" title="${t2("Retry")}" aria-label="${t2("Retry")}" hidden>${iconHtml("refresh")}</button></div><div id="preview-offline" hidden></div></div></main>
17249
17450
  <dialog id="configuration-dialog" class="conversation-dialog"><header><h2>${t2("Configuration actions")}</h2><button id="close-configurations" class="icon-button" title="${t2("Close")}" aria-label="${t2("Close")}">${iconHtml("close")}</button></header><div class="dialog-body configuration-command-list"></div></dialog>
@@ -17656,7 +17857,12 @@ ${state2.user?.avatarUrl ?? ""}`;
17656
17857
  controls();
17657
17858
  }
17658
17859
  };
17659
- element("usage").onclick = () => dialogs.usage(() => host.postMessage({ type: "usage" }));
17860
+ element("usage").onclick = () => dialogs.usage((requestId) => host.postMessage({ type: "usage", requestId }));
17861
+ element("project-info").onclick = () => {
17862
+ if (project) {
17863
+ dialogs.projectInfo(project);
17864
+ }
17865
+ };
17660
17866
  window.addEventListener("message", (event) => {
17661
17867
  const message = event.data;
17662
17868
  if (event.source === frame.contentWindow) {
@@ -17736,6 +17942,7 @@ ${state2.user?.avatarUrl ?? ""}`;
17736
17942
  saveTimer = setTimeout(() => void save().catch(showError), 250);
17737
17943
  }
17738
17944
  } else {
17945
+ dialogs.closeUsage();
17739
17946
  for (const waiting of pending.values()) {
17740
17947
  clearTimeout(waiting.timer);
17741
17948
  waiting.reject(new Error(t2("Connection interrupted.")));
@@ -17752,15 +17959,16 @@ ${state2.user?.avatarUrl ?? ""}`;
17752
17959
  if (authRevision !== message.authenticationRevision) {
17753
17960
  authRevision = message.authenticationRevision;
17754
17961
  previewKey = "";
17962
+ dialogs.closeUsage();
17755
17963
  }
17756
17964
  element("usage").hidden = message.account.status !== "authenticated";
17757
17965
  update(message.kanban);
17758
17966
  }
17759
17967
  if (message.type === "usage") {
17760
- dialogs.usageResult(message.usage);
17968
+ dialogs.usageResult(message.requestId, message.usage);
17761
17969
  }
17762
17970
  if (message.type === "error" && message.requestType === "usage") {
17763
- dialogs.usageResult(void 0, message.message);
17971
+ dialogs.usageResult(message.requestId, void 0, message.message);
17764
17972
  return;
17765
17973
  }
17766
17974
  if (message.type === "error" && !message.silent && !message.requestId) {