@gravity-rail/cli 0.11.0 → 0.12.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-LODUVCW6.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_LODUVCW6 = __esm({
4443
+ "../sdk/dist/chunk-LODUVCW6.js"() {
4440
4444
  init_chunk_FSSXKQR5();
4441
4445
  init_libphonenumber_js();
4442
4446
  AbilitiesApi = class extends BaseApiClient {
@@ -9025,24 +9029,24 @@ 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
  }
9048
9052
  // ============================================================================
@@ -9058,8 +9062,8 @@ var init_chunk_YESHLUL7 = __esm({
9058
9062
  * which is impossible (lifecycle status is one of `draft` /
9059
9063
  * `pending-review` / `in-review` / `twilio-approved` / `twilio-rejected`).
9060
9064
  */
9061
- async getBusinessProfile(orgUuid) {
9062
- return this.fetch(`o/${orgUuid}/business-profile`);
9065
+ async getBusinessProfile(orgUuid, legalEntityUuid) {
9066
+ return this.fetch(businessProfilePath(orgUuid, legalEntityUuid));
9063
9067
  }
9064
9068
  /**
9065
9069
  * Upsert the org's business profile. Idempotent via cached SIDs.
@@ -9067,8 +9071,8 @@ var init_chunk_YESHLUL7 = __esm({
9067
9071
  * compliance evaluation result so the frontend can immediately enable
9068
9072
  * Submit without a second round-trip.
9069
9073
  */
9070
- async updateBusinessProfile(orgUuid, data) {
9071
- return this.fetch(`o/${orgUuid}/business-profile`, {
9074
+ async updateBusinessProfile(orgUuid, data, legalEntityUuid) {
9075
+ return this.fetch(businessProfilePath(orgUuid, legalEntityUuid), {
9072
9076
  method: "PUT",
9073
9077
  body: JSON.stringify(data)
9074
9078
  });
@@ -9078,20 +9082,46 @@ var init_chunk_YESHLUL7 = __esm({
9078
9082
  * compliance live and returns 412 if the profile is not currently
9079
9083
  * `compliant`; returns 409 if a review is already in flight.
9080
9084
  */
9081
- async submitBusinessProfile(orgUuid) {
9082
- return this.fetch(`o/${orgUuid}/business-profile/submit`, {
9083
- method: "POST"
9084
- });
9085
+ async submitBusinessProfile(orgUuid, legalEntityUuid) {
9086
+ return this.fetch(
9087
+ `${businessProfilePath(orgUuid, legalEntityUuid)}/submit`,
9088
+ { method: "POST" }
9089
+ );
9085
9090
  }
9086
9091
  /**
9087
9092
  * Cancel an in-flight Twilio review. Resets the cached profile state
9088
9093
  * to `draft` so the user can edit and resubmit.
9089
9094
  */
9090
- async cancelBusinessProfile(orgUuid) {
9091
- return this.fetch(`o/${orgUuid}/business-profile/cancel`, {
9092
- method: "POST"
9095
+ async cancelBusinessProfile(orgUuid, legalEntityUuid) {
9096
+ return this.fetch(
9097
+ `${businessProfilePath(orgUuid, legalEntityUuid)}/cancel`,
9098
+ { method: "POST" }
9099
+ );
9100
+ }
9101
+ // ============================================================================
9102
+ // Legal entities (Twilio Secondary Customer Profiles)
9103
+ // ============================================================================
9104
+ /** List the org's legal entities (one Customer Profile each). */
9105
+ async listLegalEntities(orgUuid) {
9106
+ return this.fetch(`o/${orgUuid}/legal-entities`);
9107
+ }
9108
+ /** Create a legal entity. Its business profile is edited via the entity-scoped business-profile methods. */
9109
+ async createLegalEntity(orgUuid, data) {
9110
+ return this.fetch(`o/${orgUuid}/legal-entities`, {
9111
+ method: "POST",
9112
+ body: JSON.stringify(data)
9093
9113
  });
9094
9114
  }
9115
+ async getLegalEntity(orgUuid, legalEntityUuid) {
9116
+ return this.fetch(`o/${orgUuid}/legal-entities/${legalEntityUuid}`);
9117
+ }
9118
+ /**
9119
+ * Brand detail with live registration-workflow state (`workflowStatus`,
9120
+ * `pendingSampleMessages`) for the sample-approval step.
9121
+ */
9122
+ async getA2PBrand(orgUuid, brandUuid) {
9123
+ return this.fetch(`o/${orgUuid}/a2p-brands/${brandUuid}`);
9124
+ }
9095
9125
  /**
9096
9126
  * List the org's A2P brands (broker resources). The SMS-consent editor uses
9097
9127
  * this to pick which brand's consent config to edit.
@@ -10405,11 +10435,11 @@ var init_chunk_YESHLUL7 = __esm({
10405
10435
  * customer, and subscription are created on payment by the checkout
10406
10436
  * completion handler.
10407
10437
  */
10408
- async createCheckoutSession(productId, planPeriod = "month") {
10438
+ async createCheckoutSession(productId, planPeriod = "month", options = {}) {
10409
10439
  return this.fetch(`subscriptions/checkout-session`, {
10410
10440
  method: "POST",
10411
10441
  credentials: "include",
10412
- body: JSON.stringify({ productId, planPeriod }),
10442
+ body: JSON.stringify({ productId, planPeriod, ...options }),
10413
10443
  headers: { "Content-Type": "application/json" }
10414
10444
  });
10415
10445
  }
@@ -10466,12 +10496,15 @@ var init_chunk_YESHLUL7 = __esm({
10466
10496
  return this.fetch(`subscriptions/${subscriptionId}/items`);
10467
10497
  }
10468
10498
  /** Purchase extra credits on a subscription (org-level). */
10469
- async purchaseCredits(subscriptionId, amountCents) {
10499
+ async purchaseCredits(subscriptionId, amountCents, idempotencyKey = crypto.randomUUID()) {
10470
10500
  return this.fetch(`subscriptions/${subscriptionId}/purchase-credits`, {
10471
10501
  method: "POST",
10472
10502
  credentials: "include",
10473
10503
  body: JSON.stringify({ amount_cents: amountCents }),
10474
- headers: { "Content-Type": "application/json" }
10504
+ headers: {
10505
+ "Content-Type": "application/json",
10506
+ "Idempotency-Key": idempotencyKey
10507
+ }
10475
10508
  });
10476
10509
  }
10477
10510
  };
@@ -10588,6 +10621,13 @@ var init_chunk_YESHLUL7 = __esm({
10588
10621
  async getMyCustomerInvoices(uuid) {
10589
10622
  return this.fetch(`customers/${uuid}/invoices`);
10590
10623
  }
10624
+ async createMyCustomerPortalSession(uuid, returnUrl) {
10625
+ return this.fetch(`customers/${uuid}/stripe/portal-session`, {
10626
+ method: "POST",
10627
+ body: JSON.stringify({ returnUrl }),
10628
+ headers: { "Content-Type": "application/json" }
10629
+ });
10630
+ }
10591
10631
  async updateMyCustomer(uuid, data) {
10592
10632
  return this.fetch(`customers/${uuid}`, {
10593
10633
  method: "PUT",
@@ -10605,7 +10645,8 @@ var init_chunk_YESHLUL7 = __esm({
10605
10645
  async attachMyCustomerPaymentMethod(uuid, paymentMethodId, setAsDefault = false) {
10606
10646
  return this.fetch(`customers/${uuid}/stripe/payment-methods/${paymentMethodId}/attach`, {
10607
10647
  method: "POST",
10608
- body: JSON.stringify({ setAsDefault })
10648
+ body: JSON.stringify({ setAsDefault }),
10649
+ headers: { "Content-Type": "application/json" }
10609
10650
  });
10610
10651
  }
10611
10652
  async detachMyCustomerPaymentMethod(uuid, paymentMethodId) {
@@ -11437,6 +11478,7 @@ var init_chunk_YESHLUL7 = __esm({
11437
11478
  EventRuleEventType2["CALL_STARTED"] = "call:started";
11438
11479
  EventRuleEventType2["CALL_COMPLETED"] = "call:completed";
11439
11480
  EventRuleEventType2["CALL_SUMMARY"] = "call:summary";
11481
+ EventRuleEventType2["VOICEMAIL_RECEIVED"] = "voicemail:received";
11440
11482
  return EventRuleEventType2;
11441
11483
  })(EventRuleEventType || {});
11442
11484
  DriverMode = /* @__PURE__ */ ((DriverMode2) => {
@@ -13826,6 +13868,7 @@ var init_chunk_YESHLUL7 = __esm({
13826
13868
  getMyCustomerAccounts;
13827
13869
  getMyCustomerSubscriptions;
13828
13870
  getMyCustomerInvoices;
13871
+ createMyCustomerPortalSession;
13829
13872
  updateMyCustomer;
13830
13873
  createMyCustomerSetupIntent;
13831
13874
  getMyCustomerPaymentMethods;
@@ -14056,7 +14099,7 @@ var init_chunk_V7ZKEH4V = __esm({
14056
14099
  var SEARCHABLE_EVENT_RULE_SOURCE_FIELDS;
14057
14100
  var init_dist = __esm({
14058
14101
  "../sdk/dist/index.js"() {
14059
- init_chunk_YESHLUL7();
14102
+ init_chunk_LODUVCW6();
14060
14103
  init_chunk_V7ZKEH4V();
14061
14104
  init_chunk_FSSXKQR5();
14062
14105
  SEARCHABLE_EVENT_RULE_SOURCE_FIELDS = [
@@ -41558,6 +41601,11 @@ function priceSummary(product) {
41558
41601
  }
41559
41602
  return parts.join(", ") || "\u2014";
41560
41603
  }
41604
+ function checkoutPeriod(args) {
41605
+ const value = typeof args.period === "string" ? args.period : "month";
41606
+ if (value === "month" || value === "quarter" || value === "year") return value;
41607
+ throw new Error("Billing period must be 'month', 'quarter', or 'year'");
41608
+ }
41561
41609
  var PRODUCT_COLUMNS2 = [
41562
41610
  { header: "ID", getValue: (p) => String(p.id ?? "") },
41563
41611
  { header: "NAME", getValue: (p) => p.name ?? "" },
@@ -41582,6 +41630,14 @@ var SUBSCRIPTION_COLUMNS = [
41582
41630
  getValue: (s) => String(s.customerOrganizationUuid ?? s.organizationUuid ?? "")
41583
41631
  }
41584
41632
  ];
41633
+ var CONTRACT_BEARING_STATUSES = /* @__PURE__ */ new Set([
41634
+ "incomplete",
41635
+ "trialing",
41636
+ "active",
41637
+ "past_due",
41638
+ "unpaid",
41639
+ "paused"
41640
+ ]);
41585
41641
  function isTable(ctx) {
41586
41642
  return (ctx.outputFormat ?? "table") === "table";
41587
41643
  }
@@ -41619,7 +41675,7 @@ var billingDomain = {
41619
41675
  } else {
41620
41676
  hint(ctx, [
41621
41677
  "Next \u2014 buy an organization plan to get started:",
41622
- " gr billing checkout --product <id> [--period month|year]"
41678
+ " gr billing checkout --product <id> [--org <id>|--new-org]"
41623
41679
  ]);
41624
41680
  }
41625
41681
  }
@@ -41631,15 +41687,40 @@ var billingDomain = {
41631
41687
  requiresWorkspace: false,
41632
41688
  args: [
41633
41689
  { name: "product", description: "Product ID of the org plan to buy", required: true },
41634
- { name: "period", description: "Billing period: 'month' or 'year'", default: "month" }
41690
+ {
41691
+ name: "period",
41692
+ description: "Billing period: 'month', 'quarter', or 'year'",
41693
+ default: "month"
41694
+ },
41695
+ {
41696
+ name: "org",
41697
+ description: "Existing organization ID to own the subscription"
41698
+ },
41699
+ {
41700
+ name: "new-org",
41701
+ description: "Create a new organization for this subscription",
41702
+ isFlag: true
41703
+ }
41704
+ ],
41705
+ examples: [
41706
+ "gr billing checkout --product 12 --period month --org 7",
41707
+ "gr billing checkout --product 12 --period month --new-org"
41635
41708
  ],
41636
- examples: ["gr billing checkout --product 12 --period month"],
41637
41709
  handler: async ({ ctx, args }) => {
41638
41710
  const productId = Number(requireString(args, "product"));
41639
- const period = args.period || "month";
41711
+ const period = checkoutPeriod(args);
41712
+ const organizationId = typeof args.org === "string" ? Number(args.org) : void 0;
41713
+ const createNewOrg = args["new-org"] === true;
41714
+ if (organizationId !== void 0 && (!Number.isInteger(organizationId) || organizationId <= 0)) {
41715
+ throw new Error("Organization ID must be a positive integer");
41716
+ }
41717
+ if (organizationId !== void 0 && createNewOrg) {
41718
+ throw new Error("Choose either --org or --new-org, not both");
41719
+ }
41640
41720
  const result3 = await requireAuth(ctx).apiClient.createCheckoutSession(
41641
41721
  productId,
41642
- period
41722
+ period,
41723
+ organizationId !== void 0 || createNewOrg ? { checkoutContext: { organizationId, createNewOrg } } : void 0
41643
41724
  );
41644
41725
  if (isTable(ctx)) {
41645
41726
  process.stdout.write(
@@ -41666,10 +41747,10 @@ Then check it landed:
41666
41747
  handler: async ({ ctx }) => {
41667
41748
  const subs = await requireAuth(ctx).apiClient.getSubscriptions();
41668
41749
  outputData(subs, ctx, SUBSCRIPTION_COLUMNS);
41669
- const active = subs.find(
41670
- (s) => ["active", "trialing"].includes(String(s.status ?? s.subscriptionStatus ?? ""))
41750
+ const contract = subs.find(
41751
+ (s) => CONTRACT_BEARING_STATUSES.has(String(s.status ?? s.subscriptionStatus ?? ""))
41671
41752
  );
41672
- if (!active) {
41753
+ if (!contract) {
41673
41754
  hint(ctx, [
41674
41755
  "No active subscription yet. To get started:",
41675
41756
  " gr billing products --type org # pick a plan",
@@ -41677,8 +41758,16 @@ Then check it landed:
41677
41758
  ]);
41678
41759
  return;
41679
41760
  }
41761
+ const contractStatus = String(contract.status ?? contract.subscriptionStatus ?? "");
41762
+ if (!["active", "trialing"].includes(contractStatus)) {
41763
+ hint(ctx, [
41764
+ `Your subscription is ${contractStatus}; it still represents a live billing contract.`,
41765
+ "Resolve its payment or cancellation status in Gravity Rail billing before starting another checkout."
41766
+ ]);
41767
+ return;
41768
+ }
41680
41769
  const orgUuid = String(
41681
- active.organizationUuid ?? active.customerOrganizationUuid ?? "<org-uuid>"
41770
+ contract.organizationUuid ?? contract.customerOrganizationUuid ?? "<org-uuid>"
41682
41771
  );
41683
41772
  hint(ctx, [
41684
41773
  "You have an active subscription. Add a workspace:",
@@ -49547,6 +49636,7 @@ var MAX_HITL_ROUNDS = 25;
49547
49636
  async function runConciergeAguiLoop(client, initialMessages, onEvent, opts) {
49548
49637
  let streamText = "";
49549
49638
  let hasToolCalls = false;
49639
+ let errorMessage;
49550
49640
  let resume;
49551
49641
  for (let round = 0; round < MAX_HITL_ROUNDS; round++) {
49552
49642
  let hitlPayload = null;
@@ -49563,8 +49653,11 @@ async function runConciergeAguiLoop(client, initialMessages, onEvent, opts) {
49563
49653
  const type = event.type?.toLowerCase() ?? "";
49564
49654
  if (type === "tool_call_start") hasToolCalls = true;
49565
49655
  const errorMsg = getErrorMessage(event);
49566
- if (errorMsg) process.stderr.write(`\x1B[31mError: ${errorMsg}\x1B[0m
49656
+ if (errorMsg) {
49657
+ errorMessage = errorMsg;
49658
+ process.stderr.write(`\x1B[31mError: ${errorMsg}\x1B[0m
49567
49659
  `);
49660
+ }
49568
49661
  const hitl = extractHumanInputRequest(event);
49569
49662
  if (hitl) hitlPayload = hitl;
49570
49663
  },
@@ -49593,13 +49686,15 @@ async function runConciergeAguiLoop(client, initialMessages, onEvent, opts) {
49593
49686
  return {
49594
49687
  streamText,
49595
49688
  hasToolCalls,
49596
- unsupportedHitl: normalizeUnsupportedHitl(hitlPayload)
49689
+ unsupportedHitl: normalizeUnsupportedHitl(hitlPayload),
49690
+ errorMessage
49597
49691
  };
49598
49692
  }
49599
49693
  resume = next;
49600
49694
  streamText = "";
49695
+ errorMessage = void 0;
49601
49696
  }
49602
- return { streamText, hasToolCalls };
49697
+ return { streamText, hasToolCalls, errorMessage };
49603
49698
  }
49604
49699
  function normalizeUnsupportedHitl(raw) {
49605
49700
  const payload = raw && typeof raw === "object" ? raw : {};
@@ -51164,6 +51259,7 @@ var AudioPlayer = class extends EventEmitter {
51164
51259
 
51165
51260
  // src/lib/chat-session.ts
51166
51261
  var HITL_INTERRUPT_EXIT_CODE = 3;
51262
+ var NO_FINAL_RESPONSE_EXIT_CODE = 4;
51167
51263
  async function runChatSession(session, args) {
51168
51264
  const debug = !!args.debug;
51169
51265
  const isVoice = !!args.voice;
@@ -51220,7 +51316,7 @@ async function singleTurnChatSession(session, message, debug, autoApprove = fals
51220
51316
  `);
51221
51317
  }
51222
51318
  };
51223
- const { streamText, hasToolCalls, unsupportedHitl } = await runConciergeAguiLoop(
51319
+ const { streamText, hasToolCalls, unsupportedHitl, errorMessage } = await runConciergeAguiLoop(
51224
51320
  aguiClient,
51225
51321
  [{ role: "user", content: message }],
51226
51322
  onEvent,
@@ -51274,12 +51370,30 @@ async function singleTurnChatSession(session, message, debug, autoApprove = fals
51274
51370
  } catch {
51275
51371
  }
51276
51372
  }
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)
51373
+ if (finalText) {
51374
+ process.stdout.write(`\x1B[32mAssistant:\x1B[0m ${finalText}
51281
51375
  `);
51376
+ return;
51377
+ }
51378
+ throw noFinalResponseError(
51379
+ errorMessage,
51380
+ /* hadToolCalls */
51381
+ true
51382
+ );
51282
51383
  }
51384
+ if (errorMessage) {
51385
+ throw noFinalResponseError(
51386
+ errorMessage,
51387
+ /* hadToolCalls */
51388
+ false
51389
+ );
51390
+ }
51391
+ process.stdout.write(`\x1B[32mAssistant:\x1B[0m (no response)
51392
+ `);
51393
+ }
51394
+ function noFinalResponseError(errorMessage, hadToolCalls) {
51395
+ 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";
51396
+ return new CLIError(`No assistant reply \u2014 ${detail}`, NO_FINAL_RESPONSE_EXIT_CODE);
51283
51397
  }
51284
51398
  async function interactiveChatSession(session, debug, autoApprove, allowWrite) {
51285
51399
  const aguiClient = new AGUIClient({
@@ -52542,7 +52656,7 @@ init_concierge_api();
52542
52656
 
52543
52657
  // package.json
52544
52658
  var package_default = {
52545
- version: "0.11.0"};
52659
+ version: "0.12.0"};
52546
52660
 
52547
52661
  // src/gr.ts
52548
52662
  var VERSION = package_default.version;