@weftlabs/cli 0.25.0 → 0.26.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 +34 -28
- package/dist/cli.js +136 -99
- package/dist/cli.js.map +1 -1
- package/dist/weft-skill/rules/cli.md +23 -19
- package/examples/agent-bootstrap.sh +14 -14
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -75,9 +75,9 @@ is clipped.
|
|
|
75
75
|
## With no credential: agent bootstrap and human claim
|
|
76
76
|
|
|
77
77
|
An agent that has no Weft credential can start by itself. The flow needs the
|
|
78
|
-
human's email address and nothing else.
|
|
79
|
-
|
|
80
|
-
|
|
78
|
+
human's email address and nothing else. After the human verifies the claim
|
|
79
|
+
email, Weft applies the one-time signup grant. Check the balance after claim;
|
|
80
|
+
do not ask for a wallet top-up during onboarding.
|
|
81
81
|
|
|
82
82
|
```sh
|
|
83
83
|
npm install -g @weftlabs/cli
|
|
@@ -91,15 +91,16 @@ weft bootstrap --email "human@example.com" \
|
|
|
91
91
|
# 3. Search immediately, before the human does anything.
|
|
92
92
|
weft search "weather data API"
|
|
93
93
|
|
|
94
|
-
# 4.
|
|
94
|
+
# 4. Ask the human to verify the claim email so Weft can apply the one-time
|
|
95
|
+
# signup grant, then approve the agent.
|
|
95
96
|
# 5. Poll at the interval the bootstrap response returned.
|
|
96
97
|
weft auth status
|
|
97
98
|
|
|
98
|
-
# 6.
|
|
99
|
-
# credential, and normal authenticated commands work again.
|
|
99
|
+
# 6. Auth status reports claimed. The same bearer is now durable until revoked.
|
|
100
100
|
weft me
|
|
101
101
|
|
|
102
|
-
# 7.
|
|
102
|
+
# 7. The claim is verified and the signup grant is applied. Check the balance;
|
|
103
|
+
# do not ask for a wallet top-up during onboarding.
|
|
103
104
|
weft balance
|
|
104
105
|
```
|
|
105
106
|
|
|
@@ -144,19 +145,24 @@ untouched. Restart the agent host after the first install. Set
|
|
|
144
145
|
leaves the Skill in place; remove the host's `skills/weft` directory if you
|
|
145
146
|
also want to remove the Skill.
|
|
146
147
|
|
|
147
|
-
`weft bootstrap`
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
148
|
+
`weft bootstrap` creates the bootstrap and writes the `wbt_` credential to a
|
|
149
|
+
local credential file created with mode `0600`. The response contains the
|
|
150
|
+
bootstrap capabilities and approval data. `weft auth status` updates those
|
|
151
|
+
fields after the server promotes the same bearer. It never requests an OAuth
|
|
152
|
+
exchange token, and normal output never prints secrets.
|
|
151
153
|
|
|
152
|
-
### The
|
|
154
|
+
### The `wbt_` credential
|
|
153
155
|
|
|
154
156
|
- **Secret.** Never print, log, paste, commit, or email it. The CLI stores it
|
|
155
157
|
for you.
|
|
156
|
-
- **Temporary
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
158
|
+
- **Temporary before claim.** Its search-only claim window expires after 30
|
|
159
|
+
minutes. Pre-claim capabilities are exactly `search`, `status`, and `cancel`.
|
|
160
|
+
- **Durable after claim.** Human approval promotes the same bearer to exactly
|
|
161
|
+
`identity`, `search`, `balance`, `fetch`, `purchases`, `status`, and `revoke`.
|
|
162
|
+
It has no post-claim expiry and remains valid until the human disconnects it.
|
|
163
|
+
- **Always refused elsewhere.** Seller, organization, API-key administration,
|
|
164
|
+
dashboard-session, transfer, withdrawal, and MCP surfaces reject it before
|
|
165
|
+
and after claim.
|
|
160
166
|
|
|
161
167
|
The human's password is never part of this flow. The agent does not choose,
|
|
162
168
|
receive, or store it. An existing user completes fresh authentication on the
|
|
@@ -167,18 +173,18 @@ existing account.
|
|
|
167
173
|
|
|
168
174
|
| Status | Meaning | Agent action |
|
|
169
175
|
| --- | --- | --- |
|
|
170
|
-
| `pending` | Waiting for the human. Search works. |
|
|
171
|
-
| `claimed` | The human approved.
|
|
172
|
-
| `rejected` | The human declined. Terminal. | Stop
|
|
173
|
-
| `expired` | The 30-minute window closed unclaimed. Terminal. |
|
|
174
|
-
| `
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
bootstrap
|
|
176
|
+
| `pending` | Waiting for the human. Search works. | Poll at the returned interval. |
|
|
177
|
+
| `claimed` | The human approved. The same bearer is durable with the fixed post-claim capabilities. | Continue with normal commands. |
|
|
178
|
+
| `rejected` | The human declined. Terminal. | Stop and start a new bootstrap. |
|
|
179
|
+
| `expired` | The 30-minute window closed unclaimed. Terminal. | Start a new bootstrap. |
|
|
180
|
+
| `revoked` | The human disconnected the credential. Terminal; all later authentication fails. | Start a new bootstrap only if the human requests it. |
|
|
181
|
+
|
|
182
|
+
`weft auth status` returns `claimed` after approval and keeps the same bearer.
|
|
183
|
+
It does not register an OAuth client or call `/oauth/token`.
|
|
184
|
+
|
|
185
|
+
`rejected`, `expired`, and `revoked` are terminal. Existing stored OAuth
|
|
186
|
+
credentials from older CLI releases remain supported and refresh normally;
|
|
187
|
+
new bootstrap flows do not create OAuth credentials.
|
|
182
188
|
|
|
183
189
|
See [`examples/agent-bootstrap.sh`](examples/agent-bootstrap.sh) for the same
|
|
184
190
|
sequence as a script, and
|
package/dist/cli.js
CHANGED
|
@@ -19,7 +19,13 @@ function isObject(value) {
|
|
|
19
19
|
return typeof value === "object" && value !== null;
|
|
20
20
|
}
|
|
21
21
|
function isBootstrapCredentials(value) {
|
|
22
|
-
if (value.
|
|
22
|
+
if (typeof value.base_url === "string" && typeof value.id === "string" && typeof value.status === "string" && Array.isArray(value.capabilities) && value.capabilities.every((capability) => typeof capability === "string") && (typeof value.expires_at === "string" || value.expires_at === null) && isObject(value.approval) && typeof value.approval.method === "string" && typeof value.approval.expires_in === "number" && typeof value.approval.interval === "number" && (value.approval.user_code === void 0 || typeof value.approval.user_code === "string") && typeof value.temporary_api_key === "string") {
|
|
23
|
+
return value;
|
|
24
|
+
}
|
|
25
|
+
return void 0;
|
|
26
|
+
}
|
|
27
|
+
function isLegacyBootstrapCredentials(value) {
|
|
28
|
+
if (value.version === 1 && value.type === "bootstrap" && typeof value.base_url === "string" && typeof value.bootstrap_id === "string" && typeof value.temporary_api_key === "string" && typeof value.device_code === "string" && typeof value.client_id === "string" && typeof value.expiry === "string" && typeof value.polling_interval === "number") {
|
|
23
29
|
return value;
|
|
24
30
|
}
|
|
25
31
|
return void 0;
|
|
@@ -45,13 +51,19 @@ async function readStoredCredentials(env) {
|
|
|
45
51
|
const raw = await readFile(path, "utf8");
|
|
46
52
|
const parsed = JSON.parse(raw);
|
|
47
53
|
if (!isObject(parsed)) throw new Error("Stored credentials malformed");
|
|
48
|
-
return isBootstrapCredentials(parsed) ?? isOAuthCredentials(parsed);
|
|
54
|
+
return isBootstrapCredentials(parsed) ?? isLegacyBootstrapCredentials(parsed) ?? isOAuthCredentials(parsed);
|
|
49
55
|
} catch (error) {
|
|
50
56
|
if (error.code === "ENOENT") return void 0;
|
|
51
57
|
throw error;
|
|
52
58
|
}
|
|
53
59
|
}
|
|
54
60
|
async function writeStoredCredentials(env, credentials) {
|
|
61
|
+
await withCredentialsLock(
|
|
62
|
+
env,
|
|
63
|
+
() => writeStoredCredentialsWhileLocked(env, credentials)
|
|
64
|
+
);
|
|
65
|
+
}
|
|
66
|
+
async function writeStoredCredentialsWhileLocked(env, credentials) {
|
|
55
67
|
const path = resolveCredentialsPath(env);
|
|
56
68
|
if (!path) {
|
|
57
69
|
throw new Error("HOME, USERPROFILE, or WEFT_CREDENTIALS_FILE is required");
|
|
@@ -189,8 +201,6 @@ var COMMANDS = [
|
|
|
189
201
|
"purchases"
|
|
190
202
|
];
|
|
191
203
|
var WEFT_API_BASE = "https://weft.network";
|
|
192
|
-
var OAUTH_SCOPE = "balance fetch search";
|
|
193
|
-
var OAUTH_CLIENT_NAME = "Weft CLI";
|
|
194
204
|
var OAUTH_HOST_NAME = "Weft CLI";
|
|
195
205
|
var OAUTH_REFRESH_SKEW_MS = 6e4;
|
|
196
206
|
var PROCESS_OUTPUT_LIMIT = 8192;
|
|
@@ -208,7 +218,7 @@ var COMMAND_HELP = {
|
|
|
208
218
|
]
|
|
209
219
|
},
|
|
210
220
|
auth: {
|
|
211
|
-
description: "Check bootstrap status
|
|
221
|
+
description: "Check bootstrap status",
|
|
212
222
|
usage: "weft auth status",
|
|
213
223
|
options: ["status"]
|
|
214
224
|
},
|
|
@@ -449,14 +459,24 @@ function baseApiUrl(baseUrl, env) {
|
|
|
449
459
|
}
|
|
450
460
|
function resolveApiKeyFromStored(credentials) {
|
|
451
461
|
if (!credentials) return void 0;
|
|
452
|
-
if (credentials.
|
|
462
|
+
if ("access_token" in credentials && typeof credentials.access_token === "string" && credentials.access_token.trim()) {
|
|
453
463
|
return credentials.access_token;
|
|
454
464
|
}
|
|
455
|
-
if (credentials.
|
|
465
|
+
if ("temporary_api_key" in credentials && typeof credentials.temporary_api_key === "string" && credentials.temporary_api_key.trim()) {
|
|
456
466
|
return credentials.temporary_api_key;
|
|
457
467
|
}
|
|
458
468
|
return void 0;
|
|
459
469
|
}
|
|
470
|
+
function isOAuthCredentials2(credentials) {
|
|
471
|
+
return Boolean(
|
|
472
|
+
credentials && "type" in credentials && credentials.type === "oauth"
|
|
473
|
+
);
|
|
474
|
+
}
|
|
475
|
+
function isLegacyBootstrapCredentials2(credentials) {
|
|
476
|
+
return Boolean(
|
|
477
|
+
credentials && "type" in credentials && credentials.type === "bootstrap"
|
|
478
|
+
);
|
|
479
|
+
}
|
|
460
480
|
function oauthNeedsRefresh(credentials) {
|
|
461
481
|
const expiry = Date.parse(credentials.expiry);
|
|
462
482
|
return !Number.isFinite(expiry) || expiry <= Date.now() + OAUTH_REFRESH_SKEW_MS;
|
|
@@ -484,14 +504,13 @@ async function refreshOAuthCredentials(fetchApi, env, stored) {
|
|
|
484
504
|
scope: token.scope,
|
|
485
505
|
expiry: new Date(Date.now() + token.expires_in * 1e3).toISOString()
|
|
486
506
|
};
|
|
487
|
-
await
|
|
507
|
+
await writeStoredCredentialsWhileLocked(env, refreshed);
|
|
488
508
|
return refreshed;
|
|
489
509
|
}
|
|
490
510
|
function noSecretFields(data) {
|
|
491
511
|
return {
|
|
492
512
|
...data,
|
|
493
513
|
temporary_api_key: void 0,
|
|
494
|
-
device_code: void 0,
|
|
495
514
|
access_token: void 0,
|
|
496
515
|
refresh_token: void 0,
|
|
497
516
|
client_secret: void 0
|
|
@@ -728,27 +747,6 @@ async function runCli(args, dependencies = {}) {
|
|
|
728
747
|
const email = requiredOption(parsed.options, "email");
|
|
729
748
|
const agentName = requiredOption(parsed.options, "agent-name");
|
|
730
749
|
const reason = requiredOption(parsed.options, "reason");
|
|
731
|
-
const register = await requestJson(
|
|
732
|
-
fetchApi,
|
|
733
|
-
`${baseUrl}/oauth/register`,
|
|
734
|
-
{
|
|
735
|
-
method: "POST",
|
|
736
|
-
headers: {
|
|
737
|
-
"content-type": "application/json"
|
|
738
|
-
},
|
|
739
|
-
body: JSON.stringify({
|
|
740
|
-
client_name: OAUTH_CLIENT_NAME,
|
|
741
|
-
redirect_uris: ["http://localhost/callback"],
|
|
742
|
-
grant_types: [
|
|
743
|
-
"urn:ietf:params:oauth:grant-type:device_code",
|
|
744
|
-
"refresh_token"
|
|
745
|
-
],
|
|
746
|
-
token_endpoint_auth_method: "none",
|
|
747
|
-
scope: OAUTH_SCOPE
|
|
748
|
-
})
|
|
749
|
-
}
|
|
750
|
-
);
|
|
751
|
-
const clientId = register.client_id;
|
|
752
750
|
const bootstrap = await requestJson(
|
|
753
751
|
fetchApi,
|
|
754
752
|
`${baseUrl}/api/v1/account_bootstraps`,
|
|
@@ -761,22 +759,13 @@ async function runCli(args, dependencies = {}) {
|
|
|
761
759
|
email,
|
|
762
760
|
agent_name: agentName,
|
|
763
761
|
host_name: OAUTH_HOST_NAME,
|
|
764
|
-
reason
|
|
765
|
-
oauth_client_id: clientId,
|
|
766
|
-
requested_scopes: ["balance", "fetch", "search"]
|
|
762
|
+
reason
|
|
767
763
|
})
|
|
768
764
|
}
|
|
769
765
|
);
|
|
770
766
|
const stored = {
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
base_url: baseUrl,
|
|
774
|
-
bootstrap_id: bootstrap.data.id,
|
|
775
|
-
temporary_api_key: bootstrap.data.temporary_api_key,
|
|
776
|
-
device_code: bootstrap.data.device_code,
|
|
777
|
-
client_id: clientId,
|
|
778
|
-
expiry: bootstrap.data.expires_at,
|
|
779
|
-
polling_interval: bootstrap.data.approval.interval
|
|
767
|
+
...bootstrap.data,
|
|
768
|
+
base_url: baseUrl
|
|
780
769
|
};
|
|
781
770
|
await writeStoredCredentials(env, stored);
|
|
782
771
|
await writeOut(
|
|
@@ -784,12 +773,7 @@ async function runCli(args, dependencies = {}) {
|
|
|
784
773
|
schema_version: "1",
|
|
785
774
|
ok: true,
|
|
786
775
|
command,
|
|
787
|
-
data: noSecretFields(
|
|
788
|
-
...bootstrap.data,
|
|
789
|
-
client_id: clientId,
|
|
790
|
-
base_url: baseUrl,
|
|
791
|
-
polling_interval: bootstrap.data.approval.interval
|
|
792
|
-
})
|
|
776
|
+
data: noSecretFields(stored)
|
|
793
777
|
})}
|
|
794
778
|
`
|
|
795
779
|
);
|
|
@@ -805,7 +789,7 @@ async function runCli(args, dependencies = {}) {
|
|
|
805
789
|
);
|
|
806
790
|
}
|
|
807
791
|
const stored = await readStoredCredentials(env);
|
|
808
|
-
if (stored
|
|
792
|
+
if (isOAuthCredentials2(stored)) {
|
|
809
793
|
await writeOut(
|
|
810
794
|
`${JSON.stringify({
|
|
811
795
|
schema_version: "1",
|
|
@@ -821,74 +805,125 @@ async function runCli(args, dependencies = {}) {
|
|
|
821
805
|
);
|
|
822
806
|
return EXIT_SUCCESS;
|
|
823
807
|
}
|
|
824
|
-
if (
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
808
|
+
if (isLegacyBootstrapCredentials2(stored)) {
|
|
809
|
+
const status2 = await requestJson(
|
|
810
|
+
fetchApi,
|
|
811
|
+
`${stored.base_url}/api/v1/account_bootstraps/${stored.bootstrap_id}`,
|
|
812
|
+
{
|
|
813
|
+
method: "GET",
|
|
814
|
+
headers: withCredentials({}, stored.temporary_api_key)
|
|
815
|
+
}
|
|
829
816
|
);
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
817
|
+
if (status2.data.status !== "claimed" && status2.data.status !== "consumed") {
|
|
818
|
+
await writeOut(
|
|
819
|
+
`${JSON.stringify({
|
|
820
|
+
schema_version: "1",
|
|
821
|
+
ok: true,
|
|
822
|
+
command,
|
|
823
|
+
data: { status: status2.data.status }
|
|
824
|
+
})}
|
|
825
|
+
`
|
|
826
|
+
);
|
|
827
|
+
return EXIT_SUCCESS;
|
|
838
828
|
}
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
829
|
+
const token = await requestJson(
|
|
830
|
+
fetchApi,
|
|
831
|
+
`${stored.base_url}/oauth/token`,
|
|
832
|
+
{
|
|
833
|
+
method: "POST",
|
|
834
|
+
headers: {
|
|
835
|
+
"content-type": "application/x-www-form-urlencoded"
|
|
836
|
+
},
|
|
837
|
+
body: new URLSearchParams({
|
|
838
|
+
grant_type: "urn:ietf:params:oauth:grant-type:device_code",
|
|
839
|
+
device_code: stored.device_code,
|
|
840
|
+
client_id: stored.client_id,
|
|
841
|
+
name: "Weft CLI"
|
|
842
|
+
}).toString()
|
|
843
|
+
},
|
|
844
|
+
true
|
|
845
|
+
);
|
|
846
|
+
const oauth = {
|
|
847
|
+
version: 1,
|
|
848
|
+
type: "oauth",
|
|
849
|
+
base_url: stored.base_url,
|
|
850
|
+
client_id: stored.client_id,
|
|
851
|
+
access_token: token.access_token,
|
|
852
|
+
refresh_token: token.refresh_token,
|
|
853
|
+
token_type: token.token_type,
|
|
854
|
+
scope: token.scope,
|
|
855
|
+
expiry: new Date(Date.now() + token.expires_in * 1e3).toISOString()
|
|
856
|
+
};
|
|
857
|
+
const active2 = await withCredentialsLock(env, async () => {
|
|
858
|
+
const current = await readStoredCredentials(env);
|
|
859
|
+
if (isOAuthCredentials2(current)) return current;
|
|
860
|
+
if (!isLegacyBootstrapCredentials2(current) || JSON.stringify(current) !== JSON.stringify(stored)) {
|
|
861
|
+
throw new CliError(
|
|
862
|
+
EXIT_AUTH,
|
|
863
|
+
"CREDENTIALS_CHANGED",
|
|
864
|
+
"Stored credentials changed; rerun auth status"
|
|
865
|
+
);
|
|
866
|
+
}
|
|
867
|
+
await writeStoredCredentialsWhileLocked(env, oauth);
|
|
868
|
+
return oauth;
|
|
869
|
+
});
|
|
842
870
|
await writeOut(
|
|
843
871
|
`${JSON.stringify({
|
|
844
872
|
schema_version: "1",
|
|
845
873
|
ok: true,
|
|
846
874
|
command,
|
|
847
|
-
data: {
|
|
875
|
+
data: {
|
|
876
|
+
status: "consumed",
|
|
877
|
+
authentication: "oauth",
|
|
878
|
+
scope: active2.scope
|
|
879
|
+
}
|
|
848
880
|
})}
|
|
849
881
|
`
|
|
850
882
|
);
|
|
851
883
|
return EXIT_SUCCESS;
|
|
852
884
|
}
|
|
853
|
-
|
|
885
|
+
if (!stored) {
|
|
886
|
+
throw new CliError(
|
|
887
|
+
EXIT_AUTH,
|
|
888
|
+
"BOOTSTRAP_REQUIRED",
|
|
889
|
+
"Run weft bootstrap before auth status"
|
|
890
|
+
);
|
|
891
|
+
}
|
|
892
|
+
const status = await requestJson(
|
|
854
893
|
fetchApi,
|
|
855
|
-
`${
|
|
894
|
+
`${stored.base_url}/api/v1/account_bootstraps/${stored.id}`,
|
|
856
895
|
{
|
|
857
|
-
method: "
|
|
858
|
-
headers: {
|
|
859
|
-
|
|
860
|
-
},
|
|
861
|
-
body: new URLSearchParams({
|
|
862
|
-
grant_type: "urn:ietf:params:oauth:grant-type:device_code",
|
|
863
|
-
device_code: stored.device_code,
|
|
864
|
-
client_id: stored.client_id,
|
|
865
|
-
name: OAUTH_CLIENT_NAME
|
|
866
|
-
}).toString()
|
|
867
|
-
},
|
|
868
|
-
true
|
|
896
|
+
method: "GET",
|
|
897
|
+
headers: withCredentials({}, stored.temporary_api_key)
|
|
898
|
+
}
|
|
869
899
|
);
|
|
870
|
-
const
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
scope: token.scope,
|
|
879
|
-
expiry: new Date(Date.now() + token.expires_in * 1e3).toISOString()
|
|
900
|
+
const merged = {
|
|
901
|
+
base_url: stored.base_url,
|
|
902
|
+
id: status.data.id ?? stored.id,
|
|
903
|
+
status: status.data.status,
|
|
904
|
+
capabilities: status.data.capabilities ?? stored.capabilities,
|
|
905
|
+
expires_at: status.data.expires_at === void 0 ? stored.expires_at : status.data.expires_at,
|
|
906
|
+
approval: status.data.approval ?? stored.approval,
|
|
907
|
+
temporary_api_key: stored.temporary_api_key
|
|
880
908
|
};
|
|
881
|
-
await
|
|
909
|
+
const active = await withCredentialsLock(env, async () => {
|
|
910
|
+
const current = await readStoredCredentials(env);
|
|
911
|
+
if (JSON.stringify(current) !== JSON.stringify(stored)) {
|
|
912
|
+
throw new CliError(
|
|
913
|
+
EXIT_AUTH,
|
|
914
|
+
"CREDENTIALS_CHANGED",
|
|
915
|
+
"Stored credentials changed; rerun auth status"
|
|
916
|
+
);
|
|
917
|
+
}
|
|
918
|
+
await writeStoredCredentialsWhileLocked(env, merged);
|
|
919
|
+
return merged;
|
|
920
|
+
});
|
|
882
921
|
await writeOut(
|
|
883
922
|
`${JSON.stringify({
|
|
884
923
|
schema_version: "1",
|
|
885
924
|
ok: true,
|
|
886
925
|
command,
|
|
887
|
-
data:
|
|
888
|
-
status: "consumed",
|
|
889
|
-
authentication: "oauth",
|
|
890
|
-
scope: token.scope
|
|
891
|
-
}
|
|
926
|
+
data: noSecretFields(active)
|
|
892
927
|
})}
|
|
893
928
|
`
|
|
894
929
|
);
|
|
@@ -906,17 +941,19 @@ async function runCli(args, dependencies = {}) {
|
|
|
906
941
|
}
|
|
907
942
|
if (!apiKey && !parsed.apiKeyStdin) {
|
|
908
943
|
let stored = await readStoredCredentials(env);
|
|
909
|
-
if (stored
|
|
944
|
+
if (isOAuthCredentials2(stored) && oauthNeedsRefresh(stored)) {
|
|
910
945
|
stored = await withCredentialsLock(env, async () => {
|
|
911
946
|
const current = await readStoredCredentials(env);
|
|
912
|
-
if (current
|
|
947
|
+
if (isOAuthCredentials2(current) && oauthNeedsRefresh(current)) {
|
|
913
948
|
return refreshOAuthCredentials(fetchApi, env, current);
|
|
914
949
|
}
|
|
915
950
|
return current;
|
|
916
951
|
});
|
|
917
952
|
}
|
|
918
953
|
apiKey = resolveApiKeyFromStored(stored);
|
|
919
|
-
if (stored)
|
|
954
|
+
if (stored) {
|
|
955
|
+
authenticatedBaseUrl = stored.base_url;
|
|
956
|
+
}
|
|
920
957
|
}
|
|
921
958
|
if (!apiKey) {
|
|
922
959
|
throw new CliError(
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/credentials.ts","../src/cli.ts","../src/results.ts"],"sourcesContent":["import { randomUUID } from \"node:crypto\";\nimport {\n chmod,\n mkdir,\n open,\n readFile,\n rename,\n rm,\n writeFile,\n} from \"node:fs/promises\";\nimport { dirname } from \"node:path\";\nimport { setTimeout as delay } from \"node:timers/promises\";\n\nconst CREDENTIALS_FILE_MODE = 0o600;\nconst CREDENTIALS_DIR_MODE = 0o700;\nconst LOCK_RETRY_MS = 50;\nconst LOCK_TIMEOUT_MS = 10_000;\n\nexport interface BootstrapCredentials {\n version: 1;\n type: \"bootstrap\";\n base_url: string;\n bootstrap_id: string;\n temporary_api_key: string;\n device_code: string;\n client_id: string;\n expiry: string;\n polling_interval: number;\n}\n\nexport interface OAuthCredentials {\n version: 1;\n type: \"oauth\";\n base_url: string;\n client_id: string;\n access_token: string;\n refresh_token: string;\n token_type: string;\n scope: string;\n expiry: string;\n}\n\nexport type StoredCredentials = BootstrapCredentials | OAuthCredentials;\n\nfunction isObject(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null;\n}\n\nfunction isBootstrapCredentials(\n value: Record<string, unknown>,\n): BootstrapCredentials | undefined {\n if (\n value.type === \"bootstrap\" &&\n typeof value.version === \"number\" &&\n typeof value.base_url === \"string\" &&\n typeof value.bootstrap_id === \"string\" &&\n typeof value.temporary_api_key === \"string\" &&\n typeof value.device_code === \"string\" &&\n typeof value.client_id === \"string\" &&\n typeof value.expiry === \"string\" &&\n typeof value.polling_interval === \"number\"\n ) {\n return value as BootstrapCredentials;\n }\n\n return undefined;\n}\n\nfunction isOAuthCredentials(\n value: Record<string, unknown>,\n): OAuthCredentials | undefined {\n if (\n value.type === \"oauth\" &&\n typeof value.version === \"number\" &&\n typeof value.base_url === \"string\" &&\n typeof value.client_id === \"string\" &&\n typeof value.access_token === \"string\" &&\n typeof value.refresh_token === \"string\" &&\n typeof value.token_type === \"string\" &&\n typeof value.scope === \"string\" &&\n typeof value.expiry === \"string\"\n ) {\n return value as OAuthCredentials;\n }\n\n return undefined;\n}\n\nexport function resolveCredentialsPath(\n env: Record<string, string | undefined>,\n): string | undefined {\n if (env.WEFT_CREDENTIALS_FILE) return env.WEFT_CREDENTIALS_FILE;\n if (env.XDG_CONFIG_HOME)\n return `${env.XDG_CONFIG_HOME}/weft/credentials.json`;\n const home = env.HOME || env.USERPROFILE;\n if (!home) return undefined;\n return `${home}/.config/weft/credentials.json`;\n}\n\nexport async function readStoredCredentials(\n env: Record<string, string | undefined>,\n): Promise<StoredCredentials | undefined> {\n const path = resolveCredentialsPath(env);\n if (!path) return undefined;\n try {\n const raw = await readFile(path, \"utf8\");\n const parsed: unknown = JSON.parse(raw);\n if (!isObject(parsed)) throw new Error(\"Stored credentials malformed\");\n return isBootstrapCredentials(parsed) ?? isOAuthCredentials(parsed);\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === \"ENOENT\") return undefined;\n throw error;\n }\n}\n\nexport async function writeStoredCredentials(\n env: Record<string, string | undefined>,\n credentials: StoredCredentials,\n): Promise<void> {\n const path = resolveCredentialsPath(env);\n if (!path) {\n throw new Error(\"HOME, USERPROFILE, or WEFT_CREDENTIALS_FILE is required\");\n }\n const parent = dirname(path);\n await mkdir(parent, { recursive: true, mode: CREDENTIALS_DIR_MODE });\n await chmod(parent, CREDENTIALS_DIR_MODE);\n\n const tempPath = `${path}.${randomUUID()}.tmp`;\n try {\n await writeFile(tempPath, JSON.stringify(credentials), {\n mode: CREDENTIALS_FILE_MODE,\n });\n await rename(tempPath, path);\n await chmod(path, CREDENTIALS_FILE_MODE);\n } catch (error) {\n await rm(tempPath, { force: true });\n throw error;\n }\n}\n\nexport async function withCredentialsLock<T>(\n env: Record<string, string | undefined>,\n action: () => Promise<T>,\n): Promise<T> {\n const path = resolveCredentialsPath(env);\n if (!path) {\n throw new Error(\"HOME, USERPROFILE, or WEFT_CREDENTIALS_FILE is required\");\n }\n const lockPath = `${path}.lock`;\n const deadline = Date.now() + LOCK_TIMEOUT_MS;\n await mkdir(dirname(path), { recursive: true, mode: CREDENTIALS_DIR_MODE });\n\n for (;;) {\n try {\n const lock = await open(lockPath, \"wx\", CREDENTIALS_FILE_MODE);\n await lock.close();\n break;\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== \"EEXIST\") throw error;\n if (Date.now() >= deadline) {\n throw new Error(\n `Timed out waiting for the credential lock; if no Weft CLI process is running, remove ${lockPath}`,\n );\n }\n await delay(LOCK_RETRY_MS);\n }\n }\n\n try {\n return await action();\n } finally {\n await rm(lockPath, { force: true });\n }\n}\n","import {\n readStoredCredentials,\n type BootstrapCredentials,\n type OAuthCredentials,\n withCredentialsLock,\n writeStoredCredentials,\n} from \"./credentials\";\nimport { spawn } from \"node:child_process\";\nimport { randomUUID } from \"node:crypto\";\nimport { existsSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport {\n readableBody,\n reserveResultDirectory,\n writeResultFile,\n} from \"./results\";\nimport {\n type PaidFetchRequest,\n ResponseError,\n WeftClient,\n WeftError,\n} from \"@weftlabs/sdk\";\n\nexport const EXIT_SUCCESS = 0;\nexport const EXIT_USAGE = 2;\nexport const EXIT_AUTH = 3;\nexport const EXIT_API = 4;\nexport const EXIT_INTERNAL = 5;\n\ntype Command =\n | \"bootstrap\"\n | \"auth\"\n | \"skill\"\n | \"me\"\n | \"balance\"\n | \"search\"\n | \"fetch\"\n | \"purchases\";\n\nconst COMMANDS: Command[] = [\n \"bootstrap\",\n \"auth\",\n \"skill\",\n \"me\",\n \"balance\",\n \"search\",\n \"fetch\",\n \"purchases\",\n];\n\nconst WEFT_API_BASE = \"https://weft.network\";\nconst OAUTH_SCOPE = \"balance fetch search\";\nconst OAUTH_CLIENT_NAME = \"Weft CLI\";\nconst OAUTH_HOST_NAME = \"Weft CLI\";\nconst OAUTH_REFRESH_SKEW_MS = 60_000;\nconst PROCESS_OUTPUT_LIMIT = 8_192;\nconst SKILL_NAME_PATTERN = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;\nconst CORE_SKILL_NAMES = new Set([\"weft\", \"weft-setup\"]);\n\nconst COMMAND_HELP = {\n bootstrap: {\n description: \"Bootstrap an agent account\",\n usage: \"weft bootstrap --email <email> --agent-name <name> --reason <text>\",\n options: [\n \"--email <email>\",\n \"--agent-name <name>\",\n \"--reason <text>\",\n \"[--base-url <url>]\",\n ],\n },\n auth: {\n description: \"Check bootstrap status and exchange device token\",\n usage: \"weft auth status\",\n options: [\"status\"],\n },\n skill: {\n description: \"Install the core Weft Skill or one optional workflow Skill\",\n usage: \"weft skill install [name --agent <agent> [--global]]\",\n options: [\"install\", \"[name]\", \"--agent <agent>\", \"--global\"],\n },\n me: {\n description: \"Return the authenticated principal\",\n usage: \"weft me\",\n options: [],\n },\n balance: {\n description: \"Return wallet balance and spending policy\",\n usage: \"weft balance\",\n options: [],\n },\n search: {\n description: \"Search for payable resources\",\n usage: \"weft search <query> [--max-results <1..50>]\",\n options: [\"--max-results <1..50>\"],\n },\n fetch: {\n description: \"Fetch a URL within an explicit spending limit\",\n usage:\n \"weft fetch <url> --max-cost-usd <amount> [--method <method>] [--idempotency-key <key>] [--raw]\",\n options: [\n \"--max-cost-usd <amount>\",\n \"--method <method>\",\n \"--idempotency-key <key>\",\n \"--raw\",\n ],\n },\n purchases: {\n description: \"List purchases or return one purchase by ID\",\n usage: \"weft purchases [id] [--page <number>] [--per-page <1..100>]\",\n options: [\"--page <number>\", \"--per-page <1..100>\"],\n },\n} satisfies Record<\n Command,\n { description: string; usage: string; options: string[] }\n>;\n\ninterface SkillInstallResult {\n status: \"ok\" | \"skipped\";\n reason?: string;\n installed: number;\n hosts: string[];\n warnings: string[];\n}\n\ntype SkillInstaller = (options?: {\n force?: boolean;\n silent?: boolean;\n}) => Promise<SkillInstallResult>;\n\n/**\n * The Skill installer ships as a plain script beside `dist/`, and reads the\n * packed Skill relative to its own location. The specifier is built at runtime\n * so the bundler leaves it external and that relative path stays correct in the\n * published package.\n */\nasync function loadSkillInstaller(): Promise<SkillInstaller> {\n const specifier = new URL(\"../scripts/install-skill.mjs\", import.meta.url)\n .href;\n const module = (await import(specifier)) as { installSkill: SkillInstaller };\n return module.installSkill;\n}\n\n/**\n * Best-effort Skill installation on any ordinary command. This is the safety\n * net for a user who never runs `weft skill install`, and it is what lets the\n * Skill appear in an agent host that was installed after the CLI. It is\n * idempotent, it stays silent, and it never fails the command the user asked\n * for.\n */\nasync function installSkillInBackground(): Promise<void> {\n try {\n const installSkill = await loadSkillInstaller();\n await installSkill({ silent: true });\n } catch {\n // Deliberately ignored — `weft skill install` is the surface that reports\n // installation problems.\n }\n}\n\ninterface BootstrapCreateResponse {\n data: {\n id: string;\n status: string;\n capabilities: unknown;\n expires_at: string;\n temporary_api_key: string;\n device_code: string;\n approval: {\n interval: number;\n expires_in: number;\n method: string;\n user_code: string;\n };\n };\n}\n\ninterface BootstrapStatus {\n data: {\n id: string;\n status: string;\n expires_at?: string;\n capabilities?: unknown;\n };\n}\n\ninterface OAuthTokenResponse {\n access_token: string;\n token_type: string;\n expires_in: number;\n refresh_token: string;\n scope: string;\n}\n\nconst GLOBAL_OPTIONS = [\"--api-key-stdin\", \"--base-url <url>\", \"--help\", \"-h\"];\n\nexport interface CliDependencies {\n env?: Record<string, string | undefined>;\n fetchApi?: typeof fetch;\n readStdin?: () => Promise<string>;\n writeOut?: (value: string) => void | Promise<void>;\n writeErr?: (value: string) => void;\n generateIdempotencyKey?: () => string;\n runProcess?: ProcessRunner;\n platform?: NodeJS.Platform;\n nodeExecutable?: string;\n npxCliPath?: string;\n}\n\ninterface ProcessResult {\n exitCode: number;\n stdout: string;\n stderr: string;\n}\n\ntype ProcessRunner = (\n command: string,\n args: string[],\n) => Promise<ProcessResult>;\n\ninterface ParsedArgs {\n command: Command;\n apiKeyStdin: boolean;\n baseUrl?: string;\n positionals: string[];\n options: Map<string, string | true>;\n}\n\nclass CliError extends Error {\n constructor(\n readonly exitCode: number,\n readonly code: string,\n message: string,\n readonly details?: unknown,\n ) {\n super(message);\n }\n}\n\nfunction takeValue(\n args: string[],\n index: number,\n option: string,\n): [string, number] {\n const value = args[index + 1];\n if (value == null || value.startsWith(\"--\")) {\n throw new CliError(\n EXIT_USAGE,\n \"INVALID_ARGUMENT\",\n `${option} requires a value`,\n );\n }\n return [value, index + 1];\n}\n\nfunction appendBounded(current: string, chunk: Buffer | string): string {\n return `${current}${chunk.toString()}`.slice(-PROCESS_OUTPUT_LIMIT);\n}\n\nfunction defaultRunProcess(\n command: string,\n args: string[],\n): Promise<ProcessResult> {\n return new Promise((resolve) => {\n const child = spawn(command, args, {\n shell: false,\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n });\n let stdout = \"\";\n let stderr = \"\";\n child.stdout.on(\"data\", (chunk: Buffer) => {\n stdout = appendBounded(stdout, chunk);\n });\n child.stderr.on(\"data\", (chunk: Buffer) => {\n stderr = appendBounded(stderr, chunk);\n });\n child.on(\"error\", (error) => {\n resolve({\n exitCode: 1,\n stdout,\n stderr: appendBounded(stderr, error.message),\n });\n });\n child.on(\"close\", (exitCode) => {\n resolve({ exitCode: exitCode ?? 1, stdout, stderr });\n });\n });\n}\n\nfunction resolveNpxCliPath(\n env: Record<string, string | undefined>,\n nodeExecutable: string,\n): string | undefined {\n const executableDirectory = dirname(nodeExecutable);\n const candidates = [\n ...(env.npm_execpath\n ? [join(dirname(env.npm_execpath), \"npx-cli.js\")]\n : []),\n join(executableDirectory, \"node_modules\", \"npm\", \"bin\", \"npx-cli.js\"),\n join(\n executableDirectory,\n \"..\",\n \"lib\",\n \"node_modules\",\n \"npm\",\n \"bin\",\n \"npx-cli.js\",\n ),\n ];\n return candidates.find((candidate) => existsSync(candidate));\n}\n\nfunction npxProcessInvocation(\n processArgs: string[],\n dependencies: CliDependencies,\n env: Record<string, string | undefined>,\n): { executable: string; arguments: string[] } {\n if ((dependencies.platform ?? process.platform) !== \"win32\") {\n return { executable: \"npx\", arguments: processArgs };\n }\n\n const nodeExecutable = dependencies.nodeExecutable ?? process.execPath;\n const npxCliPath =\n dependencies.npxCliPath ?? resolveNpxCliPath(env, nodeExecutable);\n if (!npxCliPath) {\n throw new CliError(\n EXIT_INTERNAL,\n \"NPX_NOT_FOUND\",\n \"Could not find the npm npx program. Install npm, then run the command again.\",\n );\n }\n return {\n executable: nodeExecutable,\n arguments: [npxCliPath, ...processArgs],\n };\n}\n\nfunction rejectUnsafeCredentialArgument(args: string[]): void {\n if (args.some((arg) => arg === \"--api-key\" || arg.startsWith(\"--api-key=\"))) {\n throw new CliError(\n EXIT_USAGE,\n \"UNSAFE_CREDENTIAL_ARGUMENT\",\n \"API keys are accepted only through WEFT_API_KEY or --api-key-stdin\",\n );\n }\n}\n\nfunction requestedHelp(args: string[]): Command | \"all\" | undefined {\n const isHelp = (value: string) => value === \"--help\" || value === \"-h\";\n if (args.length === 1 && isHelp(args[0])) return \"all\";\n if (\n args.length === 2 &&\n COMMANDS.includes(args[0] as Command) &&\n isHelp(args[1])\n ) {\n return args[0] as Command;\n }\n return undefined;\n}\n\nfunction helpData(command: Command | \"all\") {\n if (command !== \"all\") {\n return {\n command,\n ...COMMAND_HELP[command],\n global_options: GLOBAL_OPTIONS,\n };\n }\n return {\n usage: \"weft <command> [options]\",\n commands: COMMANDS.map((name) => ({ name, ...COMMAND_HELP[name] })),\n global_options: GLOBAL_OPTIONS,\n authentication: [\"WEFT_API_KEY\", \"--api-key-stdin\"],\n exit_codes: { success: 0, usage: 2, auth: 3, api: 4, internal: 5 },\n };\n}\n\nfunction parseArgs(args: string[]): ParsedArgs {\n let command: Command | undefined;\n let apiKeyStdin = false;\n let baseUrl: string | undefined;\n const positionals: string[] = [];\n const options = new Map<string, string | true>();\n\n for (let index = 0; index < args.length; index += 1) {\n const arg = args[index];\n if (arg === \"--api-key-stdin\") {\n apiKeyStdin = true;\n } else if (arg === \"--base-url\") {\n [baseUrl, index] = takeValue(args, index, arg);\n } else if (arg === \"--global\" || arg === \"--raw\") {\n options.set(arg.slice(2), true);\n } else if (arg.startsWith(\"--\")) {\n const [value, nextIndex] = takeValue(args, index, arg);\n options.set(arg.slice(2), value);\n index = nextIndex;\n } else if (!command) {\n if (!COMMANDS.includes(arg as Command)) {\n throw new CliError(\n EXIT_USAGE,\n \"UNKNOWN_COMMAND\",\n `Unknown command: ${arg}`,\n );\n }\n command = arg as Command;\n } else {\n positionals.push(arg);\n }\n }\n\n if (!command) {\n throw new CliError(\n EXIT_USAGE,\n \"COMMAND_REQUIRED\",\n \"Command required: bootstrap, auth, me, balance, search, fetch, or purchases\",\n );\n }\n\n return { command, apiKeyStdin, baseUrl, positionals, options };\n}\n\nfunction positiveInteger(\n value: string | true | undefined,\n option: string,\n maximum?: number,\n): number | undefined {\n if (value == null) return undefined;\n const parsed = Number(value);\n if (!Number.isInteger(parsed) || parsed <= 0) {\n throw new CliError(\n EXIT_USAGE,\n \"INVALID_ARGUMENT\",\n `${option} must be a positive integer`,\n );\n }\n if (maximum != null && parsed > maximum) {\n throw new CliError(\n EXIT_USAGE,\n \"INVALID_ARGUMENT\",\n `${option} must be at most ${maximum}`,\n );\n }\n return parsed;\n}\n\nfunction requiredOption(\n options: Map<string, string | true>,\n name: string,\n): string {\n const value = options.get(name);\n if (typeof value !== \"string\" || !value.trim()) {\n throw new CliError(EXIT_USAGE, \"MISSING_ARGUMENT\", `--${name} is required`);\n }\n return value;\n}\n\nfunction baseApiUrl(\n baseUrl: string | undefined,\n env: Record<string, string | undefined>,\n): string {\n const raw = baseUrl ?? env.WEFT_BASE_URL ?? WEFT_API_BASE;\n return raw.endsWith(\"/\") ? raw.slice(0, -1) : raw;\n}\n\nfunction resolveApiKeyFromStored(\n credentials?:\n | {\n temporary_api_key: string;\n type: \"bootstrap\";\n }\n | {\n access_token: string;\n type: \"oauth\";\n },\n): string | undefined {\n if (!credentials) return undefined;\n if (credentials.type === \"oauth\" && credentials.access_token.trim()) {\n return credentials.access_token;\n }\n if (\n credentials.type === \"bootstrap\" &&\n credentials.temporary_api_key.trim()\n ) {\n return credentials.temporary_api_key;\n }\n return undefined;\n}\n\nfunction oauthNeedsRefresh(credentials: OAuthCredentials): boolean {\n const expiry = Date.parse(credentials.expiry);\n return (\n !Number.isFinite(expiry) || expiry <= Date.now() + OAUTH_REFRESH_SKEW_MS\n );\n}\n\nasync function refreshOAuthCredentials(\n fetchApi: typeof fetch,\n env: Record<string, string | undefined>,\n stored: OAuthCredentials,\n): Promise<OAuthCredentials> {\n const token = await requestJson<OAuthTokenResponse>(\n fetchApi,\n `${stored.base_url}/oauth/token`,\n {\n method: \"POST\",\n headers: { \"content-type\": \"application/x-www-form-urlencoded\" },\n body: new URLSearchParams({\n grant_type: \"refresh_token\",\n refresh_token: stored.refresh_token,\n client_id: stored.client_id,\n }).toString(),\n },\n true,\n );\n const refreshed: OAuthCredentials = {\n ...stored,\n access_token: token.access_token,\n refresh_token: token.refresh_token,\n token_type: token.token_type,\n scope: token.scope,\n expiry: new Date(Date.now() + token.expires_in * 1000).toISOString(),\n };\n await writeStoredCredentials(env, refreshed);\n return refreshed;\n}\n\nfunction noSecretFields(\n data: Record<string, unknown>,\n): Record<string, unknown> {\n return {\n ...data,\n temporary_api_key: undefined,\n device_code: undefined,\n access_token: undefined,\n refresh_token: undefined,\n client_secret: undefined,\n };\n}\n\nasync function requestJson<T>(\n fetchApi: typeof fetch,\n url: string,\n init: RequestInit,\n redactError = false,\n): Promise<T> {\n const response = await fetchApi(url, init);\n if (!response.ok) {\n if (redactError) {\n throw new CliError(\n response.status === 401 || response.status === 403\n ? EXIT_AUTH\n : response.status >= 500\n ? EXIT_INTERNAL\n : EXIT_API,\n \"OAUTH_TOKEN_ERROR\",\n `OAuth token request failed with HTTP ${response.status}`,\n );\n }\n throw new ResponseError(response);\n }\n\n return (await response.json()) as T;\n}\n\nfunction withCredentials(\n headers: Record<string, string>,\n apiKey: string,\n): Record<string, string> {\n return {\n ...headers,\n authorization: `Bearer ${apiKey}`,\n };\n}\n\nfunction ensureOnly(\n options: Map<string, string | true>,\n allowed: string[],\n): void {\n for (const name of options.keys()) {\n if (!allowed.includes(name)) {\n throw new CliError(\n EXIT_USAGE,\n \"UNKNOWN_OPTION\",\n `Unknown option: --${name}`,\n );\n }\n }\n}\n\nasync function responseDetails(error: ResponseError): Promise<unknown> {\n try {\n return await error.response.json();\n } catch {\n return undefined;\n }\n}\n\nasync function normalizeError(error: unknown): Promise<CliError> {\n if (error instanceof CliError) return error;\n if (error instanceof WeftError) {\n // status 0 is a transport failure with no API response; it exits like an\n // internal failure, not an API rejection.\n const exitCode =\n error.status === 401 || error.status === 403\n ? EXIT_AUTH\n : error.status >= 500 || error.status === 0\n ? EXIT_INTERNAL\n : EXIT_API;\n return new CliError(exitCode, error.code, error.message, error.details);\n }\n if (error instanceof ResponseError) {\n const details = await responseDetails(error);\n const body = details as\n | {\n error?: { code?: string; message?: string } | string;\n error_description?: string;\n }\n | undefined;\n const nested = typeof body?.error === \"object\" ? body.error : undefined;\n const code =\n nested?.code ??\n (typeof body?.error === \"string\"\n ? body.error\n : `HTTP_${error.response.status}`);\n const message =\n nested?.message ??\n body?.error_description ??\n `Weft API returned HTTP ${error.response.status}`;\n const exitCode =\n error.response.status === 401 || error.response.status === 403\n ? EXIT_AUTH\n : error.response.status >= 500\n ? EXIT_INTERNAL\n : EXIT_API;\n return new CliError(exitCode, code, message, details);\n }\n const message = error instanceof Error ? error.message : String(error);\n return new CliError(EXIT_INTERNAL, \"INTERNAL_ERROR\", message);\n}\n\nasync function defaultReadStdin(): Promise<string> {\n const chunks: Buffer[] = [];\n for await (const chunk of process.stdin) {\n chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));\n }\n return Buffer.concat(chunks).toString(\"utf8\");\n}\n\nasync function defaultWriteOut(value: string): Promise<void> {\n await new Promise<void>((resolve, reject) => {\n // The write callback reports failure before the stream emits its error.\n // Keep the one-shot listener until that event to prevent an uncaught EPIPE.\n const onError = (error: Error) => reject(error);\n process.stdout.once(\"error\", onError);\n process.stdout.write(value, (error) => {\n if (error) {\n reject(error);\n } else {\n process.stdout.removeListener(\"error\", onError);\n resolve();\n }\n });\n });\n}\n\nexport async function runCli(\n args: string[],\n dependencies: CliDependencies = {},\n): Promise<number> {\n const outputWriter = dependencies.writeOut ?? defaultWriteOut;\n const writeErr =\n dependencies.writeErr ?? ((value) => process.stderr.write(value));\n let command = \"unknown\";\n let idempotencyKey: string | undefined;\n let schemaVersion = \"1\";\n let meta: Record<string, unknown> | undefined;\n let deliveryReceipt: Record<string, unknown> | undefined;\n const fetchApi = dependencies.fetchApi ?? fetch;\n const writeOut = async (value: string) => {\n try {\n await outputWriter(value);\n } catch {\n throw new CliError(\n EXIT_INTERNAL,\n command === \"fetch\" ? \"RESULT_OUTPUT_FAILED\" : \"OUTPUT_FAILED\",\n \"Cannot write stdout. Use the saved result paths below if present. Otherwise keep this receipt and retry the same fetch with --idempotency-key and the same key.\",\n deliveryReceipt === undefined\n ? undefined\n : { receipt: deliveryReceipt },\n );\n }\n };\n\n try {\n rejectUnsafeCredentialArgument(args);\n const help = requestedHelp(args);\n if (help !== undefined) {\n command = \"help\";\n await writeOut(\n `${JSON.stringify({\n schema_version: \"1\",\n ok: true,\n command,\n data: helpData(help),\n })}\\n`,\n );\n return EXIT_SUCCESS;\n }\n\n const parsed = parseArgs(args);\n command = parsed.command;\n const env = dependencies.env ?? process.env;\n const baseUrl = baseApiUrl(parsed.baseUrl, env);\n\n if (parsed.command === \"skill\") {\n if (\n parsed.positionals[0] !== \"install\" ||\n parsed.positionals.length > 2\n ) {\n throw new CliError(\n EXIT_USAGE,\n \"INVALID_ARGUMENT\",\n \"skill requires 'install' and accepts at most one Skill name\",\n );\n }\n\n const skillName = parsed.positionals[1];\n if (skillName) {\n ensureOnly(parsed.options, [\"agent\", \"global\"]);\n const agent = requiredOption(parsed.options, \"agent\");\n if (!SKILL_NAME_PATTERN.test(skillName)) {\n throw new CliError(\n EXIT_USAGE,\n \"INVALID_ARGUMENT\",\n \"Skill name must contain only lowercase letters, numbers, and single hyphens\",\n );\n }\n if (CORE_SKILL_NAMES.has(skillName)) {\n throw new CliError(\n EXIT_USAGE,\n \"INVALID_ARGUMENT\",\n `Use 'weft skill install' without a name to install the core ${skillName} Skill`,\n );\n }\n if (!SKILL_NAME_PATTERN.test(agent)) {\n throw new CliError(\n EXIT_USAGE,\n \"INVALID_ARGUMENT\",\n \"Agent name must contain only lowercase letters, numbers, and single hyphens\",\n );\n }\n\n const processArgs = [\n \"--yes\",\n \"skills\",\n \"add\",\n \"weftlabs/skills\",\n \"--skill\",\n skillName,\n \"--agent\",\n agent,\n \"--yes\",\n ...(parsed.options.get(\"global\") === true ? [\"--global\"] : []),\n ];\n const invocation = npxProcessInvocation(processArgs, dependencies, env);\n const result = await (dependencies.runProcess ?? defaultRunProcess)(\n invocation.executable,\n invocation.arguments,\n );\n if (result.exitCode !== 0) {\n const remediation = `npx ${processArgs.join(\" \")}`;\n throw new CliError(\n EXIT_INTERNAL,\n \"SKILL_INSTALL_FAILED\",\n `Could not install ${skillName}. Run '${remediation}' directly for more detail.`,\n {\n executable: invocation.executable,\n arguments: invocation.arguments,\n exit_code: result.exitCode,\n stderr: result.stderr,\n },\n );\n }\n await writeOut(\n `${JSON.stringify({\n schema_version: \"1\",\n ok: true,\n command,\n data: {\n status: \"installed\",\n skill: skillName,\n agent,\n scope:\n parsed.options.get(\"global\") === true ? \"global\" : \"project\",\n },\n })}\\n`,\n );\n return EXIT_SUCCESS;\n }\n\n ensureOnly(parsed.options, []);\n const installSkill = await loadSkillInstaller();\n const result = await installSkill({ force: true });\n await writeOut(\n `${JSON.stringify({\n schema_version: \"1\",\n ok: true,\n command,\n data: {\n status: result.status,\n installed: result.installed,\n hosts: result.hosts,\n ...(result.reason === undefined ? {} : { reason: result.reason }),\n ...(result.warnings.length === 0\n ? {}\n : { warnings: result.warnings }),\n },\n })}\\n`,\n );\n return EXIT_SUCCESS;\n }\n\n await installSkillInBackground();\n\n if (parsed.command === \"bootstrap\") {\n ensureOnly(parsed.options, [\"email\", \"agent-name\", \"reason\"]);\n if (parsed.positionals.length !== 0) {\n throw new CliError(\n EXIT_USAGE,\n \"INVALID_ARGUMENT\",\n \"bootstrap does not accept positional arguments\",\n );\n }\n const email = requiredOption(parsed.options, \"email\");\n const agentName = requiredOption(parsed.options, \"agent-name\");\n const reason = requiredOption(parsed.options, \"reason\");\n\n const register = await requestJson<{ client_id: string }>(\n fetchApi,\n `${baseUrl}/oauth/register`,\n {\n method: \"POST\",\n headers: {\n \"content-type\": \"application/json\",\n },\n body: JSON.stringify({\n client_name: OAUTH_CLIENT_NAME,\n redirect_uris: [\"http://localhost/callback\"],\n grant_types: [\n \"urn:ietf:params:oauth:grant-type:device_code\",\n \"refresh_token\",\n ],\n token_endpoint_auth_method: \"none\",\n scope: OAUTH_SCOPE,\n }),\n },\n );\n\n const clientId = register.client_id;\n const bootstrap = await requestJson<BootstrapCreateResponse>(\n fetchApi,\n `${baseUrl}/api/v1/account_bootstraps`,\n {\n method: \"POST\",\n headers: {\n \"content-type\": \"application/json\",\n },\n body: JSON.stringify({\n email,\n agent_name: agentName,\n host_name: OAUTH_HOST_NAME,\n reason,\n oauth_client_id: clientId,\n requested_scopes: [\"balance\", \"fetch\", \"search\"],\n }),\n },\n );\n\n const stored: BootstrapCredentials = {\n version: 1,\n type: \"bootstrap\",\n base_url: baseUrl,\n bootstrap_id: bootstrap.data.id,\n temporary_api_key: bootstrap.data.temporary_api_key,\n device_code: bootstrap.data.device_code,\n client_id: clientId,\n expiry: bootstrap.data.expires_at,\n polling_interval: bootstrap.data.approval.interval,\n };\n\n await writeStoredCredentials(env, stored);\n\n await writeOut(\n `${JSON.stringify({\n schema_version: \"1\",\n ok: true,\n command,\n data: noSecretFields({\n ...bootstrap.data,\n client_id: clientId,\n base_url: baseUrl,\n polling_interval: bootstrap.data.approval.interval,\n }),\n })}\\n`,\n );\n return EXIT_SUCCESS;\n }\n\n if (parsed.command === \"auth\") {\n ensureOnly(parsed.options, []);\n if (\n parsed.positionals.length !== 1 ||\n parsed.positionals[0] !== \"status\"\n ) {\n throw new CliError(\n EXIT_USAGE,\n \"INVALID_ARGUMENT\",\n \"auth requires 'status'\",\n );\n }\n\n const stored = await readStoredCredentials(env);\n if (stored?.type === \"oauth\") {\n await writeOut(\n `${JSON.stringify({\n schema_version: \"1\",\n ok: true,\n command,\n data: {\n status: \"consumed\",\n authentication: \"oauth\",\n scope: stored.scope,\n },\n })}\\n`,\n );\n return EXIT_SUCCESS;\n }\n if (!stored) {\n throw new CliError(\n EXIT_AUTH,\n \"BOOTSTRAP_REQUIRED\",\n \"Run weft bootstrap before auth status\",\n );\n }\n\n const statusBaseUrl = stored.base_url;\n const status = await requestJson<BootstrapStatus>(\n fetchApi,\n `${statusBaseUrl}/api/v1/account_bootstraps/${stored.bootstrap_id}`,\n {\n method: \"GET\",\n headers: withCredentials({}, stored.temporary_api_key),\n },\n );\n\n const statusValue = status.data.status;\n if (statusValue !== \"claimed\" && statusValue !== \"consumed\") {\n await writeOut(\n `${JSON.stringify({\n schema_version: \"1\",\n ok: true,\n command,\n data: { status: statusValue },\n })}\\n`,\n );\n return EXIT_SUCCESS;\n }\n\n const token = await requestJson<OAuthTokenResponse>(\n fetchApi,\n `${statusBaseUrl}/oauth/token`,\n {\n method: \"POST\",\n headers: {\n \"content-type\": \"application/x-www-form-urlencoded\",\n },\n body: new URLSearchParams({\n grant_type: \"urn:ietf:params:oauth:grant-type:device_code\",\n device_code: stored.device_code,\n client_id: stored.client_id,\n name: OAUTH_CLIENT_NAME,\n }).toString(),\n },\n true,\n );\n\n const oauth: OAuthCredentials = {\n version: 1,\n type: \"oauth\",\n base_url: statusBaseUrl,\n client_id: stored.client_id,\n access_token: token.access_token,\n refresh_token: token.refresh_token,\n token_type: token.token_type,\n scope: token.scope,\n expiry: new Date(Date.now() + token.expires_in * 1000).toISOString(),\n };\n await writeStoredCredentials(env, oauth);\n\n await writeOut(\n `${JSON.stringify({\n schema_version: \"1\",\n ok: true,\n command,\n data: {\n status: \"consumed\",\n authentication: \"oauth\",\n scope: token.scope,\n },\n })}\\n`,\n );\n return EXIT_SUCCESS;\n }\n\n const rawKey = parsed.apiKeyStdin\n ? await (dependencies.readStdin ?? defaultReadStdin)()\n : env.WEFT_API_KEY;\n let apiKey = rawKey?.trim();\n let authenticatedBaseUrl = baseUrl;\n if (parsed.apiKeyStdin && !apiKey) {\n throw new CliError(\n EXIT_AUTH,\n \"API_KEY_REQUIRED\",\n \"--api-key-stdin requires a non-empty API key\",\n );\n }\n if (!apiKey && !parsed.apiKeyStdin) {\n let stored = await readStoredCredentials(env);\n if (stored?.type === \"oauth\" && oauthNeedsRefresh(stored)) {\n stored = await withCredentialsLock(env, async () => {\n const current = await readStoredCredentials(env);\n if (current?.type === \"oauth\" && oauthNeedsRefresh(current)) {\n return refreshOAuthCredentials(fetchApi, env, current);\n }\n return current;\n });\n }\n apiKey = resolveApiKeyFromStored(stored);\n if (stored) authenticatedBaseUrl = stored.base_url;\n }\n\n if (!apiKey) {\n throw new CliError(\n EXIT_AUTH,\n \"API_KEY_REQUIRED\",\n \"Set WEFT_API_KEY, pass --api-key-stdin, or store credentials\",\n );\n }\n\n const client = new WeftClient({\n apiKey,\n baseUrl: authenticatedBaseUrl,\n fetchApi,\n });\n\n let data: unknown;\n if (parsed.command === \"me\") {\n ensureOnly(parsed.options, []);\n data = await client.me();\n } else if (parsed.command === \"balance\") {\n ensureOnly(parsed.options, []);\n data = await client.balance();\n } else if (parsed.command === \"search\") {\n ensureOnly(parsed.options, [\"max-results\"]);\n if (parsed.positionals.length !== 1) {\n throw new CliError(\n EXIT_USAGE,\n \"INVALID_ARGUMENT\",\n \"search requires exactly one query\",\n );\n }\n data = await client.search({\n query: parsed.positionals[0],\n maxResults: positiveInteger(\n parsed.options.get(\"max-results\"),\n \"--max-results\",\n 50,\n ),\n });\n } else if (parsed.command === \"fetch\") {\n ensureOnly(parsed.options, [\n \"max-cost-usd\",\n \"method\",\n \"idempotency-key\",\n \"raw\",\n ]);\n const raw = parsed.options.has(\"raw\");\n schemaVersion = raw ? \"1\" : \"2\";\n if (parsed.positionals.length !== 1) {\n throw new CliError(\n EXIT_USAGE,\n \"INVALID_ARGUMENT\",\n \"fetch requires exactly one URL\",\n );\n }\n const maxCostUsd = requiredOption(parsed.options, \"max-cost-usd\");\n if (!/^\\d+(?:\\.\\d+)?$/.test(maxCostUsd) || Number(maxCostUsd) <= 0) {\n throw new CliError(\n EXIT_USAGE,\n \"INVALID_ARGUMENT\",\n \"--max-cost-usd must be a positive decimal\",\n );\n }\n const method = parsed.options.get(\"method\");\n const request: PaidFetchRequest = {\n url: parsed.positionals[0],\n maxCostUsd,\n method:\n typeof method === \"string\"\n ? (method.toUpperCase() as PaidFetchRequest[\"method\"])\n : undefined,\n };\n const explicitKey = parsed.options.get(\"idempotency-key\");\n idempotencyKey =\n typeof explicitKey === \"string\"\n ? explicitKey\n : (dependencies.generateIdempotencyKey ?? randomUUID)();\n let resultDirectory: string | undefined;\n if (!raw) {\n try {\n resultDirectory = await reserveResultDirectory(env);\n } catch {\n throw new CliError(\n EXIT_INTERNAL,\n \"RESULT_STORAGE_UNAVAILABLE\",\n \"Cannot reserve local result storage. Set WEFT_RESULTS_DIR to a directory you own that is writable only by you, with no symlink at that path, then retry. No fetch was sent.\",\n );\n }\n }\n const response = await client.fetch(request, { idempotencyKey });\n meta = { idempotency_key: idempotencyKey };\n data = response;\n const { bodyBase64, ...receipt } = response;\n deliveryReceipt = receipt;\n if (resultDirectory) {\n const savedPath = join(resultDirectory, \"body\");\n const receiptPath = join(resultDirectory, \"receipt.json\");\n const bytes =\n typeof bodyBase64 === \"string\"\n ? Buffer.from(bodyBase64, \"base64\")\n : undefined;\n if (!bytes || bytes.toString(\"base64\") !== bodyBase64) {\n throw new CliError(\n EXIT_INTERNAL,\n \"RESULT_DECODE_FAILED\",\n \"Fetch returned invalid Base64. No body was saved. Keep this receipt and retry the same request with --idempotency-key and the same key; if it persists, report the artifact ID to support.\",\n { receipt, file_complete: false },\n );\n }\n try {\n meta = {\n ...meta,\n saved_path: savedPath,\n receipt_path: receiptPath,\n byte_count: bytes.length,\n };\n await writeResultFile(\n receiptPath,\n `${JSON.stringify({ schema_version: \"2\", meta, data: receipt })}\\n`,\n );\n await writeResultFile(savedPath, bytes);\n data = { ...receipt, ...readableBody(bytes, response.headers) };\n } catch {\n throw new CliError(\n EXIT_INTERNAL,\n \"RESULT_STORAGE_FAILED\",\n \"Fetch returned, but local result delivery failed. Keep this receipt. Check local storage, then retry the same request with --idempotency-key and the key below. Do not use a new key.\",\n {\n receipt,\n saved_path: savedPath,\n receipt_path: receiptPath,\n file_complete: false,\n },\n );\n }\n }\n } else {\n ensureOnly(parsed.options, [\"page\", \"per-page\"]);\n if (parsed.positionals.length > 1) {\n throw new CliError(\n EXIT_USAGE,\n \"INVALID_ARGUMENT\",\n \"purchases accepts at most one purchase ID\",\n );\n }\n data = parsed.positionals[0]\n ? await client.purchase(\n positiveInteger(parsed.positionals[0], \"purchase ID\")!,\n )\n : await client.purchases({\n page: positiveInteger(parsed.options.get(\"page\"), \"--page\"),\n perPage: positiveInteger(\n parsed.options.get(\"per-page\"),\n \"--per-page\",\n 100,\n ),\n });\n }\n\n await writeOut(\n `${JSON.stringify({\n schema_version: schemaVersion,\n ok: true,\n command,\n ...(meta === undefined ? {} : { meta }),\n data,\n })}\\n`,\n );\n return EXIT_SUCCESS;\n } catch (error) {\n const normalized = await normalizeError(error);\n writeErr(\n `${JSON.stringify({\n schema_version: schemaVersion,\n ok: false,\n command,\n ...(idempotencyKey === undefined\n ? {}\n : { meta: { ...meta, idempotency_key: idempotencyKey } }),\n error: {\n code: normalized.code,\n message: normalized.message,\n ...(normalized.details === undefined\n ? {}\n : { details: normalized.details }),\n },\n })}\\n`,\n );\n return normalized.exitCode;\n }\n}\n","import { chmod, lstat, mkdir, mkdtemp, open, realpath } from \"node:fs/promises\";\nimport { homedir } from \"node:os\";\nimport { join, resolve } from \"node:path\";\n\nexport async function reserveResultDirectory(\n env: Record<string, string | undefined>,\n): Promise<string> {\n const root = resolve(\n env.WEFT_RESULTS_DIR ||\n join(env.HOME || env.USERPROFILE || homedir(), \".weft-results\"),\n );\n await mkdir(root, { recursive: true, mode: 0o700 });\n const stat = await lstat(root);\n if (!stat.isDirectory() || stat.isSymbolicLink()) {\n throw new Error(\n \"The result storage root must be a directory, not a symlink\",\n );\n }\n if (\n process.platform !== \"win32\" &&\n ((stat.mode & 0o022) !== 0 || stat.uid !== process.getuid?.())\n ) {\n throw new Error(\n \"The result storage root must be owned by this user and not writable by others\",\n );\n }\n // A private child keeps payloads protected without changing an existing parent.\n const directory = await mkdtemp(join(await realpath(root), \"result-\"));\n await chmod(directory, 0o700);\n return directory;\n}\n\nexport async function writeResultFile(\n path: string,\n contents: string | Buffer,\n): Promise<void> {\n const file = await open(path, \"wx\", 0o600);\n try {\n await file.chmod(0o600);\n await file.writeFile(contents);\n await file.sync();\n } finally {\n await file.close();\n }\n}\n\nexport function readableBody(\n bytes: Buffer,\n headers: Record<string, string>,\n): {\n media_type: string | null;\n body_encoding: \"utf-8\" | \"file\";\n body?: string;\n} {\n const header = (name: string) =>\n Object.entries(headers).find(([key]) => key.toLowerCase() === name)?.[1];\n const contentType = header(\"content-type\")?.toLowerCase() ?? \"\";\n const mediaType = contentType.split(\";\", 1)[0].trim();\n const charset = /(?:^|;)\\s*charset\\s*=\\s*\"?([^;\"\\s]+)/.exec(contentType)?.[1];\n const encoding = header(\"content-encoding\")?.trim().toLowerCase();\n const file = {\n media_type: mediaType || null,\n body_encoding: \"file\" as const,\n };\n const textual =\n mediaType.startsWith(\"text/\") ||\n /^application\\/(?:json|xml|javascript|x-ndjson|x-www-form-urlencoded|[^;]+\\+(?:json|xml))$/.test(\n mediaType,\n );\n if (\n (encoding && encoding !== \"identity\") ||\n (charset && ![\"utf-8\", \"utf8\", \"us-ascii\"].includes(charset)) ||\n (!textual && !(bytes.length === 0 && !mediaType))\n )\n return file;\n try {\n // Keep a UTF-8 BOM and JSON spelling exactly as delivered.\n const body = new TextDecoder(\"utf-8\", {\n fatal: true,\n ignoreBOM: true,\n }).decode(bytes);\n return { media_type: mediaType || null, body_encoding: \"utf-8\", body };\n } catch {\n return file;\n }\n}\n"],"mappings":"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","names":["randomUUID","dirname","join","chmod","mkdir","open","resolve","dirname","join","message","result","randomUUID"]}
|
|
1
|
+
{"version":3,"sources":["../src/credentials.ts","../src/cli.ts","../src/results.ts"],"sourcesContent":["import { randomUUID } from \"node:crypto\";\nimport {\n chmod,\n mkdir,\n open,\n readFile,\n rename,\n rm,\n writeFile,\n} from \"node:fs/promises\";\nimport { dirname } from \"node:path\";\nimport { setTimeout as delay } from \"node:timers/promises\";\n\nconst CREDENTIALS_FILE_MODE = 0o600;\nconst CREDENTIALS_DIR_MODE = 0o700;\nconst LOCK_RETRY_MS = 50;\nconst LOCK_TIMEOUT_MS = 10_000;\n\nexport interface BootstrapCredentials {\n base_url: string;\n id: string;\n status: string;\n capabilities: string[];\n expires_at: string | null;\n approval: {\n method: string;\n expires_in: number;\n interval: number;\n user_code?: string;\n };\n temporary_api_key: string;\n}\n\nexport interface LegacyBootstrapCredentials {\n version: 1;\n type: \"bootstrap\";\n base_url: string;\n bootstrap_id: string;\n temporary_api_key: string;\n device_code: string;\n client_id: string;\n expiry: string;\n polling_interval: number;\n}\n\nexport interface OAuthCredentials {\n version: 1;\n type: \"oauth\";\n base_url: string;\n client_id: string;\n access_token: string;\n refresh_token: string;\n token_type: string;\n scope: string;\n expiry: string;\n}\n\nexport type StoredCredentials =\n BootstrapCredentials | LegacyBootstrapCredentials | OAuthCredentials;\n\nfunction isObject(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null;\n}\n\nfunction isBootstrapCredentials(\n value: Record<string, unknown>,\n): BootstrapCredentials | undefined {\n if (\n typeof value.base_url === \"string\" &&\n typeof value.id === \"string\" &&\n typeof value.status === \"string\" &&\n Array.isArray(value.capabilities) &&\n value.capabilities.every((capability) => typeof capability === \"string\") &&\n (typeof value.expires_at === \"string\" || value.expires_at === null) &&\n isObject(value.approval) &&\n typeof value.approval.method === \"string\" &&\n typeof value.approval.expires_in === \"number\" &&\n typeof value.approval.interval === \"number\" &&\n (value.approval.user_code === undefined ||\n typeof value.approval.user_code === \"string\") &&\n typeof value.temporary_api_key === \"string\"\n ) {\n return value as BootstrapCredentials;\n }\n\n return undefined;\n}\n\nfunction isLegacyBootstrapCredentials(\n value: Record<string, unknown>,\n): LegacyBootstrapCredentials | undefined {\n if (\n value.version === 1 &&\n value.type === \"bootstrap\" &&\n typeof value.base_url === \"string\" &&\n typeof value.bootstrap_id === \"string\" &&\n typeof value.temporary_api_key === \"string\" &&\n typeof value.device_code === \"string\" &&\n typeof value.client_id === \"string\" &&\n typeof value.expiry === \"string\" &&\n typeof value.polling_interval === \"number\"\n ) {\n return value as LegacyBootstrapCredentials;\n }\n\n return undefined;\n}\n\nfunction isOAuthCredentials(\n value: Record<string, unknown>,\n): OAuthCredentials | undefined {\n if (\n value.type === \"oauth\" &&\n typeof value.version === \"number\" &&\n typeof value.base_url === \"string\" &&\n typeof value.client_id === \"string\" &&\n typeof value.access_token === \"string\" &&\n typeof value.refresh_token === \"string\" &&\n typeof value.token_type === \"string\" &&\n typeof value.scope === \"string\" &&\n typeof value.expiry === \"string\"\n ) {\n return value as OAuthCredentials;\n }\n\n return undefined;\n}\n\nexport function resolveCredentialsPath(\n env: Record<string, string | undefined>,\n): string | undefined {\n if (env.WEFT_CREDENTIALS_FILE) return env.WEFT_CREDENTIALS_FILE;\n if (env.XDG_CONFIG_HOME)\n return `${env.XDG_CONFIG_HOME}/weft/credentials.json`;\n const home = env.HOME || env.USERPROFILE;\n if (!home) return undefined;\n return `${home}/.config/weft/credentials.json`;\n}\n\nexport async function readStoredCredentials(\n env: Record<string, string | undefined>,\n): Promise<StoredCredentials | undefined> {\n const path = resolveCredentialsPath(env);\n if (!path) return undefined;\n try {\n const raw = await readFile(path, \"utf8\");\n const parsed: unknown = JSON.parse(raw);\n if (!isObject(parsed)) throw new Error(\"Stored credentials malformed\");\n return (\n isBootstrapCredentials(parsed) ??\n isLegacyBootstrapCredentials(parsed) ??\n isOAuthCredentials(parsed)\n );\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === \"ENOENT\") return undefined;\n throw error;\n }\n}\n\nexport async function writeStoredCredentials(\n env: Record<string, string | undefined>,\n credentials: StoredCredentials,\n): Promise<void> {\n await withCredentialsLock(env, () =>\n writeStoredCredentialsWhileLocked(env, credentials),\n );\n}\n\nexport async function writeStoredCredentialsWhileLocked(\n env: Record<string, string | undefined>,\n credentials: StoredCredentials,\n): Promise<void> {\n const path = resolveCredentialsPath(env);\n if (!path) {\n throw new Error(\"HOME, USERPROFILE, or WEFT_CREDENTIALS_FILE is required\");\n }\n const parent = dirname(path);\n await mkdir(parent, { recursive: true, mode: CREDENTIALS_DIR_MODE });\n await chmod(parent, CREDENTIALS_DIR_MODE);\n\n const tempPath = `${path}.${randomUUID()}.tmp`;\n try {\n await writeFile(tempPath, JSON.stringify(credentials), {\n mode: CREDENTIALS_FILE_MODE,\n });\n await rename(tempPath, path);\n await chmod(path, CREDENTIALS_FILE_MODE);\n } catch (error) {\n await rm(tempPath, { force: true });\n throw error;\n }\n}\n\nexport async function withCredentialsLock<T>(\n env: Record<string, string | undefined>,\n action: () => Promise<T>,\n): Promise<T> {\n const path = resolveCredentialsPath(env);\n if (!path) {\n throw new Error(\"HOME, USERPROFILE, or WEFT_CREDENTIALS_FILE is required\");\n }\n const lockPath = `${path}.lock`;\n const deadline = Date.now() + LOCK_TIMEOUT_MS;\n await mkdir(dirname(path), { recursive: true, mode: CREDENTIALS_DIR_MODE });\n\n for (;;) {\n try {\n const lock = await open(lockPath, \"wx\", CREDENTIALS_FILE_MODE);\n await lock.close();\n break;\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== \"EEXIST\") throw error;\n if (Date.now() >= deadline) {\n throw new Error(\n `Timed out waiting for the credential lock; if no Weft CLI process is running, remove ${lockPath}`,\n );\n }\n await delay(LOCK_RETRY_MS);\n }\n }\n\n try {\n return await action();\n } finally {\n await rm(lockPath, { force: true });\n }\n}\n","import {\n readStoredCredentials,\n type BootstrapCredentials,\n type LegacyBootstrapCredentials,\n type OAuthCredentials,\n type StoredCredentials,\n withCredentialsLock,\n writeStoredCredentials,\n writeStoredCredentialsWhileLocked,\n} from \"./credentials\";\nimport { spawn } from \"node:child_process\";\nimport { randomUUID } from \"node:crypto\";\nimport { existsSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport {\n readableBody,\n reserveResultDirectory,\n writeResultFile,\n} from \"./results\";\nimport {\n type PaidFetchRequest,\n ResponseError,\n WeftClient,\n WeftError,\n} from \"@weftlabs/sdk\";\n\nexport const EXIT_SUCCESS = 0;\nexport const EXIT_USAGE = 2;\nexport const EXIT_AUTH = 3;\nexport const EXIT_API = 4;\nexport const EXIT_INTERNAL = 5;\n\ntype Command =\n | \"bootstrap\"\n | \"auth\"\n | \"skill\"\n | \"me\"\n | \"balance\"\n | \"search\"\n | \"fetch\"\n | \"purchases\";\n\nconst COMMANDS: Command[] = [\n \"bootstrap\",\n \"auth\",\n \"skill\",\n \"me\",\n \"balance\",\n \"search\",\n \"fetch\",\n \"purchases\",\n];\n\nconst WEFT_API_BASE = \"https://weft.network\";\nconst OAUTH_HOST_NAME = \"Weft CLI\";\nconst OAUTH_REFRESH_SKEW_MS = 60_000;\nconst PROCESS_OUTPUT_LIMIT = 8_192;\nconst SKILL_NAME_PATTERN = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;\nconst CORE_SKILL_NAMES = new Set([\"weft\", \"weft-setup\"]);\n\nconst COMMAND_HELP = {\n bootstrap: {\n description: \"Bootstrap an agent account\",\n usage: \"weft bootstrap --email <email> --agent-name <name> --reason <text>\",\n options: [\n \"--email <email>\",\n \"--agent-name <name>\",\n \"--reason <text>\",\n \"[--base-url <url>]\",\n ],\n },\n auth: {\n description: \"Check bootstrap status\",\n usage: \"weft auth status\",\n options: [\"status\"],\n },\n skill: {\n description: \"Install the core Weft Skill or one optional workflow Skill\",\n usage: \"weft skill install [name --agent <agent> [--global]]\",\n options: [\"install\", \"[name]\", \"--agent <agent>\", \"--global\"],\n },\n me: {\n description: \"Return the authenticated principal\",\n usage: \"weft me\",\n options: [],\n },\n balance: {\n description: \"Return wallet balance and spending policy\",\n usage: \"weft balance\",\n options: [],\n },\n search: {\n description: \"Search for payable resources\",\n usage: \"weft search <query> [--max-results <1..50>]\",\n options: [\"--max-results <1..50>\"],\n },\n fetch: {\n description: \"Fetch a URL within an explicit spending limit\",\n usage:\n \"weft fetch <url> --max-cost-usd <amount> [--method <method>] [--idempotency-key <key>] [--raw]\",\n options: [\n \"--max-cost-usd <amount>\",\n \"--method <method>\",\n \"--idempotency-key <key>\",\n \"--raw\",\n ],\n },\n purchases: {\n description: \"List purchases or return one purchase by ID\",\n usage: \"weft purchases [id] [--page <number>] [--per-page <1..100>]\",\n options: [\"--page <number>\", \"--per-page <1..100>\"],\n },\n} satisfies Record<\n Command,\n { description: string; usage: string; options: string[] }\n>;\n\ninterface SkillInstallResult {\n status: \"ok\" | \"skipped\";\n reason?: string;\n installed: number;\n hosts: string[];\n warnings: string[];\n}\n\ntype SkillInstaller = (options?: {\n force?: boolean;\n silent?: boolean;\n}) => Promise<SkillInstallResult>;\n\n/**\n * The Skill installer ships as a plain script beside `dist/`, and reads the\n * packed Skill relative to its own location. The specifier is built at runtime\n * so the bundler leaves it external and that relative path stays correct in the\n * published package.\n */\nasync function loadSkillInstaller(): Promise<SkillInstaller> {\n const specifier = new URL(\"../scripts/install-skill.mjs\", import.meta.url)\n .href;\n const module = (await import(specifier)) as { installSkill: SkillInstaller };\n return module.installSkill;\n}\n\n/**\n * Best-effort Skill installation on any ordinary command. This is the safety\n * net for a user who never runs `weft skill install`, and it is what lets the\n * Skill appear in an agent host that was installed after the CLI. It is\n * idempotent, it stays silent, and it never fails the command the user asked\n * for.\n */\nasync function installSkillInBackground(): Promise<void> {\n try {\n const installSkill = await loadSkillInstaller();\n await installSkill({ silent: true });\n } catch {\n // Deliberately ignored — `weft skill install` is the surface that reports\n // installation problems.\n }\n}\n\ninterface BootstrapCreateResponse {\n data: Omit<BootstrapCredentials, \"base_url\">;\n}\n\ninterface BootstrapStatus {\n data: {\n id?: string;\n status: string;\n expires_at?: string | null;\n capabilities?: string[];\n approval?: BootstrapCredentials[\"approval\"];\n };\n}\n\ninterface OAuthTokenResponse {\n access_token: string;\n token_type: string;\n expires_in: number;\n refresh_token: string;\n scope: string;\n}\n\nconst GLOBAL_OPTIONS = [\"--api-key-stdin\", \"--base-url <url>\", \"--help\", \"-h\"];\n\nexport interface CliDependencies {\n env?: Record<string, string | undefined>;\n fetchApi?: typeof fetch;\n readStdin?: () => Promise<string>;\n writeOut?: (value: string) => void | Promise<void>;\n writeErr?: (value: string) => void;\n generateIdempotencyKey?: () => string;\n runProcess?: ProcessRunner;\n platform?: NodeJS.Platform;\n nodeExecutable?: string;\n npxCliPath?: string;\n}\n\ninterface ProcessResult {\n exitCode: number;\n stdout: string;\n stderr: string;\n}\n\ntype ProcessRunner = (\n command: string,\n args: string[],\n) => Promise<ProcessResult>;\n\ninterface ParsedArgs {\n command: Command;\n apiKeyStdin: boolean;\n baseUrl?: string;\n positionals: string[];\n options: Map<string, string | true>;\n}\n\nclass CliError extends Error {\n constructor(\n readonly exitCode: number,\n readonly code: string,\n message: string,\n readonly details?: unknown,\n ) {\n super(message);\n }\n}\n\nfunction takeValue(\n args: string[],\n index: number,\n option: string,\n): [string, number] {\n const value = args[index + 1];\n if (value == null || value.startsWith(\"--\")) {\n throw new CliError(\n EXIT_USAGE,\n \"INVALID_ARGUMENT\",\n `${option} requires a value`,\n );\n }\n return [value, index + 1];\n}\n\nfunction appendBounded(current: string, chunk: Buffer | string): string {\n return `${current}${chunk.toString()}`.slice(-PROCESS_OUTPUT_LIMIT);\n}\n\nfunction defaultRunProcess(\n command: string,\n args: string[],\n): Promise<ProcessResult> {\n return new Promise((resolve) => {\n const child = spawn(command, args, {\n shell: false,\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n });\n let stdout = \"\";\n let stderr = \"\";\n child.stdout.on(\"data\", (chunk: Buffer) => {\n stdout = appendBounded(stdout, chunk);\n });\n child.stderr.on(\"data\", (chunk: Buffer) => {\n stderr = appendBounded(stderr, chunk);\n });\n child.on(\"error\", (error) => {\n resolve({\n exitCode: 1,\n stdout,\n stderr: appendBounded(stderr, error.message),\n });\n });\n child.on(\"close\", (exitCode) => {\n resolve({ exitCode: exitCode ?? 1, stdout, stderr });\n });\n });\n}\n\nfunction resolveNpxCliPath(\n env: Record<string, string | undefined>,\n nodeExecutable: string,\n): string | undefined {\n const executableDirectory = dirname(nodeExecutable);\n const candidates = [\n ...(env.npm_execpath\n ? [join(dirname(env.npm_execpath), \"npx-cli.js\")]\n : []),\n join(executableDirectory, \"node_modules\", \"npm\", \"bin\", \"npx-cli.js\"),\n join(\n executableDirectory,\n \"..\",\n \"lib\",\n \"node_modules\",\n \"npm\",\n \"bin\",\n \"npx-cli.js\",\n ),\n ];\n return candidates.find((candidate) => existsSync(candidate));\n}\n\nfunction npxProcessInvocation(\n processArgs: string[],\n dependencies: CliDependencies,\n env: Record<string, string | undefined>,\n): { executable: string; arguments: string[] } {\n if ((dependencies.platform ?? process.platform) !== \"win32\") {\n return { executable: \"npx\", arguments: processArgs };\n }\n\n const nodeExecutable = dependencies.nodeExecutable ?? process.execPath;\n const npxCliPath =\n dependencies.npxCliPath ?? resolveNpxCliPath(env, nodeExecutable);\n if (!npxCliPath) {\n throw new CliError(\n EXIT_INTERNAL,\n \"NPX_NOT_FOUND\",\n \"Could not find the npm npx program. Install npm, then run the command again.\",\n );\n }\n return {\n executable: nodeExecutable,\n arguments: [npxCliPath, ...processArgs],\n };\n}\n\nfunction rejectUnsafeCredentialArgument(args: string[]): void {\n if (args.some((arg) => arg === \"--api-key\" || arg.startsWith(\"--api-key=\"))) {\n throw new CliError(\n EXIT_USAGE,\n \"UNSAFE_CREDENTIAL_ARGUMENT\",\n \"API keys are accepted only through WEFT_API_KEY or --api-key-stdin\",\n );\n }\n}\n\nfunction requestedHelp(args: string[]): Command | \"all\" | undefined {\n const isHelp = (value: string) => value === \"--help\" || value === \"-h\";\n if (args.length === 1 && isHelp(args[0])) return \"all\";\n if (\n args.length === 2 &&\n COMMANDS.includes(args[0] as Command) &&\n isHelp(args[1])\n ) {\n return args[0] as Command;\n }\n return undefined;\n}\n\nfunction helpData(command: Command | \"all\") {\n if (command !== \"all\") {\n return {\n command,\n ...COMMAND_HELP[command],\n global_options: GLOBAL_OPTIONS,\n };\n }\n return {\n usage: \"weft <command> [options]\",\n commands: COMMANDS.map((name) => ({ name, ...COMMAND_HELP[name] })),\n global_options: GLOBAL_OPTIONS,\n authentication: [\"WEFT_API_KEY\", \"--api-key-stdin\"],\n exit_codes: { success: 0, usage: 2, auth: 3, api: 4, internal: 5 },\n };\n}\n\nfunction parseArgs(args: string[]): ParsedArgs {\n let command: Command | undefined;\n let apiKeyStdin = false;\n let baseUrl: string | undefined;\n const positionals: string[] = [];\n const options = new Map<string, string | true>();\n\n for (let index = 0; index < args.length; index += 1) {\n const arg = args[index];\n if (arg === \"--api-key-stdin\") {\n apiKeyStdin = true;\n } else if (arg === \"--base-url\") {\n [baseUrl, index] = takeValue(args, index, arg);\n } else if (arg === \"--global\" || arg === \"--raw\") {\n options.set(arg.slice(2), true);\n } else if (arg.startsWith(\"--\")) {\n const [value, nextIndex] = takeValue(args, index, arg);\n options.set(arg.slice(2), value);\n index = nextIndex;\n } else if (!command) {\n if (!COMMANDS.includes(arg as Command)) {\n throw new CliError(\n EXIT_USAGE,\n \"UNKNOWN_COMMAND\",\n `Unknown command: ${arg}`,\n );\n }\n command = arg as Command;\n } else {\n positionals.push(arg);\n }\n }\n\n if (!command) {\n throw new CliError(\n EXIT_USAGE,\n \"COMMAND_REQUIRED\",\n \"Command required: bootstrap, auth, me, balance, search, fetch, or purchases\",\n );\n }\n\n return { command, apiKeyStdin, baseUrl, positionals, options };\n}\n\nfunction positiveInteger(\n value: string | true | undefined,\n option: string,\n maximum?: number,\n): number | undefined {\n if (value == null) return undefined;\n const parsed = Number(value);\n if (!Number.isInteger(parsed) || parsed <= 0) {\n throw new CliError(\n EXIT_USAGE,\n \"INVALID_ARGUMENT\",\n `${option} must be a positive integer`,\n );\n }\n if (maximum != null && parsed > maximum) {\n throw new CliError(\n EXIT_USAGE,\n \"INVALID_ARGUMENT\",\n `${option} must be at most ${maximum}`,\n );\n }\n return parsed;\n}\n\nfunction requiredOption(\n options: Map<string, string | true>,\n name: string,\n): string {\n const value = options.get(name);\n if (typeof value !== \"string\" || !value.trim()) {\n throw new CliError(EXIT_USAGE, \"MISSING_ARGUMENT\", `--${name} is required`);\n }\n return value;\n}\n\nfunction baseApiUrl(\n baseUrl: string | undefined,\n env: Record<string, string | undefined>,\n): string {\n const raw = baseUrl ?? env.WEFT_BASE_URL ?? WEFT_API_BASE;\n return raw.endsWith(\"/\") ? raw.slice(0, -1) : raw;\n}\n\nfunction resolveApiKeyFromStored(\n credentials?: StoredCredentials,\n): string | undefined {\n if (!credentials) return undefined;\n if (\n \"access_token\" in credentials &&\n typeof credentials.access_token === \"string\" &&\n credentials.access_token.trim()\n ) {\n return credentials.access_token;\n }\n if (\n \"temporary_api_key\" in credentials &&\n typeof credentials.temporary_api_key === \"string\" &&\n credentials.temporary_api_key.trim()\n ) {\n return credentials.temporary_api_key;\n }\n return undefined;\n}\n\nfunction isOAuthCredentials(\n credentials: StoredCredentials | undefined,\n): credentials is OAuthCredentials {\n return Boolean(\n credentials && \"type\" in credentials && credentials.type === \"oauth\",\n );\n}\n\nfunction isLegacyBootstrapCredentials(\n credentials: StoredCredentials | undefined,\n): credentials is LegacyBootstrapCredentials {\n return Boolean(\n credentials && \"type\" in credentials && credentials.type === \"bootstrap\",\n );\n}\n\nfunction oauthNeedsRefresh(credentials: OAuthCredentials): boolean {\n const expiry = Date.parse(credentials.expiry);\n return (\n !Number.isFinite(expiry) || expiry <= Date.now() + OAUTH_REFRESH_SKEW_MS\n );\n}\n\nasync function refreshOAuthCredentials(\n fetchApi: typeof fetch,\n env: Record<string, string | undefined>,\n stored: OAuthCredentials,\n): Promise<OAuthCredentials> {\n const token = await requestJson<OAuthTokenResponse>(\n fetchApi,\n `${stored.base_url}/oauth/token`,\n {\n method: \"POST\",\n headers: { \"content-type\": \"application/x-www-form-urlencoded\" },\n body: new URLSearchParams({\n grant_type: \"refresh_token\",\n refresh_token: stored.refresh_token,\n client_id: stored.client_id,\n }).toString(),\n },\n true,\n );\n const refreshed: OAuthCredentials = {\n ...stored,\n access_token: token.access_token,\n refresh_token: token.refresh_token,\n token_type: token.token_type,\n scope: token.scope,\n expiry: new Date(Date.now() + token.expires_in * 1000).toISOString(),\n };\n await writeStoredCredentialsWhileLocked(env, refreshed);\n return refreshed;\n}\n\nfunction noSecretFields(data: object): Record<string, unknown> {\n return {\n ...data,\n temporary_api_key: undefined,\n access_token: undefined,\n refresh_token: undefined,\n client_secret: undefined,\n };\n}\n\nasync function requestJson<T>(\n fetchApi: typeof fetch,\n url: string,\n init: RequestInit,\n redactError = false,\n): Promise<T> {\n const response = await fetchApi(url, init);\n if (!response.ok) {\n if (redactError) {\n throw new CliError(\n response.status === 401 || response.status === 403\n ? EXIT_AUTH\n : response.status >= 500\n ? EXIT_INTERNAL\n : EXIT_API,\n \"OAUTH_TOKEN_ERROR\",\n `OAuth token request failed with HTTP ${response.status}`,\n );\n }\n throw new ResponseError(response);\n }\n\n return (await response.json()) as T;\n}\n\nfunction withCredentials(\n headers: Record<string, string>,\n apiKey: string,\n): Record<string, string> {\n return {\n ...headers,\n authorization: `Bearer ${apiKey}`,\n };\n}\n\nfunction ensureOnly(\n options: Map<string, string | true>,\n allowed: string[],\n): void {\n for (const name of options.keys()) {\n if (!allowed.includes(name)) {\n throw new CliError(\n EXIT_USAGE,\n \"UNKNOWN_OPTION\",\n `Unknown option: --${name}`,\n );\n }\n }\n}\n\nasync function responseDetails(error: ResponseError): Promise<unknown> {\n try {\n return await error.response.json();\n } catch {\n return undefined;\n }\n}\n\nasync function normalizeError(error: unknown): Promise<CliError> {\n if (error instanceof CliError) return error;\n if (error instanceof WeftError) {\n // status 0 is a transport failure with no API response; it exits like an\n // internal failure, not an API rejection.\n const exitCode =\n error.status === 401 || error.status === 403\n ? EXIT_AUTH\n : error.status >= 500 || error.status === 0\n ? EXIT_INTERNAL\n : EXIT_API;\n return new CliError(exitCode, error.code, error.message, error.details);\n }\n if (error instanceof ResponseError) {\n const details = await responseDetails(error);\n const body = details as\n | {\n error?: { code?: string; message?: string } | string;\n error_description?: string;\n }\n | undefined;\n const nested = typeof body?.error === \"object\" ? body.error : undefined;\n const code =\n nested?.code ??\n (typeof body?.error === \"string\"\n ? body.error\n : `HTTP_${error.response.status}`);\n const message =\n nested?.message ??\n body?.error_description ??\n `Weft API returned HTTP ${error.response.status}`;\n const exitCode =\n error.response.status === 401 || error.response.status === 403\n ? EXIT_AUTH\n : error.response.status >= 500\n ? EXIT_INTERNAL\n : EXIT_API;\n return new CliError(exitCode, code, message, details);\n }\n const message = error instanceof Error ? error.message : String(error);\n return new CliError(EXIT_INTERNAL, \"INTERNAL_ERROR\", message);\n}\n\nasync function defaultReadStdin(): Promise<string> {\n const chunks: Buffer[] = [];\n for await (const chunk of process.stdin) {\n chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));\n }\n return Buffer.concat(chunks).toString(\"utf8\");\n}\n\nasync function defaultWriteOut(value: string): Promise<void> {\n await new Promise<void>((resolve, reject) => {\n // The write callback reports failure before the stream emits its error.\n // Keep the one-shot listener until that event to prevent an uncaught EPIPE.\n const onError = (error: Error) => reject(error);\n process.stdout.once(\"error\", onError);\n process.stdout.write(value, (error) => {\n if (error) {\n reject(error);\n } else {\n process.stdout.removeListener(\"error\", onError);\n resolve();\n }\n });\n });\n}\n\nexport async function runCli(\n args: string[],\n dependencies: CliDependencies = {},\n): Promise<number> {\n const outputWriter = dependencies.writeOut ?? defaultWriteOut;\n const writeErr =\n dependencies.writeErr ?? ((value) => process.stderr.write(value));\n let command = \"unknown\";\n let idempotencyKey: string | undefined;\n let schemaVersion = \"1\";\n let meta: Record<string, unknown> | undefined;\n let deliveryReceipt: Record<string, unknown> | undefined;\n const fetchApi = dependencies.fetchApi ?? fetch;\n const writeOut = async (value: string) => {\n try {\n await outputWriter(value);\n } catch {\n throw new CliError(\n EXIT_INTERNAL,\n command === \"fetch\" ? \"RESULT_OUTPUT_FAILED\" : \"OUTPUT_FAILED\",\n \"Cannot write stdout. Use the saved result paths below if present. Otherwise keep this receipt and retry the same fetch with --idempotency-key and the same key.\",\n deliveryReceipt === undefined\n ? undefined\n : { receipt: deliveryReceipt },\n );\n }\n };\n\n try {\n rejectUnsafeCredentialArgument(args);\n const help = requestedHelp(args);\n if (help !== undefined) {\n command = \"help\";\n await writeOut(\n `${JSON.stringify({\n schema_version: \"1\",\n ok: true,\n command,\n data: helpData(help),\n })}\\n`,\n );\n return EXIT_SUCCESS;\n }\n\n const parsed = parseArgs(args);\n command = parsed.command;\n const env = dependencies.env ?? process.env;\n const baseUrl = baseApiUrl(parsed.baseUrl, env);\n\n if (parsed.command === \"skill\") {\n if (\n parsed.positionals[0] !== \"install\" ||\n parsed.positionals.length > 2\n ) {\n throw new CliError(\n EXIT_USAGE,\n \"INVALID_ARGUMENT\",\n \"skill requires 'install' and accepts at most one Skill name\",\n );\n }\n\n const skillName = parsed.positionals[1];\n if (skillName) {\n ensureOnly(parsed.options, [\"agent\", \"global\"]);\n const agent = requiredOption(parsed.options, \"agent\");\n if (!SKILL_NAME_PATTERN.test(skillName)) {\n throw new CliError(\n EXIT_USAGE,\n \"INVALID_ARGUMENT\",\n \"Skill name must contain only lowercase letters, numbers, and single hyphens\",\n );\n }\n if (CORE_SKILL_NAMES.has(skillName)) {\n throw new CliError(\n EXIT_USAGE,\n \"INVALID_ARGUMENT\",\n `Use 'weft skill install' without a name to install the core ${skillName} Skill`,\n );\n }\n if (!SKILL_NAME_PATTERN.test(agent)) {\n throw new CliError(\n EXIT_USAGE,\n \"INVALID_ARGUMENT\",\n \"Agent name must contain only lowercase letters, numbers, and single hyphens\",\n );\n }\n\n const processArgs = [\n \"--yes\",\n \"skills\",\n \"add\",\n \"weftlabs/skills\",\n \"--skill\",\n skillName,\n \"--agent\",\n agent,\n \"--yes\",\n ...(parsed.options.get(\"global\") === true ? [\"--global\"] : []),\n ];\n const invocation = npxProcessInvocation(processArgs, dependencies, env);\n const result = await (dependencies.runProcess ?? defaultRunProcess)(\n invocation.executable,\n invocation.arguments,\n );\n if (result.exitCode !== 0) {\n const remediation = `npx ${processArgs.join(\" \")}`;\n throw new CliError(\n EXIT_INTERNAL,\n \"SKILL_INSTALL_FAILED\",\n `Could not install ${skillName}. Run '${remediation}' directly for more detail.`,\n {\n executable: invocation.executable,\n arguments: invocation.arguments,\n exit_code: result.exitCode,\n stderr: result.stderr,\n },\n );\n }\n await writeOut(\n `${JSON.stringify({\n schema_version: \"1\",\n ok: true,\n command,\n data: {\n status: \"installed\",\n skill: skillName,\n agent,\n scope:\n parsed.options.get(\"global\") === true ? \"global\" : \"project\",\n },\n })}\\n`,\n );\n return EXIT_SUCCESS;\n }\n\n ensureOnly(parsed.options, []);\n const installSkill = await loadSkillInstaller();\n const result = await installSkill({ force: true });\n await writeOut(\n `${JSON.stringify({\n schema_version: \"1\",\n ok: true,\n command,\n data: {\n status: result.status,\n installed: result.installed,\n hosts: result.hosts,\n ...(result.reason === undefined ? {} : { reason: result.reason }),\n ...(result.warnings.length === 0\n ? {}\n : { warnings: result.warnings }),\n },\n })}\\n`,\n );\n return EXIT_SUCCESS;\n }\n\n await installSkillInBackground();\n\n if (parsed.command === \"bootstrap\") {\n ensureOnly(parsed.options, [\"email\", \"agent-name\", \"reason\"]);\n if (parsed.positionals.length !== 0) {\n throw new CliError(\n EXIT_USAGE,\n \"INVALID_ARGUMENT\",\n \"bootstrap does not accept positional arguments\",\n );\n }\n const email = requiredOption(parsed.options, \"email\");\n const agentName = requiredOption(parsed.options, \"agent-name\");\n const reason = requiredOption(parsed.options, \"reason\");\n\n const bootstrap = await requestJson<BootstrapCreateResponse>(\n fetchApi,\n `${baseUrl}/api/v1/account_bootstraps`,\n {\n method: \"POST\",\n headers: {\n \"content-type\": \"application/json\",\n },\n body: JSON.stringify({\n email,\n agent_name: agentName,\n host_name: OAUTH_HOST_NAME,\n reason,\n }),\n },\n );\n\n const stored: BootstrapCredentials = {\n ...bootstrap.data,\n base_url: baseUrl,\n };\n\n await writeStoredCredentials(env, stored);\n\n await writeOut(\n `${JSON.stringify({\n schema_version: \"1\",\n ok: true,\n command,\n data: noSecretFields(stored),\n })}\\n`,\n );\n return EXIT_SUCCESS;\n }\n\n if (parsed.command === \"auth\") {\n ensureOnly(parsed.options, []);\n if (\n parsed.positionals.length !== 1 ||\n parsed.positionals[0] !== \"status\"\n ) {\n throw new CliError(\n EXIT_USAGE,\n \"INVALID_ARGUMENT\",\n \"auth requires 'status'\",\n );\n }\n\n const stored = await readStoredCredentials(env);\n if (isOAuthCredentials(stored)) {\n await writeOut(\n `${JSON.stringify({\n schema_version: \"1\",\n ok: true,\n command,\n data: {\n status: \"consumed\",\n authentication: \"oauth\",\n scope: stored.scope,\n },\n })}\\n`,\n );\n return EXIT_SUCCESS;\n }\n if (isLegacyBootstrapCredentials(stored)) {\n const status = await requestJson<BootstrapStatus>(\n fetchApi,\n `${stored.base_url}/api/v1/account_bootstraps/${stored.bootstrap_id}`,\n {\n method: \"GET\",\n headers: withCredentials({}, stored.temporary_api_key),\n },\n );\n if (\n status.data.status !== \"claimed\" &&\n status.data.status !== \"consumed\"\n ) {\n await writeOut(\n `${JSON.stringify({\n schema_version: \"1\",\n ok: true,\n command,\n data: { status: status.data.status },\n })}\\n`,\n );\n return EXIT_SUCCESS;\n }\n\n const token = await requestJson<OAuthTokenResponse>(\n fetchApi,\n `${stored.base_url}/oauth/token`,\n {\n method: \"POST\",\n headers: {\n \"content-type\": \"application/x-www-form-urlencoded\",\n },\n body: new URLSearchParams({\n grant_type: \"urn:ietf:params:oauth:grant-type:device_code\",\n device_code: stored.device_code,\n client_id: stored.client_id,\n name: \"Weft CLI\",\n }).toString(),\n },\n true,\n );\n const oauth: OAuthCredentials = {\n version: 1,\n type: \"oauth\",\n base_url: stored.base_url,\n client_id: stored.client_id,\n access_token: token.access_token,\n refresh_token: token.refresh_token,\n token_type: token.token_type,\n scope: token.scope,\n expiry: new Date(Date.now() + token.expires_in * 1000).toISOString(),\n };\n const active = await withCredentialsLock(env, async () => {\n const current = await readStoredCredentials(env);\n if (isOAuthCredentials(current)) return current;\n if (\n !isLegacyBootstrapCredentials(current) ||\n JSON.stringify(current) !== JSON.stringify(stored)\n ) {\n throw new CliError(\n EXIT_AUTH,\n \"CREDENTIALS_CHANGED\",\n \"Stored credentials changed; rerun auth status\",\n );\n }\n await writeStoredCredentialsWhileLocked(env, oauth);\n return oauth;\n });\n await writeOut(\n `${JSON.stringify({\n schema_version: \"1\",\n ok: true,\n command,\n data: {\n status: \"consumed\",\n authentication: \"oauth\",\n scope: active.scope,\n },\n })}\\n`,\n );\n return EXIT_SUCCESS;\n }\n if (!stored) {\n throw new CliError(\n EXIT_AUTH,\n \"BOOTSTRAP_REQUIRED\",\n \"Run weft bootstrap before auth status\",\n );\n }\n\n const status = await requestJson<BootstrapStatus>(\n fetchApi,\n `${stored.base_url}/api/v1/account_bootstraps/${stored.id}`,\n {\n method: \"GET\",\n headers: withCredentials({}, stored.temporary_api_key),\n },\n );\n\n const merged: BootstrapCredentials = {\n base_url: stored.base_url,\n id: status.data.id ?? stored.id,\n status: status.data.status,\n capabilities: status.data.capabilities ?? stored.capabilities,\n expires_at:\n status.data.expires_at === undefined\n ? stored.expires_at\n : status.data.expires_at,\n approval: status.data.approval ?? stored.approval,\n temporary_api_key: stored.temporary_api_key,\n };\n const active = await withCredentialsLock(env, async () => {\n const current = await readStoredCredentials(env);\n if (JSON.stringify(current) !== JSON.stringify(stored)) {\n throw new CliError(\n EXIT_AUTH,\n \"CREDENTIALS_CHANGED\",\n \"Stored credentials changed; rerun auth status\",\n );\n }\n await writeStoredCredentialsWhileLocked(env, merged);\n return merged;\n });\n\n await writeOut(\n `${JSON.stringify({\n schema_version: \"1\",\n ok: true,\n command,\n data: noSecretFields(active),\n })}\\n`,\n );\n return EXIT_SUCCESS;\n }\n\n const rawKey = parsed.apiKeyStdin\n ? await (dependencies.readStdin ?? defaultReadStdin)()\n : env.WEFT_API_KEY;\n let apiKey = rawKey?.trim();\n let authenticatedBaseUrl = baseUrl;\n if (parsed.apiKeyStdin && !apiKey) {\n throw new CliError(\n EXIT_AUTH,\n \"API_KEY_REQUIRED\",\n \"--api-key-stdin requires a non-empty API key\",\n );\n }\n if (!apiKey && !parsed.apiKeyStdin) {\n let stored = await readStoredCredentials(env);\n if (isOAuthCredentials(stored) && oauthNeedsRefresh(stored)) {\n stored = await withCredentialsLock(env, async () => {\n const current = await readStoredCredentials(env);\n if (isOAuthCredentials(current) && oauthNeedsRefresh(current)) {\n return refreshOAuthCredentials(fetchApi, env, current);\n }\n return current;\n });\n }\n apiKey = resolveApiKeyFromStored(stored);\n if (stored) {\n authenticatedBaseUrl = stored.base_url;\n }\n }\n\n if (!apiKey) {\n throw new CliError(\n EXIT_AUTH,\n \"API_KEY_REQUIRED\",\n \"Set WEFT_API_KEY, pass --api-key-stdin, or store credentials\",\n );\n }\n\n const client = new WeftClient({\n apiKey,\n baseUrl: authenticatedBaseUrl,\n fetchApi,\n });\n\n let data: unknown;\n if (parsed.command === \"me\") {\n ensureOnly(parsed.options, []);\n data = await client.me();\n } else if (parsed.command === \"balance\") {\n ensureOnly(parsed.options, []);\n data = await client.balance();\n } else if (parsed.command === \"search\") {\n ensureOnly(parsed.options, [\"max-results\"]);\n if (parsed.positionals.length !== 1) {\n throw new CliError(\n EXIT_USAGE,\n \"INVALID_ARGUMENT\",\n \"search requires exactly one query\",\n );\n }\n data = await client.search({\n query: parsed.positionals[0],\n maxResults: positiveInteger(\n parsed.options.get(\"max-results\"),\n \"--max-results\",\n 50,\n ),\n });\n } else if (parsed.command === \"fetch\") {\n ensureOnly(parsed.options, [\n \"max-cost-usd\",\n \"method\",\n \"idempotency-key\",\n \"raw\",\n ]);\n const raw = parsed.options.has(\"raw\");\n schemaVersion = raw ? \"1\" : \"2\";\n if (parsed.positionals.length !== 1) {\n throw new CliError(\n EXIT_USAGE,\n \"INVALID_ARGUMENT\",\n \"fetch requires exactly one URL\",\n );\n }\n const maxCostUsd = requiredOption(parsed.options, \"max-cost-usd\");\n if (!/^\\d+(?:\\.\\d+)?$/.test(maxCostUsd) || Number(maxCostUsd) <= 0) {\n throw new CliError(\n EXIT_USAGE,\n \"INVALID_ARGUMENT\",\n \"--max-cost-usd must be a positive decimal\",\n );\n }\n const method = parsed.options.get(\"method\");\n const request: PaidFetchRequest = {\n url: parsed.positionals[0],\n maxCostUsd,\n method:\n typeof method === \"string\"\n ? (method.toUpperCase() as PaidFetchRequest[\"method\"])\n : undefined,\n };\n const explicitKey = parsed.options.get(\"idempotency-key\");\n idempotencyKey =\n typeof explicitKey === \"string\"\n ? explicitKey\n : (dependencies.generateIdempotencyKey ?? randomUUID)();\n let resultDirectory: string | undefined;\n if (!raw) {\n try {\n resultDirectory = await reserveResultDirectory(env);\n } catch {\n throw new CliError(\n EXIT_INTERNAL,\n \"RESULT_STORAGE_UNAVAILABLE\",\n \"Cannot reserve local result storage. Set WEFT_RESULTS_DIR to a directory you own that is writable only by you, with no symlink at that path, then retry. No fetch was sent.\",\n );\n }\n }\n const response = await client.fetch(request, { idempotencyKey });\n meta = { idempotency_key: idempotencyKey };\n data = response;\n const { bodyBase64, ...receipt } = response;\n deliveryReceipt = receipt;\n if (resultDirectory) {\n const savedPath = join(resultDirectory, \"body\");\n const receiptPath = join(resultDirectory, \"receipt.json\");\n const bytes =\n typeof bodyBase64 === \"string\"\n ? Buffer.from(bodyBase64, \"base64\")\n : undefined;\n if (!bytes || bytes.toString(\"base64\") !== bodyBase64) {\n throw new CliError(\n EXIT_INTERNAL,\n \"RESULT_DECODE_FAILED\",\n \"Fetch returned invalid Base64. No body was saved. Keep this receipt and retry the same request with --idempotency-key and the same key; if it persists, report the artifact ID to support.\",\n { receipt, file_complete: false },\n );\n }\n try {\n meta = {\n ...meta,\n saved_path: savedPath,\n receipt_path: receiptPath,\n byte_count: bytes.length,\n };\n await writeResultFile(\n receiptPath,\n `${JSON.stringify({ schema_version: \"2\", meta, data: receipt })}\\n`,\n );\n await writeResultFile(savedPath, bytes);\n data = { ...receipt, ...readableBody(bytes, response.headers) };\n } catch {\n throw new CliError(\n EXIT_INTERNAL,\n \"RESULT_STORAGE_FAILED\",\n \"Fetch returned, but local result delivery failed. Keep this receipt. Check local storage, then retry the same request with --idempotency-key and the key below. Do not use a new key.\",\n {\n receipt,\n saved_path: savedPath,\n receipt_path: receiptPath,\n file_complete: false,\n },\n );\n }\n }\n } else {\n ensureOnly(parsed.options, [\"page\", \"per-page\"]);\n if (parsed.positionals.length > 1) {\n throw new CliError(\n EXIT_USAGE,\n \"INVALID_ARGUMENT\",\n \"purchases accepts at most one purchase ID\",\n );\n }\n data = parsed.positionals[0]\n ? await client.purchase(\n positiveInteger(parsed.positionals[0], \"purchase ID\")!,\n )\n : await client.purchases({\n page: positiveInteger(parsed.options.get(\"page\"), \"--page\"),\n perPage: positiveInteger(\n parsed.options.get(\"per-page\"),\n \"--per-page\",\n 100,\n ),\n });\n }\n\n await writeOut(\n `${JSON.stringify({\n schema_version: schemaVersion,\n ok: true,\n command,\n ...(meta === undefined ? {} : { meta }),\n data,\n })}\\n`,\n );\n return EXIT_SUCCESS;\n } catch (error) {\n const normalized = await normalizeError(error);\n writeErr(\n `${JSON.stringify({\n schema_version: schemaVersion,\n ok: false,\n command,\n ...(idempotencyKey === undefined\n ? {}\n : { meta: { ...meta, idempotency_key: idempotencyKey } }),\n error: {\n code: normalized.code,\n message: normalized.message,\n ...(normalized.details === undefined\n ? {}\n : { details: normalized.details }),\n },\n })}\\n`,\n );\n return normalized.exitCode;\n }\n}\n","import { chmod, lstat, mkdir, mkdtemp, open, realpath } from \"node:fs/promises\";\nimport { homedir } from \"node:os\";\nimport { join, resolve } from \"node:path\";\n\nexport async function reserveResultDirectory(\n env: Record<string, string | undefined>,\n): Promise<string> {\n const root = resolve(\n env.WEFT_RESULTS_DIR ||\n join(env.HOME || env.USERPROFILE || homedir(), \".weft-results\"),\n );\n await mkdir(root, { recursive: true, mode: 0o700 });\n const stat = await lstat(root);\n if (!stat.isDirectory() || stat.isSymbolicLink()) {\n throw new Error(\n \"The result storage root must be a directory, not a symlink\",\n );\n }\n if (\n process.platform !== \"win32\" &&\n ((stat.mode & 0o022) !== 0 || stat.uid !== process.getuid?.())\n ) {\n throw new Error(\n \"The result storage root must be owned by this user and not writable by others\",\n );\n }\n // A private child keeps payloads protected without changing an existing parent.\n const directory = await mkdtemp(join(await realpath(root), \"result-\"));\n await chmod(directory, 0o700);\n return directory;\n}\n\nexport async function writeResultFile(\n path: string,\n contents: string | Buffer,\n): Promise<void> {\n const file = await open(path, \"wx\", 0o600);\n try {\n await file.chmod(0o600);\n await file.writeFile(contents);\n await file.sync();\n } finally {\n await file.close();\n }\n}\n\nexport function readableBody(\n bytes: Buffer,\n headers: Record<string, string>,\n): {\n media_type: string | null;\n body_encoding: \"utf-8\" | \"file\";\n body?: string;\n} {\n const header = (name: string) =>\n Object.entries(headers).find(([key]) => key.toLowerCase() === name)?.[1];\n const contentType = header(\"content-type\")?.toLowerCase() ?? \"\";\n const mediaType = contentType.split(\";\", 1)[0].trim();\n const charset = /(?:^|;)\\s*charset\\s*=\\s*\"?([^;\"\\s]+)/.exec(contentType)?.[1];\n const encoding = header(\"content-encoding\")?.trim().toLowerCase();\n const file = {\n media_type: mediaType || null,\n body_encoding: \"file\" as const,\n };\n const textual =\n mediaType.startsWith(\"text/\") ||\n /^application\\/(?:json|xml|javascript|x-ndjson|x-www-form-urlencoded|[^;]+\\+(?:json|xml))$/.test(\n mediaType,\n );\n if (\n (encoding && encoding !== \"identity\") ||\n (charset && ![\"utf-8\", \"utf8\", \"us-ascii\"].includes(charset)) ||\n (!textual && !(bytes.length === 0 && !mediaType))\n )\n return file;\n try {\n // Keep a UTF-8 BOM and JSON spelling exactly as delivered.\n const body = new TextDecoder(\"utf-8\", {\n fatal: true,\n ignoreBOM: true,\n }).decode(bytes);\n return { media_type: mediaType || null, body_encoding: \"utf-8\", body };\n } catch {\n return file;\n }\n}\n"],"mappings":";AAAA,SAAS,kBAAkB;AAC3B;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,eAAe;AACxB,SAAS,cAAc,aAAa;AAEpC,IAAM,wBAAwB;AAC9B,IAAM,uBAAuB;AAC7B,IAAM,gBAAgB;AACtB,IAAM,kBAAkB;AA4CxB,SAAS,SAAS,OAAkD;AAClE,SAAO,OAAO,UAAU,YAAY,UAAU;AAChD;AAEA,SAAS,uBACP,OACkC;AAClC,MACE,OAAO,MAAM,aAAa,YAC1B,OAAO,MAAM,OAAO,YACpB,OAAO,MAAM,WAAW,YACxB,MAAM,QAAQ,MAAM,YAAY,KAChC,MAAM,aAAa,MAAM,CAAC,eAAe,OAAO,eAAe,QAAQ,MACtE,OAAO,MAAM,eAAe,YAAY,MAAM,eAAe,SAC9D,SAAS,MAAM,QAAQ,KACvB,OAAO,MAAM,SAAS,WAAW,YACjC,OAAO,MAAM,SAAS,eAAe,YACrC,OAAO,MAAM,SAAS,aAAa,aAClC,MAAM,SAAS,cAAc,UAC5B,OAAO,MAAM,SAAS,cAAc,aACtC,OAAO,MAAM,sBAAsB,UACnC;AACA,WAAO;AAAA,EACT;AAEA,SAAO;AACT;AAEA,SAAS,6BACP,OACwC;AACxC,MACE,MAAM,YAAY,KAClB,MAAM,SAAS,eACf,OAAO,MAAM,aAAa,YAC1B,OAAO,MAAM,iBAAiB,YAC9B,OAAO,MAAM,sBAAsB,YACnC,OAAO,MAAM,gBAAgB,YAC7B,OAAO,MAAM,cAAc,YAC3B,OAAO,MAAM,WAAW,YACxB,OAAO,MAAM,qBAAqB,UAClC;AACA,WAAO;AAAA,EACT;AAEA,SAAO;AACT;AAEA,SAAS,mBACP,OAC8B;AAC9B,MACE,MAAM,SAAS,WACf,OAAO,MAAM,YAAY,YACzB,OAAO,MAAM,aAAa,YAC1B,OAAO,MAAM,cAAc,YAC3B,OAAO,MAAM,iBAAiB,YAC9B,OAAO,MAAM,kBAAkB,YAC/B,OAAO,MAAM,eAAe,YAC5B,OAAO,MAAM,UAAU,YACvB,OAAO,MAAM,WAAW,UACxB;AACA,WAAO;AAAA,EACT;AAEA,SAAO;AACT;AAEO,SAAS,uBACd,KACoB;AACpB,MAAI,IAAI,sBAAuB,QAAO,IAAI;AAC1C,MAAI,IAAI;AACN,WAAO,GAAG,IAAI,eAAe;AAC/B,QAAM,OAAO,IAAI,QAAQ,IAAI;AAC7B,MAAI,CAAC,KAAM,QAAO;AAClB,SAAO,GAAG,IAAI;AAChB;AAEA,eAAsB,sBACpB,KACwC;AACxC,QAAM,OAAO,uBAAuB,GAAG;AACvC,MAAI,CAAC,KAAM,QAAO;AAClB,MAAI;AACF,UAAM,MAAM,MAAM,SAAS,MAAM,MAAM;AACvC,UAAM,SAAkB,KAAK,MAAM,GAAG;AACtC,QAAI,CAAC,SAAS,MAAM,EAAG,OAAM,IAAI,MAAM,8BAA8B;AACrE,WACE,uBAAuB,MAAM,KAC7B,6BAA6B,MAAM,KACnC,mBAAmB,MAAM;AAAA,EAE7B,SAAS,OAAO;AACd,QAAK,MAAgC,SAAS,SAAU,QAAO;AAC/D,UAAM;AAAA,EACR;AACF;AAEA,eAAsB,uBACpB,KACA,aACe;AACf,QAAM;AAAA,IAAoB;AAAA,IAAK,MAC7B,kCAAkC,KAAK,WAAW;AAAA,EACpD;AACF;AAEA,eAAsB,kCACpB,KACA,aACe;AACf,QAAM,OAAO,uBAAuB,GAAG;AACvC,MAAI,CAAC,MAAM;AACT,UAAM,IAAI,MAAM,yDAAyD;AAAA,EAC3E;AACA,QAAM,SAAS,QAAQ,IAAI;AAC3B,QAAM,MAAM,QAAQ,EAAE,WAAW,MAAM,MAAM,qBAAqB,CAAC;AACnE,QAAM,MAAM,QAAQ,oBAAoB;AAExC,QAAM,WAAW,GAAG,IAAI,IAAI,WAAW,CAAC;AACxC,MAAI;AACF,UAAM,UAAU,UAAU,KAAK,UAAU,WAAW,GAAG;AAAA,MACrD,MAAM;AAAA,IACR,CAAC;AACD,UAAM,OAAO,UAAU,IAAI;AAC3B,UAAM,MAAM,MAAM,qBAAqB;AAAA,EACzC,SAAS,OAAO;AACd,UAAM,GAAG,UAAU,EAAE,OAAO,KAAK,CAAC;AAClC,UAAM;AAAA,EACR;AACF;AAEA,eAAsB,oBACpB,KACA,QACY;AACZ,QAAM,OAAO,uBAAuB,GAAG;AACvC,MAAI,CAAC,MAAM;AACT,UAAM,IAAI,MAAM,yDAAyD;AAAA,EAC3E;AACA,QAAM,WAAW,GAAG,IAAI;AACxB,QAAM,WAAW,KAAK,IAAI,IAAI;AAC9B,QAAM,MAAM,QAAQ,IAAI,GAAG,EAAE,WAAW,MAAM,MAAM,qBAAqB,CAAC;AAE1E,aAAS;AACP,QAAI;AACF,YAAM,OAAO,MAAM,KAAK,UAAU,MAAM,qBAAqB;AAC7D,YAAM,KAAK,MAAM;AACjB;AAAA,IACF,SAAS,OAAO;AACd,UAAK,MAAgC,SAAS,SAAU,OAAM;AAC9D,UAAI,KAAK,IAAI,KAAK,UAAU;AAC1B,cAAM,IAAI;AAAA,UACR,wFAAwF,QAAQ;AAAA,QAClG;AAAA,MACF;AACA,YAAM,MAAM,aAAa;AAAA,IAC3B;AAAA,EACF;AAEA,MAAI;AACF,WAAO,MAAM,OAAO;AAAA,EACtB,UAAE;AACA,UAAM,GAAG,UAAU,EAAE,OAAO,KAAK,CAAC;AAAA,EACpC;AACF;;;ACxNA,SAAS,aAAa;AACtB,SAAS,cAAAA,mBAAkB;AAC3B,SAAS,kBAAkB;AAC3B,SAAS,WAAAC,UAAS,QAAAC,aAAY;;;ACb9B,SAAS,SAAAC,QAAO,OAAO,SAAAC,QAAO,SAAS,QAAAC,OAAM,gBAAgB;AAC7D,SAAS,eAAe;AACxB,SAAS,MAAM,eAAe;AAE9B,eAAsB,uBACpB,KACiB;AACjB,QAAM,OAAO;AAAA,IACX,IAAI,oBACF,KAAK,IAAI,QAAQ,IAAI,eAAe,QAAQ,GAAG,eAAe;AAAA,EAClE;AACA,QAAMD,OAAM,MAAM,EAAE,WAAW,MAAM,MAAM,IAAM,CAAC;AAClD,QAAM,OAAO,MAAM,MAAM,IAAI;AAC7B,MAAI,CAAC,KAAK,YAAY,KAAK,KAAK,eAAe,GAAG;AAChD,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AACA,MACE,QAAQ,aAAa,aACnB,KAAK,OAAO,QAAW,KAAK,KAAK,QAAQ,QAAQ,SAAS,IAC5D;AACA,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAEA,QAAM,YAAY,MAAM,QAAQ,KAAK,MAAM,SAAS,IAAI,GAAG,SAAS,CAAC;AACrE,QAAMD,OAAM,WAAW,GAAK;AAC5B,SAAO;AACT;AAEA,eAAsB,gBACpB,MACA,UACe;AACf,QAAM,OAAO,MAAME,MAAK,MAAM,MAAM,GAAK;AACzC,MAAI;AACF,UAAM,KAAK,MAAM,GAAK;AACtB,UAAM,KAAK,UAAU,QAAQ;AAC7B,UAAM,KAAK,KAAK;AAAA,EAClB,UAAE;AACA,UAAM,KAAK,MAAM;AAAA,EACnB;AACF;AAEO,SAAS,aACd,OACA,SAKA;AACA,QAAM,SAAS,CAAC,SACd,OAAO,QAAQ,OAAO,EAAE,KAAK,CAAC,CAAC,GAAG,MAAM,IAAI,YAAY,MAAM,IAAI,IAAI,CAAC;AACzE,QAAM,cAAc,OAAO,cAAc,GAAG,YAAY,KAAK;AAC7D,QAAM,YAAY,YAAY,MAAM,KAAK,CAAC,EAAE,CAAC,EAAE,KAAK;AACpD,QAAM,UAAU,uCAAuC,KAAK,WAAW,IAAI,CAAC;AAC5E,QAAM,WAAW,OAAO,kBAAkB,GAAG,KAAK,EAAE,YAAY;AAChE,QAAM,OAAO;AAAA,IACX,YAAY,aAAa;AAAA,IACzB,eAAe;AAAA,EACjB;AACA,QAAM,UACJ,UAAU,WAAW,OAAO,KAC5B,4FAA4F;AAAA,IAC1F;AAAA,EACF;AACF,MACG,YAAY,aAAa,cACzB,WAAW,CAAC,CAAC,SAAS,QAAQ,UAAU,EAAE,SAAS,OAAO,KAC1D,CAAC,WAAW,EAAE,MAAM,WAAW,KAAK,CAAC;AAEtC,WAAO;AACT,MAAI;AAEF,UAAM,OAAO,IAAI,YAAY,SAAS;AAAA,MACpC,OAAO;AAAA,MACP,WAAW;AAAA,IACb,CAAC,EAAE,OAAO,KAAK;AACf,WAAO,EAAE,YAAY,aAAa,MAAM,eAAe,SAAS,KAAK;AAAA,EACvE,QAAQ;AACN,WAAO;AAAA,EACT;AACF;;;ADlEA;AAAA,EAEE;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAEA,IAAM,eAAe;AACrB,IAAM,aAAa;AACnB,IAAM,YAAY;AAClB,IAAM,WAAW;AACjB,IAAM,gBAAgB;AAY7B,IAAM,WAAsB;AAAA,EAC1B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEA,IAAM,gBAAgB;AACtB,IAAM,kBAAkB;AACxB,IAAM,wBAAwB;AAC9B,IAAM,uBAAuB;AAC7B,IAAM,qBAAqB;AAC3B,IAAM,mBAAmB,oBAAI,IAAI,CAAC,QAAQ,YAAY,CAAC;AAEvD,IAAM,eAAe;AAAA,EACnB,WAAW;AAAA,IACT,aAAa;AAAA,IACb,OAAO;AAAA,IACP,SAAS;AAAA,MACP;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EACA,MAAM;AAAA,IACJ,aAAa;AAAA,IACb,OAAO;AAAA,IACP,SAAS,CAAC,QAAQ;AAAA,EACpB;AAAA,EACA,OAAO;AAAA,IACL,aAAa;AAAA,IACb,OAAO;AAAA,IACP,SAAS,CAAC,WAAW,UAAU,mBAAmB,UAAU;AAAA,EAC9D;AAAA,EACA,IAAI;AAAA,IACF,aAAa;AAAA,IACb,OAAO;AAAA,IACP,SAAS,CAAC;AAAA,EACZ;AAAA,EACA,SAAS;AAAA,IACP,aAAa;AAAA,IACb,OAAO;AAAA,IACP,SAAS,CAAC;AAAA,EACZ;AAAA,EACA,QAAQ;AAAA,IACN,aAAa;AAAA,IACb,OAAO;AAAA,IACP,SAAS,CAAC,uBAAuB;AAAA,EACnC;AAAA,EACA,OAAO;AAAA,IACL,aAAa;AAAA,IACb,OACE;AAAA,IACF,SAAS;AAAA,MACP;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EACA,WAAW;AAAA,IACT,aAAa;AAAA,IACb,OAAO;AAAA,IACP,SAAS,CAAC,mBAAmB,qBAAqB;AAAA,EACpD;AACF;AAwBA,eAAe,qBAA8C;AAC3D,QAAM,YAAY,IAAI,IAAI,gCAAgC,YAAY,GAAG,EACtE;AACH,QAAM,SAAU,MAAM,OAAO;AAC7B,SAAO,OAAO;AAChB;AASA,eAAe,2BAA0C;AACvD,MAAI;AACF,UAAM,eAAe,MAAM,mBAAmB;AAC9C,UAAM,aAAa,EAAE,QAAQ,KAAK,CAAC;AAAA,EACrC,QAAQ;AAAA,EAGR;AACF;AAwBA,IAAM,iBAAiB,CAAC,mBAAmB,oBAAoB,UAAU,IAAI;AAkC7E,IAAM,WAAN,cAAuB,MAAM;AAAA,EAC3B,YACW,UACA,MACT,SACS,SACT;AACA,UAAM,OAAO;AALJ;AACA;AAEA;AAAA,EAGX;AACF;AAEA,SAAS,UACP,MACA,OACA,QACkB;AAClB,QAAM,QAAQ,KAAK,QAAQ,CAAC;AAC5B,MAAI,SAAS,QAAQ,MAAM,WAAW,IAAI,GAAG;AAC3C,UAAM,IAAI;AAAA,MACR;AAAA,MACA;AAAA,MACA,GAAG,MAAM;AAAA,IACX;AAAA,EACF;AACA,SAAO,CAAC,OAAO,QAAQ,CAAC;AAC1B;AAEA,SAAS,cAAc,SAAiB,OAAgC;AACtE,SAAO,GAAG,OAAO,GAAG,MAAM,SAAS,CAAC,GAAG,MAAM,CAAC,oBAAoB;AACpE;AAEA,SAAS,kBACP,SACA,MACwB;AACxB,SAAO,IAAI,QAAQ,CAACC,aAAY;AAC9B,UAAM,QAAQ,MAAM,SAAS,MAAM;AAAA,MACjC,OAAO;AAAA,MACP,OAAO,CAAC,UAAU,QAAQ,MAAM;AAAA,IAClC,CAAC;AACD,QAAI,SAAS;AACb,QAAI,SAAS;AACb,UAAM,OAAO,GAAG,QAAQ,CAAC,UAAkB;AACzC,eAAS,cAAc,QAAQ,KAAK;AAAA,IACtC,CAAC;AACD,UAAM,OAAO,GAAG,QAAQ,CAAC,UAAkB;AACzC,eAAS,cAAc,QAAQ,KAAK;AAAA,IACtC,CAAC;AACD,UAAM,GAAG,SAAS,CAAC,UAAU;AAC3B,MAAAA,SAAQ;AAAA,QACN,UAAU;AAAA,QACV;AAAA,QACA,QAAQ,cAAc,QAAQ,MAAM,OAAO;AAAA,MAC7C,CAAC;AAAA,IACH,CAAC;AACD,UAAM,GAAG,SAAS,CAAC,aAAa;AAC9B,MAAAA,SAAQ,EAAE,UAAU,YAAY,GAAG,QAAQ,OAAO,CAAC;AAAA,IACrD,CAAC;AAAA,EACH,CAAC;AACH;AAEA,SAAS,kBACP,KACA,gBACoB;AACpB,QAAM,sBAAsBC,SAAQ,cAAc;AAClD,QAAM,aAAa;AAAA,IACjB,GAAI,IAAI,eACJ,CAACC,MAAKD,SAAQ,IAAI,YAAY,GAAG,YAAY,CAAC,IAC9C,CAAC;AAAA,IACLC,MAAK,qBAAqB,gBAAgB,OAAO,OAAO,YAAY;AAAA,IACpEA;AAAA,MACE;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACA,SAAO,WAAW,KAAK,CAAC,cAAc,WAAW,SAAS,CAAC;AAC7D;AAEA,SAAS,qBACP,aACA,cACA,KAC6C;AAC7C,OAAK,aAAa,YAAY,QAAQ,cAAc,SAAS;AAC3D,WAAO,EAAE,YAAY,OAAO,WAAW,YAAY;AAAA,EACrD;AAEA,QAAM,iBAAiB,aAAa,kBAAkB,QAAQ;AAC9D,QAAM,aACJ,aAAa,cAAc,kBAAkB,KAAK,cAAc;AAClE,MAAI,CAAC,YAAY;AACf,UAAM,IAAI;AAAA,MACR;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACA,SAAO;AAAA,IACL,YAAY;AAAA,IACZ,WAAW,CAAC,YAAY,GAAG,WAAW;AAAA,EACxC;AACF;AAEA,SAAS,+BAA+B,MAAsB;AAC5D,MAAI,KAAK,KAAK,CAAC,QAAQ,QAAQ,eAAe,IAAI,WAAW,YAAY,CAAC,GAAG;AAC3E,UAAM,IAAI;AAAA,MACR;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACF;AAEA,SAAS,cAAc,MAA6C;AAClE,QAAM,SAAS,CAAC,UAAkB,UAAU,YAAY,UAAU;AAClE,MAAI,KAAK,WAAW,KAAK,OAAO,KAAK,CAAC,CAAC,EAAG,QAAO;AACjD,MACE,KAAK,WAAW,KAChB,SAAS,SAAS,KAAK,CAAC,CAAY,KACpC,OAAO,KAAK,CAAC,CAAC,GACd;AACA,WAAO,KAAK,CAAC;AAAA,EACf;AACA,SAAO;AACT;AAEA,SAAS,SAAS,SAA0B;AAC1C,MAAI,YAAY,OAAO;AACrB,WAAO;AAAA,MACL;AAAA,MACA,GAAG,aAAa,OAAO;AAAA,MACvB,gBAAgB;AAAA,IAClB;AAAA,EACF;AACA,SAAO;AAAA,IACL,OAAO;AAAA,IACP,UAAU,SAAS,IAAI,CAAC,UAAU,EAAE,MAAM,GAAG,aAAa,IAAI,EAAE,EAAE;AAAA,IAClE,gBAAgB;AAAA,IAChB,gBAAgB,CAAC,gBAAgB,iBAAiB;AAAA,IAClD,YAAY,EAAE,SAAS,GAAG,OAAO,GAAG,MAAM,GAAG,KAAK,GAAG,UAAU,EAAE;AAAA,EACnE;AACF;AAEA,SAAS,UAAU,MAA4B;AAC7C,MAAI;AACJ,MAAI,cAAc;AAClB,MAAI;AACJ,QAAM,cAAwB,CAAC;AAC/B,QAAM,UAAU,oBAAI,IAA2B;AAE/C,WAAS,QAAQ,GAAG,QAAQ,KAAK,QAAQ,SAAS,GAAG;AACnD,UAAM,MAAM,KAAK,KAAK;AACtB,QAAI,QAAQ,mBAAmB;AAC7B,oBAAc;AAAA,IAChB,WAAW,QAAQ,cAAc;AAC/B,OAAC,SAAS,KAAK,IAAI,UAAU,MAAM,OAAO,GAAG;AAAA,IAC/C,WAAW,QAAQ,cAAc,QAAQ,SAAS;AAChD,cAAQ,IAAI,IAAI,MAAM,CAAC,GAAG,IAAI;AAAA,IAChC,WAAW,IAAI,WAAW,IAAI,GAAG;AAC/B,YAAM,CAAC,OAAO,SAAS,IAAI,UAAU,MAAM,OAAO,GAAG;AACrD,cAAQ,IAAI,IAAI,MAAM,CAAC,GAAG,KAAK;AAC/B,cAAQ;AAAA,IACV,WAAW,CAAC,SAAS;AACnB,UAAI,CAAC,SAAS,SAAS,GAAc,GAAG;AACtC,cAAM,IAAI;AAAA,UACR;AAAA,UACA;AAAA,UACA,oBAAoB,GAAG;AAAA,QACzB;AAAA,MACF;AACA,gBAAU;AAAA,IACZ,OAAO;AACL,kBAAY,KAAK,GAAG;AAAA,IACtB;AAAA,EACF;AAEA,MAAI,CAAC,SAAS;AACZ,UAAM,IAAI;AAAA,MACR;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAEA,SAAO,EAAE,SAAS,aAAa,SAAS,aAAa,QAAQ;AAC/D;AAEA,SAAS,gBACP,OACA,QACA,SACoB;AACpB,MAAI,SAAS,KAAM,QAAO;AAC1B,QAAM,SAAS,OAAO,KAAK;AAC3B,MAAI,CAAC,OAAO,UAAU,MAAM,KAAK,UAAU,GAAG;AAC5C,UAAM,IAAI;AAAA,MACR;AAAA,MACA;AAAA,MACA,GAAG,MAAM;AAAA,IACX;AAAA,EACF;AACA,MAAI,WAAW,QAAQ,SAAS,SAAS;AACvC,UAAM,IAAI;AAAA,MACR;AAAA,MACA;AAAA,MACA,GAAG,MAAM,oBAAoB,OAAO;AAAA,IACtC;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,eACP,SACA,MACQ;AACR,QAAM,QAAQ,QAAQ,IAAI,IAAI;AAC9B,MAAI,OAAO,UAAU,YAAY,CAAC,MAAM,KAAK,GAAG;AAC9C,UAAM,IAAI,SAAS,YAAY,oBAAoB,KAAK,IAAI,cAAc;AAAA,EAC5E;AACA,SAAO;AACT;AAEA,SAAS,WACP,SACA,KACQ;AACR,QAAM,MAAM,WAAW,IAAI,iBAAiB;AAC5C,SAAO,IAAI,SAAS,GAAG,IAAI,IAAI,MAAM,GAAG,EAAE,IAAI;AAChD;AAEA,SAAS,wBACP,aACoB;AACpB,MAAI,CAAC,YAAa,QAAO;AACzB,MACE,kBAAkB,eAClB,OAAO,YAAY,iBAAiB,YACpC,YAAY,aAAa,KAAK,GAC9B;AACA,WAAO,YAAY;AAAA,EACrB;AACA,MACE,uBAAuB,eACvB,OAAO,YAAY,sBAAsB,YACzC,YAAY,kBAAkB,KAAK,GACnC;AACA,WAAO,YAAY;AAAA,EACrB;AACA,SAAO;AACT;AAEA,SAASC,oBACP,aACiC;AACjC,SAAO;AAAA,IACL,eAAe,UAAU,eAAe,YAAY,SAAS;AAAA,EAC/D;AACF;AAEA,SAASC,8BACP,aAC2C;AAC3C,SAAO;AAAA,IACL,eAAe,UAAU,eAAe,YAAY,SAAS;AAAA,EAC/D;AACF;AAEA,SAAS,kBAAkB,aAAwC;AACjE,QAAM,SAAS,KAAK,MAAM,YAAY,MAAM;AAC5C,SACE,CAAC,OAAO,SAAS,MAAM,KAAK,UAAU,KAAK,IAAI,IAAI;AAEvD;AAEA,eAAe,wBACb,UACA,KACA,QAC2B;AAC3B,QAAM,QAAQ,MAAM;AAAA,IAClB;AAAA,IACA,GAAG,OAAO,QAAQ;AAAA,IAClB;AAAA,MACE,QAAQ;AAAA,MACR,SAAS,EAAE,gBAAgB,oCAAoC;AAAA,MAC/D,MAAM,IAAI,gBAAgB;AAAA,QACxB,YAAY;AAAA,QACZ,eAAe,OAAO;AAAA,QACtB,WAAW,OAAO;AAAA,MACpB,CAAC,EAAE,SAAS;AAAA,IACd;AAAA,IACA;AAAA,EACF;AACA,QAAM,YAA8B;AAAA,IAClC,GAAG;AAAA,IACH,cAAc,MAAM;AAAA,IACpB,eAAe,MAAM;AAAA,IACrB,YAAY,MAAM;AAAA,IAClB,OAAO,MAAM;AAAA,IACb,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,MAAM,aAAa,GAAI,EAAE,YAAY;AAAA,EACrE;AACA,QAAM,kCAAkC,KAAK,SAAS;AACtD,SAAO;AACT;AAEA,SAAS,eAAe,MAAuC;AAC7D,SAAO;AAAA,IACL,GAAG;AAAA,IACH,mBAAmB;AAAA,IACnB,cAAc;AAAA,IACd,eAAe;AAAA,IACf,eAAe;AAAA,EACjB;AACF;AAEA,eAAe,YACb,UACA,KACA,MACA,cAAc,OACF;AACZ,QAAM,WAAW,MAAM,SAAS,KAAK,IAAI;AACzC,MAAI,CAAC,SAAS,IAAI;AAChB,QAAI,aAAa;AACf,YAAM,IAAI;AAAA,QACR,SAAS,WAAW,OAAO,SAAS,WAAW,MAC3C,YACA,SAAS,UAAU,MACjB,gBACA;AAAA,QACN;AAAA,QACA,wCAAwC,SAAS,MAAM;AAAA,MACzD;AAAA,IACF;AACA,UAAM,IAAI,cAAc,QAAQ;AAAA,EAClC;AAEA,SAAQ,MAAM,SAAS,KAAK;AAC9B;AAEA,SAAS,gBACP,SACA,QACwB;AACxB,SAAO;AAAA,IACL,GAAG;AAAA,IACH,eAAe,UAAU,MAAM;AAAA,EACjC;AACF;AAEA,SAAS,WACP,SACA,SACM;AACN,aAAW,QAAQ,QAAQ,KAAK,GAAG;AACjC,QAAI,CAAC,QAAQ,SAAS,IAAI,GAAG;AAC3B,YAAM,IAAI;AAAA,QACR;AAAA,QACA;AAAA,QACA,qBAAqB,IAAI;AAAA,MAC3B;AAAA,IACF;AAAA,EACF;AACF;AAEA,eAAe,gBAAgB,OAAwC;AACrE,MAAI;AACF,WAAO,MAAM,MAAM,SAAS,KAAK;AAAA,EACnC,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,eAAe,eAAe,OAAmC;AAC/D,MAAI,iBAAiB,SAAU,QAAO;AACtC,MAAI,iBAAiB,WAAW;AAG9B,UAAM,WACJ,MAAM,WAAW,OAAO,MAAM,WAAW,MACrC,YACA,MAAM,UAAU,OAAO,MAAM,WAAW,IACtC,gBACA;AACR,WAAO,IAAI,SAAS,UAAU,MAAM,MAAM,MAAM,SAAS,MAAM,OAAO;AAAA,EACxE;AACA,MAAI,iBAAiB,eAAe;AAClC,UAAM,UAAU,MAAM,gBAAgB,KAAK;AAC3C,UAAM,OAAO;AAMb,UAAM,SAAS,OAAO,MAAM,UAAU,WAAW,KAAK,QAAQ;AAC9D,UAAM,OACJ,QAAQ,SACP,OAAO,MAAM,UAAU,WACpB,KAAK,QACL,QAAQ,MAAM,SAAS,MAAM;AACnC,UAAMC,WACJ,QAAQ,WACR,MAAM,qBACN,0BAA0B,MAAM,SAAS,MAAM;AACjD,UAAM,WACJ,MAAM,SAAS,WAAW,OAAO,MAAM,SAAS,WAAW,MACvD,YACA,MAAM,SAAS,UAAU,MACvB,gBACA;AACR,WAAO,IAAI,SAAS,UAAU,MAAMA,UAAS,OAAO;AAAA,EACtD;AACA,QAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AACrE,SAAO,IAAI,SAAS,eAAe,kBAAkB,OAAO;AAC9D;AAEA,eAAe,mBAAoC;AACjD,QAAM,SAAmB,CAAC;AAC1B,mBAAiB,SAAS,QAAQ,OAAO;AACvC,WAAO,KAAK,OAAO,SAAS,KAAK,IAAI,QAAQ,OAAO,KAAK,KAAK,CAAC;AAAA,EACjE;AACA,SAAO,OAAO,OAAO,MAAM,EAAE,SAAS,MAAM;AAC9C;AAEA,eAAe,gBAAgB,OAA8B;AAC3D,QAAM,IAAI,QAAc,CAACL,UAAS,WAAW;AAG3C,UAAM,UAAU,CAAC,UAAiB,OAAO,KAAK;AAC9C,YAAQ,OAAO,KAAK,SAAS,OAAO;AACpC,YAAQ,OAAO,MAAM,OAAO,CAAC,UAAU;AACrC,UAAI,OAAO;AACT,eAAO,KAAK;AAAA,MACd,OAAO;AACL,gBAAQ,OAAO,eAAe,SAAS,OAAO;AAC9C,QAAAA,SAAQ;AAAA,MACV;AAAA,IACF,CAAC;AAAA,EACH,CAAC;AACH;AAEA,eAAsB,OACpB,MACA,eAAgC,CAAC,GAChB;AACjB,QAAM,eAAe,aAAa,YAAY;AAC9C,QAAM,WACJ,aAAa,aAAa,CAAC,UAAU,QAAQ,OAAO,MAAM,KAAK;AACjE,MAAI,UAAU;AACd,MAAI;AACJ,MAAI,gBAAgB;AACpB,MAAI;AACJ,MAAI;AACJ,QAAM,WAAW,aAAa,YAAY;AAC1C,QAAM,WAAW,OAAO,UAAkB;AACxC,QAAI;AACF,YAAM,aAAa,KAAK;AAAA,IAC1B,QAAQ;AACN,YAAM,IAAI;AAAA,QACR;AAAA,QACA,YAAY,UAAU,yBAAyB;AAAA,QAC/C;AAAA,QACA,oBAAoB,SAChB,SACA,EAAE,SAAS,gBAAgB;AAAA,MACjC;AAAA,IACF;AAAA,EACF;AAEA,MAAI;AACF,mCAA+B,IAAI;AACnC,UAAM,OAAO,cAAc,IAAI;AAC/B,QAAI,SAAS,QAAW;AACtB,gBAAU;AACV,YAAM;AAAA,QACJ,GAAG,KAAK,UAAU;AAAA,UAChB,gBAAgB;AAAA,UAChB,IAAI;AAAA,UACJ;AAAA,UACA,MAAM,SAAS,IAAI;AAAA,QACrB,CAAC,CAAC;AAAA;AAAA,MACJ;AACA,aAAO;AAAA,IACT;AAEA,UAAM,SAAS,UAAU,IAAI;AAC7B,cAAU,OAAO;AACjB,UAAM,MAAM,aAAa,OAAO,QAAQ;AACxC,UAAM,UAAU,WAAW,OAAO,SAAS,GAAG;AAE9C,QAAI,OAAO,YAAY,SAAS;AAC9B,UACE,OAAO,YAAY,CAAC,MAAM,aAC1B,OAAO,YAAY,SAAS,GAC5B;AACA,cAAM,IAAI;AAAA,UACR;AAAA,UACA;AAAA,UACA;AAAA,QACF;AAAA,MACF;AAEA,YAAM,YAAY,OAAO,YAAY,CAAC;AACtC,UAAI,WAAW;AACb,mBAAW,OAAO,SAAS,CAAC,SAAS,QAAQ,CAAC;AAC9C,cAAM,QAAQ,eAAe,OAAO,SAAS,OAAO;AACpD,YAAI,CAAC,mBAAmB,KAAK,SAAS,GAAG;AACvC,gBAAM,IAAI;AAAA,YACR;AAAA,YACA;AAAA,YACA;AAAA,UACF;AAAA,QACF;AACA,YAAI,iBAAiB,IAAI,SAAS,GAAG;AACnC,gBAAM,IAAI;AAAA,YACR;AAAA,YACA;AAAA,YACA,+DAA+D,SAAS;AAAA,UAC1E;AAAA,QACF;AACA,YAAI,CAAC,mBAAmB,KAAK,KAAK,GAAG;AACnC,gBAAM,IAAI;AAAA,YACR;AAAA,YACA;AAAA,YACA;AAAA,UACF;AAAA,QACF;AAEA,cAAM,cAAc;AAAA,UAClB;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA,GAAI,OAAO,QAAQ,IAAI,QAAQ,MAAM,OAAO,CAAC,UAAU,IAAI,CAAC;AAAA,QAC9D;AACA,cAAM,aAAa,qBAAqB,aAAa,cAAc,GAAG;AACtE,cAAMM,UAAS,OAAO,aAAa,cAAc;AAAA,UAC/C,WAAW;AAAA,UACX,WAAW;AAAA,QACb;AACA,YAAIA,QAAO,aAAa,GAAG;AACzB,gBAAM,cAAc,OAAO,YAAY,KAAK,GAAG,CAAC;AAChD,gBAAM,IAAI;AAAA,YACR;AAAA,YACA;AAAA,YACA,qBAAqB,SAAS,UAAU,WAAW;AAAA,YACnD;AAAA,cACE,YAAY,WAAW;AAAA,cACvB,WAAW,WAAW;AAAA,cACtB,WAAWA,QAAO;AAAA,cAClB,QAAQA,QAAO;AAAA,YACjB;AAAA,UACF;AAAA,QACF;AACA,cAAM;AAAA,UACJ,GAAG,KAAK,UAAU;AAAA,YAChB,gBAAgB;AAAA,YAChB,IAAI;AAAA,YACJ;AAAA,YACA,MAAM;AAAA,cACJ,QAAQ;AAAA,cACR,OAAO;AAAA,cACP;AAAA,cACA,OACE,OAAO,QAAQ,IAAI,QAAQ,MAAM,OAAO,WAAW;AAAA,YACvD;AAAA,UACF,CAAC,CAAC;AAAA;AAAA,QACJ;AACA,eAAO;AAAA,MACT;AAEA,iBAAW,OAAO,SAAS,CAAC,CAAC;AAC7B,YAAM,eAAe,MAAM,mBAAmB;AAC9C,YAAM,SAAS,MAAM,aAAa,EAAE,OAAO,KAAK,CAAC;AACjD,YAAM;AAAA,QACJ,GAAG,KAAK,UAAU;AAAA,UAChB,gBAAgB;AAAA,UAChB,IAAI;AAAA,UACJ;AAAA,UACA,MAAM;AAAA,YACJ,QAAQ,OAAO;AAAA,YACf,WAAW,OAAO;AAAA,YAClB,OAAO,OAAO;AAAA,YACd,GAAI,OAAO,WAAW,SAAY,CAAC,IAAI,EAAE,QAAQ,OAAO,OAAO;AAAA,YAC/D,GAAI,OAAO,SAAS,WAAW,IAC3B,CAAC,IACD,EAAE,UAAU,OAAO,SAAS;AAAA,UAClC;AAAA,QACF,CAAC,CAAC;AAAA;AAAA,MACJ;AACA,aAAO;AAAA,IACT;AAEA,UAAM,yBAAyB;AAE/B,QAAI,OAAO,YAAY,aAAa;AAClC,iBAAW,OAAO,SAAS,CAAC,SAAS,cAAc,QAAQ,CAAC;AAC5D,UAAI,OAAO,YAAY,WAAW,GAAG;AACnC,cAAM,IAAI;AAAA,UACR;AAAA,UACA;AAAA,UACA;AAAA,QACF;AAAA,MACF;AACA,YAAM,QAAQ,eAAe,OAAO,SAAS,OAAO;AACpD,YAAM,YAAY,eAAe,OAAO,SAAS,YAAY;AAC7D,YAAM,SAAS,eAAe,OAAO,SAAS,QAAQ;AAEtD,YAAM,YAAY,MAAM;AAAA,QACtB;AAAA,QACA,GAAG,OAAO;AAAA,QACV;AAAA,UACE,QAAQ;AAAA,UACR,SAAS;AAAA,YACP,gBAAgB;AAAA,UAClB;AAAA,UACA,MAAM,KAAK,UAAU;AAAA,YACnB;AAAA,YACA,YAAY;AAAA,YACZ,WAAW;AAAA,YACX;AAAA,UACF,CAAC;AAAA,QACH;AAAA,MACF;AAEA,YAAM,SAA+B;AAAA,QACnC,GAAG,UAAU;AAAA,QACb,UAAU;AAAA,MACZ;AAEA,YAAM,uBAAuB,KAAK,MAAM;AAExC,YAAM;AAAA,QACJ,GAAG,KAAK,UAAU;AAAA,UAChB,gBAAgB;AAAA,UAChB,IAAI;AAAA,UACJ;AAAA,UACA,MAAM,eAAe,MAAM;AAAA,QAC7B,CAAC,CAAC;AAAA;AAAA,MACJ;AACA,aAAO;AAAA,IACT;AAEA,QAAI,OAAO,YAAY,QAAQ;AAC7B,iBAAW,OAAO,SAAS,CAAC,CAAC;AAC7B,UACE,OAAO,YAAY,WAAW,KAC9B,OAAO,YAAY,CAAC,MAAM,UAC1B;AACA,cAAM,IAAI;AAAA,UACR;AAAA,UACA;AAAA,UACA;AAAA,QACF;AAAA,MACF;AAEA,YAAM,SAAS,MAAM,sBAAsB,GAAG;AAC9C,UAAIH,oBAAmB,MAAM,GAAG;AAC9B,cAAM;AAAA,UACJ,GAAG,KAAK,UAAU;AAAA,YAChB,gBAAgB;AAAA,YAChB,IAAI;AAAA,YACJ;AAAA,YACA,MAAM;AAAA,cACJ,QAAQ;AAAA,cACR,gBAAgB;AAAA,cAChB,OAAO,OAAO;AAAA,YAChB;AAAA,UACF,CAAC,CAAC;AAAA;AAAA,QACJ;AACA,eAAO;AAAA,MACT;AACA,UAAIC,8BAA6B,MAAM,GAAG;AACxC,cAAMG,UAAS,MAAM;AAAA,UACnB;AAAA,UACA,GAAG,OAAO,QAAQ,8BAA8B,OAAO,YAAY;AAAA,UACnE;AAAA,YACE,QAAQ;AAAA,YACR,SAAS,gBAAgB,CAAC,GAAG,OAAO,iBAAiB;AAAA,UACvD;AAAA,QACF;AACA,YACEA,QAAO,KAAK,WAAW,aACvBA,QAAO,KAAK,WAAW,YACvB;AACA,gBAAM;AAAA,YACJ,GAAG,KAAK,UAAU;AAAA,cAChB,gBAAgB;AAAA,cAChB,IAAI;AAAA,cACJ;AAAA,cACA,MAAM,EAAE,QAAQA,QAAO,KAAK,OAAO;AAAA,YACrC,CAAC,CAAC;AAAA;AAAA,UACJ;AACA,iBAAO;AAAA,QACT;AAEA,cAAM,QAAQ,MAAM;AAAA,UAClB;AAAA,UACA,GAAG,OAAO,QAAQ;AAAA,UAClB;AAAA,YACE,QAAQ;AAAA,YACR,SAAS;AAAA,cACP,gBAAgB;AAAA,YAClB;AAAA,YACA,MAAM,IAAI,gBAAgB;AAAA,cACxB,YAAY;AAAA,cACZ,aAAa,OAAO;AAAA,cACpB,WAAW,OAAO;AAAA,cAClB,MAAM;AAAA,YACR,CAAC,EAAE,SAAS;AAAA,UACd;AAAA,UACA;AAAA,QACF;AACA,cAAM,QAA0B;AAAA,UAC9B,SAAS;AAAA,UACT,MAAM;AAAA,UACN,UAAU,OAAO;AAAA,UACjB,WAAW,OAAO;AAAA,UAClB,cAAc,MAAM;AAAA,UACpB,eAAe,MAAM;AAAA,UACrB,YAAY,MAAM;AAAA,UAClB,OAAO,MAAM;AAAA,UACb,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,MAAM,aAAa,GAAI,EAAE,YAAY;AAAA,QACrE;AACA,cAAMC,UAAS,MAAM,oBAAoB,KAAK,YAAY;AACxD,gBAAM,UAAU,MAAM,sBAAsB,GAAG;AAC/C,cAAIL,oBAAmB,OAAO,EAAG,QAAO;AACxC,cACE,CAACC,8BAA6B,OAAO,KACrC,KAAK,UAAU,OAAO,MAAM,KAAK,UAAU,MAAM,GACjD;AACA,kBAAM,IAAI;AAAA,cACR;AAAA,cACA;AAAA,cACA;AAAA,YACF;AAAA,UACF;AACA,gBAAM,kCAAkC,KAAK,KAAK;AAClD,iBAAO;AAAA,QACT,CAAC;AACD,cAAM;AAAA,UACJ,GAAG,KAAK,UAAU;AAAA,YAChB,gBAAgB;AAAA,YAChB,IAAI;AAAA,YACJ;AAAA,YACA,MAAM;AAAA,cACJ,QAAQ;AAAA,cACR,gBAAgB;AAAA,cAChB,OAAOI,QAAO;AAAA,YAChB;AAAA,UACF,CAAC,CAAC;AAAA;AAAA,QACJ;AACA,eAAO;AAAA,MACT;AACA,UAAI,CAAC,QAAQ;AACX,cAAM,IAAI;AAAA,UACR;AAAA,UACA;AAAA,UACA;AAAA,QACF;AAAA,MACF;AAEA,YAAM,SAAS,MAAM;AAAA,QACnB;AAAA,QACA,GAAG,OAAO,QAAQ,8BAA8B,OAAO,EAAE;AAAA,QACzD;AAAA,UACE,QAAQ;AAAA,UACR,SAAS,gBAAgB,CAAC,GAAG,OAAO,iBAAiB;AAAA,QACvD;AAAA,MACF;AAEA,YAAM,SAA+B;AAAA,QACnC,UAAU,OAAO;AAAA,QACjB,IAAI,OAAO,KAAK,MAAM,OAAO;AAAA,QAC7B,QAAQ,OAAO,KAAK;AAAA,QACpB,cAAc,OAAO,KAAK,gBAAgB,OAAO;AAAA,QACjD,YACE,OAAO,KAAK,eAAe,SACvB,OAAO,aACP,OAAO,KAAK;AAAA,QAClB,UAAU,OAAO,KAAK,YAAY,OAAO;AAAA,QACzC,mBAAmB,OAAO;AAAA,MAC5B;AACA,YAAM,SAAS,MAAM,oBAAoB,KAAK,YAAY;AACxD,cAAM,UAAU,MAAM,sBAAsB,GAAG;AAC/C,YAAI,KAAK,UAAU,OAAO,MAAM,KAAK,UAAU,MAAM,GAAG;AACtD,gBAAM,IAAI;AAAA,YACR;AAAA,YACA;AAAA,YACA;AAAA,UACF;AAAA,QACF;AACA,cAAM,kCAAkC,KAAK,MAAM;AACnD,eAAO;AAAA,MACT,CAAC;AAED,YAAM;AAAA,QACJ,GAAG,KAAK,UAAU;AAAA,UAChB,gBAAgB;AAAA,UAChB,IAAI;AAAA,UACJ;AAAA,UACA,MAAM,eAAe,MAAM;AAAA,QAC7B,CAAC,CAAC;AAAA;AAAA,MACJ;AACA,aAAO;AAAA,IACT;AAEA,UAAM,SAAS,OAAO,cAClB,OAAO,aAAa,aAAa,kBAAkB,IACnD,IAAI;AACR,QAAI,SAAS,QAAQ,KAAK;AAC1B,QAAI,uBAAuB;AAC3B,QAAI,OAAO,eAAe,CAAC,QAAQ;AACjC,YAAM,IAAI;AAAA,QACR;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,IACF;AACA,QAAI,CAAC,UAAU,CAAC,OAAO,aAAa;AAClC,UAAI,SAAS,MAAM,sBAAsB,GAAG;AAC5C,UAAIL,oBAAmB,MAAM,KAAK,kBAAkB,MAAM,GAAG;AAC3D,iBAAS,MAAM,oBAAoB,KAAK,YAAY;AAClD,gBAAM,UAAU,MAAM,sBAAsB,GAAG;AAC/C,cAAIA,oBAAmB,OAAO,KAAK,kBAAkB,OAAO,GAAG;AAC7D,mBAAO,wBAAwB,UAAU,KAAK,OAAO;AAAA,UACvD;AACA,iBAAO;AAAA,QACT,CAAC;AAAA,MACH;AACA,eAAS,wBAAwB,MAAM;AACvC,UAAI,QAAQ;AACV,+BAAuB,OAAO;AAAA,MAChC;AAAA,IACF;AAEA,QAAI,CAAC,QAAQ;AACX,YAAM,IAAI;AAAA,QACR;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAEA,UAAM,SAAS,IAAI,WAAW;AAAA,MAC5B;AAAA,MACA,SAAS;AAAA,MACT;AAAA,IACF,CAAC;AAED,QAAI;AACJ,QAAI,OAAO,YAAY,MAAM;AAC3B,iBAAW,OAAO,SAAS,CAAC,CAAC;AAC7B,aAAO,MAAM,OAAO,GAAG;AAAA,IACzB,WAAW,OAAO,YAAY,WAAW;AACvC,iBAAW,OAAO,SAAS,CAAC,CAAC;AAC7B,aAAO,MAAM,OAAO,QAAQ;AAAA,IAC9B,WAAW,OAAO,YAAY,UAAU;AACtC,iBAAW,OAAO,SAAS,CAAC,aAAa,CAAC;AAC1C,UAAI,OAAO,YAAY,WAAW,GAAG;AACnC,cAAM,IAAI;AAAA,UACR;AAAA,UACA;AAAA,UACA;AAAA,QACF;AAAA,MACF;AACA,aAAO,MAAM,OAAO,OAAO;AAAA,QACzB,OAAO,OAAO,YAAY,CAAC;AAAA,QAC3B,YAAY;AAAA,UACV,OAAO,QAAQ,IAAI,aAAa;AAAA,UAChC;AAAA,UACA;AAAA,QACF;AAAA,MACF,CAAC;AAAA,IACH,WAAW,OAAO,YAAY,SAAS;AACrC,iBAAW,OAAO,SAAS;AAAA,QACzB;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF,CAAC;AACD,YAAM,MAAM,OAAO,QAAQ,IAAI,KAAK;AACpC,sBAAgB,MAAM,MAAM;AAC5B,UAAI,OAAO,YAAY,WAAW,GAAG;AACnC,cAAM,IAAI;AAAA,UACR;AAAA,UACA;AAAA,UACA;AAAA,QACF;AAAA,MACF;AACA,YAAM,aAAa,eAAe,OAAO,SAAS,cAAc;AAChE,UAAI,CAAC,kBAAkB,KAAK,UAAU,KAAK,OAAO,UAAU,KAAK,GAAG;AAClE,cAAM,IAAI;AAAA,UACR;AAAA,UACA;AAAA,UACA;AAAA,QACF;AAAA,MACF;AACA,YAAM,SAAS,OAAO,QAAQ,IAAI,QAAQ;AAC1C,YAAM,UAA4B;AAAA,QAChC,KAAK,OAAO,YAAY,CAAC;AAAA,QACzB;AAAA,QACA,QACE,OAAO,WAAW,WACb,OAAO,YAAY,IACpB;AAAA,MACR;AACA,YAAM,cAAc,OAAO,QAAQ,IAAI,iBAAiB;AACxD,uBACE,OAAO,gBAAgB,WACnB,eACC,aAAa,0BAA0BM,aAAY;AAC1D,UAAI;AACJ,UAAI,CAAC,KAAK;AACR,YAAI;AACF,4BAAkB,MAAM,uBAAuB,GAAG;AAAA,QACpD,QAAQ;AACN,gBAAM,IAAI;AAAA,YACR;AAAA,YACA;AAAA,YACA;AAAA,UACF;AAAA,QACF;AAAA,MACF;AACA,YAAM,WAAW,MAAM,OAAO,MAAM,SAAS,EAAE,eAAe,CAAC;AAC/D,aAAO,EAAE,iBAAiB,eAAe;AACzC,aAAO;AACP,YAAM,EAAE,YAAY,GAAG,QAAQ,IAAI;AACnC,wBAAkB;AAClB,UAAI,iBAAiB;AACnB,cAAM,YAAYP,MAAK,iBAAiB,MAAM;AAC9C,cAAM,cAAcA,MAAK,iBAAiB,cAAc;AACxD,cAAM,QACJ,OAAO,eAAe,WAClB,OAAO,KAAK,YAAY,QAAQ,IAChC;AACN,YAAI,CAAC,SAAS,MAAM,SAAS,QAAQ,MAAM,YAAY;AACrD,gBAAM,IAAI;AAAA,YACR;AAAA,YACA;AAAA,YACA;AAAA,YACA,EAAE,SAAS,eAAe,MAAM;AAAA,UAClC;AAAA,QACF;AACA,YAAI;AACF,iBAAO;AAAA,YACL,GAAG;AAAA,YACH,YAAY;AAAA,YACZ,cAAc;AAAA,YACd,YAAY,MAAM;AAAA,UACpB;AACA,gBAAM;AAAA,YACJ;AAAA,YACA,GAAG,KAAK,UAAU,EAAE,gBAAgB,KAAK,MAAM,MAAM,QAAQ,CAAC,CAAC;AAAA;AAAA,UACjE;AACA,gBAAM,gBAAgB,WAAW,KAAK;AACtC,iBAAO,EAAE,GAAG,SAAS,GAAG,aAAa,OAAO,SAAS,OAAO,EAAE;AAAA,QAChE,QAAQ;AACN,gBAAM,IAAI;AAAA,YACR;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,cACE;AAAA,cACA,YAAY;AAAA,cACZ,cAAc;AAAA,cACd,eAAe;AAAA,YACjB;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF,OAAO;AACL,iBAAW,OAAO,SAAS,CAAC,QAAQ,UAAU,CAAC;AAC/C,UAAI,OAAO,YAAY,SAAS,GAAG;AACjC,cAAM,IAAI;AAAA,UACR;AAAA,UACA;AAAA,UACA;AAAA,QACF;AAAA,MACF;AACA,aAAO,OAAO,YAAY,CAAC,IACvB,MAAM,OAAO;AAAA,QACX,gBAAgB,OAAO,YAAY,CAAC,GAAG,aAAa;AAAA,MACtD,IACA,MAAM,OAAO,UAAU;AAAA,QACrB,MAAM,gBAAgB,OAAO,QAAQ,IAAI,MAAM,GAAG,QAAQ;AAAA,QAC1D,SAAS;AAAA,UACP,OAAO,QAAQ,IAAI,UAAU;AAAA,UAC7B;AAAA,UACA;AAAA,QACF;AAAA,MACF,CAAC;AAAA,IACP;AAEA,UAAM;AAAA,MACJ,GAAG,KAAK,UAAU;AAAA,QAChB,gBAAgB;AAAA,QAChB,IAAI;AAAA,QACJ;AAAA,QACA,GAAI,SAAS,SAAY,CAAC,IAAI,EAAE,KAAK;AAAA,QACrC;AAAA,MACF,CAAC,CAAC;AAAA;AAAA,IACJ;AACA,WAAO;AAAA,EACT,SAAS,OAAO;AACd,UAAM,aAAa,MAAM,eAAe,KAAK;AAC7C;AAAA,MACE,GAAG,KAAK,UAAU;AAAA,QAChB,gBAAgB;AAAA,QAChB,IAAI;AAAA,QACJ;AAAA,QACA,GAAI,mBAAmB,SACnB,CAAC,IACD,EAAE,MAAM,EAAE,GAAG,MAAM,iBAAiB,eAAe,EAAE;AAAA,QACzD,OAAO;AAAA,UACL,MAAM,WAAW;AAAA,UACjB,SAAS,WAAW;AAAA,UACpB,GAAI,WAAW,YAAY,SACvB,CAAC,IACD,EAAE,SAAS,WAAW,QAAQ;AAAA,QACpC;AAAA,MACF,CAAC,CAAC;AAAA;AAAA,IACJ;AACA,WAAO,WAAW;AAAA,EACpB;AACF;","names":["randomUUID","dirname","join","chmod","mkdir","open","resolve","dirname","join","isOAuthCredentials","isLegacyBootstrapCredentials","message","result","status","active","randomUUID"]}
|
|
@@ -14,13 +14,13 @@ flag.
|
|
|
14
14
|
## Install
|
|
15
15
|
|
|
16
16
|
```sh
|
|
17
|
-
npm install -g @
|
|
17
|
+
npm install -g @weftlabs/cli
|
|
18
18
|
```
|
|
19
19
|
|
|
20
20
|
Zero-install equivalent for any command below:
|
|
21
21
|
|
|
22
22
|
```sh
|
|
23
|
-
npx --package @
|
|
23
|
+
npx --package @weftlabs/cli weft --help
|
|
24
24
|
```
|
|
25
25
|
|
|
26
26
|
## Commands
|
|
@@ -56,36 +56,40 @@ weft bootstrap --email "human@example.com" \
|
|
|
56
56
|
# 2. Search immediately — free, works while the claim is pending.
|
|
57
57
|
weft search "weather data API"
|
|
58
58
|
|
|
59
|
-
# 3.
|
|
60
|
-
#
|
|
59
|
+
# 3. Ask the human to verify the claim email so Weft can apply the one-time
|
|
60
|
+
# signup grant, then approve. Show them the user code from the bootstrap
|
|
61
|
+
# response so they can match this session.
|
|
61
62
|
|
|
62
63
|
# 4. Poll at the interval the bootstrap response returned — no faster.
|
|
63
64
|
weft auth status
|
|
64
65
|
|
|
65
|
-
# 5. After approval the stored
|
|
66
|
+
# 5. After approval the same stored bearer is durable until revoked.
|
|
66
67
|
weft me
|
|
67
68
|
|
|
68
|
-
# 6.
|
|
69
|
-
# signup grant
|
|
70
|
-
# https://weft.network/dashboard/wallet.
|
|
69
|
+
# 6. Ask the human to verify the claim email so Weft can apply the one-time
|
|
70
|
+
# signup grant, then check the balance.
|
|
71
71
|
weft balance
|
|
72
72
|
```
|
|
73
73
|
|
|
74
|
-
Status lifecycle: `pending` (search works, keep polling) → `claimed`
|
|
75
|
-
|
|
76
|
-
(terminal — stop; do not create a second bootstrap for
|
|
77
|
-
without asking the user).
|
|
74
|
+
Status lifecycle: `pending` (search works, keep polling) → `claimed`
|
|
75
|
+
(done — the same bearer now supports normal buyer commands) or `rejected` /
|
|
76
|
+
`expired` / `revoked` (terminal — stop; do not create a second bootstrap for
|
|
77
|
+
the same request without asking the user).
|
|
78
78
|
|
|
79
|
-
The
|
|
80
|
-
search
|
|
81
|
-
|
|
82
|
-
|
|
79
|
+
The `wbt_` credential is secret. Before claim, its 30-minute search-only window
|
|
80
|
+
permits `search`, `status`, and `cancel`. Human approval promotes the same bearer
|
|
81
|
+
to durable `identity`, `search`, `balance`, `fetch`, `purchases`, `status`, and
|
|
82
|
+
`revoke` capabilities until the human revokes it. Refusals on balance/fetch
|
|
83
|
+
before the claim are the contract, not bugs. No subsidy or treasury funding is
|
|
84
|
+
required; paid fetch uses the human-funded wallet. The CLI stores every
|
|
85
|
+
credential in a mode-0600 local file and never prints secrets — neither do you.
|
|
83
86
|
|
|
84
87
|
## Credentials
|
|
85
88
|
|
|
86
|
-
Precedence: `--api-key-stdin`, then `WEFT_API_KEY`, then the stored
|
|
87
|
-
|
|
88
|
-
|
|
89
|
+
Precedence: `--api-key-stdin`, then `WEFT_API_KEY`, then the stored bootstrap
|
|
90
|
+
or legacy OAuth credential. New bootstrap flows keep the same `wbt_` bearer
|
|
91
|
+
and do not register an OAuth client or call `/oauth/token`. The CLI rejects API
|
|
92
|
+
keys passed as command arguments so they never reach shell history. Never echo any credential —
|
|
89
93
|
`wbt_`, `wk_`, or an OAuth token — into your output.
|
|
90
94
|
|
|
91
95
|
## Errors
|
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
#
|
|
4
4
|
# The agent needs the human's email address and nothing else.
|
|
5
5
|
# It never asks for, receives, or stores the human's password.
|
|
6
|
-
#
|
|
7
|
-
#
|
|
6
|
+
# After the human verifies the claim email, Weft applies the one-time signup
|
|
7
|
+
# grant. Do not ask for a wallet top-up during onboarding.
|
|
8
8
|
#
|
|
9
9
|
# Every command prints one JSON envelope. Parse it; never echo a credential.
|
|
10
10
|
set -eu
|
|
@@ -28,18 +28,17 @@ bootstrap="$(weft bootstrap \
|
|
|
28
28
|
--reason "$REASON")"
|
|
29
29
|
printf '%s\n' "$bootstrap"
|
|
30
30
|
POLL_INTERVAL="$(printf '%s' "$bootstrap" | node -e \
|
|
31
|
-
|
|
31
|
+
'let s=""; process.stdin.on("data", d => s += d).on("end", () => process.stdout.write(String(JSON.parse(s).data.approval.interval)))')"
|
|
32
32
|
|
|
33
33
|
# 3. Search immediately. The temporary credential is search-only and expires
|
|
34
34
|
# 30 minutes after creation.
|
|
35
35
|
weft search "weather data API"
|
|
36
36
|
|
|
37
|
-
# 4.
|
|
38
|
-
#
|
|
39
|
-
# the email.
|
|
37
|
+
# 4. Ask the human to verify the claim email so Weft can apply the one-time
|
|
38
|
+
# signup grant, then approve this agent. Show them the user code from the
|
|
39
|
+
# bootstrap envelope above; the claim link is only in the email.
|
|
40
40
|
# 5. Poll at the interval the bootstrap response returned. A claimed response
|
|
41
|
-
#
|
|
42
|
-
# need a new bootstrap.
|
|
41
|
+
# means the same bearer is durable with its fixed post-claim capabilities.
|
|
43
42
|
while :; do
|
|
44
43
|
sleep "$POLL_INTERVAL"
|
|
45
44
|
auth="$(weft auth status)"
|
|
@@ -48,8 +47,8 @@ while :; do
|
|
|
48
47
|
'let s=""; process.stdin.on("data", d => s += d).on("end", () => process.stdout.write(JSON.parse(s).data.status))')"
|
|
49
48
|
case "$status" in
|
|
50
49
|
pending) ;;
|
|
51
|
-
|
|
52
|
-
rejected|expired)
|
|
50
|
+
claimed) break ;;
|
|
51
|
+
rejected|expired|revoked)
|
|
53
52
|
echo "Bootstrap ended with status: $status" >&2
|
|
54
53
|
exit 1
|
|
55
54
|
;;
|
|
@@ -60,10 +59,11 @@ while :; do
|
|
|
60
59
|
esac
|
|
61
60
|
done
|
|
62
61
|
|
|
63
|
-
# 6. After approval the CLI
|
|
64
|
-
#
|
|
62
|
+
# 6. After approval the CLI keeps the same bearer. It does not register an OAuth
|
|
63
|
+
# client or exchange a device code. Ordinary commands now use its durable
|
|
64
|
+
# identity, search, balance, fetch, purchases, status, and revoke capabilities.
|
|
65
65
|
weft me
|
|
66
66
|
|
|
67
|
-
# 7.
|
|
68
|
-
#
|
|
67
|
+
# 7. The claim is verified and the signup grant is applied. Check the balance;
|
|
68
|
+
# do not ask for a wallet top-up during onboarding.
|
|
69
69
|
weft balance
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@weftlabs/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.26.0",
|
|
4
4
|
"description": "Command-line client for the Weft buyer runtime",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
"directory": "cli"
|
|
29
29
|
},
|
|
30
30
|
"dependencies": {
|
|
31
|
-
"@weftlabs/sdk": "0.
|
|
31
|
+
"@weftlabs/sdk": "0.26.0"
|
|
32
32
|
},
|
|
33
33
|
"devDependencies": {
|
|
34
34
|
"@types/node": "^26.1.2",
|