@gravity-rail/cli 0.7.3 → 0.8.0

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/dist/gr.js CHANGED
@@ -5,7 +5,7 @@ import { dirname } from 'node:path';
5
5
  import fs, { readFileSync, existsSync, mkdirSync, writeFileSync, createWriteStream, chmodSync, unlinkSync } from 'fs';
6
6
  import path3, { join, resolve, dirname as dirname$1 } from 'path';
7
7
  import { createServer } from 'http';
8
- import { randomBytes, createHash } from 'crypto';
8
+ import { randomUUID, randomBytes, createHash } from 'crypto';
9
9
  import { execSync, execFile, exec, spawn, spawnSync } from 'child_process';
10
10
  import * as readline from 'readline';
11
11
  import readline__default from 'readline';
@@ -2685,7 +2685,7 @@ var init_libphonenumber_js = __esm({
2685
2685
  }
2686
2686
  });
2687
2687
 
2688
- // ../sdk/dist/chunk-YCASSXLL.js
2688
+ // ../sdk/dist/chunk-ML55PVP7.js
2689
2689
  function getCookieValue(name) {
2690
2690
  if (typeof document === "undefined") return void 0;
2691
2691
  const cookies = document.cookie.split(";");
@@ -2912,6 +2912,7 @@ function bindAgentsMethods(target, agents) {
2912
2912
  target.archiveAgent = agents.archiveAgent.bind(agents);
2913
2913
  target.unarchiveAgent = agents.unarchiveAgent.bind(agents);
2914
2914
  target.resolveAgentTools = agents.resolveAgentTools.bind(agents);
2915
+ target.listAgentAbilities = agents.listAgentAbilities.bind(agents);
2915
2916
  }
2916
2917
  function bindTasksMethods(target, tasks, abilities) {
2917
2918
  target.getTasks = tasks.getTasks.bind(tasks);
@@ -2923,6 +2924,11 @@ function bindTasksMethods(target, tasks, abilities) {
2923
2924
  target.unarchiveTask = tasks.unarchiveTask.bind(tasks);
2924
2925
  target.cloneTask = tasks.cloneTask.bind(tasks);
2925
2926
  target.getAbilityTypes = abilities.getAbilityTypes.bind(abilities);
2927
+ target.getAbilityType = abilities.getAbilityType.bind(abilities);
2928
+ target.listAbilities = abilities.listAbilities.bind(abilities);
2929
+ target.createAbility = abilities.createAbility.bind(abilities);
2930
+ target.updateAbility = abilities.updateAbility.bind(abilities);
2931
+ target.deleteAbility = abilities.deleteAbility.bind(abilities);
2926
2932
  }
2927
2933
  function bindChatsMethods(target, chats) {
2928
2934
  target.getChats = chats.getChats.bind(chats);
@@ -3447,6 +3453,8 @@ function bindBillingMethods(target, apiKeys, subscriptions, reports) {
3447
3453
  target.updateSubscription = subscriptions.updateSubscription.bind(subscriptions);
3448
3454
  target.addWorkspaceToSubscription = subscriptions.addWorkspaceToSubscription.bind(subscriptions);
3449
3455
  target.purchaseCredits = subscriptions.purchaseCredits.bind(subscriptions);
3456
+ target.createCheckoutSession = subscriptions.createCheckoutSession.bind(subscriptions);
3457
+ target.listSelfServeProducts = subscriptions.listSelfServeProducts.bind(subscriptions);
3450
3458
  target.getAIUsageReport = reports.getAIUsageReport.bind(reports);
3451
3459
  target.getSMSUsageReport = reports.getSMSUsageReport.bind(reports);
3452
3460
  target.getPhoneUsageReport = reports.getPhoneUsageReport.bind(reports);
@@ -3640,6 +3648,7 @@ function bindIntegrationsMethods(target, mondayIntegration, discordBots, slackAp
3640
3648
  target.updatePlatformApp = appConnections.updatePlatformApp.bind(appConnections);
3641
3649
  target.deletePlatformApp = appConnections.deletePlatformApp.bind(appConnections);
3642
3650
  target.listConnectionMemberFieldKeys = appConnections.listConnectionMemberFieldKeys.bind(appConnections);
3651
+ target.setDefaultGooglePlatformAccount = appConnections.setDefaultGooglePlatformAccount.bind(appConnections);
3643
3652
  }
3644
3653
  function bindOperatorMethods(target, operatorGroups) {
3645
3654
  target.getOperatorGroups = operatorGroups.getOperatorGroups.bind(operatorGroups);
@@ -3673,6 +3682,8 @@ function bindOrgMethods(target, org) {
3673
3682
  target.updateBusinessProfile = org.updateBusinessProfile.bind(org);
3674
3683
  target.submitBusinessProfile = org.submitBusinessProfile.bind(org);
3675
3684
  target.cancelBusinessProfile = org.cancelBusinessProfile.bind(org);
3685
+ target.createOrganizationWorkspace = org.createOrganizationWorkspace.bind(org);
3686
+ target.getOrgBillingCustomer = org.getOrgBillingCustomer.bind(org);
3676
3687
  }
3677
3688
  function bindPronunciationsMethods(target, pronunciations) {
3678
3689
  target.getPronunciationEntries = pronunciations.getPronunciationEntries.bind(pronunciations);
@@ -3785,8 +3796,8 @@ function bindSupportRequestMethods(target, supportRequests) {
3785
3796
  target.clickWorkspaceSupportRequestResource = supportRequests.clickWorkspaceSupportRequestResource.bind(supportRequests);
3786
3797
  }
3787
3798
  var ApiError, BaseApiClient, AbilitiesApi, AccessGrantsApi, AgentTasksApi, AgentsApi, AIModelsApi, ApiKeysApi, AppsApi, AssignmentsApi, VoiceApi, AuthApi, BuildersApi, CalendarsApi, CallsApi, CELApi, ChatsApi, ConfluenceApi, CustomToolkitsApi, DataTypesApi, DiscordBotsApi, SlackAppsApi, EventsApi, FeaturesApi, FhirConnectionsApi, HealthieApi, FilesApi, InboxesApi, InquiriesApi, AppConnectionsApi, McpServersApi, MembersApi, MilestonesApi, MondayIntegrationApi, NotificationRulesApi, OperatorApi, OrgApi, OAuthConnectionsApi, OAuthApi, PhoneNumbersApi, PronunciationsApi, PromptsApi, PersonasApi, QualificationsApi, ReportsApi, SalesforceApi, ConnectionSyncApi, HubspotApi, SitesApi, SubscriptionsApi, SupportRequestsApi, CustomersApi, ResellersApi, SupervisorsApi, TasksApi, TemplatesApi, ToolkitsApi, JourneysApi, WorkflowsApi, WorkflowNotesApi, EventRuleEventType, WorkspaceInvitationsApi, WorkspacesApi, TeamsAppsApi, ExperimentsApi, WORKSPACE_METHOD_NAMES, WORKSPACE_METHOD_NAME_SET, GravityRailClient, CHAT_TYPES, BUILTIN_ASSISTANT_CHAT_TYPES;
3788
- var init_chunk_YCASSXLL = __esm({
3789
- "../sdk/dist/chunk-YCASSXLL.js"() {
3799
+ var init_chunk_ML55PVP7 = __esm({
3800
+ "../sdk/dist/chunk-ML55PVP7.js"() {
3790
3801
  init_libphonenumber_js();
3791
3802
  ApiError = class extends Error {
3792
3803
  statusCode;
@@ -4202,10 +4213,52 @@ ${formattedErrors}`, response.status);
4202
4213
  };
4203
4214
  AbilitiesApi = class extends BaseApiClient {
4204
4215
  /**
4205
- * List all available ability types from the registry.
4216
+ * List available ability types from the registry.
4217
+ * Pass includeSystem to also return auto-injected system abilities.
4206
4218
  */
4207
- async getAbilityTypes(wid) {
4208
- return this.fetch(`w/${wid}/abilities/types`);
4219
+ async getAbilityTypes(wid, options = {}) {
4220
+ const params = new URLSearchParams();
4221
+ if (options.includeSystem) params.append("includeSystem", "true");
4222
+ const qs = params.toString() ? `?${params.toString()}` : "";
4223
+ return this.fetch(`w/${wid}/abilities/types${qs}`);
4224
+ }
4225
+ /** Get the full spec for a single ability type by slug. */
4226
+ async getAbilityType(wid, slug) {
4227
+ return this.fetch(
4228
+ `w/${wid}/abilities/types/${encodeURIComponent(slug)}`
4229
+ );
4230
+ }
4231
+ /**
4232
+ * List configured ability instances for a workflow or task scope.
4233
+ * Exactly one of workflowId / taskId must be provided.
4234
+ */
4235
+ async listAbilities(wid, options) {
4236
+ const params = new URLSearchParams();
4237
+ if (options.workflowId !== void 0)
4238
+ params.append("workflowId", options.workflowId.toString());
4239
+ if (options.taskId !== void 0)
4240
+ params.append("taskId", options.taskId.toString());
4241
+ return this.fetch(`w/${wid}/abilities?${params}`);
4242
+ }
4243
+ /** Create (enable) a configured ability on a workflow or task scope. */
4244
+ async createAbility(wid, body) {
4245
+ return this.fetch(`w/${wid}/abilities`, {
4246
+ method: "POST",
4247
+ body: JSON.stringify(body)
4248
+ });
4249
+ }
4250
+ /** Update a configured ability (configure / enable / disable) by UUID. */
4251
+ async updateAbility(wid, abilityUuid, body) {
4252
+ return this.fetch(`w/${wid}/abilities/${abilityUuid}`, {
4253
+ method: "PATCH",
4254
+ body: JSON.stringify(body)
4255
+ });
4256
+ }
4257
+ /** Delete a configured ability instance by UUID. */
4258
+ async deleteAbility(wid, abilityUuid) {
4259
+ return this.fetch(`w/${wid}/abilities/${abilityUuid}`, {
4260
+ method: "DELETE"
4261
+ });
4209
4262
  }
4210
4263
  };
4211
4264
  AccessGrantsApi = class extends BaseApiClient {
@@ -4362,9 +4415,21 @@ ${formattedErrors}`, response.status);
4362
4415
  async resolveAgentTools(wid, id, options) {
4363
4416
  const params = new URLSearchParams();
4364
4417
  params.append("channel", options.channel);
4365
- params.append("taskId", options.taskId.toString());
4418
+ if (options.taskId !== void 0) params.append("taskId", options.taskId.toString());
4419
+ if (options.taskUuid !== void 0) params.append("taskUuid", options.taskUuid);
4366
4420
  return this.fetch(`w/${wid}/agents/${id}/resolve-tools?${params}`);
4367
4421
  }
4422
+ /**
4423
+ * List the configured abilities effective for an agent via a task's workflow.
4424
+ * Requires taskId because abilities are scoped to workflows/tasks, not agents.
4425
+ */
4426
+ async listAgentAbilities(wid, id, options) {
4427
+ const params = new URLSearchParams();
4428
+ params.append("taskId", options.taskId.toString());
4429
+ return this.fetch(
4430
+ `w/${wid}/agents/${id}/abilities?${params}`
4431
+ );
4432
+ }
4368
4433
  };
4369
4434
  AIModelsApi = class extends BaseApiClient {
4370
4435
  /**
@@ -4420,7 +4485,11 @@ ${formattedErrors}`, response.status);
4420
4485
  return this.fetch(url);
4421
4486
  }
4422
4487
  /**
4423
- * Get available speech-to-text models
4488
+ * Get available speech-to-text models.
4489
+ *
4490
+ * Returns the per-shape `STTModelsResponse` so callers see `languages` and
4491
+ * `capabilities` on each model (the chat-shape `AIModelsResponse` it used
4492
+ * to return doesn't include either).
4424
4493
  */
4425
4494
  async getSTTModels(provider) {
4426
4495
  const searchParams = new URLSearchParams();
@@ -7137,6 +7206,12 @@ ${formattedErrors}`, response.status);
7137
7206
  * values are intentionally never exposed. Operators can also add a
7138
7207
  * new key via the UI's "Add custom field key" free-text action.
7139
7208
  */
7209
+ async setDefaultGooglePlatformAccount(wid, connectionUuid, credentialUuid) {
7210
+ return this.fetch(
7211
+ `w/${wid}/app-connections/google/platform-apps/${connectionUuid}/accounts/${credentialUuid}/default`,
7212
+ { method: "POST" }
7213
+ );
7214
+ }
7140
7215
  async listConnectionMemberFieldKeys(wid, connectionId) {
7141
7216
  return this.fetch(
7142
7217
  `w/${wid}/app-connections/${connectionId}/member-field-keys`
@@ -9418,6 +9493,28 @@ ${formattedErrors}`, response.status);
9418
9493
  async getSubscriptions() {
9419
9494
  return this.fetch("subscriptions");
9420
9495
  }
9496
+ /**
9497
+ * Create a Stripe Checkout session to purchase an organization plan.
9498
+ * Returns the checkout URL to open in a browser. The organization, billing
9499
+ * customer, and subscription are created on payment by the checkout
9500
+ * completion handler.
9501
+ */
9502
+ async createCheckoutSession(productId, planPeriod = "month") {
9503
+ return this.fetch(`subscriptions/checkout-session`, {
9504
+ method: "POST",
9505
+ credentials: "include",
9506
+ body: JSON.stringify({ productId, planPeriod }),
9507
+ headers: { "Content-Type": "application/json" }
9508
+ });
9509
+ }
9510
+ /**
9511
+ * List self-service, purchasable plans (org or workspace). Only plans with a
9512
+ * paid Stripe price are returned. No auth required.
9513
+ */
9514
+ async listSelfServeProducts(productType2) {
9515
+ const qs = productType2 ? `?product_type=${productType2}` : "";
9516
+ return this.fetch(`products/self-service${qs}`);
9517
+ }
9421
9518
  /** List all subscriptions associated with a workspace. */
9422
9519
  async getWorkspaceSubscriptions(wid) {
9423
9520
  return this.fetch(`w/${wid}/subscriptions`);
@@ -9458,6 +9555,10 @@ ${formattedErrors}`, response.status);
9458
9555
  }
9459
9556
  });
9460
9557
  }
9558
+ /** List line items for a subscription. */
9559
+ async getSubscriptionItems(subscriptionId) {
9560
+ return this.fetch(`subscriptions/${subscriptionId}/items`);
9561
+ }
9461
9562
  /** Purchase extra credits on a subscription (org-level). */
9462
9563
  async purchaseCredits(subscriptionId, amountCents) {
9463
9564
  return this.fetch(`subscriptions/${subscriptionId}/purchase-credits`, {
@@ -9681,6 +9782,12 @@ ${formattedErrors}`, response.status);
9681
9782
  if (options.workflowId) {
9682
9783
  params.append("workflow_id", options.workflowId.toString());
9683
9784
  }
9785
+ if (options.sortBy) {
9786
+ params.append("sortBy", options.sortBy);
9787
+ }
9788
+ if (options.sortOrder) {
9789
+ params.append("sortOrder", options.sortOrder);
9790
+ }
9684
9791
  return this.fetch(
9685
9792
  `w/${wid}/tasks${params.toString() ? `?${params.toString()}` : ""}`
9686
9793
  );
@@ -10043,9 +10150,17 @@ ${formattedErrors}`, response.status);
10043
10150
  `w/${wid}/workflows/activity/batch?${params.toString()}`
10044
10151
  );
10045
10152
  }
10046
- /** Get the Mermaid diagram representation of a workflow. */
10047
- async getWorkflowDiagram(wid, id) {
10048
- return this.fetch(`w/${wid}/workflows/${id}/diagram`);
10153
+ /**
10154
+ * Get the Mermaid diagram representation of a workflow.
10155
+ *
10156
+ * By default only active tasks are rendered. Pass `includeArchived: true`
10157
+ * to also render archived tasks (distinctly styled). `taskCount` is always
10158
+ * the total (active + archived); `archivedTaskCount` breaks out the archived
10159
+ * portion so the active count can be derived.
10160
+ */
10161
+ async getWorkflowDiagram(wid, id, options = {}) {
10162
+ const query = options.includeArchived ? "?include_archived=true" : "";
10163
+ return this.fetch(`w/${wid}/workflows/${id}/diagram${query}`);
10049
10164
  }
10050
10165
  /**
10051
10166
  * Get workflow thumbnail URL.
@@ -10993,6 +11108,7 @@ ${formattedErrors}`, response.status);
10993
11108
  "convertEmail",
10994
11109
  "convertFile",
10995
11110
  "crawlSite",
11111
+ "createAbility",
10996
11112
  "createAccessGrant",
10997
11113
  "createAgent",
10998
11114
  "createApiKey",
@@ -11056,6 +11172,7 @@ ${formattedErrors}`, response.status);
11056
11172
  "createWorkspaceMember",
11057
11173
  "createWorkspaceSupportRequest",
11058
11174
  "deactivateWorkflowVersion",
11175
+ "deleteAbility",
11059
11176
  "deleteAgent",
11060
11177
  "deleteAssignment",
11061
11178
  "deleteCalendar",
@@ -11179,6 +11296,7 @@ ${formattedErrors}`, response.status);
11179
11296
  "generateICalToken",
11180
11297
  "generateSiteMediaUploadUrl",
11181
11298
  "getAIUsageReport",
11299
+ "getAbilityType",
11182
11300
  "getAbilityTypes",
11183
11301
  "getAccessGrant",
11184
11302
  "getAccessGrants",
@@ -11466,11 +11584,14 @@ ${formattedErrors}`, response.status);
11466
11584
  "linkMemberToMonday",
11467
11585
  "linkMemberToSalesforce",
11468
11586
  "linkPhoneNumber",
11587
+ "listAbilities",
11588
+ "listAgentAbilities",
11469
11589
  "listAppConnections",
11470
11590
  "listAvailableAppConnections",
11471
11591
  "listConfluencePages",
11472
11592
  "listConfluenceSpaces",
11473
11593
  "listConnectionMemberFieldKeys",
11594
+ "setDefaultGooglePlatformAccount",
11474
11595
  "listGoogleCalendars",
11475
11596
  "listHealthieAppointmentTypes",
11476
11597
  "listHealthiePatients",
@@ -11559,6 +11680,7 @@ ${formattedErrors}`, response.status);
11559
11680
  "unlinkMemberFromMonday",
11560
11681
  "unlinkMemberFromSalesforce",
11561
11682
  "unregisterPushSubscription",
11683
+ "updateAbility",
11562
11684
  "updateAgent",
11563
11685
  "updateAssignment",
11564
11686
  "updateCalendar",
@@ -11653,6 +11775,11 @@ ${formattedErrors}`, response.status);
11653
11775
  unarchiveTask;
11654
11776
  cloneTask;
11655
11777
  getAbilityTypes;
11778
+ getAbilityType;
11779
+ listAbilities;
11780
+ createAbility;
11781
+ updateAbility;
11782
+ deleteAbility;
11656
11783
  // Chats API
11657
11784
  getChats;
11658
11785
  getChat;
@@ -11792,6 +11919,7 @@ ${formattedErrors}`, response.status);
11792
11919
  archiveAgent;
11793
11920
  unarchiveAgent;
11794
11921
  resolveAgentTools;
11922
+ listAgentAbilities;
11795
11923
  // Qualifications API
11796
11924
  getQualifications;
11797
11925
  getQualification;
@@ -11946,6 +12074,8 @@ ${formattedErrors}`, response.status);
11946
12074
  updateBusinessProfile;
11947
12075
  submitBusinessProfile;
11948
12076
  cancelBusinessProfile;
12077
+ createOrganizationWorkspace;
12078
+ getOrgBillingCustomer;
11949
12079
  getVapidPublicKey;
11950
12080
  registerPushSubscription;
11951
12081
  unregisterPushSubscription;
@@ -12274,6 +12404,8 @@ ${formattedErrors}`, response.status);
12274
12404
  updateSubscription;
12275
12405
  addWorkspaceToSubscription;
12276
12406
  purchaseCredits;
12407
+ createCheckoutSession;
12408
+ listSelfServeProducts;
12277
12409
  getAIUsageReport;
12278
12410
  getSMSUsageReport;
12279
12411
  getPhoneUsageReport;
@@ -12476,6 +12608,7 @@ ${formattedErrors}`, response.status);
12476
12608
  updatePlatformApp;
12477
12609
  deletePlatformApp;
12478
12610
  listConnectionMemberFieldKeys;
12611
+ setDefaultGooglePlatformAccount;
12479
12612
  // Pronunciations API
12480
12613
  getPronunciationEntries;
12481
12614
  createPronunciationEntry;
@@ -12718,7 +12851,7 @@ var init_chunk_QS6ZRQUZ = __esm({
12718
12851
  var SEARCHABLE_EVENT_RULE_SOURCE_FIELDS;
12719
12852
  var init_dist = __esm({
12720
12853
  "../sdk/dist/index.js"() {
12721
- init_chunk_YCASSXLL();
12854
+ init_chunk_ML55PVP7();
12722
12855
  init_chunk_QS6ZRQUZ();
12723
12856
  SEARCHABLE_EVENT_RULE_SOURCE_FIELDS = [
12724
12857
  "taskId",
@@ -30811,9 +30944,9 @@ var require_sender = __commonJS({
30811
30944
  constructor(socket) {
30812
30945
  this.#socket = socket;
30813
30946
  }
30814
- add(item, cb, hint) {
30815
- if (hint !== sendHints.blob) {
30816
- const frame = createFrame(item, hint);
30947
+ add(item, cb, hint2) {
30948
+ if (hint2 !== sendHints.blob) {
30949
+ const frame = createFrame(item, hint2);
30817
30950
  if (!this.#running) {
30818
30951
  this.#socket.write(frame, cb);
30819
30952
  } else {
@@ -30829,7 +30962,7 @@ var require_sender = __commonJS({
30829
30962
  const node = {
30830
30963
  promise: item.arrayBuffer().then((ab) => {
30831
30964
  node.promise = null;
30832
- node.frame = createFrame(ab, hint);
30965
+ node.frame = createFrame(ab, hint2);
30833
30966
  }),
30834
30967
  callback: cb,
30835
30968
  frame: null
@@ -30853,11 +30986,11 @@ var require_sender = __commonJS({
30853
30986
  this.#running = false;
30854
30987
  }
30855
30988
  };
30856
- function createFrame(data, hint) {
30857
- return new WebsocketFrameSend(toBuffer(data, hint)).createFrame(hint === sendHints.string ? opcodes.TEXT : opcodes.BINARY);
30989
+ function createFrame(data, hint2) {
30990
+ return new WebsocketFrameSend(toBuffer(data, hint2)).createFrame(hint2 === sendHints.string ? opcodes.TEXT : opcodes.BINARY);
30858
30991
  }
30859
- function toBuffer(data, hint) {
30860
- switch (hint) {
30992
+ function toBuffer(data, hint2) {
30993
+ switch (hint2) {
30861
30994
  case sendHints.string:
30862
30995
  return Buffer.from(data);
30863
30996
  case sendHints.arrayBuffer:
@@ -32108,7 +32241,7 @@ var init_context = __esm({
32108
32241
  });
32109
32242
 
32110
32243
  // src/lib/concierge-api.ts
32111
- function baseUrl2(ctx) {
32244
+ function baseUrl(ctx) {
32112
32245
  return `${ctx.envConfig.apiUrl}/api/v2/concierge`;
32113
32246
  }
32114
32247
  function authHeaders(ctx) {
@@ -32139,13 +32272,13 @@ function toCamelMessage(raw) {
32139
32272
  };
32140
32273
  }
32141
32274
  async function listConciergeChats(ctx) {
32142
- const res = await fetch(`${baseUrl2(ctx)}/chats`, { headers: authHeaders(ctx) });
32275
+ const res = await fetch(`${baseUrl(ctx)}/chats`, { headers: authHeaders(ctx) });
32143
32276
  if (!res.ok) throw new Error(`Failed to list concierge chats: ${res.status}`);
32144
32277
  const data = await res.json();
32145
32278
  return data.map(toCamelChat);
32146
32279
  }
32147
32280
  async function createConciergeChat(ctx, title) {
32148
- const res = await fetch(`${baseUrl2(ctx)}/chats`, {
32281
+ const res = await fetch(`${baseUrl(ctx)}/chats`, {
32149
32282
  method: "POST",
32150
32283
  headers: authHeaders(ctx),
32151
32284
  body: JSON.stringify({ title: null })
@@ -32154,15 +32287,18 @@ async function createConciergeChat(ctx, title) {
32154
32287
  return toCamelChat(await res.json());
32155
32288
  }
32156
32289
  async function getConciergeChat(ctx, chatId) {
32157
- const res = await fetch(`${baseUrl2(ctx)}/chats/${chatId}`, { headers: authHeaders(ctx) });
32290
+ const res = await fetch(`${baseUrl(ctx)}/chats/${chatId}`, { headers: authHeaders(ctx) });
32158
32291
  if (!res.ok) throw new Error(`Failed to get concierge chat ${chatId}: ${res.status}`);
32159
32292
  return toCamelChat(await res.json());
32160
32293
  }
32161
- async function originateConciergeCall(ctx, kind = "concierge_setup") {
32162
- const res = await fetch(`${baseUrl2(ctx)}/calls`, {
32294
+ async function originateConciergeCall(ctx, kind = "concierge_setup", outboundMessage, clientSurface) {
32295
+ const body = { kind };
32296
+ if (outboundMessage) body.outbound_message = outboundMessage;
32297
+ body.client_surface = clientSurface;
32298
+ const res = await fetch(`${baseUrl(ctx)}/calls`, {
32163
32299
  method: "POST",
32164
32300
  headers: authHeaders(ctx),
32165
- body: JSON.stringify({ kind })
32301
+ body: JSON.stringify(body)
32166
32302
  });
32167
32303
  if (res.status === 412) {
32168
32304
  throw new Error("Your account phone is not verified. Run `gr account verify-phone` first.");
@@ -32174,7 +32310,7 @@ async function originateConciergeCall(ctx, kind = "concierge_setup") {
32174
32310
  return await res.json();
32175
32311
  }
32176
32312
  async function originateConciergeSms(ctx, kind = "concierge_setup") {
32177
- const res = await fetch(`${baseUrl2(ctx)}/sms`, {
32313
+ const res = await fetch(`${baseUrl(ctx)}/sms`, {
32178
32314
  method: "POST",
32179
32315
  headers: authHeaders(ctx),
32180
32316
  body: JSON.stringify({ kind })
@@ -32211,7 +32347,7 @@ async function confirmAccountPhoneVerify(ctx, code) {
32211
32347
  }
32212
32348
  }
32213
32349
  async function getConciergeChatMessages(ctx, chatId) {
32214
- const res = await fetch(`${baseUrl2(ctx)}/chats/${chatId}/messages`, {
32350
+ const res = await fetch(`${baseUrl(ctx)}/chats/${chatId}/messages`, {
32215
32351
  headers: authHeaders(ctx)
32216
32352
  });
32217
32353
  if (!res.ok)
@@ -32912,8 +33048,8 @@ function requireNumberFrom(args, ...keys) {
32912
33048
  if (!isNaN(num)) return num;
32913
33049
  }
32914
33050
  }
32915
- const hint = keys.map((k) => `--${k}`).join(" or ");
32916
- throw new Error(`Missing required argument: ${hint}`);
33051
+ const hint2 = keys.map((k) => `--${k}`).join(" or ");
33052
+ throw new Error(`Missing required argument: ${hint2}`);
32917
33053
  }
32918
33054
 
32919
33055
  // src/domains/agent-tasks.ts
@@ -33054,11 +33190,35 @@ var agentTasksDomain = {
33054
33190
  // src/domains/agents.ts
33055
33191
  init_output();
33056
33192
  init_context();
33193
+ init_errors();
33057
33194
  var COLUMNS = [COL.id(), COL.uuid(), COL.name(), COL.status(), COL.created()];
33058
33195
  var TOOL_COLUMNS = [
33059
33196
  COL.name(),
33060
33197
  { header: "DESCRIPTION", getValue: (item) => (item.description ?? "").slice(0, 60) }
33061
33198
  ];
33199
+ var ABILITY_COLUMNS = [
33200
+ COL.uuid(),
33201
+ { header: "ABILITY-TYPE", getValue: (item) => item.abilityType ?? "" },
33202
+ COL.enabled(),
33203
+ { header: "CEL-CONDITION", getValue: (item) => item.celCondition ?? "" }
33204
+ ];
33205
+ function requireAbilityScope(args) {
33206
+ const hasWorkflow = typeof args["workflow-id"] === "string";
33207
+ const hasTask = typeof args["task-id"] === "string";
33208
+ if (hasWorkflow === hasTask) {
33209
+ throw new CLIError(
33210
+ "Specify exactly one of --workflow-id or --task-id. Abilities are scoped to a workflow or task, not to the agent row itself."
33211
+ );
33212
+ }
33213
+ if (hasTask) {
33214
+ const taskId = Number(args["task-id"]);
33215
+ if (isNaN(taskId)) throw new CLIError("--task-id must be a number");
33216
+ return { taskId };
33217
+ }
33218
+ const workflowId = Number(args["workflow-id"]);
33219
+ if (isNaN(workflowId)) throw new CLIError("--workflow-id must be a number");
33220
+ return { workflowId };
33221
+ }
33062
33222
  function normalizeChannel(channel) {
33063
33223
  const aliases = {
33064
33224
  phone: "phone-voice",
@@ -33083,11 +33243,16 @@ var agentsDomain = {
33083
33243
  archiveMethod: "archiveAgent",
33084
33244
  unarchiveMethod: "unarchiveAgent",
33085
33245
  columns: COLUMNS,
33086
- paginationSupport: "full"
33246
+ paginationSupport: "full",
33247
+ updateHelp: "Update an agent. Body schema (JSON via --data/--file/stdin), all fields optional:\n name string display name\n description string short summary shown in listings\n systemPrompt string base instructions for the agent\n model string AI model slug (see `gr ai-models list`)\n temperature number sampling temperature (0-2)\n avatarFileId number workspace file ID for the avatar\n config object AgentConfig overrides (advanced)\nAbilities are NOT set here \u2014 they live on a workflow/task scope; use `gr agents abilities` to manage them.",
33248
+ updateExamples: [
33249
+ `gr agents update --id 42 --data '{"name":"Scheduler","temperature":0.4}'`,
33250
+ "gr agents update --id 42 --file agent.json"
33251
+ ]
33087
33252
  }),
33088
33253
  {
33089
33254
  path: ["agents", "resolve-tools"],
33090
- description: "Show resolved runtime tools for an agent in a channel context. Channel accepts canonical values (phone-voice, web-voice, phone-sms, web-chat) or shorthand aliases: phone -> phone-voice, voice -> phone-voice, sms -> phone-sms, web -> web-chat. Unknown values are passed through unchanged.",
33255
+ description: "Show resolved runtime tools for an agent in a channel context. Channel accepts canonical values (phone-voice, web-voice, phone-sms, web-chat) or shorthand aliases: phone -> phone-voice, voice -> phone-voice, sms -> phone-sms, web -> web-chat. Unknown values are passed through unchanged. When neither --task-id nor --task-uuid is supplied the agent's workflow start task is used.",
33091
33256
  requiresWorkspace: true,
33092
33257
  args: [
33093
33258
  { name: "id", description: "Agent ID", required: true },
@@ -33098,22 +33263,142 @@ var agentsDomain = {
33098
33263
  },
33099
33264
  {
33100
33265
  name: "task-id",
33101
- description: "Task ID whose workflow abilities to resolve",
33102
- required: true
33266
+ description: "Numeric task ID whose workflow abilities to resolve. Omit to use the workflow start task (or supply --task-uuid instead).",
33267
+ required: false
33268
+ },
33269
+ {
33270
+ name: "task-uuid",
33271
+ description: "Task UUID as an alternative to --task-id. Omit to use the workflow start task.",
33272
+ required: false
33103
33273
  }
33104
33274
  ],
33105
33275
  handler: async ({ ctx, workspace, args }) => {
33276
+ const rawTaskId = args["task-id"];
33277
+ const rawTaskUuid = args["task-uuid"];
33278
+ if (rawTaskId !== void 0 && rawTaskUuid !== void 0) {
33279
+ throw new Error("Provide at most one of --task-id or --task-uuid, not both");
33280
+ }
33281
+ const options = {
33282
+ channel: normalizeChannel(String(args.channel))
33283
+ };
33284
+ if (typeof rawTaskId === "string") {
33285
+ const n = Number(rawTaskId);
33286
+ if (isNaN(n)) throw new Error("Argument --task-id must be a number");
33287
+ options.taskId = n;
33288
+ }
33289
+ if (typeof rawTaskUuid === "string") {
33290
+ options.taskUuid = rawTaskUuid;
33291
+ }
33106
33292
  const result2 = await requireAuth(ctx).apiClient.resolveAgentTools(
33107
33293
  workspace,
33108
33294
  requireNumber(args, "id"),
33109
- {
33110
- channel: normalizeChannel(String(args.channel)),
33111
- taskId: requireNumber(args, "task-id")
33112
- }
33295
+ options
33113
33296
  );
33114
33297
  const tools = result2.tools ?? result2;
33115
33298
  outputData(Array.isArray(tools) ? tools : [tools], ctx, TOOL_COLUMNS);
33116
33299
  }
33300
+ },
33301
+ {
33302
+ path: ["agents", "abilities", "list"],
33303
+ description: "Show the abilities effective for an agent on a task (read-only). Requires --task-id because abilities are resolved through the task's workflow, not stored on the agent row.",
33304
+ requiresWorkspace: true,
33305
+ columns: ABILITY_COLUMNS,
33306
+ args: [
33307
+ { name: "id", description: "Agent ID", required: true },
33308
+ {
33309
+ name: "task-id",
33310
+ description: "Task ID whose workflow abilities to list",
33311
+ required: true
33312
+ }
33313
+ ],
33314
+ handler: async ({ ctx, workspace, args }) => {
33315
+ const result2 = await requireAuth(ctx).apiClient.listAgentAbilities(
33316
+ workspace,
33317
+ requireNumber(args, "id"),
33318
+ { taskId: requireNumber(args, "task-id") }
33319
+ );
33320
+ outputData(result2, ctx, ABILITY_COLUMNS);
33321
+ }
33322
+ },
33323
+ {
33324
+ path: ["agents", "abilities", "enable"],
33325
+ description: "Enable (create) an ability on a workflow or task scope. Requires exactly one of --workflow-id or --task-id \u2014 abilities are scoped to a workflow/task, never to the agent row. Provide initial --config JSON inline or via --data/--file.",
33326
+ mutates: true,
33327
+ requiresWorkspace: true,
33328
+ args: [
33329
+ { name: "ability-type", description: "Ability type slug (e.g. 'communication:send_sms')", required: true },
33330
+ { name: "workflow-id", description: "Workflow scope (mutually exclusive with --task-id)" },
33331
+ { name: "task-id", description: "Task scope (mutually exclusive with --workflow-id)" }
33332
+ ],
33333
+ examples: [
33334
+ "gr agents abilities enable --workflow-id 7 --ability-type tools:web_search",
33335
+ `gr agents abilities enable --task-id 12 --ability-type integration:data_access --data '{"dataTypeUuid":"..."}'`
33336
+ ],
33337
+ handler: async ({ ctx, workspace, args, data }) => {
33338
+ const abilityType = args["ability-type"];
33339
+ if (typeof abilityType !== "string") {
33340
+ throw new CLIError("--ability-type is required");
33341
+ }
33342
+ const scope = requireAbilityScope(args);
33343
+ const config = data && typeof data === "object" ? data : {};
33344
+ const body = {
33345
+ abilityType,
33346
+ config,
33347
+ ...scope
33348
+ };
33349
+ const result2 = await requireAuth(ctx).apiClient.createAbility(workspace, body);
33350
+ outputSingle(result2, ctx, ABILITY_COLUMNS);
33351
+ }
33352
+ },
33353
+ {
33354
+ path: ["agents", "abilities", "disable"],
33355
+ description: "Disable an ability instance by UUID (sets enabled=false, keeps config). Use `gr agents abilities list` to find the UUID.",
33356
+ mutates: true,
33357
+ requiresWorkspace: true,
33358
+ args: [{ name: "uuid", description: "Ability instance UUID", required: true }],
33359
+ handler: async ({ ctx, workspace, args }) => {
33360
+ const uuid = args.uuid;
33361
+ if (typeof uuid !== "string") throw new CLIError("--uuid is required");
33362
+ const result2 = await requireAuth(ctx).apiClient.updateAbility(workspace, uuid, {
33363
+ enabled: false
33364
+ });
33365
+ outputSingle(result2, ctx, ABILITY_COLUMNS);
33366
+ }
33367
+ },
33368
+ {
33369
+ path: ["agents", "abilities", "configure"],
33370
+ description: "Update an ability instance by UUID. Pass --data/--file JSON to merge into config, and/or --enabled true|false to toggle. config is merged with the existing config server-side.",
33371
+ mutates: true,
33372
+ requiresWorkspace: true,
33373
+ args: [
33374
+ { name: "uuid", description: "Ability instance UUID", required: true },
33375
+ { name: "enabled", description: "Set enabled state (true|false)" }
33376
+ ],
33377
+ examples: [
33378
+ `gr agents abilities configure --uuid <uuid> --data '{"canForward":true}'`,
33379
+ "gr agents abilities configure --uuid <uuid> --enabled true"
33380
+ ],
33381
+ handler: async ({ ctx, workspace, args, data }) => {
33382
+ const uuid = args.uuid;
33383
+ if (typeof uuid !== "string") throw new CLIError("--uuid is required");
33384
+ const body = {};
33385
+ if (data && typeof data === "object") {
33386
+ body.config = data;
33387
+ }
33388
+ if (typeof args.enabled === "string") {
33389
+ if (args.enabled !== "true" && args.enabled !== "false") {
33390
+ throw new CLIError("--enabled must be true or false");
33391
+ }
33392
+ body.enabled = args.enabled === "true";
33393
+ }
33394
+ if (Object.keys(body).length === 0) {
33395
+ throw new CLIError(
33396
+ "Nothing to update: provide --data config and/or --enabled"
33397
+ );
33398
+ }
33399
+ const result2 = await requireAuth(ctx).apiClient.updateAbility(workspace, uuid, body);
33400
+ outputSingle(result2, ctx, ABILITY_COLUMNS);
33401
+ }
33117
33402
  }
33118
33403
  ]
33119
33404
  };
@@ -33122,6 +33407,7 @@ var agentsDomain = {
33122
33407
  init_output();
33123
33408
  init_cli_utils();
33124
33409
  init_context();
33410
+ init_concierge_api();
33125
33411
  var COLUMNS2 = [
33126
33412
  COL.id(),
33127
33413
  COL.uuid(),
@@ -33342,21 +33628,47 @@ var chatsDomain = {
33342
33628
  // Inspect (aggregated debug view)
33343
33629
  {
33344
33630
  path: ["chats", "inspect"],
33345
- description: "Inspect a chat with messages, assignment state, and data records",
33346
- requiresWorkspace: true,
33631
+ description: "Inspect a chat with messages, assignment state, and data records. Omit -w for concierge (account-level) chats.",
33632
+ requiresWorkspace: false,
33347
33633
  args: [{ name: "id", description: "Chat ID", required: true }],
33348
33634
  handler: async ({ ctx, workspace, args }) => {
33349
33635
  const chatId = requireNumber(args, "id");
33350
- const [chat, messages, ws] = await Promise.all([
33351
- requireAuth(ctx).apiClient.getChat(workspace, chatId),
33352
- requireAuth(ctx).apiClient.getChatMessages(workspace, chatId),
33353
- requireAuth(ctx).apiClient.getWorkspace(workspace)
33354
- ]);
33355
- const isHipaa = ws.features?.includes("hipaa_compliance");
33636
+ const authed = requireAuth(ctx);
33356
33637
  const truncate2 = (content) => {
33357
33638
  const text = typeof content === "string" ? content : JSON.stringify(content);
33358
33639
  return text.slice(0, 200);
33359
33640
  };
33641
+ if (!workspace) {
33642
+ const [chat2, messages2] = await Promise.all([
33643
+ getConciergeChat(authed, chatId),
33644
+ getConciergeChatMessages(authed, chatId)
33645
+ ]);
33646
+ outputSingle(
33647
+ {
33648
+ chat: {
33649
+ id: chat2.id,
33650
+ uuid: chat2.uuid,
33651
+ title: chat2.title,
33652
+ chatType: chat2.chatType,
33653
+ threadId: chat2.threadId,
33654
+ createdAt: chat2.createdAt
33655
+ },
33656
+ messages: messages2.map((m) => ({
33657
+ id: m.id,
33658
+ role: m.role,
33659
+ content: truncate2(m.content)
33660
+ }))
33661
+ },
33662
+ ctx
33663
+ );
33664
+ return;
33665
+ }
33666
+ const [chat, messages, ws] = await Promise.all([
33667
+ authed.apiClient.getChat(workspace, chatId),
33668
+ authed.apiClient.getChatMessages(workspace, chatId),
33669
+ authed.apiClient.getWorkspace(workspace)
33670
+ ]);
33671
+ const isHipaa = ws.features?.includes("hipaa_compliance");
33360
33672
  const result2 = {
33361
33673
  chat: {
33362
33674
  id: chat.id,
@@ -33376,10 +33688,7 @@ var chatsDomain = {
33376
33688
  };
33377
33689
  const assignmentId = chat.assignmentId;
33378
33690
  if (assignmentId) {
33379
- const assignment = await requireAuth(ctx).apiClient.getAssignment(
33380
- workspace,
33381
- assignmentId
33382
- );
33691
+ const assignment = await authed.apiClient.getAssignment(workspace, assignmentId);
33383
33692
  result2.assignment = {
33384
33693
  id: assignment.id,
33385
33694
  status: assignment.status,
@@ -33637,10 +33946,7 @@ var memberRolesDomain = {
33637
33946
  updateMethod: "updateMemberRole",
33638
33947
  deleteMethod: "deleteMemberRole",
33639
33948
  columns: ROLE_COLUMNS2,
33640
- createExamples: [
33641
- "gr member-roles list -w $WID",
33642
- "gr member-roles get -w $WID --id 2"
33643
- ]
33949
+ createExamples: ["gr member-roles list -w $WID", "gr member-roles get -w $WID --id 2"]
33644
33950
  })
33645
33951
  };
33646
33952
 
@@ -33651,10 +33957,13 @@ var COLUMNS4 = [
33651
33957
  COL.id(),
33652
33958
  COL.uuid(),
33653
33959
  COL.name(),
33654
- COL.status(),
33960
+ // TaskResponse has no `status` field — it has `archived`. Surface that
33961
+ // directly so active vs archived is visible in the default table (relevant
33962
+ // once --include-archived mixes both into the listing).
33963
+ { header: "STATUS", getValue: (item) => item.archived ? "archived" : "active" },
33655
33964
  {
33656
33965
  header: "WORKFLOW",
33657
- getValue: (item) => item.workflow_name ?? String(item.workflow_id ?? "")
33966
+ getValue: (item) => String(item.workflowId ?? "")
33658
33967
  },
33659
33968
  COL.created()
33660
33969
  ];
@@ -33672,7 +33981,21 @@ var tasksDomain = {
33672
33981
  deleteMethod: "deleteTask",
33673
33982
  archiveMethod: "archiveTask",
33674
33983
  unarchiveMethod: "unarchiveTask",
33675
- columns: COLUMNS4
33984
+ columns: COLUMNS4,
33985
+ // `tasks list` is workspace-wide by default. Filter to one workflow
33986
+ // with --workflow-id, and opt into archived tasks with
33987
+ // --include-archived (active-only by default, matching the backend).
33988
+ listArgs: [
33989
+ {
33990
+ name: "workflow-id",
33991
+ description: "Filter tasks to a single workflow by ID"
33992
+ },
33993
+ {
33994
+ name: "include-archived",
33995
+ description: "Include archived tasks in the listing",
33996
+ isFlag: true
33997
+ }
33998
+ ]
33676
33999
  }),
33677
34000
  {
33678
34001
  path: ["tasks", "clone"],
@@ -33732,9 +34055,18 @@ var COLUMNS5 = [
33732
34055
  COL.id(),
33733
34056
  COL.uuid(),
33734
34057
  COL.name(),
33735
- { header: "TASKS", getValue: (item) => String(item.taskCount ?? "") },
34058
+ // taskCount is the total (active + archived). Show the active count as the
34059
+ // headline number — matching `tasks list` — and call out archived tasks
34060
+ // separately so the table never overstates how many tasks actually run.
34061
+ { header: "TASKS", getValue: (item) => formatTaskCount(item) },
33736
34062
  COL.created()
33737
34063
  ];
34064
+ function formatTaskCount(item) {
34065
+ const total = Number(item.taskCount ?? 0);
34066
+ const archived = Number(item.archivedTaskCount ?? 0);
34067
+ const active = total - archived;
34068
+ return archived > 0 ? `${active} (+${archived} archived)` : String(active);
34069
+ }
33738
34070
  var NOTE_COLUMNS = [
33739
34071
  COL.id(),
33740
34072
  { header: "TITLE", getValue: (item) => item.title ?? "" },
@@ -33835,13 +34167,21 @@ var workflowsDomain = {
33835
34167
  // Diagram
33836
34168
  {
33837
34169
  path: ["workflows", "diagram"],
33838
- description: "Get workflow diagram",
34170
+ description: "Get workflow diagram (active tasks only by default)",
33839
34171
  requiresWorkspace: true,
33840
- args: [{ name: "id", description: "Workflow ID", required: true }],
34172
+ args: [
34173
+ { name: "id", description: "Workflow ID", required: true },
34174
+ {
34175
+ name: "include-archived",
34176
+ description: "Render archived tasks (distinctly styled) too",
34177
+ isFlag: true
34178
+ }
34179
+ ],
33841
34180
  handler: async ({ ctx, workspace, args }) => {
33842
34181
  const result2 = await requireAuth(ctx).apiClient.getWorkflowDiagram(
33843
34182
  workspace,
33844
- requireNumber(args, "id")
34183
+ requireNumber(args, "id"),
34184
+ { includeArchived: args["include-archived"] === true }
33845
34185
  );
33846
34186
  outputSingle(result2, ctx);
33847
34187
  }
@@ -34364,28 +34704,64 @@ var workspacesDomain = {
34364
34704
  outputSingle(result2, ctx, COLUMNS7);
34365
34705
  }
34366
34706
  },
34367
- // Create a workspace via the public endpoint
34707
+ // Provision a workspace under an organization's active subscription.
34368
34708
  {
34369
34709
  path: ["workspaces", "create"],
34370
- description: "Create a workspace",
34710
+ description: "Provision a workspace in an organization (requires an active subscription)",
34371
34711
  mutates: true,
34372
34712
  requiresWorkspace: false,
34373
- handler: async ({ ctx, data }) => {
34374
- if (!data) throw new CLIError("JSON data required (--data, --file, or stdin)");
34375
- const payload = data;
34376
- if (!payload.organizationId) {
34713
+ args: [
34714
+ {
34715
+ name: "org",
34716
+ aliases: ["org-uuid"],
34717
+ description: "Organization UUID",
34718
+ required: true
34719
+ },
34720
+ { name: "product", description: "Workspace plan product ID", required: true },
34721
+ { name: "name", description: "Workspace name", required: true },
34722
+ { name: "period", description: "Billing period: 'month' or 'year'", default: "month" },
34723
+ { name: "slug", description: "Workspace slug (optional)" },
34724
+ { name: "template", description: "Template workspace UUID to clone (optional)" }
34725
+ ],
34726
+ examples: ['gr workspaces create --org <org-uuid> --product 14 --name "Front Desk"'],
34727
+ handler: async ({ ctx, args }) => {
34728
+ const orgUuid = args.org ?? args["org-uuid"];
34729
+ const name = args.name;
34730
+ const productRaw = args.product;
34731
+ if (!orgUuid) throw new CLIError("Missing required argument: --org <org-uuid>");
34732
+ if (!name) throw new CLIError("Missing required argument: --name");
34733
+ if (!productRaw) {
34377
34734
  throw new CLIError(
34378
- `organizationId is required in --data (e.g. --data '{"organizationId": 1, "name": "My Workspace"}')`
34735
+ "Missing required argument: --product\nList workspace plans with: gr billing products --type workspace"
34379
34736
  );
34380
34737
  }
34738
+ const payload = {
34739
+ name,
34740
+ productId: Number(productRaw),
34741
+ planPeriod: args.period || "month"
34742
+ };
34743
+ if (args.slug) payload.slug = args.slug;
34744
+ if (args.template) payload.templateWorkspaceUuid = args.template;
34381
34745
  try {
34382
- const result2 = await requireAuth(ctx).apiClient.createWorkspace(payload);
34746
+ const result2 = await requireAuth(ctx).apiClient.createOrganizationWorkspace(
34747
+ orgUuid,
34748
+ payload
34749
+ );
34383
34750
  outputSingle(result2, ctx, COLUMNS7);
34751
+ if ((ctx.outputFormat ?? "table") === "table") {
34752
+ const wsUuid = result2?.uuid ?? "<workspace-uuid>";
34753
+ process.stdout.write(
34754
+ `
34755
+ Provisioning started. Watch it come up with:
34756
+ gr workspaces get -w ${wsUuid}
34757
+ `
34758
+ );
34759
+ }
34384
34760
  } catch (err) {
34385
34761
  const statusCode = err?.statusCode;
34386
- if (statusCode === 405) {
34762
+ if (statusCode === 400) {
34387
34763
  throw new CLIError(
34388
- 'Creating a workspace directly is not supported \u2014 provisioning runs through the concierge (it handles product selection and billing).\nNext: gr concierge chat --allow-write --message "Create a new workspace"\nThen: gr workspaces list (to get the new workspace UUID for -w)'
34764
+ "Could not create the workspace. The organization needs an active, paid subscription first.\n gr billing products --type org # pick an org plan\n gr billing checkout --product <id> # pay up front\n gr billing status # confirm it is active"
34389
34765
  );
34390
34766
  }
34391
34767
  throw err;
@@ -35451,35 +35827,24 @@ Common optional
35451
35827
  Scope (set exactly one when objectType requires it)
35452
35828
  routineId, workflowId, taskId, dataTypeId, journeyStepId, calendarId, ...
35453
35829
 
35454
- chat:create actionParams (outbound voice/SMS)
35455
- {"workflowId":<id>,"channel":"phone-voice"|"phone-sms","phoneNumberId":<id>,
35456
- "inboxId":<optional>,"assistantEnabled":<bool>}
35830
+ chat:create actionParams (outbound voice/SMS \u2014 starts a workflow chat)
35831
+ {"workflowUUID":"<workflow-uuid>","channel":"phone-voice"|"phone-sms",
35832
+ "phoneNumberUUID":"<uuid>","inboxUUID":"<optional-uuid>","assistantEnabled":<bool>}
35833
+ Keys are UUID strings: workflowUUID (not workflowId), phoneNumberUUID (not
35834
+ phoneNumberId), inboxUUID (not inboxId). Unknown keys are rejected.
35835
+
35836
+ sms:send actionParams (send an SMS, or start an SMS workflow chat)
35837
+ One-off text: {"phoneNumberUUID":"<from-number-uuid>","messageTemplate":"Hi {{name}} \u2026"}
35838
+ Workflow chat: {"phoneNumberUUID":"<from-number-uuid>","workflowUUID":"<workflow-uuid>",
35839
+ "initialUserMessage":"<optional seed>"}
35840
+ phoneNumberUUID (the from-number) is required. The message body is messageTemplate
35841
+ (supports {{record/member}} template vars) \u2014 there is no "body"/"message" key.
35842
+ Provide messageTemplate for a one-off text, OR workflowUUID to start a chat.
35457
35843
 
35458
35844
  member:label actionParams
35459
35845
  {"addLabelIds":["<uuid>"],"removeLabelIds":["<uuid>"]}
35460
35846
  `;
35461
35847
 
35462
- // src/lib/routines/field-help.ts
35463
- var ROUTINE_FIELD_REFERENCE = `
35464
- Field reference for --data JSON (create/update):
35465
-
35466
- Core
35467
- name (string) Display name
35468
- workflowId (number) Workflow run when the routine fires
35469
- targetMemberId (number) Member who receives the scheduled outreach
35470
-
35471
- Schedule
35472
- scheduleEnabled (bool) Master on/off for the cron trigger
35473
- scheduleMode (string) "CRON" (only mode today)
35474
- cronString (string) Standard cron, e.g. "0 7 * * *"
35475
- timezone (string, optional) IANA name, e.g. "America/Los_Angeles"
35476
- Defaults to workspace timezone, else UTC
35477
-
35478
- Visibility / lifecycle
35479
- archived (bool) Archive flag on update
35480
- event rules Use gr events rules create \u2014 not inline here
35481
- `;
35482
-
35483
35848
  // src/domains/events.ts
35484
35849
  var RULE_COLUMNS = [
35485
35850
  COL.id(),
@@ -35487,15 +35852,6 @@ var RULE_COLUMNS = [
35487
35852
  { header: "EVENT", getValue: (item) => item.eventType ?? "" },
35488
35853
  { header: "ACTIVE", getValue: (item) => String(item.active ?? "") }
35489
35854
  ];
35490
- var ROUTINE_COLUMNS = [
35491
- COL.id(),
35492
- COL.name(),
35493
- { header: "MODE", getValue: (item) => item.scheduleMode ?? "" },
35494
- { header: "CRON", getValue: (item) => item.cronString ?? "" },
35495
- { header: "TZ", getValue: (item) => item.timezone ?? "UTC" },
35496
- { header: "ENABLED", getValue: (item) => String(item.scheduleEnabled ?? "") },
35497
- { header: "NEXT RUN", getValue: (item) => item.nextRun ?? "" }
35498
- ];
35499
35855
  var eventRulesCrudNoList = crudCommands({
35500
35856
  prefix: ["events", "rules"],
35501
35857
  entityName: "event rule",
@@ -35519,8 +35875,8 @@ ${EVENT_RULE_FIELD_REFERENCE}`,
35519
35875
  `gr events rules create -w $WID --allow-write --data '{"name":"AM voice check-in",`,
35520
35876
  ' "objectType":"routine","eventType":"routine:triggered","actionType":"chat:create",',
35521
35877
  ' "routineId":<routine-id>,',
35522
- ' "actionParams":{"workflowId":<workflow-id>,"channel":"phone-voice",',
35523
- ` "phoneNumberId":<workspace-phone-id>}}'`,
35878
+ ' "actionParams":{"workflowUUID":"<workflow-uuid>","channel":"phone-voice",',
35879
+ ` "phoneNumberUUID":"<workspace-phone-uuid>"}}'`,
35524
35880
  "",
35525
35881
  ' PM SMS variant: use "channel":"phone-sms" and a second rule on the same routineId.',
35526
35882
  " Prereq: org phone assigned + gr phone-numbers link; workflow published with start task.",
@@ -35658,74 +36014,6 @@ var eventsDomain = {
35658
36014
  const result2 = await requireAuth(ctx).apiClient.searchEventRules(workspace, opts);
35659
36015
  outputData(result2, ctx, RULE_COLUMNS);
35660
36016
  }
35661
- },
35662
- // Routines
35663
- ...crudCommands({
35664
- prefix: ["routines"],
35665
- entityName: "routine",
35666
- listMethod: "getRoutines",
35667
- getMethod: "getRoutine",
35668
- createMethod: "createRoutine",
35669
- updateMethod: "updateRoutine",
35670
- deleteMethod: "deleteRoutine",
35671
- paginationSupport: "full",
35672
- columns: ROUTINE_COLUMNS,
35673
- createHelp: `Create a routine
35674
-
35675
- ${ROUTINE_FIELD_REFERENCE}`,
35676
- updateHelp: `Update a routine
35677
-
35678
- ${ROUTINE_FIELD_REFERENCE}`,
35679
- createExamples: [
35680
- "Daily 7am check-in in the member\u2019s timezone (cron is interpreted in `timezone`):",
35681
- `gr routines create -w $WID --allow-write --data '{"name":"AM check-in",`,
35682
- ' "scheduleEnabled":true,"scheduleMode":"CRON","cronString":"0 7 * * *",',
35683
- ` "timezone":"America/Los_Angeles","targetMemberId":1,"workflowId":2}'`,
35684
- " (timezone is an IANA name; omit it to default to the workspace timezone, else UTC.",
35685
- ' Without it, "0 7 * * *" fires at 07:00 UTC, not 7am local.)'
35686
- ]
35687
- }),
35688
- {
35689
- path: ["routines", "run"],
35690
- description: "Run a routine now",
35691
- mutates: true,
35692
- requiresWorkspace: true,
35693
- args: [{ name: "id", description: "Routine ID", required: true }],
35694
- handler: async ({ ctx, workspace, args, data }) => {
35695
- const result2 = await requireAuth(ctx).apiClient.runRoutine(
35696
- workspace,
35697
- requireNumber(args, "id"),
35698
- data ?? {}
35699
- );
35700
- outputSingle(result2, ctx);
35701
- }
35702
- },
35703
- {
35704
- path: ["routines", "runs", "list"],
35705
- description: "List runs for a routine",
35706
- requiresWorkspace: true,
35707
- args: [
35708
- {
35709
- name: "id",
35710
- description: "Routine ID (aligns with routines get/run/update/delete)"
35711
- },
35712
- { name: "status", description: "Filter by run status" },
35713
- { name: "page", description: "Page number (1-indexed)" },
35714
- { name: "page-size", description: "Page size (max 100)" }
35715
- ],
35716
- handler: async ({ ctx, workspace, args }) => {
35717
- const routineId = args.id ? requireNumber(args, "id") : void 0;
35718
- const page = args.page ? requireNumber(args, "page") : void 0;
35719
- const pageSize = args["page-size"] ? requireNumber(args, "page-size") : void 0;
35720
- const status = args.status ?? void 0;
35721
- const result2 = await requireAuth(ctx).apiClient.getRoutineRuns(workspace, {
35722
- ...routineId !== void 0 ? { routineId } : {},
35723
- ...page !== void 0 ? { page } : {},
35724
- ...pageSize !== void 0 ? { pageSize } : {},
35725
- ...status ? { status } : {}
35726
- });
35727
- outputData(result2, ctx);
35728
- }
35729
36017
  }
35730
36018
  ]
35731
36019
  };
@@ -36120,11 +36408,11 @@ var ACTION_COLUMNS = [
36120
36408
  { header: "ACTIVE", getValue: (item) => String(item.active ?? "") },
36121
36409
  { header: "CONDITIONS", getValue: (item) => (item.conditions ?? "").slice(0, 40) }
36122
36410
  ];
36123
- function baseUrl(ctx, wid) {
36411
+ function baseUrl2(ctx, wid) {
36124
36412
  return `${ctx.envConfig.apiUrl}/api/v2/w/${wid}/journeys`;
36125
36413
  }
36126
36414
  function notesUrl(ctx, wid, journeyId) {
36127
- return `${baseUrl(ctx, wid)}/${journeyId}/notes`;
36415
+ return `${baseUrl2(ctx, wid)}/${journeyId}/notes`;
36128
36416
  }
36129
36417
  function headers(ctx) {
36130
36418
  return {
@@ -36191,7 +36479,7 @@ var journeysDomain = {
36191
36479
  requiresWorkspace: true,
36192
36480
  examples: ["gr journeys list -w $WID --env staging"],
36193
36481
  handler: async ({ ctx, workspace }) => {
36194
- const result2 = await apiGet(requireAuth(ctx), baseUrl(requireAuth(ctx), workspace));
36482
+ const result2 = await apiGet(requireAuth(ctx), baseUrl2(requireAuth(ctx), workspace));
36195
36483
  outputData(listResult(result2, false), ctx, JOURNEY_COLUMNS);
36196
36484
  }
36197
36485
  },
@@ -36204,7 +36492,7 @@ var journeysDomain = {
36204
36492
  const id = requireString(args, "id");
36205
36493
  const result2 = await apiGet(
36206
36494
  requireAuth(ctx),
36207
- `${baseUrl(requireAuth(ctx), workspace)}/${id}`
36495
+ `${baseUrl2(requireAuth(ctx), workspace)}/${id}`
36208
36496
  );
36209
36497
  outputSingle(result2, ctx, JOURNEY_COLUMNS);
36210
36498
  }
@@ -36224,7 +36512,7 @@ var journeysDomain = {
36224
36512
  if (!data) throw new CLIError("JSON data required (--data, --file, or stdin)");
36225
36513
  const result2 = await apiPost(
36226
36514
  requireAuth(ctx),
36227
- baseUrl(requireAuth(ctx), workspace),
36515
+ baseUrl2(requireAuth(ctx), workspace),
36228
36516
  data
36229
36517
  );
36230
36518
  outputSingle(result2, ctx, JOURNEY_COLUMNS);
@@ -36242,7 +36530,7 @@ var journeysDomain = {
36242
36530
  const id = requireString(args, "id");
36243
36531
  const result2 = await apiPut(
36244
36532
  requireAuth(ctx),
36245
- `${baseUrl(requireAuth(ctx), workspace)}/${id}`,
36533
+ `${baseUrl2(requireAuth(ctx), workspace)}/${id}`,
36246
36534
  data
36247
36535
  );
36248
36536
  outputSingle(result2, ctx, JOURNEY_COLUMNS);
@@ -36256,7 +36544,7 @@ var journeysDomain = {
36256
36544
  args: [{ name: "id", description: "Journey ID", required: true }],
36257
36545
  handler: async ({ ctx, workspace, args }) => {
36258
36546
  const id = requireString(args, "id");
36259
- await apiDelete(requireAuth(ctx), `${baseUrl(requireAuth(ctx), workspace)}/${id}`);
36547
+ await apiDelete(requireAuth(ctx), `${baseUrl2(requireAuth(ctx), workspace)}/${id}`);
36260
36548
  process.stdout.write(`Archived journey ${id}
36261
36549
  `);
36262
36550
  }
@@ -36272,7 +36560,7 @@ var journeysDomain = {
36272
36560
  const id = requireString(args, "id");
36273
36561
  const result2 = await apiGet(
36274
36562
  requireAuth(ctx),
36275
- `${baseUrl(requireAuth(ctx), workspace)}/${id}`
36563
+ `${baseUrl2(requireAuth(ctx), workspace)}/${id}`
36276
36564
  );
36277
36565
  outputData(result2?.steps ?? [], ctx, STEP_COLUMNS);
36278
36566
  }
@@ -36297,7 +36585,7 @@ var journeysDomain = {
36297
36585
  const journeyId = requireString(args, "journey-id");
36298
36586
  const result2 = await apiPost(
36299
36587
  requireAuth(ctx),
36300
- `${baseUrl(requireAuth(ctx), workspace)}/${journeyId}/steps`,
36588
+ `${baseUrl2(requireAuth(ctx), workspace)}/${journeyId}/steps`,
36301
36589
  data
36302
36590
  );
36303
36591
  outputSingle(result2, ctx, STEP_COLUMNS);
@@ -36318,7 +36606,7 @@ var journeysDomain = {
36318
36606
  const stepId = requireString(args, "id");
36319
36607
  const result2 = await apiPut(
36320
36608
  requireAuth(ctx),
36321
- `${baseUrl(requireAuth(ctx), workspace)}/${journeyId}/steps/${stepId}`,
36609
+ `${baseUrl2(requireAuth(ctx), workspace)}/${journeyId}/steps/${stepId}`,
36322
36610
  data
36323
36611
  );
36324
36612
  outputSingle(result2, ctx, STEP_COLUMNS);
@@ -36338,7 +36626,7 @@ var journeysDomain = {
36338
36626
  const stepId = requireString(args, "id");
36339
36627
  await apiDelete(
36340
36628
  requireAuth(ctx),
36341
- `${baseUrl(requireAuth(ctx), workspace)}/${journeyId}/steps/${stepId}`
36629
+ `${baseUrl2(requireAuth(ctx), workspace)}/${journeyId}/steps/${stepId}`
36342
36630
  );
36343
36631
  process.stdout.write(`Archived step ${stepId}
36344
36632
  `);
@@ -36355,7 +36643,7 @@ var journeysDomain = {
36355
36643
  const id = requireString(args, "id");
36356
36644
  const result2 = await apiGet(
36357
36645
  requireAuth(ctx),
36358
- `${baseUrl(requireAuth(ctx), workspace)}/${id}`
36646
+ `${baseUrl2(requireAuth(ctx), workspace)}/${id}`
36359
36647
  );
36360
36648
  const seen = /* @__PURE__ */ new Set();
36361
36649
  const connections = [];
@@ -36399,7 +36687,7 @@ var journeysDomain = {
36399
36687
  const journeyId = requireString(args, "journey-id");
36400
36688
  const result2 = await apiPost(
36401
36689
  requireAuth(ctx),
36402
- `${baseUrl(requireAuth(ctx), workspace)}/${journeyId}/connections`,
36690
+ `${baseUrl2(requireAuth(ctx), workspace)}/${journeyId}/connections`,
36403
36691
  data
36404
36692
  );
36405
36693
  outputSingle(result2, ctx, CONNECTION_COLUMNS);
@@ -36420,7 +36708,7 @@ var journeysDomain = {
36420
36708
  const connId = requireString(args, "id");
36421
36709
  const result2 = await apiPut(
36422
36710
  requireAuth(ctx),
36423
- `${baseUrl(requireAuth(ctx), workspace)}/${journeyId}/connections/${connId}`,
36711
+ `${baseUrl2(requireAuth(ctx), workspace)}/${journeyId}/connections/${connId}`,
36424
36712
  data
36425
36713
  );
36426
36714
  outputSingle(result2, ctx, CONNECTION_COLUMNS);
@@ -36440,7 +36728,7 @@ var journeysDomain = {
36440
36728
  const connId = requireString(args, "id");
36441
36729
  await apiDelete(
36442
36730
  requireAuth(ctx),
36443
- `${baseUrl(requireAuth(ctx), workspace)}/${journeyId}/connections/${connId}`
36731
+ `${baseUrl2(requireAuth(ctx), workspace)}/${journeyId}/connections/${connId}`
36444
36732
  );
36445
36733
  process.stdout.write(`Deleted connection ${connId}
36446
36734
  `);
@@ -36457,7 +36745,7 @@ var journeysDomain = {
36457
36745
  const id = requireString(args, "id");
36458
36746
  const result2 = await apiGet(
36459
36747
  requireAuth(ctx),
36460
- `${baseUrl(requireAuth(ctx), workspace)}/${id}`
36748
+ `${baseUrl2(requireAuth(ctx), workspace)}/${id}`
36461
36749
  );
36462
36750
  outputData(result2?.goals ?? [], ctx, GOAL_COLUMNS);
36463
36751
  }
@@ -36480,7 +36768,7 @@ var journeysDomain = {
36480
36768
  const journeyId = requireString(args, "journey-id");
36481
36769
  const result2 = await apiPost(
36482
36770
  requireAuth(ctx),
36483
- `${baseUrl(requireAuth(ctx), workspace)}/${journeyId}/goals`,
36771
+ `${baseUrl2(requireAuth(ctx), workspace)}/${journeyId}/goals`,
36484
36772
  data
36485
36773
  );
36486
36774
  outputSingle(result2, ctx, GOAL_COLUMNS);
@@ -36501,7 +36789,7 @@ var journeysDomain = {
36501
36789
  const goalId = requireString(args, "id");
36502
36790
  const result2 = await apiPut(
36503
36791
  requireAuth(ctx),
36504
- `${baseUrl(requireAuth(ctx), workspace)}/${journeyId}/goals/${goalId}`,
36792
+ `${baseUrl2(requireAuth(ctx), workspace)}/${journeyId}/goals/${goalId}`,
36505
36793
  data
36506
36794
  );
36507
36795
  outputSingle(result2, ctx, GOAL_COLUMNS);
@@ -36521,7 +36809,7 @@ var journeysDomain = {
36521
36809
  const goalId = requireString(args, "id");
36522
36810
  await apiDelete(
36523
36811
  requireAuth(ctx),
36524
- `${baseUrl(requireAuth(ctx), workspace)}/${journeyId}/goals/${goalId}`
36812
+ `${baseUrl2(requireAuth(ctx), workspace)}/${journeyId}/goals/${goalId}`
36525
36813
  );
36526
36814
  process.stdout.write(`Deleted goal ${goalId}
36527
36815
  `);
@@ -36545,7 +36833,7 @@ var journeysDomain = {
36545
36833
  const id = requireString(args, "id");
36546
36834
  const result2 = await apiPost(
36547
36835
  requireAuth(ctx),
36548
- `${baseUrl(requireAuth(ctx), workspace)}/${id}/enroll`,
36836
+ `${baseUrl2(requireAuth(ctx), workspace)}/${id}/enroll`,
36549
36837
  data
36550
36838
  );
36551
36839
  outputData(listResult(result2, false), ctx, MEMBER_JOURNEY_COLUMNS);
@@ -36565,7 +36853,7 @@ var journeysDomain = {
36565
36853
  const id = requireString(args, "id");
36566
36854
  await apiPost(
36567
36855
  requireAuth(ctx),
36568
- `${baseUrl(requireAuth(ctx), workspace)}/${id}/unenroll`,
36856
+ `${baseUrl2(requireAuth(ctx), workspace)}/${id}/unenroll`,
36569
36857
  data
36570
36858
  );
36571
36859
  process.stdout.write(`Unenrolled member(s) from journey ${id}
@@ -36583,7 +36871,7 @@ var journeysDomain = {
36583
36871
  const id = requireString(args, "id");
36584
36872
  const result2 = await apiPost(
36585
36873
  requireAuth(ctx),
36586
- `${baseUrl(requireAuth(ctx), workspace)}/${id}/reenroll`,
36874
+ `${baseUrl2(requireAuth(ctx), workspace)}/${id}/reenroll`,
36587
36875
  data
36588
36876
  );
36589
36877
  outputSingle(result2, ctx, MEMBER_JOURNEY_COLUMNS);
@@ -36603,7 +36891,7 @@ var journeysDomain = {
36603
36891
  const memberId = requireString(args, "member-id");
36604
36892
  await apiDelete(
36605
36893
  requireAuth(ctx),
36606
- `${baseUrl(requireAuth(ctx), workspace)}/${journeyId}/members/${memberId}`
36894
+ `${baseUrl2(requireAuth(ctx), workspace)}/${journeyId}/members/${memberId}`
36607
36895
  );
36608
36896
  process.stdout.write(
36609
36897
  `Deleted enrollment for member ${memberId} from journey ${journeyId}
@@ -36620,7 +36908,7 @@ var journeysDomain = {
36620
36908
  const journeyId = requireString(args, "journey-id");
36621
36909
  const result2 = await apiGet(
36622
36910
  requireAuth(ctx),
36623
- `${baseUrl(requireAuth(ctx), workspace)}/${journeyId}/members`
36911
+ `${baseUrl2(requireAuth(ctx), workspace)}/${journeyId}/members`
36624
36912
  );
36625
36913
  outputData(listResult(result2, false), ctx, MEMBER_JOURNEY_COLUMNS);
36626
36914
  }
@@ -36634,7 +36922,7 @@ var journeysDomain = {
36634
36922
  const memberId = requireString(args, "member-id");
36635
36923
  const result2 = await apiGet(
36636
36924
  requireAuth(ctx),
36637
- `${baseUrl(requireAuth(ctx), workspace)}/by-member/${memberId}`
36925
+ `${baseUrl2(requireAuth(ctx), workspace)}/by-member/${memberId}`
36638
36926
  );
36639
36927
  outputData(listResult(result2, false), ctx, MEMBER_JOURNEY_COLUMNS);
36640
36928
  }
@@ -36661,7 +36949,7 @@ var journeysDomain = {
36661
36949
  const stepId = requireString(args, "id");
36662
36950
  const result2 = await apiPost(
36663
36951
  requireAuth(ctx),
36664
- `${baseUrl(requireAuth(ctx), workspace)}/${journeyId}/steps/${stepId}/advance`,
36952
+ `${baseUrl2(requireAuth(ctx), workspace)}/${journeyId}/steps/${stepId}/advance`,
36665
36953
  data ?? {}
36666
36954
  );
36667
36955
  outputSingle(result2, ctx, MEMBER_STEP_COLUMNS);
@@ -36684,7 +36972,7 @@ var journeysDomain = {
36684
36972
  const stepId = requireString(args, "id");
36685
36973
  const result2 = await apiPost(
36686
36974
  requireAuth(ctx),
36687
- `${baseUrl(requireAuth(ctx), workspace)}/${journeyId}/steps/${stepId}/skip`,
36975
+ `${baseUrl2(requireAuth(ctx), workspace)}/${journeyId}/steps/${stepId}/skip`,
36688
36976
  data ?? {}
36689
36977
  );
36690
36978
  outputSingle(result2, ctx, MEMBER_STEP_COLUMNS);
@@ -36715,7 +37003,7 @@ var journeysDomain = {
36715
37003
  if (d.pageSize) qs.set("pageSize", String(d.pageSize));
36716
37004
  }
36717
37005
  const query = qs.toString();
36718
- const url = `${baseUrl(requireAuth(ctx), workspace)}/${journeyId}/steps/${stepId}/members${query ? `?${query}` : ""}`;
37006
+ const url = `${baseUrl2(requireAuth(ctx), workspace)}/${journeyId}/steps/${stepId}/members${query ? `?${query}` : ""}`;
36719
37007
  const result2 = await apiGet(requireAuth(ctx), url);
36720
37008
  const STEP_MEMBER_COLS = [
36721
37009
  { header: "MEMBER_ID", getValue: (item) => String(item.memberId ?? "") },
@@ -36738,7 +37026,7 @@ var journeysDomain = {
36738
37026
  const id = requireString(args, "id");
36739
37027
  const result2 = await apiGet(
36740
37028
  requireAuth(ctx),
36741
- `${baseUrl(requireAuth(ctx), workspace)}/${id}/step-member-counts`
37029
+ `${baseUrl2(requireAuth(ctx), workspace)}/${id}/step-member-counts`
36742
37030
  );
36743
37031
  const COUNT_COLS = [
36744
37032
  { header: "STEP_ID", getValue: (item) => String(item.stepId ?? "") },
@@ -37356,6 +37644,178 @@ var sitesDomain = {
37356
37644
  }
37357
37645
  ]
37358
37646
  };
37647
+ init_output();
37648
+ init_context();
37649
+ init_errors();
37650
+ var ATTACHED_COLUMNS = [
37651
+ { header: "UUID", getValue: (item) => item.uuid ?? "" },
37652
+ { header: "TYPE", getValue: (item) => item.abilityType ?? "" },
37653
+ { header: "ENABLED", getValue: (item) => item.enabled === false ? "" : "yes" },
37654
+ { header: "CEL", getValue: (item) => item.celCondition ?? "" }
37655
+ ];
37656
+ function toAbilityData(a) {
37657
+ return {
37658
+ uuid: a.uuid,
37659
+ abilityType: a.abilityType,
37660
+ config: a.config ?? {},
37661
+ enabled: a.enabled ?? true,
37662
+ ...a.celCondition ? { celCondition: a.celCondition } : {}
37663
+ };
37664
+ }
37665
+ var TYPE_COLUMNS = [
37666
+ { header: "SLUG", getValue: (item) => item.slug ?? "" },
37667
+ { header: "TITLE", getValue: (item) => item.title ?? "" },
37668
+ { header: "CATEGORY", getValue: (item) => item.category ?? "" },
37669
+ {
37670
+ header: "CHANNELS",
37671
+ // null channels means "all channels" — show that explicitly so an empty
37672
+ // cell never reads as "no channels".
37673
+ getValue: (item) => Array.isArray(item.channels) ? item.channels.join(",") : "all"
37674
+ },
37675
+ { header: "SINGLETON", getValue: (item) => item.singleton ? "yes" : "" },
37676
+ { header: "FEATURE-GATE", getValue: (item) => item.requiredFeature ?? "" }
37677
+ ];
37678
+ var abilitiesDomain = {
37679
+ name: "abilities",
37680
+ description: "Inspect ability types and attach/detach them on a task",
37681
+ commands: [
37682
+ {
37683
+ path: ["abilities", "list"],
37684
+ description: "List builtin ability types with their channel constraints and param specs. Table shows SLUG, TITLE, CATEGORY, CHANNELS (all = every channel), SINGLETON, FEATURE-GATE; use -o json for full specs including the params JSON Schema.",
37685
+ requiresWorkspace: true,
37686
+ columns: TYPE_COLUMNS,
37687
+ args: [
37688
+ {
37689
+ name: "include-system",
37690
+ description: "Also list auto-injected system abilities (hidden by default)",
37691
+ isFlag: true
37692
+ }
37693
+ ],
37694
+ handler: async (hctx) => {
37695
+ const includeSystem = hctx.args["include-system"] === true;
37696
+ const result2 = await requireAuth(hctx.ctx).apiClient.getAbilityTypes(
37697
+ hctx.workspace,
37698
+ includeSystem ? { includeSystem: true } : {}
37699
+ );
37700
+ outputData(result2.types ?? [], hctx.ctx, TYPE_COLUMNS);
37701
+ }
37702
+ },
37703
+ {
37704
+ path: ["abilities", "get"],
37705
+ description: "Show the full spec for one ability type: title, description, category, channels, singleton/system flags, required feature, and the JSON Schema of its params model.",
37706
+ requiresWorkspace: true,
37707
+ args: [
37708
+ {
37709
+ name: "name",
37710
+ aliases: ["slug"],
37711
+ description: "Ability type slug (e.g. 'communication:phone_call_tools')",
37712
+ required: true
37713
+ }
37714
+ ],
37715
+ handler: async (hctx) => {
37716
+ const slug = hctx.args.name ?? hctx.args.slug;
37717
+ if (!slug) throw new CLIError("--name is required");
37718
+ const result2 = await requireAuth(hctx.ctx).apiClient.getAbilityType(
37719
+ hctx.workspace,
37720
+ slug
37721
+ );
37722
+ outputSingle(result2, hctx.ctx);
37723
+ }
37724
+ },
37725
+ {
37726
+ path: ["abilities", "attached"],
37727
+ description: "List a task's task-specific abilities (excludes workflow-inherited).",
37728
+ requiresWorkspace: true,
37729
+ columns: ATTACHED_COLUMNS,
37730
+ args: [{ name: "task", description: "Task ID", required: true }],
37731
+ handler: async (hctx) => {
37732
+ const task = await requireAuth(hctx.ctx).apiClient.getTask(
37733
+ hctx.workspace,
37734
+ requireNumber(hctx.args, "task")
37735
+ );
37736
+ outputData(task.abilities ?? [], hctx.ctx, ATTACHED_COLUMNS);
37737
+ }
37738
+ },
37739
+ {
37740
+ path: ["abilities", "attach"],
37741
+ description: "Attach an ability to a task. Reads the task, appends the new ability (generating its uuid), and saves \u2014 so existing abilities aren't lost. Find slugs via 'gr abilities list' and the config schema via 'gr abilities get'.",
37742
+ mutates: true,
37743
+ requiresWorkspace: true,
37744
+ args: [
37745
+ { name: "task", description: "Task ID to attach to", required: true },
37746
+ {
37747
+ name: "type",
37748
+ aliases: ["ability-type", "slug"],
37749
+ description: "Ability type slug, e.g. 'integration:data_access'",
37750
+ required: true
37751
+ },
37752
+ {
37753
+ name: "config",
37754
+ description: `Ability config as a JSON object, e.g. '{"pauseOnEscalate":true}'`
37755
+ },
37756
+ { name: "cel", description: "Optional CEL activation condition" },
37757
+ {
37758
+ name: "disabled",
37759
+ description: "Attach in a disabled state (default: enabled)",
37760
+ isFlag: true
37761
+ }
37762
+ ],
37763
+ handler: async (hctx) => {
37764
+ const api = requireAuth(hctx.ctx).apiClient;
37765
+ const taskId = requireNumber(hctx.args, "task");
37766
+ const abilityType = hctx.args.type ?? hctx.args["ability-type"] ?? hctx.args.slug;
37767
+ if (!abilityType) throw new CLIError("--type is required (an ability type slug)");
37768
+ let config = {};
37769
+ if (hctx.args.config) {
37770
+ try {
37771
+ config = JSON.parse(hctx.args.config);
37772
+ } catch {
37773
+ throw new CLIError("--config must be a valid JSON object");
37774
+ }
37775
+ }
37776
+ const task = await api.getTask(hctx.workspace, taskId);
37777
+ const existing = (task.abilities ?? []).map(toAbilityData);
37778
+ const next = {
37779
+ uuid: randomUUID(),
37780
+ abilityType,
37781
+ config,
37782
+ enabled: hctx.args.disabled !== true,
37783
+ ...hctx.args.cel ? { celCondition: hctx.args.cel } : {}
37784
+ };
37785
+ const updated = await api.updateTask(hctx.workspace, taskId, {
37786
+ abilities: [...existing, next]
37787
+ });
37788
+ outputData(updated.abilities ?? [], hctx.ctx, ATTACHED_COLUMNS);
37789
+ }
37790
+ },
37791
+ {
37792
+ path: ["abilities", "detach"],
37793
+ description: "Detach an ability from a task by its uuid (from `gr abilities attached`). Re-saves the remaining task-specific abilities so the rest are preserved.",
37794
+ mutates: true,
37795
+ requiresWorkspace: true,
37796
+ args: [
37797
+ { name: "task", description: "Task ID", required: true },
37798
+ { name: "uuid", description: "UUID of the attached ability to remove", required: true }
37799
+ ],
37800
+ handler: async (hctx) => {
37801
+ const api = requireAuth(hctx.ctx).apiClient;
37802
+ const taskId = requireNumber(hctx.args, "task");
37803
+ const uuid = hctx.args.uuid;
37804
+ if (!uuid) throw new CLIError("--uuid is required");
37805
+ const task = await api.getTask(hctx.workspace, taskId);
37806
+ const existing = task.abilities ?? [];
37807
+ const remaining = existing.filter((a) => a.uuid !== uuid).map(toAbilityData);
37808
+ if (remaining.length === existing.length) {
37809
+ throw new CLIError(`No attached ability with uuid '${uuid}' on task ${taskId}`);
37810
+ }
37811
+ const updated = await api.updateTask(hctx.workspace, taskId, {
37812
+ abilities: remaining
37813
+ });
37814
+ outputData(updated.abilities ?? [], hctx.ctx, ATTACHED_COLUMNS);
37815
+ }
37816
+ }
37817
+ ]
37818
+ };
37359
37819
 
37360
37820
  // src/domains/access-grants.ts
37361
37821
  init_output();
@@ -37889,6 +38349,151 @@ var authManageDomain = {
37889
38349
  ]
37890
38350
  };
37891
38351
 
38352
+ // src/domains/billing.ts
38353
+ init_context();
38354
+ init_output();
38355
+ function priceSummary(product) {
38356
+ const plans = product.plans ?? {};
38357
+ const abbr = { month: "mo", year: "yr", quarter: "qtr" };
38358
+ const parts = [];
38359
+ for (const [period, plan] of Object.entries(plans)) {
38360
+ const cents = plan?.costPerPeriod ?? 0;
38361
+ if (!plan?.stripePriceId) continue;
38362
+ parts.push(`$${(cents / 100).toFixed(0)}/${abbr[period] ?? period}`);
38363
+ }
38364
+ return parts.join(", ") || "\u2014";
38365
+ }
38366
+ var PRODUCT_COLUMNS2 = [
38367
+ { header: "ID", getValue: (p) => String(p.id ?? "") },
38368
+ { header: "NAME", getValue: (p) => p.name ?? "" },
38369
+ { header: "TYPE", getValue: (p) => String(p.productType ?? "") },
38370
+ { header: "PRICE", getValue: (p) => priceSummary(p) },
38371
+ {
38372
+ header: "TRIAL",
38373
+ getValue: (p) => {
38374
+ const days = p.trialPeriodDays ?? 0;
38375
+ return days > 0 ? `${days}d` : "\u2014";
38376
+ }
38377
+ }
38378
+ ];
38379
+ var SUBSCRIPTION_COLUMNS = [
38380
+ COL.id(),
38381
+ COL.status(),
38382
+ { header: "PLAN", getValue: (s) => String(s.plan_name ?? s.productName ?? s.plan ?? "") },
38383
+ { header: "PERIOD", getValue: (s) => String(s.planPeriod ?? s.plan_period ?? "") },
38384
+ {
38385
+ header: "ORG",
38386
+ getValue: (s) => String(s.organizationUuid ?? s.customerOrganizationUuid ?? "")
38387
+ }
38388
+ ];
38389
+ function isTable(ctx) {
38390
+ return (ctx.outputFormat ?? "table") === "table";
38391
+ }
38392
+ function hint(ctx, lines) {
38393
+ if (!isTable(ctx)) return;
38394
+ process.stdout.write("\n" + lines.join("\n") + "\n");
38395
+ }
38396
+ function productType(args) {
38397
+ const t = args.type ?? args["product-type"];
38398
+ if (t === "org" || t === "workspace") return t;
38399
+ return void 0;
38400
+ }
38401
+ var billingDomain = {
38402
+ name: "billing",
38403
+ description: "Browse plans, start checkout, and check subscription status",
38404
+ commands: [
38405
+ {
38406
+ path: ["billing", "products"],
38407
+ description: "List self-service plans you can purchase",
38408
+ requiresWorkspace: false,
38409
+ args: [
38410
+ {
38411
+ name: "type",
38412
+ description: "Filter by plan type: 'org' or 'workspace'"
38413
+ }
38414
+ ],
38415
+ examples: ["gr billing products --type org"],
38416
+ handler: async ({ ctx, args }) => {
38417
+ const products = await requireAuth(ctx).apiClient.listSelfServeProducts(
38418
+ productType(args)
38419
+ );
38420
+ outputData(products, ctx, PRODUCT_COLUMNS2);
38421
+ if (products.length === 0) {
38422
+ hint(ctx, ["No purchasable plans found. (Free plans are not sold via the CLI.)"]);
38423
+ } else {
38424
+ hint(ctx, [
38425
+ "Next \u2014 buy an organization plan to get started:",
38426
+ " gr billing checkout --product <id> [--period month|year]"
38427
+ ]);
38428
+ }
38429
+ }
38430
+ },
38431
+ {
38432
+ path: ["billing", "checkout"],
38433
+ description: "Get a Stripe payment link to purchase an organization plan",
38434
+ mutates: true,
38435
+ requiresWorkspace: false,
38436
+ args: [
38437
+ { name: "product", description: "Product ID of the org plan to buy", required: true },
38438
+ { name: "period", description: "Billing period: 'month' or 'year'", default: "month" }
38439
+ ],
38440
+ examples: ["gr billing checkout --product 12 --period month"],
38441
+ handler: async ({ ctx, args }) => {
38442
+ const productId = Number(requireString(args, "product"));
38443
+ const period = args.period || "month";
38444
+ const result2 = await requireAuth(ctx).apiClient.createCheckoutSession(
38445
+ productId,
38446
+ period
38447
+ );
38448
+ if (isTable(ctx)) {
38449
+ process.stdout.write(
38450
+ `
38451
+ \u{1F4B3} Open this link in a browser to complete payment:
38452
+
38453
+ ${result2.checkoutUrl}
38454
+
38455
+ Once payment succeeds, your organization and subscription are created automatically.
38456
+ Then check it landed:
38457
+ gr billing status
38458
+ `
38459
+ );
38460
+ } else {
38461
+ outputSingle(result2, ctx);
38462
+ }
38463
+ }
38464
+ },
38465
+ {
38466
+ path: ["billing", "status"],
38467
+ description: "Show your subscriptions and what to do next",
38468
+ requiresWorkspace: false,
38469
+ examples: ["gr billing status"],
38470
+ handler: async ({ ctx }) => {
38471
+ const subs = await requireAuth(ctx).apiClient.getSubscriptions();
38472
+ outputData(subs, ctx, SUBSCRIPTION_COLUMNS);
38473
+ const active = subs.find(
38474
+ (s) => ["active", "trialing"].includes(String(s.status ?? s.subscriptionStatus ?? ""))
38475
+ );
38476
+ if (!active) {
38477
+ hint(ctx, [
38478
+ "No active subscription yet. To get started:",
38479
+ " gr billing products --type org # pick a plan",
38480
+ " gr billing checkout --product <id> # pay up front"
38481
+ ]);
38482
+ return;
38483
+ }
38484
+ const orgUuid = String(
38485
+ active.organizationUuid ?? active.customerOrganizationUuid ?? "<org-uuid>"
38486
+ );
38487
+ hint(ctx, [
38488
+ "You have an active subscription. Add a workspace:",
38489
+ " gr billing products --type workspace # pick a workspace plan",
38490
+ ` gr workspaces create --org ${orgUuid} --product <id> --name "My Workspace"`
38491
+ ]);
38492
+ }
38493
+ }
38494
+ ]
38495
+ };
38496
+
37892
38497
  // src/domains/billing-portal.ts
37893
38498
  init_errors();
37894
38499
  init_output();
@@ -39626,9 +40231,22 @@ function formatPhoneNumberBehaviorMatrix(phone, outboundUsers, warnings = collec
39626
40231
  lines.push(`UUID: ${phone.uuid} | Mapped: ${phone.isMapped ? "yes" : "no"}`);
39627
40232
  lines.push("");
39628
40233
  lines.push("## Channels");
39629
- lines.push(` Voice: ${phone.enableVoice ? "on" : "off"} SMS: ${phone.enableSms ? "on" : "off"} WhatsApp: ${phone.enableWhatsApp ? "on" : "off"}`);
40234
+ lines.push(
40235
+ ` Voice: ${phone.enableVoice ? "on" : "off"} SMS: ${phone.enableSms ? "on" : "off"} WhatsApp: ${phone.enableWhatsApp ? "on" : "off"}`
40236
+ );
39630
40237
  lines.push(` Assistant: ${phone.assistantEnabled ? "on" : "off"}`);
39631
40238
  lines.push("");
40239
+ if (phone.enableVoice) {
40240
+ lines.push("## Channel defaults (auto-injected on voice)");
40241
+ lines.push(
40242
+ " Voice channels auto-add the hang_up_call tool (system:voice_channel);"
40243
+ );
40244
+ lines.push(
40245
+ " it is not listed by `gr agents abilities list`. See `gr abilities get"
40246
+ );
40247
+ lines.push(" --name communication:phone_call_tools` for the voice ability spec.");
40248
+ lines.push("");
40249
+ }
39632
40250
  lines.push("## Inbound route");
39633
40251
  lines.push(
39634
40252
  ` defaultWorkflowId (inbound): ${phone.defaultWorkflowId ?? "null"} restartDelay: ${phone.restartDelay ?? "null"}s`
@@ -39709,9 +40327,7 @@ async function findOutboundPhoneUsers(client, workspace, phone) {
39709
40327
  }
39710
40328
  page += 1;
39711
40329
  if (page > 50) {
39712
- process.stderr.write(
39713
- "Warning: event-rules lookup truncated at 5000 results (50 pages)\n"
39714
- );
40330
+ process.stderr.write("Warning: event-rules lookup truncated at 5000 results (50 pages)\n");
39715
40331
  break;
39716
40332
  }
39717
40333
  }
@@ -40577,6 +41193,119 @@ var reportsDomain = {
40577
41193
  ]
40578
41194
  };
40579
41195
 
41196
+ // src/domains/routines.ts
41197
+ init_output();
41198
+ init_context();
41199
+
41200
+ // src/lib/routines/field-help.ts
41201
+ var ROUTINE_FIELD_REFERENCE = `
41202
+ Field reference for --data JSON (create/update):
41203
+
41204
+ Core
41205
+ name (string) Display name
41206
+ workflowId (number) Workflow run when the routine fires
41207
+ targetMemberId (number) Member who receives the scheduled outreach
41208
+
41209
+ Schedule
41210
+ scheduleEnabled (bool) Master on/off for the cron trigger
41211
+ scheduleMode (string) "CRON" (only mode today)
41212
+ cronString (string) Standard cron, e.g. "0 7 * * *"
41213
+ timezone (string, optional) IANA name, e.g. "America/Los_Angeles"
41214
+ Defaults to workspace timezone, else UTC
41215
+
41216
+ Visibility / lifecycle
41217
+ archived (bool) Archive flag on update
41218
+ event rules Use gr events rules create \u2014 not inline here
41219
+ `;
41220
+
41221
+ // src/domains/routines.ts
41222
+ var ROUTINE_COLUMNS = [
41223
+ COL.id(),
41224
+ COL.name(),
41225
+ { header: "MODE", getValue: (item) => item.scheduleMode ?? "" },
41226
+ { header: "CRON", getValue: (item) => item.cronString ?? "" },
41227
+ { header: "TZ", getValue: (item) => item.timezone ?? "UTC" },
41228
+ { header: "ENABLED", getValue: (item) => String(item.scheduleEnabled ?? "") },
41229
+ { header: "NEXT RUN", getValue: (item) => item.nextRun ?? "" }
41230
+ ];
41231
+ var routinesDomain = {
41232
+ name: "routines",
41233
+ description: "Schedule recurring outbound (e.g. a daily SMS/voice check-in via cron)",
41234
+ commands: [
41235
+ ...crudCommands({
41236
+ prefix: ["routines"],
41237
+ entityName: "routine",
41238
+ listMethod: "getRoutines",
41239
+ getMethod: "getRoutine",
41240
+ createMethod: "createRoutine",
41241
+ updateMethod: "updateRoutine",
41242
+ deleteMethod: "deleteRoutine",
41243
+ paginationSupport: "full",
41244
+ columns: ROUTINE_COLUMNS,
41245
+ createHelp: `Create a routine
41246
+
41247
+ ${ROUTINE_FIELD_REFERENCE}`,
41248
+ updateHelp: `Update a routine
41249
+
41250
+ ${ROUTINE_FIELD_REFERENCE}`,
41251
+ createExamples: [
41252
+ "Daily 7am check-in in the member\u2019s timezone (cron is interpreted in `timezone`):",
41253
+ `gr routines create -w $WID --allow-write --data '{"name":"AM check-in",`,
41254
+ ' "scheduleEnabled":true,"scheduleMode":"CRON","cronString":"0 7 * * *",',
41255
+ ` "timezone":"America/Los_Angeles","targetMemberId":1,"workflowId":2}'`,
41256
+ " (timezone is an IANA name; omit it to default to the workspace timezone, else UTC.",
41257
+ ' Without it, "0 7 * * *" fires at 07:00 UTC, not 7am local.)',
41258
+ "",
41259
+ "To actually send via SMS/voice, pair the routine with an event rule:",
41260
+ ' gr events rules create \u2014 objectType "routine", eventType "routine:triggered",',
41261
+ ' actionType "chat:create". See `gr events --help`.'
41262
+ ]
41263
+ }),
41264
+ {
41265
+ path: ["routines", "run"],
41266
+ description: "Run a routine now",
41267
+ mutates: true,
41268
+ requiresWorkspace: true,
41269
+ args: [{ name: "id", description: "Routine ID", required: true }],
41270
+ handler: async ({ ctx, workspace, args, data }) => {
41271
+ const result2 = await requireAuth(ctx).apiClient.runRoutine(
41272
+ workspace,
41273
+ requireNumber(args, "id"),
41274
+ data ?? {}
41275
+ );
41276
+ outputSingle(result2, ctx);
41277
+ }
41278
+ },
41279
+ {
41280
+ path: ["routines", "runs", "list"],
41281
+ description: "List runs for a routine",
41282
+ requiresWorkspace: true,
41283
+ args: [
41284
+ {
41285
+ name: "id",
41286
+ description: "Routine ID (aligns with routines get/run/update/delete)"
41287
+ },
41288
+ { name: "status", description: "Filter by run status" },
41289
+ { name: "page", description: "Page number (1-indexed)" },
41290
+ { name: "page-size", description: "Page size (max 100)" }
41291
+ ],
41292
+ handler: async ({ ctx, workspace, args }) => {
41293
+ const routineId = args.id ? requireNumber(args, "id") : void 0;
41294
+ const page = args.page ? requireNumber(args, "page") : void 0;
41295
+ const pageSize = args["page-size"] ? requireNumber(args, "page-size") : void 0;
41296
+ const status = args.status ?? void 0;
41297
+ const result2 = await requireAuth(ctx).apiClient.getRoutineRuns(workspace, {
41298
+ ...routineId !== void 0 ? { routineId } : {},
41299
+ ...page !== void 0 ? { page } : {},
41300
+ ...pageSize !== void 0 ? { pageSize } : {},
41301
+ ...status ? { status } : {}
41302
+ });
41303
+ outputData(result2, ctx);
41304
+ }
41305
+ }
41306
+ ]
41307
+ };
41308
+
40580
41309
  // src/domains/subscriptions.ts
40581
41310
  init_output();
40582
41311
  init_context();
@@ -42476,11 +43205,13 @@ function registerPublicDomains(registry) {
42476
43205
  registry.register(sitesDomain);
42477
43206
  registry.register(filesDomain);
42478
43207
  registry.register(eventsDomain);
43208
+ registry.register(routinesDomain);
42479
43209
  registry.register(experimentsDomain);
42480
43210
  registry.register(calendarsDomain);
42481
43211
  registry.register(qualificationsDomain);
42482
43212
  registry.register(personasDomain);
42483
43213
  registry.register(journeysDomain);
43214
+ registry.register(abilitiesDomain);
42484
43215
  registry.register(phoneNumbersDomain);
42485
43216
  registry.register(inboxesDomain);
42486
43217
  registry.register(operatorGroupsDomain);
@@ -42493,6 +43224,7 @@ function registerPublicDomains(registry) {
42493
43224
  registry.register(mcpServersDomain);
42494
43225
  registry.register(apiKeysDomain);
42495
43226
  registry.register(subscriptionsDomain);
43227
+ registry.register(billingDomain);
42496
43228
  registry.register(supportDomain);
42497
43229
  registry.register(reportsDomain);
42498
43230
  registry.register(aiModelsDomain);
@@ -42892,13 +43624,25 @@ async function runConciergeAguiLoop(client, initialMessages, onEvent, opts) {
42892
43624
  process.stderr.write(
42893
43625
  " [HITL] Unsupported interrupt in CLI \u2014 open app.gravityrail.com/setup to continue.\n"
42894
43626
  );
42895
- break;
43627
+ return {
43628
+ streamText,
43629
+ hasToolCalls,
43630
+ unsupportedHitl: normalizeUnsupportedHitl(hitlPayload)
43631
+ };
42896
43632
  }
42897
43633
  resume = next;
42898
43634
  streamText = "";
42899
43635
  }
42900
43636
  return { streamText, hasToolCalls };
42901
43637
  }
43638
+ function normalizeUnsupportedHitl(raw) {
43639
+ const payload = raw && typeof raw === "object" ? raw : {};
43640
+ return {
43641
+ type: typeof payload.type === "string" ? payload.type : void 0,
43642
+ interruptId: typeof payload.interrupt_id === "string" ? payload.interrupt_id : void 0,
43643
+ payload
43644
+ };
43645
+ }
42902
43646
 
42903
43647
  // src/lib/chat-session.ts
42904
43648
  init_errors();
@@ -43965,8 +44709,8 @@ var ChatTUI = class {
43965
44709
  const indent = " ".repeat(labelWidth);
43966
44710
  if (!this.streamContent) {
43967
44711
  if (this.runState === "thinking" || this.runState === "tool_running") {
43968
- const hint = this.runState === "tool_running" && this.activeToolName ? `Running ${this.activeToolName}\u2026` : "Thinking\u2026";
43969
- lines.push(`${label}${YELLOW}${hint}${RESET}`);
44712
+ const hint2 = this.runState === "tool_running" && this.activeToolName ? `Running ${this.activeToolName}\u2026` : "Thinking\u2026";
44713
+ lines.push(`${label}${YELLOW}${hint2}${RESET}`);
43970
44714
  } else {
43971
44715
  lines.push(label);
43972
44716
  }
@@ -44453,6 +45197,7 @@ var AudioPlayer = class extends EventEmitter {
44453
45197
  };
44454
45198
 
44455
45199
  // src/lib/chat-session.ts
45200
+ var HITL_INTERRUPT_EXIT_CODE = 3;
44456
45201
  async function runChatSession(session, args) {
44457
45202
  const debug = !!args.debug;
44458
45203
  const isVoice = !!args.voice;
@@ -44482,6 +45227,14 @@ async function runChatSession(session, args) {
44482
45227
  function vadMode(args) {
44483
45228
  return typeof args.vad === "string" ? args.vad : "server";
44484
45229
  }
45230
+ function sanitizeInterruptForStdout(result2) {
45231
+ const url = typeof result2.payload.url === "string" ? result2.payload.url : void 0;
45232
+ return {
45233
+ type: result2.type,
45234
+ interrupt_id: result2.interruptId,
45235
+ url
45236
+ };
45237
+ }
44485
45238
  async function singleTurnChatSession(session, message, debug, autoApprove = false, allowWrite = false) {
44486
45239
  const aguiClient = new AGUIClient({
44487
45240
  baseUrl: session.ctx.envConfig.apiUrl,
@@ -44501,7 +45254,7 @@ async function singleTurnChatSession(session, message, debug, autoApprove = fals
44501
45254
  `);
44502
45255
  }
44503
45256
  };
44504
- const { streamText, hasToolCalls } = await runConciergeAguiLoop(
45257
+ const { streamText, hasToolCalls, unsupportedHitl } = await runConciergeAguiLoop(
44505
45258
  aguiClient,
44506
45259
  [{ role: "user", content: message }],
44507
45260
  onEvent,
@@ -44514,6 +45267,21 @@ async function singleTurnChatSession(session, message, debug, autoApprove = fals
44514
45267
  nonInteractive: true
44515
45268
  }
44516
45269
  );
45270
+ if (unsupportedHitl) {
45271
+ const jsonPayload = JSON.stringify({
45272
+ error: "hitl_interrupt",
45273
+ message: "A human-in-the-loop interrupt requires out-of-band action before the operation can continue.",
45274
+ resume: {
45275
+ chatId: session.chatId,
45276
+ chatUuid: session.chatUuid,
45277
+ interruptId: unsupportedHitl.interruptId
45278
+ },
45279
+ interrupt: sanitizeInterruptForStdout(unsupportedHitl)
45280
+ });
45281
+ process.stdout.write(`${jsonPayload}
45282
+ `);
45283
+ throw new CLIError("HITL interrupt requires out-of-band handling", HITL_INTERRUPT_EXIT_CODE);
45284
+ }
44517
45285
  if (streamText) {
44518
45286
  process.stdout.write(`\x1B[32mAssistant:\x1B[0m ${streamText}
44519
45287
  `);
@@ -45025,11 +45793,12 @@ init_errors();
45025
45793
  async function conciergeOutboundCommand(hctx) {
45026
45794
  const ctx = requireAuth(hctx.ctx);
45027
45795
  const { args } = hctx;
45796
+ const message = typeof args.message === "string" ? args.message : void 0;
45028
45797
  if (args.call && args.sms) {
45029
45798
  throw new CLIError("--call and --sms are mutually exclusive");
45030
45799
  }
45031
45800
  if (args.call) {
45032
- const result2 = await originateConciergeCall(ctx);
45801
+ const result2 = await originateConciergeCall(ctx, "concierge_setup", message, "cli");
45033
45802
  process.stderr.write(
45034
45803
  `Concierge call started. callSid=${result2.callSid} startedAt=${result2.startedAt}
45035
45804
  `
@@ -45490,7 +46259,11 @@ var topLevelCommands = [
45490
46259
  description: "SMS your verified account phone (server-side)",
45491
46260
  isFlag: true
45492
46261
  },
45493
- { name: "message", alias: "m", description: "Single-turn: send one message and exit" },
46262
+ {
46263
+ name: "message",
46264
+ alias: "m",
46265
+ description: 'Single-turn: send one message and exit. With --call: the "why I am calling" anchor for the opening self-introduction.'
46266
+ },
45494
46267
  { name: "chat-id", description: "Resume an existing chat by numeric ID" },
45495
46268
  { name: "vad", description: "Voice activity detection: server (default) or client" },
45496
46269
  { name: "list-devices", description: "List audio devices and exit", isFlag: true },
@@ -45552,7 +46325,7 @@ init_concierge_api();
45552
46325
 
45553
46326
  // package.json
45554
46327
  var package_default = {
45555
- version: "0.7.3"};
46328
+ version: "0.8.0"};
45556
46329
 
45557
46330
  // src/gr.ts
45558
46331
  var VERSION = package_default.version;