aipctl 2026.9.4 → 2026.9.5
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/build/index.cjs +114 -18
- package/package.json +3 -3
package/build/index.cjs
CHANGED
|
@@ -778,7 +778,7 @@ const isIterable = input => typeof input === "string" || hasProperty(input, Symb
|
|
|
778
778
|
* @since 2.0.0
|
|
779
779
|
* @see isObject
|
|
780
780
|
*/
|
|
781
|
-
const isRecord$
|
|
781
|
+
const isRecord$3 = input => isRecordOrArray(input) && !Array.isArray(input);
|
|
782
782
|
/**
|
|
783
783
|
* A refinement that checks if a value is `PromiseLike`. It performs a duck-typing
|
|
784
784
|
* check for a `.then` method.
|
|
@@ -25158,7 +25158,7 @@ const go = (ast, isDecoding) => {
|
|
|
25158
25158
|
const concurrency = getConcurrency(ast);
|
|
25159
25159
|
const batching = getBatching(ast);
|
|
25160
25160
|
return (input, options) => {
|
|
25161
|
-
if (!isRecord$
|
|
25161
|
+
if (!isRecord$3(input)) {
|
|
25162
25162
|
return left(new Type(ast, input));
|
|
25163
25163
|
}
|
|
25164
25164
|
const allErrors = options?.errors === "all";
|
|
@@ -89670,7 +89670,7 @@ const injectedBuildEnv = "dev".length > 0 ? "dev" : "local";
|
|
|
89670
89670
|
if (!isBuildEnv(injectedBuildEnv)) {
|
|
89671
89671
|
throw new Error(`Invalid AIPCTL_BUILD_ENV: ${injectedBuildEnv}`);
|
|
89672
89672
|
}
|
|
89673
|
-
const VERSION = "2026.9.
|
|
89673
|
+
const VERSION = "2026.9.5".length > 0 ? "2026.9.5" : "0.0.0";
|
|
89674
89674
|
const BUILD_ENV = injectedBuildEnv;
|
|
89675
89675
|
const INCLUDE_NATIVE_LOGS = BUILD_ENV !== "prod";
|
|
89676
89676
|
|
|
@@ -89812,10 +89812,18 @@ const implementedCommandOperationIds = /* @__PURE__ */ new Set([
|
|
|
89812
89812
|
"listCliModelExecModels",
|
|
89813
89813
|
"createCliModelChatExecution"
|
|
89814
89814
|
]);
|
|
89815
|
+
const releaseEnabledCommandOperationIds = /* @__PURE__ */ new Set([
|
|
89816
|
+
"getCliMe",
|
|
89817
|
+
"getCliUserSettings",
|
|
89818
|
+
"listCliOrganizations",
|
|
89819
|
+
"getCliOrganizationCapabilities",
|
|
89820
|
+
"listCliOrganizationMembers",
|
|
89821
|
+
"listCliModelExecModels"
|
|
89822
|
+
]);
|
|
89815
89823
|
const direct = (commands, operation) => commands.map((command) => ({
|
|
89816
89824
|
command,
|
|
89817
89825
|
tier: "GA_DIRECT",
|
|
89818
|
-
availability: implementedCommandOperationIds.has(operation.operationId ?? "") ? "IMPLEMENTED" : "
|
|
89826
|
+
availability: !implementedCommandOperationIds.has(operation.operationId ?? "") ? "PLANNED" : releaseEnabledCommandOperationIds.has(operation.operationId ?? "") ? "IMPLEMENTED" : "GATED",
|
|
89819
89827
|
...operation
|
|
89820
89828
|
}));
|
|
89821
89829
|
const candidate = (commands, owner, authBoundary, requiredGates) => commands.map((command) => ({
|
|
@@ -90554,6 +90562,7 @@ const CUSTOMER_AVAILABILITIES = /* @__PURE__ */ new Set([
|
|
|
90554
90562
|
"AVAILABLE"
|
|
90555
90563
|
]);
|
|
90556
90564
|
const isCustomerAvailable = (entry) => CUSTOMER_AVAILABILITIES.has(entry.availability);
|
|
90565
|
+
const normalizeCliArgCase = (arg) => arg.toLowerCase();
|
|
90557
90566
|
const commandSegments = (command) => command.split(" ");
|
|
90558
90567
|
const PROD_DISABLED_BUILT_INS = /* @__PURE__ */ new Set(["--completions", "--wizard"]);
|
|
90559
90568
|
const isCommandPrefix = (entry, args) => {
|
|
@@ -90579,11 +90588,12 @@ const getUnavailableCommandMessage = (args, buildEnv) => {
|
|
|
90579
90588
|
if (buildEnv !== "prod" || args.length === 0) {
|
|
90580
90589
|
return null;
|
|
90581
90590
|
}
|
|
90582
|
-
const
|
|
90591
|
+
const normalizedArgs = args.map(normalizeCliArgCase);
|
|
90592
|
+
const disabledBuiltIn = normalizedArgs.find((arg) => PROD_DISABLED_BUILT_INS.has(arg));
|
|
90583
90593
|
if (disabledBuiltIn) {
|
|
90584
90594
|
return formatUnavailableOptionMessage(disabledBuiltIn);
|
|
90585
90595
|
}
|
|
90586
|
-
const commandArgs = commandArgsForAvailability(
|
|
90596
|
+
const commandArgs = commandArgsForAvailability(normalizedArgs);
|
|
90587
90597
|
const entry = commandManifest.filter((candidate) => isCommandPrefix(candidate, commandArgs)).sort((left, right) => commandSegments(right.command).length - commandSegments(left.command).length).at(0);
|
|
90588
90598
|
if (entry) {
|
|
90589
90599
|
return isCustomerAvailable(entry) ? null : formatUnavailableMessage(entry.command);
|
|
@@ -90622,14 +90632,14 @@ class InvalidAppUrlError extends Error {
|
|
|
90622
90632
|
this.rawValue = rawValue;
|
|
90623
90633
|
}
|
|
90624
90634
|
}
|
|
90625
|
-
function isRecord$
|
|
90635
|
+
function isRecord$2(value) {
|
|
90626
90636
|
return typeof value === "object" && value !== null;
|
|
90627
90637
|
}
|
|
90628
90638
|
function optionalString$1(value) {
|
|
90629
90639
|
return typeof value === "string" ? value : void 0;
|
|
90630
90640
|
}
|
|
90631
90641
|
function parseCurrentOrganization(value) {
|
|
90632
|
-
if (!isRecord$
|
|
90642
|
+
if (!isRecord$2(value)) {
|
|
90633
90643
|
return void 0;
|
|
90634
90644
|
}
|
|
90635
90645
|
const id = optionalString$1(value["id"]);
|
|
@@ -90641,7 +90651,7 @@ function parseCurrentOrganization(value) {
|
|
|
90641
90651
|
return { id, slug, name };
|
|
90642
90652
|
}
|
|
90643
90653
|
function normalizeLoadedConfig(value) {
|
|
90644
|
-
if (!isRecord$
|
|
90654
|
+
if (!isRecord$2(value)) {
|
|
90645
90655
|
return {};
|
|
90646
90656
|
}
|
|
90647
90657
|
return {
|
|
@@ -92875,11 +92885,11 @@ const CREDENTIALS_FILE = path__namespace.join(CONFIG_DIR$1, "credentials.json");
|
|
|
92875
92885
|
const CREDENTIALS_LOCK_FILE = path__namespace.join(CONFIG_DIR$1, "credentials.lock");
|
|
92876
92886
|
class CredentialServiceTag extends Tag$1("CredentialService")() {
|
|
92877
92887
|
}
|
|
92878
|
-
function isNonEmptyString(value) {
|
|
92888
|
+
function isNonEmptyString$1(value) {
|
|
92879
92889
|
return typeof value === "string" && value.length > 0;
|
|
92880
92890
|
}
|
|
92881
92891
|
function hasOAuthClient(credentials) {
|
|
92882
|
-
return isNonEmptyString(credentials?.clientId);
|
|
92892
|
+
return isNonEmptyString$1(credentials?.clientId);
|
|
92883
92893
|
}
|
|
92884
92894
|
function isAccessTokenExpired(credentials, bufferMs = 0, now = Date.now()) {
|
|
92885
92895
|
if (!credentials?.expiresAt) {
|
|
@@ -92888,13 +92898,13 @@ function isAccessTokenExpired(credentials, bufferMs = 0, now = Date.now()) {
|
|
|
92888
92898
|
return credentials.expiresAt - bufferMs <= now;
|
|
92889
92899
|
}
|
|
92890
92900
|
function hasValidRefreshToken(credentials, now) {
|
|
92891
|
-
return isNonEmptyString(credentials.refreshToken) && (credentials.refreshExpiresAt === void 0 || credentials.refreshExpiresAt > now);
|
|
92901
|
+
return isNonEmptyString$1(credentials.refreshToken) && (credentials.refreshExpiresAt === void 0 || credentials.refreshExpiresAt > now);
|
|
92892
92902
|
}
|
|
92893
92903
|
function getCredentialAuthStatus(credentials, now = Date.now(), options = {}) {
|
|
92894
92904
|
if (!hasOAuthClient(credentials)) {
|
|
92895
92905
|
return "missing";
|
|
92896
92906
|
}
|
|
92897
|
-
const needsAccessRefresh = options.forceRefresh || !isNonEmptyString(credentials.accessToken) || isAccessTokenExpired(credentials, options.accessExpiryBufferMs ?? 0, now);
|
|
92907
|
+
const needsAccessRefresh = options.forceRefresh || !isNonEmptyString$1(credentials.accessToken) || isAccessTokenExpired(credentials, options.accessExpiryBufferMs ?? 0, now);
|
|
92898
92908
|
if (!needsAccessRefresh) {
|
|
92899
92909
|
return "authenticated";
|
|
92900
92910
|
}
|
|
@@ -93890,7 +93900,7 @@ function trimTrailingSlash(value) {
|
|
|
93890
93900
|
function toError$1(error, fallbackMessage) {
|
|
93891
93901
|
return error instanceof Error ? new Error(maskSensitiveText(error.message)) : new Error(maskSensitiveText(fallbackMessage));
|
|
93892
93902
|
}
|
|
93893
|
-
function isRecord(value) {
|
|
93903
|
+
function isRecord$1(value) {
|
|
93894
93904
|
return typeof value === "object" && value !== null;
|
|
93895
93905
|
}
|
|
93896
93906
|
function optionalString(value) {
|
|
@@ -93900,7 +93910,7 @@ function optionalNumber(value) {
|
|
|
93900
93910
|
return typeof value === "number" && Number.isFinite(value) ? value : void 0;
|
|
93901
93911
|
}
|
|
93902
93912
|
function parseOAuthTokenResponse(value) {
|
|
93903
|
-
if (!isRecord(value)) {
|
|
93913
|
+
if (!isRecord$1(value)) {
|
|
93904
93914
|
throw new OAuthRequestError("OAuth token response was not a JSON object", void 0, "invalid_token_response");
|
|
93905
93915
|
}
|
|
93906
93916
|
const accessToken = optionalString(value["access_token"]);
|
|
@@ -94429,6 +94439,55 @@ async function acquire() {
|
|
|
94429
94439
|
}
|
|
94430
94440
|
}
|
|
94431
94441
|
|
|
94442
|
+
const SERVER_CAPABILITY_SCHEMA_VERSION = 1;
|
|
94443
|
+
class ServerCapabilityError extends Error {
|
|
94444
|
+
code;
|
|
94445
|
+
constructor(code, message) {
|
|
94446
|
+
super(message);
|
|
94447
|
+
this.name = "ServerCapabilityError";
|
|
94448
|
+
this.code = code;
|
|
94449
|
+
}
|
|
94450
|
+
}
|
|
94451
|
+
function parseEnabledServerOperations(value) {
|
|
94452
|
+
if (!isRecord(value) || value["schemaVersion"] !== SERVER_CAPABILITY_SCHEMA_VERSION) {
|
|
94453
|
+
throw new ServerCapabilityError(
|
|
94454
|
+
"CLI_CAPABILITIES_INCOMPATIBLE",
|
|
94455
|
+
"The server returned an unsupported CLI capability schema."
|
|
94456
|
+
);
|
|
94457
|
+
}
|
|
94458
|
+
const enabledOperations = value["enabledOperations"];
|
|
94459
|
+
if (!Array.isArray(enabledOperations)) {
|
|
94460
|
+
throw new ServerCapabilityError(
|
|
94461
|
+
"CLI_CAPABILITIES_INCOMPATIBLE",
|
|
94462
|
+
"The server returned an invalid CLI capability operation list."
|
|
94463
|
+
);
|
|
94464
|
+
}
|
|
94465
|
+
const operationIds = /* @__PURE__ */ new Set();
|
|
94466
|
+
for (const operation of enabledOperations) {
|
|
94467
|
+
if (!isRecord(operation) || !isNonEmptyString(operation["operationId"]) || !isNonEmptyString(operation["capability"]) || operationIds.has(operation["operationId"])) {
|
|
94468
|
+
throw new ServerCapabilityError(
|
|
94469
|
+
"CLI_CAPABILITIES_INCOMPATIBLE",
|
|
94470
|
+
"The server returned an invalid CLI capability operation."
|
|
94471
|
+
);
|
|
94472
|
+
}
|
|
94473
|
+
operationIds.add(operation["operationId"]);
|
|
94474
|
+
}
|
|
94475
|
+
return operationIds;
|
|
94476
|
+
}
|
|
94477
|
+
function requireEnabledServerOperation(enabledOperations, operationId) {
|
|
94478
|
+
if (enabledOperations.has(operationId)) return;
|
|
94479
|
+
throw new ServerCapabilityError(
|
|
94480
|
+
"CLI_OPERATION_NOT_ENABLED",
|
|
94481
|
+
`CLI operation "${operationId}" is not enabled by the server.`
|
|
94482
|
+
);
|
|
94483
|
+
}
|
|
94484
|
+
function isRecord(value) {
|
|
94485
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
94486
|
+
}
|
|
94487
|
+
function isNonEmptyString(value) {
|
|
94488
|
+
return typeof value === "string" && value.length > 0;
|
|
94489
|
+
}
|
|
94490
|
+
|
|
94432
94491
|
class ApiError extends TaggedError$1("ApiError") {
|
|
94433
94492
|
}
|
|
94434
94493
|
class NotLoggedInError extends TaggedError$1("NotLoggedInError") {
|
|
@@ -94735,7 +94794,7 @@ const parseSseStream = async (body) => {
|
|
|
94735
94794
|
}
|
|
94736
94795
|
throw new AgentChatStreamIncompleteError(hasDataEvent && sawOnlyTerminalEnvelope);
|
|
94737
94796
|
};
|
|
94738
|
-
const
|
|
94797
|
+
const makeApiServiceLive = (buildEnv) => effect$1(
|
|
94739
94798
|
ApiServiceTag,
|
|
94740
94799
|
gen(function* () {
|
|
94741
94800
|
const configService = yield* ConfigService;
|
|
@@ -94852,6 +94911,34 @@ const ApiServiceLive = effect$1(
|
|
|
94852
94911
|
});
|
|
94853
94912
|
const baseUrl = () => loadConfiguredApiBaseUrl();
|
|
94854
94913
|
const chatBaseUrl = () => loadConfiguredChatBaseUrl();
|
|
94914
|
+
const requireServerOperation = (operationId, token) => {
|
|
94915
|
+
if (buildEnv !== "prod") return _void;
|
|
94916
|
+
if (!releaseEnabledCommandOperationIds.has(operationId)) {
|
|
94917
|
+
return fail$3(createApiError({
|
|
94918
|
+
message: `CLI operation "${operationId}" is not enabled in this aipctl release.`,
|
|
94919
|
+
statusCode: 404,
|
|
94920
|
+
code: "CLI_OPERATION_NOT_ENABLED"
|
|
94921
|
+
}));
|
|
94922
|
+
}
|
|
94923
|
+
return gen(function* () {
|
|
94924
|
+
const response = yield* makeRequest(
|
|
94925
|
+
baseUrl,
|
|
94926
|
+
"/api/cli/v1/capabilities",
|
|
94927
|
+
token
|
|
94928
|
+
);
|
|
94929
|
+
yield* try_({
|
|
94930
|
+
try: () => {
|
|
94931
|
+
const enabledOperations = parseEnabledServerOperations(response);
|
|
94932
|
+
requireEnabledServerOperation(enabledOperations, operationId);
|
|
94933
|
+
},
|
|
94934
|
+
catch: (error) => createApiError({
|
|
94935
|
+
message: error instanceof Error ? error.message : "CLI server capability validation failed",
|
|
94936
|
+
statusCode: error instanceof ServerCapabilityError && error.code === "CLI_OPERATION_NOT_ENABLED" ? 404 : 503,
|
|
94937
|
+
code: error instanceof ServerCapabilityError ? error.code : "CLI_CAPABILITIES_INCOMPATIBLE"
|
|
94938
|
+
})
|
|
94939
|
+
});
|
|
94940
|
+
});
|
|
94941
|
+
};
|
|
94855
94942
|
const subscribeAgentChatStream = (orgSlug, conversationId, token) => gen(function* () {
|
|
94856
94943
|
const resolvedChatBaseUrl = yield* requireChatBaseUrlEffect();
|
|
94857
94944
|
const path = `/api/${encodeURIComponent(orgSlug)}/conversations/${encodeURIComponent(conversationId)}/stream`;
|
|
@@ -94918,10 +95005,12 @@ const ApiServiceLive = effect$1(
|
|
|
94918
95005
|
return {
|
|
94919
95006
|
listOrganizations: () => gen(function* () {
|
|
94920
95007
|
const token = yield* getAccessToken();
|
|
95008
|
+
yield* requireServerOperation("listCliOrganizations", token);
|
|
94921
95009
|
return yield* makeRequest(baseUrl, "/api/cli/v1/organizations", token);
|
|
94922
95010
|
}),
|
|
94923
95011
|
getOrganization: (slug) => gen(function* () {
|
|
94924
95012
|
const token = yield* getAccessToken();
|
|
95013
|
+
yield* requireServerOperation("listCliOrganizations", token);
|
|
94925
95014
|
const orgs = yield* makeRequest(baseUrl, "/api/cli/v1/organizations", token);
|
|
94926
95015
|
const org = orgs.find((o) => o.slug === slug);
|
|
94927
95016
|
if (!org) {
|
|
@@ -95261,6 +95350,7 @@ const ApiServiceLive = effect$1(
|
|
|
95261
95350
|
// Phase 4: Monitoring
|
|
95262
95351
|
listOrgMembers: (orgSlug) => gen(function* () {
|
|
95263
95352
|
const token = yield* getAccessToken();
|
|
95353
|
+
yield* requireServerOperation("listCliOrganizationMembers", token);
|
|
95264
95354
|
const path = `/api/cli/v1/organizations/${encodeURIComponent(orgSlug)}/members`;
|
|
95265
95355
|
const raw = yield* makeRequest(baseUrl, path, token);
|
|
95266
95356
|
return {
|
|
@@ -95286,12 +95376,14 @@ const ApiServiceLive = effect$1(
|
|
|
95286
95376
|
listModelExecModels: (orgSlug) => gen(function* () {
|
|
95287
95377
|
yield* requireChatBaseUrlEffect();
|
|
95288
95378
|
const token = yield* getAccessToken();
|
|
95379
|
+
yield* requireServerOperation("listCliModelExecModels", token);
|
|
95289
95380
|
const path = `/api/cli/v1/organizations/${encodeURIComponent(orgSlug)}/model-exec/models`;
|
|
95290
95381
|
return yield* makeRequest(chatBaseUrl, path, token);
|
|
95291
95382
|
}),
|
|
95292
95383
|
executeModelExecChat: (orgSlug, body) => gen(function* () {
|
|
95293
95384
|
yield* requireChatBaseUrlEffect();
|
|
95294
95385
|
const token = yield* getAccessToken();
|
|
95386
|
+
yield* requireServerOperation("createCliModelChatExecution", token);
|
|
95295
95387
|
const path = `/api/cli/v1/organizations/${encodeURIComponent(orgSlug)}/model-exec/chat`;
|
|
95296
95388
|
return yield* makeRequest(chatBaseUrl, path, token, {
|
|
95297
95389
|
method: "POST",
|
|
@@ -95433,6 +95525,7 @@ const ApiServiceLive = effect$1(
|
|
|
95433
95525
|
// Phase 6: Auth enhancements
|
|
95434
95526
|
getMe: () => gen(function* () {
|
|
95435
95527
|
const token = yield* getAccessToken();
|
|
95528
|
+
yield* requireServerOperation("getCliMe", token);
|
|
95436
95529
|
return yield* makeRequest(baseUrl, "/api/cli/v1/me", token);
|
|
95437
95530
|
}),
|
|
95438
95531
|
refreshToken: () => refreshAccessToken({ force: true }),
|
|
@@ -95614,11 +95707,13 @@ const ApiServiceLive = effect$1(
|
|
|
95614
95707
|
// Org capabilities & user settings
|
|
95615
95708
|
getOrgCapabilities: (orgSlug) => gen(function* () {
|
|
95616
95709
|
const token = yield* getAccessToken();
|
|
95710
|
+
yield* requireServerOperation("getCliOrganizationCapabilities", token);
|
|
95617
95711
|
const path = `/api/cli/v1/organizations/${encodeURIComponent(orgSlug)}/capabilities`;
|
|
95618
95712
|
return yield* makeRequest(baseUrl, path, token);
|
|
95619
95713
|
}),
|
|
95620
95714
|
getUserSettings: () => gen(function* () {
|
|
95621
95715
|
const token = yield* getAccessToken();
|
|
95716
|
+
yield* requireServerOperation("getCliUserSettings", token);
|
|
95622
95717
|
return yield* makeRequest(baseUrl, "/api/cli/v1/me/settings", token);
|
|
95623
95718
|
}),
|
|
95624
95719
|
// Tunnel management
|
|
@@ -95736,6 +95831,7 @@ const ApiServiceLive = effect$1(
|
|
|
95736
95831
|
};
|
|
95737
95832
|
})
|
|
95738
95833
|
);
|
|
95834
|
+
const ApiServiceLive = makeApiServiceLive(BUILD_ENV);
|
|
95739
95835
|
const ApiService = ApiServiceTag;
|
|
95740
95836
|
|
|
95741
95837
|
const orgOption = text("org").pipe(
|
|
@@ -101402,10 +101498,10 @@ const hasCustomerAvailableCommand = (path) => {
|
|
|
101402
101498
|
const formatCommandList = (path, subcommands, options) => subcommands.map((command) => [...path, getCommandName(command)]).filter((commandPath) => !options.customerOnly || hasCustomerAvailableCommand(commandPath)).map((commandPath) => ` - ${formatCanonicalPath(commandPath)}`).join("\n");
|
|
101403
101499
|
const getHelpPath = (args) => {
|
|
101404
101500
|
const lastArg = args.at(-1);
|
|
101405
|
-
if (!lastArg || !HELP_FLAGS$1.has(lastArg)) {
|
|
101501
|
+
if (!lastArg || !HELP_FLAGS$1.has(normalizeCliArgCase(lastArg))) {
|
|
101406
101502
|
return null;
|
|
101407
101503
|
}
|
|
101408
|
-
const path = args.slice(0, -1);
|
|
101504
|
+
const path = args.slice(0, -1).map(normalizeCliArgCase);
|
|
101409
101505
|
return path.every((segment) => !segment.startsWith("-")) ? path : null;
|
|
101410
101506
|
};
|
|
101411
101507
|
const renderGroupHelp = ({ path, description, subcommands }, options) => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "aipctl",
|
|
3
|
-
"version": "2026.9.
|
|
3
|
+
"version": "2026.9.5",
|
|
4
4
|
"description": "QueryPie AIP and MCP CLI tool",
|
|
5
5
|
"author": "QueryPie",
|
|
6
6
|
"license": "UNLICENSED",
|
|
@@ -22,8 +22,8 @@
|
|
|
22
22
|
"node": ">=24.18.0"
|
|
23
23
|
},
|
|
24
24
|
"metadata": {
|
|
25
|
-
"contentHash": "
|
|
26
|
-
"wrapperHash": "
|
|
25
|
+
"contentHash": "41009029ba4ff1bb3ad17157d8af3499f5545ddf860fb1ea4803005b6a6ca026",
|
|
26
|
+
"wrapperHash": "15330253c506008f0676946c51659e0dfc616d42e8931180f47080a03b966203",
|
|
27
27
|
"nativeHash": "006b08c3e391f4571d9b7c0f12d684fe2448106259e7e0581b10f9be362452e9"
|
|
28
28
|
},
|
|
29
29
|
"optionalDependencies": {
|