aipctl 2026.10.1 → 2026.10.3

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 CHANGED
@@ -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.10.1".length > 0 ? "2026.10.1" : "0.0.0";
89673
+ const VERSION = "2026.10.3".length > 0 ? "2026.10.3" : "0.0.0";
89674
89674
  const BUILD_ENV = injectedBuildEnv;
89675
89675
  const INCLUDE_NATIVE_LOGS = BUILD_ENV !== "prod";
89676
89676
 
@@ -89732,6 +89732,27 @@ const isNativeCommandEnabled = (command, includeLogs = INCLUDE_NATIVE_LOGS) => {
89732
89732
  const FORCED_ARGS_SEPARATOR = "--";
89733
89733
  const NATIVE_ROOT_COMMANDS = new Set(nativeCommandNames);
89734
89734
  const trailingOptionSpecs = [
89735
+ ...["list", "get", "create", "update", "rename", "delete", "set-default", "unset-default"].map((command) => ({
89736
+ command: ["admin", "preset", command],
89737
+ booleanOptions: new Set(command === "delete" ? ["--force", "-f"] : ["list", "get"].includes(command) ? ["--json"] : []),
89738
+ valueOptions: /* @__PURE__ */ new Set(["--org", ...command === "list" ? ["--page", "--pageSize"] : []]),
89739
+ explicitBooleanValues: true,
89740
+ booleanAliases: { "-f": "--force" }
89741
+ })),
89742
+ ...["invite", "remove-member", "update-member-role"].map((command) => ({
89743
+ command: ["admin", "org", command],
89744
+ booleanOptions: new Set(command === "remove-member" ? ["--force", "-f"] : []),
89745
+ valueOptions: /* @__PURE__ */ new Set(["--org", ...command !== "remove-member" ? ["--role"] : []]),
89746
+ explicitBooleanValues: true,
89747
+ booleanAliases: { "-f": "--force" }
89748
+ })),
89749
+ {
89750
+ command: ["org", "exit"],
89751
+ booleanOptions: /* @__PURE__ */ new Set(["--force", "-f"]),
89752
+ valueOptions: /* @__PURE__ */ new Set(["--org"]),
89753
+ explicitBooleanValues: true,
89754
+ booleanAliases: { "-f": "--force" }
89755
+ },
89735
89756
  ...["list", "get"].map((command) => ({
89736
89757
  command: ["automation", command],
89737
89758
  booleanOptions: /* @__PURE__ */ new Set(["--json"]),
@@ -89878,7 +89899,27 @@ const implementedCommandOperationIds = /* @__PURE__ */ new Set([
89878
89899
  "createCliAutomation",
89879
89900
  "updateCliAutomation",
89880
89901
  "deleteCliAutomation",
89881
- "updateCliAutomationStatus"
89902
+ "updateCliAutomationStatus",
89903
+ "getCliCreditUsage",
89904
+ "listCliTopUsers",
89905
+ "getCliDailyUsageGraph",
89906
+ "listCliDailyUsers",
89907
+ "listCliTopMcpTools",
89908
+ "listCliAuditLogs",
89909
+ "listCliAuditEventTypes",
89910
+ "listCliPresets",
89911
+ "getCliPreset",
89912
+ "createCliPreset",
89913
+ "updateCliPreset",
89914
+ "updateCliPresetName",
89915
+ "deleteCliPreset",
89916
+ "updateCliDefaultPreset",
89917
+ "deleteCliDefaultPreset",
89918
+ "createCliOrganizationMemberInvitations",
89919
+ "deleteCliOrganizationMembers",
89920
+ "updateCliOrganizationMemberRoles",
89921
+ "deleteCliOrganizationMembership",
89922
+ "getCliTunnelStatus"
89882
89923
  ]);
89883
89924
  const releaseEnabledCommandOperationIds = /* @__PURE__ */ new Set([
89884
89925
  "listCliAgents",
@@ -89928,7 +89969,27 @@ const releaseEnabledCommandOperationIds = /* @__PURE__ */ new Set([
89928
89969
  "createCliAutomation",
89929
89970
  "updateCliAutomation",
89930
89971
  "deleteCliAutomation",
89931
- "updateCliAutomationStatus"
89972
+ "updateCliAutomationStatus",
89973
+ "getCliCreditUsage",
89974
+ "listCliTopUsers",
89975
+ "getCliDailyUsageGraph",
89976
+ "listCliDailyUsers",
89977
+ "listCliTopMcpTools",
89978
+ "listCliAuditLogs",
89979
+ "listCliAuditEventTypes",
89980
+ "listCliPresets",
89981
+ "getCliPreset",
89982
+ "createCliPreset",
89983
+ "updateCliPreset",
89984
+ "updateCliPresetName",
89985
+ "deleteCliPreset",
89986
+ "updateCliDefaultPreset",
89987
+ "deleteCliDefaultPreset",
89988
+ "createCliOrganizationMemberInvitations",
89989
+ "deleteCliOrganizationMembers",
89990
+ "updateCliOrganizationMemberRoles",
89991
+ "deleteCliOrganizationMembership",
89992
+ "getCliTunnelStatus"
89932
89993
  ]);
89933
89994
  const direct = (commands, operation) => commands.map((command) => ({
89934
89995
  command,
@@ -94934,6 +94995,14 @@ const makeApiServiceLive = (buildEnv) => effect$1(
94934
94995
  });
94935
94996
  const requireApiBaseUrlEffect = () => requireConfiguredBaseUrlEffect(loadConfiguredApiBaseUrl);
94936
94997
  const requireChatBaseUrlEffect = () => requireConfiguredBaseUrlEffect(loadConfiguredChatBaseUrl);
94998
+ const presetPath = (presetId, orgSlug) => try_({
94999
+ try: () => {
95000
+ const slug = orgSlug ?? configService.load().currentOrganization?.slug;
95001
+ if (!slug) throw new Error("No organization selected. Use --org or select an organization.");
95002
+ return `/api/cli/v1/organizations/${encodeURIComponent(slug)}/admin/presets/${encodeURIComponent(presetId)}`;
95003
+ },
95004
+ catch: configuredBaseUrlError
95005
+ });
94937
95006
  const toRefreshFailure = (error) => {
94938
95007
  if (error instanceof ApiError || error instanceof NotLoggedInError) {
94939
95008
  return error;
@@ -95522,57 +95591,64 @@ const makeApiServiceLive = (buildEnv) => effect$1(
95522
95591
  }),
95523
95592
  getCreditStatistics: (orgSlug, options) => gen(function* () {
95524
95593
  const token = yield* getAccessToken();
95594
+ yield* requireReleaseEnabledOperation("getCliCreditUsage");
95525
95595
  const params = new URLSearchParams();
95526
95596
  params.set("startDt", options.startDt);
95527
95597
  params.set("endDt", options.endDt);
95528
- const path = `/api/web/admin/organizations/slug/${encodeURIComponent(orgSlug)}/usage/credit/statistics?${params.toString()}`;
95598
+ const path = `/api/cli/v1/organizations/${encodeURIComponent(orgSlug)}/admin/usage/credit?${params.toString()}`;
95529
95599
  return yield* makeRequest(baseUrl, path, token);
95530
95600
  }),
95531
95601
  getCreditTopUsers: (orgSlug, options) => gen(function* () {
95532
95602
  const token = yield* getAccessToken();
95603
+ yield* requireReleaseEnabledOperation("listCliTopUsers");
95533
95604
  const params = new URLSearchParams();
95534
95605
  params.set("startDt", options.startDt);
95535
95606
  params.set("endDt", options.endDt);
95536
95607
  params.set("limit", String(options.limit));
95537
- const path = `/api/web/admin/organizations/slug/${encodeURIComponent(orgSlug)}/usage/credit/top-users?${params.toString()}`;
95608
+ const path = `/api/cli/v1/organizations/${encodeURIComponent(orgSlug)}/admin/usage/top-users?${params.toString()}`;
95538
95609
  return yield* makeRequest(baseUrl, path, token);
95539
95610
  }),
95540
95611
  getCreditDailyGraph: (orgSlug, options) => gen(function* () {
95541
95612
  const token = yield* getAccessToken();
95613
+ yield* requireReleaseEnabledOperation("getCliDailyUsageGraph");
95542
95614
  const params = new URLSearchParams();
95543
95615
  params.set("startDt", options.startDt);
95544
95616
  params.set("endDt", options.endDt);
95545
- const path = `/api/web/admin/organizations/slug/${encodeURIComponent(orgSlug)}/usage/credit/daily-graph?${params.toString()}`;
95617
+ const path = `/api/cli/v1/organizations/${encodeURIComponent(orgSlug)}/admin/usage/daily-graph?${params.toString()}`;
95546
95618
  return yield* makeRequest(baseUrl, path, token);
95547
95619
  }),
95548
95620
  getCreditDailyUsers: (orgSlug, options) => gen(function* () {
95549
95621
  const token = yield* getAccessToken();
95622
+ yield* requireReleaseEnabledOperation("listCliDailyUsers");
95550
95623
  const params = new URLSearchParams();
95551
95624
  params.set("startDt", options.startDt);
95552
95625
  params.set("endDt", options.endDt);
95553
95626
  params.set("pageNumber", String(options.pageNumber ?? 1));
95554
95627
  params.set("pageSize", String(options.pageSize ?? 20));
95555
95628
  if (options.userId) params.set("userId", options.userId);
95556
- const path = `/api/web/admin/organizations/slug/${encodeURIComponent(orgSlug)}/usage/credit/daily-users?${params.toString()}`;
95629
+ const path = `/api/cli/v1/organizations/${encodeURIComponent(orgSlug)}/admin/usage/daily-users?${params.toString()}`;
95557
95630
  return yield* makeRequest(baseUrl, path, token);
95558
95631
  }),
95559
95632
  getMcpTopTools: (orgSlug, options) => gen(function* () {
95560
95633
  const token = yield* getAccessToken();
95634
+ yield* requireReleaseEnabledOperation("listCliTopMcpTools");
95561
95635
  const params = new URLSearchParams();
95562
95636
  params.set("startDt", options.startDt);
95563
95637
  params.set("endDt", options.endDt);
95564
95638
  params.set("limit", String(options.limit));
95565
- const path = `/api/web/admin/organizations/slug/${encodeURIComponent(orgSlug)}/usage/mcp/top?${params.toString()}`;
95639
+ const path = `/api/cli/v1/organizations/${encodeURIComponent(orgSlug)}/admin/usage/mcp-top?${params.toString()}`;
95566
95640
  return yield* makeRequest(baseUrl, path, token);
95567
95641
  }),
95568
95642
  listAuditLogs: (orgSlug, options) => gen(function* () {
95569
95643
  const token = yield* getAccessToken();
95644
+ yield* requireReleaseEnabledOperation("listCliAuditLogs");
95570
95645
  const params = new URLSearchParams();
95571
95646
  params.set("page", String(options?.page ?? 1));
95572
95647
  params.set("pageSize", String(options?.pageSize ?? 20));
95573
95648
  if (options?.eventType) params.set("eventType", options.eventType);
95574
- const path = `/api/web/audit/organization/slug/${encodeURIComponent(orgSlug)}?${params.toString()}`;
95575
- return yield* makeRequest(baseUrl, path, token);
95649
+ const path = `/api/cli/v1/organizations/${encodeURIComponent(orgSlug)}/admin/audit?${params.toString()}`;
95650
+ const response = yield* makeRequest(baseUrl, path, token);
95651
+ return { ...response, pagination: normalizePageNumberPagination(response.pagination, response.list.length) };
95576
95652
  }),
95577
95653
  // Phase 5: Drive/Integration
95578
95654
  listDriveEntries: (orgSlug) => gen(function* () {
@@ -95866,9 +95942,11 @@ const makeApiServiceLive = (buildEnv) => effect$1(
95866
95942
  return yield* makeRequest(baseUrl, path, token);
95867
95943
  }),
95868
95944
  // Audit event types
95869
- listAuditEventTypes: () => gen(function* () {
95945
+ listAuditEventTypes: (orgSlug) => gen(function* () {
95870
95946
  const token = yield* getAccessToken();
95871
- return yield* makeRequest(baseUrl, "/api/web/audit/event/types", token);
95947
+ yield* requireReleaseEnabledOperation("listCliAuditEventTypes");
95948
+ const path = `/api/cli/v1/organizations/${encodeURIComponent(orgSlug)}/admin/audit/types`;
95949
+ return yield* makeRequest(baseUrl, path, token);
95872
95950
  }),
95873
95951
  // Org capabilities & user settings
95874
95952
  getOrgCapabilities: (orgSlug) => gen(function* () {
@@ -95885,7 +95963,8 @@ const makeApiServiceLive = (buildEnv) => effect$1(
95885
95963
  // Tunnel management
95886
95964
  getTunnelStatus: (orgSlug) => gen(function* () {
95887
95965
  const token = yield* getAccessToken();
95888
- const path = `/api/web/edge-tunnel/v2/organizations/slug/${encodeURIComponent(orgSlug)}/status`;
95966
+ yield* requireReleaseEnabledOperation("getCliTunnelStatus");
95967
+ const path = `/api/cli/v1/organizations/${encodeURIComponent(orgSlug)}/admin/tunnel/status`;
95889
95968
  return yield* makeRequest(baseUrl, path, token);
95890
95969
  }),
95891
95970
  getTunnelConfig: (orgSlug) => gen(function* () {
@@ -95899,49 +95978,60 @@ const makeApiServiceLive = (buildEnv) => effect$1(
95899
95978
  return yield* makeRequest(baseUrl, path, token, { method: "POST" });
95900
95979
  }),
95901
95980
  // Preset management
95902
- listPresets: (orgSlug) => gen(function* () {
95981
+ listPresets: (orgSlug, page = 1, pageSize = 100) => gen(function* () {
95903
95982
  const token = yield* getAccessToken();
95904
- const path = `/api/web/presets/v2?organizationSlug=${encodeURIComponent(orgSlug)}`;
95905
- return yield* makeRequest(baseUrl, path, token);
95983
+ yield* requireReleaseEnabledOperation("listCliPresets");
95984
+ const path = `/api/cli/v1/organizations/${encodeURIComponent(orgSlug)}/admin/presets?page=${page}&pageSize=${pageSize}`;
95985
+ const response = yield* makeRequest(baseUrl, path, token);
95986
+ return response.list;
95906
95987
  }),
95907
- getPreset: (presetId) => gen(function* () {
95988
+ getPreset: (presetId, orgSlug) => gen(function* () {
95908
95989
  const token = yield* getAccessToken();
95909
- const path = `/api/web/presets/${encodeURIComponent(presetId)}`;
95990
+ yield* requireReleaseEnabledOperation("getCliPreset");
95991
+ const path = yield* presetPath(presetId, orgSlug);
95910
95992
  return yield* makeRequest(baseUrl, path, token);
95911
95993
  }),
95912
95994
  createPreset: (body) => gen(function* () {
95913
95995
  const token = yield* getAccessToken();
95914
- return yield* makeRequest(baseUrl, "/api/web/presets/v2", token, {
95996
+ yield* requireReleaseEnabledOperation("createCliPreset");
95997
+ const { organizationSlug, ...request } = body;
95998
+ const path = `/api/cli/v1/organizations/${encodeURIComponent(organizationSlug)}/admin/presets`;
95999
+ return yield* makeRequest(baseUrl, path, token, {
95915
96000
  method: "POST",
95916
- body
96001
+ body: request
95917
96002
  });
95918
96003
  }),
95919
- updatePreset: (presetId, body) => gen(function* () {
96004
+ updatePreset: (presetId, body, orgSlug) => gen(function* () {
95920
96005
  const token = yield* getAccessToken();
95921
- const path = `/api/web/presets/${encodeURIComponent(presetId)}`;
96006
+ yield* requireReleaseEnabledOperation("updateCliPreset");
96007
+ const path = yield* presetPath(presetId, orgSlug);
95922
96008
  return yield* makeRequest(baseUrl, path, token, { method: "PUT", body });
95923
96009
  }),
95924
- renamePreset: (presetId, name) => gen(function* () {
96010
+ renamePreset: (presetId, name, orgSlug) => gen(function* () {
95925
96011
  const token = yield* getAccessToken();
95926
- const path = `/api/web/presets/${encodeURIComponent(presetId)}`;
96012
+ yield* requireReleaseEnabledOperation("updateCliPresetName");
96013
+ const path = yield* presetPath(presetId, orgSlug);
95927
96014
  return yield* makeRequest(baseUrl, path, token, {
95928
96015
  method: "PATCH",
95929
96016
  body: { name }
95930
96017
  });
95931
96018
  }),
95932
- deletePreset: (presetId) => gen(function* () {
96019
+ deletePreset: (presetId, orgSlug) => gen(function* () {
95933
96020
  const token = yield* getAccessToken();
95934
- const path = `/api/web/presets/${encodeURIComponent(presetId)}`;
96021
+ yield* requireReleaseEnabledOperation("deleteCliPreset");
96022
+ const path = yield* presetPath(presetId, orgSlug);
95935
96023
  return yield* makeRequest(baseUrl, path, token, { method: "DELETE", skipJsonParse: true });
95936
96024
  }),
95937
- setPresetAsDefault: (presetId) => gen(function* () {
96025
+ setPresetAsDefault: (presetId, orgSlug) => gen(function* () {
95938
96026
  const token = yield* getAccessToken();
95939
- const path = `/api/web/presets/${encodeURIComponent(presetId)}/default`;
95940
- return yield* makeRequest(baseUrl, path, token, { method: "POST" });
96027
+ yield* requireReleaseEnabledOperation("updateCliDefaultPreset");
96028
+ const path = `${yield* presetPath(presetId, orgSlug)}/default`;
96029
+ return yield* makeRequest(baseUrl, path, token, { method: "PUT" });
95941
96030
  }),
95942
- unsetPresetAsDefault: (presetId) => gen(function* () {
96031
+ unsetPresetAsDefault: (presetId, orgSlug) => gen(function* () {
95943
96032
  const token = yield* getAccessToken();
95944
- const path = `/api/web/presets/${encodeURIComponent(presetId)}/default`;
96033
+ yield* requireReleaseEnabledOperation("deleteCliDefaultPreset");
96034
+ const path = `${yield* presetPath(presetId, orgSlug)}/default`;
95945
96035
  return yield* makeRequest(baseUrl, path, token, { method: "DELETE" });
95946
96036
  }),
95947
96037
  regenPresetKey: (presetId) => gen(function* () {
@@ -95957,29 +96047,33 @@ const makeApiServiceLive = (buildEnv) => effect$1(
95957
96047
  // Org member management
95958
96048
  inviteOrgMembers: (req) => gen(function* () {
95959
96049
  const token = yield* getAccessToken();
95960
- return yield* makeRequest(baseUrl, `/api/web/organizations/slug/${encodeURIComponent(req.organizationSlug)}/invite`, token, {
96050
+ yield* requireReleaseEnabledOperation("createCliOrganizationMemberInvitations");
96051
+ return yield* makeRequest(baseUrl, `/api/cli/v1/organizations/${encodeURIComponent(req.organizationSlug)}/members/invitations`, token, {
95961
96052
  method: "POST",
95962
96053
  body: { emails: req.emails, role: req.role }
95963
96054
  });
95964
96055
  }),
95965
96056
  removeOrgMembers: (req) => gen(function* () {
95966
96057
  const token = yield* getAccessToken();
95967
- yield* makeRequest(baseUrl, `/api/web/organizations/slug/${encodeURIComponent(req.organizationSlug)}/members`, token, {
96058
+ yield* requireReleaseEnabledOperation("deleteCliOrganizationMembers");
96059
+ yield* makeRequest(baseUrl, `/api/cli/v1/organizations/${encodeURIComponent(req.organizationSlug)}/members`, token, {
95968
96060
  method: "DELETE",
95969
96061
  body: { members: req.members }
95970
96062
  });
95971
96063
  }),
95972
96064
  updateOrgMemberRoles: (req) => gen(function* () {
95973
96065
  const token = yield* getAccessToken();
95974
- yield* makeRequest(baseUrl, `/api/web/organizations/slug/${encodeURIComponent(req.organizationSlug)}/members`, token, {
96066
+ yield* requireReleaseEnabledOperation("updateCliOrganizationMemberRoles");
96067
+ yield* makeRequest(baseUrl, `/api/cli/v1/organizations/${encodeURIComponent(req.organizationSlug)}/members/role`, token, {
95975
96068
  method: "PUT",
95976
96069
  body: { members: req.members, role: req.role }
95977
96070
  });
95978
96071
  }),
95979
96072
  exitOrg: (slug) => gen(function* () {
95980
96073
  const token = yield* getAccessToken();
95981
- yield* makeRequest(baseUrl, `/api/web/organizations/slug/${encodeURIComponent(slug)}/exit`, token, {
95982
- method: "POST"
96074
+ yield* requireReleaseEnabledOperation("deleteCliOrganizationMembership");
96075
+ yield* makeRequest(baseUrl, `/api/cli/v1/organizations/${encodeURIComponent(slug)}/membership`, token, {
96076
+ method: "DELETE"
95983
96077
  });
95984
96078
  }),
95985
96079
  // Agent headless chat
@@ -96390,10 +96484,11 @@ const listCommand$a = make$4(
96390
96484
 
96391
96485
  const typesCommand = make$4(
96392
96486
  "types",
96393
- {},
96394
- () => gen(function* () {
96487
+ { org: orgOption },
96488
+ ({ org }) => gen(function* () {
96395
96489
  const api = yield* ApiService;
96396
- const eventTypes = yield* api.listAuditEventTypes().pipe(
96490
+ const orgSlug = yield* resolveOrgSlug(org, api);
96491
+ const eventTypes = yield* api.listAuditEventTypes(orgSlug).pipe(
96397
96492
  catchTag(
96398
96493
  "NotLoggedInError",
96399
96494
  (e) => gen(function* () {
@@ -96935,13 +97030,13 @@ const deleteCommand$4 = make$4(
96935
97030
  { id: idArg$7, org: orgOption, force: forceOption$5 },
96936
97031
  ({ id, org, force }) => gen(function* () {
96937
97032
  const api = yield* ApiService;
96938
- yield* resolveOrgSlug(org, api);
97033
+ const orgSlug = yield* resolveOrgSlug(org, api);
96939
97034
  if (!force) {
96940
97035
  yield* log(`Warning: This will permanently delete preset "${id}".`);
96941
97036
  yield* log("Use --force (-f) to skip this confirmation.");
96942
97037
  return;
96943
97038
  }
96944
- yield* api.deletePreset(id).pipe(
97039
+ yield* api.deletePreset(id, orgSlug).pipe(
96945
97040
  catchTag(
96946
97041
  "NotLoggedInError",
96947
97042
  (e) => gen(function* () {
@@ -96974,8 +97069,8 @@ const getCommand$6 = make$4(
96974
97069
  { id: idArg$6, org: orgOption, json: jsonOption$h },
96975
97070
  ({ id, org, json }) => gen(function* () {
96976
97071
  const api = yield* ApiService;
96977
- yield* resolveOrgSlug(org, api);
96978
- const preset = yield* api.getPreset(id).pipe(
97072
+ const orgSlug = yield* resolveOrgSlug(org, api);
97073
+ const preset = yield* api.getPreset(id, orgSlug).pipe(
96979
97074
  catchTag(
96980
97075
  "NotLoggedInError",
96981
97076
  (e) => gen(function* () {
@@ -97030,11 +97125,19 @@ function formatPresetListPrompt(prompt) {
97030
97125
  }
97031
97126
  const listCommand$9 = make$4(
97032
97127
  "list",
97033
- { org: orgOption, json: jsonOption$g },
97034
- ({ org, json }) => gen(function* () {
97128
+ {
97129
+ org: orgOption,
97130
+ json: jsonOption$g,
97131
+ page: integer("page").pipe(withDescription$3("Page number, starting at 1"), withDefault(1)),
97132
+ pageSize: integer("pageSize").pipe(withDescription$3("Presets per page (1\u2013100)"), withDefault(100))
97133
+ },
97134
+ ({ org, json, page, pageSize }) => gen(function* () {
97135
+ if (page < 1 || pageSize < 1 || pageSize > 100) {
97136
+ return yield* fail$3(new ApiError({ message: "Use --page 1 or higher and --pageSize between 1 and 100." }));
97137
+ }
97035
97138
  const api = yield* ApiService;
97036
97139
  const orgSlug = yield* resolveOrgSlug(org, api);
97037
- const result = yield* api.listPresets(orgSlug).pipe(
97140
+ const result = yield* api.listPresets(orgSlug, page, pageSize).pipe(
97038
97141
  catchTag(
97039
97142
  "NotLoggedInError",
97040
97143
  (e) => gen(function* () {
@@ -97055,10 +97158,10 @@ const listCommand$9 = make$4(
97055
97158
  return;
97056
97159
  }
97057
97160
  if (result.length === 0) {
97058
- yield* log("No presets found.");
97161
+ yield* log(`No presets found on page ${page}.`);
97059
97162
  return;
97060
97163
  }
97061
- yield* log(`Presets in organization "${orgSlug}":
97164
+ yield* log(`Presets in organization "${orgSlug}" (page ${page}):
97062
97165
  `);
97063
97166
  for (const preset of result) {
97064
97167
  const defaultMark = preset.isDefault ? " (default)" : "";
@@ -97134,8 +97237,8 @@ const renameCommand$1 = make$4(
97134
97237
  { id: idArg$3, name: nameArg$1, org: orgOption },
97135
97238
  ({ id, name, org }) => gen(function* () {
97136
97239
  const api = yield* ApiService;
97137
- yield* resolveOrgSlug(org, api);
97138
- yield* api.renamePreset(id, name).pipe(
97240
+ const orgSlug = yield* resolveOrgSlug(org, api);
97241
+ yield* api.renamePreset(id, name, orgSlug).pipe(
97139
97242
  catchTag(
97140
97243
  "NotLoggedInError",
97141
97244
  (e) => gen(function* () {
@@ -97161,8 +97264,8 @@ const setDefaultCommand = make$4(
97161
97264
  { id: idArg$2, org: orgOption },
97162
97265
  ({ id, org }) => gen(function* () {
97163
97266
  const api = yield* ApiService;
97164
- yield* resolveOrgSlug(org, api);
97165
- yield* api.setPresetAsDefault(id).pipe(
97267
+ const orgSlug = yield* resolveOrgSlug(org, api);
97268
+ yield* api.setPresetAsDefault(id, orgSlug).pipe(
97166
97269
  catchTag(
97167
97270
  "NotLoggedInError",
97168
97271
  (e) => gen(function* () {
@@ -97188,8 +97291,8 @@ const unsetDefaultCommand = make$4(
97188
97291
  { id: idArg$1, org: orgOption },
97189
97292
  ({ id, org }) => gen(function* () {
97190
97293
  const api = yield* ApiService;
97191
- yield* resolveOrgSlug(org, api);
97192
- yield* api.unsetPresetAsDefault(id).pipe(
97294
+ const orgSlug = yield* resolveOrgSlug(org, api);
97295
+ yield* api.unsetPresetAsDefault(id, orgSlug).pipe(
97193
97296
  catchTag(
97194
97297
  "NotLoggedInError",
97195
97298
  (e) => gen(function* () {
@@ -97218,7 +97321,7 @@ const updateCommand$1 = make$4(
97218
97321
  { id: idArg, jsonFile: jsonFileArg$2, org: orgOption },
97219
97322
  ({ id, jsonFile, org }) => gen(function* () {
97220
97323
  const api = yield* ApiService;
97221
- yield* resolveOrgSlug(org, api);
97324
+ const orgSlug = yield* resolveOrgSlug(org, api);
97222
97325
  const body = yield* try_({
97223
97326
  try: () => {
97224
97327
  const content = fs__namespace.readFileSync(jsonFile, "utf-8");
@@ -97233,7 +97336,7 @@ const updateCommand$1 = make$4(
97233
97336
  })
97234
97337
  )
97235
97338
  );
97236
- yield* api.updatePreset(id, body).pipe(
97339
+ yield* api.updatePreset(id, body, orgSlug).pipe(
97237
97340
  catchTag(
97238
97341
  "NotLoggedInError",
97239
97342
  (e) => gen(function* () {
@@ -40,8 +40,8 @@
40
40
  | AUTH-02 | auth | `aipctl auth refresh` | `ApiService.refreshToken` → `refreshAccessToken` → `src/core/oauth.ts#refreshOAuthToken` | api | `POST` | `/oauth2/token` | refresh token form body | refreshed local `Credentials` | not found in current `resource/oas` for `/oauth2/token` | none | `oas-missing` | N/A | `legacy-exception` | owner=`backend/api OAuth server`; rationale=`token refresh is required for session continuity but token endpoint is outside current OAS`; removal condition=`official OAuth token contract exists in resource/oas and independent generated contract`; incorporation plan=`same OAuth server contract as AUTH-01, plus refresh fixture` | `AIP-PUB-05` | existing `src/core/oauth.test.ts`, `src/core/api.test.ts`; needed token refresh path snapshot |
41
41
  | AUTH-03 | auth | `aipctl auth whoami` | `ApiService.getMe` | api | `GET` | `/api/cli/v1/me` | none | local `UserProfile` | `resource/oas/modules/backend/cli/openapi.yaml` | `backend/api/.../cli/generated/api/CliV1Api.kt#getCliMe` | `generated-ready` | N/A | `migrate` | none | N/A | `src/core/api.test.ts` verifies the dedicated path and bearer request; `commands/auth/auth.test.ts` covers command behavior |
42
42
  | ORG-01 | org | `aipctl org list`, `aipctl org use`, `aipctl org select` | `listOrganizations`, `getOrganization` | api | `GET` | `/api/cli/v1/organizations`; `use/select` resolve locally from the returned list | none | local `Organization[]` / `Organization` | `resource/oas/modules/backend/cli/openapi.yaml` | `backend/api/.../cli/generated/api/CliV1Api.kt#listCliOrganizations` | `generated-ready` | N/A | `migrate` | none | N/A | `src/core/api.test.ts`, `commands/org/org.test.ts`; covers dedicated path, local slug selection, default/IP-blocked fields |
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
- | 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 |
43
+ | ORG-02 | org | `aipctl org capabilities`, `aipctl org settings`, `aipctl org exit` | `getOrgCapabilities`, `getUserSettings`, `exitOrg` | api | `GET`, `GET`, `DELETE` | organization v1 `/api/cli/v1/organizations/{organizationSlug}/capabilities`; user-global v1 `/api/cli/v1/me/settings`; exit v1 `/api/cli/v1/organizations/{organizationSlug}/membership` | none | local `OrgCapabilities`, `UserSettings`, `void` | `resource/oas/modules/backend/cli/openapi.yaml` | `CliOrganizationApi`/`CliV1Api`; exit `deleteCliOrganizationMembership` | `generated-ready` | N/A | `migrate` | none; exit delegates existing member authorization, owner protection and audit | `AI-6344`; common error/deadline gate `AI-6378` | `src/core/api.test.ts`, `src/core/remaining-direct-contract.test.ts`, org tests, Backend controller test; actual CLI member exit/owner rejection |
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` | prefix `/api/cli/v1/organizations/{organizationSlug}`; `/members`; `/members/invitations`; `/members`; `/members/role` | `{ emails, role }` or `{ members, role? }`; 1..100 unique targets, email/userId/status checked against current membership | local `ListMembersResponse`, `InviteOrgMembersResponse`, `void` | `resource/oas/modules/backend/cli/openapi.yaml` | `backend/api/.../cli/generated/api/CliOrganizationApi.kt` | `generated-ready` | `P0` | `migrate` | none; preserves existing admin authorization, audit, pending/active/inactive semantics, skipped owner/self removal and invite partial failure; stale/missing target returns 409 before mutation | `AI-6344`; operational gates remain separate | API/command and Backend controller tests; actual CLI invite with LocalStack SES, role/remove for three statuses, non-admin 403, stale 409, owner protection, persisted audit |
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
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 |
@@ -62,10 +62,10 @@
62
62
  | 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 |
63
63
  | P1-MODEL-EXEC-01 | model-exec | `aipctl model-exec models`, `get`, `sample`, `chat` | `listModelExecModels`, `executeModelExecChat` | chat | `GET`, `POST` | `/api/cli/v1/organizations/{orgSlug}/model-exec/models`; `/chat` | local `ModelExecChatRequest`; Chat Zod/Swagger DTO source `chat/packages/chat/src/modules/cli-model-exec/interface/dto/cli-model-exec.dto.ts` | local `ModelExecModelCatalog`, `ModelExecChatResponse` | code-first OAS: `chat/packages/chat/src/modules/cli-model-exec/interface/cli-model-exec-v1.interface.controller.ts` | runtime Swagger contract | `oas-source-only` | `P1` | `migrate` | none | `AIP-PUB-05` | `src/core/api.test.ts` verifies both v1 paths; Chat controller contract test verifies operation IDs, request/response schemas, delegation to the existing service, and absence of a v1 image route |
64
64
  | P1-MODEL-EXEC-02 | model-exec-image | `aipctl model-exec image generate` | `executeModelExecImageGeneration`; output uses `downloadFromUrl` | chat + external artifact URL | `POST`, external `GET` | legacy `/api/{orgSlug}/cli/model-exec/images/generations`; response `downloadUrl` | local `ModelExecImageGenerationRequest`; Chat DTO source `chat/packages/chat/src/modules/cli-model-exec/interface/dto/cli-model-exec.dto.ts` | local `ModelExecImageGenerationResponse`; image bytes from external URL | no GA OAS; legacy controller only | none | `oas-missing` | deferred | `hide` | owner=`chat CLI Model Exec API`; rationale=`synchronous image execution, external artifact lifetime, and cost recovery require the deferred async design`; removal condition=`image job/artifact/TTL/My Drive/cost gates pass`; incorporation plan=`publish a separate v1 image job contract only after the deferred design is implemented` | follow-up image hardening | existing image request/path test remains on the legacy route; customer capability must stay disabled |
65
- | USAGE-01 | usage | `aipctl admin usage credit`, `top-users`, `daily-graph`, `daily-users`, `mcp-top` | `getCreditStatistics`, `getCreditTopUsers`, `getCreditDailyGraph`, `getCreditDailyUsers`, `getMcpTopTools` | api | `GET` | `/api/web/admin/organizations/slug/{organizationSlug}/usage/...` | query `{ startDt,endDt,limit,pageNumber,pageSize,userId }` | local usage DTOs, `DailyUsageDetailsResponse.pagination { page,pageSize,total }` | `resource/oas/modules/backend/usage/openapi.yaml` | `frontend/packages/api/src/out/modules/usage-types.ts#paths[...]` | `generated-ready` | N/A | `keep` | none | N/A | existing `commands/usage/usage.test.ts`; needed generated path snapshots |
66
- | AUDIT-01 | audit | `aipctl admin audit list`, `types` | `listAuditLogs`, `listAuditEventTypes` | api | `GET` | `/api/web/audit/organization/slug/{organizationSlug}`; `/api/web/audit/event/types` | query `{ eventType,page,pageSize }` | local `ListAuditResponse`, `AuditEventType[]` | `resource/oas/modules/backend/audit/openapi.yaml` | `frontend/packages/api/src/out/modules/backend-audit-types.ts#paths[...]` | `generated-ready` | N/A | `keep` | none | N/A | existing `commands/audit/audit.test.ts`; needed generated path snapshots |
67
- | TUNNEL-01 | tunnel | `aipctl admin tunnel status`, `config`, `token` | `getTunnelStatus`, `getTunnelConfig`, `createTunnelToken` | api | `GET`, `GET`, `POST` | `/api/web/edge-tunnel/v2/organizations/slug/{organizationSlug}/status`; `/config`; `/token` | none | local `TunnelStatus`, `TunnelConfig`, `void` | `resource/oas/modules/backend/tunnel/openapi.yaml` | `frontend/packages/api/src/out/modules/tunnel-types.ts#paths[...]` | `generated-ready` | N/A | `keep` | none | N/A | existing `commands/tunnel/tunnel.test.ts`; needed v2 path snapshot |
68
- | P1-PRESET-01 | preset | `aipctl admin preset list`, `get`, `create`, `update`, `rename`, `delete`, `set-default`, `unset-default`, `regen-key`, `regen-static-key` | `listPresets`, `getPreset`, `createPreset`, `updatePreset`, `renamePreset`, `deletePreset`, `setPresetAsDefault`, `unsetPresetAsDefault`, `regenPresetKey`, `regenPresetStaticKey` | api | `GET`, `POST`, `PUT`, `PATCH`, `DELETE` mix | `/api/web/presets/v2`; `/api/web/presets/{presetId}`; `/key`; `/static-key`; `/default` | legacy preset API kept; delete response is contract-aligned to 204 No Content and CLI treats delete as endpoint-specific void response to tolerate deployed 200 empty drift | local preset DTOs with installation/json command fields; delete returns `void` | `resource/oas/duplo-web.yaml` | `frontend/packages/api/src/out/user-types.ts#paths["/api/web/presets/v2"]`, `#paths["/api/web/presets/{presetId}"]`, `#paths["/api/web/presets/{presetId}/default"]` | `legacy-generated` | `P1` | `keep` | owner=`backend app PresetsApiController`; rationale=`runtime returned 200 empty while generated/OAS says 204, causing JSON parse false failure`; removal condition=`204 is deployed everywhere and CLI no longer needs 200-empty tolerance`; incorporation plan=`keep endpoint-specific void mode, do not add global 200-empty fallback` | N/A | updated `src/core/api.test.ts`, `commands/admin/preset/preset.test.ts`, `../docs/how-to/aip-cli-usage.md`, `backend/api/src/test/kotlin/.../PresetsApiControllerTest.kt`; covers admin namespace docs, `/v2`, `/{id}`, `/default`, `/key`, `/static-key`, delete 200-empty tolerance, and JSON endpoint 200-empty failure |
65
+ | USAGE-01 | usage | `aipctl admin usage credit`, `top-users`, `daily-graph`, `daily-users`, `mcp-top` | `getCreditStatistics`, `getCreditTopUsers`, `getCreditDailyGraph`, `getCreditDailyUsers`, `getMcpTopTools` | api | `GET` | `/api/cli/v1/organizations/{organizationSlug}/admin/usage/credit`; `/admin/usage/top-users`; `/admin/usage/daily-graph`; `/admin/usage/daily-users`; `/admin/usage/mcp-top` | query `{ startDt,endDt,limit,pageNumber,pageSize,userId }`; daily-users uses one-based page/pageSize 1..100 | existing usage DTOs; `DailyUsageDetailsResponse.pagination { page,pageSize,total }` normalized to CLI output | `resource/oas/modules/backend/cli/openapi.yaml` → `paths/v1_admin_usage_*.yaml`; response aliases reuse `resource/oas/modules/backend/usage/components/schemas/*` | `backend/api/.../cli/generated/api/CliUsageApi.kt`; domain DTOs remain `com.querypie.duplo.api.usage.generated.model.*` | `generated-ready` | `P0` | `migrate` | none; dedicated adapter preserves organization admin authorization, three-month/future-date validation, and existing aggregation service | `AI-6344`; query/page workload bounds remain `AI-6413` | `src/core/usage-audit-contract.test.ts`, usage command tests, `CliUsageAuditApiControllerTest`, Gateway registry/contract parity; real production CLI verifies all five paths, 401/403/404/400 and future-date clamp |
66
+ | AUDIT-01 | audit | `aipctl admin audit list`, `types` | `listAuditLogs`, `listAuditEventTypes` | api | `GET` | `/api/cli/v1/organizations/{organizationSlug}/admin/audit`; `/api/cli/v1/organizations/{organizationSlug}/admin/audit/types` | query `{ eventType,page,pageSize }`; page is one-based and pageSize is 1..100 | existing `ListAuditResponse`/`AuditEventType[]`; page/total is normalized for CLI pagination output | `resource/oas/modules/backend/cli/openapi.yaml` → `paths/v1_admin_audit*.yaml`; response aliases reuse `resource/oas/modules/backend/audit/components/schemas/*` | `backend/api/.../cli/generated/api/CliAuditApi.kt`; domain DTOs remain `com.querypie.duplo.api.generated.models.*` | `generated-ready` | `P0` | `migrate` | none; dedicated adapter preserves AUDIT_LOGS capability, plan/retention/viewable-period and organization filters | `AI-6344`; audit volume/query workload bounds remain `AI-6413` | `src/core/usage-audit-contract.test.ts`, `commands/admin/audit/*.test.ts`, `CliUsageAuditApiControllerTest`, Gateway registry/contract parity; real production CLI verifies page 2/3, types, 401/403/404/400 |
67
+ | TUNNEL-01 | tunnel | `aipctl admin tunnel status`; `config`/`token` remain gated | `getTunnelStatus`; candidate `getTunnelConfig`, `createTunnelToken` | api | `GET`; candidate `GET`/`POST` | status `/api/cli/v1/organizations/{organizationSlug}/admin/tunnel/status`; candidates retain Web `/config`/`/token` | none | status `{ connected: boolean }` only | status `resource/oas/modules/backend/cli/openapi.yaml`; candidates Tunnel OAS | `backend/api/.../cli/generated/api/CliTunnelApi.kt#getCliTunnelStatus` | `generated-ready` | N/A | `migrate` | none for status; existing personal Tunnel service checks current user/org; token/config secret gates remain | `AI-6344`; sensitive gate `AI-6380` | status contract/adapter/registry tests; actual CLI + Go Tunnel server disconnected/Redis session connected/user isolation, token count unchanged; actual edge handshake not verified |
68
+ | P1-PRESET-01 | preset | `aipctl admin preset list`, `get`, `create`, `update`, `rename`, `delete`, `set-default`, `unset-default`; key rotation commands remain gated | `listPresets`, `getPreset`, `createPreset`, `updatePreset`, `renamePreset`, `deletePreset`, `setPresetAsDefault`, `unsetPresetAsDefault` | api | list/get `GET`; create `POST`; update/default set `PUT`; rename `PATCH`; delete/default unset `DELETE` | `/api/cli/v1/organizations/{organizationSlug}/admin/presets`; `/{presetId}`; `/{presetId}/default` | bounded one-based page/pageSize 1..100; default pageSize 100; existing basic mutation bodies, explicit org in path | dedicated safe `CliPreset` metadata; no installation/json commands, auth, keys or MCP URL; list CLI JSON remains a page array; delete `void` | `resource/oas/modules/backend/cli/openapi.yaml` | `backend/api/.../cli/generated/api/CliPresetApi.kt`; `CliPreset` DTOs | `generated-ready` | `P1` | `migrate` | none for basic operations; user-owned resources require member+owner+org checks despite admin namespace; read service does not mint keys/enrich remotely; domain mutation/audit reused | `AI-6344`; key gate `AI-6380`; larger workload gate `AI-6413` | `src/core/remaining-direct-contract.test.ts`, Backend safe-read/controller tests, registry/manifest/help, trailing argv tests; actual production CLI eight-operation lifecycle, ownership/accessible integration/pagination/quota/key-count/DB/audit checks |
69
69
 
70
70
  ## 공통 CLI request quota 오류 계약
71
71
 
@@ -86,7 +86,7 @@ CLI `ApiError`는 위 여섯 code에서 allowlist된 quota detail만 보존하
86
86
 
87
87
  ### P0 queue
88
88
 
89
- - `P0-ORG-01` org member list/mutation legacy-exception aligned (done in `AIP-PUB-04`, independent contract follow-up remains)
89
+ - `P0-ORG-01` member list and invite/remove/role mutations use dedicated CLI v1 contracts (`AI-6344`); `ORG-02` exit uses DELETE membership
90
90
  - `P0-ORG-02` org invite-link trio hidden from public beta (done in `AIP-PUB-04`)
91
91
  - `P0-AGENT-01` / `P0-AGENT-02` moved to dedicated CLI lifecycle endpoints with metadata quota and capability checks (`AI-6344`)
92
92
  - `P0-AGENT-03` export remains a gated transfer candidate (`AI-6380`)
@@ -98,7 +98,7 @@ CLI `ApiError`는 위 여섯 code에서 allowlist된 quota detail만 보존하
98
98
 
99
99
  - `P1-INT-01` integration legacy-exception documented; current/legacy path+DTO tests added
100
100
  - `P1-AUTO-01` Automation management uses eight dedicated v1 operations; Schedule/Webhook/My Drive lifecycle and stored safe reads are implemented. External provider metadata/mutations and `P1-AUTO-02` remain gated.
101
- - `P1-PRESET-01` preset admin namespace/docs + legacy path tests done
101
+ - `P1-PRESET-01` eight basic operations use dedicated CLI v1 contracts and safe metadata DTOs (`AI-6344`); key rotation stays gated
102
102
  - `P1-SKILL-01` skill JSON/help/docs field sync done
103
103
  - `P1-CHAT-01` chat SSE fixture tests added for final/fallback/error cases
104
104
  - `P1-MODEL-EXEC-01` catalog/text moved to the dedicated v1 code-first OAS and CLI path; `P1-MODEL-EXEC-02` image remains deferred on the legacy route
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "aipctl",
3
- "version": "2026.10.1",
3
+ "version": "2026.10.3",
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": "ea5c348d28e6d1e64655c97b08350c4e9b14572c4474243a654e18c2b6bb7917",
26
- "wrapperHash": "03b7520e6526fd395045d78d3a17ba20bf875e10cd352306b5417a3b63ed384c",
25
+ "contentHash": "cd3e1d96a6c80cca1c9594573468ecac8876ea644f388d0d53950cc063451a72",
26
+ "wrapperHash": "1f9932e5f826496deb9203873e0e543319d84afda6610a78305ffa034fd665c0",
27
27
  "nativeHash": "006b08c3e391f4571d9b7c0f12d684fe2448106259e7e0581b10f9be362452e9"
28
28
  },
29
29
  "optionalDependencies": {