@workflow-code/cli 0.2.4-20261013003.codex-studio-integration → 0.2.4-20261013005.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,44 @@
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
+ "AI usage": "AI \u7528\u91CF",
12612
+ All: "\u5168\u90E8",
12613
+ "Basic information": "\u57FA\u672C\u4FE1\u606F",
12614
+ Declarations: "\u58F0\u660E",
12615
+ "Default name": "\u9ED8\u8BA4\u540D\u79F0",
12616
+ "Entrypoints granted": "\u5165\u53E3\u8C03\u7528\u6388\u6743",
12617
+ "Knowledge read granted": "\u77E5\u8BC6\u5E93\u8BFB\u53D6\u6388\u6743",
12618
+ "Knowledge write granted": "\u77E5\u8BC6\u5E93\u5199\u5165\u6388\u6743",
12619
+ "KV read granted": "KV \u8BFB\u53D6\u6388\u6743",
12620
+ "KV write granted": "KV \u5199\u5165\u6388\u6743",
12621
+ "Limit reached": "\u989D\u5EA6\u5DF2\u7528\u5C3D",
12622
+ "Loading usage...": "\u6B63\u5728\u52A0\u8F7D\u7528\u91CF...",
12623
+ Local: "\u672C\u5730",
12624
+ "Local and server": "\u672C\u5730\u4E0E\u670D\u52A1\u5668",
12625
+ "Local path": "\u672C\u5730\u8DEF\u5F84",
12626
+ "Localized names": "\u591A\u8BED\u8A00\u540D\u79F0",
12627
+ "Multiple languages": "\u591A\u8BED\u8A00",
12628
+ "Multiple platforms": "\u591A\u5E73\u53F0",
12629
+ "Not allowed": "\u4E0D\u5141\u8BB8",
12630
+ "Not available": "\u6682\u65E0\u6570\u636E",
12631
+ "Not declared": "\u672A\u58F0\u660E",
12632
+ "Platform independent": "\u5E73\u53F0\u65E0\u5173",
12633
+ "Platform support": "\u5E73\u53F0\u652F\u6301",
12634
+ Prefixes: "\u524D\u7F00",
12635
+ "Project declarations": "\u9879\u76EE\u58F0\u660E",
12636
+ "Project information": "\u9879\u76EE\u4FE1\u606F",
12637
+ "Project type": "\u9879\u76EE\u7C7B\u578B",
12638
+ "Project UUID": "\u9879\u76EE UUID",
12639
+ "Related project: {0}": "\u5173\u8054\u9879\u76EE\uFF1A{0}",
12640
+ "Storage location": "\u5B58\u50A8\u4F4D\u7F6E",
12641
+ "Usage unavailable": "\u6682\u65F6\u65E0\u6CD5\u83B7\u53D6\u7528\u91CF",
12642
+ Used: "\u5DF2\u4F7F\u7528",
12643
+ Version: "\u7248\u672C",
12644
+ "Working directory": "\u5DE5\u4F5C\u76EE\u5F55",
12645
+ "{0} (default)": "{0}\uFF08\u9ED8\u8BA4\uFF09",
12646
+ "{0} remaining": "\u5269\u4F59 {0}",
12647
+ "{0} usage": "{0}\u7528\u91CF",
12610
12648
  "Add attachment": "\u6DFB\u52A0\u9644\u4EF6",
12611
12649
  "Agent run": "Agent \u8FD0\u884C",
12612
12650
  "All chats": "\u5168\u90E8\u804A\u5929",
@@ -13014,11 +13052,20 @@
13014
13052
  const label = document.createElement("span");
13015
13053
  label.className = "param-action-label";
13016
13054
  const view = { action, button, label };
13055
+ if (action.kind === "quick" && action.id === "ai") {
13056
+ button.classList.add("param-action-ai");
13057
+ button.append(icon("sparkle"));
13058
+ }
13017
13059
  if (action.kind === "auxiliary") {
13018
13060
  button.append(icon("settings"));
13019
13061
  view.count = document.createElement("small");
13020
13062
  }
13021
13063
  button.append(label);
13064
+ if (action.kind === "quick") {
13065
+ view.summary = document.createElement("span");
13066
+ view.summary.className = "param-action-summary";
13067
+ button.append(view.summary);
13068
+ }
13022
13069
  if (view.count) {
13023
13070
  button.append(view.count);
13024
13071
  }
@@ -13075,14 +13122,17 @@
13075
13122
  view.button.hidden = fields.length === 0;
13076
13123
  view.button.disabled = disabled || (action.kind === "auxiliary" ? loading : fields.every((field) => states[field.name]?.disabled === true || this.visibleOptions(field).length === 0));
13077
13124
  const summaries = action.summary?.map((name) => fields.find((field) => field.name === name)).filter((field) => !!field && !!values[field.name]?.length).map((field) => parameterSelectionLabel(field, values[field.name], states[field.name])) ?? [];
13078
- view.label.textContent = action.kind === "quick" && summaries.length ? `${action.label}: ${summaries.join(" \xB7 ")}` : action.label;
13125
+ view.label.textContent = action.label;
13126
+ if (view.summary) {
13127
+ view.summary.textContent = summaries.join(" \xB7 ");
13128
+ view.summary.hidden = !summaries.length;
13129
+ }
13079
13130
  if (view.count) {
13080
13131
  view.count.textContent = String(fields.length);
13081
13132
  }
13082
13133
  view.button.setAttribute("aria-busy", String(loading));
13083
13134
  }
13084
- view.button.title = view.label.textContent || "";
13085
- view.button.ariaLabel = view.label.textContent || "";
13135
+ view.button.title = view.button.ariaLabel = [view.label.textContent, view.summary?.textContent].filter(Boolean).join(": ");
13086
13136
  }
13087
13137
  if (this.active) {
13088
13138
  if (disabled || this.active.button.hidden) {
@@ -13332,6 +13382,17 @@
13332
13382
  };
13333
13383
 
13334
13384
  // src/web/workflow-types.ts
13385
+ var projectTypeLabels = {
13386
+ get conversation() {
13387
+ return t2("Conversation");
13388
+ },
13389
+ get workflow() {
13390
+ return t2("Workflow");
13391
+ },
13392
+ get kanban() {
13393
+ return t2("Kanban");
13394
+ }
13395
+ };
13335
13396
  function workflowParameters(project, entrypointId) {
13336
13397
  return project.entrypoints.find((entry) => entry.id === entrypointId) ?? project;
13337
13398
  }
@@ -15908,6 +15969,89 @@ Please report this to https://github.com/markedjs/marked.`, e) {
15908
15969
  }
15909
15970
  };
15910
15971
 
15972
+ // src/web/ui/project-information.ts
15973
+ function access(rule) {
15974
+ if (rule?.mode === "all") {
15975
+ return t2("All");
15976
+ }
15977
+ if (rule?.mode === "none") {
15978
+ return t2("Not allowed");
15979
+ }
15980
+ if (rule?.mode === "prefixes") {
15981
+ return `${t2("Prefixes")}: ${rule.prefixes.join(", ")}`;
15982
+ }
15983
+ return t2("Not declared");
15984
+ }
15985
+ function projectInformation(project) {
15986
+ const info = project.projectInfo;
15987
+ const storage = { local: t2("Local"), server: t2("Server"), both: t2("Local and server") };
15988
+ const declarations = { multilingual: t2("Multiple languages"), multiplatform: t2("Multiple platforms") };
15989
+ const platforms = { macos: "macOS", windows: "Windows", web: "Web" };
15990
+ const sections = [{
15991
+ title: t2("Basic information"),
15992
+ expanded: true,
15993
+ rows: [
15994
+ { label: t2("Default name"), value: project.manifest?.name || project.name },
15995
+ { label: t2("Project type"), value: projectTypeLabels[project.projectType] },
15996
+ { label: t2("Version"), value: project.manifest?.version || t2("Not declared") },
15997
+ { label: t2("Project UUID"), value: project.id },
15998
+ { label: project.assistant ? t2("Working directory") : t2("Local path"), value: project.assistant?.workdir || project.folderPath }
15999
+ ]
16000
+ }, {
16001
+ title: t2("Project declarations"),
16002
+ expanded: true,
16003
+ rows: [
16004
+ { label: t2("Storage location"), value: info?.dataStorage ? storage[info.dataStorage.mode] : t2("Not declared") },
16005
+ { label: t2("Platform support"), value: info?.platformSupport.mode === "specific" ? info.platformSupport.platforms.map((id) => platforms[id] || id).join(", ") : t2("Platform independent") },
16006
+ { label: t2("Declarations"), value: info?.declarations.map((id) => declarations[id] || id).join(", ") || t2("Not declared") }
16007
+ ]
16008
+ }];
16009
+ if (info && Object.keys(info.localizedNames).length) {
16010
+ sections.push({ title: t2("Localized names"), rows: Object.entries(info.localizedNames).map(([label, value]) => ({ label, value })) });
16011
+ }
16012
+ for (const relation of info?.relatedProjects ?? []) {
16013
+ const grant = relation.grantToRelatedProject;
16014
+ sections.push({ title: t2("Related project: {0}", relation.alias), rows: [
16015
+ { label: t2("Project UUID"), value: relation.projectId },
16016
+ { label: t2("KV read granted"), value: access(grant.read) },
16017
+ { label: t2("KV write granted"), value: access(grant.write) },
16018
+ { label: t2("Knowledge read granted"), value: access(grant.knowledge?.read) },
16019
+ { label: t2("Knowledge write granted"), value: access(grant.knowledge?.write) },
16020
+ { label: t2("Entrypoints granted"), value: access(grant.entrypoints) }
16021
+ ] });
16022
+ }
16023
+ if (project.entrypoints.length) {
16024
+ sections.push({ title: t2("Entrypoints"), rows: project.entrypoints.map((entry) => ({
16025
+ label: entry.title || entry.id,
16026
+ value: entry.id === project.defaultEntrypoint ? t2("{0} (default)", entry.id) : entry.id
16027
+ })) });
16028
+ }
16029
+ return sections;
16030
+ }
16031
+
16032
+ // src/web/ui/ai-usage.ts
16033
+ function usageAmount(value) {
16034
+ return value != null && Number.isFinite(Number(value)) ? `$${Math.max(0, Number(value)).toFixed(2)}` : t2("Not available");
16035
+ }
16036
+ function usagePeriods(subscription) {
16037
+ const labels = { daily: t2("Daily"), weekly: t2("Weekly"), monthly: t2("Monthly") };
16038
+ return ["daily", "weekly", "monthly"].map((period) => {
16039
+ const rawUsed = subscription[`${period}UsageUsd`], rawLimit = subscription[`${period}LimitUsd`];
16040
+ const used = Number.isFinite(Number(rawUsed)) && rawUsed != null ? Math.max(0, Number(rawUsed)) : void 0;
16041
+ const limit = rawLimit === null ? null : Number.isFinite(Number(rawLimit)) && rawLimit !== void 0 ? Math.max(0, Number(rawLimit)) : void 0;
16042
+ const ratio = used !== void 0 && limit !== null && limit !== void 0 ? limit > 0 ? used / limit : 1 : void 0;
16043
+ return {
16044
+ period,
16045
+ label: labels[period],
16046
+ used,
16047
+ limit,
16048
+ ratio,
16049
+ status: ratio === void 0 ? "" : ratio >= 1 ? "exhausted" : ratio >= 0.8 ? "near-limit" : "",
16050
+ remaining: used !== void 0 && limit !== null && limit !== void 0 ? Math.max(0, limit - used) : void 0
16051
+ };
16052
+ });
16053
+ }
16054
+
15911
16055
  // src/web/ui/conversation-tools.ts
15912
16056
  var ConversationTools = class {
15913
16057
  dialog = document.createElement("dialog");
@@ -15917,6 +16061,8 @@ Please report this to https://github.com/markedjs/marked.`, e) {
15917
16061
  refresh;
15918
16062
  constructor() {
15919
16063
  this.dialog.className = "conversation-dialog";
16064
+ this.title.id = "conversation-dialog-title";
16065
+ this.dialog.setAttribute("aria-labelledby", this.title.id);
15920
16066
  const header = document.createElement("header");
15921
16067
  header.append(this.title, iconButton("close", t2("Close"), () => this.close()));
15922
16068
  this.body.className = "dialog-body";
@@ -15930,6 +16076,7 @@ Please report this to https://github.com/markedjs/marked.`, e) {
15930
16076
  }
15931
16077
  }
15932
16078
  });
16079
+ this.dialog.addEventListener("cancel", () => this.close());
15933
16080
  }
15934
16081
  get open() {
15935
16082
  return this.dialog.open;
@@ -15944,6 +16091,7 @@ Please report this to https://github.com/markedjs/marked.`, e) {
15944
16091
  this.close();
15945
16092
  this.title.textContent = title;
15946
16093
  this.body.replaceChildren();
16094
+ this.body.setAttribute("aria-busy", "false");
15947
16095
  this.dialog.showModal();
15948
16096
  }
15949
16097
  plan(content) {
@@ -15961,6 +16109,35 @@ Please report this to https://github.com/markedjs/marked.`, e) {
15961
16109
  image.className = "image-preview";
15962
16110
  this.body.append(image);
15963
16111
  }
16112
+ projectInfo(project) {
16113
+ this.show(t2("Project information"));
16114
+ const heading = document.createElement("h3");
16115
+ heading.className = "project-information-name";
16116
+ heading.textContent = project.name;
16117
+ this.body.append(heading);
16118
+ if (project.manifest?.description) {
16119
+ const description = document.createElement("p");
16120
+ description.className = "project-information-description";
16121
+ description.textContent = project.manifest.description;
16122
+ this.body.append(description);
16123
+ }
16124
+ for (const section of projectInformation(project)) {
16125
+ const details = document.createElement("details");
16126
+ details.className = "project-information-section";
16127
+ details.open = !!section.expanded;
16128
+ const summary = document.createElement("summary");
16129
+ summary.innerHTML = `${iconHtml("chevron-right")}<span>${escapeHtml(section.title)}</span>`;
16130
+ const list = document.createElement("dl");
16131
+ for (const row of section.rows) {
16132
+ const label = document.createElement("dt"), value = document.createElement("dd");
16133
+ label.textContent = row.label;
16134
+ value.textContent = row.value;
16135
+ list.append(label, value);
16136
+ }
16137
+ details.append(summary, list);
16138
+ this.body.append(details);
16139
+ }
16140
+ }
15964
16141
  permissions(parameters, policies, changed) {
15965
16142
  this.show(t2("Tool permissions"));
15966
16143
  const tools = parameters.tools ?? [];
@@ -16004,14 +16181,18 @@ Please report this to https://github.com/markedjs/marked.`, e) {
16004
16181
  }
16005
16182
  }
16006
16183
  usage(load) {
16007
- this.show(t2("System AI"));
16184
+ this.show(t2("AI usage"));
16008
16185
  this.usageOpen = true;
16009
- const refresh = this.refresh = iconButton("refresh", t2("Refresh usage"), () => {
16010
- this.body.textContent = t2("Loading...");
16011
- load();
16012
- });
16186
+ const refresh = this.refresh = iconButton("refresh", t2("Refresh usage"), () => this.loadUsage(load));
16013
16187
  this.dialog.querySelector("header").insertBefore(refresh, this.dialog.querySelector("header > button:last-child"));
16014
- this.body.textContent = t2("Loading...");
16188
+ this.loadUsage(load);
16189
+ }
16190
+ loadUsage(load) {
16191
+ this.body.innerHTML = `<div class="usage-status" role="status">${iconHtml("loading")}<span>${t2("Loading usage...")}</span></div>`;
16192
+ this.body.setAttribute("aria-busy", "true");
16193
+ if (this.refresh) {
16194
+ this.refresh.disabled = true;
16195
+ }
16015
16196
  load();
16016
16197
  }
16017
16198
  usageResult(data, error) {
@@ -16019,20 +16200,26 @@ Please report this to https://github.com/markedjs/marked.`, e) {
16019
16200
  return;
16020
16201
  }
16021
16202
  this.body.replaceChildren();
16022
- if (error) {
16023
- this.body.textContent = error;
16024
- return;
16025
- }
16026
- if (!data) {
16203
+ this.body.setAttribute("aria-busy", "false");
16204
+ if (this.refresh) {
16205
+ this.refresh.disabled = false;
16206
+ }
16207
+ if (error || !data) {
16208
+ const status = document.createElement("p");
16209
+ status.className = error ? "error usage-status" : "usage-status";
16210
+ status.setAttribute("role", error ? "alert" : "status");
16211
+ status.textContent = error || t2("Usage unavailable");
16212
+ this.body.append(status);
16027
16213
  return;
16028
16214
  }
16029
- const balance = document.createElement("p");
16030
- balance.textContent = t2("Account balance ${0}", Number(data.balance ?? 0).toFixed(2));
16215
+ const balance = document.createElement("div");
16216
+ balance.className = "usage-balance";
16217
+ balance.innerHTML = `<span>${t2("Account balance")}</span><strong>${escapeHtml(usageAmount(data.balance))}</strong><small>USD</small>`;
16031
16218
  this.body.append(balance);
16032
- const labels = { daily: t2("Daily"), weekly: t2("Weekly"), monthly: t2("Monthly") };
16033
16219
  const plans = data.groups.filter((group) => group.subscriptionType === "subscription" && group.subscription?.status === "active");
16034
16220
  if (!plans.length) {
16035
16221
  const empty = document.createElement("p");
16222
+ empty.className = "usage-status";
16036
16223
  empty.textContent = t2("No active subscriptions");
16037
16224
  this.body.append(empty);
16038
16225
  }
@@ -16042,19 +16229,24 @@ Please report this to https://github.com/markedjs/marked.`, e) {
16042
16229
  const title = document.createElement("h3");
16043
16230
  title.textContent = plan.name;
16044
16231
  section.append(title);
16045
- for (const period of ["daily", "weekly", "monthly"]) {
16046
- const limit = plan.subscription[`${period}LimitUsd`];
16047
- const used = Number(plan.subscription[`${period}UsageUsd`] ?? 0);
16232
+ for (const period of usagePeriods(plan.subscription)) {
16048
16233
  const row = document.createElement("div");
16049
- const label = document.createElement("span");
16050
- label.textContent = `${labels[period]} $${used.toFixed(2)} / ${limit === null ? t2("Unlimited") : `$${Number(limit).toFixed(2)}`}`;
16051
- row.append(label);
16052
- if (limit !== null && limit > 0) {
16234
+ row.className = "usage-period";
16235
+ row.dataset.status = period.status;
16236
+ const used = period.used === void 0 ? t2("Not available") : usageAmount(period.used);
16237
+ const limit = period.limit === null ? t2("Unlimited") : period.limit === void 0 ? t2("Not available") : usageAmount(period.limit);
16238
+ 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>`;
16239
+ if (period.ratio !== void 0) {
16053
16240
  const progress = document.createElement("progress");
16054
- progress.max = limit;
16055
- progress.value = used;
16241
+ progress.max = 1;
16242
+ progress.value = Math.min(1, period.ratio);
16243
+ progress.ariaLabel = t2("{0} usage", period.label);
16056
16244
  row.append(progress);
16057
16245
  }
16246
+ const remaining = document.createElement("span");
16247
+ remaining.className = "usage-period-remaining";
16248
+ remaining.textContent = period.status === "exhausted" ? t2("Limit reached") : period.remaining === void 0 ? t2("Used") : t2("{0} remaining", usageAmount(period.remaining));
16249
+ row.append(remaining);
16058
16250
  section.append(row);
16059
16251
  }
16060
16252
  this.body.append(section);
@@ -17881,11 +18073,11 @@ ${state.user?.avatarUrl ?? ""}`;
17881
18073
  app.dataset.initialized = "true";
17882
18074
  app.innerHTML = `
17883
18075
  <header class="toolbar">
17884
- <div class="project-title"><button id="menu-toggle" class="icon-button" title="${t2("Show conversations")}" aria-label="${t2("Show conversations")}" aria-controls="project-menu">${iconHtml("layout-sidebar-left")}</button><span id="project-icon" class="project-icon">${iconHtml("comment-discussion")}</span><div class="project-heading"><h1 id="conversation-title">Workflow</h1><span id="assistant-folder" hidden></span></div><span id="project-name" class="project-name"></span></div>
17885
- <div class="toolbar-actions"><button id="usage" class="icon-button" title="${t2("System AI usage")}" aria-label="${t2("System AI usage")}" hidden>${iconHtml("dashboard")}</button><button id="tools" class="icon-button" title="${t2("Tool permissions")}" aria-label="${t2("Tool permissions")}" hidden>${iconHtml("tools")}</button></div>
18076
+ <div class="project-title"><button id="menu-toggle" class="icon-button" title="${t2("Show conversations")}" aria-label="${t2("Show conversations")}" aria-controls="project-menu">${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 id="project-icon" class="project-icon">${iconHtml("comment-discussion")}</span><div class="project-heading"><h1 id="conversation-title">Workflow</h1><span id="assistant-folder" hidden></span></div><span id="project-name" class="project-name"></span></div>
18077
+ <div class="toolbar-actions"><button id="new" class="icon-button" title="${t2("New conversation")}" aria-label="${t2("New conversation")}">${iconHtml("comment-add")}</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="tools" class="icon-button" title="${t2("Tool permissions")}" aria-label="${t2("Tool permissions")}" hidden>${iconHtml("tools")}</button></div>
17886
18078
  </header>
17887
18079
  <aside id="project-menu" class="project-menu" aria-label="${t2("Conversations")}">
17888
- <div class="menu-heading"><span id="menu-label">${t2("Conversations")}</span><div class="menu-actions"><button id="history-toggle" class="icon-button" title="${t2("Search conversations")}" aria-label="${t2("Search conversations")}" aria-haspopup="dialog" aria-controls="history-popover" aria-expanded="false" popovertarget="history-popover">${iconHtml("search")}</button><button id="new" class="icon-button" title="${t2("New conversation")}" aria-label="${t2("New conversation")}">${iconHtml("edit")}</button><button id="hide-menu" class="icon-button" title="${t2("Hide conversations")}" aria-label="${t2("Hide conversations")}">${iconHtml("chevron-left")}</button></div></div>
18080
+ <div class="menu-heading"><span id="menu-label">${t2("Conversations")}</span><div class="menu-actions"><button id="history-toggle" class="icon-button" title="${t2("Search conversations")}" aria-label="${t2("Search conversations")}" aria-haspopup="dialog" aria-controls="history-popover" aria-expanded="false" popovertarget="history-popover">${iconHtml("search")}</button><button id="hide-menu" class="icon-button" title="${t2("Hide conversations")}" aria-label="${t2("Hide conversations")}">${iconHtml("chevron-left")}</button></div></div>
17889
18081
  <section id="chats"><nav id="session-list" aria-label="${t2("Conversation history")}"></nav><button id="load-more-history" class="all-history" hidden>${iconHtml("chevron-down")}<span>${t2("Load more")}</span></button><button id="all-history" class="all-history" aria-haspopup="dialog" aria-controls="history-popover" aria-expanded="false" popovertarget="history-popover" hidden></button><div id="no-history" class="no-history" hidden>${t2("No conversations")}</div></section>
17890
18082
  </aside>
17891
18083
  <main><div class="transcript-area"><div id="transcript" class="transcript" role="log" aria-label="${t2("Conversation messages")}" aria-live="polite" aria-relevant="additions"></div><button id="latest" class="icon-button latest-button" title="${t2("Go to latest message")}" aria-label="${t2("Go to latest message")}" hidden>${iconHtml("arrow-down")}</button></div>
@@ -17977,8 +18169,6 @@ ${state.user?.avatarUrl ?? ""}`;
17977
18169
  const toggle = document.querySelector("#menu-toggle");
17978
18170
  toggle.hidden = open;
17979
18171
  toggle.setAttribute("aria-expanded", String(open));
17980
- const actions = document.querySelector(narrow.matches && open ? ".menu-actions" : ".toolbar-actions");
17981
- actions.prepend(document.querySelector("#usage"), document.querySelector("#tools"));
17982
18172
  document.querySelector("#menu-label").textContent = narrow.matches ? t2("Chat") : t2("Conversations");
17983
18173
  closeHistory();
17984
18174
  renderHistory(true);
@@ -18864,6 +19054,12 @@ ${state.user?.avatarUrl ?? ""}`;
18864
19054
  saveDraft();
18865
19055
  post({ type: "new", text: textarea.value, attachments: draftFiles });
18866
19056
  });
19057
+ document.querySelector("#project-info").addEventListener("click", () => {
19058
+ if (state) {
19059
+ parameterActions.close();
19060
+ dialogs.projectInfo(state.project);
19061
+ }
19062
+ });
18867
19063
  document.querySelector("#attach").addEventListener("click", () => post({ type: "attach" }));
18868
19064
  document.querySelector("#cancel-queue-edit").addEventListener("click", () => post({ type: "queue-cancel-edit" }));
18869
19065
  document.querySelector("#tools").addEventListener("click", () => dialogs.permissions(currentParameters(), currentSession()?.toolPermissionPolicies ?? {}, (policies) => post({ type: "tool-policy", entrypointId: entrypoint.value, policies })));
@@ -70,6 +70,7 @@ summary:focus-visible {
70
70
  }
71
71
  .project-heading {
72
72
  min-width: 0;
73
+ flex: 1;
73
74
  }
74
75
  #assistant-folder {
75
76
  display: block;
@@ -107,6 +108,9 @@ h1 {
107
108
  .project-name {
108
109
  color: var(--muted);
109
110
  font-size: 10px;
111
+ max-width: 160px;
112
+ overflow: hidden;
113
+ text-overflow: ellipsis;
110
114
  white-space: nowrap;
111
115
  }
112
116
  .toolbar-actions {
@@ -131,6 +135,15 @@ h1 {
131
135
  .icon-button:hover:not(:disabled) {
132
136
  background: var(--vscode-toolbar-hoverBackground);
133
137
  }
138
+ .usage-button {
139
+ width: auto;
140
+ gap: 6px;
141
+ padding: 0 8px;
142
+ color: var(--vscode-textLink-foreground);
143
+ white-space: nowrap;
144
+ font-size: 12px;
145
+ font-weight: 500;
146
+ }
134
147
  .toolbar-actions [aria-expanded=true] {
135
148
  background: var(--vscode-toolbar-activeBackground, var(--vscode-toolbar-hoverBackground));
136
149
  }
@@ -1304,6 +1317,52 @@ main {
1304
1317
  overflow: auto;
1305
1318
  padding: 16px;
1306
1319
  }
1320
+ .project-information-name {
1321
+ margin: 0 0 8px;
1322
+ font-size: 18px;
1323
+ line-height: 1.4;
1324
+ overflow-wrap: anywhere;
1325
+ }
1326
+ .project-information-description {
1327
+ margin: 0 0 16px;
1328
+ color: var(--muted);
1329
+ line-height: 1.6;
1330
+ white-space: pre-wrap;
1331
+ overflow-wrap: anywhere;
1332
+ }
1333
+ .project-information-section {
1334
+ padding: 10px 0;
1335
+ border-top: 1px solid var(--border);
1336
+ }
1337
+ .project-information-section summary {
1338
+ display: flex;
1339
+ align-items: center;
1340
+ gap: 6px;
1341
+ min-height: 28px;
1342
+ font-weight: 500;
1343
+ cursor: pointer;
1344
+ overflow-wrap: anywhere;
1345
+ }
1346
+ .project-information-section[open] summary > .codicon {
1347
+ transform: rotate(90deg);
1348
+ }
1349
+ .project-information-section dl {
1350
+ display: grid;
1351
+ grid-template-columns: minmax(80px, 130px) minmax(0, 1fr);
1352
+ gap: 12px 16px;
1353
+ margin: 12px 0 4px;
1354
+ line-height: 1.5;
1355
+ }
1356
+ .project-information-section dt {
1357
+ color: var(--muted);
1358
+ overflow-wrap: anywhere;
1359
+ }
1360
+ .project-information-section dd {
1361
+ margin: 0;
1362
+ white-space: pre-wrap;
1363
+ overflow-wrap: anywhere;
1364
+ user-select: text;
1365
+ }
1307
1366
  .action-dialog {
1308
1367
  width: min(380px, calc(100vw - 32px));
1309
1368
  }
@@ -1348,25 +1407,122 @@ main {
1348
1407
  .permissions-table td:not(:first-child) {
1349
1408
  text-align: center;
1350
1409
  }
1410
+ .usage-balance {
1411
+ display: flex;
1412
+ flex-wrap: wrap;
1413
+ align-items: baseline;
1414
+ gap: 8px 10px;
1415
+ padding: 4px 0 20px;
1416
+ }
1417
+ .usage-balance > span {
1418
+ flex-basis: 100%;
1419
+ color: var(--muted);
1420
+ font-size: 12px;
1421
+ }
1422
+ .usage-balance > strong {
1423
+ font-size: 28px;
1424
+ font-weight: 600;
1425
+ font-variant-numeric: tabular-nums;
1426
+ overflow-wrap: anywhere;
1427
+ }
1428
+ .usage-balance small {
1429
+ color: var(--muted);
1430
+ font-size: 11px;
1431
+ }
1432
+ .usage-status {
1433
+ display: flex;
1434
+ align-items: center;
1435
+ gap: 8px;
1436
+ min-height: 52px;
1437
+ margin: 0;
1438
+ color: var(--muted);
1439
+ overflow-wrap: anywhere;
1440
+ }
1441
+ .usage-status.error {
1442
+ color: var(--vscode-errorForeground);
1443
+ }
1444
+ .usage-status > .codicon-loading {
1445
+ animation: spin 1.2s linear infinite;
1446
+ }
1351
1447
  .usage-plan {
1352
- padding: 12px 0;
1448
+ display: grid;
1449
+ grid-template-columns: repeat(3, minmax(0, 1fr));
1450
+ gap: 16px;
1451
+ padding: 18px 0;
1353
1452
  border-top: 1px solid var(--border);
1354
1453
  }
1355
1454
  .usage-plan h3 {
1356
- margin: 0 0 12px;
1357
- font-size: 13px;
1455
+ grid-column: 1 / -1;
1456
+ margin: 0;
1457
+ font-size: 14px;
1458
+ overflow-wrap: anywhere;
1358
1459
  }
1359
- .usage-plan > div {
1460
+ .usage-period {
1360
1461
  display: grid;
1361
- gap: 6px;
1362
- margin: 12px 0;
1462
+ align-content: start;
1463
+ gap: 10px;
1464
+ min-width: 0;
1363
1465
  font-size: 12px;
1364
1466
  }
1467
+ .usage-period-heading {
1468
+ display: flex;
1469
+ justify-content: space-between;
1470
+ align-items: baseline;
1471
+ flex-wrap: wrap;
1472
+ gap: 6px;
1473
+ }
1474
+ .usage-period-heading > span {
1475
+ color: var(--muted);
1476
+ }
1477
+ .usage-period-amount {
1478
+ display: flex;
1479
+ flex-wrap: wrap;
1480
+ align-items: baseline;
1481
+ gap: 4px;
1482
+ font-variant-numeric: tabular-nums;
1483
+ overflow-wrap: anywhere;
1484
+ }
1485
+ .usage-period-amount > strong {
1486
+ font-size: 18px;
1487
+ font-weight: 600;
1488
+ }
1489
+ .usage-period-amount > span,
1490
+ .usage-period-remaining {
1491
+ color: var(--muted);
1492
+ }
1365
1493
  .usage-plan progress {
1494
+ appearance: none;
1366
1495
  width: 100%;
1367
- height: 6px;
1496
+ height: 8px;
1497
+ border: 0;
1498
+ border-radius: 4px;
1499
+ overflow: hidden;
1500
+ background: var(--vscode-textCodeBlock-background);
1501
+ color: var(--vscode-progressBar-background);
1368
1502
  accent-color: var(--vscode-progressBar-background);
1369
1503
  }
1504
+ .usage-plan progress::-webkit-progress-bar {
1505
+ background: var(--vscode-textCodeBlock-background);
1506
+ }
1507
+ .usage-plan progress::-webkit-progress-value {
1508
+ background: var(--vscode-progressBar-background);
1509
+ }
1510
+ .usage-plan progress::-moz-progress-bar {
1511
+ background: var(--vscode-progressBar-background);
1512
+ }
1513
+ .usage-period[data-status=near-limit] {
1514
+ --vscode-progressBar-background: var(--vscode-editorWarning-foreground);
1515
+ }
1516
+ .usage-period[data-status=exhausted] {
1517
+ --vscode-progressBar-background: var(--vscode-errorForeground);
1518
+ }
1519
+ .usage-period[data-status=near-limit] .usage-period-heading > strong {
1520
+ color: var(--vscode-editorWarning-foreground);
1521
+ }
1522
+ .usage-period[data-status=exhausted] .usage-period-heading > strong,
1523
+ .usage-period[data-status=exhausted] .usage-period-remaining {
1524
+ color: var(--vscode-errorForeground);
1525
+ }
1370
1526
  .content-search {
1371
1527
  position: absolute;
1372
1528
  top: 4px;
@@ -1537,6 +1693,20 @@ textarea::placeholder {
1537
1693
  text-overflow: ellipsis;
1538
1694
  white-space: nowrap;
1539
1695
  }
1696
+ .param-action-summary {
1697
+ min-width: 0;
1698
+ overflow: hidden;
1699
+ text-overflow: ellipsis;
1700
+ white-space: nowrap;
1701
+ color: var(--vscode-editor-foreground);
1702
+ }
1703
+ .param-action:has(.param-action-summary:not([hidden])) .param-action-label {
1704
+ flex-shrink: 0;
1705
+ font-weight: 500;
1706
+ }
1707
+ .param-action-ai {
1708
+ color: var(--vscode-textLink-foreground);
1709
+ }
1540
1710
  .param-action .codicon {
1541
1711
  flex-shrink: 0;
1542
1712
  font-size: 13px;
@@ -1733,12 +1903,9 @@ textarea::placeholder {
1733
1903
  }
1734
1904
  @media (max-width: 680px) {
1735
1905
  #app.menu-open {
1736
- grid-template-areas: "menu" "main";
1906
+ grid-template-areas: "toolbar" "menu" "main";
1737
1907
  grid-template-columns: minmax(0, 1fr);
1738
- grid-template-rows: auto minmax(0, 1fr);
1739
- }
1740
- .menu-open .toolbar {
1741
- display: none;
1908
+ grid-template-rows: auto auto minmax(0, 1fr);
1742
1909
  }
1743
1910
  .toolbar {
1744
1911
  padding: 8px 12px;
@@ -1750,6 +1917,9 @@ textarea::placeholder {
1750
1917
  .project-name {
1751
1918
  display: none;
1752
1919
  }
1920
+ .project-icon {
1921
+ display: none;
1922
+ }
1753
1923
  .toolbar-actions {
1754
1924
  gap: 1px;
1755
1925
  }
@@ -1781,6 +1951,15 @@ textarea::placeholder {
1781
1951
  padding: 8px 18px 10px;
1782
1952
  }
1783
1953
  }
1954
+ @media (max-width: 520px) {
1955
+ .usage-plan {
1956
+ grid-template-columns: minmax(0, 1fr);
1957
+ gap: 18px;
1958
+ }
1959
+ .usage-period-amount > strong {
1960
+ font-size: 20px;
1961
+ }
1962
+ }
1784
1963
  @media (max-width: 420px) {
1785
1964
  .toolbar {
1786
1965
  padding: 8px;
@@ -1788,6 +1967,14 @@ textarea::placeholder {
1788
1967
  .project-title {
1789
1968
  gap: 2px;
1790
1969
  }
1970
+ .usage-button {
1971
+ gap: 4px;
1972
+ padding-inline: 5px;
1973
+ }
1974
+ .project-information-section dl {
1975
+ grid-template-columns: minmax(72px, 95px) minmax(0, 1fr);
1976
+ gap: 10px;
1977
+ }
1791
1978
  h1 {
1792
1979
  font-size: 13px;
1793
1980
  }