dsh-github-copilot 0.4.0-alpha.30 → 0.4.0-alpha.32

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/lib/client.js CHANGED
@@ -5410,7 +5410,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5410
5410
  expectedRevision: revision
5411
5411
  }).strict();
5412
5412
  const DualModelCreateResultSchema = object$1({ sessionId: id }).strict();
5413
- const contribution$2 = {
5413
+ const contribution$3 = {
5414
5414
  package: "dsh-github-copilot",
5415
5415
  descriptors: [
5416
5416
  {
@@ -5458,7 +5458,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5458
5458
  supported: boolean(),
5459
5459
  providers: array(object$1({ id: string().min(1).max(512) }).strict()).max(512)
5460
5460
  }).strict();
5461
- const contribution$1 = {
5461
+ const contribution$2 = {
5462
5462
  package: "dsh-github-copilot",
5463
5463
  descriptors: [{
5464
5464
  id: "dsh-github-copilot:githubCopilotSearchRouting.providers",
@@ -5471,6 +5471,97 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5471
5471
  }]
5472
5472
  };
5473
5473
  //#endregion
5474
+ //#region lib/types/copilot-usage-types.js
5475
+ const COPILOT_USAGE_MAX_AMOUNT = 0xe8d4a51000;
5476
+ const COPILOT_USAGE_MAX_TIMESTAMP = 0xe677d21fdbff;
5477
+ const COPILOT_USAGE_DIAGNOSTICS = [
5478
+ "COPILOT_USAGE_SIGNED_OUT",
5479
+ "COPILOT_USAGE_INVALID_GRANT",
5480
+ "COPILOT_USAGE_CREDENTIALS_UNAVAILABLE",
5481
+ "COPILOT_USAGE_ENTERPRISE_UNSUPPORTED",
5482
+ "COPILOT_USAGE_ACCOUNT_CHANGED",
5483
+ "COPILOT_USAGE_DISPOSED",
5484
+ "COPILOT_USAGE_BILLING_UNKNOWN",
5485
+ "COPILOT_USAGE_SNAPSHOT_MISSING",
5486
+ "COPILOT_USAGE_INVALID_RESPONSE",
5487
+ "COPILOT_USAGE_POOLED_UNAVAILABLE",
5488
+ "COPILOT_USAGE_POOLED_EXHAUSTED",
5489
+ "COPILOT_USAGE_NO_ALLOCATION",
5490
+ "COPILOT_USAGE_NETWORK",
5491
+ "COPILOT_USAGE_TIMEOUT",
5492
+ "COPILOT_USAGE_BODY_TOO_LARGE",
5493
+ "COPILOT_USAGE_REDIRECT",
5494
+ "COPILOT_USAGE_AUTH_REJECTED",
5495
+ "COPILOT_USAGE_HTTP_ERROR",
5496
+ "COPILOT_USAGE_RATE_LIMITED"
5497
+ ];
5498
+ //#endregion
5499
+ //#region lib/types/copilot-usage-remote.js
5500
+ const amount$1 = number().finite().nonnegative().max(COPILOT_USAGE_MAX_AMOUNT);
5501
+ const timestamp = number().int().nonnegative().max(COPILOT_USAGE_MAX_TIMESTAMP);
5502
+ const CopilotUsageViewSchema = object$1({
5503
+ state: _enum([
5504
+ "ready",
5505
+ "stale",
5506
+ "unavailable",
5507
+ "signed-out"
5508
+ ]),
5509
+ billing: _enum([
5510
+ "credits",
5511
+ "requests",
5512
+ "unknown"
5513
+ ]),
5514
+ budget: _enum([
5515
+ "individual",
5516
+ "pooled",
5517
+ "unknown"
5518
+ ]),
5519
+ used: amount$1.optional(),
5520
+ remaining: amount$1.optional(),
5521
+ limit: amount$1.positive().optional(),
5522
+ percentUsed: number().finite().min(0).max(100).optional(),
5523
+ resetAt: timestamp.optional(),
5524
+ observedAt: timestamp.optional(),
5525
+ diagnostic: _enum(COPILOT_USAGE_DIAGNOSTICS).optional()
5526
+ }).strict().superRefine((view, ctx) => {
5527
+ const invalid = () => ctx.addIssue({
5528
+ code: "custom",
5529
+ message: "Invalid account quota snapshot"
5530
+ });
5531
+ const hasAmounts = [
5532
+ view.used,
5533
+ view.remaining,
5534
+ view.limit,
5535
+ view.percentUsed
5536
+ ].some((value) => value !== void 0);
5537
+ if (view.state === "unavailable" || view.state === "signed-out") {
5538
+ if (hasAmounts || view.observedAt !== void 0 || view.resetAt !== void 0 || view.diagnostic === void 0) invalid();
5539
+ if (view.state === "signed-out" && (view.billing !== "unknown" || view.budget !== "unknown")) invalid();
5540
+ return;
5541
+ }
5542
+ if (!hasAmounts || view.observedAt === void 0 || view.billing === "unknown" || view.budget === "unknown") invalid();
5543
+ if (view.state === "stale" && view.diagnostic === void 0) invalid();
5544
+ if (view.state === "ready" && view.diagnostic !== void 0) invalid();
5545
+ if (view.budget === "pooled" && (view.billing !== "credits" || view.used === void 0 || view.remaining !== void 0 || view.limit !== void 0 || view.percentUsed !== void 0)) invalid();
5546
+ if (view.limit !== void 0) {
5547
+ if (view.used !== void 0 && view.used > view.limit || view.remaining !== void 0 && view.remaining > view.limit) invalid();
5548
+ if (view.used !== void 0 && view.remaining !== void 0 && Math.abs(view.used + view.remaining - view.limit) > Math.max(1e-8, view.limit * 1e-12)) invalid();
5549
+ if (view.remaining !== void 0 && view.percentUsed !== void 0 && Math.abs((1 - view.remaining / view.limit) * 100 - view.percentUsed) > 1) invalid();
5550
+ }
5551
+ });
5552
+ const contribution$1 = {
5553
+ package: "dsh-github-copilot",
5554
+ descriptors: ["get", "refresh"].map((method) => ({
5555
+ id: `dsh-github-copilot:githubCopilotUsage.${method}`,
5556
+ namespace: "githubCopilotUsage",
5557
+ service: "githubCopilotUsage",
5558
+ method,
5559
+ invocation: { kind: "direct" },
5560
+ parameters: [],
5561
+ result: strictRemoteCodec("dsh-github-copilot#CopilotUsageView", CopilotUsageViewSchema)
5562
+ }))
5563
+ };
5564
+ //#endregion
5474
5565
  //#region lib/types/remote.js
5475
5566
  /**
5476
5567
  * Client-safe Remote contribution for the plugin-owned authorization bridge.
@@ -5623,6 +5714,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5623
5714
  parameters: [],
5624
5715
  result: strictRemoteCodec(GITHUB_COPILOT_MIGRATION_STATUS_TYPE_SYMBOL, GitHubCopilotMigrationStatusSchema)
5625
5716
  },
5717
+ ...contribution$3.descriptors,
5626
5718
  ...contribution$2.descriptors,
5627
5719
  ...contribution$1.descriptors
5628
5720
  ]
@@ -5634,15 +5726,15 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5634
5726
  const ASSISTANT_ORIGIN_KEY = "github-copilot-assistant-origin";
5635
5727
  const CHAT_NODE_SLOT = "conversation.chat.node";
5636
5728
  const ASSISTANT_KEY = "assistant-step";
5637
- const noop = () => {};
5638
- function record$1(value) {
5729
+ const noop$1 = () => {};
5730
+ function record$2(value) {
5639
5731
  return typeof value === "object" && value !== null;
5640
5732
  }
5641
5733
  function sequence(value) {
5642
5734
  return typeof value === "number" && Number.isSafeInteger(value) && value >= 0;
5643
5735
  }
5644
5736
  function eventLocation(event) {
5645
- if (!record$1(event) || !record$1(event.data)) return void 0;
5737
+ if (!record$2(event) || !record$2(event.data)) return void 0;
5646
5738
  const { turn, step } = event.data;
5647
5739
  return sequence(turn) && sequence(step) ? {
5648
5740
  turn,
@@ -5650,9 +5742,9 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5650
5742
  } : void 0;
5651
5743
  }
5652
5744
  function messageOrigin(event) {
5653
- if (!record$1(event) || event.type !== "assistant/message" || event.surfaceOp !== "append" || !sequence(event.seq) || !record$1(event.data) || !record$1(event.data.message)) return void 0;
5745
+ if (!record$2(event) || event.type !== "assistant/message" || event.surfaceOp !== "append" || !sequence(event.seq) || !record$2(event.data) || !record$2(event.data.message)) return void 0;
5654
5746
  const source = event.data.message.source;
5655
- if (!record$1(source) || typeof source.provider !== "string" || source.provider.trim() === "" || typeof source.model !== "string" || source.model.trim() === "") return void 0;
5747
+ if (!record$2(source) || typeof source.provider !== "string" || source.provider.trim() === "" || typeof source.model !== "string" || source.model.trim() === "") return void 0;
5656
5748
  return {
5657
5749
  seq: event.seq,
5658
5750
  provider: source.provider,
@@ -5663,7 +5755,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5663
5755
  const assistantOriginDefinition = {
5664
5756
  kind: ASSISTANT_ORIGIN_KEY,
5665
5757
  match(event) {
5666
- if (!record$1(event)) return null;
5758
+ if (!record$2(event)) return null;
5667
5759
  const location = eventLocation(event);
5668
5760
  if (location === void 0) return null;
5669
5761
  if (event.type === "step/start") return {
@@ -5678,14 +5770,14 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5678
5770
  },
5679
5771
  start(_context, match) {
5680
5772
  const location = eventLocation(match.event);
5681
- if (location === void 0 || !record$1(match.event) || match.event.type !== "step/start") throw new Error("COPILOT_REASONING_ORIGIN_START: expected step/start");
5773
+ if (location === void 0 || !record$2(match.event) || match.event.type !== "step/start") throw new Error("COPILOT_REASONING_ORIGIN_START: expected step/start");
5682
5774
  return {
5683
5775
  ...location,
5684
5776
  origin: void 0
5685
5777
  };
5686
5778
  },
5687
5779
  update(context, match) {
5688
- if (!record$1(match.event) || match.event.type !== "assistant/message" || match.event.surfaceOp !== "append") return context.state;
5780
+ if (!record$2(match.event) || match.event.type !== "assistant/message" || match.event.surfaceOp !== "append") return context.state;
5689
5781
  return {
5690
5782
  ...context.state,
5691
5783
  origin: messageOrigin(match.event)
@@ -5696,7 +5788,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5696
5788
  let state = context.state;
5697
5789
  if (state === void 0) for (const match of context.matches) {
5698
5790
  const event = match.event;
5699
- if (!record$1(event) || event.type !== "assistant/message" || event.surfaceOp !== "append") continue;
5791
+ if (!record$2(event) || event.type !== "assistant/message" || event.surfaceOp !== "append") continue;
5700
5792
  const location = eventLocation(event);
5701
5793
  if (location !== void 0) state = {
5702
5794
  ...location,
@@ -5717,12 +5809,12 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5717
5809
  };
5718
5810
  /** Shallow UI-only projection. Unchanged input retains its exact props identity. */
5719
5811
  function projectReasoningPresentation(props, origin) {
5720
- if (!record$1(props) || !record$1(props.node) || props.node.kind !== ASSISTANT_KEY || !record$1(props.node.data) || !record$1(origin)) return props;
5812
+ if (!record$2(props) || !record$2(props.node) || props.node.kind !== ASSISTANT_KEY || !record$2(props.node.data) || !record$2(origin)) return props;
5721
5813
  const node = props.node;
5722
5814
  const data = node.data;
5723
- if (data.status !== "settled" || !record$1(data.finalNode) || !sequence(data.finalNode.seq) || origin.seq !== data.finalNode.seq) return props;
5815
+ if (data.status !== "settled" || !record$2(data.finalNode) || !sequence(data.finalNode.seq) || origin.seq !== data.finalNode.seq) return props;
5724
5816
  if (!(origin.provider === "github-copilot" || origin.provider === "github-copilot-preview") || typeof origin.model !== "string" || origin.model.trim() === "" || !Array.isArray(data.blocks)) return props;
5725
- const blocks = data.blocks.filter((block) => !(record$1(block) && block.kind === "reasoning" && typeof block.text === "string" && block.text.trim() === ""));
5817
+ const blocks = data.blocks.filter((block) => !(record$2(block) && block.kind === "reasoning" && typeof block.text === "string" && block.text.trim() === ""));
5726
5818
  if (blocks.length === data.blocks.length) return props;
5727
5819
  return {
5728
5820
  ...props,
@@ -5737,16 +5829,16 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5737
5829
  }
5738
5830
  const missingOriginSource = {
5739
5831
  getSnapshot: () => void 0,
5740
- subscribe: () => noop
5832
+ subscribe: () => noop$1
5741
5833
  };
5742
5834
  function originSource(props) {
5743
5835
  const node = props.node;
5744
- if (!record$1(node) || !record$1(node.location) || node.location.kind !== "step" || !record$1(node.location.step) || !record$1(node.location.step.data)) return missingOriginSource;
5836
+ if (!record$2(node) || !record$2(node.location) || node.location.kind !== "step" || !record$2(node.location.step) || !record$2(node.location.step.data)) return missingOriginSource;
5745
5837
  const store = node.location.step.data;
5746
5838
  if (typeof store.source !== "function") return missingOriginSource;
5747
5839
  try {
5748
5840
  const source = store.source(ASSISTANT_ORIGIN_KEY);
5749
- if (!record$1(source) || typeof source.getSnapshot !== "function" || typeof source.subscribe !== "function") return missingOriginSource;
5841
+ if (!record$2(source) || typeof source.getSnapshot !== "function" || typeof source.subscribe !== "function") return missingOriginSource;
5750
5842
  return source;
5751
5843
  } catch {
5752
5844
  return missingOriginSource;
@@ -5760,7 +5852,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5760
5852
  */
5761
5853
  function supportedNative(entry) {
5762
5854
  const component = entry.component;
5763
- return (entry.options.priority ?? 0) === 0 && entry.locale === "chat" && entry.options.id === void 0 && entry.options.order === void 0 && entry.options.label === void 0 && entry.inject === void 0 && entry.store === void 0 && entry.children === void 0 && entry.select === void 0 && record$1(component) && component.$$typeof === Symbol.for("react.memo") && typeof component.type === "function" && component.type.name === "AssistantNodeView";
5855
+ return (entry.options.priority ?? 0) === 0 && entry.locale === "chat" && entry.options.id === void 0 && entry.options.order === void 0 && entry.options.label === void 0 && entry.inject === void 0 && entry.store === void 0 && entry.children === void 0 && entry.select === void 0 && record$2(component) && component.$$typeof === Symbol.for("react.memo") && typeof component.type === "function" && component.type.name === "AssistantNodeView";
5764
5856
  }
5765
5857
  /**
5766
5858
  * Optional Client enhancement. The caller owns the returned disposer in its
@@ -5770,20 +5862,20 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5770
5862
  const { diagnostic } = capabilities;
5771
5863
  const slotsCandidate = capabilities.slots;
5772
5864
  const conversation = capabilities.uiConversation;
5773
- if (!record$1(slotsCandidate) || ![
5865
+ if (!record$2(slotsCandidate) || ![
5774
5866
  "entries",
5775
5867
  "spec",
5776
5868
  "subscribe",
5777
5869
  "inject",
5778
5870
  "register"
5779
- ].every((key) => typeof slotsCandidate[key] === "function") || !record$1(conversation) || !record$1(conversation.events) || typeof conversation.events.register !== "function") {
5871
+ ].every((key) => typeof slotsCandidate[key] === "function") || !record$2(conversation) || !record$2(conversation.events) || typeof conversation.events.register !== "function") {
5780
5872
  diagnostic("COPILOT_REASONING_PRESENTATION_UNAVAILABLE");
5781
- return noop;
5873
+ return noop$1;
5782
5874
  }
5783
5875
  const slots = slotsCandidate;
5784
5876
  const events = conversation.events;
5785
- let removeOrigin = noop;
5786
- let removeInjection = noop;
5877
+ let removeOrigin = noop$1;
5878
+ let removeInjection = noop$1;
5787
5879
  let disposed = false;
5788
5880
  try {
5789
5881
  removeOrigin = events.register(assistantOriginDefinition);
@@ -5791,7 +5883,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5791
5883
  const spec = slots.spec(CHAT_NODE_SLOT);
5792
5884
  if (spec?.kind !== "keyed" || spec.scope !== "session") {
5793
5885
  diagnostic("COPILOT_REASONING_SLOT_UNSUPPORTED");
5794
- return noop;
5886
+ return noop$1;
5795
5887
  }
5796
5888
  let active = true;
5797
5889
  let reconciling = false;
@@ -5799,7 +5891,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5799
5891
  let native;
5800
5892
  let failedNative;
5801
5893
  let wrapper;
5802
- let unregister = noop;
5894
+ let unregister = noop$1;
5803
5895
  let lastDiagnostic;
5804
5896
  const report = (code) => {
5805
5897
  if (lastDiagnostic !== code) diagnostic(code);
@@ -5807,7 +5899,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5807
5899
  };
5808
5900
  const retire = () => {
5809
5901
  const remove = unregister;
5810
- unregister = noop;
5902
+ unregister = noop$1;
5811
5903
  native = void 0;
5812
5904
  remove();
5813
5905
  wrapper = void 0;
@@ -5869,7 +5961,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5869
5961
  removeInjection();
5870
5962
  removeOrigin();
5871
5963
  diagnostic("COPILOT_REASONING_REGISTRATION_FAILED");
5872
- return noop;
5964
+ return noop$1;
5873
5965
  }
5874
5966
  return () => {
5875
5967
  if (disposed) return;
@@ -5958,7 +6050,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5958
6050
  overflowWrap: "anywhere",
5959
6051
  margin: 0
5960
6052
  };
5961
- function record(value) {
6053
+ function record$1(value) {
5962
6054
  return typeof value === "object" && value !== null && !Array.isArray(value) ? value : {};
5963
6055
  }
5964
6056
  function revisionOf(value) {
@@ -5968,7 +6060,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5968
6060
  return id === GITHUB_COPILOT_SEARCH_PROVIDER ? "GitHub Copilot" : id === DEEPSEEK_SEARCH_PROVIDER ? "DeepSeek" : id;
5969
6061
  }
5970
6062
  function saveFailure(error) {
5971
- const code = record(error).code;
6063
+ const code = record$1(error).code;
5972
6064
  if (code === "settings-conflict") return "Search settings changed since you opened this page. Reload settings, then review and save your choices again.";
5973
6065
  if (code === "settings-rejected") return "The settings service rejected this change. Reload settings to check whether editing is available, then try again.";
5974
6066
  return "Could not confirm the save. Reload settings to check saved values before retrying. Your current choices have been kept.";
@@ -6013,7 +6105,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6013
6105
  }
6014
6106
  const routing = result.value.namespaces.find((entry) => entry.ns === WEB_SEARCH_ROUTING_SETTINGS_NAMESPACE);
6015
6107
  const copilot = result.value.namespaces.find((entry) => entry.ns === GITHUB_COPILOT_SETTINGS_NAMESPACE);
6016
- const routingValue = record(routing?.value), copilotValue = record(copilot?.value);
6108
+ const routingValue = record$1(routing?.value), copilotValue = record$1(copilot?.value);
6017
6109
  const normalized = normalizeWebSearchRouting({
6018
6110
  searchProvider: typeof routingValue.searchProvider === "string" ? routingValue.searchProvider : void 0,
6019
6111
  searchMode: routingValue.searchMode === "fixed" ? "fixed" : "auto",
@@ -6284,7 +6376,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6284
6376
  plannerModel: "",
6285
6377
  executorModel: ""
6286
6378
  };
6287
- const copy = {
6379
+ const copy$1 = {
6288
6380
  en: {
6289
6381
  title: "Model roles",
6290
6382
  description: "The planning model plans and reviews acceptance. The execution model changes code and runs tests.",
@@ -6449,7 +6541,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6449
6541
  });
6450
6542
  /** Additive Models settings card. All mutations belong to the injected scoped Remote. */
6451
6543
  function DualModelCard(props) {
6452
- const t = props.locale?.toLowerCase().startsWith("zh") ? copy.zh : copy.en;
6544
+ const t = props.locale?.toLowerCase().startsWith("zh") ? copy$1.zh : copy$1.en;
6453
6545
  const id = (0, react.useId)();
6454
6546
  const [view, setView] = (0, react.useState)();
6455
6547
  const [draft, setDraft] = (0, react.useState)(off);
@@ -6771,6 +6863,406 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6771
6863
  }, status));
6772
6864
  }
6773
6865
  //#endregion
6866
+ //#region lib/types/external-link.js
6867
+ /** Use Desktop's public v1 navigation handoff instead of WebView popup creation. */
6868
+ function externalLinkTarget() {
6869
+ if (typeof window !== "undefined" && "dshDesktop" in window) {
6870
+ const desktop = window.dshDesktop;
6871
+ if (typeof desktop === "object" && desktop !== null && "protocolVersion" in desktop && desktop.protocolVersion === 1) return "_self";
6872
+ }
6873
+ return "_blank";
6874
+ }
6875
+ //#endregion
6876
+ //#region lib/types/copilot-usage-card.js
6877
+ const copy = {
6878
+ en: {
6879
+ credits: "Credits",
6880
+ requests: "Premium requests",
6881
+ unknown: "Copilot usage",
6882
+ title: "Copilot credits",
6883
+ account: "Account-wide · across Copilot apps",
6884
+ used: "used",
6885
+ left: "left",
6886
+ usedLabel: "Used this cycle",
6887
+ remaining: "Remaining",
6888
+ unavailable: "Not available",
6889
+ loading: "Loading…",
6890
+ stale: "Last known",
6891
+ individual: "Cycle budget",
6892
+ pooled: "Shared budget · no personal balance available",
6893
+ budgetUnknown: "Budget unavailable",
6894
+ session: "This session",
6895
+ sessionExplanation: "The native adapter does not expose per-session billing usage. Token counts are not billing amounts.",
6896
+ close: "Close usage details",
6897
+ refresh: "Refresh",
6898
+ refreshing: "Refreshing…",
6899
+ error: "Could not refresh usage. Try again.",
6900
+ unavailableExplanation: "Account usage is currently unavailable.",
6901
+ signedOut: "Sign in to Copilot in Models to view account usage.",
6902
+ lastUpdated: "Last updated",
6903
+ reset: "Resets",
6904
+ progress: "Cycle budget used",
6905
+ plan: "View usage and plan",
6906
+ manual: "If the browser does not open, copy this address:",
6907
+ rounding: "Amounts rounded for display. GitHub billing is authoritative.",
6908
+ low: "Low remaining budget",
6909
+ missing: "COPILOT_USAGE_REMOTE_UNAVAILABLE · Account usage is unavailable in this deployment."
6910
+ },
6911
+ zh: {
6912
+ credits: "额度",
6913
+ requests: "高级请求",
6914
+ unknown: "Copilot 用量",
6915
+ title: "Copilot 额度",
6916
+ account: "账号范围 · 所有 Copilot 应用",
6917
+ used: "已用",
6918
+ left: "剩余",
6919
+ usedLabel: "本周期已用",
6920
+ remaining: "剩余",
6921
+ unavailable: "暂不可用",
6922
+ loading: "正在加载…",
6923
+ stale: "上次已知数据",
6924
+ individual: "周期额度",
6925
+ pooled: "共享额度 · 无个人余额信息",
6926
+ budgetUnknown: "额度上限暂不可用",
6927
+ session: "本会话",
6928
+ sessionExplanation: "原生适配器未提供单个会话的计费用量。Token 数量不等于计费额度。",
6929
+ close: "关闭用量详情",
6930
+ refresh: "刷新",
6931
+ refreshing: "正在刷新…",
6932
+ error: "无法刷新用量,请重试。",
6933
+ unavailableExplanation: "当前无法获取账号用量。",
6934
+ signedOut: "请在模型设置中登录 Copilot,以查看账号用量。",
6935
+ lastUpdated: "更新于",
6936
+ reset: "重置时间",
6937
+ progress: "本周期已用比例",
6938
+ plan: "查看用量与套餐",
6939
+ manual: "若浏览器未打开,请复制此地址:",
6940
+ rounding: "显示数值经过四舍五入,账单以 GitHub 为准。",
6941
+ low: "剩余额度较低",
6942
+ missing: "COPILOT_USAGE_REMOTE_UNAVAILABLE · 当前部署无法提供账号用量。"
6943
+ }
6944
+ };
6945
+ const secondary = "var(--dsw-alias-label-secondary, GrayText)";
6946
+ const border = "1px solid var(--dsw-alias-border-main, color-mix(in srgb, currentColor 20%, transparent))";
6947
+ const button = {
6948
+ font: "inherit",
6949
+ color: "inherit",
6950
+ cursor: "pointer",
6951
+ border,
6952
+ borderRadius: 8,
6953
+ background: "var(--dsw-alias-bg-layer-1, Canvas)",
6954
+ padding: "5px 9px"
6955
+ };
6956
+ const muted = {
6957
+ color: secondary,
6958
+ fontSize: 12,
6959
+ lineHeight: 1.5,
6960
+ margin: 0
6961
+ };
6962
+ const row = {
6963
+ display: "flex",
6964
+ justifyContent: "space-between",
6965
+ alignItems: "center",
6966
+ gap: 12
6967
+ };
6968
+ const separator = {
6969
+ borderTop: border,
6970
+ paddingTop: 12
6971
+ };
6972
+ function amount(value) {
6973
+ return typeof value === "number" && Number.isFinite(value) && value >= 0;
6974
+ }
6975
+ function dateLabel(value, locale) {
6976
+ if (!amount(value)) return void 0;
6977
+ const date = new Date(value);
6978
+ if (!Number.isFinite(date.getTime())) return void 0;
6979
+ return date.toLocaleString(locale);
6980
+ }
6981
+ /** Mounted only for a proven effective Copilot selection in the owning Session. */
6982
+ function CopilotUsageCard(props) {
6983
+ const language = props.locale?.toLowerCase().startsWith("zh") ? "zh-CN" : "en-US";
6984
+ const t = language === "zh-CN" ? copy.zh : copy.en;
6985
+ const id = (0, react.useId)();
6986
+ const [view, setView] = (0, react.useState)();
6987
+ const [busy, setBusy] = (0, react.useState)(false);
6988
+ const [failed, setFailed] = (0, react.useState)(false);
6989
+ const [open, setOpen] = (0, react.useState)(false);
6990
+ const [position, setPosition] = (0, react.useState)({
6991
+ left: 12,
6992
+ bottom: 12
6993
+ });
6994
+ const trigger = (0, react.useRef)(null);
6995
+ const panel = (0, react.useRef)(null);
6996
+ const closeButton = (0, react.useRef)(null);
6997
+ const lifecycle = (0, react.useRef)({
6998
+ active: false,
6999
+ generation: 0,
7000
+ busy: false
7001
+ });
7002
+ const close = (0, react.useCallback)((restore = false) => {
7003
+ setOpen(false);
7004
+ if (restore) trigger.current?.focus();
7005
+ }, []);
7006
+ const load = (0, react.useCallback)(async (force) => {
7007
+ const owner = lifecycle.current;
7008
+ if (!owner.active || owner.busy || props.remote === void 0 || document.visibilityState === "hidden") return;
7009
+ owner.busy = true;
7010
+ const generation = ++owner.generation;
7011
+ const current = () => owner.active && owner.generation === generation;
7012
+ setBusy(true);
7013
+ setFailed(false);
7014
+ try {
7015
+ const result = await (force ? props.remote.refresh() : props.remote.get());
7016
+ if (!current()) return;
7017
+ const parsed = result.ok ? CopilotUsageViewSchema.safeParse(result.value) : void 0;
7018
+ if (parsed?.success !== true) {
7019
+ setView(void 0);
7020
+ setFailed(true);
7021
+ } else setView(parsed.data);
7022
+ } catch {
7023
+ if (current()) {
7024
+ setView(void 0);
7025
+ setFailed(true);
7026
+ }
7027
+ } finally {
7028
+ if (current()) {
7029
+ owner.busy = false;
7030
+ setBusy(false);
7031
+ }
7032
+ }
7033
+ }, [props.remote, props.contextKey]);
7034
+ (0, react.useEffect)(() => {
7035
+ const owner = lifecycle.current;
7036
+ owner.active = true;
7037
+ setView(void 0);
7038
+ setFailed(false);
7039
+ setBusy(false);
7040
+ setOpen(false);
7041
+ load(false);
7042
+ const timer = props.remote === void 0 ? void 0 : window.setInterval(() => {
7043
+ load(false);
7044
+ }, 6e4);
7045
+ const visible = () => {
7046
+ if (document.visibilityState === "visible") load(false);
7047
+ };
7048
+ document.addEventListener("visibilitychange", visible);
7049
+ return () => {
7050
+ owner.active = false;
7051
+ owner.generation++;
7052
+ owner.busy = false;
7053
+ if (timer !== void 0) window.clearInterval(timer);
7054
+ document.removeEventListener("visibilitychange", visible);
7055
+ };
7056
+ }, [load, props.remote]);
7057
+ (0, react.useLayoutEffect)(() => {
7058
+ if (!open) return;
7059
+ panel.current?.showPopover?.();
7060
+ const place = () => {
7061
+ const anchor = trigger.current?.getBoundingClientRect();
7062
+ if (!anchor) return;
7063
+ const width = panel.current?.getBoundingClientRect().width || 336;
7064
+ setPosition({
7065
+ left: Math.max(12, Math.min(anchor.right - width, window.innerWidth - width - 12)),
7066
+ bottom: Math.max(12, Math.min(window.innerHeight - anchor.top + 8, window.innerHeight - 40))
7067
+ });
7068
+ };
7069
+ place();
7070
+ closeButton.current?.focus();
7071
+ window.addEventListener("resize", place);
7072
+ window.addEventListener("scroll", place, true);
7073
+ return () => {
7074
+ window.removeEventListener("resize", place);
7075
+ window.removeEventListener("scroll", place, true);
7076
+ };
7077
+ }, [open]);
7078
+ (0, react.useEffect)(() => {
7079
+ if (!open) return;
7080
+ const outside = (event) => {
7081
+ const target = event.target;
7082
+ if (target instanceof Node && !panel.current?.contains(target) && !trigger.current?.contains(target)) close();
7083
+ };
7084
+ const key = (event) => {
7085
+ if (event.key === "Escape") {
7086
+ event.preventDefault();
7087
+ close(true);
7088
+ }
7089
+ if (event.key === "Tab" && panel.current?.contains(document.activeElement)) {
7090
+ const buttons = Array.from(panel.current.querySelectorAll("button:not(:disabled),a[href],summary"));
7091
+ const target = event.shiftKey ? buttons.at(-1) : buttons[0];
7092
+ const edge = event.shiftKey ? buttons[0] : buttons.at(-1);
7093
+ if (document.activeElement === edge) {
7094
+ event.preventDefault();
7095
+ target?.focus();
7096
+ }
7097
+ }
7098
+ };
7099
+ document.addEventListener("pointerdown", outside);
7100
+ document.addEventListener("keydown", key);
7101
+ return () => {
7102
+ document.removeEventListener("pointerdown", outside);
7103
+ document.removeEventListener("keydown", key);
7104
+ };
7105
+ }, [open, close]);
7106
+ const available = view?.state === "ready" || view?.state === "stale";
7107
+ const knownUnits = view?.billing === "credits" || view?.billing === "requests";
7108
+ const numbers = available && knownUnits;
7109
+ const used = numbers && amount(view.used) ? view.used : void 0;
7110
+ const remaining = numbers && view.budget !== "pooled" && amount(view.remaining) ? view.remaining : void 0;
7111
+ const limit = numbers && view.budget === "individual" && amount(view.limit) ? view.limit : void 0;
7112
+ const percent = numbers && view.budget === "individual" && amount(view.percentUsed) ? view.percentUsed : void 0;
7113
+ const unit = view?.billing === "credits" ? t.credits : view?.billing === "requests" ? t.requests : t.unknown;
7114
+ const format = (value) => value === void 0 ? t.unavailable : value > 0 && value < .01 ? "<0.01" : new Intl.NumberFormat(language, { maximumFractionDigits: 2 }).format(value);
7115
+ const compact = (value) => value > 0 && value < .01 ? "<0.01" : new Intl.NumberFormat(language, {
7116
+ notation: "compact",
7117
+ maximumFractionDigits: 2
7118
+ }).format(value);
7119
+ const reading = [
7120
+ unit,
7121
+ ...view?.state === "stale" ? [t.stale] : [],
7122
+ used === void 0 ? void 0 : `${compact(used)} ${t.used}`,
7123
+ remaining === void 0 ? void 0 : `${compact(remaining)} ${t.left}`
7124
+ ].filter(Boolean).join(" · ");
7125
+ const noAmount = used === void 0 && remaining === void 0;
7126
+ const observed = available ? dateLabel(view.observedAt, language) : void 0;
7127
+ const reset = available ? dateLabel(view.resetAt, language) : void 0;
7128
+ return (0, react.createElement)("span", { style: {
7129
+ display: "inline-flex",
7130
+ minWidth: 0,
7131
+ maxWidth: "100%",
7132
+ fontFamily: "var(--dsw-font-family, inherit)"
7133
+ } }, (0, react.createElement)("button", {
7134
+ ref: trigger,
7135
+ type: "button",
7136
+ "data-copilot-usage-trigger": "",
7137
+ "aria-haspopup": "dialog",
7138
+ "aria-expanded": open,
7139
+ "aria-controls": open ? id : void 0,
7140
+ onClick: () => {
7141
+ setOpen((value) => !value);
7142
+ },
7143
+ style: {
7144
+ ...button,
7145
+ border: "none",
7146
+ background: "transparent",
7147
+ borderRadius: 16,
7148
+ padding: "3px 5px",
7149
+ fontSize: 11,
7150
+ minWidth: 0,
7151
+ lineHeight: 1.5,
7152
+ textAlign: "center",
7153
+ overflowWrap: "anywhere",
7154
+ color: secondary,
7155
+ fontVariantNumeric: "tabular-nums"
7156
+ }
7157
+ }, `${reading}${noAmount ? ` · ${busy ? t.loading : t.unavailable}` : ""}`), open ? (0, react.createElement)("div", {
7158
+ id,
7159
+ ref: panel,
7160
+ role: "dialog",
7161
+ "aria-labelledby": `${id}-title`,
7162
+ "aria-describedby": `${id}-scope`,
7163
+ popover: "manual",
7164
+ style: {
7165
+ position: "fixed",
7166
+ inset: "auto",
7167
+ margin: 0,
7168
+ ...position,
7169
+ width: 336,
7170
+ maxWidth: "calc(100vw - 24px)",
7171
+ maxHeight: `calc(100vh - ${position.bottom + 12}px)`,
7172
+ overflowY: "auto",
7173
+ boxSizing: "border-box",
7174
+ zIndex: 1e3,
7175
+ padding: 16,
7176
+ display: "grid",
7177
+ gap: 14,
7178
+ border,
7179
+ borderRadius: 14,
7180
+ color: "var(--dsw-alias-label-primary, CanvasText)",
7181
+ background: "var(--dsw-specific-menu, Canvas)",
7182
+ fontFamily: "var(--dsw-font-family, inherit)",
7183
+ fontSize: 13,
7184
+ boxShadow: "0 8px 32px color-mix(in srgb, CanvasText 16%, transparent)",
7185
+ overflowWrap: "anywhere"
7186
+ }
7187
+ }, (0, react.createElement)("div", { style: row }, (0, react.createElement)("div", null, (0, react.createElement)("strong", { id: `${id}-title` }, view?.billing === "credits" ? t.title : unit), (0, react.createElement)("p", {
7188
+ id: `${id}-scope`,
7189
+ style: muted
7190
+ }, t.account)), (0, react.createElement)("button", {
7191
+ ref: closeButton,
7192
+ type: "button",
7193
+ "aria-label": t.close,
7194
+ style: button,
7195
+ onClick: () => {
7196
+ close(true);
7197
+ }
7198
+ }, "×")), view?.state === "stale" ? (0, react.createElement)("p", {
7199
+ role: "status",
7200
+ style: muted
7201
+ }, t.stale) : null, view?.diagnostic === void 0 ? null : (0, react.createElement)("code", { style: muted }, view.diagnostic), props.remote === void 0 ? (0, react.createElement)("p", {
7202
+ role: "status",
7203
+ style: muted
7204
+ }, t.missing) : null, failed ? (0, react.createElement)("p", {
7205
+ role: "alert",
7206
+ style: muted
7207
+ }, t.error) : null, view?.state === "signed-out" ? (0, react.createElement)("p", { style: muted }, t.signedOut) : !available && !busy && props.remote !== void 0 ? (0, react.createElement)("p", { style: muted }, t.unavailableExplanation) : null, (0, react.createElement)("div", { style: {
7208
+ display: "grid",
7209
+ gridTemplateColumns: "minmax(0, 1fr) minmax(0, 1fr)",
7210
+ gap: 12
7211
+ } }, (0, react.createElement)("div", null, (0, react.createElement)("p", { style: muted }, t.usedLabel), (0, react.createElement)("strong", { style: {
7212
+ fontSize: 22,
7213
+ fontVariantNumeric: "tabular-nums"
7214
+ } }, format(used)), (0, react.createElement)("p", { style: muted }, unit)), (0, react.createElement)("div", null, (0, react.createElement)("p", { style: muted }, t.remaining), (0, react.createElement)("strong", { style: {
7215
+ fontSize: 22,
7216
+ fontVariantNumeric: "tabular-nums"
7217
+ } }, format(remaining)), (0, react.createElement)("p", { style: muted }, unit))), percent === void 0 ? null : (0, react.createElement)("div", {
7218
+ role: "progressbar",
7219
+ "aria-label": t.progress,
7220
+ "aria-valuemin": 0,
7221
+ "aria-valuemax": 100,
7222
+ "aria-valuenow": percent,
7223
+ style: {
7224
+ height: 5,
7225
+ background: "var(--dsw-alias-bg-layer-2, ButtonFace)",
7226
+ borderRadius: 8,
7227
+ overflow: "hidden"
7228
+ }
7229
+ }, (0, react.createElement)("div", { style: {
7230
+ height: "100%",
7231
+ width: `${percent}%`,
7232
+ background: percent >= 90 ? "#d9a441" : "var(--dsw-alias-label-primary, CanvasText)"
7233
+ } })), view?.state === "ready" && percent !== void 0 && percent >= 90 ? (0, react.createElement)("p", {
7234
+ role: "status",
7235
+ style: muted
7236
+ }, t.low) : null, (0, react.createElement)("p", { style: muted }, available && view.budget === "pooled" ? t.pooled : limit === void 0 ? t.budgetUnknown : `${t.individual}: ${format(limit)} ${unit}`), numbers ? (0, react.createElement)("p", { style: muted }, t.rounding) : null, reset === void 0 ? null : (0, react.createElement)("p", { style: muted }, `${t.reset}: ${reset}`), (0, react.createElement)("div", { style: separator }, (0, react.createElement)("div", { style: row }, (0, react.createElement)("strong", null, t.session), (0, react.createElement)("span", null, t.unavailable)), (0, react.createElement)("p", { style: {
7237
+ ...muted,
7238
+ marginTop: 4
7239
+ } }, t.sessionExplanation)), (0, react.createElement)("div", { style: {
7240
+ ...row,
7241
+ ...separator
7242
+ } }, (0, react.createElement)("span", { style: muted }, observed === void 0 ? null : `${t.lastUpdated}: ${observed}`), (0, react.createElement)("button", {
7243
+ type: "button",
7244
+ style: {
7245
+ ...button,
7246
+ flexShrink: 0
7247
+ },
7248
+ disabled: busy || props.remote === void 0,
7249
+ onClick: () => {
7250
+ load(true);
7251
+ }
7252
+ }, busy ? t.refreshing : t.refresh)), (0, react.createElement)("a", {
7253
+ href: "https://github.com/settings/copilot",
7254
+ target: externalLinkTarget(),
7255
+ rel: "noreferrer",
7256
+ style: {
7257
+ color: "inherit",
7258
+ fontSize: 12
7259
+ }
7260
+ }, t.plan), (0, react.createElement)("details", { style: muted }, (0, react.createElement)("summary", { style: { cursor: "pointer" } }, t.manual), (0, react.createElement)("code", { style: {
7261
+ userSelect: "all",
7262
+ overflowWrap: "anywhere"
7263
+ } }, "https://github.com/settings/copilot"))) : null);
7264
+ }
7265
+ //#endregion
6774
7266
  //#region lib/types/current-workspace.js
6775
7267
  const object = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
6776
7268
  function listOf(value) {
@@ -6864,11 +7356,11 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6864
7356
  }
6865
7357
  //#endregion
6866
7358
  //#region lib/types/dual-model-ui.js
6867
- const emptySubscribe = () => () => {};
7359
+ const emptySubscribe$1 = () => () => {};
6868
7360
  function DualModelSurface({ ctx, remote, workspaceSource, close }) {
6869
7361
  const locale = ctx.get("locale");
6870
7362
  const navigation = ctx.get("uiWorkspace");
6871
- const language = (0, react.useSyncExternalStore)(locale === void 0 ? emptySubscribe : (listener) => locale.subscribe(listener), () => locale?.getLocale().active ?? "en", () => "en");
7363
+ const language = (0, react.useSyncExternalStore)(locale === void 0 ? emptySubscribe$1 : (listener) => locale.subscribe(listener), () => locale?.getLocale().active ?? "en", () => "en");
6872
7364
  const currentWorkspaceId = (0, react.useSyncExternalStore)(workspaceSource.subscribe, workspaceSource.getSnapshot, () => void 0);
6873
7365
  return (0, react.createElement)(DualModelCard, {
6874
7366
  remote,
@@ -6955,6 +7447,141 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6955
7447
  };
6956
7448
  }
6957
7449
  //#endregion
7450
+ //#region lib/types/copilot-usage-ui.js
7451
+ const slot = "conversation.composer.dock";
7452
+ const noop = () => {};
7453
+ const emptySubscribe = () => noop;
7454
+ function record(value) {
7455
+ return typeof value === "object" && value !== null;
7456
+ }
7457
+ function isSlots(value) {
7458
+ return record(value) && typeof value.spec === "function" && typeof value.inject === "function" && typeof value.register === "function";
7459
+ }
7460
+ function isRemote(value) {
7461
+ return record(value) && typeof value.get === "function" && typeof value.refresh === "function";
7462
+ }
7463
+ function isLocale(value) {
7464
+ return record(value) && typeof value.getLocale === "function" && typeof value.subscribe === "function";
7465
+ }
7466
+ function isRuntime(value) {
7467
+ return record(value) && typeof value.sessionId === "string" && value.sessionId !== "" && typeof value.useSession === "function" && typeof value.useProjection === "function";
7468
+ }
7469
+ function selection(value) {
7470
+ return record(value) && typeof value.provider === "string" && value.provider.trim() !== "" && typeof value.model === "string" && value.model.trim() !== "";
7471
+ }
7472
+ /**
7473
+ * Verified alpha.2 wire projection: next = pending ?? lastUsed; lastUsed is
7474
+ * request/header.config. Never consult the future global default or the model
7475
+ * catalog. A blank Session without explicit selection waits for that evidence.
7476
+ */
7477
+ function effectiveCopilot(projection) {
7478
+ if (!record(projection) || !(projection.lastUsed === null || selection(projection.lastUsed)) || !(projection.next === null || selection(projection.next))) return void 0;
7479
+ const next = projection.next;
7480
+ if (!selection(next)) return void 0;
7481
+ return next.provider === "github-copilot" || next.provider === "github-copilot-preview" ? next : void 0;
7482
+ }
7483
+ function Surface({ runtime, remote, locale, diagnostic }) {
7484
+ const session = runtime.useSession();
7485
+ const projection = runtime.useProjection("modelSelection");
7486
+ const language = (0, react.useSyncExternalStore)(locale === void 0 ? emptySubscribe : (listener) => locale.subscribe(listener), () => locale?.getLocale().active ?? "en", () => "en");
7487
+ const current = effectiveCopilot(projection);
7488
+ const valid = record(session) && session.sessionId === runtime.sessionId && session.removed === false && session.openState === "open";
7489
+ (0, react.useEffect)(() => {
7490
+ if (projection === void 0) diagnostic("COPILOT_USAGE_MODEL_PROJECTION_UNAVAILABLE");
7491
+ }, [projection, diagnostic]);
7492
+ if (!valid || current === void 0) return null;
7493
+ const contextKey = JSON.stringify([
7494
+ runtime.sessionId,
7495
+ current.provider,
7496
+ current.model
7497
+ ]);
7498
+ return (0, react.createElement)(CopilotUsageCard, {
7499
+ key: contextKey,
7500
+ contextKey,
7501
+ remote,
7502
+ locale: language
7503
+ });
7504
+ }
7505
+ /** Public additive dock only; native composer, ContextMeter and other features stay owned by Core. */
7506
+ function registerCopilotUsageUi(ctx) {
7507
+ const diagnosed = /* @__PURE__ */ new Set();
7508
+ const diagnostic = (code) => {
7509
+ if (!diagnosed.has(code)) {
7510
+ diagnosed.add(code);
7511
+ ctx.logger.warn(`[github-copilot] ${code}`);
7512
+ }
7513
+ };
7514
+ const candidate = ctx.slots;
7515
+ if (!isSlots(candidate)) {
7516
+ diagnostic("COPILOT_USAGE_SLOT_UNAVAILABLE");
7517
+ return noop;
7518
+ }
7519
+ const slots = candidate;
7520
+ let remote;
7521
+ try {
7522
+ const namespaces = ctx.remote;
7523
+ const face = record(namespaces) ? namespaces.githubCopilotUsage : void 0;
7524
+ if (isRemote(face)) remote = face;
7525
+ else diagnostic("COPILOT_USAGE_REMOTE_UNAVAILABLE");
7526
+ } catch {
7527
+ diagnostic("COPILOT_USAGE_REMOTE_UNAVAILABLE");
7528
+ }
7529
+ const localeCandidate = ctx.get("locale");
7530
+ const locale = isLocale(localeCandidate) ? localeCandidate : void 0;
7531
+ let active = true;
7532
+ let remove;
7533
+ let injection = noop;
7534
+ try {
7535
+ if (slots.spec(slot) === void 0) diagnostic("COPILOT_USAGE_SLOT_UNAVAILABLE");
7536
+ injection = slots.inject(slot, () => {
7537
+ if (!active) return noop;
7538
+ const spec = slots.spec(slot);
7539
+ if (spec?.kind !== "list" || spec.scope !== "session") {
7540
+ diagnostic("COPILOT_USAGE_SLOT_UNAVAILABLE");
7541
+ return noop;
7542
+ }
7543
+ try {
7544
+ const dispose = slots.register({
7545
+ name: slot,
7546
+ id: "github-copilot-usage",
7547
+ order: 20
7548
+ }, (props) => {
7549
+ if (!isRuntime(props)) {
7550
+ diagnostic("COPILOT_USAGE_SESSION_RUNTIME_UNAVAILABLE");
7551
+ return null;
7552
+ }
7553
+ return (0, react.createElement)(Surface, {
7554
+ runtime: props,
7555
+ remote,
7556
+ locale,
7557
+ diagnostic
7558
+ });
7559
+ });
7560
+ let removed = false;
7561
+ const cleanup = () => {
7562
+ if (!removed) {
7563
+ removed = true;
7564
+ dispose();
7565
+ }
7566
+ };
7567
+ remove = cleanup;
7568
+ return cleanup;
7569
+ } catch {
7570
+ diagnostic("COPILOT_USAGE_SLOT_UNAVAILABLE");
7571
+ return noop;
7572
+ }
7573
+ });
7574
+ } catch {
7575
+ diagnostic("COPILOT_USAGE_SLOT_UNAVAILABLE");
7576
+ }
7577
+ return () => {
7578
+ if (!active) return;
7579
+ active = false;
7580
+ injection();
7581
+ remove?.();
7582
+ };
7583
+ }
7584
+ //#endregion
6958
7585
  //#region lib/types/client.js
6959
7586
  /**
6960
7587
  * Browser companion for the Models provider-card slot.
@@ -7105,13 +7732,6 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
7105
7732
  if (writer === void 0) throw new Error("Clipboard access is unavailable");
7106
7733
  await writer.writeText(code);
7107
7734
  }
7108
- function verificationLinkTarget() {
7109
- if (typeof window !== "undefined" && "dshDesktop" in window) {
7110
- const desktop = window.dshDesktop;
7111
- if (typeof desktop === "object" && desktop !== null && "protocolVersion" in desktop && desktop.protocolVersion === 1) return "_self";
7112
- }
7113
- return "_blank";
7114
- }
7115
7735
  /** Pure presentation for the in-flight GitHub device-code handoff. */
7116
7736
  function GitHubCopilotAuthorizationNotice(props) {
7117
7737
  const feedback = props.copyState === "copying" ? "Copying code…" : props.copyState === "copied" ? "Code copied to clipboard." : props.copyState === "failed" ? "Copy failed. Select the code and copy it manually." : "";
@@ -7120,7 +7740,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
7120
7740
  style: noticePanelStyle
7121
7741
  }, (0, react.createElement)("div", null, props.message), props.url === void 0 ? null : (0, react.createElement)("a", {
7122
7742
  href: props.url,
7123
- target: verificationLinkTarget(),
7743
+ target: externalLinkTarget(),
7124
7744
  rel: "noreferrer"
7125
7745
  }, "Open GitHub verification page"), props.url === void 0 ? null : (0, react.createElement)("div", null, "If the browser does not open, copy this address into your browser:", (0, react.createElement)("code", {
7126
7746
  "data-dsh-github-copilot-verification-url": true,
@@ -7965,12 +8585,14 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
7965
8585
  "slots"
7966
8586
  ], registerSearchUi);
7967
8587
  const dualModelUi = ctx.inject(["remote.githubCopilotDualModel", "slots"], registerDualModelUi);
8588
+ const usageUi = ctx.inject(["remote.githubCopilotUsage", "slots"], registerCopilotUsageUi);
7968
8589
  const presentation = ctx.inject(["uiConversation", "slots"], (scope) => installReasoningPresentation({
7969
8590
  slots: scope.slots,
7970
8591
  uiConversation: scope.get("uiConversation"),
7971
8592
  diagnostic: (code) => scope.logger.warn(`[github-copilot] ${code}`)
7972
8593
  }));
7973
8594
  return async () => {
8595
+ await usageUi.dispose();
7974
8596
  await presentation.dispose();
7975
8597
  await dualModelUi.dispose();
7976
8598
  await searchUi.dispose();
@@ -7979,6 +8601,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
7979
8601
  };
7980
8602
  }
7981
8603
  //#endregion
8604
+ exports.CopilotUsageCard = CopilotUsageCard;
7982
8605
  exports.DualModelCard = DualModelCard;
7983
8606
  exports.GitHubCopilotAccountModelsPanel = GitHubCopilotAccountModelsPanel;
7984
8607
  exports.GitHubCopilotAccountModelsSummary = GitHubCopilotAccountModelsSummary;