opencode-copilot-statusline 0.1.0 → 0.2.0

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/README.md CHANGED
@@ -11,7 +11,7 @@ Display your GitHub Copilot quota in the OpenCode TUI footer statusline.
11
11
 
12
12
  - Live used-quota percentage in the prompt footer (`Copilot 87%`)
13
13
  - Monthly reset countdown when the footer details are expanded (or the terminal is wide enough)
14
- - Color feedback: subdued normally, info at ≥70%, error at ≥90%
14
+ - Color feedback on the whole segment (label and percentage): subdued normally, info at ≥70%, error at ≥90% or when the quota cannot be resolved
15
15
  - Only appears for sessions whose model provider is `github-copilot`
16
16
  - Usage refreshes about once per minute
17
17
 
package/README.zh-CN.md CHANGED
@@ -11,7 +11,7 @@
11
11
 
12
12
  - 在输入框底栏实时显示配额已用百分比(`Copilot 87%`)
13
13
  - 展开底栏详情(或终端足够宽)时显示每月重置倒计时
14
- - 颜色提示:正常为弱化色,≥70% 变提示色,≥90% 变错误色
14
+ - 颜色提示:`Copilot` 标签与百分比整段同步变色 —— 正常为弱化色,≥70% 为提示色,≥90% 或无法解析配额时为错误色
15
15
  - 仅当会话模型 provider 为 `github-copilot` 时显示
16
16
  - 用量约每分钟自动刷新一次
17
17
 
package/dist/tui.js CHANGED
@@ -59,17 +59,6 @@ function countdown(resetsAt, now) {
59
59
  return `${mins}m`;
60
60
  }
61
61
  function Segment(props) {
62
- const ctx = usePlugin();
63
- const fg = () => {
64
- const t = ctx.theme;
65
- if (props.usage.unlimited)
66
- return t.text.subdued;
67
- if (props.usage.usedPercent >= 90)
68
- return t.text.feedback.error.default;
69
- if (props.usage.usedPercent >= 70)
70
- return t.text.feedback.info.default;
71
- return t.text.subdued;
72
- };
73
62
  const text = () => {
74
63
  if (props.usage.unlimited)
75
64
  return "\u221E";
@@ -81,7 +70,7 @@ function Segment(props) {
81
70
  _$setProp(_el$, "wrapMode", "none");
82
71
  _$setProp(_el$, "flexShrink", 1);
83
72
  _$insert(_el$, text);
84
- _$effect((_$p) => _$setProp(_el$, "fg", fg(), _$p));
73
+ _$effect((_$p) => _$setProp(_el$, "fg", props.color(), _$p));
85
74
  return _el$;
86
75
  })();
87
76
  }
@@ -90,6 +79,19 @@ function CopilotUsage(props) {
90
79
  const [isCopilot, setIsCopilot] = createSignal(false);
91
80
  const dims = useTerminalDimensions();
92
81
  const detailed = () => props.showDetails() || dims().width >= DETAILED_WIDTH;
82
+ const fg = () => {
83
+ const t = ctx.theme;
84
+ const u = props.usage();
85
+ if (!u)
86
+ return props.loaded() ? t.text.feedback.error.default : t.text.subdued;
87
+ if (u.unlimited)
88
+ return t.text.subdued;
89
+ if (u.usedPercent >= 90)
90
+ return t.text.feedback.error.default;
91
+ if (u.usedPercent >= 70)
92
+ return t.text.feedback.info.default;
93
+ return t.text.subdued;
94
+ };
93
95
  let generation = 0;
94
96
  async function check(id) {
95
97
  const current = ++generation;
@@ -134,7 +136,7 @@ function CopilotUsage(props) {
134
136
  var _el$6 = _$createElement("text");
135
137
  _$insertNode(_el$6, _$createTextNode(`\u2014`));
136
138
  _$setProp(_el$6, "flexShrink", 0);
137
- _$effect((_$p) => _$setProp(_el$6, "fg", ctx.theme.text.subdued, _$p));
139
+ _$effect((_$p) => _$setProp(_el$6, "fg", fg(), _$p));
138
140
  return _el$6;
139
141
  })();
140
142
  },
@@ -142,12 +144,13 @@ function CopilotUsage(props) {
142
144
  get usage() {
143
145
  return u();
144
146
  },
147
+ color: fg,
145
148
  get detailed() {
146
149
  return detailed();
147
150
  }
148
151
  })
149
152
  }), null);
150
- _$effect((_$p) => _$setProp(_el$3, "fg", ctx.theme.text.subdued, _$p));
153
+ _$effect((_$p) => _$setProp(_el$3, "fg", fg(), _$p));
151
154
  return _el$2;
152
155
  }
153
156
  });
@@ -157,13 +160,16 @@ var tui_default = Plugin.define({
157
160
  setup(context) {
158
161
  const rpc = context.client.rpc(UsageRpc);
159
162
  const [usage, setUsage] = createSignal();
163
+ const [loaded, setLoaded] = createSignal(false);
160
164
  let timer;
161
165
  async function refresh() {
162
166
  try {
163
167
  const result = await rpc.get({});
164
168
  if (result?.usage)
165
169
  setUsage(result.usage);
166
- } catch {}
170
+ } catch {} finally {
171
+ setLoaded(true);
172
+ }
167
173
  }
168
174
  refresh();
169
175
  timer = setInterval(() => void refresh(), INTERVAL_MS);
@@ -172,7 +178,8 @@ var tui_default = Plugin.define({
172
178
  render: (input) => _$createComponent(CopilotUsage, {
173
179
  sessionID: () => input.sessionID,
174
180
  showDetails: () => input.showDetails,
175
- usage
181
+ usage,
182
+ loaded
176
183
  })
177
184
  });
178
185
  return () => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencode-copilot-statusline",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "OpenCode TUI plugin: display GitHub Copilot quota (premium requests, with a chat fallback for Copilot Free) in the footer statusline. V2-native, zero-config, no cookies.",
5
5
  "type": "module",
6
6
  "license": "MIT",