@shardflux/cli 0.6.1 → 0.7.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 +79 -24
- package/README.md +105 -67
- package/dist/account-args.js +1 -1
- package/dist/account-commands.js +10 -3
- package/dist/args.d.ts +1 -1
- package/dist/args.js +45 -22
- package/dist/browser.js +1 -1
- package/dist/commands.d.ts +2 -2
- package/dist/commands.js +81 -17
- package/dist/errors.d.ts +3 -3
- package/dist/errors.js +16 -9
- package/dist/format.d.ts +22 -10
- package/dist/format.js +64 -13
- package/dist/http.d.ts +1 -17
- package/dist/http.js +6 -24
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/main.js +21 -21
- package/dist/template-yaml.js +1 -1
- package/dist/timing.d.ts +12 -0
- package/dist/timing.js +46 -0
- package/dist/update-check.js +1 -1
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,7 +1,65 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
-
Every command and option the README shows is available from the version named here.
|
|
4
|
-
|
|
3
|
+
Every command and option the README shows is available from the version named here. Breaking changes ship in minor
|
|
4
|
+
releases and are marked **Breaking**.
|
|
5
|
+
|
|
6
|
+
## 0.6.2
|
|
7
|
+
|
|
8
|
+
Needs `@shardflux/sdk` 0.11.1 or later.
|
|
9
|
+
|
|
10
|
+
### The signup trial: when it ends, and it is never for sale
|
|
11
|
+
|
|
12
|
+
New organizations can start on a trial: 60 days at Developer limits, no card. The API gives the plan in force an end
|
|
13
|
+
(`plan.ends_at`) and the usage period of a trial its own window (`period.source` `grant`).
|
|
14
|
+
|
|
15
|
+
- `shard billing status` shows the end: `plan trial, ends 2026-11-29 14:03:00Z, then free (trial, catalog ...)`, and
|
|
16
|
+
on a trial the next step is `keep these limits after the trial: shard billing upgrade developer` (a subscription
|
|
17
|
+
outranks the trial and ends it). A design-partner plan shows its end the same way. Plans without an end read as
|
|
18
|
+
before.
|
|
19
|
+
- `shard billing plans` lists the public plans only: the trial and the design-partner plan are granted, never bought,
|
|
20
|
+
and are left out (also of the purchasable plans `billing upgrade` names). `--json` still prints the API's catalog.
|
|
21
|
+
- `shard usage`: a trial's period reads `<start> .. <end> (the trial; then free)`, and a used-up trial allowance
|
|
22
|
+
`yes (the trial ends; the organization is back on free)` instead of "new opens/resumes are refused".
|
|
23
|
+
|
|
24
|
+
### Wording: help, hints and messages say what to do, without internals (no behaviour change)
|
|
25
|
+
|
|
26
|
+
- `shard feedback` goes to the Shardflux team: `Sent to the Shardflux team (feedback <id>). Thank you.`, and the help
|
|
27
|
+
asks agents to also pass on what their user asks for (a capability, an option or a smoother workflow) and their
|
|
28
|
+
ideas. The help examples are a `template_not_found` bug report and an idea; `--error-code` shows
|
|
29
|
+
`e.g. template_not_found`.
|
|
30
|
+
- `capacity_unavailable` hint: `nothing was started; run the same command again`. A wait that times out on a queued
|
|
31
|
+
start says `it stays queued server side until <deadline_at> and fails with capacity_unavailable if it has not
|
|
32
|
+
started by then`.
|
|
33
|
+
- `no_execution_host`: `the execution cannot be placed right now, also after retries with the same execution id;
|
|
34
|
+
nothing ran. Retry`. `host_capacity`: `the workspace cannot be woken right now and the call did not run; retry in a
|
|
35
|
+
few seconds`.
|
|
36
|
+
- `host_feature_unavailable`: `files search is not available for this workspace (retrying does not help); search with
|
|
37
|
+
a command instead: ...` (the same for `files patch` and other calls).
|
|
38
|
+
- An interrupted file-first `ws exec` says `(an execution runs to completion)`; `mode_not_available` drops "yet";
|
|
39
|
+
`--open` no longer says "best effort"; `templates init --help` no longer names an internal document.
|
|
40
|
+
|
|
41
|
+
## 0.7.0 (release candidate)
|
|
42
|
+
|
|
43
|
+
Completed exec output streams are drained before releasing their HTTP connections, with a bounded cleanup if a peer does not close.
|
|
44
|
+
|
|
45
|
+
Uses SDK 0.12.0 and its pooled transport. Adds --labels/--idle-policy to open, --labels to list, ws labels, ws idle, ws exec-start --stdin-open and ws exec-input --offset. Protocol-error JSON includes source. Resume recovers failed workspaces; completed deletion permits key reuse.
|
|
46
|
+
|
|
47
|
+
Requires the QM integration backend release for labels, failed recovery, key reuse and pipe stdin. No production deployment has occurred from this branch.
|
|
48
|
+
|
|
49
|
+
### Instant suspend: durable storage
|
|
50
|
+
|
|
51
|
+
- `shard ws suspend --wait` still returns when the suspend succeeds (sealed on its host); a finished suspend or fork
|
|
52
|
+
now prints `durable: yes (<n> ms after the suspend)` or `durable: in progress ...` when the result says so.
|
|
53
|
+
- `shard ws suspend --durable`: waits until `result.durable` is true (implies `--wait`, shares `--timeout`). A copy
|
|
54
|
+
that cannot be made exits 6 with code `durability_lost` (operation id, `details.state` `lost`, `details.reason`); a
|
|
55
|
+
timeout exits 5 with `details.durable` false and `details.state` `pending`. `--durable` with `--when-idle` or
|
|
56
|
+
`--cancel-when-idle` is a usage error.
|
|
57
|
+
- `shard operations wait <id> --durable`, and a `durable` line in `operations get|wait` for suspends and forks.
|
|
58
|
+
- `--timing --json`: `server` gains `durable`, `suspend_path`, `durability` and `lost_suspend`.
|
|
59
|
+
- A resume (or a command's wake) whose result carries `lost_suspend` prints a note on stderr naming the restored
|
|
60
|
+
checkpoint and its time.
|
|
61
|
+
- A suspend-when-idle canceled `workspace_active` says the workspace was in use and keeps running.
|
|
62
|
+
- The `ws suspend` summary no longer says "durable checkpoint".
|
|
5
63
|
|
|
6
64
|
## 0.6.1
|
|
7
65
|
|
|
@@ -19,9 +77,9 @@ range is still exit 2 before any request: `--when-idle must be between 0s and 1h
|
|
|
19
77
|
|
|
20
78
|
Needs `@shardflux/sdk` 0.11.0 or later.
|
|
21
79
|
|
|
22
|
-
### A resume that restarted processes says so (cold boot
|
|
80
|
+
### A resume that restarted processes says so (cold boot)
|
|
23
81
|
|
|
24
|
-
|
|
82
|
+
After a platform runtime change, the cell resumes
|
|
25
83
|
the workspace by booting its saved disk (a cold boot), automatically, also when a command wakes it. Files are as of the
|
|
26
84
|
suspend; every process was restarted.
|
|
27
85
|
|
|
@@ -87,7 +145,7 @@ cell had ended the session `failed_to_start` (`working directory "app" is not a
|
|
|
87
145
|
`overage_paused` (a payment is past due: update the payment method, `shard billing portal --open`). The exit code
|
|
88
146
|
stays 1.
|
|
89
147
|
|
|
90
|
-
### Suspend when idle
|
|
148
|
+
### Suspend when idle
|
|
91
149
|
|
|
92
150
|
- `shard workspaces suspend <id|key> --when-idle <duration>` (30s to 1h): the workspace is suspended once it has been
|
|
93
151
|
idle that long, counted from the later of its last work and the request (suspend when idle, for the end of an agent
|
|
@@ -95,11 +153,11 @@ cell had ended the session `failed_to_start` (`working directory "app" is not a
|
|
|
95
153
|
`--cancel-when-idle` cancels it. `--json` prints `{workspace, operation, suspend_request}`.
|
|
96
154
|
- `shard workspaces get` shows a pending request (`suspend when idle after N s idle, not before ...`).
|
|
97
155
|
|
|
98
|
-
## 0.5.0
|
|
156
|
+
## 0.5.0
|
|
99
157
|
|
|
100
158
|
Needs `@shardflux/sdk` 0.9.0 or later.
|
|
101
159
|
|
|
102
|
-
### File search, patches and revisions
|
|
160
|
+
### File search, patches and revisions
|
|
103
161
|
|
|
104
162
|
- `shard files search <id|key> <path> <pattern>`: content search under a directory (or in one file), printed
|
|
105
163
|
grep-style (`path:line:column: text`, context lines as `path-line- text`). `--regex` (RE2), `-i`/`--ignore-case`,
|
|
@@ -115,20 +173,20 @@ Needs `@shardflux/sdk` 0.9.0 or later.
|
|
|
115
173
|
- Hints for the new refusals: `revision_mismatch` (exit 1) names the current revision; `edit_not_found` and
|
|
116
174
|
`edit_ambiguous` (exit 2, like any `validation_failed`) name the `--old` by position; `host_capacity` says to retry
|
|
117
175
|
shortly (reads, searches and patches already retry it after `Retry-After`).
|
|
118
|
-
- A workspace
|
|
176
|
+
- A workspace without search and patches: `files
|
|
119
177
|
search` and `files patch` fail at once with 409 `conflict` `host_feature_unavailable` (exit 1, not retried, no
|
|
120
178
|
wake), with a hint naming `details.feature` and another way to do it now (`shard ws exec <id|key> -- grep -rn ...`
|
|
121
|
-
for a search; `files read` then `files write` for a patch)
|
|
122
|
-
Such a
|
|
179
|
+
for a search; `files read` then `files write` for a patch).
|
|
180
|
+
Such a workspace returns no revisions (`files stat --revision` prints none).
|
|
123
181
|
- All three take `--timing`. `files patch` wakes a suspended workspace like `files write`; `files search` and
|
|
124
182
|
`files stat` read its disk (below).
|
|
125
183
|
- `files read|ls|stat|search` of a suspended workspace are answered from its disk without resuming it (the state at
|
|
126
184
|
suspension), also on the first command after the suspend: every `shard` run fetches a new tool token, which the API
|
|
127
185
|
refused for a suspended workspace, so these commands used to resume it. Needs `@shardflux/sdk` 0.9.0 and an API
|
|
128
|
-
that issues tool tokens for suspended workspaces
|
|
186
|
+
that issues tool tokens for suspended workspaces; with an older API they resume it as before.
|
|
129
187
|
Every other command still resumes it.
|
|
130
188
|
|
|
131
|
-
### File-first workspaces
|
|
189
|
+
### File-first workspaces
|
|
132
190
|
|
|
133
191
|
- `shard workspaces open --mode processful|file-first` (`file_first` too): a file-first workspace is a versioned file
|
|
134
192
|
tree with no VM between commands. It is ready at once, never suspended and always persistent. Without `--mode` a new
|
|
@@ -165,7 +223,7 @@ Needs `@shardflux/sdk` 0.9.0 or later.
|
|
|
165
223
|
`host_restarted`, `tree_moved`, ...).
|
|
166
224
|
- The error line names `execution_id=` when the error is about an execution.
|
|
167
225
|
|
|
168
|
-
### Waking a suspended workspace is one request
|
|
226
|
+
### Waking a suspended workspace is one request
|
|
169
227
|
|
|
170
228
|
- Through `@shardflux/sdk` 0.9.0: a command on a suspended workspace (`ws exec`, `files ...`, `ws changes`) wakes it
|
|
171
229
|
with one held resume that returns the running workspace and the CLI's tool token, then runs (refused call, resume,
|
|
@@ -173,10 +231,9 @@ Needs `@shardflux/sdk` 0.9.0 or later.
|
|
|
173
231
|
- `--timing` shows the wake as one `request` phase `(held)`; a wake that runs out of time shows the hold, then the
|
|
174
232
|
states it saw after it (`request 1.00 s (held) → queued …`).
|
|
175
233
|
- `shard workspaces resume --wait` is one held request; its tool token is attributed to the CLI's agent label.
|
|
176
|
-
### The account plane
|
|
234
|
+
### The account plane
|
|
177
235
|
|
|
178
|
-
Needs `@shardflux/sdk` 0.9.0 or later (`ShardfluxAccount`, `checkClientVersion`) and an API with CLI sessions
|
|
179
|
-
(contracts §30).
|
|
236
|
+
Needs `@shardflux/sdk` 0.9.0 or later (`ShardfluxAccount`, `checkClientVersion`) and an API with CLI sessions.
|
|
180
237
|
|
|
181
238
|
### Everything the web app does, from a terminal (docs/progress/account-cli.md §5)
|
|
182
239
|
|
|
@@ -247,10 +304,10 @@ unchanged and still stores nothing.
|
|
|
247
304
|
- The top help starts with the no-browser path and groups commands by the credential they use; `shard <group>`
|
|
248
305
|
and `shard auth totp` (a sub-group) list their commands.
|
|
249
306
|
|
|
250
|
-
### Feedback straight to the
|
|
307
|
+
### Feedback straight to the Shardflux team (needs an API with POST /v1/feedback)
|
|
251
308
|
|
|
252
309
|
- `shard feedback [--category bug|confusing|missing|idea|praise|other] [--workspace W] [--request-id ID]
|
|
253
|
-
[--error-code CODE] [--command TEXT] [--from-file F|-] <message...>` sends feedback to the Shardflux
|
|
310
|
+
[--error-code CODE] [--command TEXT] [--from-file F|-] <message...>` sends feedback to the Shardflux team by
|
|
254
311
|
email. The message is the remaining words (no quotes needed unless the shell needs them) or `--from-file` (`-`:
|
|
255
312
|
standard input, for logs). It is checked before any request (1-8000 characters, a known category, the context
|
|
256
313
|
bounds). The context carries `client: shard-cli/0.5.0` and, unless it is the default `cli`, the agent label as
|
|
@@ -260,8 +317,7 @@ unchanged and still stores nothing.
|
|
|
260
317
|
continue or to email shardflux@heliosone.fi.
|
|
261
318
|
- `shard --help` opens with a Feedback section, and `shard feedback --help` explains when to use each category: coding
|
|
262
319
|
agents are asked to send short feedback while they work, the moment something fails, confuses or is missing, and to
|
|
263
|
-
pass on (paraphrased, without private data) what their user
|
|
264
|
-
do, telling the user they sent it.
|
|
320
|
+
pass on (paraphrased, without private data) what their user asks for, telling the user they sent it.
|
|
265
321
|
- A failure ends with
|
|
266
322
|
`feedback: shard feedback --category bug --request-id <id> --error-code <code> "<what you expected>"`; with `--json`
|
|
267
323
|
the error object gains a sibling `"feedback"` field holding that command. Existing fields are unchanged. Not for
|
|
@@ -280,7 +336,7 @@ exports type-check without casts), and the CLI moves to it so `shardflux` instal
|
|
|
280
336
|
|
|
281
337
|
Needs `@shardflux/sdk` 0.7.0 or later. New dependency: `yaml` (template.yaml).
|
|
282
338
|
|
|
283
|
-
### Template editor
|
|
339
|
+
### Template editor
|
|
284
340
|
|
|
285
341
|
- `shard templates build <file> [--slug] [--display-name] [--description] [--publish] [--acknowledge PATH]... [--wait]
|
|
286
342
|
[--timeout] [--timing]`: builds a template from template.yaml. Local `from` files and folders are uploaded (folders
|
|
@@ -308,13 +364,12 @@ Needs `@shardflux/sdk` 0.7.0 or later. New dependency: `yaml` (template.yaml).
|
|
|
308
364
|
|
|
309
365
|
Needs `@shardflux/sdk` 0.6.2 or later.
|
|
310
366
|
|
|
311
|
-
The API no longer lets a start (open, resume, fork) wait in `capacity_pending` forever: one
|
|
312
|
-
15 minutes after it began fails with `capacity_unavailable` (retryable; nothing was started, a suspended workspace
|
|
367
|
+
The API no longer lets a start (open, resume, fork) wait in `capacity_pending` forever: one still queued 15 minutes after it began fails with `capacity_unavailable` (retryable; nothing was started, a suspended workspace
|
|
313
368
|
stays suspended).
|
|
314
369
|
|
|
315
370
|
- A failed operation's error has `retryable` (the operation error's own flag): `retryable=true|false` in the error line,
|
|
316
371
|
`"retryable"` in the `--json` error document, next to `details.error_code`. `details.reason` carries the operation
|
|
317
|
-
error's reason (for `capacity_unavailable`,
|
|
372
|
+
error's reason (for `capacity_unavailable`, e.g. `no_ready_hosts`), printed after the message.
|
|
318
373
|
- A retryable failure gets a hint to retry later. Exit codes are unchanged (6 for any failed operation); `shard` does
|
|
319
374
|
not retry.
|
|
320
375
|
- A `--timeout` that ends while the start waits for capacity names the time it gives up (the SDK's message).
|
package/README.md
CHANGED
|
@@ -8,8 +8,8 @@ invitations and keys, buy or change a plan, export data and delete an account. B
|
|
|
8
8
|
[`@shardflux/sdk`](https://www.npmjs.com/package/@shardflux/sdk), so it gets the SDK's retries,
|
|
9
9
|
idempotency keys, operation polling and tool-token handling.
|
|
10
10
|
|
|
11
|
-
> **
|
|
12
|
-
>
|
|
11
|
+
> **Compatibility.** The API is versioned (`/v1`). Breaking changes ship only in minor releases and are marked
|
|
12
|
+
> **Breaking** in the changelog.
|
|
13
13
|
|
|
14
14
|
Requires Node.js 24 or later.
|
|
15
15
|
|
|
@@ -63,21 +63,20 @@ shard login # verify the key: organization, pr
|
|
|
63
63
|
|
|
64
64
|
## Feedback: agents, use this while you work
|
|
65
65
|
|
|
66
|
-
**(0.5.0+)** `shard feedback` sends a message straight to the Shardflux
|
|
66
|
+
**(0.5.0+)** `shard feedback` sends a message straight to the Shardflux team, who read every one. If you are a
|
|
67
67
|
coding agent (Claude Code, Codex, Cursor, ...) driving `shard`, use it actively while you work, not once at the end.
|
|
68
68
|
Send a short message the moment:
|
|
69
69
|
|
|
70
70
|
- something fails unexpectedly (`--category bug`),
|
|
71
71
|
- an error, doc, name or output is confusing (`--category confusing`),
|
|
72
72
|
- a capability, option or template you need is missing (`--category missing`),
|
|
73
|
-
-
|
|
74
|
-
- your user
|
|
75
|
-
|
|
76
|
-
- your user asked for something Shardflux could not do, or made awkward.
|
|
73
|
+
- you needed a workaround,
|
|
74
|
+
- your user asks for a capability, an option or a smoother workflow: paraphrase it, with what they were trying to do,
|
|
75
|
+
- your user has an idea for how Shardflux could fit their work better.
|
|
77
76
|
|
|
78
77
|
Short and frequent beats polished: what you ran, what happened, what you expected. No need to ask first, but tell your
|
|
79
78
|
user you sent it. Leave out private data about the user and secrets or code they did not mean to share; paraphrase,
|
|
80
|
-
never paste transcripts. Pass the request id and error code from the error so the
|
|
79
|
+
never paste transcripts. Pass the request id and error code from the error so the team can find the logs. A failed
|
|
81
80
|
`shard` command ends with a ready-made line to fill in:
|
|
82
81
|
|
|
83
82
|
```text
|
|
@@ -86,11 +85,11 @@ feedback: shard feedback --category bug --request-id req-2b9d4f6a8c0e4a1b3d5f7e9
|
|
|
86
85
|
```
|
|
87
86
|
|
|
88
87
|
```sh
|
|
89
|
-
shard feedback --category bug --request-id req-5c7744b2bb5c457b86b76101 --error-code
|
|
90
|
-
"ws open
|
|
91
|
-
shard feedback --category
|
|
92
|
-
"user
|
|
93
|
-
shard feedback --category
|
|
88
|
+
shard feedback --category bug --request-id req-5c7744b2bb5c457b86b76101 --error-code template_not_found \
|
|
89
|
+
"ws open --template python-node failed; expected a suggestion of the closest slug"
|
|
90
|
+
shard feedback --category idea \
|
|
91
|
+
"user would like shard ws open to remember the last template they used"
|
|
92
|
+
shard feedback --category praise forking a workspace with its dev server still running is exactly what we needed
|
|
94
93
|
npm test 2>&1 | tail -n 60 | shard feedback --category bug --workspace acme/demo --from-file -
|
|
95
94
|
```
|
|
96
95
|
|
|
@@ -131,7 +130,7 @@ terminal, `--json` on every command, secrets only on standard input, and documen
|
|
|
131
130
|
authentication; valid 10 minutes). Without a terminal `shard` does not ask: the command fails with
|
|
132
131
|
`step_up_required` (exit 4) and the hint names this command.
|
|
133
132
|
7. **Feedback:** send `shard feedback` as you work, the moment something fails, confuses you or is
|
|
134
|
-
missing, or your user
|
|
133
|
+
missing, or your user asks for an improvement (see [Feedback](#feedback-agents-use-this-while-you-work)).
|
|
135
134
|
|
|
136
135
|
What stays human: reading the verification email, entering a card in Stripe Checkout, and the
|
|
137
136
|
authenticator app's codes.
|
|
@@ -228,7 +227,7 @@ the workspace commands instead of printing it. Revoking the saved key also remov
|
|
|
228
227
|
|
|
229
228
|
```sh
|
|
230
229
|
shard billing plans # public: no sign-in needed
|
|
231
|
-
shard billing status # plan, billing state, period end, pending checkout
|
|
230
|
+
shard billing status # plan (a trial with its end), billing state, period end, pending checkout
|
|
232
231
|
shard billing upgrade <plan> [--open] [--wait] [--timeout 15m]
|
|
233
232
|
shard billing portal [--open] # plan changes, payment methods, invoices, cancellation
|
|
234
233
|
shard billing invoices [--all]
|
|
@@ -241,12 +240,17 @@ shard billing overage off # turn it off (always allow
|
|
|
241
240
|
|
|
242
241
|
`billing upgrade` checks the plan against the public catalog (an unknown one lists the purchasable
|
|
243
242
|
plans), starts Stripe Checkout and prints its URL: a person pays there. `--open` also opens it in the
|
|
244
|
-
default browser (`$BROWSER`, else `xdg-open`, `open` or `start
|
|
243
|
+
default browser (`$BROWSER`, else `xdg-open`, `open` or `start`). The API activates the
|
|
245
244
|
plan only when Stripe confirms the payment, so `--wait` polls until the subscription is active (exit
|
|
246
245
|
0), the checkout expires or is canceled (exit 6), or `--timeout` runs out (exit 5; the checkout stays
|
|
247
246
|
open). An organization that already has a subscription changes plans in the billing portal: the
|
|
248
247
|
command prints the portal URL instead (exit 0).
|
|
249
248
|
|
|
249
|
+
On the signup trial (60 days at Developer limits, no card), `billing status` shows when it ends and
|
|
250
|
+
what follows (0.6.2+): `plan trial, ends 2026-11-29 14:03:00Z, then free (trial, catalog ...)`, then
|
|
251
|
+
`keep these limits after the trial: shard billing upgrade developer`. A subscription outranks the
|
|
252
|
+
trial and ends it. The trial is granted, never bought, so `billing plans` leaves it out.
|
|
253
|
+
|
|
250
254
|
`billing overage` shows and changes opt-in overage (owners and billing members). With it on,
|
|
251
255
|
workspaces keep opening and running past the CPU-hours and RAM GiB-hours allowances, and the usage
|
|
252
256
|
past them is charged on the next invoice until the charges reach the spend cap. The cap is per
|
|
@@ -261,7 +265,7 @@ already charged this period (`spend_cap_below_charges`); a plan without overage
|
|
|
261
265
|
```text
|
|
262
266
|
$ shard billing overage on --cap 9
|
|
263
267
|
Acme: overage is on, spend cap $9.00 per billing period ($1.00 to $9.00, the plan price).
|
|
264
|
-
Rates past the allowances: $0.
|
|
268
|
+
Rates past the allowances: $0.03 per RAM GiB-hour, $0.12 per CPU-hour, charged on the next invoice (this period: shard usage).
|
|
265
269
|
Saved (policy version 1).
|
|
266
270
|
```
|
|
267
271
|
|
|
@@ -369,9 +373,7 @@ shows the status; `shard version --check` asks now (`--json`: `{"cli", "sdk", "u
|
|
|
369
373
|
| `login`, `whoami` | Show the principal behind the project key (`SHARDFLUX_API_KEY`, else the saved one). |
|
|
370
374
|
| `version [--check]` | Print the CLI and SDK versions and the update status (`--check` asks the API now). |
|
|
371
375
|
| `usage [--org <id>] [--estimate \| --series \| --workspace <id\|key>] [--from T] [--to T] [--granularity hour\|day] [--meter M]` | Usage summary for the current period: plan, meters and allowances. `--estimate`: the bill so far and projected allowance use; `--series`: usage over time; `--workspace`: one workspace's usage over time (0.5.0+). The summary includes the [overage](#usage-and-overage) block (0.5.1+). |
|
|
372
|
-
|
|
373
|
-
| `feedback [--category C] [--workspace W] [--request-id ID] [--error-code CODE] [--command TEXT] [--from-file F\|-] <message...>` | Send feedback straight to the Shardflux founder (0.5.0+). See [Feedback](#feedback-agents-use-this-while-you-work). |
|
|
374
|
-
| `usage [--org <id>] [--estimate \| --series \| --workspace <id\|key>] [--from T] [--to T] [--granularity hour\|day] [--meter M]` | Usage summary for the current period: plan, meters and allowances. `--estimate`: the bill so far and projected allowance use; `--series`: usage over time; `--workspace`: one workspace's usage over time (0.5.0+). |
|
|
376
|
+
| `feedback [--category C] [--workspace W] [--request-id ID] [--error-code CODE] [--command TEXT] [--from-file F\|-] <message...>` | Send feedback straight to the Shardflux team (0.5.0+). See [Feedback](#feedback-agents-use-this-while-you-work). |
|
|
375
377
|
| `workspaces open <key> --template <slug> [--secret NAME]... [--input NAME=value]... [--input-file F] [--lifetime persistent\|session] [--mode processful\|file-first] [--cpu-millis N --memory-mib N --disk-gib N] [--no-wait] [--timeout 5m] [--timing]` | Open by key. Creates the workspace on first use and reconnects or resumes it afterwards, never resetting it. Waits until it is ready (the template's start commands and services included) unless you pass `--no-wait`. `--secret` binds secret names (replacing the binding of an existing workspace). `--input` (0.4.0+) passes the template's text inputs (replacing those of an existing workspace); `--input-file` reads `NAME=value` lines or a JSON object. `--lifetime session`: the workspace is discarded when the session ends (`workspaces close` or the idle timeout), and the key then opens a new workspace. `--mode file-first` (0.5.0+) opens a [file-first workspace](#file-first-workspaces); the default is processful for a new key and the stored mode for an existing one. |
|
|
376
378
|
| `workspaces list [--state S] [--prefix P] [--lifetime persistent\|session\|any] [--purpose standard\|template_draft\|template_test\|any] [--include-deleted] [--all] [--limit N] [--cursor C]` | One page, or every page with `--all`. The next cursor is printed on stderr. By default only persistent standard workspaces are listed. A file-first workspace's state reads `running (file-first)` (0.5.0+). |
|
|
377
379
|
| `workspaces get <id\|key>` | One workspace (deleted ones included), with the startup of its template's start commands and services (0.4.0+): a failed step shows its exit code, reason and output tail. Its mode, and a file-first workspace's tree revision (0.5.0+). |
|
|
@@ -385,9 +387,10 @@ shows the status; `shard version --check` asks now (`--json`: `{"cli", "sdk", "u
|
|
|
385
387
|
| `files search <id\|key> <path> <pattern> [--regex] [-i\|--ignore-case] [--include G]... [--exclude G]... [--max N]` | Search file contents under a directory (or in one file; gitignore-style globs): `path:line:column: text` per match (0.5.0+). |
|
|
386
388
|
| `files patch <id\|key> <path> (--old T --new T)... [--replace-all] \| --content-file F\|- [--expected-revision R] [--if-revision N]` | Replace exact text (each `--old` must occur once unless `--replace-all`), or the whole content, atomically; `R` is a revision from `files stat --revision` or `absent` (0.5.0+). `--if-revision` (0.5.0+): file-first workspaces only. |
|
|
387
389
|
| `workspaces suspend\|resume <id\|key> [--wait] [--timeout T] [--timing]` | Lifecycle operation. Returns immediately unless you pass `--wait`. |
|
|
390
|
+
| `workspaces suspend <id\|key> --durable [--timeout T]` | (0.7.0+) Suspend and wait until the copy is in durable storage. See "Durable storage". |
|
|
388
391
|
| `workspaces suspend <id\|key> --when-idle D` / `--cancel-when-idle` | (0.5.1+) Suspend once the workspace has been idle for `D` (0 to 1h; `0` = as soon as it is idle, 0.6.1+), or cancel that. See "Suspend when idle". |
|
|
389
392
|
| `workspaces fork <id\|key> <new-key> [caps] [--wait]` | Fork into a new key. |
|
|
390
|
-
| `workspaces delete <id\|key> --yes [--wait]` | Delete the workspace. Tool access ends at once.
|
|
393
|
+
| `workspaces delete <id\|key> --yes [--wait]` | Delete the workspace. Tool access ends at once. After deletion finishes, the key can open a new workspace ID. |
|
|
391
394
|
| `workspaces close <id\|key> [--wait]` | End a session workspace now: it is deleted, and the key then opens a new workspace. A persistent workspace is refused (`not_session`). |
|
|
392
395
|
| `workspaces reset <id\|key> --yes [--wait]` | Layered workspaces: wipe every change and restart on the template. The previous state stays restorable for 7 days. |
|
|
393
396
|
| `workspaces save-as-template <id\|key> --template <slug> [--display-name N] [--description T] [--checkpoint ID] [--default-lifetime L] [--default-idle-timeout D] [--acknowledge PATH]... [--no-auto-publish] [--wait]` | Save a layered workspace as the next version of an organization template. `--wait` follows the build. |
|
|
@@ -504,8 +507,8 @@ A /home/user/app/out.txt
|
|
|
504
507
|
|
|
505
508
|
- **Exit code**: the command's own once it ran to its end: 124 if it timed out (`--timeout`), 128+N if a signal N
|
|
506
509
|
killed it. An execution that `failed` (it could not run the command, e.g. `exec_failed_to_start`) or was `lost`
|
|
507
|
-
(
|
|
508
|
-
|
|
510
|
+
(see `details.reason`) published nothing and exits 6. The error names the reason and says `retryable=true|false`;
|
|
511
|
+
running it again needs a new `--execution-id`.
|
|
509
512
|
- **Output** is printed when the command ended, not streamed: stdout and stderr byte for byte, also when they are not
|
|
510
513
|
UTF-8. `--output-limit <bytes>` keeps at most that much of each (default 1 MiB, at most 16 MiB). A cut stream is
|
|
511
514
|
noted on stderr.
|
|
@@ -521,13 +524,13 @@ A /home/user/app/out.txt
|
|
|
521
524
|
with a letter or digit; default a fresh `ex-<uuid>`). The same id with the same command returns the recorded result
|
|
522
525
|
(`replayed`) instead of running it twice, so a script can repeat the call safely; the same id with another command
|
|
523
526
|
is refused (`execution_id_reused`). `shard` re-sends the request with the same id after a dropped connection and
|
|
524
|
-
after `no_execution_host` (
|
|
525
|
-
another execution holds the workspace (`execution_in_progress`).
|
|
526
|
-
- **Ctrl-C**: an execution
|
|
527
|
-
result later:
|
|
527
|
+
after `no_execution_host` (the execution cannot be placed right now; `Retry-After`, at most 5 times), and waits
|
|
528
|
+
within `--wake-timeout` while another execution holds the workspace (`execution_in_progress`).
|
|
529
|
+
- **Ctrl-C**: an execution runs to completion. Ctrl-C stops waiting (exit 130) and prints the command that fetches
|
|
530
|
+
the result later:
|
|
528
531
|
|
|
529
532
|
```text
|
|
530
|
-
error: Interrupted; execution build-42 keeps running server side if it started (an execution
|
|
533
|
+
error: Interrupted; execution build-42 keeps running server side if it started (an execution runs to completion). [code=interrupted execution_id=build-42]
|
|
531
534
|
hint: fetch its result later with: shard executions get acme/agent-7 build-42
|
|
532
535
|
```
|
|
533
536
|
- **`shard executions get <id|key> <execution-id> [--wait D]`** (also `shard ws executions get`): prints the output and
|
|
@@ -537,9 +540,9 @@ A /home/user/app/out.txt
|
|
|
537
540
|
without sending them (`not_supported_for_mode`, exit 1, with a hint). Only paths under `/home/user` exist
|
|
538
541
|
(`outside_tree_root`). `--mode file-first` with `--lifetime session` is a usage error (exit 2), and so are
|
|
539
542
|
`--execution-id`, `--output-limit` and `--if-revision` on a processful workspace.
|
|
540
|
-
- **Opening**: reopening a key with the other mode is `mode_mismatch` (exit 1);
|
|
541
|
-
|
|
542
|
-
|
|
543
|
+
- **Opening**: reopening a key with the other mode is `mode_mismatch` (exit 1); an account without file-first
|
|
544
|
+
workspaces gets `mode_not_available` (exit 2); a template version without layered disks `layout_unsupported`
|
|
545
|
+
(exit 1). Each comes with a hint.
|
|
543
546
|
|
|
544
547
|
### Tree revisions
|
|
545
548
|
|
|
@@ -566,7 +569,7 @@ API is waited for as before).
|
|
|
566
569
|
|
|
567
570
|
A file-first workspace (0.5.0+) is never suspended, so none of this applies to it.
|
|
568
571
|
|
|
569
|
-
`files read|ls|stat|search` of a suspended workspace
|
|
572
|
+
`files read|ls|stat|search` of a suspended workspace are answered from its saved disk
|
|
570
573
|
without waking it (the state at suspension); `files search` then notes it on stderr (`served_from: "disk"` with
|
|
571
574
|
`--json`).
|
|
572
575
|
|
|
@@ -575,13 +578,15 @@ without waking it (the state at suspension); `files search` then notes it on std
|
|
|
575
578
|
is still queued after 120000 ms`). The operation continues server side:
|
|
576
579
|
`shard operations wait <id>` keeps waiting.
|
|
577
580
|
- A resume or open that fails exits 6.
|
|
581
|
+
- `--no-wake` (or `SHARDFLUX_NO_WAKE=1`) turns this off. A workspace that is not running is then
|
|
582
|
+
refused at once (exit 1, `workspace_not_running`).
|
|
578
583
|
|
|
579
|
-
**
|
|
580
|
-
|
|
581
|
-
workspace
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
584
|
+
**Detecting a cold resume (0.6.0+).** A resume restores memory and running processes. After a platform runtime
|
|
585
|
+
update, a resume can boot from the saved disk instead of restoring memory (a cold boot), also when a command wakes the
|
|
586
|
+
workspace; check `memory_restored`. The command still runs with the files as of the suspend, and processes start
|
|
587
|
+
fresh, as after a reboot: start dev servers and background jobs again. `shard` then prints one line on stderr after
|
|
588
|
+
the output (also with `--json`, except on a failure, whose stderr is only the error document), whether or not you
|
|
589
|
+
pass `--timing`:
|
|
585
590
|
|
|
586
591
|
```text
|
|
587
592
|
note: workspace 01a0e5a8-3edd-74ba-b489-d62b8925e342 resumed from its saved disk; running processes were restarted (runtime_changed)
|
|
@@ -603,7 +608,6 @@ shard ws suspend acme/demo --cancel-when-idle
|
|
|
603
608
|
```
|
|
604
609
|
|
|
605
610
|
- `--when-idle 0` (0.6.1+) suspends the workspace as soon as it is idle (a few seconds after its last work).
|
|
606
|
-
|
|
607
611
|
- The idle time counts from the later of the workspace's last work and the request.
|
|
608
612
|
- A command still running, an attached stream or a keepalive postpones the suspend until the duration after it ends.
|
|
609
613
|
- The next tool call on the workspace (the next turn) or a resume cancels the request. Repeating replaces it.
|
|
@@ -613,22 +617,20 @@ shard ws suspend acme/demo --cancel-when-idle
|
|
|
613
617
|
workspace that is not running is refused with `conflict` (`not_running`, exit 1), and a file-first workspace (never
|
|
614
618
|
suspended) with `not_supported_for_mode` (exit 1).
|
|
615
619
|
|
|
616
|
-
##
|
|
620
|
+
## Start deadlines
|
|
617
621
|
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
622
|
+
A queued open, resume or fork (`capacity_pending`) has a deadline 15 minutes after it was created.
|
|
623
|
+
If `--timeout` ends first, the timeout error names the deadline. A start still pending at the
|
|
624
|
+
deadline fails with `capacity_unavailable`: nothing was started, and a suspended workspace stays
|
|
625
|
+
suspended. `shard` exits 6 as for any failed operation, and the error says `retryable=true` (with
|
|
626
|
+
`--json`, `"retryable": true`) with a hint to retry:
|
|
623
627
|
|
|
624
628
|
```text
|
|
625
629
|
error: Operation 01a0df37-b3a9-7a14-a3e7-11395c349c39 (open) failed: capacity_unavailable (no_ready_hosts) [code=operation_failed operation_id=01a0df37-b3a9-7a14-a3e7-11395c349c39 retryable=true]
|
|
626
|
-
hint:
|
|
630
|
+
hint: nothing was started; run the same command again
|
|
627
631
|
```
|
|
628
632
|
|
|
629
|
-
|
|
630
|
-
- `--no-wake` (or `SHARDFLUX_NO_WAKE=1`) turns this off. A workspace that is not running is then
|
|
631
|
-
refused at once (exit 1, `workspace_not_running`).
|
|
633
|
+
A definitive failure has `retryable=false`.
|
|
632
634
|
|
|
633
635
|
## Usage and overage
|
|
634
636
|
|
|
@@ -640,11 +642,11 @@ amount:
|
|
|
640
642
|
```text
|
|
641
643
|
overage accruing (usage past the allowances is charged on the next invoice)
|
|
642
644
|
spend cap $9.00 (at most $9.00, the plan price)
|
|
643
|
-
overage charges $
|
|
645
|
+
overage charges $2.40 of $9.00 (26.67%), $6.60 left; billed on the next invoice
|
|
644
646
|
cap reached 2026-09-29 15:02:46Z (projected at this period's average use)
|
|
645
647
|
|
|
646
648
|
OVERAGE UNIT PAST ALLOWANCE BILLED RATE AMOUNT
|
|
647
|
-
ram_gib_hours gib_hours 70 60 $0.
|
|
649
|
+
ram_gib_hours gib_hours 70 60 $0.03 $1.80
|
|
648
650
|
cpu_hours hours 5 5 $0.12 $0.60
|
|
649
651
|
```
|
|
650
652
|
|
|
@@ -665,19 +667,18 @@ names `details.reason`, and a hint says what to do (0.5.0+):
|
|
|
665
667
|
`--timing` (0.3.0+) says where the time of an open or a wait went. After the call, `shard` prints the lifecycle
|
|
666
668
|
timing that [`@shardflux/sdk`](https://www.npmjs.com/package/@shardflux/sdk) measured (its `formatTiming()`) on
|
|
667
669
|
stderr. It is printed when the call fails, times out or is interrupted too, before the error, and the exit code does
|
|
668
|
-
not change. A
|
|
670
|
+
not change. A resume reads, for example:
|
|
669
671
|
|
|
670
672
|
```text
|
|
671
|
-
$ shard ws
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
server:
|
|
677
|
-
outside the server: 0.16 s
|
|
673
|
+
$ shard ws resume acme/demo --wait --timing
|
|
674
|
+
Resuming acme/demo (01a0ead6-92e5-7d19-ab7a-f565bf4676cb): operation 01a0ead6-bd61-737a-ae88-66e2d01a6e25 resume succeeded
|
|
675
|
+
resume 413 ms, succeeded (workspace 01a0ead6-92e5-7d19-ab7a-f565bf4676cb, operation 01a0ead6-bd61-737a-ae88-66e2d01a6e25)
|
|
676
|
+
client: request 218 ms → queued 195 ms
|
|
677
|
+
server: queued 51 ms, ran 290 ms, total 341 ms; resume from local_cache, boot to ready 211 ms, host disk 0 ms, load 6 ms, ready 62 ms, total 211 ms, after_restore 36 ms
|
|
678
|
+
outside the server: 72 ms
|
|
678
679
|
```
|
|
679
680
|
|
|
680
|
-
|
|
681
|
+
This resume brought the workspace back from its host's local cache, memory and running processes included, in 341 ms on the server and 413 ms end to end.
|
|
681
682
|
|
|
682
683
|
- **client**: phases on your clock. `request` is the API call; `(held)` means the API held it until the workspace
|
|
683
684
|
was ready, up to 20 s at a time. Then come the operation states seen while waiting, with the server's reason, and
|
|
@@ -708,7 +709,7 @@ With `--json`, stdout carries the timing as a `timing` field of the command's JS
|
|
|
708
709
|
not say), `boot_to_ready_ms`, ...) and `outside_server_ms`. It is `null` when the command made no lifecycle call. On a failure the error document on stderr
|
|
709
710
|
carries it: `{"error": {...}, "timing": {...}}`.
|
|
710
711
|
|
|
711
|
-
|
|
712
|
+
For live progress events, use the SDK's `onProgress`.
|
|
712
713
|
|
|
713
714
|
## Secrets
|
|
714
715
|
|
|
@@ -787,17 +788,54 @@ printf %s "$NEW_KEY" | shard secrets rotate OPENAI_API_KEY
|
|
|
787
788
|
| 2 | usage error: bad arguments, or input the API rejected as `validation_failed` |
|
|
788
789
|
| 3 | not found: workspace, operation or route |
|
|
789
790
|
| 4 | authentication or authorization: missing, malformed, revoked or insufficient key or session; `step_up_required` (run `shard auth step-up`), `mfa_required` (a sign-in waiting for its code), `email_unverified`, `invalid_credentials` |
|
|
790
|
-
| 5 | timeout: waiting gave up (`--timeout`, or `--wake-timeout` while waking a workspace); the operation continues server side (`shard operations wait <id>`),
|
|
791
|
-
| 6 | the awaited operation ended `failed` or `canceled` (also a resume or open that failed while waking a workspace). `retryable=true` in the error means
|
|
792
|
-
| 130 | interrupted (Ctrl-C). Waits stop at once, and exec sends a cancel to the session. A file-first execution
|
|
791
|
+
| 5 | timeout: waiting gave up (`--timeout`, or `--wake-timeout` while waking a workspace); the operation continues server side (`shard operations wait <id>`), up to a queued start's 15-minute deadline. `executions get` (0.5.0+): the execution is still queued or running. `billing upgrade --wait` (0.5.0+): nobody paid in time (the checkout stays open) |
|
|
792
|
+
| 6 | the awaited operation ended `failed` or `canceled` (also a resume or open that failed while waking a workspace). `retryable=true` in the error means a retry can succeed (`capacity_unavailable`). Also a file-first execution that ended `failed` or `lost` (0.5.0+): nothing was published. `exec` (0.5.1+): the command could not start (`exec_failed_to_start`). `billing upgrade --wait` (0.5.0+): the checkout expired or was canceled (`checkout_ended`) |
|
|
793
|
+
| 130 | interrupted (Ctrl-C). Waits stop at once, and exec sends a cancel to the session. A file-first execution runs to completion, and the error names the `shard executions get` command for its result. |
|
|
793
794
|
| exec, executions get | the command's own code: 124 if it timed out, 128+N if killed by signal N. Failures before the command ran use the codes above; use `--json` to tell them apart. |
|
|
794
795
|
|
|
796
|
+
## Durable storage (0.7.0+)
|
|
797
|
+
|
|
798
|
+
`shard ws suspend --wait` returns as soon as the workspace is sealed on its host, typically in a few hundred ms, and
|
|
799
|
+
its RAM and CPU are released then. The copy lands in durable storage right after, typically within a second:
|
|
800
|
+
|
|
801
|
+
```sh
|
|
802
|
+
shard ws suspend acme/demo --wait
|
|
803
|
+
# Suspending acme/demo (<id>): operation <op> suspend succeeded
|
|
804
|
+
# durable: in progress, typically within a second (wait with: shard operations wait <op> --durable)
|
|
805
|
+
shard ws suspend acme/demo --durable # returns once it is durable: "durable: yes (435 ms after the suspend)"
|
|
806
|
+
shard operations wait <op> --durable # the same for a suspend or fork you already started
|
|
807
|
+
```
|
|
808
|
+
|
|
809
|
+
- `--durable` implies `--wait` and shares its `--timeout`.
|
|
810
|
+
- `--json` prints the operation as the API returns it: `result.durable` and `result.durability` (`state`
|
|
811
|
+
`pending` or `durable`, `local_commit_at`, `durable_at`, ...). `--timing` adds `durable`, `suspend_path` and
|
|
812
|
+
`durability` to `server`.
|
|
813
|
+
- `operations get|wait` show a `durable` line for suspends and forks. A fork of a running workspace reports its copy the
|
|
814
|
+
same way.
|
|
815
|
+
- The exit codes and errors of `--durable` are in the CLI reference on docs.shardflux.dev.
|
|
816
|
+
|
|
795
817
|
## HTTP connections
|
|
796
818
|
|
|
797
|
-
`shard`
|
|
798
|
-
releases a request sent on a reused keep-alive connection can stall until the request timeout.
|
|
799
|
-
Set `SHARDFLUX_HTTP_KEEPALIVE=1` to reuse connections instead.
|
|
819
|
+
`shard` 0.7.0 uses the SDK’s pooled HTTP/1.1 transport on Node 26. Custom fetch is preserved. `SHARDFLUX_HTTP_KEEPALIVE=0` forces connection closure for diagnosis; `=1` opts into native pooling.
|
|
800
820
|
|
|
801
821
|
## License
|
|
802
822
|
|
|
803
823
|
Apache-2.0
|
|
824
|
+
|
|
825
|
+
|
|
826
|
+
## Integration controls (0.7.0+)
|
|
827
|
+
|
|
828
|
+
```sh
|
|
829
|
+
shard ws open qm/project-42 --template python-node-browser --labels '{"scope":"project-42"}' --idle-policy never
|
|
830
|
+
shard ws list --labels '{"scope":"project-42"}' --json
|
|
831
|
+
shard ws labels qm/project-42 --set '{"scope":"project-42","owner":"qm"}'
|
|
832
|
+
shard ws idle qm/project-42 --json
|
|
833
|
+
shard ws idle qm/project-42 --keepalive 60
|
|
834
|
+
shard ws idle qm/project-42 --policy adaptive
|
|
835
|
+
shard ws suspend qm/project-42 --when-idle 2s
|
|
836
|
+
shard ws exec-start qm/project-42 --stdin-open --session-id qm-worker-1 -- cat
|
|
837
|
+
shard ws exec-input qm/project-42 qm-worker-1 hello --offset 0
|
|
838
|
+
shard ws exec-input qm/project-42 qm-worker-1 --offset 5 --close
|
|
839
|
+
```
|
|
840
|
+
|
|
841
|
+
Use the byte offset in each acknowledgement, including partial writes. `ws resume` can recover a failed workspace with its existing ID and disk. A completed delete frees the key; old IDs remain deleted. Protocol-error JSON includes `source`; HTTP 404 alone does not mean a workspace was deleted.
|
package/dist/account-args.js
CHANGED
|
@@ -16,7 +16,7 @@ const PAGE = {
|
|
|
16
16
|
limit: { type: 'string', value: '<n>', description: 'Page size.' },
|
|
17
17
|
cursor: { type: 'string', value: '<cursor>', description: 'Continue from a previous page.' },
|
|
18
18
|
};
|
|
19
|
-
const OPEN = { open: { type: 'boolean', description: 'Also open the page in the default browser (
|
|
19
|
+
const OPEN = { open: { type: 'boolean', description: 'Also open the page in the default browser (the URL is printed either way).' } };
|
|
20
20
|
const AUDIT_FILTERS = {
|
|
21
21
|
source: { type: 'string', value: '<app|cell_tool>', description: 'API events (app) or workspace tool calls (cell_tool).' },
|
|
22
22
|
'actor-type': { type: 'string', value: '<type>', description: 'user, api_key, system, operator or anonymous.' },
|
package/dist/account-commands.js
CHANGED
|
@@ -18,7 +18,7 @@ import { UUID, parseDuration, parsePositiveInt } from "./args.js";
|
|
|
18
18
|
import { openUrl } from "./browser.js";
|
|
19
19
|
import { fileExists, oneOf, out, parseSlugVersion, principal, readInput, resolveWorkspace, str, strs, waitTimeout } from "./commands.js";
|
|
20
20
|
import { AuthConfigError, CheckoutEndedError, InterruptedError, MfaPendingError, NotFoundError, UsageError } from "./errors.js";
|
|
21
|
-
import { apiKeyTable, attachmentTable, auditTable, authSessionTable, billingStatusText, dataExportText, egressVersionTable, invitationTable, invoiceTable, kv, memberTable, money, orgTable, overagePolicyText, planTable, projectEgressText, projectTable, table, time, toolsText, volumeDetail, volumeTable, workspaceEgressText, WORKSPACE_HEADERS, workspaceRow, } from "./format.js";
|
|
21
|
+
import { apiKeyTable, attachmentTable, auditTable, authSessionTable, billingStatusText, dataExportText, egressVersionTable, invitationTable, invoiceTable, isGrantPlan, kv, memberTable, money, orgTable, overagePolicyText, planTable, projectEgressText, projectTable, table, time, toolsText, volumeDetail, volumeTable, workspaceEgressText, WORKSPACE_HEADERS, workspaceRow, } from "./format.js";
|
|
22
22
|
export const DEFAULT_API_URL = 'https://api.shardflux.dev';
|
|
23
23
|
const TOTP = /^\d{6}$/;
|
|
24
24
|
const ROLES = ['owner', 'admin', 'member', 'billing'];
|
|
@@ -418,7 +418,7 @@ export function dollarsToMinor(text, what) {
|
|
|
418
418
|
return Number(m[1]) * 100 + Number((m[2] ?? '').padEnd(2, '0'));
|
|
419
419
|
}
|
|
420
420
|
function purchasablePlans(catalog) {
|
|
421
|
-
return catalog.plans.filter((p) => p.prices.some((x) => x.purchasable)).map((p) => p.plan_key);
|
|
421
|
+
return catalog.plans.filter((p) => !isGrantPlan(p) && p.prices.some((x) => x.purchasable)).map((p) => p.plan_key);
|
|
422
422
|
}
|
|
423
423
|
function priceText(catalog, planKey) {
|
|
424
424
|
const plan = catalog.plans.find((p) => p.plan_key === planKey);
|
|
@@ -1280,7 +1280,14 @@ export const ACCOUNT_HANDLERS = {
|
|
|
1280
1280
|
const account = ctx.account();
|
|
1281
1281
|
const org = await resolveOrg(ctx, account, values);
|
|
1282
1282
|
const s = await account.billing.subscription(org.id);
|
|
1283
|
-
|
|
1283
|
+
// The trial has Developer limits: Developer keeps them (a subscription outranks the trial and ends it).
|
|
1284
|
+
const next = s.subscription
|
|
1285
|
+
? 'manage it: shard billing portal'
|
|
1286
|
+
: s.purchase_available
|
|
1287
|
+
? s.plan?.plan_key === 'trial'
|
|
1288
|
+
? 'keep these limits after the trial: shard billing upgrade developer'
|
|
1289
|
+
: 'buy a plan: shard billing plans, then shard billing upgrade <plan>'
|
|
1290
|
+
: '';
|
|
1284
1291
|
out(ctx, `${billingStatusText(s, org)}${next ? `${next}\n` : ''}`, s);
|
|
1285
1292
|
return 0;
|
|
1286
1293
|
},
|
package/dist/args.d.ts
CHANGED