aipctl 2026.9.8 → 2026.9.10
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 +180 -135
- package/docs/api-contract-inventory.md +9 -6
- 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$2 = 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$2(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.10".length > 0 ? "2026.9.10" : "0.0.0";
|
|
89674
89674
|
const BUILD_ENV = injectedBuildEnv;
|
|
89675
89675
|
const INCLUDE_NATIVE_LOGS = BUILD_ENV !== "prod";
|
|
89676
89676
|
|
|
@@ -89819,7 +89819,25 @@ const implementedCommandOperationIds = /* @__PURE__ */ new Set([
|
|
|
89819
89819
|
"listCliOrganizationMembers",
|
|
89820
89820
|
"listCliModels",
|
|
89821
89821
|
"listCliModelExecModels",
|
|
89822
|
-
"createCliModelChatExecution"
|
|
89822
|
+
"createCliModelChatExecution",
|
|
89823
|
+
"listCliSkills",
|
|
89824
|
+
"getCliSkill",
|
|
89825
|
+
"deleteCliSkill",
|
|
89826
|
+
"listCliSkillLibrary",
|
|
89827
|
+
"createCliSkillClones",
|
|
89828
|
+
"listCliBuiltInSkills",
|
|
89829
|
+
"createCliBuiltInSkillClones",
|
|
89830
|
+
"listCliAdminSkills",
|
|
89831
|
+
"getCliAdminSkill",
|
|
89832
|
+
"deleteCliAdminSkill",
|
|
89833
|
+
"updateCliAdminSkill",
|
|
89834
|
+
"listCliAdminBuiltInSkills",
|
|
89835
|
+
"createCliAdminBuiltInSkillClones",
|
|
89836
|
+
"listCliDriveEntries",
|
|
89837
|
+
"getCliDriveUsage",
|
|
89838
|
+
"createCliDriveFolder",
|
|
89839
|
+
"updateCliDriveEntryName",
|
|
89840
|
+
"deleteCliDriveEntries"
|
|
89823
89841
|
]);
|
|
89824
89842
|
const releaseEnabledCommandOperationIds = /* @__PURE__ */ new Set([
|
|
89825
89843
|
"listCliAgents",
|
|
@@ -89836,7 +89854,25 @@ const releaseEnabledCommandOperationIds = /* @__PURE__ */ new Set([
|
|
|
89836
89854
|
"getCliOrganizationCapabilities",
|
|
89837
89855
|
"listCliOrganizationMembers",
|
|
89838
89856
|
"listCliModels",
|
|
89839
|
-
"listCliModelExecModels"
|
|
89857
|
+
"listCliModelExecModels",
|
|
89858
|
+
"listCliSkills",
|
|
89859
|
+
"getCliSkill",
|
|
89860
|
+
"deleteCliSkill",
|
|
89861
|
+
"listCliSkillLibrary",
|
|
89862
|
+
"createCliSkillClones",
|
|
89863
|
+
"listCliBuiltInSkills",
|
|
89864
|
+
"createCliBuiltInSkillClones",
|
|
89865
|
+
"listCliAdminSkills",
|
|
89866
|
+
"getCliAdminSkill",
|
|
89867
|
+
"deleteCliAdminSkill",
|
|
89868
|
+
"updateCliAdminSkill",
|
|
89869
|
+
"listCliAdminBuiltInSkills",
|
|
89870
|
+
"createCliAdminBuiltInSkillClones",
|
|
89871
|
+
"listCliDriveEntries",
|
|
89872
|
+
"getCliDriveUsage",
|
|
89873
|
+
"createCliDriveFolder",
|
|
89874
|
+
"updateCliDriveEntryName",
|
|
89875
|
+
"deleteCliDriveEntries"
|
|
89840
89876
|
]);
|
|
89841
89877
|
const direct = (commands, operation) => commands.map((command) => ({
|
|
89842
89878
|
command,
|
|
@@ -90650,14 +90686,14 @@ class InvalidAppUrlError extends Error {
|
|
|
90650
90686
|
this.rawValue = rawValue;
|
|
90651
90687
|
}
|
|
90652
90688
|
}
|
|
90653
|
-
function isRecord$
|
|
90689
|
+
function isRecord$1(value) {
|
|
90654
90690
|
return typeof value === "object" && value !== null;
|
|
90655
90691
|
}
|
|
90656
90692
|
function optionalString$1(value) {
|
|
90657
90693
|
return typeof value === "string" ? value : void 0;
|
|
90658
90694
|
}
|
|
90659
90695
|
function parseCurrentOrganization(value) {
|
|
90660
|
-
if (!isRecord$
|
|
90696
|
+
if (!isRecord$1(value)) {
|
|
90661
90697
|
return void 0;
|
|
90662
90698
|
}
|
|
90663
90699
|
const id = optionalString$1(value["id"]);
|
|
@@ -90669,7 +90705,7 @@ function parseCurrentOrganization(value) {
|
|
|
90669
90705
|
return { id, slug, name };
|
|
90670
90706
|
}
|
|
90671
90707
|
function normalizeLoadedConfig(value) {
|
|
90672
|
-
if (!isRecord$
|
|
90708
|
+
if (!isRecord$1(value)) {
|
|
90673
90709
|
return {};
|
|
90674
90710
|
}
|
|
90675
90711
|
return {
|
|
@@ -92903,11 +92939,11 @@ const CREDENTIALS_FILE = path__namespace.join(CONFIG_DIR$1, "credentials.json");
|
|
|
92903
92939
|
const CREDENTIALS_LOCK_FILE = path__namespace.join(CONFIG_DIR$1, "credentials.lock");
|
|
92904
92940
|
class CredentialServiceTag extends Tag$1("CredentialService")() {
|
|
92905
92941
|
}
|
|
92906
|
-
function isNonEmptyString
|
|
92942
|
+
function isNonEmptyString(value) {
|
|
92907
92943
|
return typeof value === "string" && value.length > 0;
|
|
92908
92944
|
}
|
|
92909
92945
|
function hasOAuthClient(credentials) {
|
|
92910
|
-
return isNonEmptyString
|
|
92946
|
+
return isNonEmptyString(credentials?.clientId);
|
|
92911
92947
|
}
|
|
92912
92948
|
function isAccessTokenExpired(credentials, bufferMs = 0, now = Date.now()) {
|
|
92913
92949
|
if (!credentials?.expiresAt) {
|
|
@@ -92916,13 +92952,13 @@ function isAccessTokenExpired(credentials, bufferMs = 0, now = Date.now()) {
|
|
|
92916
92952
|
return credentials.expiresAt - bufferMs <= now;
|
|
92917
92953
|
}
|
|
92918
92954
|
function hasValidRefreshToken(credentials, now) {
|
|
92919
|
-
return isNonEmptyString
|
|
92955
|
+
return isNonEmptyString(credentials.refreshToken) && (credentials.refreshExpiresAt === void 0 || credentials.refreshExpiresAt > now);
|
|
92920
92956
|
}
|
|
92921
92957
|
function getCredentialAuthStatus(credentials, now = Date.now(), options = {}) {
|
|
92922
92958
|
if (!hasOAuthClient(credentials)) {
|
|
92923
92959
|
return "missing";
|
|
92924
92960
|
}
|
|
92925
|
-
const needsAccessRefresh = options.forceRefresh || !isNonEmptyString
|
|
92961
|
+
const needsAccessRefresh = options.forceRefresh || !isNonEmptyString(credentials.accessToken) || isAccessTokenExpired(credentials, options.accessExpiryBufferMs ?? 0, now);
|
|
92926
92962
|
if (!needsAccessRefresh) {
|
|
92927
92963
|
return "authenticated";
|
|
92928
92964
|
}
|
|
@@ -93918,7 +93954,7 @@ function trimTrailingSlash(value) {
|
|
|
93918
93954
|
function toError$1(error, fallbackMessage) {
|
|
93919
93955
|
return error instanceof Error ? new Error(maskSensitiveText(error.message)) : new Error(maskSensitiveText(fallbackMessage));
|
|
93920
93956
|
}
|
|
93921
|
-
function isRecord
|
|
93957
|
+
function isRecord(value) {
|
|
93922
93958
|
return typeof value === "object" && value !== null;
|
|
93923
93959
|
}
|
|
93924
93960
|
function optionalString(value) {
|
|
@@ -93928,7 +93964,7 @@ function optionalNumber(value) {
|
|
|
93928
93964
|
return typeof value === "number" && Number.isFinite(value) ? value : void 0;
|
|
93929
93965
|
}
|
|
93930
93966
|
function parseOAuthTokenResponse(value) {
|
|
93931
|
-
if (!isRecord
|
|
93967
|
+
if (!isRecord(value)) {
|
|
93932
93968
|
throw new OAuthRequestError("OAuth token response was not a JSON object", void 0, "invalid_token_response");
|
|
93933
93969
|
}
|
|
93934
93970
|
const accessToken = optionalString(value["access_token"]);
|
|
@@ -94457,55 +94493,6 @@ async function acquire() {
|
|
|
94457
94493
|
}
|
|
94458
94494
|
}
|
|
94459
94495
|
|
|
94460
|
-
const SERVER_CAPABILITY_SCHEMA_VERSION = 1;
|
|
94461
|
-
class ServerCapabilityError extends Error {
|
|
94462
|
-
code;
|
|
94463
|
-
constructor(code, message) {
|
|
94464
|
-
super(message);
|
|
94465
|
-
this.name = "ServerCapabilityError";
|
|
94466
|
-
this.code = code;
|
|
94467
|
-
}
|
|
94468
|
-
}
|
|
94469
|
-
function parseEnabledServerOperations(value) {
|
|
94470
|
-
if (!isRecord(value) || value["schemaVersion"] !== SERVER_CAPABILITY_SCHEMA_VERSION) {
|
|
94471
|
-
throw new ServerCapabilityError(
|
|
94472
|
-
"CLI_CAPABILITIES_INCOMPATIBLE",
|
|
94473
|
-
"The server returned an unsupported CLI capability schema."
|
|
94474
|
-
);
|
|
94475
|
-
}
|
|
94476
|
-
const enabledOperations = value["enabledOperations"];
|
|
94477
|
-
if (!Array.isArray(enabledOperations)) {
|
|
94478
|
-
throw new ServerCapabilityError(
|
|
94479
|
-
"CLI_CAPABILITIES_INCOMPATIBLE",
|
|
94480
|
-
"The server returned an invalid CLI capability operation list."
|
|
94481
|
-
);
|
|
94482
|
-
}
|
|
94483
|
-
const operationIds = /* @__PURE__ */ new Set();
|
|
94484
|
-
for (const operation of enabledOperations) {
|
|
94485
|
-
if (!isRecord(operation) || !isNonEmptyString(operation["operationId"]) || !isNonEmptyString(operation["capability"]) || operationIds.has(operation["operationId"])) {
|
|
94486
|
-
throw new ServerCapabilityError(
|
|
94487
|
-
"CLI_CAPABILITIES_INCOMPATIBLE",
|
|
94488
|
-
"The server returned an invalid CLI capability operation."
|
|
94489
|
-
);
|
|
94490
|
-
}
|
|
94491
|
-
operationIds.add(operation["operationId"]);
|
|
94492
|
-
}
|
|
94493
|
-
return operationIds;
|
|
94494
|
-
}
|
|
94495
|
-
function requireEnabledServerOperation(enabledOperations, operationId) {
|
|
94496
|
-
if (enabledOperations.has(operationId)) return;
|
|
94497
|
-
throw new ServerCapabilityError(
|
|
94498
|
-
"CLI_OPERATION_NOT_ENABLED",
|
|
94499
|
-
`CLI operation "${operationId}" is not enabled by the server.`
|
|
94500
|
-
);
|
|
94501
|
-
}
|
|
94502
|
-
function isRecord(value) {
|
|
94503
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
94504
|
-
}
|
|
94505
|
-
function isNonEmptyString(value) {
|
|
94506
|
-
return typeof value === "string" && value.length > 0;
|
|
94507
|
-
}
|
|
94508
|
-
|
|
94509
94496
|
class ApiError extends TaggedError$1("ApiError") {
|
|
94510
94497
|
}
|
|
94511
94498
|
class NotLoggedInError extends TaggedError$1("NotLoggedInError") {
|
|
@@ -94670,26 +94657,31 @@ async function toApiError(response) {
|
|
|
94670
94657
|
errorData = await response.json();
|
|
94671
94658
|
} catch {
|
|
94672
94659
|
}
|
|
94673
|
-
const
|
|
94674
|
-
const
|
|
94660
|
+
const code = errorData.code ?? errorData.errorCode;
|
|
94661
|
+
const details = isCliQuotaErrorCode(code) ? parseCliQuotaErrorDetails(errorData.details, code) : void 0;
|
|
94662
|
+
const retryAfterSeconds = details ? details.limitKind === "concurrent" ? void 0 : details.retryAfterSeconds ?? parseRetryAfterSeconds(response.headers.get("retry-after")) : void 0;
|
|
94675
94663
|
return createApiError({
|
|
94676
94664
|
message: errorData.message || `HTTP ${response.status}: ${response.statusText}`,
|
|
94677
94665
|
statusCode: response.status,
|
|
94678
|
-
code
|
|
94666
|
+
code,
|
|
94679
94667
|
...details ? { details } : {},
|
|
94680
94668
|
...retryAfterSeconds === void 0 ? {} : { retryAfterSeconds }
|
|
94681
94669
|
});
|
|
94682
94670
|
}
|
|
94683
94671
|
function isCliQuotaErrorCode(code) {
|
|
94684
|
-
return code === "CLI_QUOTA_EXCEEDED" || code === "CLI_QUOTA_POLICY_UNAVAILABLE" || code === "CLI_QUOTA_LIMITER_UNAVAILABLE";
|
|
94672
|
+
return code === "CLI_QUOTA_EXCEEDED" || code === "CLI_QUOTA_POLICY_UNAVAILABLE" || code === "CLI_QUOTA_LIMITER_UNAVAILABLE" || code === "CLI_TEXT_DAILY_LIMIT" || code === "CLI_TEXT_USER_CONCURRENCY_LIMIT" || code === "CLI_TEXT_ORGANIZATION_CONCURRENCY_LIMIT";
|
|
94673
|
+
}
|
|
94674
|
+
function isCliTextQuotaErrorCode(code) {
|
|
94675
|
+
return code === "CLI_TEXT_DAILY_LIMIT" || code === "CLI_TEXT_USER_CONCURRENCY_LIMIT" || code === "CLI_TEXT_ORGANIZATION_CONCURRENCY_LIMIT";
|
|
94685
94676
|
}
|
|
94686
|
-
function parseCliQuotaErrorDetails(value) {
|
|
94677
|
+
function parseCliQuotaErrorDetails(value, code) {
|
|
94687
94678
|
if (typeof value !== "object" || value === null || Array.isArray(value)) return void 0;
|
|
94688
94679
|
const details = value;
|
|
94689
|
-
|
|
94690
|
-
|
|
94691
|
-
|
|
94692
|
-
|
|
94680
|
+
const sourceLimitKind = details["limitKind"];
|
|
94681
|
+
const limitKind = sourceLimitKind === "request_rate" ? "request_rate" : sourceLimitKind === "dailyTextAdmissions" ? "daily" : sourceLimitKind === "concurrentTextExecutions" ? "concurrent" : void 0;
|
|
94682
|
+
if (!limitKind) return void 0;
|
|
94683
|
+
const quotaClass = details["quotaClass"] ?? (isCliTextQuotaErrorCode(code) ? "text-execution" : void 0);
|
|
94684
|
+
if (typeof quotaClass !== "string" || !["bootstrap", "metadata", "text-execution", "control-read"].includes(quotaClass)) return void 0;
|
|
94693
94685
|
if (typeof details["requestId"] !== "string" || details["requestId"].length === 0) return void 0;
|
|
94694
94686
|
const scope = details["scope"];
|
|
94695
94687
|
if (scope !== void 0 && (typeof scope !== "string" || !["user", "organization", "bootstrap", "control-read"].includes(scope))) {
|
|
@@ -94699,17 +94691,42 @@ function parseCliQuotaErrorDetails(value) {
|
|
|
94699
94691
|
if (resetAt !== void 0 && (typeof resetAt !== "string" || !Number.isFinite(Date.parse(resetAt)))) {
|
|
94700
94692
|
return void 0;
|
|
94701
94693
|
}
|
|
94694
|
+
const retryAfterSeconds = details["retryAfterSeconds"];
|
|
94695
|
+
if (retryAfterSeconds !== void 0 && (typeof retryAfterSeconds !== "number" || !Number.isSafeInteger(retryAfterSeconds) || retryAfterSeconds < 0)) {
|
|
94696
|
+
return void 0;
|
|
94697
|
+
}
|
|
94702
94698
|
const dependency = details["dependency"];
|
|
94703
94699
|
if (dependency !== void 0 && dependency !== "policy" && dependency !== "limiter") return void 0;
|
|
94700
|
+
if (!isCliQuotaCombinationValid(code, limitKind, quotaClass, scope, dependency)) return void 0;
|
|
94704
94701
|
return {
|
|
94705
|
-
limitKind
|
|
94706
|
-
quotaClass
|
|
94702
|
+
limitKind,
|
|
94703
|
+
quotaClass,
|
|
94707
94704
|
requestId: details["requestId"],
|
|
94708
94705
|
...scope === void 0 ? {} : { scope },
|
|
94709
|
-
...resetAt === void 0 ? {} : { resetAt },
|
|
94706
|
+
...resetAt === void 0 || limitKind === "concurrent" ? {} : { resetAt },
|
|
94707
|
+
...retryAfterSeconds === void 0 || limitKind === "concurrent" ? {} : { retryAfterSeconds },
|
|
94710
94708
|
...dependency === void 0 ? {} : { dependency }
|
|
94711
94709
|
};
|
|
94712
94710
|
}
|
|
94711
|
+
function isCliQuotaCombinationValid(code, limitKind, quotaClass, scope, dependency) {
|
|
94712
|
+
if (isCliTextQuotaErrorCode(code)) {
|
|
94713
|
+
const expectedLimitKind = code === "CLI_TEXT_DAILY_LIMIT" ? "daily" : "concurrent";
|
|
94714
|
+
const expectedScope = code === "CLI_TEXT_ORGANIZATION_CONCURRENCY_LIMIT" ? "organization" : "user";
|
|
94715
|
+
return limitKind === expectedLimitKind && quotaClass === "text-execution" && scope === expectedScope && dependency === void 0;
|
|
94716
|
+
}
|
|
94717
|
+
if (limitKind !== "request_rate") return false;
|
|
94718
|
+
const validScope = scope === void 0 || (quotaClass === "bootstrap" ? scope === "bootstrap" : quotaClass === "control-read" ? scope === "control-read" : scope === "user" || scope === "organization");
|
|
94719
|
+
if (!validScope) return false;
|
|
94720
|
+
switch (code) {
|
|
94721
|
+
case "CLI_QUOTA_EXCEEDED":
|
|
94722
|
+
return dependency === void 0;
|
|
94723
|
+
case "CLI_QUOTA_POLICY_UNAVAILABLE":
|
|
94724
|
+
return dependency === void 0 || dependency === "policy";
|
|
94725
|
+
case "CLI_QUOTA_LIMITER_UNAVAILABLE":
|
|
94726
|
+
return dependency === void 0 || dependency === "limiter";
|
|
94727
|
+
}
|
|
94728
|
+
return false;
|
|
94729
|
+
}
|
|
94713
94730
|
function parseRetryAfterSeconds(value) {
|
|
94714
94731
|
if (!value || !/^\d+$/.test(value)) return void 0;
|
|
94715
94732
|
const parsed = Number(value);
|
|
@@ -94968,7 +94985,7 @@ const makeApiServiceLive = (buildEnv) => effect$1(
|
|
|
94968
94985
|
});
|
|
94969
94986
|
const baseUrl = () => loadConfiguredApiBaseUrl();
|
|
94970
94987
|
const chatBaseUrl = () => loadConfiguredChatBaseUrl();
|
|
94971
|
-
const
|
|
94988
|
+
const requireReleaseEnabledOperation = (operationId) => {
|
|
94972
94989
|
if (buildEnv !== "prod") return _void;
|
|
94973
94990
|
if (!releaseEnabledCommandOperationIds.has(operationId)) {
|
|
94974
94991
|
return fail$3(createApiError({
|
|
@@ -94977,24 +94994,7 @@ const makeApiServiceLive = (buildEnv) => effect$1(
|
|
|
94977
94994
|
code: "CLI_OPERATION_NOT_ENABLED"
|
|
94978
94995
|
}));
|
|
94979
94996
|
}
|
|
94980
|
-
return
|
|
94981
|
-
const response = yield* makeRequest(
|
|
94982
|
-
baseUrl,
|
|
94983
|
-
"/api/cli/v1/capabilities",
|
|
94984
|
-
token
|
|
94985
|
-
);
|
|
94986
|
-
yield* try_({
|
|
94987
|
-
try: () => {
|
|
94988
|
-
const enabledOperations = parseEnabledServerOperations(response);
|
|
94989
|
-
requireEnabledServerOperation(enabledOperations, operationId);
|
|
94990
|
-
},
|
|
94991
|
-
catch: (error) => createApiError({
|
|
94992
|
-
message: error instanceof Error ? error.message : "CLI server capability validation failed",
|
|
94993
|
-
statusCode: error instanceof ServerCapabilityError && error.code === "CLI_OPERATION_NOT_ENABLED" ? 404 : 503,
|
|
94994
|
-
code: error instanceof ServerCapabilityError ? error.code : "CLI_CAPABILITIES_INCOMPATIBLE"
|
|
94995
|
-
})
|
|
94996
|
-
});
|
|
94997
|
-
});
|
|
94997
|
+
return _void;
|
|
94998
94998
|
};
|
|
94999
94999
|
const subscribeAgentChatStream = (orgSlug, conversationId, token) => gen(function* () {
|
|
95000
95000
|
const resolvedChatBaseUrl = yield* requireChatBaseUrlEffect();
|
|
@@ -95062,12 +95062,12 @@ const makeApiServiceLive = (buildEnv) => effect$1(
|
|
|
95062
95062
|
return {
|
|
95063
95063
|
listOrganizations: () => gen(function* () {
|
|
95064
95064
|
const token = yield* getAccessToken();
|
|
95065
|
-
yield*
|
|
95065
|
+
yield* requireReleaseEnabledOperation("listCliOrganizations");
|
|
95066
95066
|
return yield* makeRequest(baseUrl, "/api/cli/v1/organizations", token);
|
|
95067
95067
|
}),
|
|
95068
95068
|
getOrganization: (slug) => gen(function* () {
|
|
95069
95069
|
const token = yield* getAccessToken();
|
|
95070
|
-
yield*
|
|
95070
|
+
yield* requireReleaseEnabledOperation("listCliOrganizations");
|
|
95071
95071
|
const orgs = yield* makeRequest(baseUrl, "/api/cli/v1/organizations", token);
|
|
95072
95072
|
const org = orgs.find((o) => o.slug === slug);
|
|
95073
95073
|
if (!org) {
|
|
@@ -95082,11 +95082,12 @@ const makeApiServiceLive = (buildEnv) => effect$1(
|
|
|
95082
95082
|
}),
|
|
95083
95083
|
listSkills: (orgSlug, options) => gen(function* () {
|
|
95084
95084
|
const token = yield* getAccessToken();
|
|
95085
|
+
yield* requireReleaseEnabledOperation("listCliSkills");
|
|
95085
95086
|
const params = new URLSearchParams();
|
|
95086
95087
|
params.set("count", String(options?.count ?? 50));
|
|
95087
95088
|
if (options?.cursor) params.set("cursor", options.cursor);
|
|
95088
95089
|
if (options?.search) params.set("search", options.search);
|
|
95089
|
-
const path = `/api/
|
|
95090
|
+
const path = `/api/cli/v1/organizations/${encodeURIComponent(orgSlug)}/skills?${params.toString()}`;
|
|
95090
95091
|
const response = yield* makeRequest(baseUrl, path, token);
|
|
95091
95092
|
return {
|
|
95092
95093
|
...response,
|
|
@@ -95103,11 +95104,12 @@ const makeApiServiceLive = (buildEnv) => effect$1(
|
|
|
95103
95104
|
}),
|
|
95104
95105
|
listAdminSkills: (orgSlug, options) => gen(function* () {
|
|
95105
95106
|
const token = yield* getAccessToken();
|
|
95107
|
+
yield* requireReleaseEnabledOperation("listCliAdminSkills");
|
|
95106
95108
|
const params = new URLSearchParams();
|
|
95107
95109
|
params.set("pageNumber", String(options?.pageNumber ?? 1));
|
|
95108
95110
|
params.set("pageSize", String(options?.pageSize ?? 20));
|
|
95109
95111
|
if (options?.search) params.set("search", options.search);
|
|
95110
|
-
const path = `/api/
|
|
95112
|
+
const path = `/api/cli/v1/organizations/${encodeURIComponent(orgSlug)}/admin/skills?${params.toString()}`;
|
|
95111
95113
|
const response = yield* makeRequest(baseUrl, path, token);
|
|
95112
95114
|
return {
|
|
95113
95115
|
...response,
|
|
@@ -95177,12 +95179,14 @@ const makeApiServiceLive = (buildEnv) => effect$1(
|
|
|
95177
95179
|
}),
|
|
95178
95180
|
deleteSkill: (orgSlug, skillId) => gen(function* () {
|
|
95179
95181
|
const token = yield* getAccessToken();
|
|
95180
|
-
|
|
95182
|
+
yield* requireReleaseEnabledOperation("deleteCliSkill");
|
|
95183
|
+
const path = `/api/cli/v1/organizations/${encodeURIComponent(orgSlug)}/skills/${encodeURIComponent(skillId)}`;
|
|
95181
95184
|
return yield* makeRequest(baseUrl, path, token, { method: "DELETE" });
|
|
95182
95185
|
}),
|
|
95183
95186
|
deleteAdminSkill: (orgSlug, skillId) => gen(function* () {
|
|
95184
95187
|
const token = yield* getAccessToken();
|
|
95185
|
-
|
|
95188
|
+
yield* requireReleaseEnabledOperation("deleteCliAdminSkill");
|
|
95189
|
+
const path = `/api/cli/v1/organizations/${encodeURIComponent(orgSlug)}/admin/skills/${encodeURIComponent(skillId)}`;
|
|
95186
95190
|
return yield* makeRequest(baseUrl, path, token, { method: "DELETE" });
|
|
95187
95191
|
}),
|
|
95188
95192
|
getCurrentOrganization: () => gen(function* () {
|
|
@@ -95199,10 +95203,11 @@ const makeApiServiceLive = (buildEnv) => effect$1(
|
|
|
95199
95203
|
// Phase 1: Skill detail/download/library/clone
|
|
95200
95204
|
getSkill: (orgSlug, skillId, options) => gen(function* () {
|
|
95201
95205
|
const token = yield* getAccessToken();
|
|
95206
|
+
yield* requireReleaseEnabledOperation("getCliSkill");
|
|
95202
95207
|
const params = new URLSearchParams();
|
|
95203
95208
|
if (options?.maxFiles) params.set("maxFiles", String(options.maxFiles));
|
|
95204
95209
|
const qs = params.toString();
|
|
95205
|
-
const path = `/api/
|
|
95210
|
+
const path = `/api/cli/v1/organizations/${encodeURIComponent(orgSlug)}/skills/${encodeURIComponent(skillId)}${qs ? `?${qs}` : ""}`;
|
|
95206
95211
|
const response = yield* makeRequest(baseUrl, path, token);
|
|
95207
95212
|
return {
|
|
95208
95213
|
...response,
|
|
@@ -95214,10 +95219,11 @@ const makeApiServiceLive = (buildEnv) => effect$1(
|
|
|
95214
95219
|
}),
|
|
95215
95220
|
getAdminSkill: (orgSlug, skillId, options) => gen(function* () {
|
|
95216
95221
|
const token = yield* getAccessToken();
|
|
95222
|
+
yield* requireReleaseEnabledOperation("getCliAdminSkill");
|
|
95217
95223
|
const params = new URLSearchParams();
|
|
95218
95224
|
if (options?.maxFiles) params.set("maxFiles", String(options.maxFiles));
|
|
95219
95225
|
const qs = params.toString();
|
|
95220
|
-
const path = `/api/
|
|
95226
|
+
const path = `/api/cli/v1/organizations/${encodeURIComponent(orgSlug)}/admin/skills/${encodeURIComponent(skillId)}${qs ? `?${qs}` : ""}`;
|
|
95221
95227
|
const response = yield* makeRequest(baseUrl, path, token);
|
|
95222
95228
|
return {
|
|
95223
95229
|
...response,
|
|
@@ -95229,7 +95235,8 @@ const makeApiServiceLive = (buildEnv) => effect$1(
|
|
|
95229
95235
|
}),
|
|
95230
95236
|
updateAdminSkill: (orgSlug, skillId, body) => gen(function* () {
|
|
95231
95237
|
const token = yield* getAccessToken();
|
|
95232
|
-
|
|
95238
|
+
yield* requireReleaseEnabledOperation("updateCliAdminSkill");
|
|
95239
|
+
const path = `/api/cli/v1/organizations/${encodeURIComponent(orgSlug)}/admin/skills/${encodeURIComponent(skillId)}`;
|
|
95233
95240
|
return yield* makeRequest(baseUrl, path, token, {
|
|
95234
95241
|
method: "PATCH",
|
|
95235
95242
|
body
|
|
@@ -95289,16 +95296,18 @@ const makeApiServiceLive = (buildEnv) => effect$1(
|
|
|
95289
95296
|
}),
|
|
95290
95297
|
listLibrarySkills: (orgSlug, options) => gen(function* () {
|
|
95291
95298
|
const token = yield* getAccessToken();
|
|
95299
|
+
yield* requireReleaseEnabledOperation("listCliSkillLibrary");
|
|
95292
95300
|
const params = new URLSearchParams();
|
|
95293
95301
|
params.set("count", String(options?.count ?? 50));
|
|
95294
95302
|
if (options?.cursor) params.set("cursor", options.cursor);
|
|
95295
95303
|
if (options?.search) params.set("search", options.search);
|
|
95296
|
-
const path = `/api/
|
|
95304
|
+
const path = `/api/cli/v1/organizations/${encodeURIComponent(orgSlug)}/skills/library?${params.toString()}`;
|
|
95297
95305
|
return yield* makeRequest(baseUrl, path, token);
|
|
95298
95306
|
}),
|
|
95299
95307
|
cloneSkills: (orgSlug, sourceSkillIds) => gen(function* () {
|
|
95300
95308
|
const token = yield* getAccessToken();
|
|
95301
|
-
|
|
95309
|
+
yield* requireReleaseEnabledOperation("createCliSkillClones");
|
|
95310
|
+
const path = `/api/cli/v1/organizations/${encodeURIComponent(orgSlug)}/skills/library/clone`;
|
|
95302
95311
|
return yield* makeRequest(baseUrl, path, token, {
|
|
95303
95312
|
method: "POST",
|
|
95304
95313
|
body: { sourceSkillIds }
|
|
@@ -95307,7 +95316,7 @@ const makeApiServiceLive = (buildEnv) => effect$1(
|
|
|
95307
95316
|
// Phase 2: Agent management
|
|
95308
95317
|
listInstalledAgents: (orgSlug) => gen(function* () {
|
|
95309
95318
|
const token = yield* getAccessToken();
|
|
95310
|
-
yield*
|
|
95319
|
+
yield* requireReleaseEnabledOperation("listCliAgents");
|
|
95311
95320
|
const path = `/api/cli/v1/organizations/${encodeURIComponent(orgSlug)}/agents`;
|
|
95312
95321
|
const raw = yield* makeRequest(baseUrl, path, token);
|
|
95313
95322
|
return {
|
|
@@ -95317,7 +95326,7 @@ const makeApiServiceLive = (buildEnv) => effect$1(
|
|
|
95317
95326
|
}),
|
|
95318
95327
|
getInstalledAgent: (orgSlug, agentId) => gen(function* () {
|
|
95319
95328
|
const token = yield* getAccessToken();
|
|
95320
|
-
yield*
|
|
95329
|
+
yield* requireReleaseEnabledOperation("getCliAgent");
|
|
95321
95330
|
const path = `/api/cli/v1/organizations/${encodeURIComponent(orgSlug)}/agents/${encodeURIComponent(agentId)}`;
|
|
95322
95331
|
const raw = yield* makeRequest(baseUrl, path, token);
|
|
95323
95332
|
return {
|
|
@@ -95330,7 +95339,7 @@ const makeApiServiceLive = (buildEnv) => effect$1(
|
|
|
95330
95339
|
}),
|
|
95331
95340
|
updateInstalledAgentStatus: (orgSlug, agentId, status) => gen(function* () {
|
|
95332
95341
|
const token = yield* getAccessToken();
|
|
95333
|
-
yield*
|
|
95342
|
+
yield* requireReleaseEnabledOperation("updateCliAgentStatus");
|
|
95334
95343
|
const path = `/api/cli/v1/organizations/${encodeURIComponent(orgSlug)}/agents/${encodeURIComponent(agentId)}/status`;
|
|
95335
95344
|
return yield* makeRequest(baseUrl, path, token, {
|
|
95336
95345
|
method: "PATCH",
|
|
@@ -95410,7 +95419,7 @@ const makeApiServiceLive = (buildEnv) => effect$1(
|
|
|
95410
95419
|
// Phase 4: Monitoring
|
|
95411
95420
|
listOrgMembers: (orgSlug) => gen(function* () {
|
|
95412
95421
|
const token = yield* getAccessToken();
|
|
95413
|
-
yield*
|
|
95422
|
+
yield* requireReleaseEnabledOperation("listCliOrganizationMembers");
|
|
95414
95423
|
const path = `/api/cli/v1/organizations/${encodeURIComponent(orgSlug)}/members`;
|
|
95415
95424
|
const raw = yield* makeRequest(baseUrl, path, token);
|
|
95416
95425
|
return {
|
|
@@ -95426,7 +95435,7 @@ const makeApiServiceLive = (buildEnv) => effect$1(
|
|
|
95426
95435
|
listModels: (orgSlug) => gen(function* () {
|
|
95427
95436
|
yield* requireChatBaseUrlEffect();
|
|
95428
95437
|
const token = yield* getAccessToken();
|
|
95429
|
-
yield*
|
|
95438
|
+
yield* requireReleaseEnabledOperation("listCliModels");
|
|
95430
95439
|
const path = `/api/cli/v1/organizations/${encodeURIComponent(orgSlug)}/models`;
|
|
95431
95440
|
const response = yield* makeRequest(chatBaseUrl, path, token);
|
|
95432
95441
|
return response.models.map((id) => ({
|
|
@@ -95437,14 +95446,14 @@ const makeApiServiceLive = (buildEnv) => effect$1(
|
|
|
95437
95446
|
listModelExecModels: (orgSlug) => gen(function* () {
|
|
95438
95447
|
yield* requireChatBaseUrlEffect();
|
|
95439
95448
|
const token = yield* getAccessToken();
|
|
95440
|
-
yield*
|
|
95449
|
+
yield* requireReleaseEnabledOperation("listCliModelExecModels");
|
|
95441
95450
|
const path = `/api/cli/v1/organizations/${encodeURIComponent(orgSlug)}/model-exec/models`;
|
|
95442
95451
|
return yield* makeRequest(chatBaseUrl, path, token);
|
|
95443
95452
|
}),
|
|
95444
95453
|
executeModelExecChat: (orgSlug, body) => gen(function* () {
|
|
95445
95454
|
yield* requireChatBaseUrlEffect();
|
|
95446
95455
|
const token = yield* getAccessToken();
|
|
95447
|
-
yield*
|
|
95456
|
+
yield* requireReleaseEnabledOperation("createCliModelChatExecution");
|
|
95448
95457
|
const path = `/api/cli/v1/organizations/${encodeURIComponent(orgSlug)}/model-exec/chat`;
|
|
95449
95458
|
return yield* makeRequest(chatBaseUrl, path, token, {
|
|
95450
95459
|
method: "POST",
|
|
@@ -95517,8 +95526,9 @@ const makeApiServiceLive = (buildEnv) => effect$1(
|
|
|
95517
95526
|
// Phase 5: Drive/Integration
|
|
95518
95527
|
listDriveEntries: (orgSlug) => gen(function* () {
|
|
95519
95528
|
const token = yield* getAccessToken();
|
|
95529
|
+
yield* requireReleaseEnabledOperation("listCliDriveEntries");
|
|
95520
95530
|
const params = new URLSearchParams({ count: "200" });
|
|
95521
|
-
const path = `/api/
|
|
95531
|
+
const path = `/api/cli/v1/organizations/${encodeURIComponent(orgSlug)}/drive/entries?${params.toString()}`;
|
|
95522
95532
|
return yield* makeRequest(baseUrl, path, token);
|
|
95523
95533
|
}),
|
|
95524
95534
|
getDriveDownloadUrl: (orgSlug, entryId) => gen(function* () {
|
|
@@ -95552,22 +95562,26 @@ const makeApiServiceLive = (buildEnv) => effect$1(
|
|
|
95552
95562
|
}),
|
|
95553
95563
|
deleteDriveEntries: (orgSlug, entryIds) => gen(function* () {
|
|
95554
95564
|
const token = yield* getAccessToken();
|
|
95555
|
-
|
|
95565
|
+
yield* requireReleaseEnabledOperation("deleteCliDriveEntries");
|
|
95566
|
+
const path = `/api/cli/v1/organizations/${encodeURIComponent(orgSlug)}/drive/entries/delete`;
|
|
95556
95567
|
return yield* makeRequest(baseUrl, path, token, { method: "POST", body: { entryIds } });
|
|
95557
95568
|
}),
|
|
95558
95569
|
createDriveFolder: (orgSlug, name) => gen(function* () {
|
|
95559
95570
|
const token = yield* getAccessToken();
|
|
95560
|
-
|
|
95571
|
+
yield* requireReleaseEnabledOperation("createCliDriveFolder");
|
|
95572
|
+
const path = `/api/cli/v1/organizations/${encodeURIComponent(orgSlug)}/drive/folders`;
|
|
95561
95573
|
return yield* makeRequest(baseUrl, path, token, { method: "POST", body: { name } });
|
|
95562
95574
|
}),
|
|
95563
95575
|
renameDriveEntry: (orgSlug, entryId, newName) => gen(function* () {
|
|
95564
95576
|
const token = yield* getAccessToken();
|
|
95565
|
-
|
|
95577
|
+
yield* requireReleaseEnabledOperation("updateCliDriveEntryName");
|
|
95578
|
+
const path = `/api/cli/v1/organizations/${encodeURIComponent(orgSlug)}/drive/entries/${encodeURIComponent(entryId)}`;
|
|
95566
95579
|
return yield* makeRequest(baseUrl, path, token, { method: "PATCH", body: { newName } });
|
|
95567
95580
|
}),
|
|
95568
95581
|
getDriveUsage: (orgSlug) => gen(function* () {
|
|
95569
95582
|
const token = yield* getAccessToken();
|
|
95570
|
-
|
|
95583
|
+
yield* requireReleaseEnabledOperation("getCliDriveUsage");
|
|
95584
|
+
const path = `/api/cli/v1/organizations/${encodeURIComponent(orgSlug)}/drive/usage`;
|
|
95571
95585
|
return yield* makeRequest(baseUrl, path, token);
|
|
95572
95586
|
}),
|
|
95573
95587
|
listIntegrations: (orgSlug) => gen(function* () {
|
|
@@ -95586,7 +95600,7 @@ const makeApiServiceLive = (buildEnv) => effect$1(
|
|
|
95586
95600
|
// Phase 6: Auth enhancements
|
|
95587
95601
|
getMe: () => gen(function* () {
|
|
95588
95602
|
const token = yield* getAccessToken();
|
|
95589
|
-
yield*
|
|
95603
|
+
yield* requireReleaseEnabledOperation("getCliMe");
|
|
95590
95604
|
return yield* makeRequest(baseUrl, "/api/cli/v1/me", token);
|
|
95591
95605
|
}),
|
|
95592
95606
|
refreshToken: () => refreshAccessToken({ force: true }),
|
|
@@ -95624,7 +95638,7 @@ const makeApiServiceLive = (buildEnv) => effect$1(
|
|
|
95624
95638
|
// Phase 8: Agent admin CRUD
|
|
95625
95639
|
createInstalledAgent: (orgSlug, body) => gen(function* () {
|
|
95626
95640
|
const token = yield* getAccessToken();
|
|
95627
|
-
yield*
|
|
95641
|
+
yield* requireReleaseEnabledOperation("createCliAgent");
|
|
95628
95642
|
const path = `/api/cli/v1/organizations/${encodeURIComponent(orgSlug)}/agents`;
|
|
95629
95643
|
return yield* makeRequest(baseUrl, path, token, {
|
|
95630
95644
|
method: "POST",
|
|
@@ -95633,7 +95647,7 @@ const makeApiServiceLive = (buildEnv) => effect$1(
|
|
|
95633
95647
|
}),
|
|
95634
95648
|
updateInstalledAgent: (orgSlug, agentId, body) => gen(function* () {
|
|
95635
95649
|
const token = yield* getAccessToken();
|
|
95636
|
-
yield*
|
|
95650
|
+
yield* requireReleaseEnabledOperation("updateCliAgent");
|
|
95637
95651
|
const path = `/api/cli/v1/organizations/${encodeURIComponent(orgSlug)}/agents/${encodeURIComponent(agentId)}`;
|
|
95638
95652
|
return yield* makeRequest(baseUrl, path, token, {
|
|
95639
95653
|
method: "PATCH",
|
|
@@ -95642,7 +95656,7 @@ const makeApiServiceLive = (buildEnv) => effect$1(
|
|
|
95642
95656
|
}),
|
|
95643
95657
|
deleteInstalledAgent: (orgSlug, agentId) => gen(function* () {
|
|
95644
95658
|
const token = yield* getAccessToken();
|
|
95645
|
-
yield*
|
|
95659
|
+
yield* requireReleaseEnabledOperation("deleteCliAgent");
|
|
95646
95660
|
const path = `/api/cli/v1/organizations/${encodeURIComponent(orgSlug)}/agents/${encodeURIComponent(agentId)}`;
|
|
95647
95661
|
return yield* makeRequest(baseUrl, path, token, { method: "DELETE" });
|
|
95648
95662
|
}),
|
|
@@ -95669,7 +95683,7 @@ const makeApiServiceLive = (buildEnv) => effect$1(
|
|
|
95669
95683
|
}),
|
|
95670
95684
|
getInstalledAgentShare: (orgSlug, agentId) => gen(function* () {
|
|
95671
95685
|
const token = yield* getAccessToken();
|
|
95672
|
-
yield*
|
|
95686
|
+
yield* requireReleaseEnabledOperation("getCliAgentShare");
|
|
95673
95687
|
const path = `/api/cli/v1/organizations/${encodeURIComponent(orgSlug)}/agents/${encodeURIComponent(agentId)}/share`;
|
|
95674
95688
|
const raw = yield* makeRequest(baseUrl, path, token);
|
|
95675
95689
|
const sharedUserList = yield* try_({
|
|
@@ -95683,7 +95697,7 @@ const makeApiServiceLive = (buildEnv) => effect$1(
|
|
|
95683
95697
|
}),
|
|
95684
95698
|
listAgentTemplates: (orgSlug) => gen(function* () {
|
|
95685
95699
|
const token = yield* getAccessToken();
|
|
95686
|
-
yield*
|
|
95700
|
+
yield* requireReleaseEnabledOperation("listCliAgentTemplates");
|
|
95687
95701
|
const path = `/api/cli/v1/organizations/${encodeURIComponent(orgSlug)}/agents/templates`;
|
|
95688
95702
|
const templates = [];
|
|
95689
95703
|
let page = 1;
|
|
@@ -95707,16 +95721,37 @@ const makeApiServiceLive = (buildEnv) => effect$1(
|
|
|
95707
95721
|
// Built-in skill library
|
|
95708
95722
|
listBuiltInSkills: (orgSlug, options) => gen(function* () {
|
|
95709
95723
|
const token = yield* getAccessToken();
|
|
95724
|
+
yield* requireReleaseEnabledOperation("listCliBuiltInSkills");
|
|
95710
95725
|
const params = new URLSearchParams();
|
|
95711
95726
|
params.set("limit", String(options?.limit ?? 50));
|
|
95712
95727
|
if (options?.cursor) params.set("cursor", options.cursor);
|
|
95713
95728
|
if (options?.search) params.set("search", options.search);
|
|
95714
|
-
const path = `/api/
|
|
95729
|
+
const path = `/api/cli/v1/organizations/${encodeURIComponent(orgSlug)}/skills/built-in?${params.toString()}`;
|
|
95715
95730
|
return yield* makeRequest(baseUrl, path, token);
|
|
95716
95731
|
}),
|
|
95717
95732
|
cloneBuiltInSkills: (orgSlug, sourceSkillIds) => gen(function* () {
|
|
95718
95733
|
const token = yield* getAccessToken();
|
|
95719
|
-
|
|
95734
|
+
yield* requireReleaseEnabledOperation("createCliBuiltInSkillClones");
|
|
95735
|
+
const path = `/api/cli/v1/organizations/${encodeURIComponent(orgSlug)}/skills/built-in/clone`;
|
|
95736
|
+
return yield* makeRequest(baseUrl, path, token, {
|
|
95737
|
+
method: "POST",
|
|
95738
|
+
body: { sourceSkillIds }
|
|
95739
|
+
});
|
|
95740
|
+
}),
|
|
95741
|
+
listAdminBuiltInSkills: (orgSlug, options) => gen(function* () {
|
|
95742
|
+
const token = yield* getAccessToken();
|
|
95743
|
+
yield* requireReleaseEnabledOperation("listCliAdminBuiltInSkills");
|
|
95744
|
+
const params = new URLSearchParams();
|
|
95745
|
+
params.set("limit", String(options?.limit ?? 50));
|
|
95746
|
+
if (options?.cursor) params.set("cursor", options.cursor);
|
|
95747
|
+
if (options?.search) params.set("search", options.search);
|
|
95748
|
+
const path = `/api/cli/v1/organizations/${encodeURIComponent(orgSlug)}/admin/skills/built-in?${params.toString()}`;
|
|
95749
|
+
return yield* makeRequest(baseUrl, path, token);
|
|
95750
|
+
}),
|
|
95751
|
+
cloneAdminBuiltInSkills: (orgSlug, sourceSkillIds) => gen(function* () {
|
|
95752
|
+
const token = yield* getAccessToken();
|
|
95753
|
+
yield* requireReleaseEnabledOperation("createCliAdminBuiltInSkillClones");
|
|
95754
|
+
const path = `/api/cli/v1/organizations/${encodeURIComponent(orgSlug)}/admin/skills/built-in/clone`;
|
|
95720
95755
|
return yield* makeRequest(baseUrl, path, token, {
|
|
95721
95756
|
method: "POST",
|
|
95722
95757
|
body: { sourceSkillIds }
|
|
@@ -95780,13 +95815,13 @@ const makeApiServiceLive = (buildEnv) => effect$1(
|
|
|
95780
95815
|
// Org capabilities & user settings
|
|
95781
95816
|
getOrgCapabilities: (orgSlug) => gen(function* () {
|
|
95782
95817
|
const token = yield* getAccessToken();
|
|
95783
|
-
yield*
|
|
95818
|
+
yield* requireReleaseEnabledOperation("getCliOrganizationCapabilities");
|
|
95784
95819
|
const path = `/api/cli/v1/organizations/${encodeURIComponent(orgSlug)}/capabilities`;
|
|
95785
95820
|
return yield* makeRequest(baseUrl, path, token);
|
|
95786
95821
|
}),
|
|
95787
95822
|
getUserSettings: () => gen(function* () {
|
|
95788
95823
|
const token = yield* getAccessToken();
|
|
95789
|
-
yield*
|
|
95824
|
+
yield* requireReleaseEnabledOperation("getCliUserSettings");
|
|
95790
95825
|
return yield* makeRequest(baseUrl, "/api/cli/v1/me/settings", token);
|
|
95791
95826
|
}),
|
|
95792
95827
|
// Tunnel management
|
|
@@ -97182,14 +97217,14 @@ const searchOption$3 = text("search").pipe(
|
|
|
97182
97217
|
withDescription$3("Search built-in skills by name"),
|
|
97183
97218
|
optional
|
|
97184
97219
|
);
|
|
97185
|
-
const
|
|
97220
|
+
const makeBuiltInCommand = (listSkills = (api, orgSlug, options) => api.listBuiltInSkills(orgSlug, options), description = "List built-in skills from the library") => make$4(
|
|
97186
97221
|
"built-in",
|
|
97187
97222
|
{ org: orgOption, search: searchOption$3 },
|
|
97188
97223
|
({ org, search }) => gen(function* () {
|
|
97189
97224
|
const api = yield* ApiService;
|
|
97190
97225
|
const orgSlug = yield* resolveOrgSlug(org, api);
|
|
97191
97226
|
const searchValue = search._tag === "Some" ? search.value : void 0;
|
|
97192
|
-
const result = yield* api
|
|
97227
|
+
const result = yield* listSkills(api, orgSlug, { search: searchValue }).pipe(
|
|
97193
97228
|
catchTag(
|
|
97194
97229
|
"NotLoggedInError",
|
|
97195
97230
|
(e) => gen(function* () {
|
|
@@ -97227,7 +97262,8 @@ const builtInCommand = make$4(
|
|
|
97227
97262
|
yield* log("(More built-in skills available.)");
|
|
97228
97263
|
}
|
|
97229
97264
|
})
|
|
97230
|
-
).pipe(withDescription(
|
|
97265
|
+
).pipe(withDescription(description));
|
|
97266
|
+
const builtInCommand = makeBuiltInCommand();
|
|
97231
97267
|
|
|
97232
97268
|
const MAX_CLONE_SKILLS$1 = 5;
|
|
97233
97269
|
const formatCloneBuiltInFailureMessage = maskSensitiveText;
|
|
@@ -97235,7 +97271,7 @@ const skillIdsArg$1 = text$2({ name: "id" }).pipe(
|
|
|
97235
97271
|
withDescription$5(`Built-in skill ID(s) to clone (max ${MAX_CLONE_SKILLS$1})`),
|
|
97236
97272
|
repeated
|
|
97237
97273
|
);
|
|
97238
|
-
const
|
|
97274
|
+
const makeCloneBuiltInCommand = (cloneSkills = (api, orgSlug, sourceSkillIds) => api.cloneBuiltInSkills(orgSlug, sourceSkillIds), description = "Clone built-in skills from the library to your organization") => make$4(
|
|
97239
97275
|
"clone-built-in",
|
|
97240
97276
|
{ skillIds: skillIdsArg$1, org: orgOption },
|
|
97241
97277
|
({ skillIds, org }) => gen(function* () {
|
|
@@ -97251,7 +97287,7 @@ const cloneBuiltInCommand = make$4(
|
|
|
97251
97287
|
return;
|
|
97252
97288
|
}
|
|
97253
97289
|
yield* log(`Cloning ${ids.length} built-in skill(s) to organization "${orgSlug}"...`);
|
|
97254
|
-
const result = yield* api
|
|
97290
|
+
const result = yield* cloneSkills(api, orgSlug, ids).pipe(
|
|
97255
97291
|
catchTag(
|
|
97256
97292
|
"NotLoggedInError",
|
|
97257
97293
|
(e) => gen(function* () {
|
|
@@ -97281,7 +97317,8 @@ const cloneBuiltInCommand = make$4(
|
|
|
97281
97317
|
}
|
|
97282
97318
|
}
|
|
97283
97319
|
})
|
|
97284
|
-
).pipe(withDescription(
|
|
97320
|
+
).pipe(withDescription(description));
|
|
97321
|
+
const cloneBuiltInCommand = makeCloneBuiltInCommand();
|
|
97285
97322
|
|
|
97286
97323
|
const skillIdArg$4 = text$2({ name: "id" }).pipe(withDescription$5("Skill ID to download"));
|
|
97287
97324
|
const outputOption$2 = text("output").pipe(
|
|
@@ -97858,6 +97895,14 @@ const unpublishCommand = make$4(
|
|
|
97858
97895
|
yield* log(`Organization skill "${skillId}" was removed from the shared library.`);
|
|
97859
97896
|
})
|
|
97860
97897
|
).pipe(withDescription("Remove an organization skill from the shared library"));
|
|
97898
|
+
const adminBuiltInCommand = makeBuiltInCommand(
|
|
97899
|
+
(api, orgSlug, options) => api.listAdminBuiltInSkills(orgSlug, options),
|
|
97900
|
+
"List built-in skills available to an AI operator"
|
|
97901
|
+
);
|
|
97902
|
+
const adminCloneBuiltInCommand = makeCloneBuiltInCommand(
|
|
97903
|
+
(api, orgSlug, sourceSkillIds) => api.cloneAdminBuiltInSkills(orgSlug, sourceSkillIds),
|
|
97904
|
+
"Clone built-in skills as an AI operator"
|
|
97905
|
+
);
|
|
97861
97906
|
const adminSkillCommandDescription = "Admin skill management (list, get, upload, download, delete, publish, unpublish, built-in, clone-built-in, github)";
|
|
97862
97907
|
const adminSkillSubcommands = [
|
|
97863
97908
|
listCommand$8,
|
|
@@ -97867,8 +97912,8 @@ const adminSkillSubcommands = [
|
|
|
97867
97912
|
deleteCommand$3,
|
|
97868
97913
|
publishCommand,
|
|
97869
97914
|
unpublishCommand,
|
|
97870
|
-
|
|
97871
|
-
|
|
97915
|
+
adminBuiltInCommand,
|
|
97916
|
+
adminCloneBuiltInCommand,
|
|
97872
97917
|
githubSkillCommand
|
|
97873
97918
|
];
|
|
97874
97919
|
const adminSkillCommand = make$4("skill", {}).pipe(
|
|
@@ -43,10 +43,10 @@
|
|
|
43
43
|
| ORG-02 | org | `aipctl org capabilities`, `aipctl org settings`, `aipctl org exit` | `getOrgCapabilities`, `getUserSettings`, `exitOrg` | api | `GET`, `GET`, `POST` | organization v1 `/api/cli/v1/organizations/{organizationSlug}/capabilities`; user-global v1 `/api/cli/v1/me/settings`; legacy `/api/web/organizations/slug/{organizationSlug}/exit` | none | local `OrgCapabilities`, `UserSettings`, `void` | read paths: `resource/oas/modules/backend/cli/openapi.yaml`; exit: `resource/oas/duplo-web.yaml` | read generated `CliOrganizationApi`/`CliV1Api`; exit legacy generated | `legacy-generated` | N/A | `migrate` | owner=`backend`; rationale=`capabilities is organization-owned, settings remains user-global, and exit remains a Wave B mutation`; removal condition=`exit receives its dedicated v1 mutation contract`; incorporation plan=`preserve current membership authorization and non-replay behavior` | task 3.3 | `src/core/api.test.ts` verifies v1 read paths and settings ownership; org tests cover response/error behavior |
|
|
44
44
|
| P0-ORG-01 | org-member | `aipctl org members`; `aipctl admin org invite`, `aipctl admin org remove-member`, `aipctl admin org update-member-role` | `listOrgMembers`, `inviteOrgMembers`, `removeOrgMembers`, `updateOrgMemberRoles` | api | `GET`, `POST`, `DELETE`, `PUT` | list v1 `/api/cli/v1/organizations/{organizationSlug}/members`; mutations remain legacy `/invite`; `/members` | list uses stable CLI member response; mutation bodies preserve `{ emails, role }` and `{ members, role? }` | local `ListMembersResponse`, `InviteOrgMembersResponse`, `void` | list: `resource/oas/modules/backend/cli/openapi.yaml`; mutation: `resource/oas/duplo-web.yaml` | list generated `CliOrganizationApi`; mutation legacy generated | `legacy-generated` | `P0` | `legacy-exception` | owner=`backend`; rationale=`member read is migrated while admin mutations remain Wave B`; removal condition=`invite/remove/role receive dedicated v1 contracts`; incorporation plan=`reuse current admin authorization, audit, stale target validation, and non-replay semantics` | task 3.3 | `src/core/api.test.ts`, `commands/org/members.test.ts`, `commands/org/org-member.test.ts`; covers v1 member read and legacy mutation bodies |
|
|
45
45
|
| P0-ORG-02 | org-admin | hidden from public beta (`aipctl admin org invite-link`, `gen-invite-link`, `revoke-invite-link` removed from command tree) | removed from public surface | api | `GET`, `POST`, `DELETE` | previously `/api/web/organizations/slug/{organizationSlug}/invite/link` | none | hidden | latest: `resource/oas/modules/backend/organization/openapi.yaml` (`/invite/link/v2`); legacy: `resource/oas/duplo-web.yaml` (`/invite/link`) | latest `frontend/packages/api/src/out/modules/organization-types.ts#paths["/api/web/organizations/slug/{organizationSlug}/invite/link/v2"]`; legacy `frontend/packages/api/src/out/user-types.ts#paths["/api/web/organizations/slug/{organizationSlug}/invite/link"]` | `oas-source-only` | `P0` | `hide` | owner=`backend organization module`; rationale=`v2 exists but current CLI UX contract for GET/DELETE parity is not approved for public beta`; removal condition=`public beta continues hiding until a reviewed v2 CLI UX contract exists`; incorporation plan=`reintroduce only after independent organization contract/build and public UX review` | N/A | updated admin org help smoke + command-tree regression to ensure trio is absent |
|
|
46
|
-
| SKILL-01 | skill | `aipctl skill list`, `aipctl skill get`, `aipctl skill delete` | `listSkills`, `getSkill`, `deleteSkill` | api | `GET`, `GET`, `DELETE` | `/api/
|
|
46
|
+
| SKILL-01 | skill | `aipctl skill list`, `aipctl skill get`, `aipctl skill delete` | `listSkills`, `getSkill`, `deleteSkill` | api | `GET`, `GET`, `DELETE` | `/api/cli/v1/organizations/{organizationSlug}/skills`; `/api/cli/v1/organizations/{organizationSlug}/skills/{skillId}` | query `{ count,cursor,search }`; detail query `{ maxFiles }` | local `ListSkillsResponse`, `SkillDetail`, `void` | `resource/oas/modules/backend/cli/openapi.yaml` → `v1_skills*.yaml` (DTO aliases to organization Skills OAS) | `backend/api/.../cli/generated/api/CliSkillApi.kt`; domain DTOs remain `com.querypie.duplo.api.skills.generated.model.*` | `generated-ready` | `P0` | `migrate` | none; `CliSkillApiController` delegates to the existing member authorization/audit controller | `AI-6344` | `src/core/api.test.ts`, `CliSkillDriveApiControllerTest`, Gateway registry/contract parity; production CLI and local 403/404 checks (401/429 remain common gates) |
|
|
47
47
|
| SKILL-02 | skill | `aipctl skill upload` | `createUploadUrl` → `uploadToS3` → `completeUpload` (`abortUpload` on failure) | api + external | `POST` → `PUT` → `POST` | `/skills/upload-url`; external presigned `uploadUrl`; `/skills/{skillId}/complete` | local upload request `{ filename,fileSize,mimeType }`, file buffer, complete body `{ overwrite }` | `CreateSkillUploadUrlResponse`, external `void`, `CompleteSkillUploadResponse` | `resource/oas/modules/backend/organization/skills/openapi.yaml` | `frontend/packages/api/src/out/modules/organization-skills-types.ts#paths["/api/web/organizations/slug/{organizationSlug}/skills/upload-url"]`, `#paths["/api/web/organizations/slug/{organizationSlug}/skills/{skillId}/complete"]` | `external-presigned` | N/A | `keep` | none | N/A | existing skill upload tests; needed presigned URL + complete path snapshot |
|
|
48
|
-
| SKILL-03 | skill | `aipctl skill library`, `aipctl skill clone`, `aipctl skill built-in`, `aipctl skill clone-built-in`; `aipctl admin skill built-in`, `aipctl admin skill clone-built-in` | `listLibrarySkills`, `cloneSkills`, `listBuiltInSkills`, `cloneBuiltInSkills` | api | `GET`, `POST`, `GET`, `POST` | `/skills/library`; `/skills/library/clone`; `/
|
|
49
|
-
| SKILL-04 | skill-admin | `aipctl admin skill list`, `get`, `delete`, `publish`, `unpublish` | `listAdminSkills`, `getAdminSkill`, `deleteAdminSkill`, `updateAdminSkill` | api | `GET`, `GET`, `DELETE`, `PATCH` | `/api/
|
|
48
|
+
| SKILL-03 | skill | `aipctl skill library`, `aipctl skill clone`, `aipctl skill built-in`, `aipctl skill clone-built-in`; `aipctl admin skill built-in`, `aipctl admin skill clone-built-in` | `listLibrarySkills`, `cloneSkills`, `listBuiltInSkills`, `cloneBuiltInSkills`, `listAdminBuiltInSkills`, `cloneAdminBuiltInSkills` | api | `GET`, `POST`, `GET`, `POST`, `GET`, `POST` | `/api/cli/v1/organizations/{organizationSlug}/skills/library`; `/skills/library/clone`; `/skills/built-in`; `/skills/built-in/clone`; `/admin/skills/built-in`; `/admin/skills/built-in/clone` | list query `{ count,cursor,search/limit }`; clone body `{ sourceSkillIds[] }` | local list/clone DTOs | `resource/oas/modules/backend/cli/openapi.yaml` → `v1_skills_library*`, `v1_skills_built-in*`, `v1_admin_skills_built-in*` (aliases to organization Skills OAS) | `backend/api/.../cli/generated/api/CliSkillApi.kt`; domain DTOs remain `com.querypie.duplo.api.skills.generated.model.*` | `generated-ready` | `P0` | `migrate` | none; built-in execution reuses the existing AI-operator authorization owner while CLI API methods preserve general/admin operation identity | `AI-6344` | existing skill extended/admin tests, API path tests, adapter test, Gateway registry/contract parity and production CLI clone/list checks |
|
|
49
|
+
| SKILL-04 | skill-admin | `aipctl admin skill list`, `get`, `delete`, `publish`, `unpublish` | `listAdminSkills`, `getAdminSkill`, `deleteAdminSkill`, `updateAdminSkill` | api | `GET`, `GET`, `DELETE`, `PATCH` | `/api/cli/v1/organizations/{organizationSlug}/admin/skills`; `/admin/skills/{skillId}` | list query `{ pageNumber,pageSize,search }`; publish toggle body `{ availableInLibrary: boolean }` | local `ListAdminSkillsResponse`, `SkillDetail`, `void` | `resource/oas/modules/backend/cli/openapi.yaml` → `v1_admin_skills*.yaml` (DTO aliases to organization Skills OAS) | `backend/api/.../cli/generated/api/CliSkillApi.kt`; domain DTOs remain `com.querypie.duplo.api.skills.generated.model.*` | `generated-ready` | `P0` | `migrate` | none; `CliSkillApiController` delegates AI-operator authorization, workflow and audit owner | `AI-6344` | existing `commands/admin/skill.test.ts`, adapter test, Gateway parity; production admin list/publish/delete and 403/429 checks |
|
|
50
50
|
| SKILL-05 | skill-admin | `aipctl skill download`; `aipctl admin skill upload`, `aipctl admin skill download`, `aipctl admin skill github inspect/import/sync/credentials set/clear` | `createAdminUploadUrl` → `uploadToS3` → `completeAdminUpload` (`abortAdminUpload` on failure); `getSkillDownloadUrl` → `downloadFromUrl`; `inspectGitHubSkillSource`, `prepareGitHubSkill`, `syncPrepareGitHubSkill`, `updateGitHubSkillCredentials` | api + external | `POST`/`PUT`/`POST`; `POST`/`GET`; `POST`, `POST`, `POST`, `PATCH` | `/admin/.../skills/upload-url`; `/admin/.../skills/download-url`; `/admin/.../skills/github-repo-inspect`; `/github-prepare`; `/{skillId}/sync-prepare`; `/{skillId}/github-credentials` | upload/download local bodies; GitHub inspect/prepare `{ url, pat? }`; credentials `{ pat or null }` | upload/download/GitHub admin skill DTOs | `resource/oas/modules/backend/organization/skills/openapi.yaml` | `frontend/packages/api/src/out/modules/organization-skills-types.ts#paths["/api/web/admin/organizations/slug/{organizationSlug}/skills/upload-url"]`, `#paths["/api/web/admin/organizations/slug/{organizationSlug}/skills/download-url"]`, `#paths["/api/web/admin/organizations/slug/{organizationSlug}/skills/github-repo-inspect"]`, `#paths["/api/web/admin/organizations/slug/{organizationSlug}/skills/github-prepare"]`, `#paths["/api/web/admin/organizations/slug/{organizationSlug}/skills/{skillId}/sync-prepare"]`, `#paths["/api/web/admin/organizations/slug/{organizationSlug}/skills/{skillId}/github-credentials"]` | `external-presigned` | N/A | `keep` | none | N/A | existing `commands/admin/skill.test.ts`, `commands/skill/skill-extended.test.ts`; needed GitHub admin skill contract fixtures |
|
|
51
51
|
| P1-SKILL-01 | skill-docs | `aipctl skill get --json`, `aipctl admin skill get --json`, `aipctl admin skill github import/sync --json` | same owners as `SKILL-01`/`SKILL-05` | api | same as upstream rows | same as upstream rows | runtime/JSON/help/docs now align on `source`, `origin`, `updateAvailable`, `secretsAvailable`, GitHub metadata, `secretKeys`; stale `version` and file `size` removed | JSON/help/docs contract for skill objects | `resource/oas/modules/backend/organization/skills/openapi.yaml` | `frontend/packages/api/src/out/modules/organization-skills-types.ts#components[...]` | `generated-ready` | `P1` | `keep` | none | N/A | updated `src/core/api.test.ts`, `commands/skill/skill.test.ts`, `commands/skill/skill-extended.test.ts`, `commands/admin/skill.test.ts`, `commands/json-format.test.ts`, `../docs/how-to/aip-cli-usage.md`; covers JSON/help/docs field sync |
|
|
52
52
|
| P0-AGENT-01 | agent-user | `aipctl agent list`, `aipctl agent get` | `listInstalledAgents`, `getInstalledAgent` | api | `GET`, `GET` | `/api/cli/v1/organizations/{organizationSlug}/agents`; `/{installedAgentId}` | preserves user read semantics and maps `list`/`installedAgentId` to local `data`/`id` | local `ListInstalledAgentsResponse`, `{ data: InstalledAgentDetail }` | `resource/oas/modules/backend/cli/openapi.yaml`; shared DTO refs from `resource/oas/duplo.yaml` | `backend/api/.../cli/generated/api/CliAgentApi.kt` | `generated-ready` | `P0` | `migrate` | none; dedicated adapter delegates to the working `AgentsApiController` bean | `AI-6344` | `src/core/api.test.ts`, `CliAgentApiControllerTest`, Gateway registry/admission parity; real local production CLI list/get JSON |
|
|
@@ -55,7 +55,7 @@
|
|
|
55
55
|
| P1-CHAT-01 | agent-chat | `aipctl agent chat` | `agentNewChat`, `agentChat`, local `parseSseStream` | chat | `POST` + SSE | `/librechat/api/{orgSlug}/agent/new-chat`; `/librechat/api/{orgSlug}/agent/chat` | request body `{ agentInstallationId or conversationId, text, files: [] }` | local `AgentChatResult { text, conversationId }` parsed from SSE event fields `final`, `conversation.conversationId`, `responseMessage` | path source: `resource/oas/chat.yaml` | `frontend/packages/api/src/out/chat-types.ts#paths["/librechat/api/{orgSlug}/agent/new-chat"]`, `#paths["/librechat/api/{orgSlug}/agent/chat"]` | `stream-exception` | `P1` | `legacy-exception` | owner=`chat backend agent SSE stream contract`; rationale=`path exists in OpenAPI but final SSE event payload is still out-of-band`; removal condition=`official SSE event schema or versioned fixture is published with the chat contract`; incorporation plan=`bind CLI parser/tests to the published SSE fixture and drop local-only stream assumptions` | N/A | updated `src/core/api.test.ts`; covers content[] text, fallback text, malformed event skip, and no-final-event failure |
|
|
56
56
|
| P1-AUTO-01 | automation | `aipctl automation list`, `get`, `create`, `update`, `delete`, `run`, `enable`, `disable`, `history`, `cancel`, `webhook-regen`, `triggers` | `listAutomations`, `getAutomation`, `createAutomation`, `updateAutomation`, `deleteAutomation`, `runAutomation`, `updateAutomationStatus`, `listAutomationHistories`, `cancelAutomationHistory`, `regenerateWebhookUrl`, `getTriggerProviderMetadata` | api | `GET`, `POST`, `PUT`, `DELETE` mix | `/api/web/organizations/slug/{organizationSlug}/automations...`; `/automation-trigger-providers/.../metadata` | automation pagination normalized to `{ page, pageSize, total }`; metadata calls now use provider-specific OAS paths and required args (`accountId`, `folderId`, `serviceType`) | local automation DTOs + webhook URL DTO | `resource/oas/modules/backend/automation/user/openapi.yaml` | `frontend/packages/api/src/out/modules/automation-user-types.ts#paths[...]` | `generated-ready` | `P1` | `keep` | none | N/A | updated `src/core/api.test.ts`, `commands/automation/automation.test.ts`, `commands/json-format.test.ts`; covers official pagination fields, provider-specific metadata routes, and unsupported-provider preflight failure |
|
|
57
57
|
| CHAT-01 | chat-readonly | `aipctl chat list`, `aipctl chat get`, `aipctl chat messages` | `listConversations`, `getConversation`, `listMessages` | chat | `GET` | `/librechat/api/{orgSlug}/convos`; `/convos/{conversationId}`; `/messages/{conversationId}` | list sends no default query; optional cursor only (`?cursor=...`). `pageSize`/`sortBy`/`sortDirection` defaults removed due deployed Chat validation drift | local `ListConversationsResponse`, `ConversationDetail`, `ChatMessage[]` | `resource/oas/chat.yaml` | `frontend/packages/api/src/out/chat-types.ts#paths["/librechat/api/{orgSlug}/convos"]`, `#paths["/librechat/api/{orgSlug}/convos/{conversationId}"]`, `#paths["/librechat/api/{orgSlug}/messages/{conversationId}"]` | `legacy-generated` | N/A | `keep` | owner=`chat backend`; rationale=`PROD rejects CLI default pageSize/sort query while no-query and cursor-only read path are safe`; removal condition=`chat deployed contract publishes and accepts explicit pagination query for public CLI`; incorporation plan=`reintroduce explicit pagination only after OAS/source/deployed validation align` | N/A | updated `src/core/api.test.ts`, existing `commands/chat/chat.test.ts`; covers default no-query and cursor-only URL |
|
|
58
|
-
| P0-DRIVE-01 | drive | `aipctl drive list`, `download`, `delete`, `mkdir`, `rename`, `usage` | `listDriveEntries`, `getDriveDownloadUrl`, `deleteDriveEntries`, `createDriveFolder`, `renameDriveEntry`, `getDriveUsage`, `downloadFromUrl` | api + external | `GET`, `POST`, `POST`, `POST`, `PATCH`, `GET`, external `GET` | `/drive/entries?count=200
|
|
58
|
+
| P0-DRIVE-01 | drive | `aipctl drive list`, `download`, `delete`, `mkdir`, `rename`, `usage` | `listDriveEntries`, `getDriveDownloadUrl`, `deleteDriveEntries`, `createDriveFolder`, `renameDriveEntry`, `getDriveUsage`, `downloadFromUrl` | api + external | `GET`, `POST`, `POST`, `POST`, `PATCH`, `GET`, external `GET` | CLI-managed basic CRUD: `/api/cli/v1/organizations/{organizationSlug}/drive/entries?count=200`, `/drive/entries/delete`, `/drive/folders`, `/drive/entries/{entryId}`, `/drive/usage`; download/upload remain Web/presigned | official list `{ path, hasNext, nextCursor, items }`; delete body `{ entryIds[] }`; mkdir optional `parentId`; rename body `{ newName }`; download body `{ entryIds: [id] }` | official drive list/download DTOs + external file buffer | `resource/oas/modules/backend/cli/openapi.yaml` → `v1_drive_*.yaml` (DTO aliases to organization Storage OAS); download/upload remain `resource/oas/modules/backend/organization/storage/openapi.yaml` | `backend/api/.../cli/generated/api/CliDriveApi.kt`; domain DTOs remain `com.querypie.duplo.api.drive.controller.generated.model.*` | `generated-ready` | `P0` | `migrate` | none; `CliDriveApiController` delegates membership, capacity and audit owner | `AI-6344` | `src/core/api.test.ts`, `CliSkillDriveApiControllerTest`, Gateway registry/contract parity; production CRUD/usage and local 403/404 checks (401/429 remain common gates) |
|
|
59
59
|
| P0-DRIVE-02 | drive | `aipctl drive upload` | `createDriveUploadUrl` → `uploadToS3` → `completeDriveUpload` | api + external | `POST` → `PUT` → `POST` | `/drive/entries/upload-url`; external presigned `uploadUrl`; `/drive/entries/{entryId}/complete` | official upload request `{ parentId: null, filename, fileSize, mimeType }` | official `CreateDriveUploadUrlResponse { id, filename, uploadUrl, headers }` then `void` | `resource/oas/modules/backend/organization/storage/openapi.yaml` | `frontend/packages/api/src/out/modules/organization-storage-types.ts#paths["/api/web/organizations/slug/{organizationSlug}/drive/entries/upload-url"]`, `#paths["/api/web/organizations/slug/{organizationSlug}/drive/entries/{entryId}/complete"]` | `generated-ready` | `P0` | `migrate` | none | `AIP-PUB-05` | updated `src/core/api.test.ts`, `commands/drive/drive.test.ts`; covers `parentId: null` request and response `id`/`filename` usage |
|
|
60
60
|
| P1-INT-01 | integration | `aipctl integration list`, `test`; `aipctl admin integration get`, `update`, `delete`, `tools`, `available` | `listIntegrations`, `testIntegration`, `getIntegration`, `updateIntegration`, `deleteIntegration`, `listIntegrationTools`, `listConfigurableIntegrations` | api | `GET`, `POST`, `GET`, `PUT`, `DELETE`, `GET`, `GET` | `/api/web/integrations/v2`; `/api/web/integration/{integrationId}/test`; `/api/web/admin/organizations/slug/{organizationSlug}/integrations/{integrationId}`; `/{integrationId}/tools`; `/configurable-integrations` | top-level list/test and admin detail/available now follow current/legacy OAS path+body+DTO where available; admin update/delete still accept untyped legacy mutation body/path until admin mutation contract lands | local `Integration`, `IntegrationDetail`, `IntegrationToolsResponse`, `ConfigurableIntegration[]` | legacy admin paths: `resource/oas/duplo-web.yaml`; partial modern source: `resource/oas/modules/backend/integration/openapi.yaml` (does not cover these admin list/CRUD/tools paths) | legacy `frontend/packages/api/src/out/user-types.ts#paths["/api/web/admin/organizations/slug/{organizationSlug}/integrations"]`, `#paths["/api/web/admin/organizations/slug/{organizationSlug}/configurable-integrations"]`; partial current `frontend/packages/api/src/out/modules/integration-types.ts` lacks these admin list/CRUD/tools paths | `legacy-generated` | `P1` | `legacy-exception` | owner=`backend app Integrations / duplo-web legacy OAS`; rationale=`public beta keeps integration list/test/admin detail/tools/available, but admin update/delete still lack an approved current contract outside legacy duplo-web`; removal condition=`independent contract covers user list/test plus admin CRUD/tools/available`; incorporation plan=`extend integration module or independent contract for list/test/admin CRUD/tools/available, then retire legacy path/body mappings and delete/update exception` | N/A | updated `src/core/api.test.ts`, `commands/integration/integration.test.ts`; covers v2 list query, test body `{ organizationSlug }`, admin detail/tools DTO fields, configurable wrapper unwrap, and pinned update/delete legacy paths |
|
|
61
61
|
| P0-MODEL-01 | model | `aipctl model list` | `listModels` | chat | `GET` | `/api/cli/v1/organizations/{orgSlug}/models` | none | `{ models: string[], defaultModel? }` is mapped into `Model[]` and preserves active standard, custom/BYOK, and `etc` catalog IDs | code-first OAS: `chat/packages/chat/src/modules/cli-model-exec/interface/cli-model-exec-v1.interface.controller.ts` | runtime Swagger contract; the existing Web model endpoint remains an independent compatibility reference | `oas-source-only` | `P0` | `migrate` | owner=`Chat CliModelExecV1InterfaceController/ModelInternalService`; rationale=`the dedicated route reuses the existing organization-authorized model domain catalog instead of the narrowed model-exec SharedModel catalog`; removal condition=`none for the CLI route; Web migration is a separate work item`; incorporation plan=`keep the CLI path and capability/registry parity tests aligned with the code-first Chat contract` | `AIP-PUB-05` | `src/core/api.test.ts` verifies the dedicated path, production capability gate, default mapping, and preservation of custom/BYOK and `etc` IDs; Chat service/controller tests verify domain delegation and Swagger extensions |
|
|
@@ -68,15 +68,18 @@
|
|
|
68
68
|
|
|
69
69
|
## 공통 CLI request quota 오류 계약
|
|
70
70
|
|
|
71
|
-
`GA-DIRECT` 업무 호출과 `GET /api/cli/v1/capabilities`는 Gateway request-rate admission을 통과한다. Gateway-owned source 계약은 `resource/oas/modules/backend-gateway/me/components/schemas/CliQuotaErrorResponse.yaml`과 `CliQuotaErrorDetails.yaml`이다.
|
|
71
|
+
`GA-DIRECT` 업무 호출과 명시적 discovery/진단용 `GET /api/cli/v1/capabilities`는 각각 Gateway request-rate admission을 통과한다. production CLI는 업무마다 capability를 선조회하지 않는다. 로컬 release manifest는 artifact에 없는 명령을 차단하고, 실제 업무 endpoint의 Gateway registry가 최신 server release/rollout/quota를 authoritative하게 검사한다. Gateway-owned source 계약은 `resource/oas/modules/backend-gateway/me/components/schemas/CliQuotaErrorResponse.yaml`과 `CliQuotaErrorDetails.yaml`이다.
|
|
72
72
|
|
|
73
73
|
| HTTP | code | CLI 처리 |
|
|
74
74
|
| --- | --- | --- |
|
|
75
75
|
| 429 | `CLI_QUOTA_EXCEEDED` | `limitKind=request_rate`, quota class, denying scope, request ID를 보존한다. 양수 refill로 계산 가능한 경우에만 `Retry-After`, `resetAt`을 보존한다. 자동 retry는 하지 않는다. |
|
|
76
76
|
| 503 | `CLI_QUOTA_POLICY_UNAVAILABLE` | Backend effective-policy auth/timeout/schema/freshness 실패. stale/default policy로 대체하거나 자동 retry하지 않는다. |
|
|
77
77
|
| 503 | `CLI_QUOTA_LIMITER_UNAVAILABLE` | Redis timeout/script/result 실패. 유료·mutation 요청을 자동 retry하지 않는다. |
|
|
78
|
+
| 429 | `CLI_TEXT_DAILY_LIMIT` | `limitKind=daily`, `quotaClass=text-execution`, 사용자 scope와 request ID를 보존한다. 유효한 UTC reset 시각과 그 시각에서 계산한 retry만 노출하며 자동 retry하지 않는다. |
|
|
79
|
+
| 429 | `CLI_TEXT_USER_CONCURRENCY_LIMIT` | `limitKind=concurrent`, `quotaClass=text-execution`, 사용자 scope와 request ID만 보존한다. permit 해제 시각을 알 수 없으므로 `Retry-After`와 `resetAt`을 만들거나 전달하지 않는다. |
|
|
80
|
+
| 429 | `CLI_TEXT_ORGANIZATION_CONCURRENCY_LIMIT` | `limitKind=concurrent`, `quotaClass=text-execution`, 조직 scope와 request ID만 보존한다. permit 해제 시각을 알 수 없으므로 `Retry-After`와 `resetAt`을 만들거나 전달하지 않는다. |
|
|
78
81
|
|
|
79
|
-
CLI `ApiError`는 위
|
|
82
|
+
CLI `ApiError`는 위 여섯 code에서 allowlist된 quota detail만 보존하며 서버가 추가로 보낸 조직/사용자 ID, raw policy, Redis key는 노출하지 않는다. Gateway는 `code`, Chat은 `errorCode`를 사용하지만 CLI에서 같은 진단 구조로 정규화한다. 회귀 테스트는 `src/core/api.test.ts`, Chat `cli-text-execution.internal.service.spec.ts`, Gateway `test/cli/quota/**`에 있다.
|
|
80
83
|
|
|
81
84
|
## Queue IDs for follow-up
|
|
82
85
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "aipctl",
|
|
3
|
-
"version": "2026.9.
|
|
3
|
+
"version": "2026.9.10",
|
|
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": "347543a4b224c8b9c8ff935b76027e974cb8b4fe60194c8fa521914f08fd4547",
|
|
26
|
+
"wrapperHash": "78654f7e6577f5ff63efac889f31483bdd5bcd6f34f474784fd356a89dc46bdf",
|
|
27
27
|
"nativeHash": "006b08c3e391f4571d9b7c0f12d684fe2448106259e7e0581b10f9be362452e9"
|
|
28
28
|
},
|
|
29
29
|
"optionalDependencies": {
|