@gravity-rail/cli 0.11.0 → 0.13.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/README.md CHANGED
@@ -196,6 +196,7 @@ cat member.json | gr members update -w $WORKSPACE --id 42 --allow-write
196
196
  | `1` | General error |
197
197
  | `2` | Authentication required (run `gr login` or set `GRAVITY_RAIL_API_KEY`) |
198
198
  | `3` | A human-in-the-loop (HITL) interrupt requires out-of-band action before the operation can continue |
199
+ | `4` | No assistant reply — a `--message` turn made tool calls but returned no final summary, or an inference error occurred with no final message (side effects may have been applied) |
199
200
 
200
201
  When a concierge command run with `--message` (non-interactive mode) hits a HITL
201
202
  interrupt the CLI cannot resolve on its own, it exits `3` and writes a single
package/dist/gr.js CHANGED
@@ -3247,7 +3247,7 @@ var init_libphonenumber_js = __esm({
3247
3247
  }
3248
3248
  });
3249
3249
 
3250
- // ../sdk/dist/chunk-YESHLUL7.js
3250
+ // ../sdk/dist/chunk-MUEM2BLY.js
3251
3251
  function sanitizePhoneForBackend(phoneNumber) {
3252
3252
  try {
3253
3253
  let parsed = parsePhoneNumber4(phoneNumber);
@@ -3313,6 +3313,9 @@ function throwMemberImportError(errorBody, fallback) {
3313
3313
  }
3314
3314
  throw new Error(typeof detail === "string" ? detail : fallback);
3315
3315
  }
3316
+ function businessProfilePath(orgUuid, legalEntityUuid) {
3317
+ return legalEntityUuid ? `o/${orgUuid}/legal-entities/${legalEntityUuid}/business-profile` : `o/${orgUuid}/business-profile`;
3318
+ }
3316
3319
  function getOAuthPath(providerSlug, action) {
3317
3320
  if (providerSlug === "google_calendar") {
3318
3321
  return `oauth/google/calendar/${action}`;
@@ -4398,6 +4401,7 @@ function bindCustomersMethods(target, customers) {
4398
4401
  target.getMyCustomerAccounts = customers.getMyCustomerAccounts.bind(customers);
4399
4402
  target.getMyCustomerSubscriptions = customers.getMyCustomerSubscriptions.bind(customers);
4400
4403
  target.getMyCustomerInvoices = customers.getMyCustomerInvoices.bind(customers);
4404
+ target.createMyCustomerPortalSession = customers.createMyCustomerPortalSession.bind(customers);
4401
4405
  target.updateMyCustomer = customers.updateMyCustomer.bind(customers);
4402
4406
  target.createMyCustomerSetupIntent = customers.createMyCustomerSetupIntent.bind(customers);
4403
4407
  target.getMyCustomerPaymentMethods = customers.getMyCustomerPaymentMethods.bind(customers);
@@ -4435,8 +4439,8 @@ function bindSupportRequestMethods(target, supportRequests) {
4435
4439
  target.clickWorkspaceSupportRequestResource = supportRequests.clickWorkspaceSupportRequestResource.bind(supportRequests);
4436
4440
  }
4437
4441
  var 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, MemberImportValidationError, MembersApi, MilestonesApi, MondayIntegrationApi, NotificationRulesApi, OperatorApi, OrgApi, OAuthConnectionsApi, OAuthApi, PhoneNumbersApi, PronunciationsApi, PromptsApi, PersonasApi, QueriesApi, QualificationsApi, ReportsApi, SalesforceApi, ConnectionSyncApi, HubspotApi, SitesApi, SubscriptionsApi, SupportRequestsApi, CustomersApi, ResellersApi, SupervisorsApi, TasksApi, TemplatesApi, ToolkitsApi, JourneysApi, WorkflowsApi, WorkflowNotesApi, EventRuleEventType, DriverMode, WorkspaceInvitationsApi, WorkspacesApi, DashboardsApi, TeamsAppsApi, ExperimentsApi, PatientSyncConnectionsApi, MotdApi, WORKSPACE_METHOD_NAMES, WORKSPACE_METHOD_NAME_SET, GravityRailClient, WIDGET_SLUGS, CHAT_TYPES, BUILTIN_ASSISTANT_CHAT_TYPES, MEMBER_AGENT_CHAT_TYPES;
4438
- var init_chunk_YESHLUL7 = __esm({
4439
- "../sdk/dist/chunk-YESHLUL7.js"() {
4442
+ var init_chunk_MUEM2BLY = __esm({
4443
+ "../sdk/dist/chunk-MUEM2BLY.js"() {
4440
4444
  init_chunk_FSSXKQR5();
4441
4445
  init_libphonenumber_js();
4442
4446
  AbilitiesApi = class extends BaseApiClient {
@@ -9025,26 +9029,41 @@ var init_chunk_YESHLUL7 = __esm({
9025
9029
  return this.fetch(`o/${orgUuid}/phone-numbers/a2p/status`);
9026
9030
  }
9027
9031
  /**
9028
- * Start org-level A2P brand registration.
9032
+ * Start A2P brand registration under a legal entity. `legalEntityUuid`
9033
+ * is required — brands register per legal entity (Customer Profile);
9034
+ * there is no primary-entity fallback.
9029
9035
  */
9030
- async startA2PRegistration(orgUuid, brandName, brandDescription) {
9031
- return this.fetch(
9032
- `o/${orgUuid}/phone-numbers/a2p/start`,
9033
- {
9034
- method: "POST",
9035
- body: JSON.stringify({ brandName, brandDescription })
9036
- }
9037
- );
9036
+ async startA2PRegistration(orgUuid, legalEntityUuid, brandName, brandDescription) {
9037
+ return this.fetch(`o/${orgUuid}/phone-numbers/a2p/start`, {
9038
+ method: "POST",
9039
+ body: JSON.stringify({ legalEntityUuid, brandName, brandDescription })
9040
+ });
9038
9041
  }
9039
9042
  /**
9040
- * Approve sample messages for the org's A2P campaign.
9043
+ * Approve sample messages for one brand's A2P campaign. Signals the
9044
+ * brand's registration workflow to create the TCR campaign.
9041
9045
  */
9042
- async approveA2PMessages(orgUuid, sampleMessages) {
9046
+ async approveA2PMessages(orgUuid, brandUuid, sampleMessages) {
9043
9047
  return this.fetch(`o/${orgUuid}/phone-numbers/a2p/approve-messages`, {
9044
9048
  method: "POST",
9045
- body: JSON.stringify({ sampleMessages })
9049
+ body: JSON.stringify({ brandUuid, sampleMessages })
9046
9050
  });
9047
9051
  }
9052
+ /**
9053
+ * Activate SMS on a workspace-assigned number: attach it to the given
9054
+ * brand's Messaging Service (A2P 10DLC). Preconditions (412 otherwise):
9055
+ * campaign VERIFIED, brand has a Messaging Service, phone assigned to a
9056
+ * workspace with a Twilio SID.
9057
+ */
9058
+ async activateA2PNumber(orgUuid, providerPhoneUuid, brandUuid) {
9059
+ return this.fetch(
9060
+ `o/${orgUuid}/phone-numbers/a2p/activate-number`,
9061
+ {
9062
+ method: "POST",
9063
+ body: JSON.stringify({ providerPhoneUuid, brandUuid })
9064
+ }
9065
+ );
9066
+ }
9048
9067
  // ============================================================================
9049
9068
  // Organization Business Profile API (Twilio Trust Hub Secondary CP)
9050
9069
  // ============================================================================
@@ -9058,8 +9077,8 @@ var init_chunk_YESHLUL7 = __esm({
9058
9077
  * which is impossible (lifecycle status is one of `draft` /
9059
9078
  * `pending-review` / `in-review` / `twilio-approved` / `twilio-rejected`).
9060
9079
  */
9061
- async getBusinessProfile(orgUuid) {
9062
- return this.fetch(`o/${orgUuid}/business-profile`);
9080
+ async getBusinessProfile(orgUuid, legalEntityUuid) {
9081
+ return this.fetch(businessProfilePath(orgUuid, legalEntityUuid));
9063
9082
  }
9064
9083
  /**
9065
9084
  * Upsert the org's business profile. Idempotent via cached SIDs.
@@ -9067,8 +9086,8 @@ var init_chunk_YESHLUL7 = __esm({
9067
9086
  * compliance evaluation result so the frontend can immediately enable
9068
9087
  * Submit without a second round-trip.
9069
9088
  */
9070
- async updateBusinessProfile(orgUuid, data) {
9071
- return this.fetch(`o/${orgUuid}/business-profile`, {
9089
+ async updateBusinessProfile(orgUuid, data, legalEntityUuid) {
9090
+ return this.fetch(businessProfilePath(orgUuid, legalEntityUuid), {
9072
9091
  method: "PUT",
9073
9092
  body: JSON.stringify(data)
9074
9093
  });
@@ -9078,20 +9097,70 @@ var init_chunk_YESHLUL7 = __esm({
9078
9097
  * compliance live and returns 412 if the profile is not currently
9079
9098
  * `compliant`; returns 409 if a review is already in flight.
9080
9099
  */
9081
- async submitBusinessProfile(orgUuid) {
9082
- return this.fetch(`o/${orgUuid}/business-profile/submit`, {
9083
- method: "POST"
9084
- });
9100
+ async submitBusinessProfile(orgUuid, legalEntityUuid) {
9101
+ return this.fetch(
9102
+ `${businessProfilePath(orgUuid, legalEntityUuid)}/submit`,
9103
+ { method: "POST" }
9104
+ );
9085
9105
  }
9086
9106
  /**
9087
9107
  * Cancel an in-flight Twilio review. Resets the cached profile state
9088
9108
  * to `draft` so the user can edit and resubmit.
9089
9109
  */
9090
- async cancelBusinessProfile(orgUuid) {
9091
- return this.fetch(`o/${orgUuid}/business-profile/cancel`, {
9092
- method: "POST"
9110
+ async cancelBusinessProfile(orgUuid, legalEntityUuid) {
9111
+ return this.fetch(
9112
+ `${businessProfilePath(orgUuid, legalEntityUuid)}/cancel`,
9113
+ { method: "POST" }
9114
+ );
9115
+ }
9116
+ // ============================================================================
9117
+ // Legal entities (Twilio Secondary Customer Profiles)
9118
+ // ============================================================================
9119
+ /** List the org's legal entities (one Customer Profile each). */
9120
+ async listLegalEntities(orgUuid) {
9121
+ return this.fetch(`o/${orgUuid}/legal-entities`);
9122
+ }
9123
+ /** Create a legal entity. Its business profile is edited via the entity-scoped business-profile methods. */
9124
+ async createLegalEntity(orgUuid, data) {
9125
+ return this.fetch(`o/${orgUuid}/legal-entities`, {
9126
+ method: "POST",
9127
+ body: JSON.stringify(data)
9093
9128
  });
9094
9129
  }
9130
+ async getLegalEntity(orgUuid, legalEntityUuid) {
9131
+ return this.fetch(`o/${orgUuid}/legal-entities/${legalEntityUuid}`);
9132
+ }
9133
+ /** Cached voice trust product state (CNAM / SHAKEN-STIR / Voice Integrity) for one legal entity. */
9134
+ async getVoiceTrustProducts(orgUuid, legalEntityUuid) {
9135
+ return this.fetch(
9136
+ `o/${orgUuid}/legal-entities/${legalEntityUuid}/trust-products`
9137
+ );
9138
+ }
9139
+ /** Reconcile trust product state against Twilio (discovery + status refresh). */
9140
+ async syncVoiceTrustProducts(orgUuid, legalEntityUuid) {
9141
+ return this.fetch(
9142
+ `o/${orgUuid}/legal-entities/${legalEntityUuid}/trust-products/sync`,
9143
+ // Empty JSON body is the CSRF barrier the route requires (GRA-6284).
9144
+ { method: "POST", body: JSON.stringify({}) }
9145
+ );
9146
+ }
9147
+ /**
9148
+ * Set up + submit one voice trust product for a legal entity. Requires
9149
+ * the entity's business profile to be twilio-approved (412 otherwise).
9150
+ */
9151
+ async setupVoiceTrustProduct(orgUuid, legalEntityUuid, product, data) {
9152
+ return this.fetch(
9153
+ `o/${orgUuid}/legal-entities/${legalEntityUuid}/trust-products/${product}`,
9154
+ { method: "POST", body: JSON.stringify(data) }
9155
+ );
9156
+ }
9157
+ /**
9158
+ * Brand detail with live registration-workflow state (`workflowStatus`,
9159
+ * `pendingSampleMessages`) for the sample-approval step.
9160
+ */
9161
+ async getA2PBrand(orgUuid, brandUuid) {
9162
+ return this.fetch(`o/${orgUuid}/a2p-brands/${brandUuid}`);
9163
+ }
9095
9164
  /**
9096
9165
  * List the org's A2P brands (broker resources). The SMS-consent editor uses
9097
9166
  * this to pick which brand's consent config to edit.
@@ -10405,11 +10474,11 @@ var init_chunk_YESHLUL7 = __esm({
10405
10474
  * customer, and subscription are created on payment by the checkout
10406
10475
  * completion handler.
10407
10476
  */
10408
- async createCheckoutSession(productId, planPeriod = "month") {
10477
+ async createCheckoutSession(productId, planPeriod = "month", options = {}) {
10409
10478
  return this.fetch(`subscriptions/checkout-session`, {
10410
10479
  method: "POST",
10411
10480
  credentials: "include",
10412
- body: JSON.stringify({ productId, planPeriod }),
10481
+ body: JSON.stringify({ productId, planPeriod, ...options }),
10413
10482
  headers: { "Content-Type": "application/json" }
10414
10483
  });
10415
10484
  }
@@ -10466,12 +10535,15 @@ var init_chunk_YESHLUL7 = __esm({
10466
10535
  return this.fetch(`subscriptions/${subscriptionId}/items`);
10467
10536
  }
10468
10537
  /** Purchase extra credits on a subscription (org-level). */
10469
- async purchaseCredits(subscriptionId, amountCents) {
10538
+ async purchaseCredits(subscriptionId, amountCents, idempotencyKey = crypto.randomUUID()) {
10470
10539
  return this.fetch(`subscriptions/${subscriptionId}/purchase-credits`, {
10471
10540
  method: "POST",
10472
10541
  credentials: "include",
10473
10542
  body: JSON.stringify({ amount_cents: amountCents }),
10474
- headers: { "Content-Type": "application/json" }
10543
+ headers: {
10544
+ "Content-Type": "application/json",
10545
+ "Idempotency-Key": idempotencyKey
10546
+ }
10475
10547
  });
10476
10548
  }
10477
10549
  };
@@ -10588,6 +10660,13 @@ var init_chunk_YESHLUL7 = __esm({
10588
10660
  async getMyCustomerInvoices(uuid) {
10589
10661
  return this.fetch(`customers/${uuid}/invoices`);
10590
10662
  }
10663
+ async createMyCustomerPortalSession(uuid, returnUrl) {
10664
+ return this.fetch(`customers/${uuid}/stripe/portal-session`, {
10665
+ method: "POST",
10666
+ body: JSON.stringify({ returnUrl }),
10667
+ headers: { "Content-Type": "application/json" }
10668
+ });
10669
+ }
10591
10670
  async updateMyCustomer(uuid, data) {
10592
10671
  return this.fetch(`customers/${uuid}`, {
10593
10672
  method: "PUT",
@@ -10605,7 +10684,8 @@ var init_chunk_YESHLUL7 = __esm({
10605
10684
  async attachMyCustomerPaymentMethod(uuid, paymentMethodId, setAsDefault = false) {
10606
10685
  return this.fetch(`customers/${uuid}/stripe/payment-methods/${paymentMethodId}/attach`, {
10607
10686
  method: "POST",
10608
- body: JSON.stringify({ setAsDefault })
10687
+ body: JSON.stringify({ setAsDefault }),
10688
+ headers: { "Content-Type": "application/json" }
10609
10689
  });
10610
10690
  }
10611
10691
  async detachMyCustomerPaymentMethod(uuid, paymentMethodId) {
@@ -11437,6 +11517,7 @@ var init_chunk_YESHLUL7 = __esm({
11437
11517
  EventRuleEventType2["CALL_STARTED"] = "call:started";
11438
11518
  EventRuleEventType2["CALL_COMPLETED"] = "call:completed";
11439
11519
  EventRuleEventType2["CALL_SUMMARY"] = "call:summary";
11520
+ EventRuleEventType2["VOICEMAIL_RECEIVED"] = "voicemail:received";
11440
11521
  return EventRuleEventType2;
11441
11522
  })(EventRuleEventType || {});
11442
11523
  DriverMode = /* @__PURE__ */ ((DriverMode2) => {
@@ -13826,6 +13907,7 @@ var init_chunk_YESHLUL7 = __esm({
13826
13907
  getMyCustomerAccounts;
13827
13908
  getMyCustomerSubscriptions;
13828
13909
  getMyCustomerInvoices;
13910
+ createMyCustomerPortalSession;
13829
13911
  updateMyCustomer;
13830
13912
  createMyCustomerSetupIntent;
13831
13913
  getMyCustomerPaymentMethods;
@@ -14056,7 +14138,7 @@ var init_chunk_V7ZKEH4V = __esm({
14056
14138
  var SEARCHABLE_EVENT_RULE_SOURCE_FIELDS;
14057
14139
  var init_dist = __esm({
14058
14140
  "../sdk/dist/index.js"() {
14059
- init_chunk_YESHLUL7();
14141
+ init_chunk_MUEM2BLY();
14060
14142
  init_chunk_V7ZKEH4V();
14061
14143
  init_chunk_FSSXKQR5();
14062
14144
  SEARCHABLE_EVENT_RULE_SOURCE_FIELDS = [
@@ -41558,6 +41640,11 @@ function priceSummary(product) {
41558
41640
  }
41559
41641
  return parts.join(", ") || "\u2014";
41560
41642
  }
41643
+ function checkoutPeriod(args) {
41644
+ const value = typeof args.period === "string" ? args.period : "month";
41645
+ if (value === "month" || value === "quarter" || value === "year") return value;
41646
+ throw new Error("Billing period must be 'month', 'quarter', or 'year'");
41647
+ }
41561
41648
  var PRODUCT_COLUMNS2 = [
41562
41649
  { header: "ID", getValue: (p) => String(p.id ?? "") },
41563
41650
  { header: "NAME", getValue: (p) => p.name ?? "" },
@@ -41582,6 +41669,14 @@ var SUBSCRIPTION_COLUMNS = [
41582
41669
  getValue: (s) => String(s.customerOrganizationUuid ?? s.organizationUuid ?? "")
41583
41670
  }
41584
41671
  ];
41672
+ var CONTRACT_BEARING_STATUSES = /* @__PURE__ */ new Set([
41673
+ "incomplete",
41674
+ "trialing",
41675
+ "active",
41676
+ "past_due",
41677
+ "unpaid",
41678
+ "paused"
41679
+ ]);
41585
41680
  function isTable(ctx) {
41586
41681
  return (ctx.outputFormat ?? "table") === "table";
41587
41682
  }
@@ -41619,7 +41714,7 @@ var billingDomain = {
41619
41714
  } else {
41620
41715
  hint(ctx, [
41621
41716
  "Next \u2014 buy an organization plan to get started:",
41622
- " gr billing checkout --product <id> [--period month|year]"
41717
+ " gr billing checkout --product <id> [--org <id>|--new-org]"
41623
41718
  ]);
41624
41719
  }
41625
41720
  }
@@ -41631,15 +41726,40 @@ var billingDomain = {
41631
41726
  requiresWorkspace: false,
41632
41727
  args: [
41633
41728
  { name: "product", description: "Product ID of the org plan to buy", required: true },
41634
- { name: "period", description: "Billing period: 'month' or 'year'", default: "month" }
41729
+ {
41730
+ name: "period",
41731
+ description: "Billing period: 'month', 'quarter', or 'year'",
41732
+ default: "month"
41733
+ },
41734
+ {
41735
+ name: "org",
41736
+ description: "Existing organization ID to own the subscription"
41737
+ },
41738
+ {
41739
+ name: "new-org",
41740
+ description: "Create a new organization for this subscription",
41741
+ isFlag: true
41742
+ }
41743
+ ],
41744
+ examples: [
41745
+ "gr billing checkout --product 12 --period month --org 7",
41746
+ "gr billing checkout --product 12 --period month --new-org"
41635
41747
  ],
41636
- examples: ["gr billing checkout --product 12 --period month"],
41637
41748
  handler: async ({ ctx, args }) => {
41638
41749
  const productId = Number(requireString(args, "product"));
41639
- const period = args.period || "month";
41750
+ const period = checkoutPeriod(args);
41751
+ const organizationId = typeof args.org === "string" ? Number(args.org) : void 0;
41752
+ const createNewOrg = args["new-org"] === true;
41753
+ if (organizationId !== void 0 && (!Number.isInteger(organizationId) || organizationId <= 0)) {
41754
+ throw new Error("Organization ID must be a positive integer");
41755
+ }
41756
+ if (organizationId !== void 0 && createNewOrg) {
41757
+ throw new Error("Choose either --org or --new-org, not both");
41758
+ }
41640
41759
  const result3 = await requireAuth(ctx).apiClient.createCheckoutSession(
41641
41760
  productId,
41642
- period
41761
+ period,
41762
+ organizationId !== void 0 || createNewOrg ? { checkoutContext: { organizationId, createNewOrg } } : void 0
41643
41763
  );
41644
41764
  if (isTable(ctx)) {
41645
41765
  process.stdout.write(
@@ -41666,10 +41786,10 @@ Then check it landed:
41666
41786
  handler: async ({ ctx }) => {
41667
41787
  const subs = await requireAuth(ctx).apiClient.getSubscriptions();
41668
41788
  outputData(subs, ctx, SUBSCRIPTION_COLUMNS);
41669
- const active = subs.find(
41670
- (s) => ["active", "trialing"].includes(String(s.status ?? s.subscriptionStatus ?? ""))
41789
+ const contract = subs.find(
41790
+ (s) => CONTRACT_BEARING_STATUSES.has(String(s.status ?? s.subscriptionStatus ?? ""))
41671
41791
  );
41672
- if (!active) {
41792
+ if (!contract) {
41673
41793
  hint(ctx, [
41674
41794
  "No active subscription yet. To get started:",
41675
41795
  " gr billing products --type org # pick a plan",
@@ -41677,8 +41797,16 @@ Then check it landed:
41677
41797
  ]);
41678
41798
  return;
41679
41799
  }
41800
+ const contractStatus = String(contract.status ?? contract.subscriptionStatus ?? "");
41801
+ if (!["active", "trialing"].includes(contractStatus)) {
41802
+ hint(ctx, [
41803
+ `Your subscription is ${contractStatus}; it still represents a live billing contract.`,
41804
+ "Resolve its payment or cancellation status in Gravity Rail billing before starting another checkout."
41805
+ ]);
41806
+ return;
41807
+ }
41680
41808
  const orgUuid = String(
41681
- active.organizationUuid ?? active.customerOrganizationUuid ?? "<org-uuid>"
41809
+ contract.organizationUuid ?? contract.customerOrganizationUuid ?? "<org-uuid>"
41682
41810
  );
41683
41811
  hint(ctx, [
41684
41812
  "You have an active subscription. Add a workspace:",
@@ -49547,6 +49675,7 @@ var MAX_HITL_ROUNDS = 25;
49547
49675
  async function runConciergeAguiLoop(client, initialMessages, onEvent, opts) {
49548
49676
  let streamText = "";
49549
49677
  let hasToolCalls = false;
49678
+ let errorMessage;
49550
49679
  let resume;
49551
49680
  for (let round = 0; round < MAX_HITL_ROUNDS; round++) {
49552
49681
  let hitlPayload = null;
@@ -49563,8 +49692,11 @@ async function runConciergeAguiLoop(client, initialMessages, onEvent, opts) {
49563
49692
  const type = event.type?.toLowerCase() ?? "";
49564
49693
  if (type === "tool_call_start") hasToolCalls = true;
49565
49694
  const errorMsg = getErrorMessage(event);
49566
- if (errorMsg) process.stderr.write(`\x1B[31mError: ${errorMsg}\x1B[0m
49695
+ if (errorMsg) {
49696
+ errorMessage = errorMsg;
49697
+ process.stderr.write(`\x1B[31mError: ${errorMsg}\x1B[0m
49567
49698
  `);
49699
+ }
49568
49700
  const hitl = extractHumanInputRequest(event);
49569
49701
  if (hitl) hitlPayload = hitl;
49570
49702
  },
@@ -49593,13 +49725,15 @@ async function runConciergeAguiLoop(client, initialMessages, onEvent, opts) {
49593
49725
  return {
49594
49726
  streamText,
49595
49727
  hasToolCalls,
49596
- unsupportedHitl: normalizeUnsupportedHitl(hitlPayload)
49728
+ unsupportedHitl: normalizeUnsupportedHitl(hitlPayload),
49729
+ errorMessage
49597
49730
  };
49598
49731
  }
49599
49732
  resume = next;
49600
49733
  streamText = "";
49734
+ errorMessage = void 0;
49601
49735
  }
49602
- return { streamText, hasToolCalls };
49736
+ return { streamText, hasToolCalls, errorMessage };
49603
49737
  }
49604
49738
  function normalizeUnsupportedHitl(raw) {
49605
49739
  const payload = raw && typeof raw === "object" ? raw : {};
@@ -51164,6 +51298,7 @@ var AudioPlayer = class extends EventEmitter {
51164
51298
 
51165
51299
  // src/lib/chat-session.ts
51166
51300
  var HITL_INTERRUPT_EXIT_CODE = 3;
51301
+ var NO_FINAL_RESPONSE_EXIT_CODE = 4;
51167
51302
  async function runChatSession(session, args) {
51168
51303
  const debug = !!args.debug;
51169
51304
  const isVoice = !!args.voice;
@@ -51220,7 +51355,7 @@ async function singleTurnChatSession(session, message, debug, autoApprove = fals
51220
51355
  `);
51221
51356
  }
51222
51357
  };
51223
- const { streamText, hasToolCalls, unsupportedHitl } = await runConciergeAguiLoop(
51358
+ const { streamText, hasToolCalls, unsupportedHitl, errorMessage } = await runConciergeAguiLoop(
51224
51359
  aguiClient,
51225
51360
  [{ role: "user", content: message }],
51226
51361
  onEvent,
@@ -51274,12 +51409,30 @@ async function singleTurnChatSession(session, message, debug, autoApprove = fals
51274
51409
  } catch {
51275
51410
  }
51276
51411
  }
51277
- process.stdout.write(`\x1B[32mAssistant:\x1B[0m ${finalText || "(no text response)"}
51278
- `);
51279
- } else {
51280
- process.stdout.write(`\x1B[32mAssistant:\x1B[0m (no response)
51412
+ if (finalText) {
51413
+ process.stdout.write(`\x1B[32mAssistant:\x1B[0m ${finalText}
51281
51414
  `);
51415
+ return;
51416
+ }
51417
+ throw noFinalResponseError(
51418
+ errorMessage,
51419
+ /* hadToolCalls */
51420
+ true
51421
+ );
51422
+ }
51423
+ if (errorMessage) {
51424
+ throw noFinalResponseError(
51425
+ errorMessage,
51426
+ /* hadToolCalls */
51427
+ false
51428
+ );
51282
51429
  }
51430
+ process.stdout.write(`\x1B[32mAssistant:\x1B[0m (no response)
51431
+ `);
51432
+ }
51433
+ function noFinalResponseError(errorMessage, hadToolCalls) {
51434
+ const detail = errorMessage ? `inference error: ${errorMessage}` : hadToolCalls ? "the turn ran tool calls but returned no summary (side effects may have been applied)" : "no response from the assistant";
51435
+ return new CLIError(`No assistant reply \u2014 ${detail}`, NO_FINAL_RESPONSE_EXIT_CODE);
51283
51436
  }
51284
51437
  async function interactiveChatSession(session, debug, autoApprove, allowWrite) {
51285
51438
  const aguiClient = new AGUIClient({
@@ -52542,7 +52695,7 @@ init_concierge_api();
52542
52695
 
52543
52696
  // package.json
52544
52697
  var package_default = {
52545
- version: "0.11.0"};
52698
+ version: "0.13.0"};
52546
52699
 
52547
52700
  // src/gr.ts
52548
52701
  var VERSION = package_default.version;