@byokit/ui 0.7.0 → 0.9.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/CHANGELOG.md +22 -0
- package/README.md +16 -8
- package/dist/accounts.d.ts +39 -4
- package/dist/accounts.js +42 -8
- package/dist/approvals.d.ts +1 -1
- package/dist/approvals.js +1 -1
- package/dist/browser.js +1 -1
- package/dist/connect.js +5 -2
- package/dist/herdr.d.ts +2 -2
- package/dist/herdr.js +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +11 -11
- package/dist/key.d.ts +6 -4
- package/dist/key.js +1 -1
- package/dist/kits.js +5 -5
- package/dist/phase.d.ts +1 -1
- package/dist/run.d.ts +2 -0
- package/dist/run.js +3 -2
- package/dist/useAccounts.js +1 -1
- package/dist/useConnect.d.ts +5 -5
- package/dist/useConnect.js +1 -1
- package/dist/useKits.d.ts +5 -5
- package/dist/useKits.js +3 -3
- package/dist/useSignIn.d.ts +1 -1
- package/dist/useSignIn.js +1 -1
- package/dist/words.json +9 -0
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,28 @@
|
|
|
2
2
|
|
|
3
3
|
## Unreleased
|
|
4
4
|
|
|
5
|
+
- Dependency update: pins @byokit/accounts 0.24.3.
|
|
6
|
+
|
|
7
|
+
## 0.9.0 (2026-10-17)
|
|
8
|
+
|
|
9
|
+
- Dependency update: pins @byokit/accounts 0.24.2.
|
|
10
|
+
|
|
11
|
+
- FEAT: The key card has a `workspace` state (`result: 'workspace'`, words "This key works for more than one
|
|
12
|
+
workspace. Pick the one to use."), so an app shows the workspace pick for a plan key that acts for several
|
|
13
|
+
workspaces (OpenCode Go) and submits again with the one picked.
|
|
14
|
+
|
|
15
|
+
- Dependency update: pins @byokit/accounts 0.24.1.
|
|
16
|
+
|
|
17
|
+
## 0.8.0 (2026-10-16)
|
|
18
|
+
|
|
19
|
+
- Dependency update: pins @byokit/accounts 0.24.0.
|
|
20
|
+
|
|
21
|
+
- FEAT: `accountRows(accounts, room, now, windows?)` and `AccountsSource.windows` take an account's `windowsView` from `@byokit/usage/view`: a ready row gains `windows` (each usage window, tightest first, with its line, its reset line and its millisecond reset) and `asOf` (`Read 2 minutes ago`, `Read 2 days ago (stale)` past a day). A window whose reset is already past reads `Session: reset since this reading` (no percent, no countdown), and so does the row's room line (`Plus · Reset since this reading`). A stale row is never `low`, and a reading without its own time (an openclaw room) shows its resets and no age. New types `UsageWindow`, `UsageWindows` and `AsOf`. The PWA example's account card draws both windows with their resets and age, keeps the last reading when a refresh fails so it shows as stale instead of unknown, and fits the longest address at 320px with larger text.
|
|
22
|
+
- FEAT: `runStore` tolerates an account run's first frame: the run stream may open with an `account` event (O14m) naming the account the reply bills to, which the run view ignores while the reply, tools and end behave as before.
|
|
23
|
+
- FIX: a subscription row whose route name already says plan ("Qwen Token Plan", "Qwen Token Plan CN", "Qwen Token Plan Individual") no longer reads "Uses your ... plan" with the word twice: `connectView` leaves the template's trailing plan out when the name already carries the word (any case). Names without it ("Qwen") still read "Uses your Qwen plan".
|
|
24
|
+
|
|
25
|
+
- Dependency update: pins @byokit/accounts 0.23.0.
|
|
26
|
+
|
|
5
27
|
## 0.7.0 (2026-10-12)
|
|
6
28
|
|
|
7
29
|
- Dependency update: pins @byokit/accounts 0.22.0.
|
package/README.md
CHANGED
|
@@ -123,9 +123,9 @@ export function useChatGptSheet() {
|
|
|
123
123
|
| `useRun`, `useApprovals`, `useHerdrTree`, `useBlocked` | React hooks over those stores |
|
|
124
124
|
| `connectView(routes, step?)`, `connectStep(step, action)` | Every account route the kits list, grouped by how the person pays, with the picked row and its key card |
|
|
125
125
|
| `signInFor(view, { read, start?, cancel })`, `useConnect({ routes, read, start?, cancel })` | `useSignIn`'s options for the picked sign-in row; the hook holds the step |
|
|
126
|
-
| `accountRows(accounts, room, now)`, `rowsOf(source, now)`, `nameSuggestions(email, taken, provider?)` | One plain-words row per account (`ChatGPT · Work` / `Plus · 72% left this week`), the honest words for every sign-in state, and untaken account-name suggestions |
|
|
126
|
+
| `accountRows(accounts, room, now, windows?)`, `rowsOf(source, now)`, `nameSuggestions(email, taken, provider?)` | One plain-words row per account (`ChatGPT · Work` / `Plus · 72% left this week`), the honest words for every sign-in state, and untaken account-name suggestions |
|
|
127
127
|
| `useAccounts(source)`, `useModelPicker(source, initial?)` | React hooks: the rows live with `refresh()` and `remove()` (a failing room leaves only its row unknown; a mid-refresh remove still drops it), and the run picker with `select()` keeping the caller's selection across refreshes; `accountsSource(accounts, member, room?)` and `cliSource(cli, room?)` fill the source with one line per member (the openclaw adapter stays pending O14) |
|
|
128
|
-
| Types | `Phase`, `SignInView`, `AccountView`, `UseSignIn`, `Route`, `RouteChoice`, `RouteCode`, `PairPhase`, `Role`, `DeviceKind`, `LinkStatus`; `RouteKind` from `@byokit/ui/route`; `Account`, `AccountRow`, `AccountAction`, `AccountsSource`, `Billing`, `Room`, `RoomSpan`, `SignInState` from `@byokit/ui/accounts` |
|
|
128
|
+
| Types | `Phase`, `SignInView`, `AccountView`, `UseSignIn`, `Route`, `RouteChoice`, `RouteCode`, `PairPhase`, `Role`, `DeviceKind`, `LinkStatus`; `RouteKind` from `@byokit/ui/route`; `Account`, `AccountRow`, `AccountAction`, `AccountsSource`, `AsOf`, `Billing`, `Room`, `RoomSpan`, `SignInState`, `UsageWindow`, `UsageWindows` from `@byokit/ui/accounts` |
|
|
129
129
|
|
|
130
130
|
Entry points: `@byokit/ui` (everything, including the React hooks), `@byokit/ui/phase`,
|
|
131
131
|
`@byokit/ui/route`, `@byokit/ui/link`, `@byokit/ui/kits`, `@byokit/ui/steps`,
|
|
@@ -208,13 +208,15 @@ const options = signInFor(view, { read: (row) => api.account(row.id), start: (ro
|
|
|
208
208
|
```
|
|
209
209
|
|
|
210
210
|
A key route's `chosen.key` is the existing `keyView` card, labelled for its billing ("Key from your plan" or "Key
|
|
211
|
-
(charged per use)"); submit the input straight to the kit and dispatch only `{ type: 'result', result }`.
|
|
211
|
+
(charged per use)"); submit the input straight to the kit and dispatch only `{ type: 'result', result }`. A key
|
|
212
|
+
that acts for several workspaces (`@byokit/accounts` `add` answers `workspaces`) dispatches `result: 'workspace'`:
|
|
213
|
+
list those workspaces, then `submit` again with the one picked.
|
|
212
214
|
`useConnect({ routes, read, start?, cancel })` holds the step in React and returns the view with `pick`, `back`,
|
|
213
215
|
`act` and `signIn`, the options to pass to `useSignIn` in a sheet keyed by `chosen.row.key`.
|
|
214
216
|
|
|
215
217
|
## Account rows
|
|
216
218
|
|
|
217
|
-
`accountRows(accounts, room, now)` (also `@byokit/ui/accounts`, no React) turns a list of accounts and a room reading
|
|
219
|
+
`accountRows(accounts, room, now, windows?)` (also `@byokit/ui/accounts`, no React) turns a list of accounts and a room reading
|
|
218
220
|
into one plain row each: the provider and the person's own name for the account (`ChatGPT · Work`), then the plan and
|
|
219
221
|
the room left (`Plus · 72% left this week`). A row also carries `state`, `billing`, `low` (room left at or below 20%,
|
|
220
222
|
exactly 20 included, never true for an unknown room) and, when it helps, an `action`: `sign_in` for a signed-out or
|
|
@@ -222,8 +224,14 @@ lapsed account, `wait` plus the `until` refill time for a resting one. `accountR
|
|
|
222
224
|
so a credential on an account never reaches a row. A row that is not ready shows its own honest words ("Checking…",
|
|
223
225
|
"Cooling down", "Not signed in", "Sign in again", "Not in your plan") instead of the room.
|
|
224
226
|
|
|
225
|
-
`
|
|
226
|
-
|
|
227
|
+
Pass `windows`, the account's `windowsView(reading, now)` from `@byokit/usage/view`, as a fourth argument and a ready
|
|
228
|
+
row also carries `windows` (each usage window, tightest first: `Week: 72% left` with `resets in 4d`) and `asOf`
|
|
229
|
+
(`Read 2 minutes ago`, or `Read 2 days ago (stale)` past a day). A window whose reset is already past reads
|
|
230
|
+
`Session: reset since this reading`, with no percent or countdown, and the room line `Reset since this reading`. A stale row is never `low`; a reading without its own
|
|
231
|
+
time, such as an openclaw room, shows its resets and no `asOf`, never a made-up age.
|
|
232
|
+
|
|
233
|
+
`AccountsSource` is the shape an app fills from its own back end — `accounts()`, `room(account)` and optionally
|
|
234
|
+
`windows(account)` — and `rowsOf(source, now)` awaits them and builds the same rows; `@byokit/accounts` `list()` and a room reading fit it with one line per member.
|
|
227
235
|
`nameSuggestions(email, taken, provider?)` offers up to three untaken account names from an email's local part
|
|
228
236
|
(deduped case-insensitively against `taken`), falling back to the provider's name; the email itself is never offered.
|
|
229
237
|
|
|
@@ -326,7 +334,7 @@ Runtime kits' state, from `@byokit/ui/kits` (no React), typed to fit `@byokit/op
|
|
|
326
334
|
|
|
327
335
|
- Runs: `runStore(oc)` with `send(message)` and `stop()`; `runView(state, { words, name })` gives the reply so far, the
|
|
328
336
|
tool at work and, for a failed run, the kit's sentence (`words` from `@byokit/openclaw/device`, `name` "ChatGPT").
|
|
329
|
-
OpenClaw's `started` and `
|
|
337
|
+
OpenClaw's `started`, `thinking` and `account` frames are accepted without changing the reply, tools or rendered state;
|
|
330
338
|
the running phase begins at `send`, not Gateway acceptance.
|
|
331
339
|
- Approvals: `approvalsStore(oc)` keeps the waiting list live (each leaves when answered anywhere or when it expires);
|
|
332
340
|
`approvalWords(approval, words, 'Your helper')` asks the question.
|
|
@@ -357,7 +365,7 @@ with the device client made once (`useMemo(() => herdrDevice(link), [link])`).
|
|
|
357
365
|
Apache-2.0. See [LICENSE](LICENSE) and [NOTICE](../../NOTICE).
|
|
358
366
|
|
|
359
367
|
`@byokit/ui/kits` also exports `keyStep(state, action)` and `keyView(state, words)` for an explicit
|
|
360
|
-
**API key (billed per use)** entry card. States are `entry`, `checking`, `ok`, `invalid`, `not_included`;
|
|
368
|
+
**API key (billed per use)** entry card. States are `entry`, `checking`, `workspace`, `ok`, `invalid`, `not_included`;
|
|
361
369
|
actions are `submit`, `edit`, and `result` with the kit's add-key outcome. Supply the OpenClaw kit's `words`
|
|
362
370
|
function for the label and sentences. These views never contain the entered key; submit it directly to the host
|
|
363
371
|
and clear the input afterwards.
|
package/dist/accounts.d.ts
CHANGED
|
@@ -27,6 +27,33 @@ export type Account = {
|
|
|
27
27
|
export type AccountsSource = {
|
|
28
28
|
accounts: () => Promise<readonly Account[]> | readonly Account[];
|
|
29
29
|
room: (account: Account) => Promise<Room> | Room;
|
|
30
|
+
/** The account's `windowsView`, when the app keeps its usage reading. */
|
|
31
|
+
windows?: (account: Account) => Promise<UsageWindows | undefined> | UsageWindows | undefined;
|
|
32
|
+
};
|
|
33
|
+
/** One usage window, restated structurally from `@byokit/usage/view` `windowsView`: its line (`Week: 58% left`), its
|
|
34
|
+
* reset line (`resets in 4h 40m`) and the unchanged millisecond reset. */
|
|
35
|
+
export type UsageWindow = {
|
|
36
|
+
kind: 'session' | 'weekly' | 'monthly' | 'rolling' | 'custom';
|
|
37
|
+
text: string;
|
|
38
|
+
resetText: string;
|
|
39
|
+
resetsAt?: number;
|
|
40
|
+
usedPercent?: number;
|
|
41
|
+
limited?: boolean;
|
|
42
|
+
};
|
|
43
|
+
/** An account's `windowsView(reading, now)`, restated structurally; only these fields are read. */
|
|
44
|
+
export type UsageWindows = {
|
|
45
|
+
windows: readonly UsageWindow[];
|
|
46
|
+
at?: number;
|
|
47
|
+
ageMs?: number;
|
|
48
|
+
ageText?: string;
|
|
49
|
+
stale: boolean;
|
|
50
|
+
};
|
|
51
|
+
/** How old a row's windows are, taken only from the reading's own time: `Read 2 minutes ago`, with `(stale)` past a day. */
|
|
52
|
+
export type AsOf = {
|
|
53
|
+
at: number;
|
|
54
|
+
ageMs: number;
|
|
55
|
+
text: string;
|
|
56
|
+
stale: boolean;
|
|
30
57
|
};
|
|
31
58
|
export type AccountAction = 'sign_in' | 'wait';
|
|
32
59
|
export type AccountRow = {
|
|
@@ -35,16 +62,24 @@ export type AccountRow = {
|
|
|
35
62
|
detail: string;
|
|
36
63
|
state: SignInState;
|
|
37
64
|
billing: Billing;
|
|
38
|
-
/** Room left is at or below 20%: true at exactly 20, false above it
|
|
65
|
+
/** Room left is at or below 20%: true at exactly 20, false above it, when the room is unknown or the windows are stale. */
|
|
39
66
|
low: boolean;
|
|
67
|
+
/** A ready account's usage windows, tightest first, each with its reset; one that reset since the reading reads
|
|
68
|
+
* `Session: reset since this reading`, with an empty `resetText` and no `usedPercent`. Present when the app passed them. */
|
|
69
|
+
windows?: UsageWindow[];
|
|
70
|
+
/** The windows' age; absent when the reading carries no time of its own (never a made-up one) or a future one. */
|
|
71
|
+
asOf?: AsOf;
|
|
40
72
|
/** What the person can do: sign in again, or wait for a resting account to refill. Absent when nothing helps. */
|
|
41
73
|
action?: AccountAction;
|
|
42
74
|
/** A resting account's next refill, epoch milliseconds. */
|
|
43
75
|
until?: number;
|
|
44
76
|
};
|
|
45
|
-
/** One row per account, reading one room per account; a missing or throwing reading is 'Room left unknown'.
|
|
46
|
-
|
|
47
|
-
|
|
77
|
+
/** One row per account, reading one room per account; a missing or throwing reading is 'Room left unknown'. `windows`
|
|
78
|
+
* is the account's `windowsView` from `@byokit/usage/view`, when the app keeps the reading; a missing or throwing one
|
|
79
|
+
* leaves the row without windows. */
|
|
80
|
+
export declare function accountRows(accounts: readonly Account[], room: (account: Account) => Room, now: number, windows?: (account: Account) => UsageWindows | undefined): AccountRow[];
|
|
81
|
+
/** `accountRows` over an `AccountsSource`: the app's own `accounts()`, `room()` and `windows()`, awaited; a failing room
|
|
82
|
+
* reads unknown and failing windows leave the row without them. */
|
|
48
83
|
export declare function rowsOf(source: AccountsSource, now: number): Promise<AccountRow[]>;
|
|
49
84
|
/** Untaken names an app can offer for a new account, from the email's local part (never the email itself), else the
|
|
50
85
|
* provider's name. Dedupes case-insensitively against `taken`; up to three. */
|
package/dist/accounts.js
CHANGED
|
@@ -15,13 +15,30 @@ function titleOf(a) {
|
|
|
15
15
|
}
|
|
16
16
|
/** A resting account whose refill time has passed reads as ready again, exactly as the Auto chooser treats it. */
|
|
17
17
|
const refilled = (a, now) => a.state === 'resting' && typeof a.until === 'number' && a.until <= now;
|
|
18
|
-
|
|
18
|
+
/** A reset at or before now happened after the reading, so its numbers no longer hold. */
|
|
19
|
+
const resetSince = (resetsAt, now) => typeof resetsAt === 'number' && resetsAt <= now;
|
|
20
|
+
/** Only the named fields, so nothing else on the app's view (a scope, a provider) reaches a row. A window that reset
|
|
21
|
+
* since the reading says so, with no percent and no countdown. */
|
|
22
|
+
const windowOf = (x, now) => resetSince(x.resetsAt, now)
|
|
23
|
+
? { kind: x.kind, text: WORDS['account.window.resetSince'].replace('{label}', WORDS[`account.window.${x.kind}`]), resetText: '', resetsAt: x.resetsAt }
|
|
24
|
+
: { kind: x.kind, text: x.text, resetText: x.resetText, ...(typeof x.resetsAt === 'number' ? { resetsAt: x.resetsAt } : {}),
|
|
25
|
+
...(typeof x.usedPercent === 'number' ? { usedPercent: x.usedPercent } : {}), ...(x.limited ? { limited: true } : {}) };
|
|
26
|
+
function asOfOf(w) {
|
|
27
|
+
if (typeof w.at !== 'number' || typeof w.ageMs !== 'number' || !w.ageText)
|
|
28
|
+
return undefined;
|
|
29
|
+
return { at: w.at, ageMs: w.ageMs, text: w.stale ? WORDS['account.stale'].replace('{age}', w.ageText) : w.ageText, stale: w.stale };
|
|
30
|
+
}
|
|
31
|
+
function rowOf(a, room, now, w) {
|
|
19
32
|
const state = refilled(a, now) ? 'ready' : a.state;
|
|
20
33
|
const title = titleOf(a);
|
|
21
34
|
if (state === 'ready') {
|
|
22
|
-
|
|
35
|
+
// A room whose window reset since the reading no longer holds its number: say so, and it is not low.
|
|
36
|
+
const reset = room.left !== 'unknown' && resetSince(room.resetsAt, now);
|
|
37
|
+
const words = reset ? WORDS['account.room.resetSince'] : roomWords(room);
|
|
38
|
+
const asOf = w && asOfOf(w);
|
|
23
39
|
return { id: a.id, title, detail: a.plan && room.left !== 'unknown' ? `${planLabel(a.plan)} · ${words}` : words, state, billing: a.billing,
|
|
24
|
-
low: room.left !== 'unknown' && room.left <= LOW_AT
|
|
40
|
+
low: room.left !== 'unknown' && room.left <= LOW_AT && !w?.stale && !reset,
|
|
41
|
+
...(w ? { windows: w.windows.map((x) => windowOf(x, now)) } : {}), ...(asOf ? { asOf } : {}) };
|
|
25
42
|
}
|
|
26
43
|
if (state === 'resting') {
|
|
27
44
|
return { id: a.id, title, detail: WORDS['account.resting'], state, billing: a.billing, low: false, action: 'wait',
|
|
@@ -30,8 +47,10 @@ function rowOf(a, room, now) {
|
|
|
30
47
|
const action = state === 'signed_out' || state === 'needs_again' ? 'sign_in' : undefined;
|
|
31
48
|
return { id: a.id, title, detail: WORDS[`account.${state}`], state, billing: a.billing, low: false, ...(action ? { action } : {}) };
|
|
32
49
|
}
|
|
33
|
-
/** One row per account, reading one room per account; a missing or throwing reading is 'Room left unknown'.
|
|
34
|
-
|
|
50
|
+
/** One row per account, reading one room per account; a missing or throwing reading is 'Room left unknown'. `windows`
|
|
51
|
+
* is the account's `windowsView` from `@byokit/usage/view`, when the app keeps the reading; a missing or throwing one
|
|
52
|
+
* leaves the row without windows. */
|
|
53
|
+
export function accountRows(accounts, room, now, windows) {
|
|
35
54
|
return accounts.map((a) => {
|
|
36
55
|
let r = UNKNOWN;
|
|
37
56
|
try {
|
|
@@ -40,13 +59,22 @@ export function accountRows(accounts, room, now) {
|
|
|
40
59
|
catch {
|
|
41
60
|
r = UNKNOWN;
|
|
42
61
|
}
|
|
43
|
-
|
|
62
|
+
let w;
|
|
63
|
+
try {
|
|
64
|
+
w = windows?.(a);
|
|
65
|
+
}
|
|
66
|
+
catch {
|
|
67
|
+
w = undefined;
|
|
68
|
+
}
|
|
69
|
+
return rowOf(a, r, now, w);
|
|
44
70
|
});
|
|
45
71
|
}
|
|
46
|
-
/** `accountRows` over an `AccountsSource`: the app's own `accounts()` and `
|
|
72
|
+
/** `accountRows` over an `AccountsSource`: the app's own `accounts()`, `room()` and `windows()`, awaited; a failing room
|
|
73
|
+
* reads unknown and failing windows leave the row without them. */
|
|
47
74
|
export async function rowsOf(source, now) {
|
|
48
75
|
const accounts = await source.accounts();
|
|
49
76
|
const rooms = new Map();
|
|
77
|
+
const windows = new Map();
|
|
50
78
|
for (const a of accounts) {
|
|
51
79
|
try {
|
|
52
80
|
rooms.set(a.id, (await source.room(a)) ?? UNKNOWN);
|
|
@@ -54,8 +82,14 @@ export async function rowsOf(source, now) {
|
|
|
54
82
|
catch {
|
|
55
83
|
rooms.set(a.id, UNKNOWN);
|
|
56
84
|
}
|
|
85
|
+
try {
|
|
86
|
+
windows.set(a.id, await source.windows?.(a));
|
|
87
|
+
}
|
|
88
|
+
catch {
|
|
89
|
+
windows.set(a.id, undefined);
|
|
90
|
+
}
|
|
57
91
|
}
|
|
58
|
-
return accountRows(accounts, (a) => rooms.get(a.id) ?? UNKNOWN, now);
|
|
92
|
+
return accountRows(accounts, (a) => rooms.get(a.id) ?? UNKNOWN, now, (a) => windows.get(a.id));
|
|
59
93
|
}
|
|
60
94
|
/** Untaken names an app can offer for a new account, from the email's local part (never the email itself), else the
|
|
61
95
|
* provider's name. Dedupes case-insensitively against `taken`; up to three. */
|
package/dist/approvals.d.ts
CHANGED
|
@@ -27,7 +27,7 @@ export type ApprovalsAction = ApprovalFrame | {
|
|
|
27
27
|
};
|
|
28
28
|
export declare function approvalsStep(list: Approval[], a: ApprovalsAction): Approval[];
|
|
29
29
|
/** The question for one approval, in the kit's own sentence (`@byokit/openclaw/device`'s `words` fits). */
|
|
30
|
-
export declare const approvalWords: (a: Approval, words: (key:
|
|
30
|
+
export declare const approvalWords: (a: Approval, words: (key: 'approval.ask', vars: {
|
|
31
31
|
helper: string;
|
|
32
32
|
summary: string;
|
|
33
33
|
}) => string, helper: string) => string;
|
package/dist/approvals.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// What is waiting for a person's yes: the approvals list kept current from the kit's event stream, each dropped when
|
|
2
2
|
// it is answered anywhere or runs out of time. Framework-free; typed structurally against `@byokit/openclaw/device`.
|
|
3
|
-
import { retrying, store } from
|
|
3
|
+
import { retrying, store } from './follow.js';
|
|
4
4
|
export function approvalsStep(list, a) {
|
|
5
5
|
if ('type' in a) {
|
|
6
6
|
if (a.type === 'set')
|
package/dist/browser.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// the chip under the chat. Framework-free; typed structurally against `@byokit/openclaw`'s `NeedSignIn` and
|
|
3
3
|
// `LiveViewState` (spec 5.17), so nothing here imports a kit. Sentences are the kit's word keys plus their values,
|
|
4
4
|
// for the kit's own `words` to say. Nothing here ever holds what the person types.
|
|
5
|
-
import { retrying, store } from
|
|
5
|
+
import { retrying, store } from './follow.js';
|
|
6
6
|
const settledLine = (s) => {
|
|
7
7
|
switch (s.state) {
|
|
8
8
|
case 'verified':
|
package/dist/connect.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
// offered by default; every other row is listed and used only when the person picks it. Nothing here names a
|
|
4
4
|
// provider: groups and words come from each row's billing, method and readiness alone. Framework-free.
|
|
5
5
|
import WORDS from './words.json' with { type: 'json' };
|
|
6
|
-
import { keyStep, keyView } from
|
|
6
|
+
import { keyStep, keyView } from './key.js';
|
|
7
7
|
const ORDER = ['plans', 'perUse', 'local', 'server', 'cloud', 'other', 'services'];
|
|
8
8
|
const SIGNIN = ['browser', 'code', 'paste', 'session', 'cli'];
|
|
9
9
|
const KEY = ['key', 'plan_key', 'setup_token'];
|
|
@@ -34,13 +34,16 @@ function rowOf(r, w) {
|
|
|
34
34
|
const group = groupOf(r);
|
|
35
35
|
const ready = r.readiness === 'ready';
|
|
36
36
|
const billing = r.via === 'endpoint' ? w['billing.server'] : r.via === 'local' ? w['billing.local'] : w[`billing.${r.billing}`];
|
|
37
|
+
// A route name can already carry the word the subscription line adds ("Qwen Token Plan CN"):
|
|
38
|
+
// then leave it out, so the row never reads "... Plan ... plan".
|
|
39
|
+
const line = r.billing === 'subscription' && /\bplan\b/i.test(name) ? billing.replace(/(\{name\})\s+plan\b/i, '$1') : billing;
|
|
37
40
|
return {
|
|
38
41
|
key: `${r.upstream?.surface ?? ''}/${id}`, id, provider: r.provider,
|
|
39
42
|
...(r.upstream ? { surface: r.upstream.surface } : {}),
|
|
40
43
|
name, company, via: r.via, billing: r.billing, group,
|
|
41
44
|
offered: group === 'plans' && ready, ready, readiness: r.readiness,
|
|
42
45
|
does: !ready ? 'unavailable' : SIGNIN.includes(r.via) ? 'signin' : KEY.includes(r.via) ? 'key' : 'setup',
|
|
43
|
-
billingWords: fill(
|
|
46
|
+
billingWords: fill(line, { name, company }), method: w[`via.${r.via}`], status: w[`ready.${r.readiness}`],
|
|
44
47
|
};
|
|
45
48
|
}
|
|
46
49
|
export function connectStep(step, action) {
|
package/dist/herdr.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type Store } from './follow.ts';
|
|
2
|
-
export type AgentStatus = 'idle' | 'working' | 'blocked' | 'done' | 'unknown';
|
|
2
|
+
export type AgentStatus = 'idle' | 'working' | 'blocked' | 'done' | 'failed' | 'unknown';
|
|
3
3
|
export type HerdrAgent = {
|
|
4
4
|
kind?: string;
|
|
5
5
|
name?: string;
|
|
@@ -79,7 +79,6 @@ export declare function herdrTreeView(tree: HerdrTree | null): {
|
|
|
79
79
|
export declare function agentIn(tree: HerdrTree | null, paneId: string | undefined): AgentRow | undefined;
|
|
80
80
|
/** The waiting agents, each with the name to show for it. */
|
|
81
81
|
export declare const blockedView: (s: HerdrState) => {
|
|
82
|
-
name: string;
|
|
83
82
|
paneId: string;
|
|
84
83
|
workspaceId: string;
|
|
85
84
|
tabId: string;
|
|
@@ -87,6 +86,7 @@ export declare const blockedView: (s: HerdrState) => {
|
|
|
87
86
|
revision: number;
|
|
88
87
|
prompt: string;
|
|
89
88
|
since: number;
|
|
89
|
+
name: string;
|
|
90
90
|
}[];
|
|
91
91
|
/** What `herdrStore` needs from a device client: `herdrDevice(link)` fits. */
|
|
92
92
|
export type HerdrSource = {
|
package/dist/herdr.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// Herdr's agents as a person sees them: the tree (where each agent is, and how it is doing) and the agents waiting
|
|
2
2
|
// for an answer, kept current from one `hd.events` stream. Framework-free; typed structurally against
|
|
3
3
|
// `@byokit/herdr/device`, so nothing here imports the kit.
|
|
4
|
-
import { retrying, store } from
|
|
4
|
+
import { retrying, store } from './follow.js';
|
|
5
5
|
export const HERDR_EMPTY = { tree: null, blocked: [] };
|
|
6
6
|
export function herdrStep(s, a) {
|
|
7
7
|
if (a.type === 'snapshot') {
|
package/dist/index.d.ts
CHANGED
|
@@ -7,5 +7,5 @@ export * from './kits.ts';
|
|
|
7
7
|
export { useApprovals, useBlocked, useHerdrTree, useRun } from './useKits.ts';
|
|
8
8
|
export { connectStep, connectView, signInFor, type ConnectAction, type ConnectDoes, type ConnectGroup, type ConnectGroupId, type ConnectRoute, type ConnectRow, type ConnectStep, type ConnectView, type ConnectWords, type UseConnectSignIn } from './connect.ts';
|
|
9
9
|
export { useConnect, type UseConnect } from './useConnect.ts';
|
|
10
|
-
export { accountRows, nameSuggestions, rowsOf, type Account, type AccountAction, type AccountRow, type AccountsSource, type Billing, type Room, type RoomSpan, type SignInState } from './accounts.ts';
|
|
10
|
+
export { accountRows, nameSuggestions, rowsOf, type Account, type AccountAction, type AccountRow, type AccountsSource, type AsOf, type Billing, type Room, type RoomSpan, type SignInState, type UsageWindow, type UsageWindows } from './accounts.ts';
|
|
11
11
|
export { accountsSource, cliSource, useAccounts, useModelPicker, type AccountHooksSource, type CliAccounts, type MemberAccounts, type ModelPickerSource, type UseAccounts, type UseModelPicker } from './useAccounts.ts';
|
package/dist/index.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
export { phaseOf, stepOf } from
|
|
2
|
-
export { connectedWords, describeRoute, routeChoices, routeShort } from
|
|
3
|
-
export { useSignIn } from
|
|
4
|
-
export { stepsText, stepsView } from
|
|
5
|
-
export { consentWords, linkWords, pairErrorWords, pairingView, qrMatrix, qrText } from
|
|
6
|
-
export * from
|
|
7
|
-
export { useApprovals, useBlocked, useHerdrTree, useRun } from
|
|
8
|
-
export { connectStep, connectView, signInFor } from
|
|
9
|
-
export { useConnect } from
|
|
10
|
-
export { accountRows, nameSuggestions, rowsOf } from
|
|
11
|
-
export { accountsSource, cliSource, useAccounts, useModelPicker } from
|
|
1
|
+
export { phaseOf, stepOf } from './phase.js';
|
|
2
|
+
export { connectedWords, describeRoute, routeChoices, routeShort } from './route.js';
|
|
3
|
+
export { useSignIn } from './useSignIn.js';
|
|
4
|
+
export { stepsText, stepsView } from './steps.js';
|
|
5
|
+
export { consentWords, linkWords, pairErrorWords, pairingView, qrMatrix, qrText } from './link.js';
|
|
6
|
+
export * from './kits.js';
|
|
7
|
+
export { useApprovals, useBlocked, useHerdrTree, useRun } from './useKits.js';
|
|
8
|
+
export { connectStep, connectView, signInFor } from './connect.js';
|
|
9
|
+
export { useConnect } from './useConnect.js';
|
|
10
|
+
export { accountRows, nameSuggestions, rowsOf } from './accounts.js';
|
|
11
|
+
export { accountsSource, cliSource, useAccounts, useModelPicker } from './useAccounts.js';
|
package/dist/key.d.ts
CHANGED
|
@@ -1,14 +1,16 @@
|
|
|
1
|
-
/** A key-entry card never holds a credential: the host submits the input directly to kit.addKey.
|
|
2
|
-
|
|
1
|
+
/** A key-entry card never holds a credential: the host submits the input directly to kit.addKey.
|
|
2
|
+
* `workspace`: the key acts for several workspaces and nothing is saved yet; the host lists the kit's workspaces
|
|
3
|
+
* and submits again with the one picked. */
|
|
4
|
+
export type KeyState = 'entry' | 'checking' | 'workspace' | 'ok' | 'invalid' | 'not_included';
|
|
3
5
|
export type KeyAction = {
|
|
4
6
|
type: 'submit';
|
|
5
7
|
} | {
|
|
6
8
|
type: 'edit';
|
|
7
9
|
} | {
|
|
8
10
|
type: 'result';
|
|
9
|
-
result: 'ok' | 'invalid' | 'not_included';
|
|
11
|
+
result: 'workspace' | 'ok' | 'invalid' | 'not_included';
|
|
10
12
|
};
|
|
11
|
-
export type KeyWords = (key: 'key.label' | 'key.entry' | 'key.checking' | 'key.ok' | 'key.invalid' | 'key.notIncluded') => string;
|
|
13
|
+
export type KeyWords = (key: 'key.label' | 'key.entry' | 'key.checking' | 'key.workspace' | 'key.ok' | 'key.invalid' | 'key.notIncluded') => string;
|
|
12
14
|
export declare function keyStep(state: KeyState, action: KeyAction): KeyState;
|
|
13
15
|
export declare function keyView(state: KeyState, words: KeyWords): {
|
|
14
16
|
state: KeyState;
|
package/dist/key.js
CHANGED
|
@@ -6,7 +6,7 @@ export function keyStep(state, action) {
|
|
|
6
6
|
return state === 'checking' ? action.result : state;
|
|
7
7
|
}
|
|
8
8
|
export function keyView(state, words) {
|
|
9
|
-
const keys = { entry: 'key.entry', checking: 'key.checking', ok: 'key.ok', invalid: 'key.invalid', not_included: 'key.notIncluded' };
|
|
9
|
+
const keys = { entry: 'key.entry', checking: 'key.checking', workspace: 'key.workspace', ok: 'key.ok', invalid: 'key.invalid', not_included: 'key.notIncluded' };
|
|
10
10
|
return { state, label: words('key.label'), message: words(keys[state]), busy: state === 'checking',
|
|
11
11
|
editable: state === 'entry' || state === 'invalid' };
|
|
12
12
|
}
|
package/dist/kits.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// View state for the runtime kits, with no React: reducers, views and live stores any UI can draw from (plain DOM,
|
|
2
2
|
// React, React Native). The hooks in `@byokit/ui` read the same stores.
|
|
3
|
-
export { RUN_IDLE, runStep, runStore, runView } from
|
|
4
|
-
export { approvalsStep, approvalsStore, approvalWords } from
|
|
5
|
-
export { HERDR_EMPTY, agentIn, blockedView, herdrStep, herdrStore, herdrTreeView } from
|
|
6
|
-
export { keyStep, keyView } from
|
|
7
|
-
export { livePanelView, signInSheetView, signInsStore } from
|
|
3
|
+
export { RUN_IDLE, runStep, runStore, runView } from './run.js';
|
|
4
|
+
export { approvalsStep, approvalsStore, approvalWords } from './approvals.js';
|
|
5
|
+
export { HERDR_EMPTY, agentIn, blockedView, herdrStep, herdrStore, herdrTreeView } from './herdr.js';
|
|
6
|
+
export { keyStep, keyView } from './key.js';
|
|
7
|
+
export { livePanelView, signInSheetView, signInsStore } from './browser.js';
|
package/dist/phase.d.ts
CHANGED
|
@@ -15,9 +15,9 @@ export type AccountView = {
|
|
|
15
15
|
signIn?: SignInView | null;
|
|
16
16
|
};
|
|
17
17
|
export declare function phaseOf(a: AccountView | null, { offline, cancelled, keepWork }?: {
|
|
18
|
-
offline?: boolean | undefined;
|
|
19
18
|
cancelled?: boolean | undefined;
|
|
20
19
|
keepWork?: boolean | undefined;
|
|
20
|
+
offline?: boolean | undefined;
|
|
21
21
|
}): Phase;
|
|
22
22
|
/** Where the three-step progress bar ("Open", "Say yes", "Done") stands. */
|
|
23
23
|
export declare const stepOf: (p: Phase) => 0 | 1 | 3;
|
package/dist/run.d.ts
CHANGED
package/dist/run.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
// idle nothing sent yet running the reply is streaming in
|
|
4
4
|
// done the reply is complete stopped stopped before the end (here, or aborted on the computer)
|
|
5
5
|
// failed it ended with a problem: `words` says which, in the kit's own sentence
|
|
6
|
-
import { store } from
|
|
6
|
+
import { store } from './follow.js';
|
|
7
7
|
export const RUN_IDLE = { phase: 'idle', text: '', tools: [] };
|
|
8
8
|
export function runStep(s, a) {
|
|
9
9
|
if (a.type === 'start')
|
|
@@ -12,7 +12,8 @@ export function runStep(s, a) {
|
|
|
12
12
|
return s; // a finished run hears nothing more
|
|
13
13
|
switch (a.type) {
|
|
14
14
|
case 'started':
|
|
15
|
-
case 'thinking':
|
|
15
|
+
case 'thinking':
|
|
16
|
+
case 'account': return s;
|
|
16
17
|
case 'text': return { ...s, text: a.text };
|
|
17
18
|
case 'tool': {
|
|
18
19
|
if (a.phase === 'start')
|
package/dist/useAccounts.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
// way. A failing room leaves only its row unknown; a mid-refresh `remove()` still drops the row. No openclaw
|
|
4
4
|
// adapter yet (pending O14).
|
|
5
5
|
import { useCallback, useEffect, useRef, useState } from 'react';
|
|
6
|
-
import { accountRows, modelPicker, rowsOf } from
|
|
6
|
+
import { accountRows, modelPicker, rowsOf } from './accounts.js';
|
|
7
7
|
const UNKNOWN_ROOM = { left: 'unknown' };
|
|
8
8
|
const CLI_LABEL = { claude: 'Claude', codex: 'Codex', pi: 'Pi' };
|
|
9
9
|
/** One line per member: the rows' source (with the picker's models and Auto pick) over a live `Accounts`. */
|
package/dist/useConnect.d.ts
CHANGED
|
@@ -4,15 +4,15 @@ export type UseConnect = UseConnectSignIn & {
|
|
|
4
4
|
words?: ConnectWords;
|
|
5
5
|
};
|
|
6
6
|
export declare function useConnect({ routes, words, ...o }: UseConnect): {
|
|
7
|
+
groups: import("./connect.ts").ConnectGroup[];
|
|
8
|
+
chosen?: {
|
|
9
|
+
row: import("./connect.ts").ConnectRow;
|
|
10
|
+
key?: ReturnType<typeof import("./key.ts").keyView>;
|
|
11
|
+
};
|
|
7
12
|
step: ConnectStep;
|
|
8
13
|
act: (a: ConnectAction) => void;
|
|
9
14
|
pick: (key: string) => void;
|
|
10
15
|
back: () => void;
|
|
11
16
|
/** Pass to `useSignIn` in a sheet keyed by `chosen.row.key`; undefined unless a ready sign-in row is chosen. */
|
|
12
17
|
signIn: import("./useSignIn.ts").UseSignIn | undefined;
|
|
13
|
-
groups: import("./connect.ts").ConnectGroup[];
|
|
14
|
-
chosen?: {
|
|
15
|
-
row: import("./connect.ts").ConnectRow;
|
|
16
|
-
key?: ReturnType<typeof import("./key.ts").keyView>;
|
|
17
|
-
};
|
|
18
18
|
};
|
package/dist/useConnect.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// the chosen sign-in row's options to `useSignIn`. Keys never enter it: the app sends the input to its kit and
|
|
3
3
|
// reports only the result.
|
|
4
4
|
import { useState } from 'react';
|
|
5
|
-
import { connectStep, connectView, signInFor } from
|
|
5
|
+
import { connectStep, connectView, signInFor } from './connect.js';
|
|
6
6
|
export function useConnect({ routes, words, ...o }) {
|
|
7
7
|
const [step, setStep] = useState({ at: 'list' });
|
|
8
8
|
const view = connectView(routes, step, words);
|
package/dist/useKits.d.ts
CHANGED
|
@@ -3,10 +3,6 @@ import { type HerdrSource } from './herdr.ts';
|
|
|
3
3
|
import { type RunSource, type RunWordsOptions } from './run.ts';
|
|
4
4
|
/** One run at a time: `send(message)` streams the reply in; `words` says how a failed run ended. */
|
|
5
5
|
export declare function useRun(source: RunSource, o: RunWordsOptions): {
|
|
6
|
-
send: (message: string, o?: {
|
|
7
|
-
sessionKey?: string;
|
|
8
|
-
}) => void;
|
|
9
|
-
stop: () => void;
|
|
10
6
|
phase: import("./run.ts").RunPhase;
|
|
11
7
|
text: string;
|
|
12
8
|
tools: {
|
|
@@ -15,6 +11,10 @@ export declare function useRun(source: RunSource, o: RunWordsOptions): {
|
|
|
15
11
|
}[];
|
|
16
12
|
tool: string | undefined;
|
|
17
13
|
words: string;
|
|
14
|
+
send: (message: string, o?: {
|
|
15
|
+
sessionKey?: string;
|
|
16
|
+
}) => void;
|
|
17
|
+
stop: () => void;
|
|
18
18
|
};
|
|
19
19
|
/** The approvals waiting for a yes, live; `decide` answers one (it leaves the list when the computer says so). */
|
|
20
20
|
export declare function useApprovals(source: ApprovalsSource & {
|
|
@@ -49,7 +49,6 @@ export declare function useBlocked(source: HerdrSource & {
|
|
|
49
49
|
answer(paneId: string, keys: string[], revision: number): Promise<void>;
|
|
50
50
|
}): {
|
|
51
51
|
blocked: {
|
|
52
|
-
name: string;
|
|
53
52
|
paneId: string;
|
|
54
53
|
workspaceId: string;
|
|
55
54
|
tabId: string;
|
|
@@ -57,6 +56,7 @@ export declare function useBlocked(source: HerdrSource & {
|
|
|
57
56
|
revision: number;
|
|
58
57
|
prompt: string;
|
|
59
58
|
since: number;
|
|
59
|
+
name: string;
|
|
60
60
|
}[];
|
|
61
61
|
answer: (paneId: string, keys: string[], revision: number) => Promise<void>;
|
|
62
62
|
};
|
package/dist/useKits.js
CHANGED
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
// framework-free stores from `@byokit/ui/kits`; pass the same device client each render (e.g. from useMemo),
|
|
3
3
|
// since a new one starts following afresh.
|
|
4
4
|
import { useEffect, useMemo, useSyncExternalStore } from 'react';
|
|
5
|
-
import { approvalsStore } from
|
|
6
|
-
import { agentIn, blockedView, herdrStore, herdrTreeView } from
|
|
7
|
-
import { runStore, runView } from
|
|
5
|
+
import { approvalsStore } from './approvals.js';
|
|
6
|
+
import { agentIn, blockedView, herdrStore, herdrTreeView } from './herdr.js';
|
|
7
|
+
import { runStore, runView } from './run.js';
|
|
8
8
|
const useStore = (s) => useSyncExternalStore(s.subscribe, s.get, s.get);
|
|
9
9
|
/** One run at a time: `send(message)` streams the reply in; `words` says how a failed run ended. */
|
|
10
10
|
export function useRun(source, o) {
|
package/dist/useSignIn.d.ts
CHANGED
|
@@ -21,7 +21,7 @@ export declare function useSignIn({ read, start, cancel, offline: isOffline, ms,
|
|
|
21
21
|
url: string | undefined;
|
|
22
22
|
/** Start again: `{ via: 'code' }` for "Having trouble?", `{ fresh: true }` to pick the account again. */
|
|
23
23
|
start: (body?: {
|
|
24
|
-
via?:
|
|
24
|
+
via?: 'code';
|
|
25
25
|
fresh?: boolean;
|
|
26
26
|
}) => void;
|
|
27
27
|
cancel: () => void;
|
package/dist/useSignIn.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// reports the phase to draw. The app keeps its own look (and its own tab for the provider's page); this is the
|
|
3
3
|
// behaviour every sign-in sheet shares.
|
|
4
4
|
import { useEffect, useState } from 'react';
|
|
5
|
-
import { phaseOf } from
|
|
5
|
+
import { phaseOf } from './phase.js';
|
|
6
6
|
export function useSignIn({ read, start, cancel, offline: isOffline = () => true, ms = 1500, pinned }) {
|
|
7
7
|
const [value, setValue] = useState(null);
|
|
8
8
|
const [offline, setOffline] = useState(false);
|
package/dist/words.json
CHANGED
|
@@ -42,6 +42,7 @@
|
|
|
42
42
|
"key.label.other": "Key",
|
|
43
43
|
"key.entry": "Paste your key. It stays on this device.",
|
|
44
44
|
"key.checking": "Checking your key…",
|
|
45
|
+
"key.workspace": "This key works for more than one workspace. Pick the one to use.",
|
|
45
46
|
"key.ok": "Your key is ready. It is used only when you choose this option.",
|
|
46
47
|
"key.invalid": "This key could not be saved. Check it and try again.",
|
|
47
48
|
"key.notIncluded": "This option is not available here.",
|
|
@@ -55,6 +56,14 @@
|
|
|
55
56
|
"account.room.week": "{left} left this week",
|
|
56
57
|
"account.room.month": "{left} left this month",
|
|
57
58
|
"account.room.tightest": "{left} left for now",
|
|
59
|
+
"account.stale": "{age} (stale)",
|
|
60
|
+
"account.room.resetSince": "Reset since this reading",
|
|
61
|
+
"account.window.resetSince": "{label}: reset since this reading",
|
|
62
|
+
"account.window.session": "Session",
|
|
63
|
+
"account.window.weekly": "Week",
|
|
64
|
+
"account.window.monthly": "Month",
|
|
65
|
+
"account.window.rolling": "Rolling window",
|
|
66
|
+
"account.window.custom": "Limit",
|
|
58
67
|
"picker.auto": "Auto — most room left",
|
|
59
68
|
"picker.out.state": "Sign in first",
|
|
60
69
|
"picker.out.resting": "Taking a break",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@byokit/ui",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.0",
|
|
4
4
|
"description": "Headless sign-in, pairing and runtime-kit view state for any UI, plus plain-words copy.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"type": "module",
|
|
@@ -62,7 +62,7 @@
|
|
|
62
62
|
}
|
|
63
63
|
},
|
|
64
64
|
"devDependencies": {
|
|
65
|
-
"@byokit/accounts": "0.
|
|
65
|
+
"@byokit/accounts": "0.24.3",
|
|
66
66
|
"@types/react": "^19.3.0",
|
|
67
67
|
"@types/react-test-renderer": "^19.3.0",
|
|
68
68
|
"react": "^19.3.0",
|