aipctl 2026.7.14 → 2026.7.16

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/README.md CHANGED
@@ -34,29 +34,6 @@ aipctl tunnel link <token>
34
34
 
35
35
  `install`, `run`, `tunnel`, `logs`는 Go native binary로 lazy dispatch됩니다. `prod` build에서는 `logs` command가 help와 command tree에서 제외됩니다.
36
36
 
37
- ## Experimental model execution
38
-
39
- `aipctl model-exec`은 CLI 전용 one-shot 모델 실행 namespace입니다. Conversation을 만들지 않고, 사용자가 선택한 모델을 한 번 호출해 stdout 또는 파일로 결과를 받습니다.
40
-
41
- ```bash
42
- aipctl model-exec models [--type chat|image-generation] [--json]
43
- aipctl model-exec get <model-id> [--json]
44
- aipctl model-exec sample <model-id> [--save input.json]
45
- aipctl model-exec chat --model <chat-model-id> -m "hello" [--json]
46
- aipctl model-exec image generate --model <image-model-id> --prompt "cat" --output ./cat.png [--json]
47
- ```
48
-
49
- 대화형 터미널에서는 `model-exec chat`과 `model-exec image generate`가 완료될 때까지 spinner와 경과 시간을 stderr에 표시합니다. JSON을 포함한 최종 결과는 기존처럼 stdout에만 출력됩니다.
50
-
51
- `model-exec image generate`의 이미지 생성 요청 timeout은 최대 5분입니다. 5분 안에 provider 응답이 완료되지 않으면 명령은 실패하며, 이 제한은 one-shot image-generation 요청에만 적용됩니다. `aipctl model-exec image generate --help`와 실행 중 spinner에서도 제한을 확인할 수 있습니다.
52
-
53
- Conversation을 유지하는 일반 채팅은 `chat send`를 사용합니다.
54
-
55
- ```bash
56
- aipctl chat send -m "hello" --json
57
- aipctl chat send --conversation <conversation-id> -m "continue" --json
58
- ```
59
-
60
37
  ## Development
61
38
 
62
39
  ```bash
package/build/index.cjs CHANGED
@@ -89670,7 +89670,7 @@ const injectedBuildEnv = "prod".length > 0 ? "prod" : "local";
89670
89670
  if (!isBuildEnv(injectedBuildEnv)) {
89671
89671
  throw new Error(`Invalid AIPCTL_BUILD_ENV: ${injectedBuildEnv}`);
89672
89672
  }
89673
- const VERSION = "2026.7.14".length > 0 ? "2026.7.14" : "0.0.0";
89673
+ const VERSION = "2026.7.16".length > 0 ? "2026.7.16" : "0.0.0";
89674
89674
  const BUILD_ENV = injectedBuildEnv;
89675
89675
  const INCLUDE_NATIVE_LOGS = BUILD_ENV !== "prod";
89676
89676
 
@@ -94487,30 +94487,6 @@ const ApiServiceLive = effect$1(
94487
94487
  ...res.defaultModel === id ? { isDefault: true } : {}
94488
94488
  }));
94489
94489
  }),
94490
- listModelExecModels: (orgSlug) => gen(function* () {
94491
- yield* requireChatBaseUrlEffect();
94492
- const token = yield* getAccessToken();
94493
- const path = `/api/${encodeURIComponent(orgSlug)}/cli/model-exec/models`;
94494
- return yield* makeRequest(chatBaseUrl, path, token);
94495
- }),
94496
- executeModelExecChat: (orgSlug, body) => gen(function* () {
94497
- yield* requireChatBaseUrlEffect();
94498
- const token = yield* getAccessToken();
94499
- const path = `/api/${encodeURIComponent(orgSlug)}/cli/model-exec/chat`;
94500
- return yield* makeRequest(chatBaseUrl, path, token, {
94501
- method: "POST",
94502
- body
94503
- });
94504
- }),
94505
- executeModelExecImageGeneration: (orgSlug, body) => gen(function* () {
94506
- yield* requireChatBaseUrlEffect();
94507
- const token = yield* getAccessToken();
94508
- const path = `/api/${encodeURIComponent(orgSlug)}/cli/model-exec/images/generations`;
94509
- return yield* makeRequest(chatBaseUrl, path, token, {
94510
- method: "POST",
94511
- body
94512
- });
94513
- }),
94514
94490
  getCreditStatistics: (orgSlug, options) => gen(function* () {
94515
94491
  const token = yield* getAccessToken();
94516
94492
  const params = new URLSearchParams();
@@ -94662,15 +94638,6 @@ const ApiServiceLive = effect$1(
94662
94638
  const path = `/librechat/api/${encodeURIComponent(orgSlug)}/messages/${encodeURIComponent(conversationId)}`;
94663
94639
  return yield* makeRequest(chatBaseUrl, path, token);
94664
94640
  }),
94665
- sendChatMessage: (orgSlug, body) => gen(function* () {
94666
- yield* requireChatBaseUrlEffect();
94667
- const token = yield* getAccessToken();
94668
- const path = `/api/${encodeURIComponent(orgSlug)}/cli/chats/messages`;
94669
- return yield* makeRequest(chatBaseUrl, path, token, {
94670
- method: "POST",
94671
- body
94672
- });
94673
- }),
94674
94641
  // Phase 8: Agent admin CRUD
94675
94642
  createInstalledAgent: (orgSlug, body) => gen(function* () {
94676
94643
  const token = yield* getAccessToken();
@@ -95078,14 +95045,14 @@ function jsonFormat(data, options = {}) {
95078
95045
  }
95079
95046
 
95080
95047
  const agentIdArg$4 = text$2({ name: "id" }).pipe(withDescription$5("Agent ID to export"));
95081
- const outputOption$3 = text("output").pipe(
95048
+ const outputOption$2 = text("output").pipe(
95082
95049
  withAlias("o"),
95083
95050
  withDescription$3("Output file path (defaults to {agentId}.yaml)"),
95084
95051
  optional
95085
95052
  );
95086
95053
  const exportCommand = make$4(
95087
95054
  "export",
95088
- { agentId: agentIdArg$4, org: orgOption, output: outputOption$3 },
95055
+ { agentId: agentIdArg$4, org: orgOption, output: outputOption$2 },
95089
95056
  ({ agentId, org, output }) => gen(function* () {
95090
95057
  const api = yield* ApiService;
95091
95058
  const orgSlug = yield* resolveOrgSlug(org, api);
@@ -95278,7 +95245,7 @@ const adminAgentCommand = make$4("agent", {}).pipe(
95278
95245
  withSubcommands(adminAgentSubcommands)
95279
95246
  );
95280
95247
 
95281
- const typeOption$1 = text("type").pipe(
95248
+ const typeOption = text("type").pipe(
95282
95249
  withDescription$3("Filter by event type"),
95283
95250
  optional
95284
95251
  );
@@ -95288,7 +95255,7 @@ const pageOption$3 = integer("page").pipe(
95288
95255
  );
95289
95256
  const listCommand$a = make$4(
95290
95257
  "list",
95291
- { org: orgOption, type: typeOption$1, page: pageOption$3 },
95258
+ { org: orgOption, type: typeOption, page: pageOption$3 },
95292
95259
  ({ org, type, page }) => gen(function* () {
95293
95260
  const api = yield* ApiService;
95294
95261
  const orgSlug = yield* resolveOrgSlug(org, api);
@@ -95452,7 +95419,7 @@ const deleteCommand$5 = make$4(
95452
95419
  ).pipe(withDescription("Delete an integration by ID (requires --force to confirm)"));
95453
95420
 
95454
95421
  const integrationIdArg$3 = text$2({ name: "id" }).pipe(withDescription$5("Integration ID"));
95455
- const getCommand$7 = make$4(
95422
+ const getCommand$6 = make$4(
95456
95423
  "get",
95457
95424
  { integrationId: integrationIdArg$3, org: orgOption },
95458
95425
  ({ integrationId, org }) => gen(function* () {
@@ -95596,7 +95563,7 @@ const updateCommand$2 = make$4(
95596
95563
 
95597
95564
  const adminIntegrationCommandDescription = "Admin integration management (get, update, delete, tools, available)";
95598
95565
  const adminIntegrationSubcommands = [
95599
- getCommand$7,
95566
+ getCommand$6,
95600
95567
  updateCommand$2,
95601
95568
  deleteCommand$5,
95602
95569
  toolsCommand,
@@ -95906,14 +95873,14 @@ const deleteCommand$4 = make$4(
95906
95873
  const idArg$6 = text$2({ name: "id" }).pipe(
95907
95874
  withDescription$5("Preset ID")
95908
95875
  );
95909
- const jsonOption$h = boolean("json").pipe(
95876
+ const jsonOption$c = boolean("json").pipe(
95910
95877
  withDescription$3("Output in JSON format"),
95911
95878
  withDefault(false)
95912
95879
  );
95913
95880
  const formatPresetPrompt = maskSensitiveText;
95914
- const getCommand$6 = make$4(
95881
+ const getCommand$5 = make$4(
95915
95882
  "get",
95916
- { id: idArg$6, org: orgOption, json: jsonOption$h },
95883
+ { id: idArg$6, org: orgOption, json: jsonOption$c },
95917
95884
  ({ id, org, json }) => gen(function* () {
95918
95885
  const api = yield* ApiService;
95919
95886
  yield* resolveOrgSlug(org, api);
@@ -95960,7 +95927,7 @@ const getCommand$6 = make$4(
95960
95927
  })
95961
95928
  ).pipe(withDescription("Get preset details by ID"));
95962
95929
 
95963
- const jsonOption$g = boolean("json").pipe(
95930
+ const jsonOption$b = boolean("json").pipe(
95964
95931
  withDescription$3(
95965
95932
  'Output in JSON format: [{"id":"string","name":"string","isDefault":"boolean","prompt":"string|null","createdAt":"ISO-8601","updatedAt":"ISO-8601"}]'
95966
95933
  ),
@@ -95972,7 +95939,7 @@ function formatPresetListPrompt(prompt) {
95972
95939
  }
95973
95940
  const listCommand$9 = make$4(
95974
95941
  "list",
95975
- { org: orgOption, json: jsonOption$g },
95942
+ { org: orgOption, json: jsonOption$b },
95976
95943
  ({ org, json }) => gen(function* () {
95977
95944
  const api = yield* ApiService;
95978
95945
  const orgSlug = yield* resolveOrgSlug(org, api);
@@ -96198,7 +96165,7 @@ const updateCommand$1 = make$4(
96198
96165
  const presetCommandDescription = "Manage presets (list, get, create, update, rename, delete, set-default, unset-default, regen-key, regen-static-key)";
96199
96166
  const presetSubcommands = [
96200
96167
  listCommand$9,
96201
- getCommand$6,
96168
+ getCommand$5,
96202
96169
  createCommand$1,
96203
96170
  updateCommand$1,
96204
96171
  renameCommand$1,
@@ -96319,14 +96286,14 @@ const cloneBuiltInCommand = make$4(
96319
96286
  ).pipe(withDescription("Clone built-in skills from the library to your organization"));
96320
96287
 
96321
96288
  const skillIdArg$4 = text$2({ name: "id" }).pipe(withDescription$5("Skill ID to download"));
96322
- const outputOption$2 = text("output").pipe(
96289
+ const outputOption$1 = text("output").pipe(
96323
96290
  withAlias("o"),
96324
96291
  withDescription$3("Output file path (defaults to original filename)"),
96325
96292
  optional
96326
96293
  );
96327
96294
  const downloadCommand$1 = make$4(
96328
96295
  "download",
96329
- { skillId: skillIdArg$4, org: orgOption, output: outputOption$2 },
96296
+ { skillId: skillIdArg$4, org: orgOption, output: outputOption$1 },
96330
96297
  ({ skillId, org, output }) => gen(function* () {
96331
96298
  const api = yield* ApiService;
96332
96299
  const orgSlug = yield* resolveOrgSlug(org, api);
@@ -96405,7 +96372,7 @@ const applyOption = boolean("apply").pipe(
96405
96372
  withDescription$3("Apply the prepared GitHub update immediately"),
96406
96373
  withDefault(false)
96407
96374
  );
96408
- const jsonOption$f = boolean("json").pipe(
96375
+ const jsonOption$a = boolean("json").pipe(
96409
96376
  withDescription$3("Output in JSON format"),
96410
96377
  withDefault(false)
96411
96378
  );
@@ -96444,7 +96411,7 @@ const discardPreparedSkill = (api, orgSlug, preparedSkillId) => api.abortAdminUp
96444
96411
  );
96445
96412
  const inspectCommand = make$4(
96446
96413
  "inspect",
96447
- { githubUrl: githubUrlArg, org: orgOption, patEnv: patEnvOption, json: jsonOption$f },
96414
+ { githubUrl: githubUrlArg, org: orgOption, patEnv: patEnvOption, json: jsonOption$a },
96448
96415
  ({ githubUrl, org, patEnv, json }) => gen(function* () {
96449
96416
  const api = yield* ApiService;
96450
96417
  const orgSlug = yield* resolveOrgSlug(org, api);
@@ -96476,7 +96443,7 @@ const inspectCommand = make$4(
96476
96443
  ).pipe(withDescription("Inspect a GitHub repository for skill import"));
96477
96444
  const importCommand = make$4(
96478
96445
  "import",
96479
- { githubUrl: githubUrlArg, org: orgOption, patEnv: patEnvOption, overwrite: overwriteOption$2, json: jsonOption$f },
96446
+ { githubUrl: githubUrlArg, org: orgOption, patEnv: patEnvOption, overwrite: overwriteOption$2, json: jsonOption$a },
96480
96447
  ({ githubUrl, org, patEnv, overwrite, json }) => gen(function* () {
96481
96448
  const api = yield* ApiService;
96482
96449
  const orgSlug = yield* resolveOrgSlug(org, api);
@@ -96514,7 +96481,7 @@ const importCommand = make$4(
96514
96481
  ).pipe(withDescription("Import a skill from GitHub"));
96515
96482
  const syncCommand = make$4(
96516
96483
  "sync",
96517
- { skillId: skillIdArg$3, org: orgOption, apply: applyOption, json: jsonOption$f },
96484
+ { skillId: skillIdArg$3, org: orgOption, apply: applyOption, json: jsonOption$a },
96518
96485
  ({ skillId, org, apply, json }) => gen(function* () {
96519
96486
  const api = yield* ApiService;
96520
96487
  const orgSlug = yield* resolveOrgSlug(org, api);
@@ -96627,7 +96594,7 @@ const pageSizeOption = integer("page-size").pipe(
96627
96594
  withDescription$3("Page size (default: 20)"),
96628
96595
  optional
96629
96596
  );
96630
- const jsonOption$e = boolean("json").pipe(
96597
+ const jsonOption$9 = boolean("json").pipe(
96631
96598
  withDescription$3("Output in JSON format"),
96632
96599
  withDefault(false)
96633
96600
  );
@@ -96644,7 +96611,7 @@ const overwriteOption$1 = boolean("overwrite").pipe(
96644
96611
  );
96645
96612
  const listCommand$8 = make$4(
96646
96613
  "list",
96647
- { org: orgOption, search: searchOption$2, page: pageOption$2, pageSize: pageSizeOption, json: jsonOption$e },
96614
+ { org: orgOption, search: searchOption$2, page: pageOption$2, pageSize: pageSizeOption, json: jsonOption$9 },
96648
96615
  ({ org, search, page, pageSize, json }) => gen(function* () {
96649
96616
  const api = yield* ApiService;
96650
96617
  const orgSlug = yield* resolveOrgSlug(org, api);
@@ -96703,9 +96670,9 @@ const listCommand$8 = make$4(
96703
96670
  }
96704
96671
  })
96705
96672
  ).pipe(withDescription("List organization-wide skills"));
96706
- const getCommand$5 = make$4(
96673
+ const getCommand$4 = make$4(
96707
96674
  "get",
96708
- { skillId: skillIdArg$2, org: orgOption, json: jsonOption$e },
96675
+ { skillId: skillIdArg$2, org: orgOption, json: jsonOption$9 },
96709
96676
  ({ skillId, org, json }) => gen(function* () {
96710
96677
  const api = yield* ApiService;
96711
96678
  const orgSlug = yield* resolveOrgSlug(org, api);
@@ -96896,7 +96863,7 @@ const unpublishCommand = make$4(
96896
96863
  const adminSkillCommandDescription = "Admin skill management (list, get, upload, download, delete, publish, unpublish, built-in, clone-built-in, github)";
96897
96864
  const adminSkillSubcommands = [
96898
96865
  listCommand$8,
96899
- getCommand$5,
96866
+ getCommand$4,
96900
96867
  uploadCommand$2,
96901
96868
  downloadCommand$1,
96902
96869
  deleteCommand$3,
@@ -97316,7 +97283,7 @@ const agentIdOption = optional(
97316
97283
  withDescription$3("Agent installation ID (UUID) to chat with. Required when starting a new chat.")
97317
97284
  )
97318
97285
  );
97319
- const messageOption$2 = optional(
97286
+ const messageOption = optional(
97320
97287
  text("message").pipe(
97321
97288
  withAlias("m"),
97322
97289
  withDescription$3("Message to send to the agent (if not provided, reads from stdin when piped)")
@@ -97327,7 +97294,7 @@ const conversationIdOption = optional(
97327
97294
  withDescription$3("Continue an existing conversation by ID (from a previous --json result)")
97328
97295
  )
97329
97296
  );
97330
- const jsonOption$d = boolean("json").pipe(
97297
+ const jsonOption$8 = boolean("json").pipe(
97331
97298
  withDescription$3('Output in JSON format: {"text":"string","conversationId":"string"}'),
97332
97299
  withDefault(false)
97333
97300
  );
@@ -97341,7 +97308,7 @@ const readStdin = () => tryPromise({
97341
97308
  },
97342
97309
  catch: (e) => new ApiError({ message: `Failed to read stdin: ${e instanceof Error ? e.message : String(e)}` })
97343
97310
  });
97344
- const SPINNER_FRAMES$1 = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
97311
+ const SPINNER_FRAMES = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
97345
97312
  const SPINNER_MESSAGES = ["thinking", "churning", "processing", "pondering", "working", "computing"];
97346
97313
  const formatAgentChatTextOutput = maskSensitiveText;
97347
97314
  const startSpinner = () => {
@@ -97349,22 +97316,22 @@ const startSpinner = () => {
97349
97316
  let frameIdx = 0;
97350
97317
  let msgIdx = 0;
97351
97318
  const timer = setInterval(() => {
97352
- frameIdx = (frameIdx + 1) % SPINNER_FRAMES$1.length;
97319
+ frameIdx = (frameIdx + 1) % SPINNER_FRAMES.length;
97353
97320
  if (frameIdx === 0) msgIdx = (msgIdx + 1) % SPINNER_MESSAGES.length;
97354
- process.stderr.write(`\r${SPINNER_FRAMES$1[frameIdx]} ${SPINNER_MESSAGES[msgIdx]}... `);
97321
+ process.stderr.write(`\r${SPINNER_FRAMES[frameIdx]} ${SPINNER_MESSAGES[msgIdx]}... `);
97355
97322
  }, 80);
97356
97323
  return () => {
97357
97324
  clearInterval(timer);
97358
97325
  process.stderr.write("\r" + " ".repeat(30) + "\r");
97359
97326
  };
97360
97327
  };
97361
- const chatCommand$2 = make$4(
97328
+ const chatCommand$1 = make$4(
97362
97329
  "chat",
97363
97330
  {
97364
97331
  agentId: agentIdOption,
97365
- message: messageOption$2,
97332
+ message: messageOption,
97366
97333
  conversationId: conversationIdOption,
97367
- json: jsonOption$d,
97334
+ json: jsonOption$8,
97368
97335
  org: orgOption
97369
97336
  },
97370
97337
  ({ agentId, message, conversationId, json, org }) => gen(function* () {
@@ -97444,15 +97411,15 @@ const resolveAgentChatTarget = (agentId, conversationId) => {
97444
97411
  const isContinuationTarget = (target) => target.conversationId !== void 0;
97445
97412
 
97446
97413
  const agentIdArg$1 = text$2({ name: "id" }).pipe(withDescription$5("Agent ID"));
97447
- const jsonOption$c = boolean("json").pipe(
97414
+ const jsonOption$7 = boolean("json").pipe(
97448
97415
  withDescription$3(
97449
97416
  'Output in JSON format: {"id":"string","displayName":"string","shortDescription":"string","description":"string|null","createdBy":"string","createdAt":"ISO-8601","updatedAt":"ISO-8601","configRequiredIntegrations":["string"]}'
97450
97417
  ),
97451
97418
  withDefault(false)
97452
97419
  );
97453
- const getCommand$4 = make$4(
97420
+ const getCommand$3 = make$4(
97454
97421
  "get",
97455
- { agentId: agentIdArg$1, org: orgOption, json: jsonOption$c },
97422
+ { agentId: agentIdArg$1, org: orgOption, json: jsonOption$7 },
97456
97423
  ({ agentId, org, json }) => gen(function* () {
97457
97424
  const api = yield* ApiService;
97458
97425
  const orgSlug = yield* resolveOrgSlug(org, api);
@@ -97496,7 +97463,7 @@ const getCommand$4 = make$4(
97496
97463
  })
97497
97464
  ).pipe(withDescription("Get agent details by ID"));
97498
97465
 
97499
- const jsonOption$b = boolean("json").pipe(
97466
+ const jsonOption$6 = boolean("json").pipe(
97500
97467
  withDescription$3(
97501
97468
  'Output in JSON format: [{"id":"string","displayName":"string","agentType":"string","shortDescription":"string","createdBy":"string","createdAt":"ISO-8601"}]'
97502
97469
  ),
@@ -97504,7 +97471,7 @@ const jsonOption$b = boolean("json").pipe(
97504
97471
  );
97505
97472
  const listCommand$7 = make$4(
97506
97473
  "list",
97507
- { org: orgOption, json: jsonOption$b },
97474
+ { org: orgOption, json: jsonOption$6 },
97508
97475
  ({ org, json }) => gen(function* () {
97509
97476
  const api = yield* ApiService;
97510
97477
  const orgSlug = yield* resolveOrgSlug(org, api);
@@ -97611,7 +97578,7 @@ const disableCommand$1 = make$4(
97611
97578
  ).pipe(withDescription("Disable an agent"));
97612
97579
 
97613
97580
  const agentCommandDescription = "Manage agents (list, get, chat, enable, disable)";
97614
- const agentSubcommands = [listCommand$7, getCommand$4, enableCommand$1, disableCommand$1, chatCommand$2];
97581
+ const agentSubcommands = [listCommand$7, getCommand$3, enableCommand$1, disableCommand$1, chatCommand$1];
97615
97582
  const agentCommand = make$4("agent", {}).pipe(
97616
97583
  withDescription(agentCommandDescription),
97617
97584
  withSubcommands(agentSubcommands)
@@ -98166,16 +98133,16 @@ const deleteCommand$2 = make$4(
98166
98133
  ).pipe(withDescription("Delete an automation by ID (requires --force to confirm)"));
98167
98134
 
98168
98135
  const automationIdArg$5 = text$2({ name: "id" }).pipe(withDescription$5("Automation ID"));
98169
- const jsonOption$a = boolean("json").pipe(
98136
+ const jsonOption$5 = boolean("json").pipe(
98170
98137
  withDescription$3(
98171
98138
  'Output in JSON format: {"id":"string","name":"string","status":"string","triggerType":"string","triggerProviderType":"string","agentId":"string","prompt":"string","lastExecutionTime":"ISO-8601|null","lastExecutionStatus":"string|null","lastExecutionChatThreadUrl":"string|null","nextExecutionTime":"ISO-8601|null","trigger":"object","createdAt":"ISO-8601","updatedAt":"ISO-8601"}'
98172
98139
  ),
98173
98140
  withDefault(false)
98174
98141
  );
98175
98142
  const formatAutomationTextOutput = maskSensitiveText;
98176
- const getCommand$3 = make$4(
98143
+ const getCommand$2 = make$4(
98177
98144
  "get",
98178
- { automationId: automationIdArg$5, org: orgOption, json: jsonOption$a },
98145
+ { automationId: automationIdArg$5, org: orgOption, json: jsonOption$5 },
98179
98146
  ({ automationId, org, json }) => gen(function* () {
98180
98147
  const api = yield* ApiService;
98181
98148
  const orgSlug = yield* resolveOrgSlug(org, api);
@@ -98286,7 +98253,7 @@ const nameOption = text("name").pipe(
98286
98253
  withDescription$3("Filter automations by name"),
98287
98254
  optional
98288
98255
  );
98289
- const jsonOption$9 = boolean("json").pipe(
98256
+ const jsonOption$4 = boolean("json").pipe(
98290
98257
  withDescription$3(
98291
98258
  'Output in JSON format: [{"id":"string","name":"string","status":"string","triggerType":"string","nextExecutionTime":"ISO-8601|null","createdAt":"ISO-8601"}]'
98292
98259
  ),
@@ -98294,7 +98261,7 @@ const jsonOption$9 = boolean("json").pipe(
98294
98261
  );
98295
98262
  const listCommand$6 = make$4(
98296
98263
  "list",
98297
- { org: orgOption, name: nameOption, json: jsonOption$9 },
98264
+ { org: orgOption, name: nameOption, json: jsonOption$4 },
98298
98265
  ({ org, name, json }) => gen(function* () {
98299
98266
  const api = yield* ApiService;
98300
98267
  const orgSlug = yield* resolveOrgSlug(org, api);
@@ -98597,7 +98564,7 @@ const webhookRegenCommand = make$4(
98597
98564
  const automationCommandDescription = "Manage automations (list, get, create, update, delete, run, enable, disable, history, cancel, webhook-regen, triggers)";
98598
98565
  const automationSubcommands = [
98599
98566
  listCommand$6,
98600
- getCommand$3,
98567
+ getCommand$2,
98601
98568
  createCommand,
98602
98569
  updateCommand,
98603
98570
  deleteCommand$2,
@@ -98617,7 +98584,7 @@ const automationCommand = make$4("automation", {}).pipe(
98617
98584
  const conversationIdArg$1 = text$2({ name: "conversationId" }).pipe(
98618
98585
  withDescription$5("Conversation ID")
98619
98586
  );
98620
- const getCommand$2 = make$4(
98587
+ const getCommand$1 = make$4(
98621
98588
  "get",
98622
98589
  { conversationId: conversationIdArg$1, org: orgOption },
98623
98590
  ({ conversationId, org }) => gen(function* () {
@@ -98656,7 +98623,7 @@ const getCommand$2 = make$4(
98656
98623
  })
98657
98624
  ).pipe(withDescription("Get conversation details by ID"));
98658
98625
 
98659
- const jsonOption$8 = boolean("json").pipe(
98626
+ const jsonOption$3 = boolean("json").pipe(
98660
98627
  withDescription$3(
98661
98628
  'Output in JSON format: [{"conversationId":"string","title":"string","type":"string","updatedAt":"ISO-8601"}]'
98662
98629
  ),
@@ -98664,7 +98631,7 @@ const jsonOption$8 = boolean("json").pipe(
98664
98631
  );
98665
98632
  const listCommand$5 = make$4(
98666
98633
  "list",
98667
- { org: orgOption, json: jsonOption$8 },
98634
+ { org: orgOption, json: jsonOption$3 },
98668
98635
  ({ org, json }) => gen(function* () {
98669
98636
  const api = yield* ApiService;
98670
98637
  const orgSlug = yield* resolveOrgSlug(org, api);
@@ -98756,174 +98723,9 @@ const messagesCommand = make$4(
98756
98723
  })
98757
98724
  ).pipe(withDescription("List messages in a conversation"));
98758
98725
 
98759
- const filterModelExecModels = (catalog, type) => {
98760
- if (!type) {
98761
- return catalog.models;
98762
- }
98763
- return catalog.models.filter((model) => model.type === type);
98764
- };
98765
- const getModelExecInputSchema = (model) => {
98766
- if (model.inputSchema) {
98767
- return model.inputSchema;
98768
- }
98769
- if (model.type === "image-generation") {
98770
- return {
98771
- type: "object",
98772
- required: ["prompt"],
98773
- properties: {
98774
- prompt: { type: "string" },
98775
- options: {
98776
- type: "object",
98777
- properties: {
98778
- size: { type: "string" },
98779
- n: { type: "integer" }
98780
- }
98781
- }
98782
- }
98783
- };
98784
- }
98785
- return {
98786
- type: "object",
98787
- required: ["input"],
98788
- properties: {
98789
- input: {
98790
- type: "object",
98791
- required: ["text"],
98792
- properties: {
98793
- text: { type: "string" }
98794
- }
98795
- },
98796
- options: { type: "object" }
98797
- }
98798
- };
98799
- };
98800
- const buildModelExecSampleInput = (model) => {
98801
- if (model.type === "image-generation") {
98802
- return {
98803
- prompt: "A small robot reading a book",
98804
- options: { size: "1024x1024", n: 1 }
98805
- };
98806
- }
98807
- return {
98808
- input: { text: "Say hello in one sentence." },
98809
- options: {}
98810
- };
98811
- };
98812
- const buildModelExecChatRequest = (model, input) => ({
98813
- model,
98814
- input
98815
- });
98816
- const buildModelExecImageGenerationRequest = (model, input) => ({
98817
- model,
98818
- prompt: input.prompt,
98819
- ...input.options ? { options: input.options } : {}
98820
- });
98821
- const readJsonInputFile = (path) => tryPromise({
98822
- try: async () => JSON.parse(await fs$1.readFile(path, "utf8")),
98823
- catch: (error) => new ApiError({
98824
- message: `Failed to read JSON input "${path}": ${error instanceof Error ? error.message : String(error)}`
98825
- })
98826
- });
98827
- const saveJsonFile = (path, value) => tryPromise({
98828
- try: async () => {
98829
- await fs$1.writeFile(path, `${JSON.stringify(value, null, 2)}
98830
- `, "utf8");
98831
- },
98832
- catch: (error) => new ApiError({
98833
- message: `Failed to write "${path}": ${error instanceof Error ? error.message : String(error)}`
98834
- })
98835
- });
98836
- const readStdinText = () => tryPromise({
98837
- try: async () => {
98838
- const chunks = [];
98839
- for await (const chunk of process.stdin) {
98840
- chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
98841
- }
98842
- return Buffer.concat(chunks).toString("utf8").trim();
98843
- },
98844
- catch: (error) => new ApiError({
98845
- message: `Failed to read stdin: ${error instanceof Error ? error.message : String(error)}`
98846
- })
98847
- });
98848
-
98849
- const messageOption$1 = optional(
98850
- text("message").pipe(
98851
- withAlias("m"),
98852
- withDescription$3("Message text. If omitted, stdin is used when piped.")
98853
- )
98854
- );
98855
- const conversationOption = optional(
98856
- text("conversation").pipe(
98857
- withDescription$3("Conversation ID to continue")
98858
- )
98859
- );
98860
- const modelOption$2 = optional(
98861
- text("model").pipe(withDescription$3("Chat model ID for a new or continued conversation"))
98862
- );
98863
- const jsonOption$7 = boolean("json").pipe(
98864
- withDescription$3("Output full response as JSON"),
98865
- withDefault(false)
98866
- );
98867
- const buildSendChatMessageRequest = (input) => ({
98868
- conversationId: getOrUndefined(input.conversationId),
98869
- model: getOrUndefined(input.model),
98870
- message: { text: input.text }
98871
- });
98872
- const sendCommand = make$4(
98873
- "send",
98874
- {
98875
- message: messageOption$1,
98876
- conversation: conversationOption,
98877
- model: modelOption$2,
98878
- json: jsonOption$7,
98879
- org: orgOption
98880
- },
98881
- ({ message, conversation, model, json, org }) => gen(function* () {
98882
- const api = yield* ApiService;
98883
- const orgSlug = yield* resolveOrgSlug(org, api);
98884
- const text = yield* resolveMessageText(message);
98885
- const request = buildSendChatMessageRequest({ conversationId: conversation, model, text });
98886
- const result = yield* api.sendChatMessage(orgSlug, request).pipe(
98887
- catchTag(
98888
- "NotLoggedInError",
98889
- (error) => gen(function* () {
98890
- yield* error$1(error.message);
98891
- return yield* fail$3(error);
98892
- })
98893
- ),
98894
- catchTag(
98895
- "ApiError",
98896
- (error) => gen(function* () {
98897
- yield* error$1(`Chat send failed: ${error.message}`);
98898
- return yield* fail$3(error);
98899
- })
98900
- )
98901
- );
98902
- if (json) {
98903
- yield* log(jsonFormat(result));
98904
- return;
98905
- }
98906
- yield* log(maskSensitiveText(result.output.text));
98907
- yield* log(`
98908
- Conversation: ${result.conversationId}`);
98909
- })
98910
- ).pipe(withDescription("Send a conversation-based chat message and print the assistant response"));
98911
- const resolveMessageText = (message) => gen(function* () {
98912
- if (isSome(message)) {
98913
- return message.value;
98914
- }
98915
- if (!process.stdin.isTTY) {
98916
- const text = yield* readStdinText();
98917
- if (text) {
98918
- return text;
98919
- }
98920
- }
98921
- return yield* fail$3(new ApiError({ message: "Provide --message/-m or pipe text through stdin." }));
98922
- });
98923
-
98924
- const chatCommandDescription = "Manage conversations (list, get, messages, send)";
98925
- const chatSubcommands = [listCommand$5, getCommand$2, messagesCommand, sendCommand];
98926
- const chatCommand$1 = make$4("chat", {}).pipe(
98726
+ const chatCommandDescription = "Manage conversations (list, get, messages)";
98727
+ const chatSubcommands = [listCommand$5, getCommand$1, messagesCommand];
98728
+ const chatCommand = make$4("chat", {}).pipe(
98927
98729
  withDescription(chatCommandDescription),
98928
98730
  withSubcommands(chatSubcommands)
98929
98731
  );
@@ -99080,13 +98882,13 @@ const deleteCommand$1 = make$4(
99080
98882
  ).pipe(withDescription("Delete drive entries by ID (requires --force to confirm)"));
99081
98883
 
99082
98884
  const entryIdArg$1 = text$2({ name: "id" }).pipe(withDescription$5("Drive entry ID"));
99083
- const outputOption$1 = text("output").pipe(
98885
+ const outputOption = text("output").pipe(
99084
98886
  withAlias("o"),
99085
98887
  withDescription$3("Output file path (required, as the API does not return the original filename)")
99086
98888
  );
99087
98889
  const downloadCommand = make$4(
99088
98890
  "download",
99089
- { entryId: entryIdArg$1, org: orgOption, output: outputOption$1 },
98891
+ { entryId: entryIdArg$1, org: orgOption, output: outputOption },
99090
98892
  ({ entryId, org, output }) => gen(function* () {
99091
98893
  const api = yield* ApiService;
99092
98894
  const orgSlug = yield* resolveOrgSlug(org, api);
@@ -99507,347 +99309,6 @@ const modelCommand = make$4("model", {}).pipe(
99507
99309
  withSubcommands(modelSubcommands)
99508
99310
  );
99509
99311
 
99510
- const SPINNER_FRAMES = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
99511
- const SPINNER_INTERVAL_MS = 80;
99512
- const CLEAR_WIDTH = 80;
99513
- const startModelExecProgress = (message, options = {}) => {
99514
- const stream = options.stream ?? process.stderr;
99515
- if (!stream.isTTY) return () => void 0;
99516
- const now = options.now ?? Date.now;
99517
- const startedAt = now();
99518
- let frameIndex = 0;
99519
- let stopped = false;
99520
- const render = () => {
99521
- const elapsedSeconds = Math.floor((now() - startedAt) / 1e3);
99522
- stream.write(`\r${SPINNER_FRAMES[frameIndex]} ${message}... ${elapsedSeconds}s`);
99523
- frameIndex = (frameIndex + 1) % SPINNER_FRAMES.length;
99524
- };
99525
- render();
99526
- const timer = setInterval(render, SPINNER_INTERVAL_MS);
99527
- return () => {
99528
- if (stopped) return;
99529
- stopped = true;
99530
- clearInterval(timer);
99531
- stream.write(`\r${" ".repeat(CLEAR_WIDTH)}\r`);
99532
- };
99533
- };
99534
-
99535
- const modelOption$1 = text("model").pipe(withDescription$3("Chat model ID"));
99536
- const messageOption = optional(
99537
- text("message").pipe(
99538
- withAlias("m"),
99539
- withDescription$3("Message text. If omitted, stdin is used when piped.")
99540
- )
99541
- );
99542
- const inputOption$1 = optional(
99543
- text("input").pipe(withDescription$3("JSON input file generated by model-exec sample"))
99544
- );
99545
- const jsonOption$6 = boolean("json").pipe(
99546
- withDescription$3("Output full response as JSON"),
99547
- withDefault(false)
99548
- );
99549
- const chatCommand = make$4(
99550
- "chat",
99551
- { model: modelOption$1, message: messageOption, input: inputOption$1, json: jsonOption$6, org: orgOption },
99552
- ({ model, message, input, json, org }) => gen(function* () {
99553
- const api = yield* ApiService;
99554
- const orgSlug = yield* resolveOrgSlug(org, api);
99555
- const request = yield* resolveChatRequest(model, message, input);
99556
- const stopProgress = startModelExecProgress("Waiting for model response");
99557
- const result = yield* api.executeModelExecChat(orgSlug, request).pipe(
99558
- ensuring$1(sync$1(stopProgress)),
99559
- catchTag(
99560
- "NotLoggedInError",
99561
- (error) => gen(function* () {
99562
- yield* error$1(error.message);
99563
- return yield* fail$3(error);
99564
- })
99565
- ),
99566
- catchTag(
99567
- "ApiError",
99568
- (error) => gen(function* () {
99569
- yield* error$1(`Model-exec chat failed: ${error.message}`);
99570
- return yield* fail$3(error);
99571
- })
99572
- )
99573
- );
99574
- if (json) {
99575
- yield* log(jsonFormat(result));
99576
- return;
99577
- }
99578
- yield* log(maskSensitiveText(result.output.text));
99579
- })
99580
- ).pipe(withDescription("Execute a chat model once without creating a conversation"));
99581
- const resolveChatRequest = (model, message, input) => gen(function* () {
99582
- if (isSome(input)) {
99583
- const parsed = yield* readJsonInputFile(input.value);
99584
- const text = parsed.input?.text;
99585
- if (!text) {
99586
- return yield* fail$3(new ApiError({ message: "Chat input JSON must include input.text" }));
99587
- }
99588
- return {
99589
- model,
99590
- input: { ...parsed.input, text },
99591
- ...parsed.options ? { options: parsed.options } : {}
99592
- };
99593
- }
99594
- if (isSome(message)) {
99595
- return buildModelExecChatRequest(model, { text: message.value });
99596
- }
99597
- if (!process.stdin.isTTY) {
99598
- const text = yield* readStdinText();
99599
- if (text) {
99600
- return buildModelExecChatRequest(model, { text });
99601
- }
99602
- }
99603
- return yield* fail$3(new ApiError({ message: "Provide --message/-m, --input, or pipe text through stdin." }));
99604
- });
99605
-
99606
- const modelIdArg$1 = text$2({ name: "model-id" }).pipe(withDescription$5("Model ID"));
99607
- const jsonOption$5 = boolean("json").pipe(
99608
- withDescription$3("Output model detail as JSON"),
99609
- withDefault(false)
99610
- );
99611
- const getCommand$1 = make$4(
99612
- "get",
99613
- { modelId: modelIdArg$1, org: orgOption, json: jsonOption$5 },
99614
- ({ modelId, org, json }) => gen(function* () {
99615
- const api = yield* ApiService;
99616
- const orgSlug = yield* resolveOrgSlug(org, api);
99617
- const catalog = yield* api.listModelExecModels(orgSlug).pipe(
99618
- catchTag(
99619
- "NotLoggedInError",
99620
- (error) => gen(function* () {
99621
- yield* error$1(error.message);
99622
- return yield* fail$3(error);
99623
- })
99624
- ),
99625
- catchTag(
99626
- "ApiError",
99627
- (error) => gen(function* () {
99628
- yield* error$1(`Failed to fetch model "${modelId}": ${error.message}`);
99629
- return yield* fail$3(error);
99630
- })
99631
- )
99632
- );
99633
- const model = catalog.models.find((item) => item.id === modelId);
99634
- if (!model) {
99635
- const error = new ApiError({ message: `Model "${modelId}" not found.`, statusCode: 404 });
99636
- yield* error$1(error.message);
99637
- return yield* fail$3(error);
99638
- }
99639
- const detail = { ...model, inputSchema: getModelExecInputSchema(model) };
99640
- if (json) {
99641
- yield* log(jsonFormat(detail));
99642
- return;
99643
- }
99644
- yield* log(`Model: ${detail.id}`);
99645
- yield* log(` Type: ${detail.type}`);
99646
- if (detail.displayName) yield* log(` Name: ${detail.displayName}`);
99647
- yield* log(" Input schema:");
99648
- yield* log(jsonFormat(detail.inputSchema));
99649
- })
99650
- ).pipe(withDescription("Show model-exec model detail and input schema"));
99651
-
99652
- const modelOption = text("model").pipe(withDescription$3("Image-generation model ID"));
99653
- const promptOption = optional(
99654
- text("prompt").pipe(withDescription$3("Image prompt"))
99655
- );
99656
- const inputOption = optional(
99657
- text("input").pipe(withDescription$3("JSON input file generated by model-exec sample"))
99658
- );
99659
- const outputOption = text("output").pipe(withDescription$3("Output image file path"));
99660
- const jsonOption$4 = boolean("json").pipe(
99661
- withDescription$3("Output full response as JSON after saving the image"),
99662
- withDefault(false)
99663
- );
99664
- const generateCommand = make$4(
99665
- "generate",
99666
- {
99667
- model: modelOption,
99668
- prompt: promptOption,
99669
- input: inputOption,
99670
- output: outputOption,
99671
- json: jsonOption$4,
99672
- org: orgOption
99673
- },
99674
- ({ model, prompt, input, output, json, org }) => gen(function* () {
99675
- const api = yield* ApiService;
99676
- const orgSlug = yield* resolveOrgSlug(org, api);
99677
- const request = yield* resolveImageRequest(model, prompt, input);
99678
- const stopProgress = startModelExecProgress("Generating image (timeout: 5m)");
99679
- const result = yield* gen(function* () {
99680
- const response = yield* api.executeModelExecImageGeneration(orgSlug, request);
99681
- const first = response.outputs[0];
99682
- if (!first) {
99683
- return yield* fail$3(new ApiError({ message: "Image generation returned no outputs." }));
99684
- }
99685
- const buffer = yield* api.downloadFromUrl(first.downloadUrl);
99686
- yield* writeImageFile(output, buffer);
99687
- return response;
99688
- }).pipe(
99689
- ensuring$1(sync$1(stopProgress)),
99690
- catchTag(
99691
- "NotLoggedInError",
99692
- (error) => gen(function* () {
99693
- yield* error$1(error.message);
99694
- return yield* fail$3(error);
99695
- })
99696
- ),
99697
- catchTag(
99698
- "ApiError",
99699
- (error) => gen(function* () {
99700
- yield* error$1(`Image generation failed: ${error.message}`);
99701
- return yield* fail$3(error);
99702
- })
99703
- )
99704
- );
99705
- if (json) {
99706
- yield* log(jsonFormat({ ...result, savedPath: output }));
99707
- return;
99708
- }
99709
- yield* log(`Saved image to ${output}`);
99710
- })
99711
- ).pipe(
99712
- withDescription(
99713
- "Generate an image once and save the first output artifact (5-minute timeout)"
99714
- )
99715
- );
99716
- const imageCommand = make$4("image", {}).pipe(
99717
- withDescription("Run image-generation model-exec commands"),
99718
- withSubcommands([generateCommand])
99719
- );
99720
- const resolveImageRequest = (model, prompt, input) => gen(function* () {
99721
- if (isSome(input)) {
99722
- const parsed = yield* readJsonInputFile(input.value);
99723
- if (!parsed.prompt) {
99724
- return yield* fail$3(new ApiError({ message: "Image input JSON must include prompt" }));
99725
- }
99726
- return buildModelExecImageGenerationRequest(model, {
99727
- prompt: parsed.prompt,
99728
- ...parsed.options ? { options: parsed.options } : {}
99729
- });
99730
- }
99731
- if (isSome(prompt)) {
99732
- return buildModelExecImageGenerationRequest(model, { prompt: prompt.value });
99733
- }
99734
- return yield* fail$3(new ApiError({ message: "Provide --prompt or --input." }));
99735
- });
99736
- const writeImageFile = (path, buffer) => tryPromise({
99737
- try: async () => {
99738
- await fs$1.writeFile(path, buffer);
99739
- },
99740
- catch: (error) => new ApiError({
99741
- message: `Failed to write image "${path}": ${error instanceof Error ? error.message : String(error)}`
99742
- })
99743
- });
99744
-
99745
- const typeOption = optional(
99746
- text("type").pipe(
99747
- withDescription$3("Filter by model type: chat, image-generation, embedding")
99748
- )
99749
- );
99750
- const jsonOption$3 = boolean("json").pipe(
99751
- withDescription$3("Output model catalog as JSON"),
99752
- withDefault(false)
99753
- );
99754
- const modelsCommand = make$4(
99755
- "models",
99756
- { org: orgOption, type: typeOption, json: jsonOption$3 },
99757
- ({ org, type, json }) => gen(function* () {
99758
- const api = yield* ApiService;
99759
- const orgSlug = yield* resolveOrgSlug(org, api);
99760
- const catalog = yield* api.listModelExecModels(orgSlug).pipe(
99761
- catchTag(
99762
- "NotLoggedInError",
99763
- (error) => gen(function* () {
99764
- yield* error$1(error.message);
99765
- return yield* fail$3(error);
99766
- })
99767
- ),
99768
- catchTag(
99769
- "ApiError",
99770
- (error) => gen(function* () {
99771
- yield* error$1(`Failed to fetch model-exec models: ${error.message}`);
99772
- return yield* fail$3(error);
99773
- })
99774
- )
99775
- );
99776
- const models = filterModelExecModels(catalog, getOrUndefined(type));
99777
- if (json) {
99778
- yield* log(jsonFormat({ ...catalog, models }));
99779
- return;
99780
- }
99781
- if (models.length === 0) {
99782
- yield* log("No model-exec models available.");
99783
- return;
99784
- }
99785
- yield* log(`Model-exec models in organization "${orgSlug}":
99786
- `);
99787
- for (const model of models) {
99788
- const name = model.displayName ? ` (${model.displayName})` : "";
99789
- const marker = model.default ? " default" : "";
99790
- yield* log(` ${model.id}${name}`);
99791
- yield* log(` Type: ${model.type}${marker}`);
99792
- }
99793
- })
99794
- ).pipe(withDescription("List experimental model-exec models by capability"));
99795
-
99796
- const modelIdArg = text$2({ name: "model-id" }).pipe(withDescription$5("Model ID"));
99797
- const saveOption = optional(
99798
- text("save").pipe(withDescription$3("Save sample JSON to a file"))
99799
- );
99800
- const sampleCommand = make$4(
99801
- "sample",
99802
- { modelId: modelIdArg, org: orgOption, save: saveOption },
99803
- ({ modelId, org, save }) => gen(function* () {
99804
- const api = yield* ApiService;
99805
- const orgSlug = yield* resolveOrgSlug(org, api);
99806
- const catalog = yield* api.listModelExecModels(orgSlug).pipe(
99807
- catchTag(
99808
- "NotLoggedInError",
99809
- (error) => gen(function* () {
99810
- yield* error$1(error.message);
99811
- return yield* fail$3(error);
99812
- })
99813
- ),
99814
- catchTag(
99815
- "ApiError",
99816
- (error) => gen(function* () {
99817
- yield* error$1(`Failed to fetch model "${modelId}": ${error.message}`);
99818
- return yield* fail$3(error);
99819
- })
99820
- )
99821
- );
99822
- const model = catalog.models.find((item) => item.id === modelId);
99823
- if (!model) {
99824
- const error = new ApiError({ message: `Model "${modelId}" not found.`, statusCode: 404 });
99825
- yield* error$1(error.message);
99826
- return yield* fail$3(error);
99827
- }
99828
- const sample = buildModelExecSampleInput(model);
99829
- if (isSome(save)) {
99830
- yield* saveJsonFile(save.value, sample);
99831
- yield* log(`Saved sample input to ${save.value}`);
99832
- return;
99833
- }
99834
- yield* log(jsonFormat(sample));
99835
- })
99836
- ).pipe(withDescription("Generate sample JSON input for a model-exec model"));
99837
-
99838
- const modelExecCommandDescription = "Experimental one-shot model execution for chat and image-generation models";
99839
- const modelExecSubcommands = [
99840
- modelsCommand,
99841
- getCommand$1,
99842
- sampleCommand,
99843
- chatCommand,
99844
- imageCommand
99845
- ];
99846
- const modelExecCommand = make$4("model-exec", {}).pipe(
99847
- withDescription(modelExecCommandDescription),
99848
- withSubcommands(modelExecSubcommands)
99849
- );
99850
-
99851
99312
  const capabilitiesCommand = make$4(
99852
99313
  "capabilities",
99853
99314
  { org: orgOption },
@@ -100540,12 +100001,11 @@ const rootSubcommands = [
100540
100001
  agentCommand,
100541
100002
  authCommand,
100542
100003
  automationCommand,
100543
- chatCommand$1,
100004
+ chatCommand,
100544
100005
  configCommand,
100545
100006
  driveCommand,
100546
100007
  integrationCommand,
100547
100008
  modelCommand,
100548
- modelExecCommand,
100549
100009
  orgCommand,
100550
100010
  skillCommand,
100551
100011
  ...nativeSubcommands
@@ -58,7 +58,6 @@
58
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 |
59
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
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
61
  | 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
62
  | 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
63
  | 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 |
@@ -83,7 +82,6 @@
83
82
  - `P1-PRESET-01` preset admin namespace/docs + legacy path tests done
84
83
  - `P1-SKILL-01` skill JSON/help/docs field sync done
85
84
  - `P1-CHAT-01` chat SSE fixture tests added for final/fallback/error cases
86
- - `P1-MODEL-EXEC-01` experimental CLI model-exec contract remains OAS-missing; current Chat controller/DTO and CLI path tests are recorded
87
85
 
88
86
  ## Manual notes
89
87
 
@@ -59,7 +59,7 @@ desktop/packages/cli/
59
59
 
60
60
  - package base version: `0.0.0`
61
61
  - publish-time CalVer가 `AIPCTL_VERSION`으로 TS bundle과 Go ldflags에 주입됩니다.
62
- - `AIPCTL_BUILD_ENV`는 `local|dev|qa|stage|prod|test` 중 하나이며 `logs` gating에 사용됩니다.
62
+ - `AIPCTL_BUILD_ENV`는 `local|dev|stage|prod|test` 중 하나이며 `logs` gating에 사용됩니다.
63
63
  - native input hash가 이전 발행본과 같으면 platform package를 새로 빌드하지 않고 기존 version을 재사용합니다.
64
64
 
65
65
  ## Dependency direction
@@ -4,7 +4,7 @@
4
4
 
5
5
  공통 규칙은 중앙 문서를 따른다.
6
6
 
7
- - [docs/rules/go-coding-guidelines.md](../../../../docs/rules/go-coding-guidelines.md)
7
+ - [docs/rules/go-coding-guidelines.md](/Users/evan/Desktop/Work/duplo/docs/rules/go-coding-guidelines.md)
8
8
 
9
9
  ## `desktop`에서 특히 중요한 규칙
10
10
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "aipctl",
3
- "version": "2026.7.14",
3
+ "version": "2026.7.16",
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": "12a38c7debad3bfb52aca611319439410508b894852126f06e9e3bd337b39fc3",
26
- "wrapperHash": "bf67d4c747818e036614ed04e2e492ba4d5c1f125ee2a4f73d1329a63a5c32a8",
25
+ "contentHash": "156db2615eb6ffb678be96f2e25f38d9628decf8121bcbf638755924ef6fe6ca",
26
+ "wrapperHash": "bf02d1a5ff6b11af9ea359c0e5996a361d47b0f9f5414b7e590477deae7cfe9f",
27
27
  "nativeHash": "bfaa115ac53b30ba141fbe842585a0ed0fca487e2eb356cda219516e53c8b4c0"
28
28
  },
29
29
  "optionalDependencies": {
30
- "aipctl-darwin-x64": "2026.7.13",
31
- "aipctl-darwin-arm64": "2026.7.13",
32
- "aipctl-linux-x64": "2026.7.13",
33
- "aipctl-linux-arm64": "2026.7.13",
34
- "aipctl-windows-x64": "2026.7.13",
35
- "aipctl-windows-arm64": "2026.7.13"
30
+ "aipctl-darwin-x64": "2026.7.16",
31
+ "aipctl-darwin-arm64": "2026.7.16",
32
+ "aipctl-linux-x64": "2026.7.16",
33
+ "aipctl-linux-arm64": "2026.7.16",
34
+ "aipctl-windows-x64": "2026.7.16",
35
+ "aipctl-windows-arm64": "2026.7.16"
36
36
  }
37
37
  }