aipctl 2026.10.8 → 2026.10.9

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.
@@ -38,146 +38,40 @@
38
38
  | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
39
39
  | AUTH-01 | auth | `aipctl auth login` | `src/core/oauth.ts`: `discoverOAuthMetadata` → `registerCliOAuthClient` → `exchangeAuthorizationCode` | api + external browser | `GET /.well-known` → `POST /oauth2/register` → browser `GET /oauth2/authorize` → `POST /oauth2/token` | `/.well-known/oauth-authorization-server`, `/oauth2/register`, `/oauth2/authorize`, `/oauth2/token` | PKCE state/challenge, dynamic client registration body, auth code exchange form | `OAuthMetadata`, `OAuthClientRegistration`, `OAuthTokenResponse` → local `Credentials` | not found in current `resource/oas` for `oauth-authorization-server` / `/oauth2/register` / `/oauth2/token` | none | `oas-missing` | N/A | `legacy-exception` | owner=`backend/api OAuth server`; rationale=`login is required public auth flow but OAuth authorization-server/DCR/token contract is not in current OAS`; removal condition=`official OAuth server contract exists in resource/oas and independent generated contract`; incorporation plan=`add OAuth server metadata/register/token paths or dedicated auth contract fixture, then bind CLI parser/tests` | `AIP-PUB-05` | existing auth tests cover login helpers; needed contract snapshot for OAuth metadata/register/token paths |
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
- | 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
- | 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`, `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 |
41
+ | AUTH-03 | auth | `aipctl auth whoami` | `ApiService.getMe` | api | `GET` | `/api/web/me` | none | local `UserProfile` | `resource/oas/duplo-web.yaml` | `frontend/packages/api/src/out/user-types.ts#paths["/api/web/me"]` | `legacy-generated` | N/A | `keep` | none | N/A | existing `commands/auth/auth.test.ts`; needed user-types ref note only |
42
+ | ORG-01 | org | `aipctl org list`, `aipctl org use` | `listOrganizations`, `getOrganization` | api | `GET` | `/api/web/organizations`; CLI `use` filters locally by slug after list call | none | local `Organization[]` / `Organization` | `resource/oas/duplo-web.yaml` | `frontend/packages/api/src/out/user-types.ts#paths["/api/web/organizations"]`, `#paths["/api/web/organizations/slug/{organizationSlug}"]` | `legacy-generated` | N/A | `keep` | none | N/A | existing `commands/org/org.test.ts`; needed slug lookup contract snapshot |
43
+ | ORG-02 | org | `aipctl org capabilities`, `aipctl org settings`, `aipctl org exit` | `getOrgCapabilities`, `getUserSettings`, `exitOrg` | api | `GET`, `GET`, `POST` | `/api/web/organizations/slug/{organizationSlug}/capabilities`; `/api/web/user/settings`; `/api/web/organizations/slug/{organizationSlug}/exit` | none | local `OrgCapabilities`, `UserSettings`, `void` | capabilities: `resource/oas/modules/backend/organization/openapi.yaml`; settings/exit: `resource/oas/duplo-web.yaml` | capabilities `frontend/packages/api/src/out/modules/organization-types.ts#paths["/api/web/organizations/slug/{organizationSlug}/capabilities"]`; settings/exit legacy `frontend/packages/api/src/out/user-types.ts#paths[...]` | `legacy-generated` | N/A | `keep` | none | N/A | existing org tests partial; needed capability/settings/exit smoke coverage |
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` | `/api/web/organizations/slug/{organizationSlug}/members/detail`; `/invite`; `/members` | list uses detail status shape; invite body `{ emails, role: 'owner' | 'admin' | 'aiOperator' | 'member' }`; remove/update bodies `{ members: [{ email, status, userId? }] }` + update `role` | local `ListMembersResponse`, `InviteOrgMembersResponse`, `void`; mutation commands preload `listOrgMembers` for selection UX | latest role enum source: `resource/oas/modules/backend/_/components/schemas/OrganizationRoleEnum.yaml`; member status source: `resource/oas/modules/backend/organization/openapi.yaml`; legacy member list/mutation paths: `resource/oas/duplo-web.yaml` | latest refs: `frontend/packages/api/src/out/modules/backend-common-types.ts#OrganizationRoleEnum`, `frontend/packages/api/src/out/modules/organization-types.ts#paths["/api/web/organizations/slug/{organizationSlug}/members/status"]`; legacy refs: `frontend/packages/api/src/out/user-types.ts#paths["/api/web/organizations/slug/{organizationSlug}/invite"]`, `#paths["/api/web/organizations/slug/{organizationSlug}/members"]`, `#paths["/api/web/organizations/slug/{organizationSlug}/members/detail"]` | `legacy-generated` | `P0` | `legacy-exception` | owner=`backend app Organization API / duplo-web legacy OAS`; rationale=`public member list/admin flow kept for beta; role/status now align with current enum/status source while invite/remove/update still rely on legacy duplo-web member mutation contract`; removal condition=`independent contract includes member detail list plus invite/remove/update member mutations`; incorporation plan=`add resource/oas-based organization member admin contract, then remove legacy duplo-web refs and local fallback mapping` | `AIP-PUB-05` | updated `src/core/api.test.ts`, `commands/org/members.test.ts`, `commands/org/org-member.test.ts`; covers detail path, lower-case role enum, failedInvitations, member mutation body |
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/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) |
46
+ | SKILL-01 | skill | `aipctl skill list`, `aipctl skill get`, `aipctl skill delete` | `listSkills`, `getSkill`, `deleteSkill` | api | `GET`, `GET`, `DELETE` | `/api/web/organizations/slug/{organizationSlug}/skills`; `/skills/{skillId}` | query `{ count,cursor,search }`; detail query `{ maxFiles }` | local `ListSkillsResponse`, `SkillDetail`, `void` | `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"]`, `#paths["/api/web/organizations/slug/{organizationSlug}/skills/{skillId}"]` | `generated-ready` | N/A | `keep` | none | N/A | existing `commands/skill/*.test.ts`; needed path/type snapshot once independent generation exists |
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`, `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 |
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`; `/admin/.../skills/built-in-library`; `/built-in-library/clone` | list query `{ count,cursor,search/limit }`; clone body `{ sourceSkillIds[] }` | local list/clone DTOs | `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/library"]`, `#paths["/api/web/organizations/slug/{organizationSlug}/skills/library/clone"]`, `#paths["/api/web/admin/organizations/slug/{organizationSlug}/skills/built-in-library"]`, `#paths["/api/web/admin/organizations/slug/{organizationSlug}/skills/built-in-library/clone"]` | `generated-ready` | N/A | `keep` | none | N/A | existing skill extended tests; needed built-in/library path snapshot |
49
+ | SKILL-04 | skill-admin | `aipctl admin skill list`, `get`, `delete`, `publish`, `unpublish` | `listAdminSkills`, `getAdminSkill`, `deleteAdminSkill`, `updateAdminSkill` | api | `GET`, `GET`, `DELETE`, `PATCH` | `/api/web/admin/organizations/slug/{organizationSlug}/skills`; `/skills/{skillId}` | list query `{ pageNumber,pageSize,search }`; publish toggle body `{ availableInLibrary: boolean }` | local `ListAdminSkillsResponse`, `SkillDetail`, `void` | `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"]`, `#paths["/api/web/admin/organizations/slug/{organizationSlug}/skills/{skillId}"]` | `generated-ready` | N/A | `keep` | none | N/A | existing `commands/admin/skill.test.ts`; needed admin list/detail/update path snapshot |
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
- | 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 |
53
- | P0-AGENT-02 | agent-admin | `aipctl admin agent create`, `update`, `delete`, `share`, `templates`; `aipctl agent enable`, `disable` | `createInstalledAgent`, `updateInstalledAgent`, `deleteInstalledAgent`, `getInstalledAgentShare`, `listAgentTemplates`, `updateInstalledAgentStatus` | api | `POST`, `PATCH`, `DELETE`, `GET`, `GET`, `PATCH` | `/api/cli/v1/organizations/{organizationSlug}/agents`; `/{installedAgentId}`; `/{installedAgentId}/share`; `/templates`; `/{installedAgentId}/status` | existing create/update/status bodies; templates collect bounded pages and retain the full catalog; share is read-only | create/update `{ id }`, void mutation responses, existing CLI template/share mapping | `resource/oas/modules/backend/cli/openapi.yaml`; shared legacy DTO refs | `backend/api/.../cli/generated/api/CliAgentApi.kt` | `generated-ready` | `P0` | `migrate` | none; AI operator/workflow/audit policy stays in existing domain owner | `AI-6344` | all eight operations capability/path tests, mutation non-replay, template paging, real CLI lifecycle/DB/audit and metadata 429 verification |
54
- | P0-AGENT-03 | agent-export | `aipctl admin agent export` (GA-CANDIDATE, production gated) | `exportInstalledAgent` | api | `GET` | `/web/admin/organizations/slug/{organizationSlug}/installed-agents/{installedAgentId}/export` | existing direct controller request | YAML `Buffer` | `backend/api/.../app/controller/AgentExportController.kt`; intentionally OAS-codegen excluded | none | `legacy-generated` | `P0` | `legacy-exception` | owner=`AgentExportController`; dedicated transfer contract, size/timeout/partial-file/authorization/audit gates remain | `AI-6380` | existing direct export path/Buffer/404 tests; production help remains hidden |
55
- | P1-CHAT-01 | agent-chat | `aipctl agent chat` | `agentNewChat`, `agentChat`, local `parseSseStream` | chat | `POST` start + `POST` SSE; continuation lookup `GET` | `/api/{orgSlug}/conversations/agent-chat`; `/api/{orgSlug}/conversations/{conversationId}/stream`; continuation lookup `/librechat/api/{orgSlug}/convos/{conversationId}` | start `{ agentInstallationId, conversationId?, text, files: [] }`; stream `{ requestMessageId? }` from the accepted start response | start `{ conversationId,requestMessageId?,runId? }`; Mastra returns both identifiers; `AgentChatResult { text, conversationId }`; UI event.data `{ seq,conversationId,runId,chunk }` and completed end must match the start-issued runId; legacy final requestMessage.messageId must match requestMessageId when provided; an uncorrelated continuation fails unknown | `lib/chat-rest/packages/schema/src/conversation/chat-start.schema.ts`; `lib/chat-rest/packages/schema/src/chat/chat-v2-stream.schema.ts` | `lib/chat-rest/packages/contract/src/chat.ts`; package-local parser fixture (no frontend runtime dependency) | `stream-exception` | `P1` | `legacy-exception` | owner=`Chat conversation/Agent stream`; rationale=`development Agent execution retains its existing conversation transport and candidate gates`; removal condition=`dedicated execution contract and quota/cancel/recovery gates pass`; incorporation plan=`bind the subscription to the accepted request/run; retry only a subscription containing no current-run data, at most 4 times; never replay the paid start` | `AI-6380` | `src/core/api.test.ts` covers prior completed continuation, bounded stale-run retries, start/terminal identifiers, incomplete/failed/abort and legacy request correlation; built CLI local HTTP fixture returns only current reply (start 1/subscription 2); earlier QA success predates run correlation, which requires updated Chat deployment and QA rerun |
56
- | P1-AUTO-01 | automation | `aipctl automation list`, `get`, `create`, `update`, `delete`, `enable`, `disable`, `history`, `triggers` | `listAutomations`, `getAutomation`, `createAutomation`, `updateAutomation`, `deleteAutomation`, `updateAutomationStatus`, `listAutomationHistories`, `getTriggerProviderMetadata` | api | `GET`, `POST`, `PUT`, `DELETE`, `PATCH` | `/api/cli/v1/organizations/{organizationSlug}/automations`; `/{automationId}`; `/{automationId}/status`; `/{automationId}/history`; `/triggers?type=...` | one-based pageNumber/pageSize (1..100); status `{ status }`; exactly one matching trigger branch; metadata retains required accountId/folderId/serviceType input | existing list/history domain DTOs; dedicated `GetCliAutomationResponse` and ID DTO; webhook detail only serviceType/boolean secretConfigured | `resource/oas/modules/backend/cli/openapi.yaml` → `v1_automations*.yaml`; request/list/history aliases reuse Automation user schemas | `backend/api/.../cli/generated/api/CliAutomationApi.kt` | `generated-ready` | `P1` | `migrate` | owner=`CLI Automation adapter`; Schedule/Webhook/My Drive management enabled; external account provider metadata/mutations return 403 before provider side effects; stored external detail never enriches remotely or fabricates account/folder validity | `AI-6344`; external lifecycle gate `AI-6380`; large pagination gate `AI-6413` | `src/core/automation-contract.test.ts`, `src/core/api.test.ts`, Automation command tests, `redaction.test.ts`, Backend safe-read/controller/audit tests, Gateway parity; real mise servers + production CLI CRUD/ownership/pagination/quota/DB/audit |
57
- | P1-AUTO-02 | automation-execution | `aipctl automation run`, `cancel`, `webhook-regen` (GA-CANDIDATE, production gated) | `runAutomation`, `cancelAutomationHistory`, `regenerateWebhookUrl` | api | `POST`, `POST`, `POST` | legacy `/api/web/organizations/slug/{organizationSlug}/automations/{automationId}/run`; `/histories/{seq}/cancel`; `/webhook/regenerate-url` | existing domain input | existing execution/history/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` | `legacy-exception` | owner=`Automation execution domain`; requires execution quota, idempotency/cancel lifetime, webhook secret rotation and safe output verification before customer enablement | `AI-6380` | existing legacy path/command tests; actual QA SUCCESS/result and PENDING→CANCELED, completed cancellation rejection and masked webhook regeneration; production availability keeps all three hidden |
58
- | CHAT-01 | chat-readonly | `aipctl chat list`, `aipctl chat get`, `aipctl chat messages` | `listConversations`, `getConversation`, `listMessages` | chat | `GET` | `/api/cli/v1/organizations/{orgSlug}/chats`; `/chats/{conversationId}`; `/chats/{conversationId}/messages` | list sends optional cursor; server fixes bounded `updatedAt desc` page size; detail/messages preserve organization and user ownership | local `ListConversationsResponse`, `ConversationDetail`, `ChatMessage[]` | `chat/packages/chat/src/modules/cli-chat/interface/cli-chat-read-v1.interface.controller.ts` | code-first controller contract with `operationId`/quota/capability extensions; no generated backend artifact | `oas-source-only` | `P0` | `migrate` | none; `CliChatReadInterfaceService` reuses the existing conversation/message ownership services and returns CLI-safe fields only | `AI-6344` | updated `src/core/api.test.ts`, Chat read service spec, Gateway registry/contract parity; local CLI/Chat verification covers cursor and no legacy fallback |
59
- | 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` with optional count/cursor/parentId (default count200), `/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) |
52
+ | P0-AGENT-01 | agent-user | `aipctl agent list`, `aipctl agent get` | `listInstalledAgents`, `getInstalledAgent` | api | `GET`, `GET` | `/api/web/organizations/slug/{organizationSlug}/installed-agents`; `/installed-agents/{installedAgentId}` | legacy implemented endpoint maps `list`/`installedAgentId` into CLI `data`/`id`; detail wraps legacy response in `{ data }` and maps `installedIntegrationList` fallback | local `ListInstalledAgentsResponse`, `{ data: InstalledAgentDetail }` | implemented: `resource/oas/duplo.yaml`; future v2 source: `resource/oas/modules/backend/agent/user/openapi.yaml` | legacy `frontend/packages/api/src/out/user-types.ts#paths["/api/web/organizations/slug/{organizationSlug}/installed-agents"]`, `#paths["/api/web/organizations/slug/{organizationSlug}/installed-agents/{installedAgentId}"]` | `legacy-generated` | `P0` | `keep legacy` | owner=`backend app AgentsApiController`; rationale=`agent v2 controllers currently throw NotImplementedError in this repo, so public beta must call implemented legacy endpoints`; removal condition=`AgentUserApiController v2 methods are implemented and deployed`; incorporation plan=`switch to agent v2 OAS/generated contract only after backend implementation lands` | `AIP-PUB-05` | updated `src/core/api.test.ts`, `commands/agent/agent.test.ts`; covers implemented legacy list/detail path and response mapping |
53
+ | P0-AGENT-02 | agent-admin | `aipctl admin agent create`, `update`, `delete`, `export`, `share`, `templates`; `aipctl agent enable`, `disable` | `createInstalledAgent`, `updateInstalledAgent`, `deleteInstalledAgent`, `exportInstalledAgent`, `getInstalledAgentShare`, `listAgentTemplates`, `updateInstalledAgentStatus` | api | `POST`, `PATCH`, `DELETE`, `GET`, `GET`, `GET`, `PATCH` | `/api/web/admin/organizations/slug/{organizationSlug}/installed-agents`; `/{installedAgentId}`; export uses legacy direct `/web/admin/organizations/slug/{organizationSlug}/installed-agents/{installedAgentId}/export`; `/share`; `/agents`; `/{installedAgentId}/status` | create/update bodies follow implemented legacy admin request (`custom.iconKeyOrUrl`, `knowledgeBundleIdList`); export is YAML bytes from direct controller path; templates map legacy `agentId`/`label`/`categoryList`; status body `{ status }` | create/update return plain `{ id }`; local admin agent DTOs + `Buffer` export | implemented: `resource/oas/duplo.yaml`; export controller path: `backend/api/src/main/kotlin/com/querypie/duplo/api/app/controller/AgentExportController.kt`; future v2 source: `resource/oas/modules/backend/agent/admin/openapi.yaml` | legacy `frontend/packages/api/src/out/user-types.ts#paths["/api/web/admin/organizations/slug/{organizationSlug}/installed-agents"]`, `#paths["/api/web/admin/organizations/slug/{organizationSlug}/installed-agents/{installedAgentId}"]`, `#paths["/api/web/admin/organizations/slug/{organizationSlug}/agents"]`; export path intentionally OAS-codegen excluded | `legacy-generated` | `P0` | `keep legacy` | owner=`backend app AgentsApiController + AgentExportController`; rationale=`agent v2 admin controllers currently throw NotImplementedError and export is implemented only at /web/admin direct controller path in PROD`; removal condition=`AgentAdminApiController v2 and export path are implemented/deployed under versioned OAS path`; incorporation plan=`switch to agent v2 OAS/generated contract only after backend implementation lands, then remove direct export exception` | `AIP-PUB-05` | updated `src/core/api.test.ts`, `commands/agent/agent.test.ts`; covers implemented legacy CRUD/status/template path/body, direct export path, Buffer response, and 404 propagation |
54
+ | 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 |
55
+ | 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 |
56
+ | 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 |
57
+ | 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`; `/drive/entries/download-url`; `/drive/entries/delete`; `/drive/entries/{entryId}`; `/drive/usage` | official list `{ path, hasNext, nextCursor, items }`; delete body `{ entryIds[] }`; rename body `{ newName }`; download body `{ entryIds: [id] }` | official drive list/download DTOs + external file buffer | `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"]`, `#paths["/api/web/organizations/slug/{organizationSlug}/drive/entries/download-url"]`, `#paths["/api/web/organizations/slug/{organizationSlug}/drive/entries/{entryId}"]`, `#paths["/api/web/organizations/slug/{organizationSlug}/drive/entries/delete"]`, `#paths["/api/web/organizations/slug/{organizationSlug}/drive/usage"]` | `generated-ready` | `P0` | `migrate` | none | `AIP-PUB-05` | updated `src/core/api.test.ts`, `commands/drive/drive.test.ts`; covers paged list shape, batch download-url request, DTO field rename (`sizeBytes`, `modifiedAt`) |
60
58
  | 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 |
61
- | 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` | read operations use `/api/cli/v1/organizations/{organizationSlug}/integrations`; `/admin/integrations/available`; `/admin/integrations/{integrationId}`; `/tools`; mutations/test remain legacy candidate paths | read responses use dedicated CLI DTOs; admin detail maps only metadata and configured boolean, never property descriptors or credential values; update/delete/test remain unchanged | local `Integration`, `IntegrationDetail`, `IntegrationToolsResponse`, `ConfigurableIntegration[]` | `resource/oas/modules/backend/cli/openapi.yaml` → `v1_integrations*.yaml` | `backend/api/.../cli/generated/api/CliIntegrationApi.kt`; generated `Cli*Integration*` models | `generated-ready` | `P1` | `migrate` | owner=`backend CLI integration adapter`; rationale=`read-only operations now have a stable v1 contract while external test and mutations retain candidate gates`; removal condition=`dedicated test/mutation contracts pass timeout, redaction and idempotency gates`; incorporation plan=`follow AI-6380 candidate work` | `AI-6344` | updated `src/core/api.test.ts`, Backend adapter/security tests, Gateway registry/contract parity; local CLI read verification and legacy mutation path regression |
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
- | 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
- | 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/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
-
70
- ## 본인 quota 진단 계약
71
-
72
- `quota status [--org <slug>] [--json]`은 `ApiService.getMyCliQuota`에서
73
- `GET /api/cli/v1/organizations/{organizationSlug}/quota`를 한 번 호출한다.
74
- Source OAS는 `resource/oas/modules/backend/cli/paths/v1_quota.yaml`, generated owner는
75
- `CliQuotaApi#getCliMyQuota`, CLI parser는 `src/core/quota-contract.ts`다.
76
- Canonical operation은 `cli.quota.self.read`, capability는 `cli.quota.self`, quota class는
77
- `control-read`다. 현재 인증 actor·active membership을 정책/사용량 조회보다 먼저 검증한다.
78
- Gateway capability discovery와 동일한 user-global control-read bucket을 쓰며 workload policy
79
- 조회나 metadata/text quota 소진에 의존하지 않는다. bucket은 유한하고 Redis 장애 시 503이다.
80
-
81
- 응답은 `userLimits`, `organizationSharedLimits`, nullable 정책 version 2개, `usage`만 허용한다.
82
- UTC 일일 text admissions, 미반납 active, unresolved 수는 PostgreSQL authoritative snapshot이다.
83
- 정책 row가 없으면 version을 `null`로 포함한다. 사용량 실패는 `UNAVAILABLE`과 required-null
84
- 사용량/reset 필드로 표시한다. 본인 사용량과 조직 공유 정책 수치는 반환하지만 조직 aggregate
85
- 사용량·다른 사용자·raw policy·credit 잔액을 반환하지 않는다. HTTP 응답은 `Cache-Control: no-store`다.
86
- 조회는 용량을 예약하거나 기존 permit을 반환하지 않는다. 테스트는 Backend
87
- `CliQuotaApiControllerTest`, Gateway admission/registry, CLI quota parser/command/API tests다.
88
- Source OAS의 429/503은 JSON `CliQuotaErrorResponse`와 공유 `CliQuotaErrorDetails`를 선언하며,
89
- 200의 `Cache-Control: no-store`와 429의 조건부 positive-integer `Retry-After`도 포함한다.
90
-
91
- ## 공통 CLI HTTP 수명과 작업량 상한
92
-
93
- Skill list/library는 `--count 1..200`/`--cursor`/`--search`, built-in/admin built-in은
94
- `--limit 1..100`/`--cursor`/`--search`, Drive list는 `--count 1..200`/`--cursor`/
95
- `--parent-id`, Chat list는 `--cursor`를 기존 OAS query로 전달한다. `--json-page`는 서버의 한
96
- 페이지 envelope와 nullable `nextCursor`를 반환한다. Admin skill list는 기존 page/page-size query와
97
- `pagination` envelope를 제공한다. 기존 Skill/Chat/admin Skill `--json` 배열은 유지하며
98
- 다음 페이지가 있으면 stderr에 안내한다. 자동 전체 수집은 없다. `src/basic-behavior.test.ts`와
99
- `src/core/api.test.ts`에서 root argv→API options→encoded query와 출력/오류를 검증한다.
100
- 삭제·멤버 제거·조직 탈퇴의 확인 누락은 요청 전 `CLI_CONFIRMATION_REQUIRED`,
101
- `outcome=not-dispatched`, exit 1이다. 공개 범위는 `command-manifest.ts`와 availability가 결정한다.
102
-
103
- 인증 state snapshot/commit·logout·환경 변경·조직 선택 저장은 동일한 짧은 credentials lock을
104
- 사용한다. refresh 전용 lock은 network 대기 중에도 logout/config 변경을 허용한다. 새 로그인·
105
- logout·환경 변경은 persistent session revision을 바꾸며, refresh는 같은 session을 유지한다.
106
- 늦은 refresh/login/org 결과는 폐기하고, HTTP admission 뒤 fetch 직전에 revision·bearer·App URL/
107
- first-party destination을 다시 확인한다. 재로그인 후 과거 invalid_grant가 새 credentials를
108
- 지우지 않는다. config/credentials JSON은 atomic rename으로 저장하고 config는 매번 다시 읽는다.
109
- 실제 filesystem을 공유하는 독립 service instance 회귀는 `src/core/auth-session.test.ts`에 있다.
110
- Refresh lock 획득은 metadata/token 각각 30초와 짧은 state lock을 고려해 최대 70초 기다린다.
111
- 대기는 취소 가능하며 시간 초과는 `CLI_AUTH_REFRESH_WAIT_TIMEOUT`, `outcome=not-dispatched`다.
112
- 취소된 대기자는 token을 재교환하지 않고, 갱신 소유자의 취소는 OAuth HTTP signal에도 전달한다.
113
- 6초 지연된 정상 갱신에서도 독립 인스턴스가 token POST 한 번을 재사용하는 회귀를 유지한다.
114
-
115
- `src/core/http-request.ts`가 로컬 admission, fetch, 전체 body 소비를 하나의 deadline으로 묶는다.
116
- 일반 API는 120초·decoded 8 MiB, OAuth는 30초·8 MiB, transfer/export download는 600초·128 MiB,
117
- external upload는 600초·응답 8 MiB, text execution은 서버 최대 600초에 응답 여유 10초를 더한다.
118
- Content-Length 사전 검사와 chunked byte 검사를 모두 적용한다. 로컬 lease는 headers 뒤에도
119
- body 소비 종료까지 유지하고 timeout/cancel/실패 시 해당 lease만 반납한다. deadline 뒤 늦게
120
- 획득된 lease도 요청을 전송하지 않고 반납한다.
121
- Forced runtime teardown은 interrupt된 HTTP와 늦은 admission cleanup을 최대 5초 기다린 뒤 종료한다.
122
-
123
- Mutation transport/invalid-body/timeout 실패는 전송 전 `not-dispatched`, 전송 후 `unknown`;
124
- GET/HEAD 실패는 `read-failed`다. 알려진 server rejection은 기존 code/status를 유지한다.
125
- 변경·유료 요청의 자동 retry나 legacy fallback은 없다. 개발 Agent stream의 terminal-envelope-only
126
- 구독 재조회는 전체 600초·최대 3회로 제한하며 start/provider 요청은 재실행하지 않는다.
127
- OAuth registration·authorization-code·refresh POST의 timeout/invalid JSON/잘못된 성공 payload도
128
- `unknown`과 safe request ID를 로그인·갱신의 최종 오류 경계까지 전달한다. 인증 상태를 확인한 뒤
129
- 재시도하도록 안내하며 자동 재전송 또는 결과가 불명인 응답으로 자격 증명 저장/삭제를 하지 않는다.
130
- 확인된 `invalid_grant`/401 응답은 기존 session-expired 처리로 구분한다.
131
-
132
- ## QA 후보 기능에서 확인한 결과 경계
133
-
134
- 개발 Agent SSE의 UI chunk는 같은 conversation/run에 속해야 하며 열린 text block을 모두 닫고
135
- 비어 있지 않은 text payload, `finish`와 `end(status=completed)`를 확인한 뒤 성공한다. terminal에 scope/run이 있으면 그것도
136
- 일치해야 한다. UI stream의 일부 뒤 legacy final이 섞이면 성공으로 처리하지 않는다.
137
- 오류·abort·미완료 결과는 `CLI_RESPONSE_INVALID/outcome=unknown`이며 provider start를 재실행하지
138
- 않는다. legacy final-only stream의 content/text 호환은 유지한다.
139
-
140
- Skill 일반/admin upload의 잘못된 확장자는 upload URL 요청 전에
141
- `CLI_INVALID_ARGUMENT/outcome=not-dispatched/exit1`이다. Integration test가 HTTP 성공 body의
142
- `success:false`를 반환해도 CLI는 `CLI_INTEGRATION_TEST_FAILED/exit1`로 실패한다. 진단은 마스킹하고
143
- 연결 테스트를 재호출하지 않는다. Tunnel config의 positional token을 포함한 전체 command는
144
- 기본 `[REDACTED]`이고 명시적 `--show-sensitive`에만 표시한다.
145
-
146
- OAuth와 조직 선택의 자동 browser launcher 실패는 출력한 URL을 통한 수동 흐름을 유지한다.
147
- 플랫폼 launcher를 shell 없이 spawn하고 같은 동기 호출에서 child-process `error`를 등록한 뒤
148
- unref한다. next-tick ENOENT와 browser 수명 때문에 CLI가 종료/대기하지 않으며 Windows/WSL은
149
- single-quoted URL을 encoded PowerShell argument로 전달한다. 인증 성공을 대신하지 않는다.
150
- Ctrl+C는 보수적인 `CLI_COMMAND_INTERRUPTED`, `outcome=unknown`, exit 130을 출력하며 remote
151
- rollback을 의미하지 않는다. API/auth/org 실패는 exit 1이고 `--json` stderr에 한 건만 기록한다.
152
-
153
- Agent templates 전체 collector는 100페이지·10,000항목·합계 8 MiB·120초를 공유한다.
154
- 반복 ID, total/pageSize 변경, 빈/짧은 중간 페이지와 상한 초과는 오류로 종료하며 부분 성공을
155
- 반환하지 않는다. Snapshot cursor가 없는 동안 같은 크기의 동시 교체까지 검출한다고 보장하지
156
- 않는다. DB/query·다른 endpoint pagination 및 대규모 tenant 측정은 AI-6413에 남아 있다.
157
-
158
- ## 공통 CLI request quota 오류 계약
159
-
160
- `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`이다.
161
-
162
- | HTTP | code | CLI 처리 |
163
- | --- | --- | --- |
164
- | 429 | `CLI_QUOTA_EXCEEDED` | `limitKind=request_rate`, quota class, denying scope, request ID를 보존한다. 양수 refill로 계산 가능한 경우에만 `Retry-After`, `resetAt`을 보존한다. 자동 retry는 하지 않는다. |
165
- | 503 | `CLI_QUOTA_POLICY_UNAVAILABLE` | Backend effective-policy auth/timeout/schema/freshness 실패. stale/default policy로 대체하거나 자동 retry하지 않는다. |
166
- | 503 | `CLI_QUOTA_LIMITER_UNAVAILABLE` | Redis timeout/script/result 실패. 유료·mutation 요청을 자동 retry하지 않는다. |
167
- | 429 | `CLI_TEXT_DAILY_LIMIT` | `limitKind=daily`, `quotaClass=text-execution`, 사용자 scope와 request ID를 보존한다. 유효한 UTC reset 시각과 그 시각에서 계산한 retry만 노출하며 자동 retry하지 않는다. |
168
- | 429 | `CLI_TEXT_USER_CONCURRENCY_LIMIT` | `limitKind=concurrent`, `quotaClass=text-execution`, 사용자 scope와 request ID만 보존한다. permit 해제 시각을 알 수 없으므로 `Retry-After`와 `resetAt`을 만들거나 전달하지 않는다. |
169
- | 429 | `CLI_TEXT_ORGANIZATION_CONCURRENCY_LIMIT` | `limitKind=concurrent`, `quotaClass=text-execution`, 조직 scope와 request ID만 보존한다. permit 해제 시각을 알 수 없으므로 `Retry-After`와 `resetAt`을 만들거나 전달하지 않는다. |
170
-
171
- 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/**`에 있다.
59
+ | 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 |
60
+ | P0-MODEL-01 | model | `aipctl model list` | `listModels` | chat | `GET` | `/api/{orgSlug}/models` | none | CLI maps official `{ models: string[], defaultModel? }` into `Model[]` with optional `isDefault` | `resource/oas/chat.yaml` | `frontend/packages/api/src/out/chat-types.ts#paths["/api/{orgSlug}/models"]` | `legacy-generated` | `P0` | `migrate` | none | `AIP-PUB-05` | updated `src/core/api.test.ts`, `commands/model/model.test.ts`; covers official path and string-array response mapping |
61
+ | P1-MODEL-EXEC-01 | model-exec | `aipctl model-exec models`, `get`, `sample`, `chat`, `image generate` | `listModelExecModels`, `executeModelExecChat`, `executeModelExecImageGeneration`; image output uses `downloadFromUrl` | chat + external artifact URL | `GET`, `POST`, `POST`, external `GET` | `/api/{orgSlug}/cli/model-exec/models`; `/chat`; `/images/generations`; response `downloadUrl` | local `ModelExecChatRequest`, `ModelExecImageGenerationRequest`; Chat DTO source `chat/packages/chat/src/modules/cli-model-exec/interface/dto/cli-model-exec.dto.ts` | local `ModelExecModelCatalog`, `ModelExecChatResponse`, `ModelExecImageGenerationResponse`; image bytes from external URL | not found in current `resource/oas`; implemented by `chat/packages/chat/src/modules/cli-model-exec/interface/cli-model-exec.interface.controller.ts` | none | `oas-missing` | `P1` | `legacy-exception` | owner=`chat CLI Model Exec API`; rationale=`experimental public command is implemented with Chat zod DTOs but no current OAS path`; removal condition=`CLI model-exec paths and DTOs are published in the Chat contract`; incorporation plan=`add the three paths and schemas to the Chat OAS, generate an independent reference, then bind CLI DTO/tests` | `AIP-PUB-05` | existing `src/core/api.test.ts`, `commands/model-exec/model-exec.test.ts`, `commands/model-exec/progress.test.ts`; covers three paths, request bodies, required Chat DTO response fields, helper/progress behavior. Needed: image command response → external download → file write regression test |
62
+ | 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 |
63
+ | 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 |
64
+ | 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 |
65
+ | 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 |
172
66
 
173
67
  ## Queue IDs for follow-up
174
68
 
175
69
  ### P0 queue
176
70
 
177
- - `P0-ORG-01` member list and invite/remove/role mutations use dedicated CLI v1 contracts (`AI-6344`); `ORG-02` exit uses DELETE membership
71
+ - `P0-ORG-01` org member list/mutation legacy-exception aligned (done in `AIP-PUB-04`, independent contract follow-up remains)
178
72
  - `P0-ORG-02` org invite-link trio hidden from public beta (done in `AIP-PUB-04`)
179
- - `P0-AGENT-01` / `P0-AGENT-02` moved to dedicated CLI lifecycle endpoints with metadata quota and capability checks (`AI-6344`)
180
- - `P0-AGENT-03` export remains a gated transfer candidate (`AI-6380`)
73
+ - `P0-AGENT-01` user agent remains on implemented legacy endpoints until v2 backend lands
74
+ - `P0-AGENT-02` admin agent remains on implemented legacy endpoints until v2 backend lands
181
75
  - `P0-DRIVE-01` drive list/download/delete/mkdir/rename/usage contract migration (done in `AIP-PUB-04`)
182
76
  - `P0-DRIVE-02` drive upload contract migration (done in `AIP-PUB-04`)
183
77
  - `P0-MODEL-01` model list path/DTO migration (done in `AIP-PUB-04`)
@@ -185,15 +79,15 @@ CLI `ApiError`는 위 여섯 code에서 allowlist된 quota detail만 보존하
185
79
  ### P1 queue
186
80
 
187
81
  - `P1-INT-01` integration legacy-exception documented; current/legacy path+DTO tests added
188
- - `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.
189
- - `P1-PRESET-01` eight basic operations use dedicated CLI v1 contracts and safe metadata DTOs (`AI-6344`); key rotation stays gated
82
+ - `P1-AUTO-01` automation pagination/trigger metadata alignment done
83
+ - `P1-PRESET-01` preset admin namespace/docs + legacy path tests done
190
84
  - `P1-SKILL-01` skill JSON/help/docs field sync done
191
85
  - `P1-CHAT-01` chat SSE fixture tests added for final/fallback/error cases
192
- - `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
86
+ - `P1-MODEL-EXEC-01` experimental CLI model-exec contract remains OAS-missing; current Chat controller/DTO and CLI path tests are recorded
193
87
 
194
88
  ## Manual notes
195
89
 
196
90
  - Generated reference files under `frontend/packages/api/src/out/**` are inventory links only. They are not imported by CLI source/build/test/lint.
197
- - Agent lifecycle uses the dedicated `CliAgentApiController` and CLI OAS, delegating internally to the implemented `AgentsApiController` bean. Future v2 implementation can replace that internal owner without changing the CLI endpoint. `agent chat` and `admin agent export` retain their separate candidate gates.
91
+ - `agent-user` / `agent-admin` modern OAS files exist under `resource/oas/modules/backend/agent/**`, but current backend v2 controllers throw `NotImplementedError`; current CLI intentionally uses implemented `AgentsApiController` endpoints until v2 implementation lands.
198
92
  - OAuth authorization-server metadata, dynamic client registration, authorize, and token endpoints used by `src/core/oauth.ts` were not found in current `resource/oas`; they need owner-backed contractization.
199
93
  - `config` commands intentionally excluded. local config surface has no network owner.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "aipctl",
3
- "version": "2026.10.8",
3
+ "version": "2026.10.9",
4
4
  "description": "QueryPie AIP and MCP CLI tool",
5
5
  "author": "QueryPie",
6
6
  "license": "UNLICENSED",
@@ -22,16 +22,16 @@
22
22
  "node": ">=24.18.0"
23
23
  },
24
24
  "metadata": {
25
- "contentHash": "77ad8ca3b49c8ec8db6998e45fdb258360432618da1ac0f6a06caabdd77391ee",
26
- "wrapperHash": "ab5d160a7a2f56e41872201f5ac977e5b28dbe01b6b81b593b67413e4f58f216",
27
- "nativeHash": "29be9c7354a141aabac5073152f9398eae045da471b18aa089176236c7341552"
25
+ "contentHash": "dc36bf38db69c8c7161089df5d9a281b0ce7504b4d20a461c859c4595ca06bfa",
26
+ "wrapperHash": "0fd00f24c5b7afc199250ea595ed6739c3d1f885eb0b8f6a6f0cf3ba746e174a",
27
+ "nativeHash": "1c74989cf1d0b80ce2c203d301ba46e7335586126e618daf3bb26cd9504aa196"
28
28
  },
29
29
  "optionalDependencies": {
30
- "aipctl-darwin-x64": "2026.9.2",
31
- "aipctl-darwin-arm64": "2026.9.2",
32
- "aipctl-linux-x64": "2026.9.2",
33
- "aipctl-linux-arm64": "2026.9.2",
34
- "aipctl-windows-x64": "2026.9.2",
35
- "aipctl-windows-arm64": "2026.9.2"
30
+ "aipctl-darwin-x64": "2026.10.9",
31
+ "aipctl-darwin-arm64": "2026.10.9",
32
+ "aipctl-linux-x64": "2026.10.9",
33
+ "aipctl-linux-arm64": "2026.10.9",
34
+ "aipctl-windows-x64": "2026.10.9",
35
+ "aipctl-windows-arm64": "2026.10.9"
36
36
  }
37
37
  }