@wirecat/cli-core 0.564.0 → 0.566.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 +76 -0
- package/constants.json +13 -0
- package/dist/calendar/busy.d.ts +10 -10
- package/dist/calendar/busy.js +9 -9
- package/dist/calendar/cli/answers.d.ts +7 -8
- package/dist/calendar/cli/answers.js +4 -5
- package/dist/calendar/cli/bodies.d.ts +33 -0
- package/dist/calendar/cli/bodies.js +52 -0
- package/dist/calendar/cli/files.d.ts +8 -0
- package/dist/calendar/cli/files.js +41 -0
- package/dist/calendar/cli/index.d.ts +58 -51
- package/dist/calendar/cli/index.js +311 -284
- package/dist/calendar/cli/remind.d.ts +2 -11
- package/dist/calendar/cli/remind.js +81 -81
- package/dist/calendar/cli/search-all.d.ts +3 -8
- package/dist/calendar/cli/search-all.js +47 -42
- package/dist/calendar/mcp/index.d.ts +13 -13
- package/dist/calendar/prepare.d.ts +1 -1
- package/dist/calendar/testing/answers.d.ts +27 -5
- package/dist/calendar/testing/answers.js +88 -17
- package/dist/calendar/testing/writer.d.ts +1 -0
- package/dist/calendar/testing/writer.js +6 -0
- package/dist/calendar/writer.d.ts +6 -1
- package/dist/calendar/writes.d.ts +3 -1
- package/dist/calendar/writes.js +42 -20
- package/dist/cli/app-doctor-command.d.ts +7 -13
- package/dist/cli/app-doctor-command.js +1 -1
- package/dist/cli/config-command.js +1 -1
- package/dist/cli/config-issues.d.ts +3 -1
- package/dist/cli/config-issues.js +2 -2
- package/dist/cli/contract-evidence.d.ts +1 -1
- package/dist/cli/early-refusal.d.ts +2 -1
- package/dist/cli/early-refusal.js +4 -2
- package/dist/cli/entry.d.ts +6 -2
- package/dist/cli/entry.js +4 -1
- package/dist/cli/envelope.d.ts +2 -2
- package/dist/cli/index.d.ts +1 -0
- package/dist/cli/index.js +1 -0
- package/dist/cli/messenger/store-maintenance-command.d.ts +1 -1
- package/dist/cli/permission-keys.d.ts +3 -1
- package/dist/cli/permission-keys.js +2 -1
- package/dist/cli/preview.d.ts +12 -0
- package/dist/cli/preview.js +8 -1
- package/dist/cli/settings.d.ts +2 -0
- package/dist/cli/settings.js +8 -1
- package/dist/constants/index.d.ts +83 -0
- package/dist/constants/index.js +77 -0
- package/dist/constants/obscure.d.ts +1 -0
- package/dist/constants/obscure.js +9 -0
- package/dist/errors/reasons.js +15 -1
- package/dist/mcp/meeting-preparation.d.ts +1 -1
- package/dist/mcp/meeting-project-candidates.d.ts +1 -1
- package/dist/mcp/meeting-series-inventory.d.ts +1 -1
- package/dist/meetings/mcp/passage.d.ts +1 -1
- package/dist/meetings/mcp/project-evidence.d.ts +1 -1
- package/dist/meetings/mcp/search.d.ts +1 -1
- package/dist/oauth/index.d.ts +1 -1
- package/dist/oauth/provider.d.ts +5 -0
- package/dist/oauth/storage.js +12 -2
- package/dist/services/metadata.d.ts +1 -1
- package/package.json +8 -3
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import * as v from "valibot";
|
|
2
|
+
import type { AppSource, OAuthClient } from "../oauth/provider.js";
|
|
3
|
+
/** cli-core's layer, read after cli-base's and before the tool's. */
|
|
4
|
+
export declare const CORE_CONSTANTS: import("url").URL;
|
|
5
|
+
/** What cli-base's and cli-core's layers hold; a tool extends it with `v.object({ ...constantsSchema.entries, … })`. */
|
|
6
|
+
export declare const constantsSchema: v.ObjectSchema<{
|
|
7
|
+
readonly google: v.ObjectSchema<{
|
|
8
|
+
readonly app: v.ObjectSchema<{
|
|
9
|
+
readonly client_id: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.NonEmptyAction<string, undefined>, v.TransformAction<string, string>]>;
|
|
10
|
+
readonly client_secret: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TransformAction<string, string>]>, undefined>;
|
|
11
|
+
}, undefined>;
|
|
12
|
+
}, undefined>;
|
|
13
|
+
readonly microsoft: v.ObjectSchema<{
|
|
14
|
+
readonly app: v.ObjectSchema<{
|
|
15
|
+
readonly client_id: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.NonEmptyAction<string, undefined>]>;
|
|
16
|
+
}, undefined>;
|
|
17
|
+
}, undefined>;
|
|
18
|
+
}, undefined>;
|
|
19
|
+
export type Constants = v.InferOutput<typeof constantsSchema>;
|
|
20
|
+
/**
|
|
21
|
+
* The packaged constants, base → core → the tool's `constants.json` when given, read once per process for each tool
|
|
22
|
+
* layer. A tool with constants of its own passes its layer and a schema built on `constantsSchema`; the first call for
|
|
23
|
+
* a layer decides its schema.
|
|
24
|
+
*/
|
|
25
|
+
export declare const constants: <TSchema extends v.GenericSchema<unknown, Constants> = typeof constantsSchema>(toolLayer?: URL, schema?: TSchema) => v.InferOutput<TSchema>;
|
|
26
|
+
export interface AppOptions {
|
|
27
|
+
env: NodeJS.ProcessEnv;
|
|
28
|
+
/** The tool's environment prefix: `GCAL` with provider `google` reads `GCAL_GOOGLE_CLIENT_ID` and `_SECRET`. */
|
|
29
|
+
prefix: string;
|
|
30
|
+
/** `--client-id`. A secret for it comes from `<PREFIX>_<PROVIDER>_CLIENT_SECRET`. */
|
|
31
|
+
clientId?: string | undefined;
|
|
32
|
+
/** The account's config key `<provider>.client_id`. A config file never holds the secret: it comes from the env. */
|
|
33
|
+
configClientId?: string | undefined;
|
|
34
|
+
}
|
|
35
|
+
export interface OAuthAppOptions extends AppOptions {
|
|
36
|
+
/** `google`, `microsoft`, `zoom`: names the env variables, upper-cased. */
|
|
37
|
+
provider: string;
|
|
38
|
+
/** WireCat's app from the constants; an empty or missing id means WireCat has none for this provider. */
|
|
39
|
+
wirecat?: {
|
|
40
|
+
client_id?: string | undefined;
|
|
41
|
+
client_secret?: string | undefined;
|
|
42
|
+
} | undefined;
|
|
43
|
+
}
|
|
44
|
+
export interface OAuthApp {
|
|
45
|
+
client: OAuthClient & {
|
|
46
|
+
source: AppSource;
|
|
47
|
+
};
|
|
48
|
+
source: AppSource;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* The app a sign-in uses, first match wins (WC-SECR-25): `--client-id`, `<PREFIX>_<PROVIDER>_CLIENT_ID`, the account's
|
|
52
|
+
* `<provider>.client_id`, WireCat's app. A secret without any of the first three ids is a `configuration_error`.
|
|
53
|
+
* Undefined when nothing names an app and WireCat has none.
|
|
54
|
+
*/
|
|
55
|
+
export declare const oauthApp: (options: OAuthAppOptions) => OAuthApp | undefined;
|
|
56
|
+
export interface GoogleAppOptions extends AppOptions {
|
|
57
|
+
/** The owner's Desktop client JSON, `--client-file`; it must be private to the owner. */
|
|
58
|
+
clientFile?: string | undefined;
|
|
59
|
+
platform?: NodeJS.Platform;
|
|
60
|
+
/** The tool's own constants, when its layer overrides the app. */
|
|
61
|
+
constants?: Constants;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* The Google Desktop app a sign-in uses: `--client-file`, then `oauthApp`'s order. Google treats a Desktop app's
|
|
65
|
+
* secret as public (https://developers.google.com/identity/protocols/oauth2/native-app), so WireCat's ships, obscured,
|
|
66
|
+
* in cli-core's constants.
|
|
67
|
+
*/
|
|
68
|
+
export declare const googleApp: (options: GoogleAppOptions) => OAuthApp;
|
|
69
|
+
/** WireCat's Microsoft app is a public client: it has an id and no secret. */
|
|
70
|
+
export declare const microsoftApp: (options: AppOptions & {
|
|
71
|
+
constants?: Constants;
|
|
72
|
+
}) => OAuthApp;
|
|
73
|
+
export interface OAuthClientReport {
|
|
74
|
+
client: "wirecat" | "own" | null;
|
|
75
|
+
source: AppSource | null;
|
|
76
|
+
/** Why there is no app, when `client` is null. */
|
|
77
|
+
reason?: string;
|
|
78
|
+
}
|
|
79
|
+
/** `doctor`'s `oauth_client` for one provider: the app a new sign-in would use; doctor reads no keyring. */
|
|
80
|
+
export declare const oauthClientReport: (app: {
|
|
81
|
+
source?: AppSource | undefined;
|
|
82
|
+
} | undefined, reason?: string) => OAuthClientReport;
|
|
83
|
+
export type { AppSource };
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { BASE_CONSTANTS, baseConstantsSchema, CliError, loadConstants } from "@wirecat/cli-base";
|
|
2
|
+
import * as v from "valibot";
|
|
3
|
+
import { readClientFile } from "../oauth/client-file.js";
|
|
4
|
+
import { reveal } from "./obscure.js";
|
|
5
|
+
/** cli-core's layer, read after cli-base's and before the tool's. */
|
|
6
|
+
export const CORE_CONSTANTS = new URL("../../constants.json", import.meta.url);
|
|
7
|
+
/** What cli-base's and cli-core's layers hold; a tool extends it with `v.object({ ...constantsSchema.entries, … })`. */
|
|
8
|
+
export const constantsSchema = v.object({
|
|
9
|
+
...baseConstantsSchema.entries,
|
|
10
|
+
google: v.object({
|
|
11
|
+
app: v.object({
|
|
12
|
+
client_id: v.pipe(v.string(), v.nonEmpty(), v.transform(reveal)),
|
|
13
|
+
client_secret: v.optional(v.pipe(v.string(), v.transform(reveal))),
|
|
14
|
+
}),
|
|
15
|
+
}),
|
|
16
|
+
microsoft: v.object({ app: v.object({ client_id: v.pipe(v.string(), v.nonEmpty()) }) }),
|
|
17
|
+
});
|
|
18
|
+
const loaded = new Map();
|
|
19
|
+
/**
|
|
20
|
+
* The packaged constants, base → core → the tool's `constants.json` when given, read once per process for each tool
|
|
21
|
+
* layer. A tool with constants of its own passes its layer and a schema built on `constantsSchema`; the first call for
|
|
22
|
+
* a layer decides its schema.
|
|
23
|
+
*/
|
|
24
|
+
export const constants = (toolLayer, schema) => {
|
|
25
|
+
const key = toolLayer?.href ?? "";
|
|
26
|
+
if (!loaded.has(key)) {
|
|
27
|
+
const layers = toolLayer ? [BASE_CONSTANTS, CORE_CONSTANTS, toolLayer] : [BASE_CONSTANTS, CORE_CONSTANTS];
|
|
28
|
+
loaded.set(key, loadConstants(layers, schema ?? constantsSchema));
|
|
29
|
+
}
|
|
30
|
+
return loaded.get(key);
|
|
31
|
+
};
|
|
32
|
+
/**
|
|
33
|
+
* The app a sign-in uses, first match wins (WC-SECR-25): `--client-id`, `<PREFIX>_<PROVIDER>_CLIENT_ID`, the account's
|
|
34
|
+
* `<provider>.client_id`, WireCat's app. A secret without any of the first three ids is a `configuration_error`.
|
|
35
|
+
* Undefined when nothing names an app and WireCat has none.
|
|
36
|
+
*/
|
|
37
|
+
export const oauthApp = (options) => {
|
|
38
|
+
const { env, prefix, provider } = options;
|
|
39
|
+
const name = `${prefix}_${provider.toUpperCase()}_CLIENT`;
|
|
40
|
+
const clientSecret = env[`${name}_SECRET`];
|
|
41
|
+
const own = [
|
|
42
|
+
[options.clientId, "flag"],
|
|
43
|
+
[env[`${name}_ID`], "env"],
|
|
44
|
+
[options.configClientId, "config"],
|
|
45
|
+
];
|
|
46
|
+
const [clientId, source] = own.find(([id]) => id) ?? [];
|
|
47
|
+
if (clientId && source)
|
|
48
|
+
return app({ clientId, ...(clientSecret ? { clientSecret } : {}) }, source);
|
|
49
|
+
if (clientSecret)
|
|
50
|
+
throw new CliError("configuration_error", `${name}_SECRET is set without a client id; set ${name}_ID too, or unset it to use WireCat's app`, { reason: "sign-in.secret-without-id" });
|
|
51
|
+
const wirecat = options.wirecat;
|
|
52
|
+
if (!wirecat?.client_id)
|
|
53
|
+
return undefined;
|
|
54
|
+
return app({ clientId: wirecat.client_id, ...(wirecat.client_secret ? { clientSecret: wirecat.client_secret } : {}) }, "constants");
|
|
55
|
+
};
|
|
56
|
+
const app = (client, source) => ({ client: { ...client, source }, source });
|
|
57
|
+
/**
|
|
58
|
+
* The Google Desktop app a sign-in uses: `--client-file`, then `oauthApp`'s order. Google treats a Desktop app's
|
|
59
|
+
* secret as public (https://developers.google.com/identity/protocols/oauth2/native-app), so WireCat's ships, obscured,
|
|
60
|
+
* in cli-core's constants.
|
|
61
|
+
*/
|
|
62
|
+
export const googleApp = (options) => {
|
|
63
|
+
const { clientFile, platform } = options;
|
|
64
|
+
if (clientFile)
|
|
65
|
+
return app(readClientFile(clientFile, platform ? { platform } : {}), "flag");
|
|
66
|
+
const wirecat = (options.constants ?? constants()).google.app;
|
|
67
|
+
return oauthApp({ ...options, provider: "google", wirecat });
|
|
68
|
+
};
|
|
69
|
+
/** WireCat's Microsoft app is a public client: it has an id and no secret. */
|
|
70
|
+
export const microsoftApp = (options) => {
|
|
71
|
+
const wirecat = (options.constants ?? constants()).microsoft.app;
|
|
72
|
+
return oauthApp({ ...options, provider: "microsoft", wirecat });
|
|
73
|
+
};
|
|
74
|
+
/** `doctor`'s `oauth_client` for one provider: the app a new sign-in would use; doctor reads no keyring. */
|
|
75
|
+
export const oauthClientReport = (app, reason) => app?.source
|
|
76
|
+
? { client: app.source === "constants" ? "wirecat" : "own", source: app.source }
|
|
77
|
+
: { client: null, source: null, ...(reason ? { reason } : {}) };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const reveal: (obscured: string) => string;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { createDecipheriv } from "node:crypto";
|
|
2
|
+
// Not protection: anyone holding the package can reveal these. It keeps secret scanners and a casual read from
|
|
3
|
+
// treating WireCat's public Desktop app as a leaked credential, as rclone does for its own app.
|
|
4
|
+
const KEY = Buffer.from("d43012779aa2dded3e98092a3dbcf5d8980c564172f5ce0a5fd0574e5f740339", "hex");
|
|
5
|
+
export const reveal = (obscured) => {
|
|
6
|
+
const bytes = Buffer.from(obscured, "base64url");
|
|
7
|
+
const decipher = createDecipheriv("aes-256-ctr", KEY, bytes.subarray(0, 16));
|
|
8
|
+
return Buffer.concat([decipher.update(bytes.subarray(16)), decipher.final()]).toString("utf8");
|
|
9
|
+
};
|
package/dist/errors/reasons.js
CHANGED
|
@@ -31,6 +31,19 @@ const SIGN_IN = [
|
|
|
31
31
|
["oauth.not-saved", "configuration_error", "the sign-in cannot be saved or read where it is kept"],
|
|
32
32
|
["sign-in.client-file-open", "configuration_error", "other users of this computer can read the client file"],
|
|
33
33
|
["sign-in.client-file-invalid", "configuration_error", "the file is not a Desktop app OAuth client JSON"],
|
|
34
|
+
["oauth.scope-missing", "permission_error", "the sign-in lacks a permission this command needs"],
|
|
35
|
+
["sign-in.client-rejected", "configuration_error", "the provider rejected the OAuth client"],
|
|
36
|
+
["sign-in.secret-without-id", "configuration_error", "an OAuth client secret is set without its client id"],
|
|
37
|
+
];
|
|
38
|
+
/** Reasons every CLI over a provider's API raises alike: gcal and drive today. */
|
|
39
|
+
const PROVIDER_API = [
|
|
40
|
+
["offline.refused", "permission_error", "this command needs the provider; --offline was given"],
|
|
41
|
+
validation("api.unknown-method", "the provider has no method by this name"),
|
|
42
|
+
["api.disabled", "configuration_error", "the provider's API is turned off for this OAuth project"],
|
|
43
|
+
["provider.usage-limit", "rate_limited", "the account's usage limit at the provider is reached; wait, do not retry"],
|
|
44
|
+
["file.not-found", "not_found", "the file named, or its folder, does not exist"],
|
|
45
|
+
validation("file.not-a-file", "the path names a folder or another thing that is not a file"),
|
|
46
|
+
["file.denied", "permission_error", "the file cannot be opened: permission denied"],
|
|
34
47
|
];
|
|
35
48
|
const OTHERS = [
|
|
36
49
|
["query.time-limit", "timeout", "the search took longer than its time limit; the query itself is valid"],
|
|
@@ -87,6 +100,7 @@ const OTHERS = [
|
|
|
87
100
|
validation("event.repeat-split", "the series cannot be split at this occurrence, or was split there already"),
|
|
88
101
|
validation("event.repeat-count", "a COUNT series is split only with a rule for its new part"),
|
|
89
102
|
validation("event.unmovable", "the provider keeps this kind of event on its calendar"),
|
|
103
|
+
validation("event.quick-add-ambiguous", "more than one event could be the one a lost quick add made"),
|
|
90
104
|
validation("event.text-with-fields", "--text takes the whole event from its line, so no field option goes with it"),
|
|
91
105
|
validation("calendar.ambiguous", "two or more calendars have this name; name one by its id"),
|
|
92
106
|
validation("export.too-many", "the query finds more events than one export writes"),
|
|
@@ -258,7 +272,7 @@ export const INPUT_FIELD_REASONS = defineReasons([
|
|
|
258
272
|
export const REASONS = defineReasons([
|
|
259
273
|
...QUERY_REASONS,
|
|
260
274
|
...INPUT_FIELD_REASONS,
|
|
261
|
-
...[...QUERY, ...SIGN_IN, ...OTHERS].map(([reason, code, message]) => ({
|
|
275
|
+
...[...QUERY, ...SIGN_IN, ...PROVIDER_API, ...OTHERS].map(([reason, code, message]) => ({
|
|
262
276
|
reason,
|
|
263
277
|
code,
|
|
264
278
|
message,
|
|
@@ -28,7 +28,7 @@ export declare const callMeetingPreparationTool: (read: MeetingPreparationReader
|
|
|
28
28
|
}[];
|
|
29
29
|
structuredContent: {
|
|
30
30
|
error: {
|
|
31
|
-
code: "authentication_error" | "cancelled" | "configuration_error" | "confirmation_required" | "internal_error" | "invalid_response" | "network_error" | "not_found" | "outcome_unknown" | "permission_error" | "provider_error" | "provider_unavailable" | "rate_limited" | "timeout" | "validation_error";
|
|
31
|
+
code: "authentication_error" | "cancelled" | "configuration_error" | "confirmation_required" | "conflict" | "internal_error" | "invalid_response" | "network_error" | "not_found" | "outcome_unknown" | "permission_error" | "provider_error" | "provider_unavailable" | "rate_limited" | "timeout" | "validation_error";
|
|
32
32
|
reason: string;
|
|
33
33
|
message: string;
|
|
34
34
|
param?: string | undefined;
|
|
@@ -23,7 +23,7 @@ export declare const callMeetingProjectCandidatesTool: (read: StoredMeetingProje
|
|
|
23
23
|
}[];
|
|
24
24
|
structuredContent: {
|
|
25
25
|
error: {
|
|
26
|
-
code: "authentication_error" | "cancelled" | "configuration_error" | "confirmation_required" | "internal_error" | "invalid_response" | "network_error" | "not_found" | "outcome_unknown" | "permission_error" | "provider_error" | "provider_unavailable" | "rate_limited" | "timeout" | "validation_error";
|
|
26
|
+
code: "authentication_error" | "cancelled" | "configuration_error" | "confirmation_required" | "conflict" | "internal_error" | "invalid_response" | "network_error" | "not_found" | "outcome_unknown" | "permission_error" | "provider_error" | "provider_unavailable" | "rate_limited" | "timeout" | "validation_error";
|
|
27
27
|
reason: string;
|
|
28
28
|
message: string;
|
|
29
29
|
param?: string | undefined;
|
|
@@ -23,7 +23,7 @@ export declare const callMeetingSeriesInventoryTool: (read: MeetingSeriesInvento
|
|
|
23
23
|
}[];
|
|
24
24
|
structuredContent: {
|
|
25
25
|
error: {
|
|
26
|
-
code: "authentication_error" | "cancelled" | "configuration_error" | "confirmation_required" | "internal_error" | "invalid_response" | "network_error" | "not_found" | "outcome_unknown" | "permission_error" | "provider_error" | "provider_unavailable" | "rate_limited" | "timeout" | "validation_error";
|
|
26
|
+
code: "authentication_error" | "cancelled" | "configuration_error" | "confirmation_required" | "conflict" | "internal_error" | "invalid_response" | "network_error" | "not_found" | "outcome_unknown" | "permission_error" | "provider_error" | "provider_unavailable" | "rate_limited" | "timeout" | "validation_error";
|
|
27
27
|
reason: string;
|
|
28
28
|
message: string;
|
|
29
29
|
param?: string | undefined;
|
|
@@ -57,7 +57,7 @@ export declare const callMeetingPassageTool: (read: MeetingPassageReader, input:
|
|
|
57
57
|
}[];
|
|
58
58
|
structuredContent: {
|
|
59
59
|
error: {
|
|
60
|
-
code: "authentication_error" | "cancelled" | "configuration_error" | "confirmation_required" | "internal_error" | "invalid_response" | "network_error" | "not_found" | "outcome_unknown" | "permission_error" | "provider_error" | "provider_unavailable" | "rate_limited" | "timeout" | "validation_error";
|
|
60
|
+
code: "authentication_error" | "cancelled" | "configuration_error" | "confirmation_required" | "conflict" | "internal_error" | "invalid_response" | "network_error" | "not_found" | "outcome_unknown" | "permission_error" | "provider_error" | "provider_unavailable" | "rate_limited" | "timeout" | "validation_error";
|
|
61
61
|
reason: string;
|
|
62
62
|
message: string;
|
|
63
63
|
param?: string | undefined;
|
|
@@ -51,7 +51,7 @@ export declare const callMeetingProjectEvidenceTool: (read: MeetingProjectDiscov
|
|
|
51
51
|
}[];
|
|
52
52
|
structuredContent: {
|
|
53
53
|
error: {
|
|
54
|
-
code: "authentication_error" | "cancelled" | "configuration_error" | "confirmation_required" | "internal_error" | "invalid_response" | "network_error" | "not_found" | "outcome_unknown" | "permission_error" | "provider_error" | "provider_unavailable" | "rate_limited" | "timeout" | "validation_error";
|
|
54
|
+
code: "authentication_error" | "cancelled" | "configuration_error" | "confirmation_required" | "conflict" | "internal_error" | "invalid_response" | "network_error" | "not_found" | "outcome_unknown" | "permission_error" | "provider_error" | "provider_unavailable" | "rate_limited" | "timeout" | "validation_error";
|
|
55
55
|
reason: string;
|
|
56
56
|
message: string;
|
|
57
57
|
param?: string | undefined;
|
|
@@ -94,7 +94,7 @@ export declare const callMeetingSearchTool: (search: MeetingHitSearch, input: un
|
|
|
94
94
|
}[];
|
|
95
95
|
structuredContent: {
|
|
96
96
|
error: {
|
|
97
|
-
code: "authentication_error" | "cancelled" | "configuration_error" | "confirmation_required" | "internal_error" | "invalid_response" | "network_error" | "not_found" | "outcome_unknown" | "permission_error" | "provider_error" | "provider_unavailable" | "rate_limited" | "timeout" | "validation_error";
|
|
97
|
+
code: "authentication_error" | "cancelled" | "configuration_error" | "confirmation_required" | "conflict" | "internal_error" | "invalid_response" | "network_error" | "not_found" | "outcome_unknown" | "permission_error" | "provider_error" | "provider_unavailable" | "rate_limited" | "timeout" | "validation_error";
|
|
98
98
|
reason: string;
|
|
99
99
|
message: string;
|
|
100
100
|
param?: string | undefined;
|
package/dist/oauth/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export { type Authorization, type AuthorizeOptions, authorize } from "./authorize.js";
|
|
2
2
|
export { type ClientFileOptions, readClientFile } from "./client-file.js";
|
|
3
3
|
export { type SignInOptions, type TokenKeeper, type TokenKeeperOptions, type TokensOptions, tokenKeeper, } from "./keeper.js";
|
|
4
|
-
export type { ExchangeContext, OAuthClient, OAuthProvider, RequestContext, TokenSet } from "./provider.js";
|
|
4
|
+
export type { AppSource, ExchangeContext, OAuthClient, OAuthProvider, RequestContext, TokenSet } from "./provider.js";
|
|
5
5
|
export { requestTokens, revokeToken, TOKEN_LOG_ALLOW, TOKEN_LOG_EVENT } from "./requests.js";
|
|
6
6
|
export { type CredentialStorageOptions, credentialStorage, driveSessionCodec, type EncodeInput, oauthAccount, type StoredTokens, standardCodec, type TokenCodec, type TokenStorage, zoomTokenCodec, } from "./storage.js";
|
package/dist/oauth/provider.d.ts
CHANGED
|
@@ -3,7 +3,12 @@ import type { Logger } from "@wirecat/cli-base";
|
|
|
3
3
|
export interface OAuthClient {
|
|
4
4
|
clientId: string;
|
|
5
5
|
clientSecret?: string;
|
|
6
|
+
/** Where the sign-in found the app (WC-SECR-25); saved with the entry, so `doctor` reports the app it used. */
|
|
7
|
+
source?: AppSource;
|
|
6
8
|
}
|
|
9
|
+
/** `flag`: `--client-file` or `--client-id`; `env`: `<TOOL>_<PROVIDER>_CLIENT_ID`; `config`: the account's
|
|
10
|
+
* `<provider>.client_id`; `constants`: WireCat's app. */
|
|
11
|
+
export type AppSource = "flag" | "env" | "config" | "constants";
|
|
7
12
|
export interface TokenSet {
|
|
8
13
|
accessToken?: string;
|
|
9
14
|
refreshToken: string;
|
package/dist/oauth/storage.js
CHANGED
|
@@ -40,8 +40,9 @@ export const standardCodec = (providerId) => ({
|
|
|
40
40
|
throw invalid();
|
|
41
41
|
if (!Array.isArray(value.scopes) || !value.scopes.every((scope) => typeof scope === "string"))
|
|
42
42
|
throw invalid();
|
|
43
|
+
const source = text(value.clientSource);
|
|
43
44
|
return {
|
|
44
|
-
client: { clientId },
|
|
45
|
+
client: defined({ clientId, clientSecret: text(value.clientSecret), source }),
|
|
45
46
|
tokens: defined({
|
|
46
47
|
accessToken: text(value.accessToken),
|
|
47
48
|
refreshToken,
|
|
@@ -57,6 +58,10 @@ export const standardCodec = (providerId) => ({
|
|
|
57
58
|
version: 1,
|
|
58
59
|
provider: providerId,
|
|
59
60
|
clientId: client.clientId,
|
|
61
|
+
// Only WireCat's secret, which is public: a later release may ship another default app, and a refresh needs
|
|
62
|
+
// the secret of the app that signed in. An owner's own secret stays where the owner keeps it.
|
|
63
|
+
clientSecret: client.source === "constants" ? client.clientSecret : undefined,
|
|
64
|
+
clientSource: client.source,
|
|
60
65
|
accessToken: tokens.accessToken,
|
|
61
66
|
refreshToken: tokens.refreshToken,
|
|
62
67
|
expiresAt: tokens.expiresAt,
|
|
@@ -80,7 +85,11 @@ export const driveSessionCodec = {
|
|
|
80
85
|
if (!refreshToken || !clientId || typeof value.principal !== "string")
|
|
81
86
|
throw invalid();
|
|
82
87
|
return {
|
|
83
|
-
client: defined({
|
|
88
|
+
client: defined({
|
|
89
|
+
clientId,
|
|
90
|
+
clientSecret: text(value.clientSecret),
|
|
91
|
+
source: text(value.clientSource),
|
|
92
|
+
}),
|
|
84
93
|
tokens: defined({
|
|
85
94
|
accessToken: text(fields.access_token),
|
|
86
95
|
refreshToken,
|
|
@@ -98,6 +107,7 @@ export const driveSessionCodec = {
|
|
|
98
107
|
...extra,
|
|
99
108
|
clientId: client.clientId,
|
|
100
109
|
...(client.clientSecret ? { clientSecret: client.clientSecret } : {}),
|
|
110
|
+
...(client.source ? { clientSource: client.source } : {}),
|
|
101
111
|
tokens: defined({
|
|
102
112
|
...oldTokens,
|
|
103
113
|
access_token: tokens.accessToken,
|
|
@@ -27,7 +27,7 @@ export declare const metadataService: (deps: ServiceDeps) => {
|
|
|
27
27
|
source?: undefined;
|
|
28
28
|
chatId: string;
|
|
29
29
|
error: {
|
|
30
|
-
code: "authentication_error" | "cancelled" | "configuration_error" | "confirmation_required" | "invalid_response" | "network_error" | "not_found" | "outcome_unknown" | "permission_error" | "provider_error" | "provider_unavailable" | "rate_limited" | "timeout" | "validation_error";
|
|
30
|
+
code: "authentication_error" | "cancelled" | "configuration_error" | "confirmation_required" | "conflict" | "invalid_response" | "network_error" | "not_found" | "outcome_unknown" | "permission_error" | "provider_error" | "provider_unavailable" | "rate_limited" | "timeout" | "validation_error";
|
|
31
31
|
message: string;
|
|
32
32
|
};
|
|
33
33
|
})[];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wirecat/cli-core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.566.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",
|
|
@@ -19,6 +19,7 @@
|
|
|
19
19
|
"packageManager": "pnpm@11.28.8",
|
|
20
20
|
"files": [
|
|
21
21
|
"dist",
|
|
22
|
+
"constants.json",
|
|
22
23
|
"parity.json",
|
|
23
24
|
"skills",
|
|
24
25
|
"README.md",
|
|
@@ -166,6 +167,10 @@
|
|
|
166
167
|
"./oauth": {
|
|
167
168
|
"types": "./dist/oauth/index.d.ts",
|
|
168
169
|
"default": "./dist/oauth/index.js"
|
|
170
|
+
},
|
|
171
|
+
"./constants": {
|
|
172
|
+
"types": "./dist/constants/index.d.ts",
|
|
173
|
+
"default": "./dist/constants/index.js"
|
|
169
174
|
}
|
|
170
175
|
},
|
|
171
176
|
"scripts": {
|
|
@@ -253,7 +258,7 @@
|
|
|
253
258
|
"@types/node": "^22.20.5",
|
|
254
259
|
"@types/pngjs": "6.0.5",
|
|
255
260
|
"@vitest/coverage-v8": "^5.0.5",
|
|
256
|
-
"@wirecat/cli-base": "0.
|
|
261
|
+
"@wirecat/cli-base": "0.77.1",
|
|
257
262
|
"@wirecat/cli-core-legacy-tags": "npm:@wirecat/cli-core@0.414.0",
|
|
258
263
|
"commander": "15.0.0",
|
|
259
264
|
"cspell": "10.4.0",
|
|
@@ -273,7 +278,7 @@
|
|
|
273
278
|
},
|
|
274
279
|
"peerDependencies": {
|
|
275
280
|
"@napi-rs/canvas": ">=0.1.69 <2",
|
|
276
|
-
"@wirecat/cli-base": ">=0.
|
|
281
|
+
"@wirecat/cli-base": ">=0.76.0 <0.78.0",
|
|
277
282
|
"commander": ">=15"
|
|
278
283
|
},
|
|
279
284
|
"bin": {
|