@duyquangnvx/create-agent-cli 0.31.0 → 0.32.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +7 -0
- package/dist/bin.js +118 -49
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,13 @@ What changed in each release of `@duyquangnvx/agent-cli` (the Runtime) and `@duy
|
|
|
4
4
|
|
|
5
5
|
## Unreleased
|
|
6
6
|
|
|
7
|
+
## v0.32.0 (2026-11-10)
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- A Login in `defineCli({ logins })` may be a function of the run's env that returns its declaration, for a CLI whose user picks its server with a variable: `ctx.login`, its refresh, `login`, `logout` and `doctor`'s row build it from each run's `env`, and an error it throws fails the run before any request. A stored Login is kept per token endpoint and client id, so a token from one server is never sent to another. `LoginSource` and `LoginDeclarations` are exported.
|
|
12
|
+
- A Grant: a Command lists in `grants` the Logins it asks a token for one action from, and `ctx.grant(name, { scope })`, typed to those names, asks the Login's server for an Approval of that scope through the device flow, taking up the one pending for the same scope. Until the person approves it fails with `APPROVAL_PENDING` (exit 75) and the rerun with `--wait 100`; a refused one fails with `APPROVAL_DENIED` and an expired one with `APPROVAL_EXPIRED` and the rerun, both exit 2. The token is given to the run only, never stored or refreshed, and the Login's Secret does not stand in for it. `--wait <seconds>` is a Standard flag of a Command with `grants`, `defineCli` throws on a name the CLI does not declare, and `ctx.grant` throws in a dry run. `GrantOptions` is exported.
|
|
13
|
+
|
|
7
14
|
## v0.31.0 (2026-11-10)
|
|
8
15
|
|
|
9
16
|
### Added
|
package/dist/bin.js
CHANGED
|
@@ -7198,9 +7198,9 @@ const WAIT_FLAG = standardFlag("--wait", {
|
|
|
7198
7198
|
takes: "value",
|
|
7199
7199
|
schema: WAIT_SECONDS
|
|
7200
7200
|
});
|
|
7201
|
-
/** Whether `--wait` is a Standard flag of the Command: it is of one that declares a Login. */
|
|
7201
|
+
/** Whether `--wait` is a Standard flag of the Command: it is of one that declares a Login or Grant. */
|
|
7202
7202
|
function takesWait(command) {
|
|
7203
|
-
return (command.logins ?? []).length > 0;
|
|
7203
|
+
return (command.logins ?? []).length > 0 || (command.grants ?? []).length > 0;
|
|
7204
7204
|
}
|
|
7205
7205
|
const EFFECT_FLAGS = {
|
|
7206
7206
|
read: [JSON_FLAG],
|
|
@@ -7829,12 +7829,37 @@ function loginRequired(names, rerun) {
|
|
|
7829
7829
|
next: [...names.map(loginStep), rerun]
|
|
7830
7830
|
});
|
|
7831
7831
|
}
|
|
7832
|
+
function loginAsking(name) {
|
|
7833
|
+
return {
|
|
7834
|
+
subject: `signing in to ${name}`,
|
|
7835
|
+
denied: () => approvalDenied(name),
|
|
7836
|
+
expired: () => approvalExpired(name)
|
|
7837
|
+
};
|
|
7838
|
+
}
|
|
7839
|
+
/** A Grant's Approval, whose expiry the rerun of the Command heals with a new code. */
|
|
7840
|
+
function grantAsking(name, scope, rerun) {
|
|
7841
|
+
const subject = `the grant of ${scope} from ${name}`;
|
|
7842
|
+
return {
|
|
7843
|
+
subject,
|
|
7844
|
+
denied: () => new CliError({
|
|
7845
|
+
code: APPROVAL_DENIED,
|
|
7846
|
+
message: `the person refused ${subject}`,
|
|
7847
|
+
hint: "ask the person whether to go ahead, and run the Command again only if they agree"
|
|
7848
|
+
}),
|
|
7849
|
+
expired: () => new CliError({
|
|
7850
|
+
code: APPROVAL_EXPIRED,
|
|
7851
|
+
message: `the code for ${subject} expired before it was approved`,
|
|
7852
|
+
hint: "run the Next step for a new code, and pass its link and code to the person",
|
|
7853
|
+
next: [rerun]
|
|
7854
|
+
})
|
|
7855
|
+
};
|
|
7856
|
+
}
|
|
7832
7857
|
/** The wait ran out before the person approved: the same Approval stays pending for the rerun. */
|
|
7833
|
-
function approvalPending(
|
|
7858
|
+
function approvalPending({ subject }, approval, rerun) {
|
|
7834
7859
|
const { verificationUri, userCode, verificationUriComplete } = approval;
|
|
7835
7860
|
return new CliError({
|
|
7836
7861
|
code: APPROVAL_PENDING,
|
|
7837
|
-
message:
|
|
7862
|
+
message: `${subject} waits for the code ${userCode} to be approved at ${verificationUriComplete ?? verificationUri}`,
|
|
7838
7863
|
hint: "the person sees only your reply: write the link and the code in it, then run the Next step, which waits for the approval",
|
|
7839
7864
|
details: {
|
|
7840
7865
|
verificationUri,
|
|
@@ -7951,7 +7976,7 @@ function mustDeclare(code, table) {
|
|
|
7951
7976
|
//#region ../agent-cli/dist/define-command.js
|
|
7952
7977
|
/** Throws when the Command's declaration breaks a rule its type cannot express; `label` names it. */
|
|
7953
7978
|
function checkCommand(command, label, table, logins) {
|
|
7954
|
-
checkLogins(command.logins ?? [], label, logins);
|
|
7979
|
+
checkLogins([...command.logins ?? [], ...command.grants ?? []], label, logins);
|
|
7955
7980
|
checkNoStandardFlags(command, label);
|
|
7956
7981
|
checkForce(command, label);
|
|
7957
7982
|
checkArrayArgLast(label, command.args);
|
|
@@ -7999,6 +8024,14 @@ function cliErrorOf(code, init, options) {
|
|
|
7999
8024
|
}, options);
|
|
8000
8025
|
}
|
|
8001
8026
|
//#endregion
|
|
8027
|
+
//#region ../agent-cli/dist/login/declared.js
|
|
8028
|
+
/** The declaration of the Login `name` for a run in `env`. */
|
|
8029
|
+
function declaredLogin(logins, name, env) {
|
|
8030
|
+
const login = logins[name];
|
|
8031
|
+
if (login === void 0) throw new Error(`${name} is not a Login the CLI declares`);
|
|
8032
|
+
return typeof login === "function" ? login(env) : login;
|
|
8033
|
+
}
|
|
8034
|
+
//#endregion
|
|
8002
8035
|
//#region ../agent-cli/dist/login/store.js
|
|
8003
8036
|
const storedLoginSchema = object({
|
|
8004
8037
|
accessToken: string(),
|
|
@@ -8015,16 +8048,20 @@ const approvalSchema = object({
|
|
|
8015
8048
|
interval: number$1()
|
|
8016
8049
|
});
|
|
8017
8050
|
const KEY_LENGTH = 16;
|
|
8018
|
-
function keyOf(
|
|
8019
|
-
return createHash("sha256").update(
|
|
8051
|
+
function keyOf(...parts) {
|
|
8052
|
+
return createHash("sha256").update(parts.join("\n")).digest("hex").slice(0, KEY_LENGTH);
|
|
8020
8053
|
}
|
|
8021
8054
|
function loginFilesOf(userFile, login) {
|
|
8022
|
-
const key = keyOf(login);
|
|
8055
|
+
const key = keyOf(login.tokenEndpoint, login.clientId);
|
|
8023
8056
|
return {
|
|
8024
8057
|
stored: userFile(`login-${key}`, storedLoginSchema),
|
|
8025
8058
|
approval: userFile(`approval-${key}`, approvalSchema)
|
|
8026
8059
|
};
|
|
8027
8060
|
}
|
|
8061
|
+
/** The Approval pending for a Grant of `scope`, kept apart from the Login's and every other scope's. */
|
|
8062
|
+
function grantApprovalOf(userFile, { tokenEndpoint, clientId }, scope) {
|
|
8063
|
+
return userFile(`grant-${keyOf(tokenEndpoint, clientId, scope)}`, approvalSchema);
|
|
8064
|
+
}
|
|
8028
8065
|
/** The file's value, or `undefined` once its `expiresAt` has passed, removing the file then. */
|
|
8029
8066
|
async function readUnexpired(file, clock) {
|
|
8030
8067
|
const value = await file.read();
|
|
@@ -8172,11 +8209,12 @@ function tokenScopeOf(ctx) {
|
|
|
8172
8209
|
}
|
|
8173
8210
|
//#endregion
|
|
8174
8211
|
//#region ../agent-cli/dist/login/doctor-rows.js
|
|
8175
|
-
function loginRow(name,
|
|
8212
|
+
function loginRow(name, logins, runAs) {
|
|
8176
8213
|
return {
|
|
8177
8214
|
name: `login ${name}`,
|
|
8178
8215
|
advisory: true,
|
|
8179
8216
|
run: async (ctx) => {
|
|
8217
|
+
const login = declaredLogin(logins, name, ctx.env);
|
|
8180
8218
|
const set = setSecretOf(login, tokenScopeOf(ctx).secret);
|
|
8181
8219
|
if (set !== void 0) return {
|
|
8182
8220
|
state: "ok",
|
|
@@ -8197,16 +8235,16 @@ function loginRow(name, login, runAs) {
|
|
|
8197
8235
|
}
|
|
8198
8236
|
/** One `doctor` row per Login: where its token comes from, and `login` as the fix with none. */
|
|
8199
8237
|
function loginRows(logins, runAs) {
|
|
8200
|
-
return Object.
|
|
8238
|
+
return Object.keys(logins).map((name) => loginRow(name, logins, runAs));
|
|
8201
8239
|
}
|
|
8202
8240
|
//#endregion
|
|
8203
8241
|
//#region ../agent-cli/dist/version.js
|
|
8204
8242
|
/** The bundler's stamp, absent when the CLI runs unbundled. Read per call, so a test can define it. */
|
|
8205
8243
|
function buildStamp() {
|
|
8206
8244
|
return {
|
|
8207
|
-
"sha": "
|
|
8245
|
+
"sha": "8907e9d",
|
|
8208
8246
|
"dirty": false,
|
|
8209
|
-
"builtAt": "2026-11-
|
|
8247
|
+
"builtAt": "2026-11-10T09:08:31.000Z"
|
|
8210
8248
|
};
|
|
8211
8249
|
}
|
|
8212
8250
|
/** The first line of `--version`: the version, and the commit and time of a stamped build. */
|
|
@@ -10050,13 +10088,6 @@ function doctorCommand(cli, launch) {
|
|
|
10050
10088
|
};
|
|
10051
10089
|
}
|
|
10052
10090
|
//#endregion
|
|
10053
|
-
//#region ../agent-cli/dist/login/declared.js
|
|
10054
|
-
function declaredLogin(logins, name) {
|
|
10055
|
-
const login = logins[name];
|
|
10056
|
-
if (login === void 0) throw new Error(`${name} is not a Login the CLI declares`);
|
|
10057
|
-
return login;
|
|
10058
|
-
}
|
|
10059
|
-
//#endregion
|
|
10060
10091
|
//#region ../agent-cli/dist/login/device-flow.js
|
|
10061
10092
|
const DEVICE_CODE_GRANT = "urn:ietf:params:oauth:grant-type:device_code";
|
|
10062
10093
|
/** RFC 8628 §3.2: the interval when the server gives none. */
|
|
@@ -10086,7 +10117,7 @@ async function startApproval(login, { fetch, clock }) {
|
|
|
10086
10117
|
interval: device.interval ?? DEFAULT_INTERVAL_S
|
|
10087
10118
|
};
|
|
10088
10119
|
}
|
|
10089
|
-
async function pollApproval(
|
|
10120
|
+
async function pollApproval(asking, login, { approval, takenUp }, scope, signal) {
|
|
10090
10121
|
const form = {
|
|
10091
10122
|
grant_type: DEVICE_CODE_GRANT,
|
|
10092
10123
|
device_code: approval.deviceCode,
|
|
@@ -10100,23 +10131,23 @@ async function pollApproval(name, login, { approval, takenUp }, scope, signal) {
|
|
|
10100
10131
|
if (granted.success) return storedLoginOf(granted.data, scope.clock);
|
|
10101
10132
|
const { error } = parsedAnswer(errorSchema, body, login.tokenEndpoint);
|
|
10102
10133
|
if (error === "slow_down") intervalS += SLOW_DOWN_S;
|
|
10103
|
-
else if (error !== "authorization_pending") throw refusal(
|
|
10134
|
+
else if (error !== "authorization_pending") throw refusal(asking, login, error);
|
|
10104
10135
|
}
|
|
10105
10136
|
}
|
|
10106
10137
|
/** The error a token endpoint's answer other than pending or slow down ends the polling with. */
|
|
10107
|
-
function refusal(
|
|
10108
|
-
if (error === "access_denied") return
|
|
10109
|
-
if (error === "expired_token" || error === "invalid_grant") return
|
|
10138
|
+
function refusal(asking, login, error) {
|
|
10139
|
+
if (error === "access_denied") return asking.denied();
|
|
10140
|
+
if (error === "expired_token" || error === "invalid_grant") return asking.expired();
|
|
10110
10141
|
return /* @__PURE__ */ new Error(`${login.tokenEndpoint} refused the device code with ${error}`);
|
|
10111
10142
|
}
|
|
10112
10143
|
function endsApproval(error) {
|
|
10113
10144
|
return error instanceof CliError && (error.code === "APPROVAL_DENIED" || error.code === "APPROVAL_EXPIRED");
|
|
10114
10145
|
}
|
|
10115
10146
|
/** Takes up the pending Approval, or asks for one and keeps it as a User file, and prints its code. */
|
|
10116
|
-
async function askedApproval(login,
|
|
10117
|
-
const pending = await readUnexpired(
|
|
10147
|
+
async function askedApproval(login, file, scope) {
|
|
10148
|
+
const pending = await readUnexpired(file, scope.clock);
|
|
10118
10149
|
const approval = pending ?? await startApproval(login, scope);
|
|
10119
|
-
if (pending === void 0) await
|
|
10150
|
+
if (pending === void 0) await file.write(approval);
|
|
10120
10151
|
scope.progress(`open ${approval.verificationUriComplete ?? approval.verificationUri} and approve code ${approval.userCode}`);
|
|
10121
10152
|
return {
|
|
10122
10153
|
approval,
|
|
@@ -10125,28 +10156,39 @@ async function askedApproval(login, files, scope) {
|
|
|
10125
10156
|
}
|
|
10126
10157
|
/** The `APPROVAL_PENDING` of the pending Approval, or of a new one, without polling it. */
|
|
10127
10158
|
async function pendingApproval(name, login, files, scope, rerun) {
|
|
10128
|
-
const { approval } = await askedApproval(login, files, scope);
|
|
10129
|
-
return approvalPending(name, approval, rerun);
|
|
10159
|
+
const { approval } = await askedApproval(login, files.approval, scope);
|
|
10160
|
+
return approvalPending(loginAsking(name), approval, rerun);
|
|
10130
10161
|
}
|
|
10131
10162
|
/**
|
|
10132
|
-
* Polls the pending
|
|
10133
|
-
*
|
|
10163
|
+
* Polls the Approval pending in `file`, or a new one, until the person approves, removing it once
|
|
10164
|
+
* refused or expired. An approved one stays until what it granted is kept, so a cut-off run loses nothing.
|
|
10134
10165
|
*/
|
|
10135
|
-
async function
|
|
10136
|
-
const asked = await askedApproval(login,
|
|
10166
|
+
async function approved(asking, login, file, scope, { waitS, rerun }) {
|
|
10167
|
+
const asked = await askedApproval(login, file, scope);
|
|
10137
10168
|
const wait = scope.deadline(waitS * MS_PER_S);
|
|
10138
|
-
let
|
|
10169
|
+
let granted;
|
|
10139
10170
|
try {
|
|
10140
|
-
|
|
10171
|
+
granted = await pollApproval(asking, login, asked, scope, wait);
|
|
10141
10172
|
} catch (error) {
|
|
10142
|
-
if (wait.aborted && !scope.signal.aborted) throw approvalPending(
|
|
10143
|
-
if (endsApproval(error)) await
|
|
10173
|
+
if (wait.aborted && !scope.signal.aborted) throw approvalPending(asking, asked.approval, rerun);
|
|
10174
|
+
if (endsApproval(error)) await file.remove();
|
|
10144
10175
|
throw error;
|
|
10145
10176
|
}
|
|
10177
|
+
return granted;
|
|
10178
|
+
}
|
|
10179
|
+
/** Polls the pending Approval, or a new one, until the person approves, and stores the Login. */
|
|
10180
|
+
async function signIn(name, login, files, scope, wait) {
|
|
10181
|
+
const stored = await approved(loginAsking(name), login, files.approval, scope, wait);
|
|
10146
10182
|
await files.stored.write(stored);
|
|
10147
10183
|
await files.approval.remove();
|
|
10148
10184
|
return stored;
|
|
10149
10185
|
}
|
|
10186
|
+
/** Polls the Approval of the Grant's scope, or a new one, until the person approves: its token. */
|
|
10187
|
+
async function grant(asking, login, file, scope, wait) {
|
|
10188
|
+
const { accessToken } = await approved(asking, login, file, scope, wait);
|
|
10189
|
+
await file.remove();
|
|
10190
|
+
return accessToken;
|
|
10191
|
+
}
|
|
10150
10192
|
//#endregion
|
|
10151
10193
|
//#region ../agent-cli/dist/built-ins/login-name.js
|
|
10152
10194
|
/** The Login a `login` or `logout` run names, or the only one; with several, the name is needed. */
|
|
@@ -10231,7 +10273,7 @@ function logoutCommand(cli, logins, names) {
|
|
|
10231
10273
|
cliName: cli.name,
|
|
10232
10274
|
command: "logout"
|
|
10233
10275
|
}, given, names);
|
|
10234
|
-
const login = declaredLogin(logins, name);
|
|
10276
|
+
const login = declaredLogin(logins, name, ctx.env);
|
|
10235
10277
|
return {
|
|
10236
10278
|
login: name,
|
|
10237
10279
|
stored: await loginFilesOf(ctx.userFile, login).stored.read() !== void 0,
|
|
@@ -10240,7 +10282,7 @@ function logoutCommand(cli, logins, names) {
|
|
|
10240
10282
|
};
|
|
10241
10283
|
},
|
|
10242
10284
|
apply: async ({ login: name, secret }, ctx) => {
|
|
10243
|
-
const login = declaredLogin(logins, name);
|
|
10285
|
+
const login = declaredLogin(logins, name, ctx.env);
|
|
10244
10286
|
const file = loginFilesOf(ctx.userFile, login).stored;
|
|
10245
10287
|
const stored = await file.read();
|
|
10246
10288
|
const kept = secret === void 0 ? {} : { secret };
|
|
@@ -10317,7 +10359,7 @@ function loginCommand(cli, logins, names) {
|
|
|
10317
10359
|
cliName: cli.name,
|
|
10318
10360
|
command: "login"
|
|
10319
10361
|
}, given, names);
|
|
10320
|
-
const login = declaredLogin(logins, name);
|
|
10362
|
+
const login = declaredLogin(logins, name, ctx.env);
|
|
10321
10363
|
const token = await currentTokenOf(login, tokenScopeOf(ctx));
|
|
10322
10364
|
const stored = await readStored(loginFilesOf(ctx.userFile, login).stored, ctx.clock);
|
|
10323
10365
|
return {
|
|
@@ -10329,7 +10371,7 @@ function loginCommand(cli, logins, names) {
|
|
|
10329
10371
|
},
|
|
10330
10372
|
apply: async ({ login: name, wait, found }, ctx) => {
|
|
10331
10373
|
if (found !== void 0) return found;
|
|
10332
|
-
const login = declaredLogin(logins, name);
|
|
10374
|
+
const login = declaredLogin(logins, name, ctx.env);
|
|
10333
10375
|
const files = loginFilesOf(ctx.userFile, login);
|
|
10334
10376
|
const stored = await readStored(files.stored, ctx.clock);
|
|
10335
10377
|
if (stored?.refreshToken !== void 0 && await refreshed(name, login, files.stored, stored.refreshToken, ctx) !== void 0) return {
|
|
@@ -12181,7 +12223,7 @@ function approvalRerun(ctx) {
|
|
|
12181
12223
|
}
|
|
12182
12224
|
async function tokensOf(names, logins, ctx, waitS) {
|
|
12183
12225
|
const found = await Promise.all(names.map(async (name) => {
|
|
12184
|
-
const login = declaredLogin(logins, name);
|
|
12226
|
+
const login = declaredLogin(logins, name, ctx.env);
|
|
12185
12227
|
return {
|
|
12186
12228
|
name,
|
|
12187
12229
|
token: ctx.dryRun ? await currentTokenOf(login, tokenScopeOf(ctx)) : await freshTokenOf(name, login, ctx)
|
|
@@ -12195,7 +12237,7 @@ async function tokensOf(names, logins, ctx, waitS) {
|
|
|
12195
12237
|
tokens.set(name, token);
|
|
12196
12238
|
continue;
|
|
12197
12239
|
}
|
|
12198
|
-
const login = declaredLogin(logins, name);
|
|
12240
|
+
const login = declaredLogin(logins, name, ctx.env);
|
|
12199
12241
|
const stored = await signIn(name, login, loginFilesOf(ctx.userFile, login), ctx, {
|
|
12200
12242
|
waitS,
|
|
12201
12243
|
rerun: approvalRerun(ctx)
|
|
@@ -12221,26 +12263,49 @@ async function afterRejection(error, tokens, logins, ctx) {
|
|
|
12221
12263
|
const name = rejectedName(error, tokens);
|
|
12222
12264
|
const token = name === void 0 ? void 0 : tokens.get(name);
|
|
12223
12265
|
if (name === void 0 || token === void 0) return new Error(`the Command threw ${LOGIN_REJECTED} naming no Login it declares in details.login`, { cause: error });
|
|
12224
|
-
const login = declaredLogin(logins, name);
|
|
12266
|
+
const login = declaredLogin(logins, name, ctx.env);
|
|
12225
12267
|
if (token.source.kind === "secret" && login.secret !== void 0) return secretRejected(name, login.secret, error);
|
|
12226
12268
|
const files = loginFilesOf(ctx.userFile, login);
|
|
12227
12269
|
await files.stored.remove();
|
|
12228
12270
|
if (ctx.dryRun) return loginRequired([name], ctx.rerun());
|
|
12229
12271
|
return await pendingApproval(name, login, files, ctx, approvalRerun(ctx));
|
|
12230
12272
|
}
|
|
12273
|
+
/** `ctx.grant`: polls the Approval of `scope` for at most `waitS` seconds, and keeps no token. */
|
|
12274
|
+
function granting(ctx, grants, logins, waitS) {
|
|
12275
|
+
return async (name, { scope }) => {
|
|
12276
|
+
if (!grants.includes(name)) undeclaredGrant(name);
|
|
12277
|
+
if (ctx.dryRun) throw new Error(`ctx.grant("${name}") in a dry run, which asks for nothing: ask in apply`);
|
|
12278
|
+
const login = {
|
|
12279
|
+
...declaredLogin(logins, name, ctx.env),
|
|
12280
|
+
scope
|
|
12281
|
+
};
|
|
12282
|
+
return await grant(grantAsking(name, scope, ctx.rerun({ remove: [WAIT_FLAG.flag] })), login, grantApprovalOf(ctx.userFile, login, scope), ctx, {
|
|
12283
|
+
waitS,
|
|
12284
|
+
rerun: approvalRerun(ctx)
|
|
12285
|
+
});
|
|
12286
|
+
};
|
|
12287
|
+
}
|
|
12231
12288
|
/**
|
|
12232
12289
|
* Runs `work` with a `ctx` whose `login` gives each named Login's token, signing in first, for at
|
|
12233
|
-
* most `waitS` seconds, where one is missing
|
|
12290
|
+
* most `waitS` seconds, where one is missing, and whose `grant` asks for a Grant. A
|
|
12291
|
+
* `LOGIN_REJECTED` from `work` drops the stored Login.
|
|
12234
12292
|
*/
|
|
12235
|
-
async function withLogins(ctx, names, logins, waitS, work) {
|
|
12293
|
+
async function withLogins(ctx, { logins: names, grants }, logins, waitS, work) {
|
|
12236
12294
|
const tokens = names.length === 0 ? /* @__PURE__ */ new Map() : await tokensOf(names, logins, ctx, waitS ?? 0);
|
|
12237
|
-
const loggedIn = derived(ctx, {
|
|
12295
|
+
const loggedIn = derived(ctx, {
|
|
12296
|
+
login: (name) => tokens.get(name)?.value ?? undeclaredLogin(name),
|
|
12297
|
+
grant: granting(ctx, grants, logins, waitS ?? 0)
|
|
12298
|
+
});
|
|
12238
12299
|
try {
|
|
12239
12300
|
return await work(loggedIn);
|
|
12240
12301
|
} catch (error) {
|
|
12241
12302
|
throw await afterRejection(error, tokens, logins, ctx);
|
|
12242
12303
|
}
|
|
12243
12304
|
}
|
|
12305
|
+
/** `ctx.grant` of a name the Command does not declare in `grants`, which only a cast reaches. */
|
|
12306
|
+
function undeclaredGrant(name) {
|
|
12307
|
+
throw new Error(`ctx.grant("${name}") names a Login the Command does not declare in grants`);
|
|
12308
|
+
}
|
|
12244
12309
|
/** `ctx.login` of a name the Command does not declare, which only a cast reaches. */
|
|
12245
12310
|
function undeclaredLogin(name) {
|
|
12246
12311
|
throw new Error(`ctx.login("${name}") names a Login the Command does not declare`);
|
|
@@ -12300,7 +12365,10 @@ async function execute(command, input, unlogged, run) {
|
|
|
12300
12365
|
envFile,
|
|
12301
12366
|
fileError
|
|
12302
12367
|
}, unlogged.rerun());
|
|
12303
|
-
return await withLogins(unlogged,
|
|
12368
|
+
return await withLogins(unlogged, {
|
|
12369
|
+
logins: command.logins ?? [],
|
|
12370
|
+
grants: command.grants ?? []
|
|
12371
|
+
}, run.logins, run.flags.wait, (ctx) => executeLoggedIn(command, input, ctx, run));
|
|
12304
12372
|
}
|
|
12305
12373
|
async function executeLoggedIn(command, input, ctx, { flags, commandLine, started, outputs: runOutputs }) {
|
|
12306
12374
|
if (command.rows !== void 0) {
|
|
@@ -12540,6 +12608,7 @@ function contextOf(scope, control, { command, flags, project, deliver, latestRel
|
|
|
12540
12608
|
...portsBase,
|
|
12541
12609
|
secret,
|
|
12542
12610
|
login: undeclaredLogin,
|
|
12611
|
+
grant: async (name) => undeclaredGrant(name),
|
|
12543
12612
|
userFile: scope.userFile,
|
|
12544
12613
|
fail: cliErrorOf,
|
|
12545
12614
|
deadline: (ms, options) => control.deadline(ms, options),
|
|
@@ -12898,7 +12967,7 @@ async function runProcess(cli) {
|
|
|
12898
12967
|
//#region package.json
|
|
12899
12968
|
var package_default = {
|
|
12900
12969
|
name: "@duyquangnvx/create-agent-cli",
|
|
12901
|
-
version: "0.
|
|
12970
|
+
version: "0.32.0",
|
|
12902
12971
|
description: "Creates a new Agent CLI repository wired to @duyquangnvx/agent-cli.",
|
|
12903
12972
|
type: "module",
|
|
12904
12973
|
engines: { "node": ">=22.12.0" },
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@duyquangnvx/create-agent-cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.32.0",
|
|
4
4
|
"description": "Creates a new Agent CLI repository wired to @duyquangnvx/agent-cli.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"engines": {
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
"access": "public"
|
|
22
22
|
},
|
|
23
23
|
"devDependencies": {
|
|
24
|
-
"@duyquangnvx/agent-cli": "0.
|
|
24
|
+
"@duyquangnvx/agent-cli": "0.32.0",
|
|
25
25
|
"tsdown": "0.23.0",
|
|
26
26
|
"zod": "4.6.7"
|
|
27
27
|
},
|