@gravity-rail/cli 0.4.0 → 0.5.1

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
@@ -1,54 +1,15 @@
1
1
  #!/usr/bin/env node
2
+ import { CLIError, handleError, AuthRequiredError } from './chunk-XRBVAFCB.js';
3
+ import fs, { readFileSync, existsSync, mkdirSync, writeFileSync, chmodSync, unlinkSync, createWriteStream } from 'fs';
4
+ import path3, { join, resolve, dirname } from 'path';
2
5
  import { createServer } from 'http';
3
6
  import { randomBytes, createHash } from 'crypto';
4
- import { readFileSync, existsSync, mkdirSync, writeFileSync, chmodSync, unlinkSync, createWriteStream } from 'fs';
5
- import { join } from 'path';
6
7
  import { execSync, execFile, exec, spawn, spawnSync } from 'child_process';
7
8
  import * as readline from 'readline';
8
- import { homedir } from 'os';
9
+ import readline__default from 'readline';
10
+ import os, { homedir } from 'os';
9
11
  import { EventEmitter } from 'events';
10
12
 
11
- // src/lib/errors.ts
12
- var CLIError = class extends Error {
13
- constructor(message, exitCode = 1) {
14
- super(message);
15
- this.exitCode = exitCode;
16
- this.name = "CLIError";
17
- }
18
- };
19
- var AuthRequiredError = class extends CLIError {
20
- constructor(message = "Not authenticated. Run `gr login` or set GRAVITY_RAIL_API_KEY.") {
21
- super(message, 2);
22
- this.name = "AuthRequiredError";
23
- }
24
- };
25
- function handleError(err) {
26
- if (err instanceof CLIError) {
27
- process.stderr.write(`Error: ${err.message}
28
- `);
29
- process.exit(err.exitCode);
30
- }
31
- if (err instanceof Error) {
32
- process.stderr.write(`Error: ${err.message}
33
- `);
34
- if ("errors" in err && Array.isArray(err.errors)) {
35
- for (const e of err.errors) {
36
- process.stderr.write(` - ${e}
37
- `);
38
- }
39
- }
40
- if ("statusCode" in err && err.statusCode === 401) {
41
- process.stderr.write(`
42
- Hint: Run "yarn gr login" or use "--realm <name>" (dev only)
43
- `);
44
- }
45
- process.exit(1);
46
- }
47
- process.stderr.write(`Error: ${String(err)}
48
- `);
49
- process.exit(1);
50
- }
51
-
52
13
  // src/lib/pagination.ts
53
14
  function isListResult(data) {
54
15
  if (!data || typeof data !== "object" || Array.isArray(data)) return false;
@@ -172,7 +133,7 @@ var COMMON_ARGS = [
172
133
  { name: "uuid", description: "Entity UUID" }
173
134
  ];
174
135
  function parseArgs(defs, argv) {
175
- const allDefs = [...COMMON_ARGS, ...defs];
136
+ const allDefs = [...defs, ...COMMON_ARGS];
176
137
  const result2 = {};
177
138
  for (const def of allDefs) {
178
139
  if (def.default !== void 0) {
@@ -199,8 +160,7 @@ function parseArgs(defs, argv) {
199
160
  const def = findDef(allDefs, flagPart);
200
161
  if (!def) {
201
162
  if ((flagPart.startsWith("--") || flagPart.startsWith("-")) && !KNOWN_GLOBAL_FLAGS.has(flagPart)) {
202
- process.stderr.write(`Warning: unknown flag "${flagPart}" (ignored)
203
- `);
163
+ throw new CLIError(`Unknown flag "${flagPart}"`);
204
164
  }
205
165
  continue;
206
166
  }
@@ -215,9 +175,11 @@ function parseArgs(defs, argv) {
215
175
  }
216
176
  }
217
177
  for (const def of allDefs) {
218
- if (def.required && result2[def.name] === void 0) {
219
- throw new CLIError(`Missing required argument: --${def.name}`);
220
- }
178
+ if (!def.required) continue;
179
+ if (result2[def.name] !== void 0) continue;
180
+ const aliasNames = [def.alias, ...def.aliases ?? []].filter(Boolean);
181
+ if (aliasNames.some((a) => result2[a] !== void 0)) continue;
182
+ throw new CLIError(`Missing required argument: --${def.name}`);
221
183
  }
222
184
  return result2;
223
185
  }
@@ -2390,7 +2352,7 @@ function parsePhoneNumber4() {
2390
2352
  return withMetadataArgument(parsePhoneNumber3, arguments);
2391
2353
  }
2392
2354
 
2393
- // ../sdk/dist/chunk-3BG2GMJZ.js
2355
+ // ../sdk/dist/chunk-XRKRVY46.js
2394
2356
  function getCookieValue(name) {
2395
2357
  if (typeof document === "undefined") return void 0;
2396
2358
  const cookies = document.cookie.split(";");
@@ -2438,7 +2400,7 @@ function parseOrgAuthChallenge(wwwAuthenticate) {
2438
2400
  const cookieNameMatch = wwwAuthenticate.match(/cookie_name="([^"]+)"/);
2439
2401
  const authUrlMatch = wwwAuthenticate.match(/auth_url="([^"]+)"/);
2440
2402
  if (!orgUuidMatch?.[1] || !cookieNameMatch?.[1] || !authUrlMatch?.[1]) {
2441
- console.warn("Invalid org auth challenge header:", wwwAuthenticate);
2403
+ console.warn("Invalid org auth challenge header: missing required fields");
2442
2404
  return null;
2443
2405
  }
2444
2406
  return {
@@ -2455,8 +2417,17 @@ var BaseApiClient = class {
2455
2417
  enhancedAuthHandler;
2456
2418
  enhancedAuthInProgress = null;
2457
2419
  orgAuthHandler;
2420
+ orgAuthInProgress = null;
2458
2421
  actingMemberUuid;
2459
2422
  orgToken;
2423
+ /**
2424
+ * The org_uuid that issued the current orgToken. Tracked so we can detect
2425
+ * a 401 challenge from a *different* org and re-fire the handler — the
2426
+ * orgToken is an opaque JWE we cannot decrypt client-side, so without this
2427
+ * the original guard `!this.orgToken` would prevent re-auth across orgs and
2428
+ * surface as a silent 401 in multi-org CLI workflows.
2429
+ */
2430
+ orgTokenOrgUuid;
2460
2431
  constructor(apiKey, baseUrl3, customFetch) {
2461
2432
  this.baseUrl = baseUrl3;
2462
2433
  this.apiKey = apiKey;
@@ -2506,9 +2477,15 @@ var BaseApiClient = class {
2506
2477
  * Set the org token for cross-domain requests.
2507
2478
  * When set, all API requests will include the X-Org-Token header,
2508
2479
  * allowing org-level SSO verification without cookies.
2480
+ *
2481
+ * `orgUuid` is the org that issued the token; passing it lets the 401
2482
+ * handler detect a stale token when a subsequent request targets a
2483
+ * different org and re-fire the org-auth handler instead of silently
2484
+ * 401-ing. Callers without that context (legacy / unknown) may omit it.
2509
2485
  */
2510
- setOrgToken(token) {
2486
+ setOrgToken(token, orgUuid) {
2511
2487
  this.orgToken = token;
2488
+ this.orgTokenOrgUuid = token ? orgUuid : void 0;
2512
2489
  }
2513
2490
  async fetch(endpoint, options) {
2514
2491
  try {
@@ -2556,29 +2533,61 @@ var BaseApiClient = class {
2556
2533
  return await this.fetch(endpoint, options);
2557
2534
  } catch (retryError) {
2558
2535
  this.orgToken = void 0;
2536
+ this.orgTokenOrgUuid = void 0;
2559
2537
  throw retryError;
2560
2538
  }
2561
2539
  }
2562
2540
  if (response.status === 401) {
2563
2541
  const orgAuthInfo = parseOrgAuthChallenge(response.headers.get("WWW-Authenticate"));
2542
+ if (orgAuthInfo && this.orgToken && this.orgTokenOrgUuid && this.orgTokenOrgUuid !== orgAuthInfo.orgUuid) {
2543
+ this.orgToken = void 0;
2544
+ this.orgTokenOrgUuid = void 0;
2545
+ }
2564
2546
  if (orgAuthInfo && !this.orgToken) {
2565
2547
  const requestCookieName = orgAuthInfo.cookieName.replace(
2566
- "orgToken",
2548
+ /^orgToken/,
2567
2549
  "requestOrgToken"
2568
2550
  );
2569
2551
  const cachedOrgToken = getCookieValue(requestCookieName);
2570
2552
  if (cachedOrgToken) {
2571
2553
  this.orgToken = cachedOrgToken;
2554
+ this.orgTokenOrgUuid = orgAuthInfo.orgUuid;
2572
2555
  try {
2573
2556
  return await this.fetch(endpoint, options);
2574
2557
  } catch (retryError) {
2575
2558
  this.orgToken = void 0;
2559
+ this.orgTokenOrgUuid = void 0;
2576
2560
  throw retryError;
2577
2561
  }
2578
2562
  }
2579
2563
  if (this.orgAuthHandler) {
2580
- await this.orgAuthHandler(orgAuthInfo);
2581
- throw new ApiError("Organization authentication required", 401);
2564
+ if (!this.orgAuthInProgress) {
2565
+ const handler = this.orgAuthHandler;
2566
+ this.orgAuthInProgress = (async () => {
2567
+ try {
2568
+ await handler(orgAuthInfo);
2569
+ } finally {
2570
+ this.orgAuthInProgress = null;
2571
+ }
2572
+ })();
2573
+ }
2574
+ await this.orgAuthInProgress;
2575
+ const postHandlerToken = getCookieValue(requestCookieName) ?? this.orgToken;
2576
+ if (!postHandlerToken) {
2577
+ throw new ApiError(
2578
+ "Organization authentication did not issue a token",
2579
+ 401
2580
+ );
2581
+ }
2582
+ this.orgToken = postHandlerToken;
2583
+ this.orgTokenOrgUuid = orgAuthInfo.orgUuid;
2584
+ try {
2585
+ return await this.fetch(endpoint, options);
2586
+ } catch (retryError) {
2587
+ this.orgToken = void 0;
2588
+ this.orgTokenOrgUuid = void 0;
2589
+ throw retryError;
2590
+ }
2582
2591
  }
2583
2592
  }
2584
2593
  }
@@ -2677,29 +2686,61 @@ ${formattedErrors}`, response.status);
2677
2686
  return await this.fetchRaw(endpoint, options, allowedErrorStatuses);
2678
2687
  } catch (retryError) {
2679
2688
  this.orgToken = void 0;
2689
+ this.orgTokenOrgUuid = void 0;
2680
2690
  throw retryError;
2681
2691
  }
2682
2692
  }
2683
2693
  if (response.status === 401) {
2684
2694
  const orgAuthInfo = parseOrgAuthChallenge(response.headers.get("WWW-Authenticate"));
2695
+ if (orgAuthInfo && this.orgToken && this.orgTokenOrgUuid && this.orgTokenOrgUuid !== orgAuthInfo.orgUuid) {
2696
+ this.orgToken = void 0;
2697
+ this.orgTokenOrgUuid = void 0;
2698
+ }
2685
2699
  if (orgAuthInfo && !this.orgToken) {
2686
2700
  const requestCookieName = orgAuthInfo.cookieName.replace(
2687
- "orgToken",
2701
+ /^orgToken/,
2688
2702
  "requestOrgToken"
2689
2703
  );
2690
2704
  const cachedOrgToken = getCookieValue(requestCookieName);
2691
2705
  if (cachedOrgToken) {
2692
2706
  this.orgToken = cachedOrgToken;
2707
+ this.orgTokenOrgUuid = orgAuthInfo.orgUuid;
2693
2708
  try {
2694
2709
  return await this.fetchRaw(endpoint, options, allowedErrorStatuses);
2695
2710
  } catch (retryError) {
2696
2711
  this.orgToken = void 0;
2712
+ this.orgTokenOrgUuid = void 0;
2697
2713
  throw retryError;
2698
2714
  }
2699
2715
  }
2700
2716
  if (this.orgAuthHandler) {
2701
- await this.orgAuthHandler(orgAuthInfo);
2702
- throw new ApiError("Organization authentication required", 401);
2717
+ if (!this.orgAuthInProgress) {
2718
+ const handler = this.orgAuthHandler;
2719
+ this.orgAuthInProgress = (async () => {
2720
+ try {
2721
+ await handler(orgAuthInfo);
2722
+ } finally {
2723
+ this.orgAuthInProgress = null;
2724
+ }
2725
+ })();
2726
+ }
2727
+ await this.orgAuthInProgress;
2728
+ const postHandlerToken = getCookieValue(requestCookieName) ?? this.orgToken;
2729
+ if (!postHandlerToken) {
2730
+ throw new ApiError(
2731
+ "Organization authentication did not issue a token",
2732
+ 401
2733
+ );
2734
+ }
2735
+ this.orgToken = postHandlerToken;
2736
+ this.orgTokenOrgUuid = orgAuthInfo.orgUuid;
2737
+ try {
2738
+ return await this.fetchRaw(endpoint, options, allowedErrorStatuses);
2739
+ } catch (retryError) {
2740
+ this.orgToken = void 0;
2741
+ this.orgTokenOrgUuid = void 0;
2742
+ throw retryError;
2743
+ }
2703
2744
  }
2704
2745
  }
2705
2746
  }
@@ -2719,7 +2760,7 @@ ${formattedErrors}`, response.status);
2719
2760
  * Fetch from root path (not prefixed with /api/v2/)
2720
2761
  * Used for OAuth and other non-API endpoints
2721
2762
  */
2722
- async fetchRoot(path, options) {
2763
+ async fetchRoot(path4, options) {
2723
2764
  try {
2724
2765
  const headers2 = new Headers({
2725
2766
  ...options?.body instanceof FormData ? {} : { "Content-Type": "application/json" },
@@ -2739,7 +2780,7 @@ ${formattedErrors}`, response.status);
2739
2780
  if (this.orgToken) {
2740
2781
  headers2.set("X-Org-Token", this.orgToken);
2741
2782
  }
2742
- const fullUrl = `${this.baseUrl}/${path}`;
2783
+ const fullUrl = `${this.baseUrl}/${path4}`;
2743
2784
  const response = await this.fetchFunction(fullUrl, {
2744
2785
  ...options,
2745
2786
  ...this.apiKey ? {} : { credentials: "include" },
@@ -3106,7 +3147,8 @@ var AssignmentsApi = class extends BaseApiClient {
3106
3147
  if (options.sortOrder) params.append("sortOrder", options.sortOrder);
3107
3148
  if (options.mine) params.append("mine", options.mine.toString());
3108
3149
  if (options.taskId) params.append("taskId", options.taskId.toString());
3109
- if (options.memberId) params.append("memberId", options.memberId.toString());
3150
+ if (options.memberId !== void 0)
3151
+ params.append("memberId", options.memberId.toString());
3110
3152
  if (options.status) params.append("status", options.status);
3111
3153
  return this.fetch(
3112
3154
  `w/${wid}/assignments${params.toString() ? `?${params.toString()}` : ""}`
@@ -3897,6 +3939,8 @@ var ChatsApi = class extends BaseApiClient {
3897
3939
  if (options.filters && options.filters.length > 0) {
3898
3940
  params.append("filters", JSON.stringify(options.filters));
3899
3941
  }
3942
+ if (options.createdAfter) params.append("createdAfter", options.createdAfter);
3943
+ if (options.createdBefore) params.append("createdBefore", options.createdBefore);
3900
3944
  return params;
3901
3945
  }
3902
3946
  /** List chats with optional filtering, sorting, and pagination. */
@@ -5159,6 +5203,40 @@ var HealthieApi = class extends BaseApiClient {
5159
5203
  method: "DELETE"
5160
5204
  });
5161
5205
  }
5206
+ async listHealthieAppointmentTypes(wid, providerId) {
5207
+ const query = new URLSearchParams();
5208
+ if (providerId) query.set("provider_id", providerId);
5209
+ const qs = query.toString() ? `?${query.toString()}` : "";
5210
+ return this.fetch(
5211
+ `w/${wid}/app-connections/healthie/appointment-types${qs}`
5212
+ );
5213
+ }
5214
+ async listHealthiePatients(wid, keywords) {
5215
+ const query = new URLSearchParams();
5216
+ if (keywords?.trim()) query.set("keywords", keywords.trim());
5217
+ const qs = query.toString() ? `?${query.toString()}` : "";
5218
+ return this.fetch(
5219
+ `w/${wid}/app-connections/healthie/patients${qs}`
5220
+ );
5221
+ }
5222
+ async getHealthieAvailableSlots(wid, request) {
5223
+ return this.fetch(
5224
+ `w/${wid}/app-connections/healthie/scheduling/available-slots`,
5225
+ {
5226
+ method: "POST",
5227
+ body: JSON.stringify(request)
5228
+ }
5229
+ );
5230
+ }
5231
+ async bookHealthieAppointment(wid, request) {
5232
+ return this.fetch(
5233
+ `w/${wid}/app-connections/healthie/scheduling/book`,
5234
+ {
5235
+ method: "POST",
5236
+ body: JSON.stringify(request)
5237
+ }
5238
+ );
5239
+ }
5162
5240
  };
5163
5241
  var FilesApi = class extends BaseApiClient {
5164
5242
  /** List files in a workspace with optional folder filtering, sorting, and search. */
@@ -5422,10 +5500,17 @@ var InboxesApi = class extends BaseApiClient {
5422
5500
  method: "POST"
5423
5501
  });
5424
5502
  }
5503
+ /** Reply to an email from the inbox. */
5504
+ async replyToEmail(wid, inboxId, emailId, content) {
5505
+ return this.fetch(`w/${wid}/inboxes/${inboxId}/emails/${emailId}/reply`, {
5506
+ method: "POST",
5507
+ body: JSON.stringify({ content })
5508
+ });
5509
+ }
5425
5510
  /** Convert an email to text, markdown, or PDF format. */
5426
- async convertEmail(wid, emailId, format = "pdf") {
5511
+ async convertEmail(wid, inboxId, emailId, format = "pdf") {
5427
5512
  return this.fetch(
5428
- `w/${wid}/inboxes/emails/${emailId}/convert?format=${format}`,
5513
+ `w/${wid}/inboxes/${inboxId}/emails/${emailId}/convert?format=${format}`,
5429
5514
  {
5430
5515
  method: "POST"
5431
5516
  }
@@ -5596,6 +5681,19 @@ var AppConnectionsApi = class extends BaseApiClient {
5596
5681
  { method: "DELETE" }
5597
5682
  );
5598
5683
  }
5684
+ /**
5685
+ * List distinct ``MemberField.key`` values scoped to a connection
5686
+ * (GRA-2920). Drives the Monday custom-match "Custom fields" picker.
5687
+ *
5688
+ * Returns only the set of keys already in use on this connection;
5689
+ * values are intentionally never exposed. Operators can also add a
5690
+ * new key via the UI's "Add custom field key" free-text action.
5691
+ */
5692
+ async listConnectionMemberFieldKeys(wid, connectionId) {
5693
+ return this.fetch(
5694
+ `w/${wid}/app-connections/${connectionId}/member-field-keys`
5695
+ );
5696
+ }
5599
5697
  };
5600
5698
  var McpServersApi = class extends BaseApiClient {
5601
5699
  /**
@@ -6210,33 +6308,6 @@ var MondayIntegrationApi = class extends BaseApiClient {
6210
6308
  );
6211
6309
  return { columns };
6212
6310
  }
6213
- /**
6214
- * Create a webhook in Monday.com
6215
- */
6216
- async createWebhook(wid, params) {
6217
- return this.fetch(`w/${wid}/app-connections/monday/webhooks`, {
6218
- method: "POST",
6219
- body: JSON.stringify(params)
6220
- });
6221
- }
6222
- /**
6223
- * Delete a webhook from Monday.com
6224
- */
6225
- async deleteWebhook(wid, webhookId) {
6226
- return this.fetch(
6227
- `w/${wid}/app-connections/monday/webhooks/${webhookId}`,
6228
- { method: "DELETE" }
6229
- );
6230
- }
6231
- /**
6232
- * Get details of a specific webhook from Monday.com
6233
- * Returns 404 if the webhook no longer exists
6234
- */
6235
- async getWebhook(wid, boardId, webhookId) {
6236
- return this.fetch(
6237
- `w/${wid}/app-connections/monday/boards/${boardId}/webhooks/${webhookId}`
6238
- );
6239
- }
6240
6311
  /**
6241
6312
  * Get groups for a specific Monday.com board
6242
6313
  */
@@ -6843,6 +6914,53 @@ var OrgApi = class extends BaseApiClient {
6843
6914
  body: JSON.stringify({ sampleMessages })
6844
6915
  });
6845
6916
  }
6917
+ // ============================================================================
6918
+ // Organization Business Profile API (Twilio Trust Hub Secondary CP)
6919
+ // ============================================================================
6920
+ /**
6921
+ * Live fetch of the org's Twilio Customer Profile + related entities.
6922
+ *
6923
+ * Response carries both the lifecycle `status` and the compliance
6924
+ * `evaluationStatus`. Twilio models lifecycle and evaluation as two
6925
+ * separate enums on two separate resources, so the Submit-button gate
6926
+ * is `evaluationStatus === 'compliant'` — never `status === 'compliant'`,
6927
+ * which is impossible (lifecycle status is one of `draft` /
6928
+ * `pending-review` / `in-review` / `twilio-approved` / `twilio-rejected`).
6929
+ */
6930
+ async getBusinessProfile(orgUuid) {
6931
+ return this.fetch(`o/${orgUuid}/business-profile`);
6932
+ }
6933
+ /**
6934
+ * Upsert the org's business profile. Idempotent via cached SIDs.
6935
+ * Returns a fresh BusinessProfileResponse on success — including the
6936
+ * compliance evaluation result so the frontend can immediately enable
6937
+ * Submit without a second round-trip.
6938
+ */
6939
+ async updateBusinessProfile(orgUuid, data) {
6940
+ return this.fetch(`o/${orgUuid}/business-profile`, {
6941
+ method: "PUT",
6942
+ body: JSON.stringify(data)
6943
+ });
6944
+ }
6945
+ /**
6946
+ * Submit the business profile to Twilio for review. Server re-evaluates
6947
+ * compliance live and returns 412 if the profile is not currently
6948
+ * `compliant`; returns 409 if a review is already in flight.
6949
+ */
6950
+ async submitBusinessProfile(orgUuid) {
6951
+ return this.fetch(`o/${orgUuid}/business-profile/submit`, {
6952
+ method: "POST"
6953
+ });
6954
+ }
6955
+ /**
6956
+ * Cancel an in-flight Twilio review. Resets the cached profile state
6957
+ * to `draft` so the user can edit and resubmit.
6958
+ */
6959
+ async cancelBusinessProfile(orgUuid) {
6960
+ return this.fetch(`o/${orgUuid}/business-profile/cancel`, {
6961
+ method: "POST"
6962
+ });
6963
+ }
6846
6964
  /**
6847
6965
  * List available member roles for a workspace in the organization.
6848
6966
  */
@@ -6876,22 +6994,22 @@ var OAuthConnectionsApi = class extends BaseApiClient {
6876
6994
  * Get the connection status for an OAuth provider
6877
6995
  */
6878
6996
  async getConnectionStatus(providerSlug) {
6879
- const path = getOAuthPath(providerSlug, "status");
6880
- return this.fetchRoot(path);
6997
+ const path4 = getOAuthPath(providerSlug, "status");
6998
+ return this.fetchRoot(path4);
6881
6999
  }
6882
7000
  /**
6883
7001
  * Get the authorization URL to start OAuth flow
6884
7002
  */
6885
7003
  async getAuthorizationUrl(providerSlug) {
6886
- const path = getOAuthPath(providerSlug, "authorize");
6887
- return this.fetchRoot(path);
7004
+ const path4 = getOAuthPath(providerSlug, "authorize");
7005
+ return this.fetchRoot(path4);
6888
7006
  }
6889
7007
  /**
6890
7008
  * Disconnect an OAuth provider
6891
7009
  */
6892
7010
  async disconnect(providerSlug) {
6893
- const path = getOAuthPath(providerSlug, "disconnect");
6894
- return this.fetchRoot(path, { method: "DELETE" });
7011
+ const path4 = getOAuthPath(providerSlug, "disconnect");
7012
+ return this.fetchRoot(path4, { method: "DELETE" });
6895
7013
  }
6896
7014
  };
6897
7015
  var OAuthApi = class extends BaseApiClient {
@@ -7186,15 +7304,15 @@ var PronunciationsApi = class extends BaseApiClient {
7186
7304
  };
7187
7305
  var PromptsApi = class extends BaseApiClient {
7188
7306
  /** Inspect the full composed prompt for a task (static) or chat (live). */
7189
- async inspectPrompt(wid, taskId, options = {}) {
7307
+ async inspectPrompt(wid, options) {
7190
7308
  const params = new URLSearchParams();
7191
- if (options.chatId) {
7309
+ if (options.chatId !== void 0) {
7192
7310
  params.append("chat_id", options.chatId.toString());
7193
- } else {
7194
- params.append("task_id", taskId.toString());
7311
+ } else if (options.taskId !== void 0) {
7312
+ params.append("task_id", options.taskId.toString());
7195
7313
  }
7196
7314
  if (options.channel) params.append("channel", options.channel);
7197
- if (options.turn) params.append("turn", options.turn.toString());
7315
+ if (options.turn !== void 0) params.append("turn", options.turn.toString());
7198
7316
  return this.fetch(`w/${wid}/prompts/inspect?${params}`);
7199
7317
  }
7200
7318
  };
@@ -7537,7 +7655,8 @@ var ConnectionSyncApi = class extends BaseApiClient {
7537
7655
  dryRun: options?.dryRun ?? false,
7538
7656
  resetCheckpoints: options?.resetCheckpoints ?? false,
7539
7657
  ...options?.entityType ? { entityType: options.entityType } : {},
7540
- ...options?.boardId ? { boardId: options.boardId } : {}
7658
+ ...options?.boardId ? { boardId: options.boardId } : {},
7659
+ ...typeof options?.recordLimit === "number" ? { recordLimit: options.recordLimit } : {}
7541
7660
  })
7542
7661
  });
7543
7662
  }
@@ -7556,6 +7675,19 @@ var ConnectionSyncApi = class extends BaseApiClient {
7556
7675
  `w/${wid}/app-connections/${connectionId}/sync/runs/${runId}/items?limit=${limit}`
7557
7676
  );
7558
7677
  }
7678
+ /**
7679
+ * Clear a manual-unlink exclusion for a member on a connection so
7680
+ * subsequent outbound syncs stop silently skipping them. Idempotent:
7681
+ * returns ``cleared=false`` when no matching exclusion exists.
7682
+ * ``boardId`` is only meaningful for multi-scope connectors (Monday).
7683
+ */
7684
+ async clearConnectionMemberExclusion(wid, connectionId, memberId, options) {
7685
+ const query = options?.boardId ? `?board_id=${encodeURIComponent(options.boardId)}` : "";
7686
+ return this.fetch(
7687
+ `w/${wid}/app-connections/${connectionId}/member-exclusions/${memberId}${query}`,
7688
+ { method: "DELETE" }
7689
+ );
7690
+ }
7559
7691
  };
7560
7692
  var HubspotApi = class extends BaseApiClient {
7561
7693
  async configureHubspot(wid, data) {
@@ -7922,6 +8054,96 @@ var SubscriptionsApi = class extends BaseApiClient {
7922
8054
  });
7923
8055
  }
7924
8056
  };
8057
+ function supportRequestParams(params) {
8058
+ const searchParams = new URLSearchParams();
8059
+ if (params?.page) searchParams.append("page", params.page.toString());
8060
+ if (params?.pageSize) searchParams.append("pageSize", params.pageSize.toString());
8061
+ if (params?.status) searchParams.append("status", params.status);
8062
+ if (params?.supportRequestType) {
8063
+ searchParams.append("supportRequestType", params.supportRequestType);
8064
+ }
8065
+ if (params?.severity) searchParams.append("severity", params.severity);
8066
+ if (params?.source) searchParams.append("source", params.source);
8067
+ if (params?.organizationId !== void 0) {
8068
+ searchParams.append("organizationId", params.organizationId.toString());
8069
+ }
8070
+ if (params?.workspaceId !== void 0) {
8071
+ searchParams.append("workspaceId", params.workspaceId.toString());
8072
+ }
8073
+ if (params?.linearLinked !== void 0) {
8074
+ searchParams.append("linearLinked", params.linearLinked.toString());
8075
+ }
8076
+ const query = searchParams.toString();
8077
+ return query ? `?${query}` : "";
8078
+ }
8079
+ var SupportRequestsApi = class extends BaseApiClient {
8080
+ async listSupportRequests(params) {
8081
+ return this.fetch(
8082
+ `support-requests${supportRequestParams(params)}`
8083
+ );
8084
+ }
8085
+ async getSupportRequest(uuid) {
8086
+ return this.fetch(`support-requests/${uuid}`);
8087
+ }
8088
+ async createSupportRequest(data) {
8089
+ return this.fetch("support-requests", {
8090
+ method: "POST",
8091
+ body: JSON.stringify(data)
8092
+ });
8093
+ }
8094
+ async commentOnSupportRequest(uuid, data) {
8095
+ return this.fetch(`support-requests/${uuid}/comments`, {
8096
+ method: "POST",
8097
+ body: JSON.stringify(data)
8098
+ });
8099
+ }
8100
+ async listOrgSupportRequests(orgUuid, params) {
8101
+ return this.fetch(
8102
+ `o/${orgUuid}/support-requests${supportRequestParams(params)}`
8103
+ );
8104
+ }
8105
+ async getOrgSupportRequest(orgUuid, uuid) {
8106
+ return this.fetch(`o/${orgUuid}/support-requests/${uuid}`);
8107
+ }
8108
+ async createOrgSupportRequest(orgUuid, data) {
8109
+ return this.fetch(`o/${orgUuid}/support-requests`, {
8110
+ method: "POST",
8111
+ body: JSON.stringify(data)
8112
+ });
8113
+ }
8114
+ async commentOnOrgSupportRequest(orgUuid, uuid, data) {
8115
+ return this.fetch(`o/${orgUuid}/support-requests/${uuid}/comments`, {
8116
+ method: "POST",
8117
+ body: JSON.stringify(data)
8118
+ });
8119
+ }
8120
+ async listWorkspaceSupportRequests(workspaceUuid, params) {
8121
+ return this.fetch(
8122
+ `w/${workspaceUuid}/support-requests${supportRequestParams(params)}`
8123
+ );
8124
+ }
8125
+ async getWorkspaceSupportRequest(workspaceUuid, uuid) {
8126
+ return this.fetch(`w/${workspaceUuid}/support-requests/${uuid}`);
8127
+ }
8128
+ async createWorkspaceSupportRequest(workspaceUuid, data) {
8129
+ return this.fetch(`w/${workspaceUuid}/support-requests`, {
8130
+ method: "POST",
8131
+ body: JSON.stringify(data)
8132
+ });
8133
+ }
8134
+ async commentOnWorkspaceSupportRequest(workspaceUuid, uuid, data) {
8135
+ return this.fetch(`w/${workspaceUuid}/support-requests/${uuid}/comments`, {
8136
+ method: "POST",
8137
+ body: JSON.stringify(data)
8138
+ });
8139
+ }
8140
+ async closeWorkspaceSupportRequest(workspaceUuid, uuid, data = {}) {
8141
+ return this.fetch(`w/${workspaceUuid}/support-requests/${uuid}/close`, {
8142
+ method: "POST",
8143
+ body: JSON.stringify(data)
8144
+ });
8145
+ }
8146
+ };
7925
8147
  var CustomersApi = class extends BaseApiClient {
7926
8148
  async getMyCustomers() {
7927
8149
  return this.fetch("customers");
@@ -7935,8 +8157,8 @@ var CustomersApi = class extends BaseApiClient {
7935
8157
  async getMyCustomerSubscriptions(uuid, opts) {
7936
8158
  const params = new URLSearchParams();
7937
8159
  if (opts?.status) params.set("status", opts.status);
7938
- if (opts?.page) params.set("page", String(opts.page));
7939
- if (opts?.pageSize) params.set("page_size", String(opts.pageSize));
8160
+ if (opts?.page !== void 0) params.set("page", String(opts.page));
8161
+ if (opts?.pageSize !== void 0) params.set("page_size", String(opts.pageSize));
7940
8162
  const qs = params.toString();
7941
8163
  return this.fetch(`customers/${uuid}/subscriptions${qs ? "?" + qs : ""}`);
7942
8164
  }
@@ -7973,6 +8195,16 @@ var CustomersApi = class extends BaseApiClient {
7973
8195
  method: "PUT"
7974
8196
  });
7975
8197
  }
8198
+ async getMyCustomerCreditGrants(uuid, opts) {
8199
+ const params = new URLSearchParams();
8200
+ if (opts?.subscriptionId !== void 0) {
8201
+ params.set("subscription_id", String(opts.subscriptionId));
8202
+ }
8203
+ if (opts?.page !== void 0) params.set("page", String(opts.page));
8204
+ if (opts?.pageSize !== void 0) params.set("page_size", String(opts.pageSize));
8205
+ const qs = params.toString();
8206
+ return this.fetch(`customers/${uuid}/credit-grants${qs ? "?" + qs : ""}`);
8207
+ }
7976
8208
  };
7977
8209
  var ResellersApi = class extends BaseApiClient {
7978
8210
  async getMyResellers() {
@@ -8195,6 +8427,14 @@ var JourneysApi = class extends BaseApiClient {
8195
8427
  method: "DELETE"
8196
8428
  });
8197
8429
  }
8430
+ /**
8431
+ * Get Journey Health diagnostics — authoring issues and runtime
8432
+ * failures for a single journey. PHI-safe: response carries IDs,
8433
+ * counts, error_type strings, and timestamps only.
8434
+ */
8435
+ async getJourneyHealth(wid, journeyId) {
8436
+ return this.fetch(`w/${wid}/journeys/${journeyId}/health`);
8437
+ }
8198
8438
  /** Create a step within a journey. */
8199
8439
  async createStep(wid, journeyId, data) {
8200
8440
  return this.fetch(`w/${wid}/journeys/${journeyId}/steps`, {
@@ -8262,6 +8502,13 @@ var JourneysApi = class extends BaseApiClient {
8262
8502
  if (params?.page) qs.set("page", String(params.page));
8263
8503
  if (params?.pageSize) qs.set("pageSize", String(params.pageSize));
8264
8504
  if (params?.search) qs.set("search", params.search);
8505
+ if (params?.status) qs.set("status", params.status);
8506
+ if (params?.enrolledAfter) qs.set("enrolledAfter", params.enrolledAfter);
8507
+ if (params?.enrolledBefore) qs.set("enrolledBefore", params.enrolledBefore);
8508
+ if (params?.currentTaskId !== void 0)
8509
+ qs.set("currentTaskId", String(params.currentTaskId));
8510
+ if (params?.runtimeFailureEdgeId !== void 0)
8511
+ qs.set("runtimeFailureEdgeId", String(params.runtimeFailureEdgeId));
8265
8512
  const query = qs.toString();
8266
8513
  return this.fetch(
8267
8514
  `w/${wid}/journeys/${journeyId}/members${query ? `?${query}` : ""}`
@@ -8282,10 +8529,10 @@ var JourneysApi = class extends BaseApiClient {
8282
8529
  });
8283
8530
  }
8284
8531
  /** Re-enroll a canceled member back to enrolled status. */
8285
- async reenrollMember(wid, journeyId, memberId) {
8532
+ async reenrollMember(wid, journeyId, data) {
8286
8533
  return this.fetch(`w/${wid}/journeys/${journeyId}/reenroll`, {
8287
8534
  method: "POST",
8288
- body: JSON.stringify({ memberId })
8535
+ body: JSON.stringify(data)
8289
8536
  });
8290
8537
  }
8291
8538
  /** Hard-delete a canceled enrollment so the member can be re-enrolled fresh. */
@@ -8298,6 +8545,18 @@ var JourneysApi = class extends BaseApiClient {
8298
8545
  async getMemberJourneys(wid, memberId) {
8299
8546
  return this.fetch(`w/${wid}/journeys/by-member/${memberId}`);
8300
8547
  }
8548
+ /**
8549
+ * Dry-run heartbeat CEL evaluation for an enrolled member.
8550
+ *
8551
+ * Evaluates all PENDING steps exactly as the heartbeat would, but writes no
8552
+ * state changes. Returns step-by-step results for debugging stuck members.
8553
+ */
8554
+ async testRunJourney(wid, journeyId, memberId) {
8555
+ return this.fetch(
8556
+ `w/${wid}/journeys/${journeyId}/members/${memberId}/test-run`,
8557
+ { method: "POST" }
8558
+ );
8559
+ }
8301
8560
  // ===== JOURNEY NOTES =====
8302
8561
  /** List notes for a journey. */
8303
8562
  async getJourneyNotes(wid, journeyId) {
@@ -8448,6 +8707,30 @@ var WorkflowsApi = class extends BaseApiClient {
8448
8707
  `w/${wid}/workflows/${workflowId}/validate-config`
8449
8708
  );
8450
8709
  }
8710
+ /**
8711
+ * Replay automatic routing for a Chat without performing the transition.
8712
+ *
8713
+ * Operator tool: returns a PHI-safe trace describing what the
8714
+ * automatic-edge evaluator would do at the next turn. Never returns
8715
+ * raw CEL, Form values, Member values, Chat content, or raw
8716
+ * exception strings — only IDs, status labels, and the exception
8717
+ * class name when the evaluator raises.
8718
+ *
8719
+ * Requires Workflow edit permission.
8720
+ */
8721
+ async getWorkflowRouteDryRun(wid, workflowId, args) {
8722
+ const params = new URLSearchParams();
8723
+ params.set("chat_id", String(args.chatId));
8724
+ if (args.currentTaskId !== void 0) {
8725
+ params.set("current_task_id", String(args.currentTaskId));
8726
+ }
8727
+ if (args.currentAssignmentTaskId !== void 0) {
8728
+ params.set("current_assignment_task_id", String(args.currentAssignmentTaskId));
8729
+ }
8730
+ return this.fetch(
8731
+ `w/${wid}/workflows/${workflowId}/route-dry-run?${params.toString()}`
8732
+ );
8733
+ }
8451
8734
  // Workflow Contributors API
8452
8735
  /** List all contributors for a workflow. */
8453
8736
  async getWorkflowContributors(wid, workflowId) {
@@ -8594,6 +8877,33 @@ var WorkflowNotesApi = class extends BaseApiClient {
8594
8877
  });
8595
8878
  }
8596
8879
  };
8880
+ var EventRuleEventType = /* @__PURE__ */ ((EventRuleEventType2) => {
8881
+ EventRuleEventType2["TASK_EXECUTE"] = "task:execute";
8882
+ EventRuleEventType2["MEMBER_JOINED"] = "workspace:member_joined";
8883
+ EventRuleEventType2["MEMBER_LEFT"] = "workspace:member_left";
8884
+ EventRuleEventType2["DATA_RECORD_CREATED"] = "data_record:created";
8885
+ EventRuleEventType2["DATA_RECORD_UPDATED"] = "data_record:updated";
8886
+ EventRuleEventType2["CHAT_CREATED"] = "chat:created";
8887
+ EventRuleEventType2["CHAT_CALLBACK"] = "chat:callback";
8888
+ EventRuleEventType2["MEMBER_UPDATED"] = "member:updated";
8889
+ EventRuleEventType2["ROUTINE_TRIGGERED"] = "routine:triggered";
8890
+ EventRuleEventType2["ASSISTANT_MESSAGE"] = "workflow:assistant_message";
8891
+ EventRuleEventType2["USER_MESSAGE"] = "workflow:user_message";
8892
+ EventRuleEventType2["CALENDAR_EVENT_CREATED"] = "calendar_event:created";
8893
+ EventRuleEventType2["CALENDAR_EVENT_UPDATED"] = "calendar_event:updated";
8894
+ EventRuleEventType2["CALENDAR_EVENT_CANCELLED"] = "calendar_event:cancelled";
8895
+ EventRuleEventType2["CALENDAR_EVENT_STARTING"] = "calendar_event:starting";
8896
+ EventRuleEventType2["CALENDAR_EVENT_ENDED"] = "calendar_event:ended";
8897
+ EventRuleEventType2["CONNECTOR_EVENT"] = "connector:event";
8898
+ EventRuleEventType2["ASSIGNMENT_CONCLUDED"] = "assignment:concluded";
8899
+ EventRuleEventType2["JOURNEY_STEP_EXECUTE"] = "journey_step:execute";
8900
+ EventRuleEventType2["JOURNEY_ENROLLED"] = "journey:enrolled";
8901
+ EventRuleEventType2["JOURNEY_COMPLETED"] = "journey:completed";
8902
+ EventRuleEventType2["CALL_STARTED"] = "call:started";
8903
+ EventRuleEventType2["CALL_COMPLETED"] = "call:completed";
8904
+ EventRuleEventType2["CALL_SUMMARY"] = "call:summary";
8905
+ return EventRuleEventType2;
8906
+ })(EventRuleEventType || {});
8597
8907
  var WorkspaceInvitationsApi = class extends BaseApiClient {
8598
8908
  /**
8599
8909
  * List user's own invitations (both org and workspace).
@@ -9051,6 +9361,66 @@ var WorkspacesApi = class extends BaseApiClient {
9051
9361
  return this.fetch(`w/${wid}/usage/dashboard`);
9052
9362
  }
9053
9363
  };
9364
+ var TeamsAppsApi = class extends BaseApiClient {
9365
+ /**
9366
+ * List all Teams apps configured for a workspace.
9367
+ */
9368
+ async getTeamsApps(wid, options = {}) {
9369
+ const params = new URLSearchParams();
9370
+ if (options.page) params.append("page", options.page.toString());
9371
+ if (options.pageSize) params.append("pageSize", options.pageSize.toString());
9372
+ if (options.sortBy) params.append("sortBy", options.sortBy);
9373
+ if (options.sortOrder) params.append("sortOrder", options.sortOrder);
9374
+ if (options.search) params.append("search", options.search);
9375
+ return this.fetch(
9376
+ `w/${wid}/app-connections/teams/apps${params.toString() ? `?${params.toString()}` : ""}`
9377
+ );
9378
+ }
9379
+ async getTeamsApp(wid, appId) {
9380
+ return this.fetch(`w/${wid}/app-connections/teams/apps/${appId}`);
9381
+ }
9382
+ async createTeamsApp(wid, data) {
9383
+ return this.fetch(`w/${wid}/app-connections/teams/apps`, {
9384
+ method: "POST",
9385
+ body: JSON.stringify(data)
9386
+ });
9387
+ }
9388
+ async updateTeamsApp(wid, appId, data) {
9389
+ return this.fetch(`w/${wid}/app-connections/teams/apps/${appId}`, {
9390
+ method: "PUT",
9391
+ body: JSON.stringify(data)
9392
+ });
9393
+ }
9394
+ async deleteTeamsApp(wid, appId) {
9395
+ return this.fetch(`w/${wid}/app-connections/teams/apps/${appId}`, {
9396
+ method: "DELETE"
9397
+ });
9398
+ }
9399
+ async getTeamsConversations(wid, appId, options = {}) {
9400
+ const params = new URLSearchParams();
9401
+ if (options.page) params.append("page", options.page.toString());
9402
+ if (options.pageSize) params.append("pageSize", options.pageSize.toString());
9403
+ return this.fetch(
9404
+ `w/${wid}/app-connections/teams/apps/${appId}/conversations${params.toString() ? `?${params.toString()}` : ""}`
9405
+ );
9406
+ }
9407
+ async getTeamsInstallations(wid, appId, options = {}) {
9408
+ const params = new URLSearchParams();
9409
+ if (options.page) params.append("page", options.page.toString());
9410
+ if (options.pageSize) params.append("pageSize", options.pageSize.toString());
9411
+ return this.fetch(
9412
+ `w/${wid}/app-connections/teams/apps/${appId}/installations${params.toString() ? `?${params.toString()}` : ""}`
9413
+ );
9414
+ }
9415
+ async getTeamsAppAccounts(wid, appId, options = {}) {
9416
+ const params = new URLSearchParams();
9417
+ if (options.page) params.append("page", options.page.toString());
9418
+ if (options.pageSize) params.append("pageSize", options.pageSize.toString());
9419
+ return this.fetch(
9420
+ `w/${wid}/app-connections/teams/apps/${appId}/accounts${params.toString() ? `?${params.toString()}` : ""}`
9421
+ );
9422
+ }
9423
+ };
9054
9424
  function createApiModules(apiKey, baseUrl3, customFetch) {
9055
9425
  return {
9056
9426
  abilities: new AbilitiesApi(apiKey, baseUrl3, customFetch),
@@ -9073,6 +9443,7 @@ function createApiModules(apiKey, baseUrl3, customFetch) {
9073
9443
  dataTypes: new DataTypesApi(apiKey, baseUrl3, customFetch),
9074
9444
  discordBots: new DiscordBotsApi(apiKey, baseUrl3, customFetch),
9075
9445
  slackApps: new SlackAppsApi(apiKey, baseUrl3, customFetch),
9446
+ teamsApps: new TeamsAppsApi(apiKey, baseUrl3, customFetch),
9076
9447
  events: new EventsApi(apiKey, baseUrl3, customFetch),
9077
9448
  fhirConnections: new FhirConnectionsApi(apiKey, baseUrl3, customFetch),
9078
9449
  healthie: new HealthieApi(apiKey, baseUrl3, customFetch),
@@ -9102,6 +9473,7 @@ function createApiModules(apiKey, baseUrl3, customFetch) {
9102
9473
  salesforce: new SalesforceApi(apiKey, baseUrl3, customFetch),
9103
9474
  sites: new SitesApi(apiKey, baseUrl3, customFetch),
9104
9475
  subscriptions: new SubscriptionsApi(apiKey, baseUrl3, customFetch),
9476
+ supportRequests: new SupportRequestsApi(apiKey, baseUrl3, customFetch),
9105
9477
  supervisors: new SupervisorsApi(apiKey, baseUrl3, customFetch),
9106
9478
  tasks: new TasksApi(apiKey, baseUrl3, customFetch),
9107
9479
  templates: new TemplatesApi(apiKey, baseUrl3, customFetch),
@@ -9598,6 +9970,7 @@ function bindCommunicationsMethods(target, phoneNumbers, inboxes, notificationRu
9598
9970
  target.getInboxThreads = inboxes.getInboxThreads.bind(inboxes);
9599
9971
  target.getThreadEmails = inboxes.getThreadEmails.bind(inboxes);
9600
9972
  target.getChatEmails = inboxes.getChatEmails.bind(inboxes);
9973
+ target.replyToEmail = inboxes.replyToEmail.bind(inboxes);
9601
9974
  target.getNotificationRules = notificationRules.getNotificationRules.bind(notificationRules);
9602
9975
  target.createNotificationRule = notificationRules.createNotificationRule.bind(notificationRules);
9603
9976
  target.updateNotificationRule = notificationRules.updateNotificationRule.bind(notificationRules);
@@ -9689,13 +10062,10 @@ function bindAppsMethods(target, apps, builders, inquiries, oauth, oauthConnecti
9689
10062
  target.getOAuthAuthorizationUrl = oauthConnections.getAuthorizationUrl.bind(oauthConnections);
9690
10063
  target.disconnectOAuthProvider = oauthConnections.disconnect.bind(oauthConnections);
9691
10064
  }
9692
- function bindIntegrationsMethods(target, mondayIntegration, discordBots, slackApps, fhirConnections, healthie, salesforce, hubspot, appConnections, connectionSync, confluence) {
10065
+ function bindIntegrationsMethods(target, mondayIntegration, discordBots, slackApps, teamsApps, fhirConnections, healthie, salesforce, hubspot, appConnections, connectionSync, confluence) {
9693
10066
  target.getMondayBoards = mondayIntegration.getBoards.bind(mondayIntegration);
9694
10067
  target.getMondayBoardColumns = mondayIntegration.getBoardColumns.bind(mondayIntegration);
9695
10068
  target.getMondayBoardGroups = mondayIntegration.getBoardGroups.bind(mondayIntegration);
9696
- target.createMondayWebhook = mondayIntegration.createWebhook.bind(mondayIntegration);
9697
- target.deleteMondayWebhook = mondayIntegration.deleteWebhook.bind(mondayIntegration);
9698
- target.getMondayWebhook = mondayIntegration.getWebhook.bind(mondayIntegration);
9699
10069
  target.getMondayCurrentUserInfo = mondayIntegration.getCurrentUserInfo.bind(mondayIntegration);
9700
10070
  target.configureMondayConnection = mondayIntegration.configureMondayConnection.bind(mondayIntegration);
9701
10071
  target.getMondayConnectionStatus = mondayIntegration.getMondayConnectionStatus.bind(mondayIntegration);
@@ -9739,6 +10109,14 @@ function bindIntegrationsMethods(target, mondayIntegration, discordBots, slackAp
9739
10109
  target.getSlackThreads = slackApps.getSlackThreads.bind(slackApps);
9740
10110
  target.getSlackInstallations = slackApps.getSlackInstallations.bind(slackApps);
9741
10111
  target.getSlackAppAccounts = slackApps.getSlackAppAccounts.bind(slackApps);
10112
+ target.getTeamsApps = teamsApps.getTeamsApps.bind(teamsApps);
10113
+ target.getTeamsApp = teamsApps.getTeamsApp.bind(teamsApps);
10114
+ target.createTeamsApp = teamsApps.createTeamsApp.bind(teamsApps);
10115
+ target.updateTeamsApp = teamsApps.updateTeamsApp.bind(teamsApps);
10116
+ target.deleteTeamsApp = teamsApps.deleteTeamsApp.bind(teamsApps);
10117
+ target.getTeamsConversations = teamsApps.getTeamsConversations.bind(teamsApps);
10118
+ target.getTeamsInstallations = teamsApps.getTeamsInstallations.bind(teamsApps);
10119
+ target.getTeamsAppAccounts = teamsApps.getTeamsAppAccounts.bind(teamsApps);
9742
10120
  target.getFhirConnections = fhirConnections.getFhirConnections.bind(fhirConnections);
9743
10121
  target.getFhirConnection = fhirConnections.getFhirConnection.bind(fhirConnections);
9744
10122
  target.getFhirConnectionByUuid = fhirConnections.getFhirConnectionByUuid.bind(fhirConnections);
@@ -9779,6 +10157,10 @@ function bindIntegrationsMethods(target, mondayIntegration, discordBots, slackAp
9779
10157
  target.getHealthieReconciliationMatches = healthie.getHealthieReconciliationMatches.bind(healthie);
9780
10158
  target.linkMemberToHealthie = healthie.linkMemberToHealthie.bind(healthie);
9781
10159
  target.unlinkMemberFromHealthie = healthie.unlinkMemberFromHealthie.bind(healthie);
10160
+ target.listHealthieAppointmentTypes = healthie.listHealthieAppointmentTypes.bind(healthie);
10161
+ target.listHealthiePatients = healthie.listHealthiePatients.bind(healthie);
10162
+ target.getHealthieAvailableSlots = healthie.getHealthieAvailableSlots.bind(healthie);
10163
+ target.bookHealthieAppointment = healthie.bookHealthieAppointment.bind(healthie);
9782
10164
  target.configureConfluence = confluence.configureConfluence.bind(confluence);
9783
10165
  target.startConfluenceOAuth = confluence.startConfluenceOAuth.bind(confluence);
9784
10166
  target.getConfluenceStatus = confluence.getConfluenceStatus.bind(confluence);
@@ -9831,12 +10213,14 @@ function bindIntegrationsMethods(target, mondayIntegration, discordBots, slackAp
9831
10213
  target.getSyncRuns = connectionSync.getSyncRuns.bind(connectionSync);
9832
10214
  target.getSyncRunItems = connectionSync.getSyncRunItems.bind(connectionSync);
9833
10215
  target.getMemberSyncSummary = connectionSync.getMemberSyncSummary.bind(connectionSync);
10216
+ target.clearConnectionMemberExclusion = connectionSync.clearConnectionMemberExclusion.bind(connectionSync);
9834
10217
  target.listAvailableAppConnections = appConnections.listAvailableAppConnections.bind(appConnections);
9835
10218
  target.listAppConnections = appConnections.listAppConnections.bind(appConnections);
9836
10219
  target.enablePlatformApp = appConnections.enablePlatformApp.bind(appConnections);
9837
10220
  target.getPlatformApp = appConnections.getPlatformApp.bind(appConnections);
9838
10221
  target.updatePlatformApp = appConnections.updatePlatformApp.bind(appConnections);
9839
10222
  target.deletePlatformApp = appConnections.deletePlatformApp.bind(appConnections);
10223
+ target.listConnectionMemberFieldKeys = appConnections.listConnectionMemberFieldKeys.bind(appConnections);
9840
10224
  }
9841
10225
  function bindOperatorMethods(target, operatorGroups) {
9842
10226
  target.getOperatorGroups = operatorGroups.getOperatorGroups.bind(operatorGroups);
@@ -9866,6 +10250,10 @@ function bindOrgMethods(target, org) {
9866
10250
  target.getOrgDomainSite = org.getOrgDomainSite.bind(org);
9867
10251
  target.verifyOrgDomainSite = org.verifyOrgDomainSite.bind(org);
9868
10252
  target.disableOrgDomainSite = org.disableOrgDomainSite.bind(org);
10253
+ target.getBusinessProfile = org.getBusinessProfile.bind(org);
10254
+ target.updateBusinessProfile = org.updateBusinessProfile.bind(org);
10255
+ target.submitBusinessProfile = org.submitBusinessProfile.bind(org);
10256
+ target.cancelBusinessProfile = org.cancelBusinessProfile.bind(org);
9869
10257
  }
9870
10258
  function bindPronunciationsMethods(target, pronunciations) {
9871
10259
  target.getPronunciationEntries = pronunciations.getPronunciationEntries.bind(pronunciations);
@@ -9885,6 +10273,7 @@ function bindPronunciationsMethods(target, pronunciations) {
9885
10273
  function bindJourneysMethods(target, journeys) {
9886
10274
  target.getJourneys = journeys.getJourneys.bind(journeys);
9887
10275
  target.getJourney = journeys.getJourney.bind(journeys);
10276
+ target.getJourneyHealth = journeys.getJourneyHealth.bind(journeys);
9888
10277
  target.createJourney = journeys.createJourney.bind(journeys);
9889
10278
  target.updateJourney = journeys.updateJourney.bind(journeys);
9890
10279
  target.archiveJourney = journeys.archiveJourney.bind(journeys);
@@ -9903,6 +10292,7 @@ function bindJourneysMethods(target, journeys) {
9903
10292
  target.reenrollMember = journeys.reenrollMember.bind(journeys);
9904
10293
  target.deleteEnrollment = journeys.deleteEnrollment.bind(journeys);
9905
10294
  target.getMemberJourneys = journeys.getMemberJourneys.bind(journeys);
10295
+ target.testRunJourney = journeys.testRunJourney.bind(journeys);
9906
10296
  target.getJourneyNotes = journeys.getJourneyNotes.bind(journeys);
9907
10297
  target.createJourneyNote = journeys.createJourneyNote.bind(journeys);
9908
10298
  target.updateJourneyNote = journeys.updateJourneyNote.bind(journeys);
@@ -9942,6 +10332,7 @@ function bindCustomersMethods(target, customers) {
9942
10332
  target.attachMyCustomerPaymentMethod = customers.attachMyCustomerPaymentMethod.bind(customers);
9943
10333
  target.detachMyCustomerPaymentMethod = customers.detachMyCustomerPaymentMethod.bind(customers);
9944
10334
  target.setDefaultMyCustomerPaymentMethod = customers.setDefaultMyCustomerPaymentMethod.bind(customers);
10335
+ target.getMyCustomerCreditGrants = customers.getMyCustomerCreditGrants.bind(customers);
9945
10336
  }
9946
10337
  function bindResellersMethods(target, resellers) {
9947
10338
  target.getMyResellers = resellers.getMyResellers.bind(resellers);
@@ -9954,6 +10345,21 @@ function bindResellersMethods(target, resellers) {
9954
10345
  function bindPromptsMethods(target, prompts) {
9955
10346
  target.inspectPrompt = prompts.inspectPrompt.bind(prompts);
9956
10347
  }
10348
+ function bindSupportRequestMethods(target, supportRequests) {
10349
+ target.listSupportRequests = supportRequests.listSupportRequests.bind(supportRequests);
10350
+ target.getSupportRequest = supportRequests.getSupportRequest.bind(supportRequests);
10351
+ target.createSupportRequest = supportRequests.createSupportRequest.bind(supportRequests);
10352
+ target.commentOnSupportRequest = supportRequests.commentOnSupportRequest.bind(supportRequests);
10353
+ target.listOrgSupportRequests = supportRequests.listOrgSupportRequests.bind(supportRequests);
10354
+ target.getOrgSupportRequest = supportRequests.getOrgSupportRequest.bind(supportRequests);
10355
+ target.createOrgSupportRequest = supportRequests.createOrgSupportRequest.bind(supportRequests);
10356
+ target.commentOnOrgSupportRequest = supportRequests.commentOnOrgSupportRequest.bind(supportRequests);
10357
+ target.listWorkspaceSupportRequests = supportRequests.listWorkspaceSupportRequests.bind(supportRequests);
10358
+ target.getWorkspaceSupportRequest = supportRequests.getWorkspaceSupportRequest.bind(supportRequests);
10359
+ target.createWorkspaceSupportRequest = supportRequests.createWorkspaceSupportRequest.bind(supportRequests);
10360
+ target.commentOnWorkspaceSupportRequest = supportRequests.commentOnWorkspaceSupportRequest.bind(supportRequests);
10361
+ target.closeWorkspaceSupportRequest = supportRequests.closeWorkspaceSupportRequest.bind(supportRequests);
10362
+ }
9957
10363
  var GravityRailClient = class {
9958
10364
  // WorkspaceInvitations is exposed publicly for backward compatibility
9959
10365
  workspaceInvitations;
@@ -10127,6 +10533,7 @@ var GravityRailClient = class {
10127
10533
  // Journeys API
10128
10534
  getJourneys;
10129
10535
  getJourney;
10536
+ getJourneyHealth;
10130
10537
  createJourney;
10131
10538
  updateJourney;
10132
10539
  archiveJourney;
@@ -10145,6 +10552,7 @@ var GravityRailClient = class {
10145
10552
  reenrollMember;
10146
10553
  deleteEnrollment;
10147
10554
  getMemberJourneys;
10555
+ testRunJourney;
10148
10556
  getJourneyNotes;
10149
10557
  createJourneyNote;
10150
10558
  updateJourneyNote;
@@ -10234,6 +10642,10 @@ var GravityRailClient = class {
10234
10642
  getOrgDomainSite;
10235
10643
  verifyOrgDomainSite;
10236
10644
  disableOrgDomainSite;
10645
+ getBusinessProfile;
10646
+ updateBusinessProfile;
10647
+ submitBusinessProfile;
10648
+ cancelBusinessProfile;
10237
10649
  getVapidPublicKey;
10238
10650
  registerPushSubscription;
10239
10651
  unregisterPushSubscription;
@@ -10507,6 +10919,7 @@ var GravityRailClient = class {
10507
10919
  getInboxThreads;
10508
10920
  getThreadEmails;
10509
10921
  getChatEmails;
10922
+ replyToEmail;
10510
10923
  getNotificationRules;
10511
10924
  createNotificationRule;
10512
10925
  updateNotificationRule;
@@ -10598,9 +11011,6 @@ var GravityRailClient = class {
10598
11011
  getMondayBoards;
10599
11012
  getMondayBoardColumns;
10600
11013
  getMondayBoardGroups;
10601
- createMondayWebhook;
10602
- deleteMondayWebhook;
10603
- getMondayWebhook;
10604
11014
  getMondayCurrentUserInfo;
10605
11015
  // Monday.com Connection API
10606
11016
  configureMondayConnection;
@@ -10647,6 +11057,15 @@ var GravityRailClient = class {
10647
11057
  getSlackThreads;
10648
11058
  getSlackInstallations;
10649
11059
  getSlackAppAccounts;
11060
+ // Teams Apps API
11061
+ getTeamsApps;
11062
+ getTeamsApp;
11063
+ createTeamsApp;
11064
+ updateTeamsApp;
11065
+ deleteTeamsApp;
11066
+ getTeamsConversations;
11067
+ getTeamsInstallations;
11068
+ getTeamsAppAccounts;
10650
11069
  // FHIR Connections API
10651
11070
  getFhirConnections;
10652
11071
  getFhirConnection;
@@ -10689,6 +11108,10 @@ var GravityRailClient = class {
10689
11108
  getHealthieReconciliationMatches;
10690
11109
  linkMemberToHealthie;
10691
11110
  unlinkMemberFromHealthie;
11111
+ listHealthieAppointmentTypes;
11112
+ listHealthiePatients;
11113
+ getHealthieAvailableSlots;
11114
+ bookHealthieAppointment;
10692
11115
  // Confluence API
10693
11116
  configureConfluence;
10694
11117
  startConfluenceOAuth;
@@ -10745,6 +11168,7 @@ var GravityRailClient = class {
10745
11168
  getSyncRuns;
10746
11169
  getSyncRunItems;
10747
11170
  getMemberSyncSummary;
11171
+ clearConnectionMemberExclusion;
10748
11172
  // App Connections API
10749
11173
  listAvailableAppConnections;
10750
11174
  listAppConnections;
@@ -10752,6 +11176,7 @@ var GravityRailClient = class {
10752
11176
  getPlatformApp;
10753
11177
  updatePlatformApp;
10754
11178
  deletePlatformApp;
11179
+ listConnectionMemberFieldKeys;
10755
11180
  // Pronunciations API
10756
11181
  getPronunciationEntries;
10757
11182
  createPronunciationEntry;
@@ -10778,6 +11203,7 @@ var GravityRailClient = class {
10778
11203
  attachMyCustomerPaymentMethod;
10779
11204
  detachMyCustomerPaymentMethod;
10780
11205
  setDefaultMyCustomerPaymentMethod;
11206
+ getMyCustomerCreditGrants;
10781
11207
  // Resellers API (self-service reseller portal)
10782
11208
  getMyResellers;
10783
11209
  getMyReseller;
@@ -10785,6 +11211,20 @@ var GravityRailClient = class {
10785
11211
  getMyResellerProducts;
10786
11212
  getMyResellerSubscriptions;
10787
11213
  updateMyReseller;
11214
+ // Support Requests API
11215
+ listSupportRequests;
11216
+ getSupportRequest;
11217
+ createSupportRequest;
11218
+ commentOnSupportRequest;
11219
+ listOrgSupportRequests;
11220
+ getOrgSupportRequest;
11221
+ createOrgSupportRequest;
11222
+ commentOnOrgSupportRequest;
11223
+ listWorkspaceSupportRequests;
11224
+ getWorkspaceSupportRequest;
11225
+ createWorkspaceSupportRequest;
11226
+ commentOnWorkspaceSupportRequest;
11227
+ closeWorkspaceSupportRequest;
10788
11228
  constructor(apiKey, baseUrl3, customFetch) {
10789
11229
  const apis = createApiModules(apiKey, baseUrl3, customFetch);
10790
11230
  this.apis = apis;
@@ -10834,6 +11274,7 @@ var GravityRailClient = class {
10834
11274
  apis.mondayIntegration,
10835
11275
  apis.discordBots,
10836
11276
  apis.slackApps,
11277
+ apis.teamsApps,
10837
11278
  apis.fhirConnections,
10838
11279
  apis.healthie,
10839
11280
  apis.salesforce,
@@ -10845,6 +11286,7 @@ var GravityRailClient = class {
10845
11286
  bindPronunciationsMethods(this, apis.pronunciations);
10846
11287
  bindCustomersMethods(this, apis.customers);
10847
11288
  bindResellersMethods(this, apis.resellers);
11289
+ bindSupportRequestMethods(this, apis.supportRequests);
10848
11290
  }
10849
11291
  /**
10850
11292
  * Set the handler for enhanced authentication requirements (RFC 9470 Step-Up Auth).
@@ -10872,6 +11314,24 @@ var GravityRailClient = class {
10872
11314
  }
10873
11315
  });
10874
11316
  }
11317
+ /**
11318
+ * Set the org token for cross-domain / non-browser clients (e.g. CLI).
11319
+ * When set, all API requests include the X-Org-Token header so the backend
11320
+ * accepts the request without requiring a browser cookie.
11321
+ *
11322
+ * `orgUuid` is the org that issued the token. Pass it so the SDK can
11323
+ * detect a stale token (e.g. switching orgs mid-session) and re-fire the
11324
+ * org-auth handler instead of silently 401-ing.
11325
+ *
11326
+ * Propagates to all API modules.
11327
+ */
11328
+ setOrgToken(token, orgUuid) {
11329
+ Object.values(this.apis).forEach((api) => {
11330
+ if (typeof api.setOrgToken === "function") {
11331
+ api.setOrgToken(token, orgUuid);
11332
+ }
11333
+ });
11334
+ }
10875
11335
  /**
10876
11336
  * Update the API key across all modules.
10877
11337
  * Used after successful re-authentication.
@@ -10926,14 +11386,74 @@ var BUILTIN_ASSISTANT_CHAT_TYPES = /* @__PURE__ */ new Set([
10926
11386
  ]);
10927
11387
 
10928
11388
  // ../client/dist/index.mjs
11389
+ function supportRequestParams2(params) {
11390
+ const searchParams = new URLSearchParams();
11391
+ if (params?.page) searchParams.append("page", params.page.toString());
11392
+ if (params?.pageSize) searchParams.append("pageSize", params.pageSize.toString());
11393
+ if (params?.status) searchParams.append("status", params.status);
11394
+ if (params?.supportRequestType) {
11395
+ searchParams.append("supportRequestType", params.supportRequestType);
11396
+ }
11397
+ if (params?.severity) searchParams.append("severity", params.severity);
11398
+ if (params?.source) searchParams.append("source", params.source);
11399
+ if (params?.organizationId !== void 0) {
11400
+ searchParams.append("organizationId", params.organizationId.toString());
11401
+ }
11402
+ if (params?.workspaceId !== void 0) {
11403
+ searchParams.append("workspaceId", params.workspaceId.toString());
11404
+ }
11405
+ if (params?.linearLinked !== void 0) {
11406
+ searchParams.append("linearLinked", params.linearLinked.toString());
11407
+ }
11408
+ const query = searchParams.toString();
11409
+ return query ? `?${query}` : "";
11410
+ }
10929
11411
  var AdminApi = class extends BaseApiClient {
10930
- // Admin Accounts API
10931
- async getAccounts(options) {
10932
- const params = new URLSearchParams();
10933
- if (options.search) params.append("search", options.search);
10934
- if (options.createdAfter) params.append("created_after", options.createdAfter);
10935
- if (options.createdBefore) params.append("created_before", options.createdBefore);
10936
- if (options.sortBy) params.append("sortBy", options.sortBy);
11412
+ // Support Requests API
11413
+ async listSupportRequestsAsAdmin(params) {
11414
+ return this.fetch(
11415
+ `admin/support-requests${supportRequestParams2(params)}`
11416
+ );
11417
+ }
11418
+ async getSupportRequestAsAdmin(uuid) {
11419
+ return this.fetch(`admin/support-requests/${uuid}`);
11420
+ }
11421
+ async commentOnSupportRequestAsAdmin(uuid, data) {
11422
+ return this.fetch(`admin/support-requests/${uuid}/comments`, {
11423
+ method: "POST",
11424
+ body: JSON.stringify(data)
11425
+ });
11426
+ }
11427
+ async noteOnSupportRequestAsAdmin(uuid, data) {
11428
+ return this.fetch(`admin/support-requests/${uuid}/notes`, {
11429
+ method: "POST",
11430
+ body: JSON.stringify(data)
11431
+ });
11432
+ }
11433
+ async updateSupportRequestStatusAsAdmin(uuid, data) {
11434
+ return this.fetch(`admin/support-requests/${uuid}/status`, {
11435
+ method: "POST",
11436
+ body: JSON.stringify(data)
11437
+ });
11438
+ }
11439
+ async updateSupportRequestAttributesAsAdmin(uuid, data) {
11440
+ return this.fetch(`admin/support-requests/${uuid}/attributes`, {
11441
+ method: "POST",
11442
+ body: JSON.stringify(data)
11443
+ });
11444
+ }
11445
+ async createSupportRequestLinearIssueAsAdmin(uuid) {
11446
+ return this.fetch(`admin/support-requests/${uuid}/linear-issue`, {
11447
+ method: "POST"
11448
+ });
11449
+ }
11450
+ // Admin Accounts API
11451
+ async getAccounts(options) {
11452
+ const params = new URLSearchParams();
11453
+ if (options.search) params.append("search", options.search);
11454
+ if (options.createdAfter) params.append("created_after", options.createdAfter);
11455
+ if (options.createdBefore) params.append("created_before", options.createdBefore);
11456
+ if (options.sortBy) params.append("sortBy", options.sortBy);
10937
11457
  if (options.sortOrder) params.append("sortOrder", options.sortOrder);
10938
11458
  if (options.page) params.append("page", options.page.toString());
10939
11459
  if (options.pageSize) params.append("pageSize", options.pageSize.toString());
@@ -11065,11 +11585,11 @@ var AdminApi = class extends BaseApiClient {
11065
11585
  return this.fetch(`o/${idOrUuid}`);
11066
11586
  }
11067
11587
  /**
11068
- * Get organization by numeric ID via admin endpoint.
11588
+ * Get organization by numeric ID or UUID via admin endpoint.
11069
11589
  * Does NOT require organization membership — superuser-only.
11070
11590
  */
11071
- async getOrganizationAsAdmin(id) {
11072
- return this.fetch(`admin/organizations/${id}`);
11591
+ async getOrganizationAsAdmin(idOrUuid) {
11592
+ return this.fetch(`admin/organizations/${idOrUuid}`);
11073
11593
  }
11074
11594
  async getOrganizationMembersAsAdmin(organizationId, options) {
11075
11595
  const params = new URLSearchParams();
@@ -11246,6 +11766,26 @@ var AdminApi = class extends BaseApiClient {
11246
11766
  body: JSON.stringify(request || {})
11247
11767
  });
11248
11768
  }
11769
+ /**
11770
+ * Switch a workspace's plan product on its active SubscriptionItem.
11771
+ *
11772
+ * Superuser only. Re-syncs ``workspace.features`` from the new product
11773
+ * and emits a ``WORKSPACE_PRODUCT_CHANGED`` audit event identifying the
11774
+ * actor, target workspace, prior and new product, and feature diff.
11775
+ *
11776
+ * Stripe is not touched here; price-id changes belong to the dedicated
11777
+ * Stripe sync surface (``syncProductToStripe``).
11778
+ */
11779
+ async changeWorkspaceProduct(workspaceUuid, productId) {
11780
+ const body = { productId };
11781
+ return this.fetch(
11782
+ `admin/workspaces/${workspaceUuid}/product`,
11783
+ {
11784
+ method: "POST",
11785
+ body: JSON.stringify(body)
11786
+ }
11787
+ );
11788
+ }
11249
11789
  // ===== Workflow Access Validation =====
11250
11790
  async validateWorkflowAccessAsAdmin(workspaceUuid) {
11251
11791
  const params = new URLSearchParams();
@@ -11278,6 +11818,11 @@ var AdminApi = class extends BaseApiClient {
11278
11818
  body: JSON.stringify(data)
11279
11819
  });
11280
11820
  }
11821
+ async unarchiveAdminWorkspaceMember(wid) {
11822
+ return this.fetch(`admin/workspaces/${wid}/me/unarchive`, {
11823
+ method: "POST"
11824
+ });
11825
+ }
11281
11826
  async getAdminWorkspaceMemberRoles(wid) {
11282
11827
  return this.fetch(`admin/workspaces/${wid}/member-roles`);
11283
11828
  }
@@ -11289,8 +11834,8 @@ var AdminApi = class extends BaseApiClient {
11289
11834
  `admin/phone-numbers/workspace/${workspaceId}/unmapped`
11290
11835
  );
11291
11836
  }
11292
- async getWorkspacePhoneNumbersAsAdmin(workspaceId) {
11293
- return this.fetch(`admin/workspace/${workspaceId}/phone-numbers`);
11837
+ async getWorkspacePhoneNumbersAsAdmin(workspaceRef) {
11838
+ return this.fetch(`admin/workspaces/${workspaceRef}/phone-numbers`);
11294
11839
  }
11295
11840
  // Phone Numbers API (Provider phone numbers from Twilio, AWS, etc.)
11296
11841
  async getProviderPhoneNumbers(options = {}) {
@@ -11399,6 +11944,11 @@ var AdminApi = class extends BaseApiClient {
11399
11944
  method: "DELETE"
11400
11945
  });
11401
11946
  }
11947
+ async getWorkspaceInboxesAsAdmin(workspaceUuid) {
11948
+ return this.fetch(
11949
+ `admin/workspaces/${workspaceUuid}/inboxes`
11950
+ );
11951
+ }
11402
11952
  // Admin Inbox Mappings API
11403
11953
  async getInboxMappings(options = {}) {
11404
11954
  const params = new URLSearchParams();
@@ -11443,21 +11993,30 @@ var AdminApi = class extends BaseApiClient {
11443
11993
  })
11444
11994
  });
11445
11995
  }
11446
- // Admin Themes API
11447
- async listAllThemes() {
11448
- return this.fetch("admin/themes/list");
11449
- }
11450
- // One-off Redis cadence-key migration (periodiq_* → routine_*). See
11451
- // lib/routes/admin/admin_routine_cadence_api.py for context.
11452
- async migrateRoutineCadenceKeys(options) {
11453
- return this.fetch("admin/redis/routine-cadence/migrate", {
11996
+ /**
11997
+ * Resolve a Langfuse trace UI URL from a trace ID, chat ID, or message ID.
11998
+ *
11999
+ * URL-only: never fetches Langfuse payloads, Message content, or
12000
+ * tool arguments. Exactly one of ``traceId``, ``chatId``, or
12001
+ * ``messageId`` must be set; chat/message forms require a
12002
+ * workspaceUuid. See
12003
+ * docs/development/observability/llm-call-investigation.md.
12004
+ */
12005
+ async getTraceUrl(options) {
12006
+ return this.fetch("admin/trace/url", {
11454
12007
  method: "POST",
11455
12008
  body: JSON.stringify({
11456
- dryRun: options.dryRun ?? true,
11457
- deleteLegacy: options.deleteLegacy ?? false
12009
+ trace_id: options.traceId,
12010
+ chat_id: options.chatId,
12011
+ message_id: options.messageId,
12012
+ workspace_uuid: options.workspaceUuid
11458
12013
  })
11459
12014
  });
11460
12015
  }
12016
+ // Admin Themes API
12017
+ async listAllThemes() {
12018
+ return this.fetch("admin/themes/list");
12019
+ }
11461
12020
  // Missing Memberships API
11462
12021
  async getMissingMemberships(workspaceId) {
11463
12022
  return this.fetch(
@@ -12030,6 +12589,13 @@ function appendTemporalWorkspaceParams(params, options) {
12030
12589
  push(options.workspaceUuid);
12031
12590
  }
12032
12591
  function bindAdminMethods(target, admin) {
12592
+ target.listSupportRequestsAsAdmin = admin.listSupportRequestsAsAdmin.bind(admin);
12593
+ target.getSupportRequestAsAdmin = admin.getSupportRequestAsAdmin.bind(admin);
12594
+ target.commentOnSupportRequestAsAdmin = admin.commentOnSupportRequestAsAdmin.bind(admin);
12595
+ target.noteOnSupportRequestAsAdmin = admin.noteOnSupportRequestAsAdmin.bind(admin);
12596
+ target.updateSupportRequestStatusAsAdmin = admin.updateSupportRequestStatusAsAdmin.bind(admin);
12597
+ target.updateSupportRequestAttributesAsAdmin = admin.updateSupportRequestAttributesAsAdmin.bind(admin);
12598
+ target.createSupportRequestLinearIssueAsAdmin = admin.createSupportRequestLinearIssueAsAdmin.bind(admin);
12033
12599
  target.getAccounts = admin.getAccounts.bind(admin);
12034
12600
  target.getAccountDetails = admin.getAccountDetails.bind(admin);
12035
12601
  target.getAccountByUuid = admin.getAccountByUuid.bind(admin);
@@ -12078,11 +12644,13 @@ function bindAdminMethods(target, admin) {
12078
12644
  target.disableMaintenanceMode = admin.disableMaintenanceMode.bind(admin);
12079
12645
  target.getWorkspaceHealth = admin.getWorkspaceHealth.bind(admin);
12080
12646
  target.provisionPlanFeatures = admin.provisionPlanFeatures.bind(admin);
12647
+ target.changeWorkspaceProduct = admin.changeWorkspaceProduct.bind(admin);
12081
12648
  target.validateWorkflowAccessAsAdmin = admin.validateWorkflowAccessAsAdmin.bind(admin);
12082
12649
  target.mergeMembers = admin.mergeMembers.bind(admin);
12083
12650
  target.getAdminWorkspaceMember = admin.getAdminWorkspaceMember.bind(admin);
12084
12651
  target.createAdminWorkspaceMember = admin.createAdminWorkspaceMember.bind(admin);
12085
12652
  target.updateAdminWorkspaceMember = admin.updateAdminWorkspaceMember.bind(admin);
12653
+ target.unarchiveAdminWorkspaceMember = admin.unarchiveAdminWorkspaceMember.bind(admin);
12086
12654
  target.getAdminWorkspaceMemberRoles = admin.getAdminWorkspaceMemberRoles.bind(admin);
12087
12655
  target.getMissingMemberships = admin.getMissingMemberships.bind(admin);
12088
12656
  target.linkMissingMembership = admin.linkMissingMembership.bind(admin);
@@ -12113,8 +12681,8 @@ function bindAdminMethods(target, admin) {
12113
12681
  target.deleteAdminInboxMapping = admin.deleteAdminInboxMapping.bind(admin);
12114
12682
  target.generateChatSummaries = admin.generateChatSummaries.bind(admin);
12115
12683
  target.executeQuery = admin.executeQuery.bind(admin);
12684
+ target.getTraceUrl = admin.getTraceUrl.bind(admin);
12116
12685
  target.listAllThemes = admin.listAllThemes.bind(admin);
12117
- target.migrateRoutineCadenceKeys = admin.migrateRoutineCadenceKeys.bind(admin);
12118
12686
  target.startBulkTOSAcceptance = admin.startBulkTOSAcceptance.bind(admin);
12119
12687
  target.startTokenUsageBackfill = admin.startTokenUsageBackfill.bind(admin);
12120
12688
  target.updateChatMessage = admin.updateChatMessage.bind(admin);
@@ -12174,6 +12742,7 @@ function bindAdminMethods(target, admin) {
12174
12742
  target.getVoiceMetrics = admin.getVoiceMetrics.bind(admin);
12175
12743
  target.getHealthMetrics = admin.getHealthMetrics.bind(admin);
12176
12744
  target.getHealthDetail = admin.getHealthDetail.bind(admin);
12745
+ target.getWorkspaceInboxesAsAdmin = admin.getWorkspaceInboxesAsAdmin.bind(admin);
12177
12746
  target.listWorkspaceChats = admin.listWorkspaceChats.bind(admin);
12178
12747
  target.getWorkspaceChat = admin.getWorkspaceChat.bind(admin);
12179
12748
  target.rateWorkspaceChatMessage = admin.rateWorkspaceChatMessage.bind(admin);
@@ -12192,6 +12761,13 @@ function bindAdminMethods(target, admin) {
12192
12761
  }
12193
12762
  var ApiClient = class extends GravityRailClient {
12194
12763
  // Admin API
12764
+ listSupportRequestsAsAdmin;
12765
+ getSupportRequestAsAdmin;
12766
+ commentOnSupportRequestAsAdmin;
12767
+ noteOnSupportRequestAsAdmin;
12768
+ updateSupportRequestStatusAsAdmin;
12769
+ updateSupportRequestAttributesAsAdmin;
12770
+ createSupportRequestLinearIssueAsAdmin;
12195
12771
  getAccounts;
12196
12772
  getAccountDetails;
12197
12773
  getAccountByUuid;
@@ -12240,11 +12816,13 @@ var ApiClient = class extends GravityRailClient {
12240
12816
  disableMaintenanceMode;
12241
12817
  getWorkspaceHealth;
12242
12818
  provisionPlanFeatures;
12819
+ changeWorkspaceProduct;
12243
12820
  validateWorkflowAccessAsAdmin;
12244
12821
  mergeMembers;
12245
12822
  getAdminWorkspaceMember;
12246
12823
  createAdminWorkspaceMember;
12247
12824
  updateAdminWorkspaceMember;
12825
+ unarchiveAdminWorkspaceMember;
12248
12826
  getAdminWorkspaceMemberRoles;
12249
12827
  getMissingMemberships;
12250
12828
  linkMissingMembership;
@@ -12275,8 +12853,8 @@ var ApiClient = class extends GravityRailClient {
12275
12853
  deleteAdminInboxMapping;
12276
12854
  generateChatSummaries;
12277
12855
  executeQuery;
12856
+ getTraceUrl;
12278
12857
  listAllThemes;
12279
- migrateRoutineCadenceKeys;
12280
12858
  startBulkTOSAcceptance;
12281
12859
  startTokenUsageBackfill;
12282
12860
  updateChatMessage;
@@ -12330,6 +12908,7 @@ var ApiClient = class extends GravityRailClient {
12330
12908
  getVoiceMetrics;
12331
12909
  getHealthMetrics;
12332
12910
  getHealthDetail;
12911
+ getWorkspaceInboxesAsAdmin;
12333
12912
  listWorkspaceChats;
12334
12913
  getWorkspaceChat;
12335
12914
  rateWorkspaceChatMessage;
@@ -12366,12 +12945,92 @@ var ApiClient = class extends GravityRailClient {
12366
12945
  this.adminApi.setActingMember(memberUuid);
12367
12946
  }
12368
12947
  }
12948
+ // setOrgToken is intentionally NOT overridden here. Admin routes
12949
+ // (/api/v2/admin/*) are protected by the bearer token's superuser claim and
12950
+ // ignore X-Org-Token entirely, so propagating an org token to adminApi is
12951
+ // dead code that would only obscure auth flow if admin route logic changes.
12952
+ };
12953
+ var ENVIRONMENTS = {
12954
+ dev: {
12955
+ apiUrl: "https://api.gravityrail.test:5054",
12956
+ frontendUrl: "https://app.gravityrail.test:3000"
12957
+ },
12958
+ prod: {
12959
+ apiUrl: "https://api.gravityrail.com",
12960
+ frontendUrl: "https://app.gravityrail.com"
12961
+ },
12962
+ staging: {
12963
+ apiUrl: "https://api.gr-staging.com",
12964
+ frontendUrl: "https://app.gr-staging.com"
12965
+ }
12369
12966
  };
12370
-
12371
- // src/cli-utils/config.ts
12372
12967
  var CALLBACK_PORT = 31337;
12373
12968
  var CALLBACK_PATH = "/oauth/callback";
12374
12969
  var REDIRECT_URI = `http://localhost:${CALLBACK_PORT}${CALLBACK_PATH}`;
12970
+ function detectWorktreePorts() {
12971
+ let dir = resolve(process.cwd());
12972
+ let overridePath;
12973
+ while (true) {
12974
+ const candidate = join(dir, "docker-compose.override.yml");
12975
+ if (existsSync(candidate)) {
12976
+ overridePath = candidate;
12977
+ break;
12978
+ }
12979
+ const parent = dirname(dir);
12980
+ if (parent === dir) break;
12981
+ dir = parent;
12982
+ }
12983
+ if (!overridePath) return {};
12984
+ let content;
12985
+ try {
12986
+ content = readFileSync(overridePath, "utf-8");
12987
+ } catch {
12988
+ return {};
12989
+ }
12990
+ if (!content.includes("worktree-setup.sh")) return {};
12991
+ let apiPort;
12992
+ let frontendPort;
12993
+ for (const match of content.matchAll(/-\s*'(\d+):(\d+)'/g)) {
12994
+ const host = parseInt(match[1], 10);
12995
+ const container = parseInt(match[2], 10);
12996
+ if (container === 5050) apiPort = host;
12997
+ if (container === 3e3) frontendPort = host;
12998
+ }
12999
+ return { apiPort, frontendPort };
13000
+ }
13001
+ function getEnvironmentConfig(env) {
13002
+ if (env.startsWith("dev-cloud:")) {
13003
+ const namespace = env.slice("dev-cloud:".length);
13004
+ if (!namespace) {
13005
+ throw new Error("dev-cloud environment requires a namespace: --env dev-cloud:NAMESPACE");
13006
+ }
13007
+ return {
13008
+ apiUrl: `https://${namespace}-api.gravityrail-dev.com`,
13009
+ frontendUrl: `https://${namespace}-app.gravityrail-dev.com`
13010
+ };
13011
+ }
13012
+ const config = ENVIRONMENTS[env];
13013
+ if (!config) {
13014
+ throw new Error(
13015
+ `Invalid environment: ${env}. Use 'dev', 'staging', 'prod', or 'dev-cloud:NAMESPACE'.`
13016
+ );
13017
+ }
13018
+ const apiUrl = process.env.GRAVITY_RAIL_API_URL || config.apiUrl;
13019
+ const frontendUrl = process.env.GRAVITY_RAIL_FRONTEND_URL || config.frontendUrl;
13020
+ if (apiUrl !== config.apiUrl || frontendUrl !== config.frontendUrl) {
13021
+ return { apiUrl, frontendUrl };
13022
+ }
13023
+ if (env === "dev") {
13024
+ const ports = detectWorktreePorts();
13025
+ if (ports.apiPort || ports.frontendPort) {
13026
+ return {
13027
+ apiUrl: ports.apiPort ? `https://api.gravityrail.test:${ports.apiPort}` : config.apiUrl,
13028
+ frontendUrl: ports.frontendPort ? `https://app.gravityrail.test:${ports.frontendPort}` : config.frontendUrl
13029
+ };
13030
+ }
13031
+ }
13032
+ return config;
13033
+ }
12375
13034
  var CredentialsManager = class {
12376
13035
  cacheDir;
12377
13036
  apiUrl;
@@ -12501,7 +13160,7 @@ function openBrowser(url) {
12501
13160
  });
12502
13161
  }
12503
13162
  function startCallbackServer() {
12504
- return new Promise((resolve, reject) => {
13163
+ return new Promise((resolve2, reject) => {
12505
13164
  let authCode = null;
12506
13165
  let error = null;
12507
13166
  let receivedState = null;
@@ -12543,7 +13202,7 @@ function startCallbackServer() {
12543
13202
  </html>
12544
13203
  `);
12545
13204
  server.close();
12546
- resolve({ code: authCode, state: receivedState });
13205
+ resolve2({ code: authCode, state: receivedState });
12547
13206
  } else {
12548
13207
  res.writeHead(400);
12549
13208
  res.end("Missing code parameter");
@@ -12735,7 +13394,7 @@ async function selectFromList(items, options = {}) {
12735
13394
  return { item: null, isNew: false };
12736
13395
  }
12737
13396
  const displayItems = allowNew ? [NEW_ITEM_MARKER, ...items] : items;
12738
- return new Promise((resolve) => {
13397
+ return new Promise((resolve2) => {
12739
13398
  let selectedIndex = allowNew ? 1 : 0;
12740
13399
  let filterText = "";
12741
13400
  const getFilteredItems = () => {
@@ -12818,16 +13477,16 @@ async function selectFromList(items, options = {}) {
12818
13477
  if (filtered.length > 0 && selectedIndex < filtered.length) {
12819
13478
  const selected = filtered[selectedIndex];
12820
13479
  if (selected === NEW_ITEM_MARKER) {
12821
- resolve({ item: null, isNew: true });
13480
+ resolve2({ item: null, isNew: true });
12822
13481
  } else {
12823
- resolve({ item: selected, isNew: false });
13482
+ resolve2({ item: selected, isNew: false });
12824
13483
  }
12825
13484
  } else {
12826
- resolve({ item: null, isNew: false });
13485
+ resolve2({ item: null, isNew: false });
12827
13486
  }
12828
13487
  } else if (key.name === "escape" || key.ctrl && key.name === "c") {
12829
13488
  cleanup();
12830
- resolve({ item: null, isNew: false });
13489
+ resolve2({ item: null, isNew: false });
12831
13490
  } else if (key.name === "backspace") {
12832
13491
  filterText = filterText.slice(0, -1);
12833
13492
  selectedIndex = allowNew ? 0 : 0;
@@ -12937,29 +13596,82 @@ function clearScreen() {
12937
13596
  // src/cli-utils/agui.ts
12938
13597
  var AGUIClient = class {
12939
13598
  endpointUrl;
13599
+ baseUrl;
13600
+ workspaceUuid;
13601
+ chatId;
12940
13602
  accessToken;
12941
13603
  debug;
12942
13604
  model;
13605
+ appContext;
12943
13606
  constructor(options) {
13607
+ this.baseUrl = options.baseUrl;
13608
+ this.workspaceUuid = options.workspaceUuid ?? "";
13609
+ this.chatId = options.chatId ?? 0;
13610
+ if (!options.endpointUrl && (!options.workspaceUuid || options.chatId === void 0)) {
13611
+ throw new Error("AGUIClient requires workspaceUuid and chatId, or endpointUrl");
13612
+ }
12944
13613
  this.endpointUrl = options.endpointUrl ?? `${options.baseUrl}/api/v2/w/${options.workspaceUuid}/web-chat/${options.chatId}/chat/agui`;
12945
13614
  this.accessToken = options.accessToken;
12946
13615
  this.debug = options.debug ?? false;
12947
13616
  this.model = "model" in options ? options.model : "manager";
13617
+ this.appContext = options.appContext;
13618
+ }
13619
+ inferenceStatusUrl() {
13620
+ if (!this.workspaceUuid || this.chatId <= 0) return null;
13621
+ return `${this.baseUrl}/api/v2/w/${this.workspaceUuid}/chats/${this.chatId}/inference/status`;
13622
+ }
13623
+ async waitForInferenceInactive(maxWaitMs = 6e4) {
13624
+ const url = this.inferenceStatusUrl();
13625
+ if (!url) return false;
13626
+ const deadline = Date.now() + maxWaitMs;
13627
+ while (Date.now() < deadline) {
13628
+ try {
13629
+ const res = await fetch(url, {
13630
+ headers: { Authorization: `Bearer ${this.accessToken}` }
13631
+ });
13632
+ if (res.ok) {
13633
+ const body = await res.json();
13634
+ if (!body.active) return true;
13635
+ }
13636
+ } catch (err) {
13637
+ if (this.debug) {
13638
+ console.log(
13639
+ `[DEBUG] waitForInferenceInactive fetch failed: ${err instanceof Error ? err.message : String(err)}`
13640
+ );
13641
+ }
13642
+ }
13643
+ await new Promise((r) => setTimeout(r, 2e3));
13644
+ }
13645
+ return false;
12948
13646
  }
12949
13647
  /**
12950
13648
  * Send messages and stream the response
12951
13649
  */
12952
13650
  async sendMessage(messages, onEvent, options) {
13651
+ return this.streamRequest({ messages }, onEvent, options);
13652
+ }
13653
+ /**
13654
+ * Stream an AG-UI request (initial messages or HITL resume).
13655
+ */
13656
+ async streamRequest(request, onEvent, options) {
12953
13657
  const body = JSON.stringify({
12954
13658
  ...this.model ? { model: this.model } : {},
12955
- messages,
13659
+ messages: request.messages ?? [],
13660
+ ...this.appContext ? { appContext: this.appContext } : {},
13661
+ ...request.resumeValue !== void 0 ? { resumeValue: request.resumeValue } : {},
13662
+ ...request.resumeInterruptId ? { resumeInterruptId: request.resumeInterruptId } : {},
12956
13663
  ...options?.autoApprove ? { context: { autoApprove: true } } : {}
12957
13664
  });
12958
13665
  if (this.debug) {
12959
13666
  console.log(`
12960
13667
  [DEBUG] POST ${this.endpointUrl}`);
12961
- console.log(`[DEBUG] Body: ${messages.length} message(s)`);
13668
+ console.log(
13669
+ `[DEBUG] Body: ${request.resumeValue !== void 0 ? "resume" : `${(request.messages ?? []).length} message(s)`}`
13670
+ );
12962
13671
  }
13672
+ await this.postStream(body, onEvent, options);
13673
+ }
13674
+ async postStream(body, onEvent, options, conflictRetries = 0) {
12963
13675
  const response = await fetch(this.endpointUrl, {
12964
13676
  method: "POST",
12965
13677
  headers: {
@@ -12972,12 +13684,21 @@ var AGUIClient = class {
12972
13684
  if (this.debug) {
12973
13685
  console.log(`[DEBUG] Response status: ${response.status}`);
12974
13686
  }
13687
+ if (response.status === 409 && conflictRetries < 3) {
13688
+ const ready = await this.waitForInferenceInactive();
13689
+ if (ready) {
13690
+ await this.postStream(body, onEvent, options, conflictRetries + 1);
13691
+ return;
13692
+ }
13693
+ }
12975
13694
  if (!response.ok) {
12976
13695
  const errorText = await response.text().catch(() => "");
12977
13696
  if (this.debug) {
12978
13697
  console.log(`[DEBUG] Error response: ${errorText}`);
12979
13698
  }
12980
- throw new Error(`Chat request failed: ${response.status}`);
13699
+ throw new Error(
13700
+ `Chat request failed: ${response.status}${errorText ? `: ${errorText.slice(0, 200)}` : ""}`
13701
+ );
12981
13702
  }
12982
13703
  const reader = response.body.getReader();
12983
13704
  const decoder = new TextDecoder();
@@ -13108,8 +13829,129 @@ var COL = {
13108
13829
  function stderr2(msg) {
13109
13830
  process.stderr.write(msg + "\n");
13110
13831
  }
13832
+ var ORG_AUTH_TIMEOUT_MS = 5 * 60 * 1e3;
13833
+ function extractOrgTokenFromSetCookies(setCookieValues, preferredCookieName) {
13834
+ let fallback;
13835
+ for (const value of setCookieValues) {
13836
+ const nameValue = value.split(";")[0]?.trim() ?? "";
13837
+ const eqIdx = nameValue.indexOf("=");
13838
+ if (eqIdx === -1) continue;
13839
+ const name = nameValue.slice(0, eqIdx).trim();
13840
+ const tokenValue = nameValue.slice(eqIdx + 1).trim() || void 0;
13841
+ if (!tokenValue) continue;
13842
+ if (name === preferredCookieName) return tokenValue;
13843
+ if (!fallback && (name.startsWith("orgToken") || name.startsWith("orgSession"))) {
13844
+ fallback = tokenValue;
13845
+ }
13846
+ }
13847
+ return fallback;
13848
+ }
13849
+ async function tryDirectJoin(apiUrl, accessToken, orgAuthInfo) {
13850
+ const response = await fetch(`${apiUrl}/api/v2/o/${orgAuthInfo.orgUuid}/join`, {
13851
+ method: "POST",
13852
+ headers: {
13853
+ "Content-Type": "application/json",
13854
+ Authorization: `Bearer ${accessToken}`
13855
+ },
13856
+ body: "{}"
13857
+ });
13858
+ if (response.status === 400) {
13859
+ return null;
13860
+ }
13861
+ if (!response.ok) {
13862
+ throw new Error(`Org join failed (HTTP ${response.status})`);
13863
+ }
13864
+ const rawHeaders = response.headers;
13865
+ const setCookies = rawHeaders.getSetCookie?.() ?? (rawHeaders.get("set-cookie") ? [rawHeaders.get("set-cookie")] : []);
13866
+ if (setCookies.length === 0) {
13867
+ throw new Error("Org join succeeded but no Set-Cookie header returned");
13868
+ }
13869
+ const orgToken = extractOrgTokenFromSetCookies(setCookies, orgAuthInfo.cookieName);
13870
+ if (!orgToken) {
13871
+ throw new Error("Org join succeeded but org token cookie not found in Set-Cookie");
13872
+ }
13873
+ return orgToken;
13874
+ }
13875
+ function isAllowedAuthUrl(url, apiUrl) {
13876
+ try {
13877
+ const parsed = new URL(url);
13878
+ const api = new URL(apiUrl);
13879
+ if (parsed.protocol !== "https:" && parsed.protocol !== "http:") return false;
13880
+ if (parsed.hostname === api.hostname) return true;
13881
+ const lastTwo = (host) => {
13882
+ const parts = host.split(".").filter(Boolean);
13883
+ return parts.length >= 2 ? parts.slice(-2).join(".") : host;
13884
+ };
13885
+ const isIp = /^[0-9.]+$|^\[.*\]$/.test(parsed.hostname);
13886
+ if (isIp) return false;
13887
+ return lastTwo(parsed.hostname) === lastTwo(api.hostname);
13888
+ } catch {
13889
+ return false;
13890
+ }
13891
+ }
13892
+ function openBrowser2(url) {
13893
+ let command;
13894
+ let args;
13895
+ if (process.platform === "darwin") {
13896
+ command = "open";
13897
+ args = [url];
13898
+ } else if (process.platform === "win32") {
13899
+ command = "cmd.exe";
13900
+ args = ["/c", "start", "", url];
13901
+ } else {
13902
+ command = "xdg-open";
13903
+ args = [url];
13904
+ }
13905
+ execFile(command, args, (_err) => {
13906
+ });
13907
+ }
13908
+ function registerOrgAuthHandler(apiClient, apiUrl, accessToken) {
13909
+ apiClient.setOrgAuthHandler(async (orgAuthInfo) => {
13910
+ try {
13911
+ const orgToken = await tryDirectJoin(apiUrl, accessToken, orgAuthInfo);
13912
+ if (orgToken !== null) {
13913
+ apiClient.setOrgToken(orgToken, orgAuthInfo.orgUuid);
13914
+ return;
13915
+ }
13916
+ } catch (err) {
13917
+ const msg = err instanceof Error ? err.message : String(err);
13918
+ stderr2(`Warning: org direct-join failed (${msg}); trying browser auth`);
13919
+ }
13920
+ if (!isAllowedAuthUrl(orgAuthInfo.authUrl, apiUrl)) {
13921
+ throw new Error(
13922
+ `Refusing to open organization auth URL: scheme/host does not match the configured API host. Re-run with the expected --api-url, or contact support.`
13923
+ );
13924
+ }
13925
+ stderr2(`
13926
+ This workspace requires organization SSO authentication.`);
13927
+ stderr2(`Opening browser to complete authentication...`);
13928
+ stderr2(` ${orgAuthInfo.authUrl}
13929
+ `);
13930
+ stderr2(`If the browser does not open, visit the URL above manually.`);
13931
+ stderr2(
13932
+ `After signing in, re-run the command \u2014 the CLI cannot receive the SSO token directly.`
13933
+ );
13934
+ openBrowser2(orgAuthInfo.authUrl);
13935
+ await new Promise((_, reject) => {
13936
+ const t = setTimeout(
13937
+ () => reject(
13938
+ new Error(
13939
+ "Organization authentication timed out.\nPlease complete authentication in the browser, then re-run the command."
13940
+ )
13941
+ ),
13942
+ ORG_AUTH_TIMEOUT_MS
13943
+ );
13944
+ t.unref?.();
13945
+ });
13946
+ });
13947
+ }
13111
13948
 
13112
13949
  // src/lib/context.ts
13950
+ function makeApiClient(accessToken, apiUrl) {
13951
+ const apiClient = new ApiClient(accessToken, apiUrl);
13952
+ registerOrgAuthHandler(apiClient, apiUrl, accessToken);
13953
+ return apiClient;
13954
+ }
13113
13955
  async function tryTokenRefresh(ctx, creds) {
13114
13956
  if (!creds.refreshToken) return null;
13115
13957
  const refreshed = await refreshAccessToken(
@@ -13119,7 +13961,7 @@ async function tryTokenRefresh(ctx, creds) {
13119
13961
  ctx.env
13120
13962
  );
13121
13963
  if (!refreshed?.accessToken) return null;
13122
- const apiClient = new ApiClient(refreshed.accessToken, ctx.envConfig.apiUrl);
13964
+ const apiClient = makeApiClient(refreshed.accessToken, ctx.envConfig.apiUrl);
13123
13965
  return { ...ctx, accessToken: refreshed.accessToken, apiClient };
13124
13966
  }
13125
13967
  function requireAuth(ctx) {
@@ -13129,12 +13971,14 @@ function requireAuth(ctx) {
13129
13971
  return ctx;
13130
13972
  }
13131
13973
  function createPublicContext(opts) {
13132
- const apiUrl = opts.apiUrl || process.env.GRAVITY_RAIL_API_URL || "https://api.gravityrail.com";
13133
- const frontendUrl = opts.frontendUrl || process.env.GRAVITY_RAIL_FRONTEND_URL || "https://app.gravityrail.com";
13134
- const envConfig = { apiUrl, frontendUrl };
13135
- const credentialsManager = new CredentialsManager(homedir(), apiUrl);
13974
+ const env = opts.env ?? "prod";
13975
+ const envConfig = opts.apiUrl ? {
13976
+ apiUrl: opts.apiUrl,
13977
+ frontendUrl: opts.frontendUrl || process.env.GRAVITY_RAIL_FRONTEND_URL || "https://app.gravityrail.com"
13978
+ } : getEnvironmentConfig(env);
13979
+ const credentialsManager = new CredentialsManager(homedir(), envConfig.apiUrl);
13136
13980
  return {
13137
- env: "prod",
13981
+ env,
13138
13982
  envConfig,
13139
13983
  outputFormat: detectOutputFormat(opts.outputFormat),
13140
13984
  verbose: opts.verbose ?? false,
@@ -13146,7 +13990,7 @@ async function createPublicAuthenticatedContext(opts) {
13146
13990
  const ctx = createPublicContext(opts);
13147
13991
  const apiKey = process.env.GRAVITY_RAIL_API_KEY;
13148
13992
  if (apiKey) {
13149
- const apiClient = new ApiClient(apiKey, ctx.envConfig.apiUrl);
13993
+ const apiClient = makeApiClient(apiKey, ctx.envConfig.apiUrl);
13150
13994
  return { ...ctx, accessToken: apiKey, apiClient };
13151
13995
  }
13152
13996
  const creds = ctx.credentialsManager.load(ctx.env);
@@ -13154,7 +13998,7 @@ async function createPublicAuthenticatedContext(opts) {
13154
13998
  const buffer = 5 * 60 * 1e3;
13155
13999
  const notExpired = !creds.expiresAt || new Date(creds.expiresAt) > new Date(Date.now() + buffer);
13156
14000
  if (notExpired) {
13157
- const apiClient = new ApiClient(creds.accessToken, ctx.envConfig.apiUrl);
14001
+ const apiClient = makeApiClient(creds.accessToken, ctx.envConfig.apiUrl);
13158
14002
  return { ...ctx, accessToken: creds.accessToken, apiClient };
13159
14003
  }
13160
14004
  const refreshed = await tryTokenRefresh(ctx, creds);
@@ -13183,32 +14027,48 @@ async function readJsonInput(args) {
13183
14027
  throw new CLIError(`Cannot read file: ${filePath}`);
13184
14028
  }
13185
14029
  }
13186
- if (!process.stdin.isTTY) {
13187
- return readStdin();
14030
+ if (process.stdin.isTTY === true) {
14031
+ return void 0;
13188
14032
  }
13189
- return void 0;
14033
+ return readStdinIfPiped();
13190
14034
  }
13191
- function readStdin() {
13192
- return new Promise((resolve, reject) => {
14035
+ function readStdinIfPiped() {
14036
+ return new Promise((resolve2, reject) => {
13193
14037
  let data = "";
13194
- process.stdin.setEncoding("utf-8");
13195
- process.stdin.on("data", (chunk) => {
13196
- data += chunk;
13197
- });
13198
- process.stdin.on("end", () => {
14038
+ let settled = false;
14039
+ const finish = (value) => {
14040
+ if (settled) return;
14041
+ settled = true;
14042
+ resolve2(value);
14043
+ };
14044
+ const flush = () => {
13199
14045
  if (!data.trim()) {
13200
- resolve(void 0);
14046
+ finish(void 0);
13201
14047
  return;
13202
14048
  }
13203
14049
  try {
13204
- resolve(JSON.parse(data));
14050
+ finish(JSON.parse(data));
13205
14051
  } catch {
13206
14052
  reject(new CLIError("Invalid JSON from stdin"));
13207
14053
  }
14054
+ };
14055
+ process.stdin.setEncoding("utf-8");
14056
+ process.stdin.on("data", (chunk) => {
14057
+ data += chunk;
13208
14058
  });
14059
+ process.stdin.on("end", flush);
13209
14060
  process.stdin.on("error", (err) => {
13210
14061
  reject(new CLIError(`Error reading stdin: ${err.message}`));
13211
14062
  });
14063
+ process.stdin.resume();
14064
+ setImmediate(() => {
14065
+ if (data) return;
14066
+ if (process.stdin.readableEnded) {
14067
+ flush();
14068
+ return;
14069
+ }
14070
+ finish(void 0);
14071
+ });
13212
14072
  });
13213
14073
  }
13214
14074
 
@@ -13614,6 +14474,17 @@ function requireNumber(args, key) {
13614
14474
  if (isNaN(num)) throw new Error(`Argument --${key} must be a number`);
13615
14475
  return num;
13616
14476
  }
14477
+ function requireNumberFrom(args, ...keys) {
14478
+ for (const key of keys) {
14479
+ const val = args[key];
14480
+ if (typeof val === "string") {
14481
+ const num = Number(val);
14482
+ if (!isNaN(num)) return num;
14483
+ }
14484
+ }
14485
+ const hint = keys.map((k) => `--${k}`).join(" or ");
14486
+ throw new Error(`Missing required argument: ${hint}`);
14487
+ }
13617
14488
 
13618
14489
  // src/domains/agent-tasks.ts
13619
14490
  var LIST_COLUMNS = [
@@ -13774,6 +14645,7 @@ var agentsDomain = {
13774
14645
  var COLUMNS2 = [
13775
14646
  COL.id(),
13776
14647
  COL.uuid(),
14648
+ { header: "TYPE", getValue: (item) => item.chatType ?? item.chat_type ?? "" },
13777
14649
  { header: "MEMBER", getValue: (item) => item.member_name ?? String(item.member_id ?? "") },
13778
14650
  COL.status(),
13779
14651
  { header: "CHANNEL", getValue: (item) => item.channel ?? "" },
@@ -13825,7 +14697,11 @@ var chatsDomain = {
13825
14697
  isFlag: true
13826
14698
  },
13827
14699
  { name: "is-test", description: "Show only test chats", isFlag: true },
13828
- { name: "member-id", description: "Filter by member ID" }
14700
+ { name: "member-id", description: "Filter by member ID" },
14701
+ {
14702
+ name: "chat-type",
14703
+ description: "Filter by chat type (assignment, manager, developer, member, contributor). Default: assignment"
14704
+ }
13829
14705
  ]
13830
14706
  }),
13831
14707
  // Messages
@@ -13834,7 +14710,7 @@ var chatsDomain = {
13834
14710
  description: "List messages for a chat. Use --limit/--offset to page; the API caps a single request at 100. Tool-call shell rows that the API filter excludes (parent_message_id IS NOT NULL or parent_call_id IS NOT NULL) are still hidden \u2014 use `gr chats inspect --id <chat>` for the full debug view.",
13835
14711
  requiresWorkspace: true,
13836
14712
  args: [
13837
- { name: "chat-id", description: "Chat ID", required: true },
14713
+ { name: "chat-id", aliases: ["id"], description: "Chat ID", required: true },
13838
14714
  {
13839
14715
  name: "limit",
13840
14716
  description: "Max messages to return (1-100, default 100)"
@@ -13857,7 +14733,7 @@ var chatsDomain = {
13857
14733
  }
13858
14734
  const result2 = await requireAuth(ctx).apiClient.getChatMessages(
13859
14735
  workspace,
13860
- requireNumber(args, "chat-id"),
14736
+ requireNumberFrom(args, "chat-id", "id"),
13861
14737
  limit,
13862
14738
  offset
13863
14739
  );
@@ -13870,7 +14746,7 @@ var chatsDomain = {
13870
14746
  mutates: true,
13871
14747
  requiresWorkspace: true,
13872
14748
  args: [
13873
- { name: "chat-id", description: "Chat ID", required: true },
14749
+ { name: "chat-id", aliases: ["id"], description: "Chat ID", required: true },
13874
14750
  { name: "stream", description: "Stream the AI response via AG-UI", isFlag: true }
13875
14751
  ],
13876
14752
  handler: async ({ ctx, workspace, args, data }) => {
@@ -13879,7 +14755,7 @@ var chatsDomain = {
13879
14755
  throw new Error(
13880
14756
  `Message content is required (pass --data '"your message"' or --data '{"content":"your message"}')`
13881
14757
  );
13882
- const chatId = requireNumber(args, "chat-id");
14758
+ const chatId = requireNumberFrom(args, "chat-id", "id");
13883
14759
  if (args.stream) {
13884
14760
  const aguiClient = new AGUIClient({
13885
14761
  baseUrl: ctx.envConfig.apiUrl,
@@ -13912,11 +14788,11 @@ var chatsDomain = {
13912
14788
  description: "Send an assistant message to a chat (does not trigger AI inference)",
13913
14789
  mutates: true,
13914
14790
  requiresWorkspace: true,
13915
- args: [{ name: "chat-id", description: "Chat ID", required: true }],
14791
+ args: [{ name: "chat-id", aliases: ["id"], description: "Chat ID", required: true }],
13916
14792
  handler: async ({ ctx, workspace, args, data }) => {
13917
14793
  const result2 = await requireAuth(ctx).apiClient.sendAssistantMessage(
13918
14794
  workspace,
13919
- requireNumber(args, "chat-id"),
14795
+ requireNumberFrom(args, "chat-id", "id"),
13920
14796
  data
13921
14797
  );
13922
14798
  outputSingle(result2, ctx, MESSAGE_COLUMNS2);
@@ -15957,8 +16833,8 @@ var dataTypesDomain = {
15957
16833
  var RULE_COLUMNS = [
15958
16834
  COL.id(),
15959
16835
  COL.name(),
15960
- { header: "EVENT", getValue: (item) => item.event_type ?? "" },
15961
- COL.enabled()
16836
+ { header: "EVENT", getValue: (item) => item.eventType ?? "" },
16837
+ { header: "ACTIVE", getValue: (item) => String(item.active ?? "") }
15962
16838
  ];
15963
16839
  var EVENT_COLUMNS2 = [
15964
16840
  COL.id(),
@@ -15966,29 +16842,33 @@ var EVENT_COLUMNS2 = [
15966
16842
  { header: "SLUG", getValue: (item) => item.slug ?? "" },
15967
16843
  COL.status()
15968
16844
  ];
15969
- var eventRulesCrud = crudCommands({
16845
+ var eventRulesCrudNoList = crudCommands({
15970
16846
  prefix: ["events", "rules"],
15971
16847
  entityName: "event rule",
15972
- listMethod: "getEventRules",
15973
16848
  getMethod: "getEventRule",
15974
16849
  createMethod: "createEventRule",
15975
16850
  updateMethod: "updateEventRule",
15976
16851
  deleteMethod: "deleteEventRule",
15977
- // The endpoint is paginated and excludes nothing by object_type. Without
15978
- // 'full', the CLI silently returned only page 1 (default 25 rules), which
15979
- // hid routine/journey/calendar-scoped rules in workspaces with many
15980
- // task-scoped rules. 'full' wires up --page/--page-size and --all.
15981
- paginationSupport: "full",
15982
16852
  columns: RULE_COLUMNS,
15983
16853
  createExamples: [
15984
16854
  `gr events rules create -w $WID --data '{"name":"Label on step","objectType":"journey",`,
15985
16855
  ' "eventType":"journey_step:execute","actionType":"member:label",',
15986
16856
  ` "actionParams":{"addLabelIds":["<label-uuid>"]},"journeyStepId":<step-id>}'`,
15987
16857
  "",
16858
+ "Scheduled outbound (routine \u2192 chat \u2192 voice/SMS):",
16859
+ `gr events rules create -w $WID --allow-write --data '{"name":"AM voice check-in",`,
16860
+ ' "objectType":"routine","eventType":"routine:triggered","actionType":"chat:create",',
16861
+ ' "routineId":<routine-id>,',
16862
+ ' "actionParams":{"workflowId":<workflow-id>,"channel":"phone-voice",',
16863
+ ` "phoneNumberId":<workspace-phone-id>}}'`,
16864
+ "",
16865
+ ' PM SMS variant: use "channel":"phone-sms" and a second rule on the same routineId.',
16866
+ " Prereq: org phone assigned + gr phone-numbers link; workflow published with start task.",
16867
+ "",
15988
16868
  "Required: objectType, eventType, actionType",
15989
- "Optional: name, actionParams, conditions (CEL), journeyStepId, delay (sec), order",
16869
+ "Optional: name, actionParams, conditions (CEL), journeyStepId, routineId, delay (sec), order",
15990
16870
  "",
15991
- "Common eventTypes: journey_step:execute, journey:enrolled, journey:completed,",
16871
+ "Common eventTypes: journey_step:execute, journey:enrolled, routine:triggered,",
15992
16872
  " task:created, chat:created, data_record:created, member:created",
15993
16873
  "",
15994
16874
  "Common actionTypes: member:label, member:notify, webhook:send, email:send,",
@@ -15997,6 +16877,57 @@ var eventRulesCrud = crudCommands({
15997
16877
  'member:label actionParams: {"addLabelIds":["uuid"],"removeLabelIds":["uuid"]}'
15998
16878
  ]
15999
16879
  });
16880
+ var eventRulesListCmd = {
16881
+ path: ["events", "rules", "list"],
16882
+ description: "List event rules (use --journey-step-id or --event-type to filter)",
16883
+ requiresWorkspace: true,
16884
+ columns: RULE_COLUMNS,
16885
+ args: [
16886
+ { name: "journey-step-id", description: "Filter by journey step ID" },
16887
+ { name: "event-type", description: "Filter by event type (e.g. journey_step:execute)" },
16888
+ { name: "object-type", description: "Filter by object type (e.g. journey, task)" },
16889
+ { name: "include-disabled", description: "Include inactive rules", isFlag: true },
16890
+ { name: "page", description: "Page number (without filters)" },
16891
+ { name: "page-size", description: "Page size (without filters)" },
16892
+ {
16893
+ name: "all",
16894
+ description: "Fetch all pages (without filters)",
16895
+ isFlag: true
16896
+ }
16897
+ ],
16898
+ handler: async ({ ctx, workspace, args }) => {
16899
+ const client = requireAuth(ctx).apiClient;
16900
+ const journeyStepId = args["journey-step-id"] ? requireNumber(args, "journey-step-id") : void 0;
16901
+ const eventType = args["event-type"];
16902
+ const objectType = args["object-type"];
16903
+ const includeDisabled = args["include-disabled"] === true;
16904
+ if (journeyStepId !== void 0 || eventType !== void 0 || objectType !== void 0 || includeDisabled) {
16905
+ const result3 = await client.searchEventRules(workspace, {
16906
+ ...journeyStepId !== void 0 ? { journeyStepId } : {},
16907
+ ...eventType ? { eventType } : {},
16908
+ ...objectType ? { objectType } : {},
16909
+ ...includeDisabled ? { includeDisabled: true } : {}
16910
+ });
16911
+ outputData(listResult(result3, false), ctx, RULE_COLUMNS);
16912
+ return;
16913
+ }
16914
+ if (args["all"]) {
16915
+ const allItems = await fetchAllPages(
16916
+ async ({ page: page2, pageSize: pageSize2 }) => client.getEventRules(workspace, { page: page2, pageSize: pageSize2 })
16917
+ );
16918
+ outputData(allItems, ctx, RULE_COLUMNS);
16919
+ return;
16920
+ }
16921
+ const page = args["page"] ? requireNumber(args, "page") : void 0;
16922
+ const pageSize = args["page-size"] ? requireNumber(args, "page-size") : void 0;
16923
+ const result2 = await client.getEventRules(workspace, {
16924
+ ...page !== void 0 ? { page } : {},
16925
+ ...pageSize !== void 0 ? { pageSize } : {}
16926
+ });
16927
+ outputData(listResult(result2, true), ctx, RULE_COLUMNS);
16928
+ }
16929
+ };
16930
+ var eventRulesCrud = [eventRulesListCmd, ...eventRulesCrudNoList];
16000
16931
  var eventRulesAliases = eventRulesCrud.filter((cmd) => {
16001
16932
  const verb = cmd.path[cmd.path.length - 1];
16002
16933
  return verb === "list" || verb === "get";
@@ -16269,6 +17200,15 @@ var NOTE_COLUMNS2 = [
16269
17200
  { header: "CONTENT", getValue: (item) => (item.contents ?? "").slice(0, 60) },
16270
17201
  { header: "CREATED", getValue: (item) => item.createdAt ?? "" }
16271
17202
  ];
17203
+ var ACTION_COLUMNS = [
17204
+ COL.id(),
17205
+ { header: "UUID", getValue: (item) => (item.uuid ?? "").slice(0, 8) },
17206
+ COL.name(),
17207
+ { header: "EVENT", getValue: (item) => item.eventType ?? "" },
17208
+ { header: "ACTION", getValue: (item) => item.actionType ?? "" },
17209
+ { header: "ACTIVE", getValue: (item) => String(item.active ?? "") },
17210
+ { header: "CONDITIONS", getValue: (item) => (item.conditions ?? "").slice(0, 40) }
17211
+ ];
16272
17212
  function baseUrl(ctx, wid) {
16273
17213
  return `${ctx.envConfig.apiUrl}/api/v2/w/${wid}/journeys`;
16274
17214
  }
@@ -16983,6 +17923,70 @@ var journeysDomain = {
16983
17923
  process.stdout.write(`Deleted note ${noteId}
16984
17924
  `);
16985
17925
  }
17926
+ },
17927
+ // ── Step execute actions (event rules scoped to a step) ────────
17928
+ {
17929
+ path: ["journeys", "steps", "actions", "list"],
17930
+ description: "List event rules (actions) attached to a journey step",
17931
+ requiresWorkspace: true,
17932
+ args: [
17933
+ { name: "step-id", description: "Journey step ID (numeric)", required: true },
17934
+ {
17935
+ name: "include-disabled",
17936
+ description: "Include inactive/disabled rules",
17937
+ isFlag: true
17938
+ }
17939
+ ],
17940
+ examples: [
17941
+ "gr journeys steps actions list -w $WID --step-id <step-id>",
17942
+ "gr journeys steps actions list -w $WID --step-id <step-id> --include-disabled"
17943
+ ],
17944
+ handler: async ({ ctx, workspace, args }) => {
17945
+ const stepId = requireNumber(args, "step-id");
17946
+ const includeDisabled = args["include-disabled"] === true;
17947
+ const result2 = await requireAuth(ctx).apiClient.searchEventRules(workspace, {
17948
+ eventType: EventRuleEventType.JOURNEY_STEP_EXECUTE,
17949
+ journeyStepId: stepId,
17950
+ ...includeDisabled ? { includeDisabled: true } : {}
17951
+ });
17952
+ outputData(listResult(result2, false), ctx, ACTION_COLUMNS);
17953
+ }
17954
+ },
17955
+ {
17956
+ path: ["journeys", "steps", "actions", "get"],
17957
+ description: "Get a journey step action (event rule) by ID",
17958
+ requiresWorkspace: true,
17959
+ args: [{ name: "id", description: "Event rule ID", required: true }],
17960
+ examples: ["gr journeys steps actions get -w $WID --id <rule-id>"],
17961
+ handler: async ({ ctx, workspace, args }) => {
17962
+ const id = requireNumber(args, "id");
17963
+ const result2 = await requireAuth(ctx).apiClient.getEventRule(workspace, id);
17964
+ outputSingle(result2, ctx, ACTION_COLUMNS);
17965
+ }
17966
+ },
17967
+ {
17968
+ path: ["journeys", "steps", "actions", "update"],
17969
+ description: "Update a journey step action \u2014 modify template, conditions, or active state",
17970
+ mutates: true,
17971
+ requiresWorkspace: true,
17972
+ args: [{ name: "id", description: "Event rule ID", required: true }],
17973
+ examples: [
17974
+ "gr journeys steps actions update -w $WID --id <rule-id> \\",
17975
+ ` --data '{"actionParams":{"messageTemplate":"Hello {{member.name}}"}}' --allow-write`,
17976
+ "",
17977
+ "Updatable fields: name, conditions (CEL), actionParams, active, delay, order",
17978
+ "Non-updatable: objectType, eventType, actionType, journeyStepId"
17979
+ ],
17980
+ handler: async ({ ctx, workspace, args, data }) => {
17981
+ if (!data) throw new CLIError("JSON data required (--data, --file, or stdin)");
17982
+ const id = requireNumber(args, "id");
17983
+ const result2 = await requireAuth(ctx).apiClient.updateEventRule(
17984
+ workspace,
17985
+ id,
17986
+ data
17987
+ );
17988
+ outputSingle(result2, ctx, ACTION_COLUMNS);
17989
+ }
16986
17990
  }
16987
17991
  ]
16988
17992
  };
@@ -17608,6 +18612,13 @@ var COLUMNS16 = [
17608
18612
  { header: "PREFIX", getValue: (item) => item.prefix ?? "" },
17609
18613
  COL.created()
17610
18614
  ];
18615
+ var CREATE_COLUMNS = [
18616
+ COL.id(),
18617
+ COL.name(),
18618
+ { header: "KEY", getValue: (item) => item.key ?? "" },
18619
+ { header: "PREFIX", getValue: (item) => item.prefix ?? "" },
18620
+ COL.created()
18621
+ ];
17611
18622
  var apiKeysDomain = {
17612
18623
  name: "api-keys",
17613
18624
  description: "Manage API keys",
@@ -17628,7 +18639,10 @@ var apiKeysDomain = {
17628
18639
  requiresWorkspace: true,
17629
18640
  handler: async ({ ctx, workspace, data }) => {
17630
18641
  const result2 = await requireAuth(ctx).apiClient.createApiKey(workspace, data);
17631
- outputSingle(result2, ctx, COLUMNS16);
18642
+ outputSingle(result2, ctx, CREATE_COLUMNS);
18643
+ if (ctx.outputFormat === "table") {
18644
+ process.stdout.write("\n\u26A0 This key will not be shown again. Copy it now.\n");
18645
+ }
17632
18646
  }
17633
18647
  },
17634
18648
  {
@@ -17660,7 +18674,10 @@ var apiKeysDomain = {
17660
18674
  requiresWorkspace: false,
17661
18675
  handler: async ({ ctx, data }) => {
17662
18676
  const result2 = await requireAuth(ctx).apiClient.createGlobalApiKey(data);
17663
- outputSingle(result2, ctx, COLUMNS16);
18677
+ outputSingle(result2, ctx, CREATE_COLUMNS);
18678
+ if (ctx.outputFormat === "table") {
18679
+ process.stdout.write("\n\u26A0 This key will not be shown again. Copy it now.\n");
18680
+ }
17664
18681
  }
17665
18682
  },
17666
18683
  {
@@ -18134,7 +19151,7 @@ var conciergeDomain = {
18134
19151
  path: ["concierge", "messages"],
18135
19152
  description: "Show messages for a concierge chat",
18136
19153
  requiresWorkspace: false,
18137
- args: [{ name: "id", description: "Chat ID", required: true }],
19154
+ args: [{ name: "id", aliases: ["chat-id"], description: "Chat ID", required: true }],
18138
19155
  handler: async ({ ctx, args }) => {
18139
19156
  const auth = requireAuth(ctx);
18140
19157
  const chatId = Number(args.id);
@@ -18566,7 +19583,7 @@ var milestonesDomain = {
18566
19583
  var COLUMNS23 = [
18567
19584
  COL.id(),
18568
19585
  COL.name(),
18569
- { header: "TYPE", getValue: (item) => item.type ?? "" },
19586
+ { header: "TYPE", getValue: (item) => item.noticeType ?? "" },
18570
19587
  COL.enabled()
18571
19588
  ];
18572
19589
  var notificationRulesDomain = {
@@ -18767,15 +19784,15 @@ var DOMAIN_UUID_ARG = {
18767
19784
  function pluralize(count, singular, plural = `${singular}s`) {
18768
19785
  return count === 1 ? singular : plural;
18769
19786
  }
18770
- function emailVerifyCommand(path, description) {
19787
+ function emailVerifyCommand(path4, description) {
18771
19788
  return {
18772
- path,
19789
+ path: path4,
18773
19790
  description,
18774
19791
  mutates: true,
18775
19792
  requiresWorkspace: false,
18776
19793
  args: [ORG_UUID_ARG, DOMAIN_UUID_ARG],
18777
19794
  examples: [
18778
- `yarn gr ${path.join(" ")} --org-uuid $ORG_UUID --domain-uuid $DOMAIN_UUID --allow-write`
19795
+ `yarn gr ${path4.join(" ")} --org-uuid $ORG_UUID --domain-uuid $DOMAIN_UUID --allow-write`
18779
19796
  ],
18780
19797
  handler: async (hctx) => {
18781
19798
  const result2 = await requireAuth(hctx.ctx).apiClient.verifyOrgDomainEmail(
@@ -18786,15 +19803,15 @@ function emailVerifyCommand(path, description) {
18786
19803
  }
18787
19804
  };
18788
19805
  }
18789
- function siteVerifyCommand(path, description) {
19806
+ function siteVerifyCommand(path4, description) {
18790
19807
  return {
18791
- path,
19808
+ path: path4,
18792
19809
  description,
18793
19810
  mutates: true,
18794
19811
  requiresWorkspace: false,
18795
19812
  args: [ORG_UUID_ARG, DOMAIN_UUID_ARG],
18796
19813
  examples: [
18797
- `yarn gr ${path.join(" ")} --org-uuid $ORG_UUID --domain-uuid $DOMAIN_UUID --allow-write`
19814
+ `yarn gr ${path4.join(" ")} --org-uuid $ORG_UUID --domain-uuid $DOMAIN_UUID --allow-write`
18798
19815
  ],
18799
19816
  handler: async (hctx) => {
18800
19817
  const result2 = await requireAuth(hctx.ctx).apiClient.verifyOrgDomainSite(
@@ -18805,9 +19822,9 @@ function siteVerifyCommand(path, description) {
18805
19822
  }
18806
19823
  };
18807
19824
  }
18808
- function registerDomainCommand(path) {
19825
+ function registerDomainCommand(path4) {
18809
19826
  return {
18810
- path,
19827
+ path: path4,
18811
19828
  description: "Register an organization domain and return ownership TXT instructions",
18812
19829
  mutates: true,
18813
19830
  requiresWorkspace: false,
@@ -18816,7 +19833,7 @@ function registerDomainCommand(path) {
18816
19833
  { name: "domain", description: "Domain to register, e.g. example.com", required: true }
18817
19834
  ],
18818
19835
  examples: [
18819
- `yarn gr ${path.join(" ")} --org-uuid $ORG_UUID --domain example.com --allow-write`
19836
+ `yarn gr ${path4.join(" ")} --org-uuid $ORG_UUID --domain example.com --allow-write`
18820
19837
  ],
18821
19838
  handler: async (hctx) => {
18822
19839
  const result2 = await requireAuth(hctx.ctx).apiClient.registerOrgDomain(
@@ -19170,6 +20187,12 @@ var commands2 = [
19170
20187
  workspaceUuid
19171
20188
  );
19172
20189
  outputSingle(result2, hctx.ctx, PROVIDER_PHONE_COLUMNS);
20190
+ process.stdout.write(
20191
+ `
20192
+ If workspace phone list is still empty, create a workspace phone record then:
20193
+ gr phone-numbers link -w ${workspaceUuid} --id <workspace-phone-id> --provider-phone-uuid ${providerPhoneUuid} --allow-write
20194
+ `
20195
+ );
19173
20196
  }
19174
20197
  },
19175
20198
  {
@@ -19273,6 +20296,31 @@ var phoneNumbersDomain = {
19273
20296
  outputData(result2, ctx, COLUMNS25);
19274
20297
  }
19275
20298
  },
20299
+ {
20300
+ path: ["phone-numbers", "link"],
20301
+ description: "Link a workspace phone number to a provider (org) phone",
20302
+ mutates: true,
20303
+ requiresWorkspace: true,
20304
+ args: [
20305
+ {
20306
+ name: "phone-number-id",
20307
+ aliases: ["id"],
20308
+ description: "Workspace phone number ID",
20309
+ required: true
20310
+ },
20311
+ { name: "provider-phone-uuid", description: "Provider phone UUID", required: true }
20312
+ ],
20313
+ examples: [
20314
+ "gr phone-numbers link -w $WID --id 1 --provider-phone-uuid <uuid> --allow-write"
20315
+ ],
20316
+ handler: async ({ ctx, workspace, args }) => {
20317
+ const auth = requireAuth(ctx);
20318
+ const id = requireNumberFrom(args, "phone-number-id", "id");
20319
+ const providerPhoneUuid = requireString(args, "provider-phone-uuid");
20320
+ const result2 = await auth.apiClient.linkPhoneNumber(workspace, id, providerPhoneUuid);
20321
+ outputData([result2], auth, COLUMNS25);
20322
+ }
20323
+ },
19276
20324
  {
19277
20325
  path: ["phone-numbers", "request"],
19278
20326
  description: "Request a phone number",
@@ -19291,7 +20339,12 @@ var phoneNumbersDomain = {
19291
20339
  description: "List calls for a phone number",
19292
20340
  requiresWorkspace: true,
19293
20341
  args: [
19294
- { name: "phone-number-id", description: "Phone number ID", required: true },
20342
+ {
20343
+ name: "phone-number-id",
20344
+ aliases: ["id"],
20345
+ description: "Phone number ID",
20346
+ required: true
20347
+ },
19295
20348
  { name: "page", description: "Page number" },
19296
20349
  { name: "page-size", description: "Page size" },
19297
20350
  { name: "status", description: "Filter by status" }
@@ -19300,7 +20353,7 @@ var phoneNumbersDomain = {
19300
20353
  const status = args.status;
19301
20354
  const result2 = await requireAuth(ctx).apiClient.getPhoneNumberCalls(
19302
20355
  workspace,
19303
- requireNumber(args, "phone-number-id"),
20356
+ requireNumberFrom(args, "phone-number-id", "id"),
19304
20357
  args.page ? Number(args.page) : void 0,
19305
20358
  args["page-size"] ? Number(args["page-size"]) : void 0,
19306
20359
  status ? { status } : void 0
@@ -19313,14 +20366,19 @@ var phoneNumbersDomain = {
19313
20366
  description: "List messages for a phone number",
19314
20367
  requiresWorkspace: true,
19315
20368
  args: [
19316
- { name: "phone-number-id", description: "Phone number ID", required: true },
20369
+ {
20370
+ name: "phone-number-id",
20371
+ aliases: ["id"],
20372
+ description: "Phone number ID",
20373
+ required: true
20374
+ },
19317
20375
  { name: "page", description: "Page number" },
19318
20376
  { name: "page-size", description: "Page size" }
19319
20377
  ],
19320
20378
  handler: async ({ ctx, workspace, args }) => {
19321
20379
  const result2 = await requireAuth(ctx).apiClient.getPhoneNumberMessages(
19322
20380
  workspace,
19323
- requireNumber(args, "phone-number-id"),
20381
+ requireNumberFrom(args, "phone-number-id", "id"),
19324
20382
  args.page ? Number(args.page) : void 0,
19325
20383
  args["page-size"] ? Number(args["page-size"]) : void 0
19326
20384
  );
@@ -19330,36 +20388,85 @@ var phoneNumbersDomain = {
19330
20388
  ]
19331
20389
  };
19332
20390
 
19333
- // src/domains/pronunciations.ts
20391
+ // src/lib/resolve-org.ts
20392
+ async function resolveOrgUuidFromWorkspace(apiClient, workspaceUuid) {
20393
+ const workspace = await apiClient.getWorkspace(workspaceUuid);
20394
+ const orgUuid = workspace.organizationUuid;
20395
+ if (!orgUuid) {
20396
+ throw new CLIError(
20397
+ "Workspace has no organization; pass --org-uuid for organization-scoped commands"
20398
+ );
20399
+ }
20400
+ return orgUuid;
20401
+ }
20402
+ function normalizePronunciationCreatePayload(data) {
20403
+ if (!data || typeof data !== "object" || Array.isArray(data)) {
20404
+ throw new CLIError("JSON body required with term and respelling (--data or --file)");
20405
+ }
20406
+ const raw = data;
20407
+ const term = raw.term ?? raw.word;
20408
+ const respelling = raw.respelling ?? raw.pronunciation;
20409
+ if (typeof term !== "string" || !term) {
20410
+ throw new CLIError("Payload requires term (alias: word)");
20411
+ }
20412
+ if (typeof respelling !== "string" || !respelling) {
20413
+ throw new CLIError("Payload requires respelling (alias: pronunciation)");
20414
+ }
20415
+ const payload = { term, respelling };
20416
+ if (raw.accountId !== void 0 && raw.accountId !== null) {
20417
+ payload.accountId = Number(raw.accountId);
20418
+ }
20419
+ return payload;
20420
+ }
20421
+ function normalizePronunciationUpdatePayload(data) {
20422
+ if (!data || typeof data !== "object" || Array.isArray(data)) {
20423
+ throw new CLIError("JSON body required (--data or --file)");
20424
+ }
20425
+ const raw = data;
20426
+ const respelling = raw.respelling ?? raw.pronunciation;
20427
+ if (typeof respelling !== "string" || !respelling) {
20428
+ throw new CLIError("Payload requires respelling (alias: pronunciation)");
20429
+ }
20430
+ return { respelling };
20431
+ }
20432
+
20433
+ // src/domains/pronunciations.ts
19334
20434
  var COLUMNS26 = [
19335
20435
  COL.id(),
19336
- { header: "WORD", getValue: (item) => item.word ?? "" },
19337
- { header: "PRONUNCIATION", getValue: (item) => item.pronunciation ?? "" },
19338
- { header: "TYPE", getValue: (item) => item.type ?? "" }
20436
+ { header: "TERM", getValue: (item) => item.term ?? "" },
20437
+ { header: "RESPELLING", getValue: (item) => item.respelling ?? "" },
20438
+ { header: "SCOPE", getValue: (item) => item.scope ?? "" }
20439
+ ];
20440
+ var CREATE_EXAMPLES = [
20441
+ `gr pronunciations create -w $WID --data '{"term":"Jeeves","respelling":"JEEVZ"}' --allow-write`,
20442
+ " (aliases: word \u2192 term, pronunciation \u2192 respelling)"
19339
20443
  ];
19340
20444
  var pronunciationsDomain = {
19341
20445
  name: "pronunciations",
19342
- description: "Manage pronunciation entries",
20446
+ description: "Manage pronunciation entries (org-scoped; -w resolves organization)",
19343
20447
  commands: [
19344
20448
  {
19345
20449
  path: ["pronunciations", "list"],
19346
- description: "List pronunciation entries",
20450
+ description: "List pronunciation entries for the workspace organization",
19347
20451
  requiresWorkspace: true,
19348
20452
  handler: async ({ ctx, workspace }) => {
19349
- const result2 = await requireAuth(ctx).apiClient.getPronunciationEntries(workspace);
20453
+ const auth = requireAuth(ctx);
20454
+ const orgUuid = await resolveOrgUuidFromWorkspace(auth.apiClient, workspace);
20455
+ const result2 = await auth.apiClient.getPronunciationEntries(orgUuid);
19350
20456
  outputData(result2, ctx, COLUMNS26);
19351
20457
  }
19352
20458
  },
19353
20459
  {
19354
20460
  path: ["pronunciations", "create"],
19355
- description: "Create a pronunciation entry",
20461
+ description: "Create a pronunciation entry (term + respelling)",
19356
20462
  mutates: true,
19357
20463
  requiresWorkspace: true,
20464
+ examples: CREATE_EXAMPLES,
19358
20465
  handler: async ({ ctx, workspace, data }) => {
19359
- const result2 = await requireAuth(ctx).apiClient.createPronunciationEntry(
19360
- workspace,
19361
- data
19362
- );
20466
+ const auth = requireAuth(ctx);
20467
+ const orgUuid = await resolveOrgUuidFromWorkspace(auth.apiClient, workspace);
20468
+ const payload = normalizePronunciationCreatePayload(data);
20469
+ const result2 = await auth.apiClient.createPronunciationEntry(orgUuid, payload);
19363
20470
  outputSingle(result2, ctx, COLUMNS26);
19364
20471
  }
19365
20472
  },
@@ -19370,10 +20477,13 @@ var pronunciationsDomain = {
19370
20477
  requiresWorkspace: true,
19371
20478
  args: [{ name: "id", description: "Pronunciation entry ID", required: true }],
19372
20479
  handler: async ({ ctx, workspace, args, data }) => {
19373
- const result2 = await requireAuth(ctx).apiClient.updatePronunciationEntry(
19374
- workspace,
20480
+ const auth = requireAuth(ctx);
20481
+ const orgUuid = await resolveOrgUuidFromWorkspace(auth.apiClient, workspace);
20482
+ const payload = normalizePronunciationUpdatePayload(data);
20483
+ const result2 = await auth.apiClient.updatePronunciationEntry(
20484
+ orgUuid,
19375
20485
  requireNumber(args, "id"),
19376
- data
20486
+ payload
19377
20487
  );
19378
20488
  outputSingle(result2, ctx, COLUMNS26);
19379
20489
  }
@@ -19385,8 +20495,10 @@ var pronunciationsDomain = {
19385
20495
  requiresWorkspace: true,
19386
20496
  args: [{ name: "id", description: "Pronunciation entry ID", required: true }],
19387
20497
  handler: async ({ ctx, workspace, args }) => {
20498
+ const auth = requireAuth(ctx);
20499
+ const orgUuid = await resolveOrgUuidFromWorkspace(auth.apiClient, workspace);
19388
20500
  const id = requireNumber(args, "id");
19389
- await requireAuth(ctx).apiClient.deletePronunciationEntry(workspace, id);
20501
+ await auth.apiClient.deletePronunciationEntry(orgUuid, id);
19390
20502
  process.stdout.write(`Deleted pronunciation entry ${id}
19391
20503
  `);
19392
20504
  }
@@ -19406,7 +20518,8 @@ var pronunciationsDomain = {
19406
20518
  mutates: true,
19407
20519
  requiresWorkspace: true,
19408
20520
  handler: async ({ ctx, data }) => {
19409
- const result2 = await requireAuth(ctx).apiClient.createMyPronunciation(data);
20521
+ const payload = normalizePronunciationCreatePayload(data);
20522
+ const result2 = await requireAuth(ctx).apiClient.createMyPronunciation(payload);
19410
20523
  outputSingle(result2, ctx, COLUMNS26);
19411
20524
  }
19412
20525
  },
@@ -19414,11 +20527,17 @@ var pronunciationsDomain = {
19414
20527
  path: ["pronunciations", "suggest"],
19415
20528
  description: "Get pronunciation suggestions for a word",
19416
20529
  requiresWorkspace: true,
19417
- args: [{ name: "word", description: "Word to get suggestions for", required: true }],
20530
+ args: [
20531
+ {
20532
+ name: "word",
20533
+ aliases: ["term"],
20534
+ description: "Word to get suggestions for",
20535
+ required: true
20536
+ }
20537
+ ],
19418
20538
  handler: async ({ ctx, args }) => {
19419
- const result2 = await requireAuth(ctx).apiClient.suggestPronunciations(
19420
- requireString(args, "word")
19421
- );
20539
+ const word = typeof args.word === "string" ? args.word : typeof args.term === "string" ? args.term : requireString(args, "word");
20540
+ const result2 = await requireAuth(ctx).apiClient.suggestPronunciations(word);
19422
20541
  outputData(result2, ctx);
19423
20542
  }
19424
20543
  },
@@ -19584,20 +20703,20 @@ var promptsDomain = {
19584
20703
  "gr prompts inspect --chat-id 789 --turn 3"
19585
20704
  ],
19586
20705
  handler: async ({ ctx, workspace, args }) => {
19587
- const taskId = args["task-id"] ? requireNumber(args, "task-id") : void 0;
19588
- const chatId = args["chat-id"] ? requireNumber(args, "chat-id") : void 0;
19589
- if (!taskId && !chatId) {
20706
+ const taskId = args["task-id"] !== void 0 ? requireNumber(args, "task-id") : void 0;
20707
+ const chatId = args["chat-id"] !== void 0 ? requireNumber(args, "chat-id") : void 0;
20708
+ if (taskId === void 0 && chatId === void 0) {
19590
20709
  throw new Error("Provide --task-id or --chat-id");
19591
20710
  }
19592
- if (taskId && chatId) {
20711
+ if (taskId !== void 0 && chatId !== void 0) {
19593
20712
  throw new Error("Provide --task-id or --chat-id, not both");
19594
20713
  }
19595
20714
  const channel = args.channel || void 0;
19596
- const turn = args.turn ? requireNumber(args, "turn") : void 0;
19597
- const result2 = await requireAuth(ctx).apiClient.inspectPrompt(workspace, taskId ?? 0, {
19598
- channel,
19599
- ...chatId ? { chatId } : {},
19600
- ...turn ? { turn } : {}
20715
+ const turn = args.turn !== void 0 ? requireNumber(args, "turn") : void 0;
20716
+ const result2 = await requireAuth(ctx).apiClient.inspectPrompt(workspace, {
20717
+ ...taskId !== void 0 ? { taskId } : { chatId },
20718
+ ...channel ? { channel } : {},
20719
+ ...turn !== void 0 ? { turn } : {}
19601
20720
  });
19602
20721
  outputSingle(result2, ctx);
19603
20722
  }
@@ -19605,6 +20724,128 @@ var promptsDomain = {
19605
20724
  ]
19606
20725
  };
19607
20726
 
20727
+ // src/domains/support.ts
20728
+ var SUPPORT_COLUMNS = [
20729
+ COL.uuid(),
20730
+ { header: "STATUS", getValue: (item) => item.status ?? "" },
20731
+ { header: "TYPE", getValue: (item) => item.supportRequestType ?? "" },
20732
+ { header: "SEVERITY", getValue: (item) => item.severity ?? "" },
20733
+ { header: "SOURCE", getValue: (item) => item.source ?? "" },
20734
+ { header: "CREATED", getValue: (item) => (item.createdAt ?? "").slice(0, 19) },
20735
+ { header: "TITLE", getValue: (item) => item.title ?? "" }
20736
+ ];
20737
+ var CONTEXT_ARGS = [
20738
+ { name: "workspace", aliases: ["w"], description: "Workspace UUID" },
20739
+ { name: "org-uuid", description: "Organization UUID" }
20740
+ ];
20741
+ function listParams(args) {
20742
+ return {
20743
+ page: args.page ? Number(args.page) : void 0,
20744
+ pageSize: args["page-size"] ? Number(args["page-size"]) : void 0,
20745
+ status: args.status,
20746
+ supportRequestType: args.type,
20747
+ severity: args.severity,
20748
+ source: args.source
20749
+ };
20750
+ }
20751
+ function requestPayload(data, args) {
20752
+ const input = data ?? {};
20753
+ return {
20754
+ supportRequestType: input.supportRequestType ?? input.support_request_type ?? args.type ?? "question",
20755
+ title: input.title ?? requireString(args, "title"),
20756
+ description: input.description ?? requireString(args, "description"),
20757
+ severity: input.severity ?? args.severity
20758
+ };
20759
+ }
20760
+ function commentPayload(data, args) {
20761
+ const input = data ?? {};
20762
+ return {
20763
+ body: input.body ?? requireString(args, "body")
20764
+ };
20765
+ }
20766
+ var supportDomain = {
20767
+ name: "support",
20768
+ description: "Manage support requests",
20769
+ commands: [
20770
+ {
20771
+ path: ["support", "list"],
20772
+ description: "List support requests",
20773
+ args: [
20774
+ ...CONTEXT_ARGS,
20775
+ { name: "status", description: "Filter by status" },
20776
+ { name: "type", description: "Filter by type: bug, feature_request, question" },
20777
+ { name: "severity", description: "Filter by severity" },
20778
+ { name: "source", description: "Filter by source" },
20779
+ { name: "page", description: "Page number" },
20780
+ { name: "page-size", description: "Page size" }
20781
+ ],
20782
+ columns: SUPPORT_COLUMNS,
20783
+ handler: async ({ ctx, args, workspace }) => {
20784
+ const client = requireAuth(ctx).apiClient;
20785
+ const wid = args.workspace ?? workspace;
20786
+ const orgUuid = args["org-uuid"];
20787
+ const result2 = wid ? await client.listWorkspaceSupportRequests(wid, listParams(args)) : orgUuid ? await client.listOrgSupportRequests(orgUuid, listParams(args)) : await client.listSupportRequests(listParams(args));
20788
+ outputData(result2, ctx, SUPPORT_COLUMNS);
20789
+ }
20790
+ },
20791
+ {
20792
+ path: ["support", "get"],
20793
+ description: "Get a support request",
20794
+ args: [
20795
+ ...CONTEXT_ARGS,
20796
+ { name: "id", aliases: ["uuid"], description: "Support request UUID", required: true }
20797
+ ],
20798
+ handler: async ({ ctx, args, workspace }) => {
20799
+ const client = requireAuth(ctx).apiClient;
20800
+ const id = requireString(args, "id");
20801
+ const wid = args.workspace ?? workspace;
20802
+ const orgUuid = args["org-uuid"];
20803
+ const result2 = wid ? await client.getWorkspaceSupportRequest(wid, id) : orgUuid ? await client.getOrgSupportRequest(orgUuid, id) : await client.getSupportRequest(id);
20804
+ outputSingle(result2, ctx, SUPPORT_COLUMNS);
20805
+ }
20806
+ },
20807
+ {
20808
+ path: ["support", "create"],
20809
+ description: "Create a support request",
20810
+ mutates: true,
20811
+ args: [
20812
+ ...CONTEXT_ARGS,
20813
+ { name: "type", description: "Request type: bug, feature_request, question" },
20814
+ { name: "title", description: "Support request title" },
20815
+ { name: "description", description: "Support request description" },
20816
+ { name: "severity", description: "Optional severity" }
20817
+ ],
20818
+ handler: async ({ ctx, args, workspace, data }) => {
20819
+ const client = requireAuth(ctx).apiClient;
20820
+ const wid = args.workspace ?? workspace;
20821
+ const orgUuid = args["org-uuid"];
20822
+ const payload = requestPayload(data, args);
20823
+ const result2 = wid ? await client.createWorkspaceSupportRequest(wid, payload) : orgUuid ? await client.createOrgSupportRequest(orgUuid, payload) : await client.createSupportRequest(payload);
20824
+ outputSingle(result2, ctx, SUPPORT_COLUMNS);
20825
+ }
20826
+ },
20827
+ {
20828
+ path: ["support", "comment"],
20829
+ description: "Add a customer comment to a support request",
20830
+ mutates: true,
20831
+ args: [
20832
+ ...CONTEXT_ARGS,
20833
+ { name: "id", aliases: ["uuid"], description: "Support request UUID", required: true },
20834
+ { name: "body", description: "Comment body" }
20835
+ ],
20836
+ handler: async ({ ctx, args, workspace, data }) => {
20837
+ const client = requireAuth(ctx).apiClient;
20838
+ const id = requireString(args, "id");
20839
+ const wid = args.workspace ?? workspace;
20840
+ const orgUuid = args["org-uuid"];
20841
+ const payload = commentPayload(data, args);
20842
+ const result2 = wid ? await client.commentOnWorkspaceSupportRequest(wid, id, payload) : orgUuid ? await client.commentOnOrgSupportRequest(orgUuid, id, payload) : await client.commentOnSupportRequest(id, payload);
20843
+ outputSingle(result2, ctx, SUPPORT_COLUMNS);
20844
+ }
20845
+ }
20846
+ ]
20847
+ };
20848
+
19608
20849
  // src/domains/supervisors.ts
19609
20850
  var COLUMNS28 = [
19610
20851
  COL.id(),
@@ -19721,6 +20962,10 @@ var syncDomain = {
19721
20962
  {
19722
20963
  name: "board-id",
19723
20964
  description: "Scope to a single board mapping (requires --entity-type)"
20965
+ },
20966
+ {
20967
+ name: "record-limit",
20968
+ description: "Cap the run to a preview sample (1..200). Requires --dry-run and --entity-type."
19724
20969
  }
19725
20970
  ],
19726
20971
  examples: [
@@ -19729,7 +20974,8 @@ var syncDomain = {
19729
20974
  "sync run --connection-id 6 --full-resync",
19730
20975
  "sync run --connection-id 6 --quiet",
19731
20976
  "sync run --connection-id 6 --entity-type member",
19732
- "sync run --connection-id 6 --entity-type member --board-id 18406694561"
20977
+ "sync run --connection-id 6 --entity-type member --board-id 18406694561",
20978
+ "sync run --connection-id 6 --dry-run --entity-type member --record-limit 20"
19733
20979
  ],
19734
20980
  mutates: true,
19735
20981
  handler: async ({ ctx, args, workspace }) => {
@@ -19749,12 +20995,39 @@ var syncDomain = {
19749
20995
  entityType = rawEntityType;
19750
20996
  }
19751
20997
  const boardId = args["board-id"];
20998
+ const rawRecordLimit = args["record-limit"];
20999
+ let recordLimit;
21000
+ if (rawRecordLimit !== void 0 && rawRecordLimit !== "") {
21001
+ const parsed = Number(rawRecordLimit);
21002
+ if (!Number.isInteger(parsed) || parsed < 1 || parsed > 200) {
21003
+ throw new CLIError(
21004
+ `Invalid --record-limit "${rawRecordLimit}". Must be an integer between 1 and 200.`
21005
+ );
21006
+ }
21007
+ if (!dryRun) {
21008
+ throw new CLIError(
21009
+ "--record-limit requires --dry-run: capped runs are preview-only."
21010
+ );
21011
+ }
21012
+ if (entityType === void 0) {
21013
+ throw new CLIError(
21014
+ "--record-limit requires --entity-type: capped previews must target a single entity type."
21015
+ );
21016
+ }
21017
+ recordLimit = parsed;
21018
+ }
21019
+ if (fullResync && (dryRun || recordLimit !== void 0)) {
21020
+ throw new CLIError(
21021
+ "--full-resync is incompatible with --dry-run / --record-limit: checkpoint reset must happen on a non-preview run."
21022
+ );
21023
+ }
19752
21024
  if (!quiet) {
19753
21025
  const flags = [
19754
21026
  dryRun && "(dry run)",
19755
21027
  fullResync && "(full re-sync)",
19756
21028
  entityType && `(${entityType} only)`,
19757
- boardId && `(board ${boardId})`
21029
+ boardId && `(board ${boardId})`,
21030
+ recordLimit !== void 0 && `(limit ${recordLimit})`
19758
21031
  ].filter(Boolean).join(" ");
19759
21032
  console.error(
19760
21033
  `Starting sync for connection ${connectionId}${flags ? ` ${flags}` : ""}...`
@@ -19767,7 +21040,8 @@ var syncDomain = {
19767
21040
  dryRun,
19768
21041
  resetCheckpoints: fullResync,
19769
21042
  entityType,
19770
- boardId
21043
+ boardId,
21044
+ recordLimit
19771
21045
  }
19772
21046
  );
19773
21047
  if (!response.ok) {
@@ -19961,6 +21235,31 @@ var appConnectionsDomain = {
19961
21235
  );
19962
21236
  outputSingle(result2, ctx);
19963
21237
  }
21238
+ },
21239
+ {
21240
+ path: ["app-connections", "relink-member"],
21241
+ description: "Re-enable sync for a previously unlinked member by clearing the manual-unlink exclusion on this connection. Idempotent: returns cleared=false when no exclusion exists.",
21242
+ mutates: true,
21243
+ requiresWorkspace: true,
21244
+ args: [
21245
+ { name: "id", description: "Connection ID (numeric)", required: true },
21246
+ { name: "member-id", description: "Member ID (numeric)", required: true },
21247
+ {
21248
+ name: "board-id",
21249
+ description: "Optional Monday board ID. Required for Monday connections where exclusions are board-scoped; omit for single-scope connectors."
21250
+ }
21251
+ ],
21252
+ handler: async ({ ctx, workspace, args }) => {
21253
+ const boardIdRaw = args["board-id"];
21254
+ const options = boardIdRaw !== void 0 && boardIdRaw !== "" ? { boardId: String(boardIdRaw) } : void 0;
21255
+ const result2 = await requireAuth(ctx).apiClient.clearConnectionMemberExclusion(
21256
+ workspace,
21257
+ requireNumber(args, "id"),
21258
+ requireNumber(args, "member-id"),
21259
+ options
21260
+ );
21261
+ outputSingle(result2, ctx);
21262
+ }
19964
21263
  }
19965
21264
  ]
19966
21265
  };
@@ -20653,49 +21952,6 @@ var mondayDomain = {
20653
21952
  outputData(result2, ctx);
20654
21953
  }
20655
21954
  },
20656
- {
20657
- path: ["monday", "webhook-get"],
20658
- description: "Get a Monday.com webhook",
20659
- requiresWorkspace: true,
20660
- args: [
20661
- { name: "board-id", description: "Board ID", required: true },
20662
- { name: "id", description: "Webhook ID", required: true }
20663
- ],
20664
- handler: async ({ ctx, args, workspace }) => {
20665
- const result2 = await requireAuth(ctx).apiClient.getMondayWebhook(
20666
- workspace,
20667
- requireString(args, "board-id"),
20668
- requireString(args, "id")
20669
- );
20670
- outputSingle(result2, ctx);
20671
- }
20672
- },
20673
- {
20674
- path: ["monday", "webhook-create"],
20675
- description: "Create a Monday.com webhook",
20676
- mutates: true,
20677
- requiresWorkspace: true,
20678
- handler: async ({ ctx, data, workspace }) => {
20679
- const result2 = await requireAuth(ctx).apiClient.createMondayWebhook(
20680
- workspace,
20681
- data
20682
- );
20683
- outputSingle(result2, ctx);
20684
- }
20685
- },
20686
- {
20687
- path: ["monday", "webhook-delete"],
20688
- description: "Delete a Monday.com webhook",
20689
- mutates: true,
20690
- requiresWorkspace: true,
20691
- args: [{ name: "id", description: "Webhook ID", required: true }],
20692
- handler: async ({ ctx, args, workspace }) => {
20693
- const id = requireString(args, "id");
20694
- await requireAuth(ctx).apiClient.deleteMondayWebhook(workspace, id);
20695
- process.stdout.write(`Deleted Monday webhook ${id}
20696
- `);
20697
- }
20698
- },
20699
21955
  {
20700
21956
  path: ["monday", "user-info"],
20701
21957
  description: "Get current Monday.com user info",
@@ -21035,6 +22291,113 @@ var slackAppsDomain = {
21035
22291
  ]
21036
22292
  };
21037
22293
 
22294
+ // src/domains/integrations/teams-apps.ts
22295
+ var COLUMNS33 = [COL.id(), COL.name(), COL.status()];
22296
+ function addTeamsUrls(data, apiUrl, workspaceUuid) {
22297
+ const base = `${apiUrl}/api/v2/w/${workspaceUuid}/app-connections/teams`;
22298
+ return {
22299
+ ...data,
22300
+ _urls: {
22301
+ eventsEndpoint: `${base}/events`,
22302
+ oauthUserAuthorize: `${base}/oauth/user/authorize?app_id=${data.id ?? ""}`,
22303
+ oauthUserCallback: `${base}/oauth/user/callback`
22304
+ }
22305
+ };
22306
+ }
22307
+ var teamsAppsDomain = {
22308
+ name: "teams-apps",
22309
+ description: "Manage Microsoft Teams app integrations",
22310
+ commands: [
22311
+ ...crudCommands({
22312
+ prefix: ["teams-apps"],
22313
+ entityName: "Teams app",
22314
+ listMethod: "getTeamsApps",
22315
+ deleteMethod: "deleteTeamsApp",
22316
+ columns: COLUMNS33,
22317
+ paginationSupport: "full"
22318
+ }),
22319
+ {
22320
+ path: ["teams-apps", "get"],
22321
+ description: "Get a Teams app by ID",
22322
+ args: [{ name: "id", description: "Teams app ID", required: true }],
22323
+ requiresWorkspace: true,
22324
+ handler: async ({ ctx, workspace, args }) => {
22325
+ const result2 = await requireAuth(ctx).apiClient.getTeamsApp(
22326
+ workspace,
22327
+ requireNumber(args, "id")
22328
+ );
22329
+ outputSingle(addTeamsUrls(result2, ctx.envConfig.apiUrl, workspace), ctx);
22330
+ }
22331
+ },
22332
+ {
22333
+ path: ["teams-apps", "create"],
22334
+ description: "Create a Teams app",
22335
+ mutates: true,
22336
+ requiresWorkspace: true,
22337
+ handler: async ({ ctx, workspace, data }) => {
22338
+ if (!data) throw new CLIError("JSON data required (--data, --file, or stdin)");
22339
+ const result2 = await requireAuth(ctx).apiClient.createTeamsApp(workspace, data);
22340
+ outputSingle(addTeamsUrls(result2, ctx.envConfig.apiUrl, workspace), ctx);
22341
+ }
22342
+ },
22343
+ {
22344
+ path: ["teams-apps", "update"],
22345
+ description: "Update a Teams app",
22346
+ mutates: true,
22347
+ args: [{ name: "id", description: "Teams app ID", required: true }],
22348
+ requiresWorkspace: true,
22349
+ handler: async ({ ctx, workspace, args, data }) => {
22350
+ if (!data) throw new CLIError("JSON data required (--data, --file, or stdin)");
22351
+ const result2 = await requireAuth(ctx).apiClient.updateTeamsApp(
22352
+ workspace,
22353
+ requireNumber(args, "id"),
22354
+ data
22355
+ );
22356
+ outputSingle(addTeamsUrls(result2, ctx.envConfig.apiUrl, workspace), ctx);
22357
+ }
22358
+ },
22359
+ {
22360
+ path: ["teams-apps", "conversations"],
22361
+ description: "List Teams conversations linked to chats",
22362
+ requiresWorkspace: true,
22363
+ args: [{ name: "id", description: "Teams app ID", required: true }],
22364
+ handler: async ({ ctx, workspace, args }) => {
22365
+ const result2 = await requireAuth(ctx).apiClient.getTeamsConversations(
22366
+ workspace,
22367
+ requireNumber(args, "id")
22368
+ );
22369
+ outputData(result2, ctx);
22370
+ }
22371
+ },
22372
+ {
22373
+ path: ["teams-apps", "installations"],
22374
+ description: "List per-tenant Teams installations",
22375
+ requiresWorkspace: true,
22376
+ args: [{ name: "id", description: "Teams app ID", required: true }],
22377
+ handler: async ({ ctx, workspace, args }) => {
22378
+ const result2 = await requireAuth(ctx).apiClient.getTeamsInstallations(
22379
+ workspace,
22380
+ requireNumber(args, "id")
22381
+ );
22382
+ outputData(result2, ctx);
22383
+ }
22384
+ },
22385
+ {
22386
+ path: ["teams-apps", "accounts"],
22387
+ description: "List linked Teams (Entra) accounts for this app",
22388
+ requiresWorkspace: true,
22389
+ args: [{ name: "id", description: "Teams app ID", required: true }],
22390
+ handler: async ({ ctx, workspace, args }) => {
22391
+ const result2 = await requireAuth(ctx).apiClient.getTeamsAppAccounts(
22392
+ workspace,
22393
+ requireNumber(args, "id")
22394
+ );
22395
+ outputData(result2, ctx);
22396
+ }
22397
+ }
22398
+ ]
22399
+ };
22400
+
21038
22401
  // src/domains/index.ts
21039
22402
  function registerPublicDomains(registry) {
21040
22403
  registry.register(tasksDomain);
@@ -21066,6 +22429,7 @@ function registerPublicDomains(registry) {
21066
22429
  registry.register(mcpServersDomain);
21067
22430
  registry.register(apiKeysDomain);
21068
22431
  registry.register(subscriptionsDomain);
22432
+ registry.register(supportDomain);
21069
22433
  registry.register(reportsDomain);
21070
22434
  registry.register(aiModelsDomain);
21071
22435
  registry.register(featuresDomain);
@@ -21081,6 +22445,7 @@ function registerPublicDomains(registry) {
21081
22445
  registry.register(confluenceDomain);
21082
22446
  registry.register(discordBotsDomain);
21083
22447
  registry.register(slackAppsDomain);
22448
+ registry.register(teamsAppsDomain);
21084
22449
  registry.register(fhirConnectionsDomain);
21085
22450
  registry.register(appConnectionsDomain);
21086
22451
  registry.register(hubspotDomain);
@@ -21129,6 +22494,327 @@ function openUrl(url) {
21129
22494
  }
21130
22495
  });
21131
22496
  }
22497
+ function buildCliConciergeAppContext() {
22498
+ const shell = process.env.SHELL ? path3.basename(process.env.SHELL) : void 0;
22499
+ return {
22500
+ clientSurface: "cli",
22501
+ channel: "text",
22502
+ cliContext: {
22503
+ shell,
22504
+ os: process.platform,
22505
+ cwdBasename: path3.basename(process.cwd())
22506
+ }
22507
+ };
22508
+ }
22509
+ var DEFAULT_MAX_READ_BYTES = 5e4;
22510
+ var ABSOLUTE_MAX_READ_BYTES = 1e6;
22511
+ function resolveSafePath(root, relativePath) {
22512
+ const rootResolved = path3.resolve(root);
22513
+ const target = path3.resolve(rootResolved, relativePath || ".");
22514
+ if (target !== rootResolved && !target.startsWith(rootResolved + path3.sep)) {
22515
+ return null;
22516
+ }
22517
+ let cursor = rootResolved;
22518
+ const rest = path3.relative(rootResolved, target);
22519
+ if (rest && rest !== ".") {
22520
+ for (const segment of rest.split(path3.sep)) {
22521
+ cursor = path3.join(cursor, segment);
22522
+ try {
22523
+ const lstat = fs.lstatSync(cursor);
22524
+ if (lstat.isSymbolicLink()) {
22525
+ return null;
22526
+ }
22527
+ } catch {
22528
+ break;
22529
+ }
22530
+ }
22531
+ }
22532
+ return target;
22533
+ }
22534
+ function executeCliLocalFileAction(root, interrupt, opts) {
22535
+ const safe = resolveSafePath(root, interrupt.path);
22536
+ if (!safe) {
22537
+ return { ok: false, error: "Path escapes trusted directory" };
22538
+ }
22539
+ try {
22540
+ switch (interrupt.action) {
22541
+ case "read_file": {
22542
+ if (!fs.existsSync(safe)) {
22543
+ return { ok: false, error: "File not found" };
22544
+ }
22545
+ const stat = fs.lstatSync(safe);
22546
+ if (stat.isSymbolicLink()) {
22547
+ return { ok: false, error: "Path escapes trusted directory" };
22548
+ }
22549
+ if (!stat.isFile()) {
22550
+ return { ok: false, error: "Not a file" };
22551
+ }
22552
+ const requested = Number.isFinite(interrupt.max_bytes) ? Math.max(1, Math.min(Number(interrupt.max_bytes), ABSOLUTE_MAX_READ_BYTES)) : DEFAULT_MAX_READ_BYTES;
22553
+ if (stat.size > requested) {
22554
+ const buf = fs.readFileSync(safe, { encoding: "utf8" });
22555
+ return {
22556
+ ok: true,
22557
+ content: buf.slice(0, requested) + `
22558
+
22559
+ [truncated at ${requested} bytes]`
22560
+ };
22561
+ }
22562
+ return { ok: true, content: fs.readFileSync(safe, "utf8") };
22563
+ }
22564
+ case "list_dir": {
22565
+ if (!fs.existsSync(safe)) {
22566
+ return { ok: false, error: "Directory not found" };
22567
+ }
22568
+ const entries = fs.readdirSync(safe, { withFileTypes: true });
22569
+ const lines = entries.slice(0, 200).map((e) => e.isDirectory() ? `${e.name}/` : e.name);
22570
+ if (entries.length > 200) {
22571
+ lines.push(`... and ${entries.length - 200} more`);
22572
+ }
22573
+ return { ok: true, content: lines.join("\n") };
22574
+ }
22575
+ case "write_file": {
22576
+ if (!opts.allowWrite) {
22577
+ return { ok: false, error: "Write requires --allow-write" };
22578
+ }
22579
+ if (interrupt.content === void 0) {
22580
+ return { ok: false, error: "Missing content for write_file" };
22581
+ }
22582
+ fs.mkdirSync(path3.dirname(safe), { recursive: true });
22583
+ fs.writeFileSync(safe, interrupt.content, "utf8");
22584
+ return { ok: true, content: "written" };
22585
+ }
22586
+ default:
22587
+ return { ok: false, error: `Unknown action: ${interrupt.action}` };
22588
+ }
22589
+ } catch (e) {
22590
+ return { ok: false, error: sanitizeLocalFileError(e) };
22591
+ }
22592
+ }
22593
+ function sanitizeLocalFileError(e) {
22594
+ if (e && typeof e === "object" && "code" in e) {
22595
+ const code = e.code;
22596
+ if (code === "ENOENT") return "File or directory not found";
22597
+ if (code === "EACCES" || code === "EPERM") return "Permission denied";
22598
+ if (code === "EISDIR") return "Not a file";
22599
+ if (code === "ENOTDIR") return "Not a directory";
22600
+ }
22601
+ return "Local file operation failed";
22602
+ }
22603
+ function isCliLocalFileInterrupt(value) {
22604
+ if (typeof value !== "object" || value === null) return false;
22605
+ const v = value;
22606
+ return v.type === "cli_local_file" && typeof v.action === "string" && typeof v.path === "string";
22607
+ }
22608
+ var STORE_VERSION = 1;
22609
+ function storePath() {
22610
+ const base = process.env.XDG_CONFIG_HOME ?? (process.platform === "win32" ? path3.join(process.env.APPDATA ?? os.homedir(), "gravityrail") : path3.join(os.homedir(), ".config", "gravityrail"));
22611
+ return path3.join(base, "trusted-dirs.json");
22612
+ }
22613
+ function loadTrustedDirsStore() {
22614
+ const file = storePath();
22615
+ try {
22616
+ const raw = JSON.parse(fs.readFileSync(file, "utf8"));
22617
+ if (raw?.version === STORE_VERSION && Array.isArray(raw.always)) {
22618
+ return { version: STORE_VERSION, always: raw.always.map((p) => path3.resolve(p)) };
22619
+ }
22620
+ } catch {
22621
+ }
22622
+ return { version: STORE_VERSION, always: [] };
22623
+ }
22624
+ function saveTrustedDirsStore(store) {
22625
+ const file = storePath();
22626
+ const dir = path3.dirname(file);
22627
+ fs.mkdirSync(dir, { recursive: true, mode: 448 });
22628
+ fs.writeFileSync(file, JSON.stringify(store, null, 2) + "\n", { mode: 384 });
22629
+ }
22630
+ function isDirectoryTrusted(dirPath, opts) {
22631
+ if (opts?.trustCwdFlag) return true;
22632
+ const resolved = path3.resolve(dirPath);
22633
+ const store = loadTrustedDirsStore();
22634
+ return store.always.includes(resolved);
22635
+ }
22636
+ async function promptTrustInteractive(dirPath) {
22637
+ const rl = readline__default.createInterface({ input: process.stdin, output: process.stderr });
22638
+ const question = (q) => new Promise((resolve2) => rl.question(q, resolve2));
22639
+ process.stderr.write(
22640
+ `
22641
+ Gravity Rail may read files in:
22642
+ ${dirPath}
22643
+
22644
+ File contents can influence the assistant. Do you trust the files in this directory?
22645
+ [1] Trust once (this session)
22646
+ [2] Trust always (remember for this path)
22647
+ [3] No \u2014 do not read local files
22648
+
22649
+ Choice [1/2/3] (default 3): `
22650
+ );
22651
+ const answer = (await question("")).trim() || "3";
22652
+ rl.close();
22653
+ if (answer === "1") return "once";
22654
+ if (answer === "2") return "always";
22655
+ return "denied";
22656
+ }
22657
+ var sessionTrusted = /* @__PURE__ */ new Set();
22658
+ async function resolveDirectoryTrust(opts) {
22659
+ const dir = path3.resolve(opts.trustDir ?? opts.cwd ?? process.cwd());
22660
+ if (isDirectoryTrusted(dir, { trustCwdFlag: opts.trustCwd })) return "trusted";
22661
+ if (sessionTrusted.has(dir)) return "trusted";
22662
+ if (opts.trustDir && path3.resolve(opts.trustDir) === dir) {
22663
+ sessionTrusted.add(dir);
22664
+ return "trusted";
22665
+ }
22666
+ if (opts.trustCwd) {
22667
+ sessionTrusted.add(dir);
22668
+ return "trusted";
22669
+ }
22670
+ if (!process.stdin.isTTY || opts.nonInteractive) {
22671
+ return "denied";
22672
+ }
22673
+ const decision = await promptTrustInteractive(dir);
22674
+ if (decision === "denied") {
22675
+ return "denied";
22676
+ }
22677
+ if (decision === "always") {
22678
+ const store = loadTrustedDirsStore();
22679
+ if (!store.always.includes(dir)) {
22680
+ store.always.push(dir);
22681
+ saveTrustedDirsStore(store);
22682
+ }
22683
+ }
22684
+ sessionTrusted.add(dir);
22685
+ return "trusted";
22686
+ }
22687
+
22688
+ // src/lib/cli-hitl.ts
22689
+ function extractHumanInputRequest(event) {
22690
+ const type = String(event.type ?? "").toUpperCase();
22691
+ if (type === "CUSTOM" && event.name === "human_input_request") {
22692
+ return event.value;
22693
+ }
22694
+ if (event.name === "human_input_request") {
22695
+ return event.value;
22696
+ }
22697
+ return null;
22698
+ }
22699
+ async function handleCliHitlInterrupt(value, opts) {
22700
+ if (!value || typeof value !== "object") return null;
22701
+ const payload = value;
22702
+ if (isCliLocalFileInterrupt(payload)) {
22703
+ const interrupt = payload;
22704
+ if (typeof payload.interrupt_id === "string") {
22705
+ interrupt.interrupt_id = payload.interrupt_id;
22706
+ }
22707
+ return handleCliLocalFile(interrupt, opts);
22708
+ }
22709
+ if (payload.type === "present_choice") {
22710
+ return handlePresentChoiceTerminal(payload);
22711
+ }
22712
+ return null;
22713
+ }
22714
+ async function handleCliLocalFile(interrupt, opts) {
22715
+ const trust = await resolveDirectoryTrust({
22716
+ cwd: process.cwd(),
22717
+ trustCwd: opts.trustCwd,
22718
+ trustDir: opts.trustDir,
22719
+ // Interactive sessions: prompt on first local-file use (review feedback).
22720
+ nonInteractive: opts.nonInteractive ?? process.stdin.isTTY !== true
22721
+ });
22722
+ if (trust !== "trusted") {
22723
+ return {
22724
+ resumeValue: JSON.stringify({
22725
+ ok: false,
22726
+ error: "Directory not trusted for local file access. Re-run with --trust-cwd or --trust-dir <path>, or approve trust interactively when prompted."
22727
+ }),
22728
+ resumeInterruptId: interrupt.interrupt_id
22729
+ };
22730
+ }
22731
+ process.stderr.write(`
22732
+ [local ${interrupt.action}] ${interrupt.path}
22733
+ `);
22734
+ const result2 = executeCliLocalFileAction(process.cwd(), interrupt, {
22735
+ allowWrite: opts.allowWrite
22736
+ });
22737
+ return {
22738
+ resumeValue: JSON.stringify(result2),
22739
+ resumeInterruptId: interrupt.interrupt_id
22740
+ };
22741
+ }
22742
+ async function handlePresentChoiceTerminal(payload) {
22743
+ const prompt = typeof payload.user_prompt === "string" && payload.user_prompt || typeof payload.description === "string" && payload.description || "Choose an option";
22744
+ const markup = typeof payload.openui_markup === "string" ? payload.openui_markup : "";
22745
+ process.stderr.write(`
22746
+ ${prompt}
22747
+ `);
22748
+ if (markup) {
22749
+ process.stderr.write(`${markup.slice(0, 2e3)}
22750
+ `);
22751
+ }
22752
+ if (!process.stdin.isTTY) {
22753
+ return {
22754
+ resumeValue: "",
22755
+ resumeInterruptId: typeof payload.interrupt_id === "string" ? payload.interrupt_id : void 0
22756
+ };
22757
+ }
22758
+ const rl = readline__default.createInterface({ input: process.stdin, output: process.stderr });
22759
+ const answer = await new Promise((resolve2) => {
22760
+ rl.question("Your choice (value): ", resolve2);
22761
+ });
22762
+ rl.close();
22763
+ return {
22764
+ resumeValue: answer.trim(),
22765
+ resumeInterruptId: typeof payload.interrupt_id === "string" ? payload.interrupt_id : void 0
22766
+ };
22767
+ }
22768
+
22769
+ // src/lib/concierge-agui-loop.ts
22770
+ var MAX_HITL_ROUNDS = 25;
22771
+ async function runConciergeAguiLoop(client, initialMessages, onEvent, opts) {
22772
+ let streamText = "";
22773
+ let hasToolCalls = false;
22774
+ let resume;
22775
+ for (let round = 0; round < MAX_HITL_ROUNDS; round++) {
22776
+ let hitlPayload = null;
22777
+ await client.streamRequest(
22778
+ resume ? {
22779
+ messages: [],
22780
+ resumeValue: resume.resumeValue,
22781
+ resumeInterruptId: resume.resumeInterruptId
22782
+ } : { messages: initialMessages },
22783
+ (event) => {
22784
+ onEvent(event);
22785
+ const delta = getTextDelta(event);
22786
+ if (delta) streamText += delta;
22787
+ const type = event.type?.toLowerCase() ?? "";
22788
+ if (type === "tool_call_start") hasToolCalls = true;
22789
+ const errorMsg = getErrorMessage(event);
22790
+ if (errorMsg) process.stderr.write(`\x1B[31mError: ${errorMsg}\x1B[0m
22791
+ `);
22792
+ const hitl = extractHumanInputRequest(event);
22793
+ if (hitl) hitlPayload = hitl;
22794
+ },
22795
+ { autoApprove: opts.autoApprove }
22796
+ );
22797
+ if (!hitlPayload) {
22798
+ break;
22799
+ }
22800
+ const next = await handleCliHitlInterrupt(hitlPayload, {
22801
+ allowWrite: opts.allowWrite,
22802
+ autoApprove: opts.autoApprove,
22803
+ trustCwd: opts.trustCwd,
22804
+ trustDir: opts.trustDir,
22805
+ nonInteractive: opts.nonInteractive
22806
+ });
22807
+ if (!next) {
22808
+ process.stderr.write(
22809
+ " [HITL] Unsupported interrupt in CLI \u2014 open app.gravityrail.com/setup to continue.\n"
22810
+ );
22811
+ break;
22812
+ }
22813
+ resume = next;
22814
+ streamText = "";
22815
+ }
22816
+ return { streamText, hasToolCalls };
22817
+ }
21132
22818
  var RealtimeClient = class extends EventEmitter {
21133
22819
  ws = null;
21134
22820
  connected = false;
@@ -21148,7 +22834,7 @@ var RealtimeClient = class extends EventEmitter {
21148
22834
  new Error("WebSocket not available. Node.js 22+ is required for realtime mode.")
21149
22835
  );
21150
22836
  }
21151
- return new Promise((resolve, reject) => {
22837
+ return new Promise((resolve2, reject) => {
21152
22838
  const params = new URLSearchParams();
21153
22839
  if (this.options.vadMode) {
21154
22840
  params.append("vad", this.options.vadMode);
@@ -21203,7 +22889,7 @@ var RealtimeClient = class extends EventEmitter {
21203
22889
  }, 1e4);
21204
22890
  this.once("connected", () => {
21205
22891
  clearTimeout(timeout);
21206
- resolve();
22892
+ resolve2();
21207
22893
  });
21208
22894
  this.once("error", () => {
21209
22895
  clearTimeout(timeout);
@@ -22168,7 +23854,7 @@ async function listOutputDevices() {
22168
23854
  return listDevices("play");
22169
23855
  }
22170
23856
  function listDevices(command) {
22171
- return new Promise((resolve) => {
23857
+ return new Promise((resolve2) => {
22172
23858
  try {
22173
23859
  const proc = spawnSync(command, ["--list-devices"], {
22174
23860
  encoding: "utf-8",
@@ -22192,9 +23878,9 @@ function listDevices(command) {
22192
23878
  if (devices.length === 0) {
22193
23879
  devices.push({ id: "default", name: "System Default", isDefault: true });
22194
23880
  }
22195
- resolve(devices);
23881
+ resolve2(devices);
22196
23882
  } catch {
22197
- resolve([{ id: "default", name: "System Default", isDefault: true }]);
23883
+ resolve2([{ id: "default", name: "System Default", isDefault: true }]);
22198
23884
  }
22199
23885
  });
22200
23886
  }
@@ -22216,14 +23902,14 @@ async function selectDevice(devices, label) {
22216
23902
  process.stderr.write(` ${i + 1}. ${dev.name}${marker}
22217
23903
  `);
22218
23904
  }
22219
- return new Promise((resolve) => {
23905
+ return new Promise((resolve2) => {
22220
23906
  const defaultIdx = devices.findIndex((d) => d.isDefault);
22221
23907
  const defaultNum = defaultIdx >= 0 ? defaultIdx + 1 : 1;
22222
23908
  rl.question(` Select [${defaultNum}]: `, (answer) => {
22223
23909
  rl.close();
22224
23910
  const num = answer.trim() ? parseInt(answer.trim(), 10) : defaultNum;
22225
23911
  const idx = Math.max(0, Math.min(devices.length - 1, num - 1));
22226
- resolve(devices[idx]);
23912
+ resolve2(devices[idx]);
22227
23913
  });
22228
23914
  });
22229
23915
  }
@@ -22481,56 +24167,51 @@ async function runChatSession(session, args) {
22481
24167
  "Interactive mode requires a TTY. Use --message for non-interactive mode."
22482
24168
  );
22483
24169
  }
24170
+ const allowWrite = !!args["allow-write"] || !!session.allowWrite;
22484
24171
  if (message) {
22485
- await singleTurnChatSession(session, message, debug, autoApprove);
24172
+ await singleTurnChatSession(session, message, debug, autoApprove, allowWrite);
22486
24173
  } else if (isVoice) {
22487
24174
  await voiceChatSession(session, vadMode(args), args, debug);
22488
24175
  } else if (isRealtime) {
22489
24176
  await realtimeChatSession(session, vadMode(args), debug);
22490
24177
  } else {
22491
- await interactiveChatSession(session, debug);
24178
+ await interactiveChatSession(session, debug, autoApprove, allowWrite);
22492
24179
  }
22493
24180
  }
22494
24181
  function vadMode(args) {
22495
24182
  return typeof args.vad === "string" ? args.vad : "server";
22496
24183
  }
22497
- async function singleTurnChatSession(session, message, debug, autoApprove = false) {
24184
+ async function singleTurnChatSession(session, message, debug, autoApprove = false, allowWrite = false) {
22498
24185
  const aguiClient = new AGUIClient({
22499
24186
  baseUrl: session.ctx.envConfig.apiUrl,
24187
+ workspaceUuid: session.workspaceUuid,
24188
+ chatId: session.chatId,
22500
24189
  endpointUrl: session.aguiEndpointUrl,
22501
24190
  accessToken: session.ctx.accessToken,
22502
24191
  debug,
22503
- model: session.model
24192
+ model: session.model,
24193
+ appContext: session.appContext
22504
24194
  });
22505
- let streamText = "";
22506
- let hasToolCalls = false;
22507
- let eventCount = 0;
22508
- const logFile = process.env.GR_SSE_LOG;
22509
- const fs = logFile ? await import('fs') : null;
22510
- const logStream = logFile && fs ? fs.createWriteStream(logFile, { flags: "a" }) : null;
22511
- await aguiClient.sendMessage(
22512
- [{ role: "user", content: message }],
22513
- (event) => {
22514
- eventCount++;
22515
- if (logStream) logStream.write(JSON.stringify(event) + "\n");
22516
- const delta = getTextDelta(event);
22517
- if (delta) streamText += delta;
22518
- const type = event.type?.toLowerCase() ?? "";
22519
- if (type === "tool_call_start") {
22520
- hasToolCalls = true;
22521
- const name = event.name ?? "";
22522
- process.stderr.write(` [${name}]
22523
- `);
22524
- }
22525
- const errorMsg = getErrorMessage(event);
22526
- if (errorMsg) process.stderr.write(`\x1B[31mError: ${errorMsg}\x1B[0m
24195
+ const onEvent = (event) => {
24196
+ const type = event.type?.toLowerCase() ?? "";
24197
+ if (type === "tool_call_start") {
24198
+ const name = event.toolCallName ?? event.name ?? "";
24199
+ process.stderr.write(` [${name}]
22527
24200
  `);
22528
- },
22529
- { autoApprove }
24201
+ }
24202
+ };
24203
+ const { streamText, hasToolCalls } = await runConciergeAguiLoop(
24204
+ aguiClient,
24205
+ [{ role: "user", content: message }],
24206
+ onEvent,
24207
+ {
24208
+ autoApprove,
24209
+ allowWrite: allowWrite || !!session.allowWrite,
24210
+ trustCwd: session.trustCwd,
24211
+ trustDir: session.trustDir,
24212
+ nonInteractive: true
24213
+ }
22530
24214
  );
22531
- if (logStream) logStream.end();
22532
- if (debug) process.stderr.write(` (${eventCount} SSE events)
22533
- `);
22534
24215
  if (streamText) {
22535
24216
  process.stdout.write(`\x1B[32mAssistant:\x1B[0m ${streamText}
22536
24217
  `);
@@ -22564,13 +24245,16 @@ async function singleTurnChatSession(session, message, debug, autoApprove = fals
22564
24245
  `);
22565
24246
  }
22566
24247
  }
22567
- async function interactiveChatSession(session, debug) {
24248
+ async function interactiveChatSession(session, debug, autoApprove, allowWrite) {
22568
24249
  const aguiClient = new AGUIClient({
22569
24250
  baseUrl: session.ctx.envConfig.apiUrl,
24251
+ workspaceUuid: session.workspaceUuid,
24252
+ chatId: session.chatId,
22570
24253
  endpointUrl: session.aguiEndpointUrl,
22571
24254
  accessToken: session.ctx.accessToken,
22572
24255
  debug,
22573
- model: session.model
24256
+ model: session.model,
24257
+ appContext: session.appContext
22574
24258
  });
22575
24259
  clearScreen();
22576
24260
  console.log("=".repeat(60));
@@ -22599,7 +24283,7 @@ async function interactiveChatSession(session, debug) {
22599
24283
  }
22600
24284
  }
22601
24285
  const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
22602
- return new Promise((resolve) => {
24286
+ return new Promise((resolve2) => {
22603
24287
  const prompt = () => {
22604
24288
  rl.question("\x1B[34mYou:\x1B[0m ", async (input) => {
22605
24289
  const trimmed = input.trim();
@@ -22616,18 +24300,34 @@ async function interactiveChatSession(session, debug) {
22616
24300
  process.stdout.write("\n\x1B[32mAssistant:\x1B[0m ");
22617
24301
  let assistantContent = "";
22618
24302
  try {
22619
- await aguiClient.sendMessage(conversationMessages, (event) => {
22620
- const delta = getTextDelta(event);
22621
- if (delta) {
22622
- process.stdout.write(delta);
22623
- assistantContent += delta;
22624
- }
22625
- const errorMsg = getErrorMessage(event);
22626
- if (errorMsg) console.log(`
24303
+ const { streamText } = await runConciergeAguiLoop(
24304
+ aguiClient,
24305
+ conversationMessages,
24306
+ (event) => {
24307
+ const delta = getTextDelta(event);
24308
+ if (delta) {
24309
+ process.stdout.write(delta);
24310
+ assistantContent += delta;
24311
+ }
24312
+ const errorMsg = getErrorMessage(event);
24313
+ if (errorMsg) console.log(`
22627
24314
  \x1B[31mError: ${errorMsg}\x1B[0m`);
22628
- });
22629
- if (assistantContent)
24315
+ },
24316
+ {
24317
+ autoApprove,
24318
+ allowWrite: allowWrite || !!session.allowWrite,
24319
+ debug,
24320
+ trustCwd: session.trustCwd,
24321
+ trustDir: session.trustDir
24322
+ }
24323
+ );
24324
+ if (streamText && !assistantContent) {
24325
+ assistantContent = streamText;
24326
+ process.stdout.write(streamText);
24327
+ }
24328
+ if (assistantContent) {
22630
24329
  conversationMessages.push({ role: "assistant", content: assistantContent });
24330
+ }
22631
24331
  console.log("\n");
22632
24332
  } catch (error) {
22633
24333
  console.log(
@@ -22641,7 +24341,7 @@ async function interactiveChatSession(session, debug) {
22641
24341
  };
22642
24342
  rl.on("close", () => {
22643
24343
  console.log("\nGoodbye!");
22644
- resolve();
24344
+ resolve2();
22645
24345
  });
22646
24346
  prompt();
22647
24347
  });
@@ -22738,8 +24438,8 @@ async function realtimeChatSession(session, vad, debug) {
22738
24438
  });
22739
24439
  tui.loadHistory(history);
22740
24440
  tui.start();
22741
- await new Promise((resolve) => {
22742
- client.once("closed", resolve);
24441
+ await new Promise((resolve2) => {
24442
+ client.once("closed", resolve2);
22743
24443
  });
22744
24444
  }
22745
24445
  async function voiceChatSession(session, vad, args, debug) {
@@ -22856,8 +24556,8 @@ Connecting to ${session.label.toLowerCase()}...
22856
24556
  tui.loadHistory(history);
22857
24557
  tui.start();
22858
24558
  mic.start(inputDeviceId);
22859
- await new Promise((resolve) => {
22860
- client.once("closed", resolve);
24559
+ await new Promise((resolve2) => {
24560
+ client.once("closed", resolve2);
22861
24561
  });
22862
24562
  }
22863
24563
  async function listAudioDevices() {
@@ -22887,13 +24587,14 @@ async function conciergeCommand(hctx) {
22887
24587
  const chatIdArg = typeof args["chat-id"] === "string" ? args["chat-id"] : void 0;
22888
24588
  const message = typeof args.message === "string" ? args.message : void 0;
22889
24589
  const chat = await getOrCreateConciergeChat(ctx, chatIdArg, !!message);
22890
- const session = buildConciergeSession(ctx, chat);
24590
+ const session = buildConciergeSession(ctx, chat, args);
22891
24591
  await runChatSession(session, args);
22892
24592
  }
22893
- function buildConciergeSession(ctx, chat) {
24593
+ function buildConciergeSession(ctx, chat, args) {
22894
24594
  const wsBase = ctx.envConfig.apiUrl.replace(/^https:/, "wss:").replace(/^http:/, "ws:");
22895
24595
  return {
22896
24596
  ctx,
24597
+ workspaceUuid: "",
22897
24598
  chatId: chat.id,
22898
24599
  chatUuid: chat.uuid,
22899
24600
  chatTitle: chat.title || chat.uuid,
@@ -22901,8 +24602,12 @@ function buildConciergeSession(ctx, chat) {
22901
24602
  wsUrl: `${wsBase}/api/v2/concierge/voice/stream-ws`,
22902
24603
  loadMessages: () => getConciergeChatMessages(ctx, chat.id).catch(() => []),
22903
24604
  label: "Concierge",
22904
- model: void 0
24605
+ model: void 0,
22905
24606
  // concierge doesn't send model field
24607
+ appContext: buildCliConciergeAppContext(),
24608
+ allowWrite: true,
24609
+ trustCwd: !!args["trust-cwd"],
24610
+ trustDir: typeof args["trust-dir"] === "string" ? args["trust-dir"] : void 0
22906
24611
  };
22907
24612
  }
22908
24613
  async function getOrCreateConciergeChat(ctx, chatIdArg, skipSelection) {
@@ -22937,6 +24642,95 @@ async function getOrCreateConciergeChat(ctx, chatIdArg, skipSelection) {
22937
24642
  }
22938
24643
  return selectedChat;
22939
24644
  }
24645
+
24646
+ // src/commands/get-started.ts
24647
+ var WEB_SETUP = "https://app.gravityrail.com/setup";
24648
+ var WEB_GET_STARTED = "https://app.gravityrail.com/get-started";
24649
+ var HUMAN_GUIDE = `Gravity Rail \u2014 getting started
24650
+
24651
+ 1. Authenticate: gr login --env prod
24652
+ Confirm: gr whoami
24653
+
24654
+ 2. Recommended path \u2014 concierge (no workspace required):
24655
+ gr concierge chat --allow-write
24656
+ The concierge can create your org (auto-created on first login), list products,
24657
+ start Stripe checkout, and create your first workspace.
24658
+
24659
+ 3. Verify workspaces: gr workspaces list
24660
+
24661
+ 4. Web wizards (human-friendly): ${WEB_SETUP} and ${WEB_GET_STARTED}
24662
+
24663
+ Headless boundary: Stripe checkout needs a human in a browser \u2014 the concierge returns
24664
+ a checkout URL; an agent should hand that link to the user, not loop on payment.
24665
+
24666
+ Agent-readable steps: gr get-started --format llm
24667
+ `;
24668
+ var LLM_GUIDE = `# Gravity Rail CLI bootstrap (agent instructions)
24669
+
24670
+ ## Preconditions
24671
+ - Install: \`npm install -g @gravity-rail/cli\` or \`npx @gravity-rail/cli\`
24672
+ - Authenticate: \`gr login --env prod\` (interactive OAuth). Verify with \`gr whoami\`.
24673
+ - **Monorepo dev:** from gravity-team with Docker dev up, use \`yarn gr <cmd> --realm superadmin\` (reads \`dev-realms.json\`; no browser). Rebuild: \`yarn workspace @gravity-rail/gr-cli build\`.
24674
+
24675
+ ## Important facts
24676
+ - **Agents/CI:** do not leave stdin open on read-only commands; use \`GRAVITY_RAIL_API_KEY\` or redirect stdin from /dev/null. Commands only read stdin when \`--data\`/\`--file\` is passed.
24677
+ - Use \`--env dev|staging|prod\` (default prod) so credentials match the target; \`gr whoami\` shows the active env.
24678
+ - After login, an **organization is created automatically** \u2014 do not create a duplicate org unless \`gr organizations list\` is empty.
24679
+ - **Workspace is required** for workflow/agent/task commands (\`-w <workspace-uuid>\`).
24680
+ - **Concierge does not require \`-w\`** \u2014 use it for first-run setup.
24681
+
24682
+ ## Recommended path (concierge-driven)
24683
+ \`\`\`bash
24684
+ gr concierge chat --allow-write --message "Help me set up my first Gravity Rail workspace"
24685
+ \`\`\`
24686
+ Flags for unattended turns:
24687
+ - \`--message\` / \`-m\`: single-turn (non-interactive)
24688
+ - \`--auto-approve\`: skip HITL tool approval where policy allows
24689
+ - \`--allow-write\`: required for create/update tools
24690
+
24691
+ The concierge can: list/create orgs, list org/workspace products, create Stripe checkout sessions, create workspace specs, and \`create_workspace\`.
24692
+
24693
+ ## Manual CLI path (if not using concierge)
24694
+ 1. \`gr whoami\` \u2014 confirm account
24695
+ 2. \`gr organizations list\` \u2014 note org slug/UUID
24696
+ 3. \`gr concierge chat\` OR web: ${WEB_GET_STARTED}
24697
+ 4. Product purchase: concierge returns Stripe checkout URL \u2192 **human must complete in browser**
24698
+ 5. \`gr workspaces list\` \u2014 pick workspace UUID for \`-w\`
24699
+
24700
+ ## Support (account-level, no workspace)
24701
+ \`\`\`bash
24702
+ gr support create --type question --title "..." --description "..." --allow-write
24703
+ gr support list
24704
+ \`\`\`
24705
+
24706
+ ## Web fallbacks
24707
+ - Concierge / setup: ${WEB_SETUP}
24708
+ - Wizard: ${WEB_GET_STARTED}
24709
+
24710
+ ## Headless limits (do not retry forever)
24711
+ - Stripe payment / checkout: requires human browser
24712
+ - OAuth login: requires human browser
24713
+ - Directory trust for future local-file tools: use \`--trust-cwd\` only after user confirms files are safe
24714
+
24715
+ ## Local project files (CLI only)
24716
+ After directory trust + \`--allow-write\`, the concierge can use \`read_local_file\`, \`list_local_dir\`, \`write_local_file\` (client-executed via HITL).
24717
+
24718
+ ## Verify success
24719
+ \`gr workspaces list\` then \`gr workflows list -w <uuid>\` or \`gr agents list -w <uuid>\`
24720
+ `;
24721
+ async function getStartedCommand(hctx) {
24722
+ const format = hctx.args.format ?? hctx.args.agent;
24723
+ const isLlm = format === "llm" || format === "agent" || hctx.args["format"] === "llm" || !!hctx.args.agent;
24724
+ if (!isLlm) {
24725
+ try {
24726
+ requireAuth(hctx.ctx);
24727
+ } catch {
24728
+ }
24729
+ process.stdout.write(HUMAN_GUIDE);
24730
+ return;
24731
+ }
24732
+ process.stdout.write(LLM_GUIDE);
24733
+ }
22940
24734
  async function devImportLocalCommand(ctx, workspace) {
22941
24735
  stderr2(`Exporting workspace ${workspace}...`);
22942
24736
  const exportData = await ctx.apiClient.exportWorkspace(workspace);
@@ -23015,8 +24809,17 @@ async function manageCommand(hctx) {
23015
24809
  const chatIdArg = typeof args["chat-id"] === "string" ? args["chat-id"] : void 0;
23016
24810
  const message = typeof args.message === "string" ? args.message : void 0;
23017
24811
  const chat = await getOrCreateChat(ctx, workspace, chatIdArg, asMember, "manager", !!message);
23018
- const session = buildWorkspaceSession(ctx, workspace, chat, "Workspace Manager");
24812
+ const session = buildWorkspaceSession(ctx, workspace, chat, "Workspace Manager", {
24813
+ appContext: buildCliConciergeAppContext(),
24814
+ allowWrite: true,
24815
+ trustCwd: !!args["trust-cwd"],
24816
+ trustDir: typeof args["trust-dir"] === "string" ? args["trust-dir"] : void 0
24817
+ });
24818
+ process.stderr.write(`Chat #${session.chatId}
24819
+ `);
23019
24820
  await runChatSession(session, args);
24821
+ process.stderr.write(`Chat #${session.chatId}
24822
+ `);
23020
24823
  }
23021
24824
  async function chatCommand(hctx) {
23022
24825
  const ctx = requireAuth(hctx.ctx);
@@ -23041,10 +24844,11 @@ async function chatCommand(hctx) {
23041
24844
  const session = buildWorkspaceSession(ctx, workspace, chat, "Chat");
23042
24845
  await runChatSession(session, args);
23043
24846
  }
23044
- function buildWorkspaceSession(ctx, workspace, chat, label) {
24847
+ function buildWorkspaceSession(ctx, workspace, chat, label, extra) {
23045
24848
  const wsBase = ctx.envConfig.apiUrl.replace(/^https:/, "wss:").replace(/^http:/, "ws:");
23046
24849
  return {
23047
24850
  ctx,
24851
+ workspaceUuid: workspace,
23048
24852
  chatId: chat.id,
23049
24853
  chatUuid: chat.uuid,
23050
24854
  chatTitle: chat.title || chat.uuid,
@@ -23052,7 +24856,8 @@ function buildWorkspaceSession(ctx, workspace, chat, label) {
23052
24856
  wsUrl: `${wsBase}/api/v2/w/${workspace}/realtime/stream-ws`,
23053
24857
  loadMessages: () => ctx.apiClient.getChatMessages(workspace, chat.id, 50).catch(() => []),
23054
24858
  label,
23055
- model: "manager"
24859
+ model: "manager",
24860
+ ...extra
23056
24861
  };
23057
24862
  }
23058
24863
  async function getOrCreateChat(ctx, workspace, chatIdArg, asMemberId, chatType, skipSelection = false) {
@@ -23134,7 +24939,7 @@ async function createMemberChat(apiClient, workspace, memberId) {
23134
24939
  }
23135
24940
 
23136
24941
  // src/commands/organizations.ts
23137
- var COLUMNS33 = [
24942
+ var COLUMNS34 = [
23138
24943
  { header: "NAME", getValue: (o) => o.organizationName || "", maxWidth: 35 },
23139
24944
  { header: "SLUG", getValue: (o) => o.organizationSlug || "", maxWidth: 25 },
23140
24945
  { header: "UUID", getValue: (o) => o.organizationUuid },
@@ -23142,24 +24947,28 @@ var COLUMNS33 = [
23142
24947
  ];
23143
24948
  async function organizationsListCommand(ctx) {
23144
24949
  const organizations = await ctx.apiClient.getMyOrganizations();
23145
- outputData(organizations, ctx, COLUMNS33);
24950
+ outputData(organizations, ctx, COLUMNS34);
23146
24951
  }
23147
24952
 
23148
24953
  // src/commands/whoami.ts
23149
- var COLUMNS34 = [
24954
+ var COLUMNS35 = [
23150
24955
  { header: "NAME", getValue: (a) => a.name || "", maxWidth: 30 },
23151
24956
  { header: "EMAIL", getValue: (a) => a.email || "", maxWidth: 40 },
23152
24957
  { header: "UUID", getValue: (a) => a.uuid },
24958
+ { header: "ENV", getValue: () => "" },
23153
24959
  { header: "SUPERUSER", getValue: (a) => a.isSuperuser ? "yes" : "no" }
23154
24960
  ];
23155
24961
  async function whoamiCommand(ctx) {
23156
24962
  const account = await ctx.apiClient.getUserAccount();
23157
- outputSingle(account, ctx, COLUMNS34);
24963
+ const columns = COLUMNS35.map(
24964
+ (col) => col.header === "ENV" ? { ...col, getValue: () => ctx.env } : col
24965
+ );
24966
+ outputSingle(account, ctx, columns);
23158
24967
  }
23159
24968
 
23160
24969
  // package.json
23161
24970
  var package_default = {
23162
- version: "0.4.0"};
24971
+ version: "0.5.1"};
23163
24972
 
23164
24973
  // src/gr.ts
23165
24974
  var VERSION = package_default.version;
@@ -23212,6 +25021,15 @@ function createRegistry() {
23212
25021
  name: "auto-approve",
23213
25022
  description: "Auto-approve all tool calls (skip HITL)",
23214
25023
  isFlag: true
25024
+ },
25025
+ {
25026
+ name: "trust-cwd",
25027
+ description: "Trust files in the current working directory (non-interactive)",
25028
+ isFlag: true
25029
+ },
25030
+ {
25031
+ name: "trust-dir",
25032
+ description: "Trust files in this directory (non-interactive; absolute path)"
23215
25033
  }
23216
25034
  ],
23217
25035
  handler: async (hctx) => {
@@ -23245,6 +25063,37 @@ function createRegistry() {
23245
25063
  await chatCommand(hctx);
23246
25064
  }
23247
25065
  });
25066
+ registry.registerCommand({
25067
+ path: ["get-started"],
25068
+ description: "Bootstrap instructions for new users and LLM agents",
25069
+ requiresAuth: false,
25070
+ args: [
25071
+ {
25072
+ name: "format",
25073
+ description: "Output format: llm (agent-readable) or default (human)"
25074
+ },
25075
+ {
25076
+ name: "agent",
25077
+ description: "Alias for --format llm",
25078
+ isFlag: true
25079
+ }
25080
+ ],
25081
+ handler: async (hctx) => {
25082
+ await getStartedCommand(hctx);
25083
+ }
25084
+ });
25085
+ registry.registerCommand({
25086
+ path: ["setup"],
25087
+ description: "Alias for get-started \u2014 bootstrap instructions",
25088
+ requiresAuth: false,
25089
+ args: [
25090
+ { name: "format", description: "Output format: llm or default" },
25091
+ { name: "agent", description: "Alias for --format llm", isFlag: true }
25092
+ ],
25093
+ handler: async (hctx) => {
25094
+ await getStartedCommand(hctx);
25095
+ }
25096
+ });
23248
25097
  registry.registerCommand({
23249
25098
  path: ["concierge", "chat"],
23250
25099
  description: "Interactive concierge chat (text, realtime, or voice)",
@@ -23264,6 +25113,15 @@ function createRegistry() {
23264
25113
  name: "auto-approve",
23265
25114
  description: "Auto-approve all tool calls (skip HITL)",
23266
25115
  isFlag: true
25116
+ },
25117
+ {
25118
+ name: "trust-cwd",
25119
+ description: "Trust files in the current working directory (non-interactive)",
25120
+ isFlag: true
25121
+ },
25122
+ {
25123
+ name: "trust-dir",
25124
+ description: "Trust files in this directory (non-interactive; absolute path)"
23267
25125
  }
23268
25126
  ],
23269
25127
  handler: async (hctx) => {
@@ -23302,6 +25160,7 @@ function createRegistry() {
23302
25160
  return registry;
23303
25161
  }
23304
25162
  function parseGlobalOptions(argv) {
25163
+ let env = "prod";
23305
25164
  let apiUrl;
23306
25165
  let outputFormat;
23307
25166
  let verbose = false;
@@ -23311,6 +25170,13 @@ function parseGlobalOptions(argv) {
23311
25170
  let collectingCommand = true;
23312
25171
  for (let i = 0; i < argv.length; i++) {
23313
25172
  const arg = argv[i];
25173
+ const eqIdx = arg.indexOf("=");
25174
+ const flagPart = eqIdx !== -1 ? arg.slice(0, eqIdx) : arg;
25175
+ const inlineValue = eqIdx !== -1 ? arg.slice(eqIdx + 1) : void 0;
25176
+ if (flagPart === "--env" && (inlineValue ?? argv[i + 1])) {
25177
+ env = inlineValue ?? argv[++i];
25178
+ continue;
25179
+ }
23314
25180
  if (arg === "--api-url" && argv[i + 1]) {
23315
25181
  apiUrl = argv[++i];
23316
25182
  continue;
@@ -23338,7 +25204,7 @@ function parseGlobalOptions(argv) {
23338
25204
  rest.unshift(commandWords.pop());
23339
25205
  }
23340
25206
  return {
23341
- opts: { apiUrl, outputFormat, verbose, allowWrite },
25207
+ opts: { env, apiUrl, outputFormat, verbose, allowWrite },
23342
25208
  commandWords,
23343
25209
  rest
23344
25210
  };
@@ -23387,7 +25253,8 @@ async function main() {
23387
25253
  process.stderr.write("Error: --workspace (-w) is required\n");
23388
25254
  process.exit(1);
23389
25255
  }
23390
- const data = await readJsonInput(parsedArgs);
25256
+ const acceptsJsonInput = cmd.args?.some((a) => a.name === "data" || a.name === "file");
25257
+ const data = acceptsJsonInput ? await readJsonInput(parsedArgs) : void 0;
23391
25258
  hctx = { ctx, args: parsedArgs, workspace, data };
23392
25259
  } else {
23393
25260
  const baseCtx = createPublicContext(opts);
@@ -23406,7 +25273,7 @@ async function main() {
23406
25273
  }
23407
25274
  await cmd.handler(hctx);
23408
25275
  if (process.stdout.writableNeedDrain) {
23409
- await new Promise((resolve) => process.stdout.once("drain", resolve));
25276
+ await new Promise((resolve2) => process.stdout.once("drain", resolve2));
23410
25277
  }
23411
25278
  process.exit(0);
23412
25279
  }