@wirecat/cli-core 0.437.0 → 0.438.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 +14 -0
- package/dist/cli/profile.d.ts +1 -0
- package/dist/cli/profile.js +2 -1
- package/dist/cli/program.js +7 -3
- package/dist/cli/settings.js +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,20 @@ Notable changes to `@wirecat/cli-core` (`@wirecat/cli-messaging` up to 0.261.0,
|
|
|
5
5
|
minor version may break callers, and says how under "Changed — may break callers". `pnpm docs:check` checks the
|
|
6
6
|
shape of this file.
|
|
7
7
|
|
|
8
|
+
## Unreleased
|
|
9
|
+
|
|
10
|
+
## 0.438.0 — 26.10.2026
|
|
11
|
+
|
|
12
|
+
### Security
|
|
13
|
+
|
|
14
|
+
- **A first word refused as a profile no longer reaches the run log.** When the first word could not be a profile
|
|
15
|
+
(`app "runs list"`, two words in one argument) or a profile lock refused it, the failed run's record kept it as
|
|
16
|
+
`profile` while its `argv` showed `[redacted]` — so whatever was typed first, possibly message text or a person's
|
|
17
|
+
name, was stored in the clear. Such a run now records no profile, as a run that names none does; a valid profile
|
|
18
|
+
the settings accepted is recorded as before. The lock's refusal quotes the refused word, so a kept error masks it,
|
|
19
|
+
and a bare first word with no command after it suggests `<tool> <word> account show` only when the word can be a
|
|
20
|
+
profile and the CLI has an `account show` command — that suggestion repeated the word unmasked in the kept error.
|
|
21
|
+
|
|
8
22
|
## 0.437.0 — 26.10.2026
|
|
9
23
|
|
|
10
24
|
### Added
|
package/dist/cli/profile.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { Command } from "commander";
|
|
2
2
|
/** How the command line names this profile: always the first word, since none is assumed. */
|
|
3
3
|
export declare const asFirstWord: (profile: string) => string;
|
|
4
|
+
export declare const isProfileName: (word: string) => boolean;
|
|
4
5
|
export declare const usableProfileName: (profile: string) => string;
|
|
5
6
|
/** The top-level commands that never read a profile; every other one is `<tool> <profile> …`. */
|
|
6
7
|
export declare const PROFILE_FREE: ReadonlySet<string>;
|
package/dist/cli/profile.js
CHANGED
|
@@ -7,8 +7,9 @@ export const asFirstWord = (profile) => `${profile} `;
|
|
|
7
7
|
* somewhere nobody would think to look.
|
|
8
8
|
*/
|
|
9
9
|
const PLAIN_NAME = /^[A-Za-z0-9][A-Za-z0-9._-]*$/;
|
|
10
|
+
export const isProfileName = (word) => PLAIN_NAME.test(word);
|
|
10
11
|
export const usableProfileName = (profile) => {
|
|
11
|
-
if (!
|
|
12
|
+
if (!isProfileName(profile)) {
|
|
12
13
|
throw new CliError("validation_error", `"${profile}" cannot be a profile name — letters, digits, dot, dash and underscore only, ` +
|
|
13
14
|
"starting with a letter or a digit");
|
|
14
15
|
}
|
package/dist/cli/program.js
CHANGED
|
@@ -27,7 +27,7 @@ import { showInputFields } from "./input-fields.js";
|
|
|
27
27
|
import { MAX_BUFFERED_INPUT, provideInputPolicy } from "./input-policy.js";
|
|
28
28
|
import { checkJson, liftJson } from "./json-fields.js";
|
|
29
29
|
import { PreviewComplete, preview } from "./preview.js";
|
|
30
|
-
import { commandWords, liftProfile, sampleCommand, takesProfile, valuedOptions } from "./profile.js";
|
|
30
|
+
import { commandWords, isProfileName, liftProfile, sampleCommand, takesProfile, valuedOptions } from "./profile.js";
|
|
31
31
|
import { absolutePaths, relayTarget } from "./relay-route.js";
|
|
32
32
|
import { NoProfileHere, namedProfile, settingsFor, } from "./settings.js";
|
|
33
33
|
import { assertSharedContracts } from "./shared-contracts.js";
|
|
@@ -433,8 +433,11 @@ const runOnce = async (argv, definition, options) => {
|
|
|
433
433
|
// A bare word with nothing after it would make commander print help **on stdout**, which breaks
|
|
434
434
|
// the one contract this program has and says nothing about why.
|
|
435
435
|
if (profile !== undefined && rest.length === 0) {
|
|
436
|
+
const asProfile = commandAt(program, "account show") && isProfileName(profile)
|
|
437
|
+
? `, or \`${command} ${profile} account show\` if "${profile}" is your profile`
|
|
438
|
+
: "";
|
|
436
439
|
const message = `"${profile}" is not a command, so it was read as a profile name — and no command followed it. ` +
|
|
437
|
-
`Run \`${command} --help\` for the commands
|
|
440
|
+
`Run \`${command} --help\` for the commands${asProfile}.`;
|
|
438
441
|
const failure = new CliError("validation_error", message, { param: "profile" });
|
|
439
442
|
const settled = await settleFailure(failure, { definition, program, rest, argv, profile, options });
|
|
440
443
|
return report(streams, reporting, failed(definition, program, rest, failure, settled, debug));
|
|
@@ -597,7 +600,8 @@ const keepFailure = async (failure, { definition, program, rest, argv, profile,
|
|
|
597
600
|
argv,
|
|
598
601
|
env,
|
|
599
602
|
}),
|
|
600
|
-
|
|
603
|
+
// Settings that did not load never accepted the word, which may be a refused name or somebody's words.
|
|
604
|
+
profile: settings ? namedProfile(settings) : undefined,
|
|
601
605
|
record: false,
|
|
602
606
|
keepFailed: settings?.keepFailedRuns ?? !rest.includes("--no-record"),
|
|
603
607
|
trace: false,
|
package/dist/cli/settings.js
CHANGED
|
@@ -168,7 +168,7 @@ export const settingsFor = (app, extension = {}) => {
|
|
|
168
168
|
if (profile.value === lock)
|
|
169
169
|
return profile;
|
|
170
170
|
if (profile.from === "first word" || profile.from === PROFILE) {
|
|
171
|
-
throw new CliError("permission_error", `this process is locked to profile ${lock} (${PROFILE_LOCK}) — profile ${profile.value} is refused`);
|
|
171
|
+
throw new CliError("permission_error", `this process is locked to profile ${lock} (${PROFILE_LOCK}) — profile "${profile.value}" is refused`);
|
|
172
172
|
}
|
|
173
173
|
return { value: lock, from: PROFILE_LOCK };
|
|
174
174
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wirecat/cli-core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.438.0",
|
|
4
4
|
"description": "The messenger-neutral half of a messaging CLI: domain model, message locators, rendering, name resolution, the SQLite seam, the command skeleton and shared read commands, the send guard, run records and the message store",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"author": "Viacheslav Ptsarev",
|