@gravity-rail/cli 0.7.2 → 0.7.3

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,18 +1,22 @@
1
1
  #!/usr/bin/env node
2
- import { createRequire } from 'module';
2
+ import { createRequire } from 'node:module';
3
+ import { fileURLToPath } from 'node:url';
4
+ import { dirname } from 'node:path';
3
5
  import fs, { readFileSync, existsSync, mkdirSync, writeFileSync, createWriteStream, chmodSync, unlinkSync } from 'fs';
4
- import path3, { join, resolve, dirname } from 'path';
6
+ import path3, { join, resolve, dirname as dirname$1 } from 'path';
5
7
  import { createServer } from 'http';
6
8
  import { randomBytes, createHash } from 'crypto';
7
9
  import { execSync, execFile, exec, spawn, spawnSync } from 'child_process';
8
10
  import * as readline from 'readline';
9
11
  import readline__default from 'readline';
10
12
  import os, { homedir } from 'os';
11
- import * as readline6 from 'readline/promises';
13
+ import * as readline5 from 'readline/promises';
12
14
  import { stdout, stdin } from 'process';
13
15
  import { EventEmitter } from 'events';
14
16
 
15
17
  const require$1 = createRequire(import.meta.url);
18
+ const __filename$1 = fileURLToPath(import.meta.url);
19
+ dirname(__filename$1);
16
20
 
17
21
  var __create = Object.create;
18
22
  var __defProp = Object.defineProperty;
@@ -73,6 +77,16 @@ function handleError(err) {
73
77
  process.stderr.write(
74
78
  `
75
79
  Hint: Run "gr login" to authenticate, or set GRAVITY_RAIL_API_KEY for non-interactive use.
80
+ `
81
+ );
82
+ }
83
+ if ("statusCode" in err && err.statusCode === 403 && process.env.GRAVITY_RAIL_SANDBOX === "1") {
84
+ process.stderr.write(
85
+ `
86
+ Hint: This is a write/admin operation and the sandbox token lacks the required scope.
87
+ Re-run the exec tool with the needed write scope, e.g.:
88
+ exec(code="<your gr command>", language="bash", scopes=["datatypes:write"])
89
+ Common scopes: datatypes:write, workflows:write, members:write, automations:admin, agents:write
76
90
  `
77
91
  );
78
92
  }
@@ -2671,7 +2685,7 @@ var init_libphonenumber_js = __esm({
2671
2685
  }
2672
2686
  });
2673
2687
 
2674
- // ../sdk/dist/chunk-WXSLDWIA.js
2688
+ // ../sdk/dist/chunk-YCASSXLL.js
2675
2689
  function getCookieValue(name) {
2676
2690
  if (typeof document === "undefined") return void 0;
2677
2691
  const cookies = document.cookie.split(";");
@@ -2725,6 +2739,41 @@ function sanitizePhoneForBackend(phoneNumber) {
2725
2739
  }
2726
2740
  return phoneNumber;
2727
2741
  }
2742
+ function isUuid(value) {
2743
+ return /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(value);
2744
+ }
2745
+ async function dataToBytes(data) {
2746
+ if (typeof data === "string") {
2747
+ return new TextEncoder().encode(data);
2748
+ }
2749
+ if (data instanceof Uint8Array) {
2750
+ return data;
2751
+ }
2752
+ if (data instanceof ArrayBuffer) {
2753
+ return new Uint8Array(data);
2754
+ }
2755
+ if (ArrayBuffer.isView(data)) {
2756
+ return new Uint8Array(data.buffer, data.byteOffset, data.byteLength);
2757
+ }
2758
+ if (typeof Blob !== "undefined" && data instanceof Blob) {
2759
+ return new Uint8Array(await data.arrayBuffer());
2760
+ }
2761
+ throw new Error("Unsupported file data type");
2762
+ }
2763
+ function bytesToBase64(bytes) {
2764
+ if (typeof btoa === "function") {
2765
+ const chunkSize = 32768;
2766
+ let binary = "";
2767
+ for (let i = 0; i < bytes.length; i += chunkSize) {
2768
+ binary += String.fromCharCode(...bytes.subarray(i, i + chunkSize));
2769
+ }
2770
+ return btoa(binary);
2771
+ }
2772
+ if (typeof Buffer !== "undefined") {
2773
+ return Buffer.from(bytes).toString("base64");
2774
+ }
2775
+ throw new Error("No base64 encoder is available in this runtime");
2776
+ }
2728
2777
  function getOAuthPath(providerSlug, action) {
2729
2778
  if (providerSlug === "google_calendar") {
2730
2779
  return `oauth/google/calendar/${action}`;
@@ -2822,6 +2871,22 @@ function createApiModules(apiKey, baseUrl3, customFetch) {
2822
2871
  workspaces: new WorkspacesApi(apiKey, baseUrl3, customFetch)
2823
2872
  };
2824
2873
  }
2874
+ function createWorkspaceClient(root, workspaceUuid) {
2875
+ return new Proxy(
2876
+ { root, workspaceUuid },
2877
+ {
2878
+ get(target, prop, receiver) {
2879
+ if (prop in target) return Reflect.get(target, prop, receiver);
2880
+ if (typeof prop !== "string" || !WORKSPACE_METHOD_NAME_SET.has(prop)) {
2881
+ return void 0;
2882
+ }
2883
+ const value = root[prop];
2884
+ if (typeof value !== "function") return void 0;
2885
+ return (...args) => value.call(root, workspaceUuid, ...args);
2886
+ }
2887
+ }
2888
+ );
2889
+ }
2825
2890
  function bindAccessGrantsMethods(target, accessGrants) {
2826
2891
  target.getMyReceivedGrants = accessGrants.getMyReceivedGrants.bind(accessGrants);
2827
2892
  target.getMyGivenGrants = accessGrants.getMyGivenGrants.bind(accessGrants);
@@ -2846,6 +2911,7 @@ function bindAgentsMethods(target, agents) {
2846
2911
  target.deleteAgent = agents.deleteAgent.bind(agents);
2847
2912
  target.archiveAgent = agents.archiveAgent.bind(agents);
2848
2913
  target.unarchiveAgent = agents.unarchiveAgent.bind(agents);
2914
+ target.resolveAgentTools = agents.resolveAgentTools.bind(agents);
2849
2915
  }
2850
2916
  function bindTasksMethods(target, tasks, abilities) {
2851
2917
  target.getTasks = tasks.getTasks.bind(tasks);
@@ -2904,6 +2970,7 @@ function bindChatsMethods(target, chats) {
2904
2970
  target.getChatFilterCount = chats.getChatFilterCount.bind(chats);
2905
2971
  }
2906
2972
  function bindCallsMethods(target, calls, cel) {
2973
+ target.getPhoneCalls = calls.getPhoneCalls.bind(calls);
2907
2974
  target.initiateCall = calls.initiateCall.bind(calls);
2908
2975
  target.getVoiceToken = calls.getVoiceToken.bind(calls);
2909
2976
  target.getMessageTiming = calls.getMessageTiming.bind(calls);
@@ -2912,6 +2979,7 @@ function bindCallsMethods(target, calls, cel) {
2912
2979
  function bindDataTypesMethods(target, dataTypes) {
2913
2980
  target.getDataTypes = dataTypes.getDataTypes.bind(dataTypes);
2914
2981
  target.getDataType = dataTypes.getDataType.bind(dataTypes);
2982
+ target.getDataTypeByUuid = dataTypes.getDataTypeByUuid.bind(dataTypes);
2915
2983
  target.getDataTypeBySlug = dataTypes.getDataTypeBySlug.bind(dataTypes);
2916
2984
  target.createDataType = dataTypes.createDataType.bind(dataTypes);
2917
2985
  target.updateDataType = dataTypes.updateDataType.bind(dataTypes);
@@ -3138,6 +3206,7 @@ function bindFilesMethods(target, files) {
3138
3206
  target.getFiles = files.getFiles.bind(files);
3139
3207
  target.getFile = files.getFile.bind(files);
3140
3208
  target.createFile = files.createFile.bind(files);
3209
+ target.uploadFile = files.uploadFile.bind(files);
3141
3210
  target.updateFile = files.updateFile.bind(files);
3142
3211
  target.deleteFile = files.deleteFile.bind(files);
3143
3212
  target.convertFile = files.convertFile.bind(files);
@@ -3642,6 +3711,10 @@ function bindJourneysMethods(target, journeys) {
3642
3711
  target.reenrollMember = journeys.reenrollMember.bind(journeys);
3643
3712
  target.deleteEnrollment = journeys.deleteEnrollment.bind(journeys);
3644
3713
  target.getMemberJourneys = journeys.getMemberJourneys.bind(journeys);
3714
+ target.getStepMembers = journeys.getStepMembers.bind(journeys);
3715
+ target.getStepMemberCounts = journeys.getStepMemberCounts.bind(journeys);
3716
+ target.advanceStep = journeys.advanceStep.bind(journeys);
3717
+ target.skipStep = journeys.skipStep.bind(journeys);
3645
3718
  target.testRunJourney = journeys.testRunJourney.bind(journeys);
3646
3719
  target.getJourneyNotes = journeys.getJourneyNotes.bind(journeys);
3647
3720
  target.createJourneyNote = journeys.createJourneyNote.bind(journeys);
@@ -3711,9 +3784,9 @@ function bindSupportRequestMethods(target, supportRequests) {
3711
3784
  target.closeWorkspaceSupportRequest = supportRequests.closeWorkspaceSupportRequest.bind(supportRequests);
3712
3785
  target.clickWorkspaceSupportRequestResource = supportRequests.clickWorkspaceSupportRequestResource.bind(supportRequests);
3713
3786
  }
3714
- var ApiError, BaseApiClient, AbilitiesApi, AccessGrantsApi, AgentTasksApi, AgentsApi, AIModelsApi, ApiKeysApi, AppsApi, AssignmentsApi, VoiceApi, AuthApi, BuildersApi, CalendarsApi, CallsApi, CELApi, ChatsApi, ConfluenceApi, CustomToolkitsApi, DataTypesApi, DiscordBotsApi, SlackAppsApi, EventsApi, FeaturesApi, FhirConnectionsApi, HealthieApi, FilesApi, InboxesApi, InquiriesApi, AppConnectionsApi, McpServersApi, MembersApi, MilestonesApi, MondayIntegrationApi, NotificationRulesApi, OperatorApi, OrgApi, OAuthConnectionsApi, OAuthApi, PhoneNumbersApi, PronunciationsApi, PromptsApi, PersonasApi, QualificationsApi, ReportsApi, SalesforceApi, ConnectionSyncApi, HubspotApi, SitesApi, SubscriptionsApi, SupportRequestsApi, CustomersApi, ResellersApi, SupervisorsApi, TasksApi, TemplatesApi, ToolkitsApi, JourneysApi, WorkflowsApi, WorkflowNotesApi, EventRuleEventType, WorkspaceInvitationsApi, WorkspacesApi, TeamsAppsApi, ExperimentsApi, GravityRailClient, CHAT_TYPES, BUILTIN_ASSISTANT_CHAT_TYPES;
3715
- var init_chunk_WXSLDWIA = __esm({
3716
- "../sdk/dist/chunk-WXSLDWIA.js"() {
3787
+ var ApiError, BaseApiClient, AbilitiesApi, AccessGrantsApi, AgentTasksApi, AgentsApi, AIModelsApi, ApiKeysApi, AppsApi, AssignmentsApi, VoiceApi, AuthApi, BuildersApi, CalendarsApi, CallsApi, CELApi, ChatsApi, ConfluenceApi, CustomToolkitsApi, DataTypesApi, DiscordBotsApi, SlackAppsApi, EventsApi, FeaturesApi, FhirConnectionsApi, HealthieApi, FilesApi, InboxesApi, InquiriesApi, AppConnectionsApi, McpServersApi, MembersApi, MilestonesApi, MondayIntegrationApi, NotificationRulesApi, OperatorApi, OrgApi, OAuthConnectionsApi, OAuthApi, PhoneNumbersApi, PronunciationsApi, PromptsApi, PersonasApi, QualificationsApi, ReportsApi, SalesforceApi, ConnectionSyncApi, HubspotApi, SitesApi, SubscriptionsApi, SupportRequestsApi, CustomersApi, ResellersApi, SupervisorsApi, TasksApi, TemplatesApi, ToolkitsApi, JourneysApi, WorkflowsApi, WorkflowNotesApi, EventRuleEventType, WorkspaceInvitationsApi, WorkspacesApi, TeamsAppsApi, ExperimentsApi, WORKSPACE_METHOD_NAMES, WORKSPACE_METHOD_NAME_SET, GravityRailClient, CHAT_TYPES, BUILTIN_ASSISTANT_CHAT_TYPES;
3788
+ var init_chunk_YCASSXLL = __esm({
3789
+ "../sdk/dist/chunk-YCASSXLL.js"() {
3717
3790
  init_libphonenumber_js();
3718
3791
  ApiError = class extends Error {
3719
3792
  statusCode;
@@ -4285,6 +4358,13 @@ ${formattedErrors}`, response.status);
4285
4358
  method: "POST"
4286
4359
  });
4287
4360
  }
4361
+ /** Resolve runtime tools for an agent on a simulated channel. */
4362
+ async resolveAgentTools(wid, id, options) {
4363
+ const params = new URLSearchParams();
4364
+ params.append("channel", options.channel);
4365
+ params.append("taskId", options.taskId.toString());
4366
+ return this.fetch(`w/${wid}/agents/${id}/resolve-tools?${params}`);
4367
+ }
4288
4368
  };
4289
4369
  AIModelsApi = class extends BaseApiClient {
4290
4370
  /**
@@ -5187,6 +5267,23 @@ ${formattedErrors}`, response.status);
5187
5267
  }
5188
5268
  };
5189
5269
  CallsApi = class extends BaseApiClient {
5270
+ /** List workspace phone calls with optional filtering. */
5271
+ async getPhoneCalls(wid, options = {}) {
5272
+ const params = new URLSearchParams();
5273
+ if (options.page) params.set("page", String(options.page));
5274
+ if (options.pageSize) params.set("pageSize", String(options.pageSize));
5275
+ if (options.phoneNumberId !== void 0)
5276
+ params.set("phoneNumberId", String(options.phoneNumberId));
5277
+ if (options.chatId !== void 0) params.set("chatId", String(options.chatId));
5278
+ if (options.workflowId !== void 0) params.set("workflowId", String(options.workflowId));
5279
+ if (options.status) params.set("status", options.status);
5280
+ if (options.inbound !== void 0) params.set("inbound", String(options.inbound));
5281
+ if (options.dateFrom) params.set("dateFrom", options.dateFrom);
5282
+ if (options.dateTo) params.set("dateTo", options.dateTo);
5283
+ return this.fetch(
5284
+ `w/${wid}/calls${params.toString() ? `?${params.toString()}` : ""}`
5285
+ );
5286
+ }
5190
5287
  /** Initiate a new outbound call. */
5191
5288
  async initiateCall(wid, request) {
5192
5289
  return this.fetch(`w/${wid}/call`, {
@@ -5701,10 +5798,17 @@ ${formattedErrors}`, response.status);
5701
5798
  const queryString = params.toString();
5702
5799
  return this.fetch(`w/${wid}/data-types${queryString ? `?${queryString}` : ""}`);
5703
5800
  }
5704
- /** Get a single data type by ID. */
5801
+ /** Get a single data type by numeric ID, or by UUID when a UUID string is supplied. */
5705
5802
  async getDataType(wid, id) {
5803
+ if (typeof id === "string" && isUuid(id)) {
5804
+ return this.getDataTypeByUuid(wid, id);
5805
+ }
5706
5806
  return this.fetch(`w/${wid}/data-types/${id}`);
5707
5807
  }
5808
+ /** Get a single data type by UUID. */
5809
+ async getDataTypeByUuid(wid, uuid) {
5810
+ return this.fetch(`w/${wid}/data-types/${uuid}`);
5811
+ }
5708
5812
  /** Get a single data type by its slug. */
5709
5813
  async getDataTypeBySlug(wid, slug) {
5710
5814
  return this.fetch(`w/${wid}/data-types/slug/${slug}`);
@@ -6589,6 +6693,25 @@ ${formattedErrors}`, response.status);
6589
6693
  body: JSON.stringify(file)
6590
6694
  });
6591
6695
  }
6696
+ /** Upload in-memory file content through the API's database-backed file path. */
6697
+ async uploadFile(wid, request) {
6698
+ const mimeType = request.mimeType ?? "application/octet-stream";
6699
+ const bytes = await dataToBytes(request.data);
6700
+ return this.createFile(wid, {
6701
+ title: request.title ?? request.filename,
6702
+ filename: request.filename,
6703
+ description: request.description,
6704
+ mimeType,
6705
+ folderId: request.folderId,
6706
+ siteId: request.siteId,
6707
+ dataBase64: bytesToBase64(bytes),
6708
+ externalId: request.externalId,
6709
+ oauthCredentialUuid: request.oauthCredentialUuid,
6710
+ access: request.access,
6711
+ labelIds: request.labelIds,
6712
+ overwrite: request.overwrite
6713
+ });
6714
+ }
6592
6715
  /** Update an existing file's metadata. */
6593
6716
  async updateFile(wid, id, file) {
6594
6717
  return this.fetch(`w/${wid}/files/${id}`, {
@@ -9828,6 +9951,36 @@ ${formattedErrors}`, response.status);
9828
9951
  async getMemberJourneys(wid, memberId) {
9829
9952
  return this.fetch(`w/${wid}/journeys/by-member/${memberId}`);
9830
9953
  }
9954
+ /** List members currently or historically associated with one journey step. */
9955
+ async getStepMembers(wid, journeyId, stepUuid, params = {}) {
9956
+ const qs = new URLSearchParams();
9957
+ if (params.status) qs.set("status", params.status);
9958
+ if (params.mode) qs.set("mode", params.mode);
9959
+ if (params.page) qs.set("page", String(params.page));
9960
+ if (params.pageSize) qs.set("pageSize", String(params.pageSize));
9961
+ const query = qs.toString();
9962
+ return this.fetch(
9963
+ `w/${wid}/journeys/${journeyId}/steps/${stepUuid}/members${query ? `?${query}` : ""}`
9964
+ );
9965
+ }
9966
+ /** Get member counts by status for each journey step. */
9967
+ async getStepMemberCounts(wid, journeyId) {
9968
+ return this.fetch(`w/${wid}/journeys/${journeyId}/step-member-counts`);
9969
+ }
9970
+ /** Advance a journey step in the current execution context. */
9971
+ async advanceStep(wid, journeyId, stepUuid, data = {}) {
9972
+ return this.fetch(
9973
+ `w/${wid}/journeys/${journeyId}/steps/${stepUuid}/advance`,
9974
+ { method: "POST", body: JSON.stringify(data) }
9975
+ );
9976
+ }
9977
+ /** Skip a journey step in the current execution context. */
9978
+ async skipStep(wid, journeyId, stepUuid, data = {}) {
9979
+ return this.fetch(
9980
+ `w/${wid}/journeys/${journeyId}/steps/${stepUuid}/skip`,
9981
+ { method: "POST", body: JSON.stringify(data) }
9982
+ );
9983
+ }
9831
9984
  /**
9832
9985
  * Dry-run heartbeat CEL evaluation for an enrolled member.
9833
9986
  *
@@ -10795,6 +10948,696 @@ ${formattedErrors}`, response.status);
10795
10948
  );
10796
10949
  }
10797
10950
  };
10951
+ WORKSPACE_METHOD_NAMES = [
10952
+ "activateWorkflowVersion",
10953
+ "addGroupMember",
10954
+ "advanceStep",
10955
+ "approveWorkspaceInvitation",
10956
+ "archiveAgent",
10957
+ "archiveChat",
10958
+ "archiveDataType",
10959
+ "archiveJourney",
10960
+ "archiveMember",
10961
+ "archivePhoneNumber",
10962
+ "archiveStep",
10963
+ "archiveTask",
10964
+ "archiveWorkflow",
10965
+ "authorizeMondayConnection",
10966
+ "autoCreateDataTypeFromBoard",
10967
+ "blockWorkspaceInvitation",
10968
+ "bookHealthieAppointment",
10969
+ "buildWorkspace",
10970
+ "bulkLinkMembersToHubspot",
10971
+ "bulkLinkMembersToMonday",
10972
+ "bulkLinkMembersToSalesforce",
10973
+ "cancelAgentTask",
10974
+ "cancelAssignment",
10975
+ "cancelCalendarEvent",
10976
+ "cancelCredentialUpdateInvite",
10977
+ "checkAvailability",
10978
+ "checkSiteDomainAvailability",
10979
+ "checkSiteSlugAvailability",
10980
+ "clearConnectionMemberExclusion",
10981
+ "clearMemberSwitch",
10982
+ "clickWorkspaceSupportRequestResource",
10983
+ "cloneDataType",
10984
+ "cloneTask",
10985
+ "cloneWorkflow",
10986
+ "closeWorkspaceSupportRequest",
10987
+ "commentOnWorkspaceSupportRequest",
10988
+ "configureConfluence",
10989
+ "configureHealthie",
10990
+ "configureHubspot",
10991
+ "configureMondayConnection",
10992
+ "configureSalesforce",
10993
+ "convertEmail",
10994
+ "convertFile",
10995
+ "crawlSite",
10996
+ "createAccessGrant",
10997
+ "createAgent",
10998
+ "createApiKey",
10999
+ "createAssignment",
11000
+ "createCalendar",
11001
+ "createCalendarEvent",
11002
+ "createCalendarSchedule",
11003
+ "createChat",
11004
+ "createChatCompletion",
11005
+ "createChatFilter",
11006
+ "createChatLabel",
11007
+ "createClientWorkspace",
11008
+ "createConnection",
11009
+ "createCustomTool",
11010
+ "createCustomToolkit",
11011
+ "createDataRecord",
11012
+ "createDataType",
11013
+ "createDiscordBot",
11014
+ "createEventRule",
11015
+ "createEventType",
11016
+ "createExperiment",
11017
+ "createExperimentAssignment",
11018
+ "createExperimentGroup",
11019
+ "createFhirConnection",
11020
+ "createFile",
11021
+ "createFileLabel",
11022
+ "createFolder",
11023
+ "createGoal",
11024
+ "createInbox",
11025
+ "createJourney",
11026
+ "createJourneyNote",
11027
+ "createMcpServer",
11028
+ "createMemberField",
11029
+ "createMemberFilter",
11030
+ "createMemberLabel",
11031
+ "createMemberMemory",
11032
+ "createMemberRole",
11033
+ "createMenuItem",
11034
+ "createMilestone",
11035
+ "createNotificationRule",
11036
+ "createOperatorGroup",
11037
+ "createPage",
11038
+ "createPersona",
11039
+ "createPhoneNumber",
11040
+ "createProduct",
11041
+ "createRoutine",
11042
+ "createScenario",
11043
+ "createSignup",
11044
+ "createSite",
11045
+ "createSlackApp",
11046
+ "createSnippet",
11047
+ "createStep",
11048
+ "createSupervisor",
11049
+ "createTask",
11050
+ "createTeamsApp",
11051
+ "createWorkflow",
11052
+ "createWorkflowContributor",
11053
+ "createWorkflowFromTemplate",
11054
+ "createWorkflowNote",
11055
+ "createWorkflowOutboundVoiceChat",
11056
+ "createWorkspaceMember",
11057
+ "createWorkspaceSupportRequest",
11058
+ "deactivateWorkflowVersion",
11059
+ "deleteAgent",
11060
+ "deleteAssignment",
11061
+ "deleteCalendar",
11062
+ "deleteCalendarEvent",
11063
+ "deleteCalendarSchedule",
11064
+ "deleteChat",
11065
+ "deleteChatFilter",
11066
+ "deleteChatLabel",
11067
+ "deleteClientWorkspace",
11068
+ "deleteConfluence",
11069
+ "deleteConnection",
11070
+ "deleteCustomTool",
11071
+ "deleteCustomToolkit",
11072
+ "deleteDataRecord",
11073
+ "deleteDataType",
11074
+ "deleteDiscordBot",
11075
+ "deleteEnrollment",
11076
+ "deleteEventRule",
11077
+ "deleteEventType",
11078
+ "deleteExperiment",
11079
+ "deleteExperimentAssignment",
11080
+ "deleteExperimentGroup",
11081
+ "deleteFhirConnection",
11082
+ "deleteFile",
11083
+ "deleteFileLabel",
11084
+ "deleteFolder",
11085
+ "deleteGoal",
11086
+ "deleteHubspot",
11087
+ "deleteInbox",
11088
+ "deleteJourneyNote",
11089
+ "deleteMcpServer",
11090
+ "deleteMember",
11091
+ "deleteMemberField",
11092
+ "deleteMemberFilter",
11093
+ "deleteMemberLabel",
11094
+ "deleteMemberMemory",
11095
+ "deleteMemberRole",
11096
+ "deleteMenuItem",
11097
+ "deleteMilestone",
11098
+ "deleteMondayConnection",
11099
+ "deleteNotificationRule",
11100
+ "deleteOperatorGroup",
11101
+ "deletePage",
11102
+ "deletePersona",
11103
+ "deletePlatformApp",
11104
+ "deleteProduct",
11105
+ "deleteRoutine",
11106
+ "deleteSalesforce",
11107
+ "deleteScenario",
11108
+ "deleteSite",
11109
+ "deleteSlackApp",
11110
+ "deleteSnippet",
11111
+ "deleteSupervisor",
11112
+ "deleteTask",
11113
+ "deleteTeamsApp",
11114
+ "deleteWorkflow",
11115
+ "deleteWorkflowContributor",
11116
+ "deleteWorkflowNote",
11117
+ "deleteWorkspace",
11118
+ "deleteWorkspaceInvitationAdmin",
11119
+ "denyWorkspaceInvitation",
11120
+ "describeSalesforceObject",
11121
+ "diffWorkflowVersions",
11122
+ "disableConfluence",
11123
+ "disableCustomToolkit",
11124
+ "disableHubspot",
11125
+ "disableMcpServer",
11126
+ "disableMondayConnection",
11127
+ "disableSalesforce",
11128
+ "disconnectConfluence",
11129
+ "disconnectHubspot",
11130
+ "disconnectMondayConnection",
11131
+ "disconnectPresence",
11132
+ "disconnectSalesforce",
11133
+ "discoverOAuthMetadata",
11134
+ "dismissAllNotifications",
11135
+ "dismissNotification",
11136
+ "downloadEmailAttachment",
11137
+ "enableConfluence",
11138
+ "enableCustomToolkit",
11139
+ "enableHubspot",
11140
+ "enableMcpServer",
11141
+ "enableMondayConnection",
11142
+ "enablePlatformApp",
11143
+ "enableSalesforce",
11144
+ "endTestChatRun",
11145
+ "enrollMembers",
11146
+ "evaluateTestChatRun",
11147
+ "executeAssignmentTool",
11148
+ "expireAnonymousMember",
11149
+ "exportChat",
11150
+ "exportChats",
11151
+ "exportMembers",
11152
+ "exportWorkspace",
11153
+ "fetchVoicemailAudio",
11154
+ "fhirBackfillEncounterSync",
11155
+ "fhirCreateEncounter",
11156
+ "fhirCsvImportApply",
11157
+ "fhirCsvImportInspect",
11158
+ "fhirFetchCareTeam",
11159
+ "fhirFetchEncounters",
11160
+ "fhirGetCsvImportRunItems",
11161
+ "fhirGetCsvImportRuns",
11162
+ "fhirGetCsvImportSettings",
11163
+ "fhirGetEncounterSyncRuns",
11164
+ "fhirGetEncounterSyncStatus",
11165
+ "fhirImportPatient",
11166
+ "fhirLinkMember",
11167
+ "fhirListLinkedMembers",
11168
+ "fhirRefreshEncounterPatient",
11169
+ "fhirRunEncounterSync",
11170
+ "fhirSearchLocations",
11171
+ "fhirSearchPatients",
11172
+ "fhirSearchPractitioners",
11173
+ "fhirSyncMember",
11174
+ "fhirUnlinkMember",
11175
+ "fhirUpdateCsvImportSettings",
11176
+ "fhirUpdateEncounterSync",
11177
+ "findOrCreateDMChat",
11178
+ "generateFileUploadUrl",
11179
+ "generateICalToken",
11180
+ "generateSiteMediaUploadUrl",
11181
+ "getAIUsageReport",
11182
+ "getAbilityTypes",
11183
+ "getAccessGrant",
11184
+ "getAccessGrants",
11185
+ "getAgent",
11186
+ "getAgentTask",
11187
+ "getAgentTaskMessages",
11188
+ "getAgentTasks",
11189
+ "getAgents",
11190
+ "getAnonymousResolution",
11191
+ "getAnonymousResolutions",
11192
+ "getApiKeys",
11193
+ "getArchiveBlockers",
11194
+ "getAssignment",
11195
+ "getAssignmentCelContext",
11196
+ "getAssignmentMessages",
11197
+ "getAssignmentTask",
11198
+ "getAssignmentTaskDetail",
11199
+ "getAssignmentTools",
11200
+ "getAssignments",
11201
+ "getAvailableActions",
11202
+ "getAvailablePhoneNumbers",
11203
+ "getAvailableSlots",
11204
+ "getBoardColumns",
11205
+ "getBoardGroups",
11206
+ "getBoards",
11207
+ "getBusinessHoursStatus",
11208
+ "getCalendar",
11209
+ "getCalendarEvent",
11210
+ "getCalendarEvents",
11211
+ "getCalendarSchedules",
11212
+ "getCalendars",
11213
+ "getCelContext",
11214
+ "getChat",
11215
+ "getChatAssignmentTasks",
11216
+ "getChatEmails",
11217
+ "getChatFilter",
11218
+ "getChatFilterByUuid",
11219
+ "getChatFilterCount",
11220
+ "getChatFilters",
11221
+ "getChatLabel",
11222
+ "getChatLabelByUuid",
11223
+ "getChatLabels",
11224
+ "getChatMessages",
11225
+ "getChatPhoneCalls",
11226
+ "getChatSkills",
11227
+ "getChatTodos",
11228
+ "getChatTokenUsage",
11229
+ "getChatToolCallMessages",
11230
+ "getChatTools",
11231
+ "getChats",
11232
+ "getChatsDailyCreationStats",
11233
+ "getChatsNeedsResponse",
11234
+ "getClientWorkspace",
11235
+ "getConfluenceStatus",
11236
+ "getConnectionSyncCapabilities",
11237
+ "getConnectionSyncCheckpoint",
11238
+ "getConnectionSyncConfig",
11239
+ "getCredentialUpdateInvites",
11240
+ "getCurrentMember",
11241
+ "getCurrentUserInfo",
11242
+ "getCustomToolkit",
11243
+ "getCustomToolkits",
11244
+ "getDataRecord",
11245
+ "getDataRecordChanges",
11246
+ "getDataRecords",
11247
+ "getDataType",
11248
+ "getDataTypeByUuid",
11249
+ "getDataTypeBySlug",
11250
+ "getDataTypes",
11251
+ "getDiscordBot",
11252
+ "getDiscordBotAccounts",
11253
+ "getDiscordBotByUuid",
11254
+ "getDiscordBots",
11255
+ "getDiscordGuilds",
11256
+ "getDiscordThreads",
11257
+ "getEventRule",
11258
+ "getEventRules",
11259
+ "getEventType",
11260
+ "getEventTypes",
11261
+ "getExperiment",
11262
+ "getExperimentStats",
11263
+ "getExperiments",
11264
+ "getFhirConnection",
11265
+ "getFhirConnectionByUuid",
11266
+ "getFhirConnections",
11267
+ "getFieldIndexStatus",
11268
+ "getFile",
11269
+ "getFileLabel",
11270
+ "getFileLabelByUuid",
11271
+ "getFileLabels",
11272
+ "getFileSharing",
11273
+ "getFiles",
11274
+ "getFirstRunState",
11275
+ "getFolder",
11276
+ "getFolderSharing",
11277
+ "getFolders",
11278
+ "getGoogleCalendarStatus",
11279
+ "getHealthieAvailableSlots",
11280
+ "getHealthieReconciliationMatches",
11281
+ "getHealthieStatus",
11282
+ "getHubspotContactProperties",
11283
+ "getHubspotManagedRules",
11284
+ "getHubspotReconciliationMatches",
11285
+ "getHubspotStatus",
11286
+ "getHubspotSyncLogs",
11287
+ "getHubspotTransformPresets",
11288
+ "getICalFeedUrl",
11289
+ "getInbox",
11290
+ "getInboxEmail",
11291
+ "getInboxEmails",
11292
+ "getInboxThreads",
11293
+ "getInboxes",
11294
+ "getJourney",
11295
+ "getJourneyHealth",
11296
+ "getJourneyMembers",
11297
+ "getJourneyNotes",
11298
+ "getJourneys",
11299
+ "getLinkablePhones",
11300
+ "getLinkedHealthieMembers",
11301
+ "getLinkedHubspotMembers",
11302
+ "getLinkedMondayMembers",
11303
+ "getLinkedRecords",
11304
+ "getLinkedSalesforceMembers",
11305
+ "getLiveOperators",
11306
+ "getMcpServer",
11307
+ "getMcpServerPrompts",
11308
+ "getMcpServerResources",
11309
+ "getMcpServerTools",
11310
+ "getMcpServers",
11311
+ "getMemberExperiments",
11312
+ "getMemberFieldDefinitions",
11313
+ "getMemberFields",
11314
+ "getMemberFilter",
11315
+ "getMemberFilterCount",
11316
+ "getMemberFilters",
11317
+ "getMemberGrants",
11318
+ "getMemberJourneys",
11319
+ "getMemberLabel",
11320
+ "getMemberLabelByUuid",
11321
+ "getMemberLabels",
11322
+ "getMemberMemories",
11323
+ "getMemberRecordCounts",
11324
+ "getMemberRole",
11325
+ "getMemberRoleByUuid",
11326
+ "getMemberRoles",
11327
+ "getMemberSyncSummary",
11328
+ "getMemberUsage",
11329
+ "getMembersMessageActivity",
11330
+ "getMenuItems",
11331
+ "getMessageTiming",
11332
+ "getMilestone",
11333
+ "getMilestones",
11334
+ "getMondayConnectionBoardColumns",
11335
+ "getMondayConnectionBoardGroups",
11336
+ "getMondayConnectionBoards",
11337
+ "getMondayConnectionStatus",
11338
+ "getMondayReconciliationMatches",
11339
+ "getMondaySyncConfig",
11340
+ "getMyCredentials",
11341
+ "getMyGivenGrants",
11342
+ "getMyReceivedGrants",
11343
+ "getNotification",
11344
+ "getNotificationRules",
11345
+ "getNotifications",
11346
+ "getOperatorChatMessages",
11347
+ "getOperatorGroup",
11348
+ "getOperatorGroups",
11349
+ "getOrCreateQualificationForWorkflow",
11350
+ "getOwnedMembers",
11351
+ "getPage",
11352
+ "getPageBySlug",
11353
+ "getPersona",
11354
+ "getPhoneCalls",
11355
+ "getPhoneNumber",
11356
+ "getPhoneNumberCalls",
11357
+ "getPhoneNumberMessages",
11358
+ "getPhoneNumberVoicemails",
11359
+ "getPhoneNumbers",
11360
+ "getPhoneUsageReport",
11361
+ "getPlatformApp",
11362
+ "getPresenceStatus",
11363
+ "getProducts",
11364
+ "getPublicFile",
11365
+ "getPublicFolder",
11366
+ "getPublicFolderFiles",
11367
+ "getPublicProducts",
11368
+ "getQualification",
11369
+ "getQualifications",
11370
+ "getResellerWorkspaces",
11371
+ "getRoutine",
11372
+ "getRoutineRuns",
11373
+ "getRoutines",
11374
+ "getRuleExecutions",
11375
+ "getSMSUsageReport",
11376
+ "getSalesforceReconciliationMatches",
11377
+ "getSalesforceStatus",
11378
+ "getSalesforceSyncConfig",
11379
+ "getScenario",
11380
+ "getSite",
11381
+ "getSiteByUuid",
11382
+ "getSiteCounts",
11383
+ "getSiteMenu",
11384
+ "getSitePages",
11385
+ "getSiteRenderedMenu",
11386
+ "getSiteRenderedPage",
11387
+ "getSites",
11388
+ "getSlackApp",
11389
+ "getSlackAppAccounts",
11390
+ "getSlackApps",
11391
+ "getSlackInstallations",
11392
+ "getSlackThreads",
11393
+ "getSnippet",
11394
+ "getStepMemberCounts",
11395
+ "getStepMembers",
11396
+ "getSupervisor",
11397
+ "getSupervisors",
11398
+ "getSyncRunItems",
11399
+ "getSyncRuns",
11400
+ "getTask",
11401
+ "getTaskChats",
11402
+ "getTasks",
11403
+ "getTeamsApp",
11404
+ "getTeamsAppAccounts",
11405
+ "getTeamsApps",
11406
+ "getTeamsConversations",
11407
+ "getTeamsInstallations",
11408
+ "getTemplateContext",
11409
+ "getTestChatRun",
11410
+ "getThreadEmails",
11411
+ "getTool",
11412
+ "getToolCallNames",
11413
+ "getToolkits",
11414
+ "getUnreadNotificationCount",
11415
+ "getUsageDashboard",
11416
+ "getVariableRegistry",
11417
+ "getVoiceToken",
11418
+ "getVoiceUsageReport",
11419
+ "getWebhookLogs",
11420
+ "getWorkflow",
11421
+ "getWorkflowAccessValidation",
11422
+ "getWorkflowActivity",
11423
+ "getWorkflowConfigValidation",
11424
+ "getWorkflowContributors",
11425
+ "getWorkflowDeletionPreview",
11426
+ "getWorkflowDiagram",
11427
+ "getWorkflowNotes",
11428
+ "getWorkflowRouteDryRun",
11429
+ "getWorkflowTaskAssignmentStats",
11430
+ "getWorkflowTemplates",
11431
+ "getWorkflowThumbnailUrl",
11432
+ "getWorkflowVersion",
11433
+ "getWorkflowVersionActive",
11434
+ "getWorkflowVersions",
11435
+ "getWorkflows",
11436
+ "getWorkflowsActivityBatch",
11437
+ "getWorkspace",
11438
+ "getWorkspaceBuilder",
11439
+ "getWorkspaceBuilders",
11440
+ "getWorkspaceCounts",
11441
+ "getWorkspaceDefaults",
11442
+ "getWorkspaceEmailDomains",
11443
+ "getWorkspaceMember",
11444
+ "getWorkspaceMembers",
11445
+ "getWorkspaceNotices",
11446
+ "getWorkspaceProduct",
11447
+ "getWorkspaceSiteDomains",
11448
+ "getWorkspaceSubscriptions",
11449
+ "getWorkspaceSupportRequest",
11450
+ "getWorkspaceThemes",
11451
+ "importFromBoard",
11452
+ "importHubspotMembers",
11453
+ "importMembers",
11454
+ "importSalesforceMembers",
11455
+ "importWorkspace",
11456
+ "initiateCall",
11457
+ "initiateOutboundCall",
11458
+ "inspectPrompt",
11459
+ "inviteMemberCredentialUpdate",
11460
+ "inviteToWorkspace",
11461
+ "leaveWorkspace",
11462
+ "linkCalendarToGoogle",
11463
+ "linkCalendarToHealthie",
11464
+ "linkMemberToHealthie",
11465
+ "linkMemberToHubspot",
11466
+ "linkMemberToMonday",
11467
+ "linkMemberToSalesforce",
11468
+ "linkPhoneNumber",
11469
+ "listAppConnections",
11470
+ "listAvailableAppConnections",
11471
+ "listConfluencePages",
11472
+ "listConfluenceSpaces",
11473
+ "listConnectionMemberFieldKeys",
11474
+ "listGoogleCalendars",
11475
+ "listHealthieAppointmentTypes",
11476
+ "listHealthiePatients",
11477
+ "listHealthieProviders",
11478
+ "listPersonas",
11479
+ "listPushSubscriptions",
11480
+ "listScenarios",
11481
+ "listSnippets",
11482
+ "listTestChatRuns",
11483
+ "listWorkspaceInvitationsAdmin",
11484
+ "listWorkspaceSupportRequests",
11485
+ "markEmailAsRead",
11486
+ "markEmailAsUnread",
11487
+ "markNotificationAsRead",
11488
+ "previewImportWorkspace",
11489
+ "previewSchedule",
11490
+ "previewTTS",
11491
+ "previewTemplate",
11492
+ "previewThinkingSound",
11493
+ "previewWorkspaceImport",
11494
+ "provisionClientWorkspace",
11495
+ "publishWorkflowVersion",
11496
+ "rateMessage",
11497
+ "reenrollMember",
11498
+ "registerLinkedRolesMetadata",
11499
+ "registerPushSubscription",
11500
+ "registerSlashCommands",
11501
+ "reindexFolder",
11502
+ "releasePhoneNumber",
11503
+ "removeFileRole",
11504
+ "removeFolderRole",
11505
+ "removeGroupMember",
11506
+ "reorderEventRules",
11507
+ "reorderMenuItems",
11508
+ "replyToEmail",
11509
+ "requestPhoneNumber",
11510
+ "requestWorkspaceMembership",
11511
+ "resetRoutineRuns",
11512
+ "resolveAccessGrant",
11513
+ "resolveAgentTools",
11514
+ "resolveAnonymousMember",
11515
+ "revokeAccessGrant",
11516
+ "revokeApiKey",
11517
+ "revokeICalToken",
11518
+ "runRoutine",
11519
+ "searchEventRules",
11520
+ "searchFolder",
11521
+ "searchHubspotRecords",
11522
+ "searchSalesforceRecords",
11523
+ "selectCurrentAssignmentTask",
11524
+ "sendAssistantMessage",
11525
+ "sendChatMessage",
11526
+ "sendOperatorMessage",
11527
+ "siteGoogleOAuthInitiate",
11528
+ "siteSendEmailCode",
11529
+ "siteSendPhoneCode",
11530
+ "siteSignup",
11531
+ "siteVerifyCode",
11532
+ "skipStep",
11533
+ "startConfluenceOAuth",
11534
+ "startHubspotOAuth",
11535
+ "startSalesforceOAuth",
11536
+ "startSyncRun",
11537
+ "startTestChatRun",
11538
+ "summarizeChat",
11539
+ "switchMember",
11540
+ "syncCalendarWithGoogle",
11541
+ "syncCalendarWithHealthie",
11542
+ "testFhirConnection",
11543
+ "testMcpServerConnection",
11544
+ "testMondayConnection",
11545
+ "testRunJourney",
11546
+ "toggleFieldIndex",
11547
+ "unarchiveAgent",
11548
+ "unarchiveChat",
11549
+ "unarchiveDataType",
11550
+ "unarchiveMember",
11551
+ "unarchiveTask",
11552
+ "unarchiveWorkflow",
11553
+ "unenrollMembers",
11554
+ "unlinkCalendarFromGoogle",
11555
+ "unlinkCalendarFromHealthie",
11556
+ "unlinkCredential",
11557
+ "unlinkMemberFromHealthie",
11558
+ "unlinkMemberFromHubspot",
11559
+ "unlinkMemberFromMonday",
11560
+ "unlinkMemberFromSalesforce",
11561
+ "unregisterPushSubscription",
11562
+ "updateAgent",
11563
+ "updateAssignment",
11564
+ "updateCalendar",
11565
+ "updateCalendarEvent",
11566
+ "updateCalendarSchedule",
11567
+ "updateChat",
11568
+ "updateChatFilter",
11569
+ "updateChatLabel",
11570
+ "updateChatMute",
11571
+ "updateChatNeedsResponse",
11572
+ "updateClientWorkspace",
11573
+ "updateConnection",
11574
+ "updateConnectionSyncConfig",
11575
+ "updateCurrentMember",
11576
+ "updateCustomTool",
11577
+ "updateCustomToolkit",
11578
+ "updateDataRecord",
11579
+ "updateDataType",
11580
+ "updateDiscordBot",
11581
+ "updateEventAttendee",
11582
+ "updateEventRule",
11583
+ "updateEventType",
11584
+ "updateExperiment",
11585
+ "updateExperimentAssignment",
11586
+ "updateExperimentGroup",
11587
+ "updateFhirConnection",
11588
+ "updateFile",
11589
+ "updateFileLabel",
11590
+ "updateFileRoles",
11591
+ "updateFileSharing",
11592
+ "updateFirstRunState",
11593
+ "updateFolder",
11594
+ "updateFolderRoles",
11595
+ "updateFolderSharing",
11596
+ "updateGoal",
11597
+ "updateInbox",
11598
+ "updateJourney",
11599
+ "updateJourneyNote",
11600
+ "updateMcpServer",
11601
+ "updateMember",
11602
+ "updateMemberField",
11603
+ "updateMemberFilter",
11604
+ "updateMemberLabel",
11605
+ "updateMemberRole",
11606
+ "updateMenuItem",
11607
+ "updateMilestone",
11608
+ "updateMondaySyncConfig",
11609
+ "updateNotificationRule",
11610
+ "updateOperatorGroup",
11611
+ "updatePage",
11612
+ "updatePersona",
11613
+ "updatePhoneNumber",
11614
+ "updatePlatformApp",
11615
+ "updateProduct",
11616
+ "updateRoutine",
11617
+ "updateSalesforceSyncConfig",
11618
+ "updateScenario",
11619
+ "updateSite",
11620
+ "updateSlackApp",
11621
+ "updateSnippet",
11622
+ "updateStep",
11623
+ "updateSupervisor",
11624
+ "updateTask",
11625
+ "updateTeamsApp",
11626
+ "uploadFile",
11627
+ "updateVoicemailStatus",
11628
+ "updateWorkflow",
11629
+ "updateWorkflowContributor",
11630
+ "updateWorkflowNote",
11631
+ "updateWorkflowVersion",
11632
+ "updateWorkspace",
11633
+ "updateWorkspaceDefaults",
11634
+ "updateWorkspaceInvitationAdmin",
11635
+ "updateWorkspaceThemes",
11636
+ "upsertDataRecord",
11637
+ "validateDataTypeSlug",
11638
+ "validateWorkflowName"
11639
+ ];
11640
+ WORKSPACE_METHOD_NAME_SET = new Set(WORKSPACE_METHOD_NAMES);
10798
11641
  GravityRailClient = class {
10799
11642
  // WorkspaceInvitations is exposed publicly for backward compatibility
10800
11643
  workspaceInvitations;
@@ -10855,6 +11698,7 @@ ${formattedErrors}`, response.status);
10855
11698
  deleteChatFilter;
10856
11699
  getChatFilterCount;
10857
11700
  // Calls API
11701
+ getPhoneCalls;
10858
11702
  initiateCall;
10859
11703
  getVoiceToken;
10860
11704
  getMessageTiming;
@@ -10862,6 +11706,7 @@ ${formattedErrors}`, response.status);
10862
11706
  // Data Types API
10863
11707
  getDataTypes;
10864
11708
  getDataType;
11709
+ getDataTypeByUuid;
10865
11710
  getDataTypeBySlug;
10866
11711
  createDataType;
10867
11712
  updateDataType;
@@ -10946,6 +11791,7 @@ ${formattedErrors}`, response.status);
10946
11791
  deleteAgent;
10947
11792
  archiveAgent;
10948
11793
  unarchiveAgent;
11794
+ resolveAgentTools;
10949
11795
  // Qualifications API
10950
11796
  getQualifications;
10951
11797
  getQualification;
@@ -10988,6 +11834,10 @@ ${formattedErrors}`, response.status);
10988
11834
  reenrollMember;
10989
11835
  deleteEnrollment;
10990
11836
  getMemberJourneys;
11837
+ getStepMembers;
11838
+ getStepMemberCounts;
11839
+ advanceStep;
11840
+ skipStep;
10991
11841
  testRunJourney;
10992
11842
  getJourneyNotes;
10993
11843
  createJourneyNote;
@@ -11203,6 +12053,7 @@ ${formattedErrors}`, response.status);
11203
12053
  getFiles;
11204
12054
  getFile;
11205
12055
  createFile;
12056
+ uploadFile;
11206
12057
  updateFile;
11207
12058
  deleteFile;
11208
12059
  convertFile;
@@ -11738,6 +12589,20 @@ ${formattedErrors}`, response.status);
11738
12589
  bindResellersMethods(this, apis.resellers);
11739
12590
  bindSupportRequestMethods(this, apis.supportRequests);
11740
12591
  }
12592
+ /**
12593
+ * Return a workspace-scoped client facade.
12594
+ *
12595
+ * Methods on the returned client are the same public SDK methods, but with
12596
+ * the workspace UUID pre-bound:
12597
+ *
12598
+ * ```ts
12599
+ * const workspace = client.workspace("workspace-uuid");
12600
+ * await workspace.getAccessGrants({ status: "approved" });
12601
+ * ```
12602
+ */
12603
+ workspace(workspaceUuid) {
12604
+ return createWorkspaceClient(this, workspaceUuid);
12605
+ }
11741
12606
  /**
11742
12607
  * Set the handler for enhanced authentication requirements (RFC 9470 Step-Up Auth).
11743
12608
  * This handler is called when a 401 response includes WWW-Authenticate header
@@ -11850,10 +12715,23 @@ var init_chunk_QS6ZRQUZ = __esm({
11850
12715
  });
11851
12716
 
11852
12717
  // ../sdk/dist/index.js
12718
+ var SEARCHABLE_EVENT_RULE_SOURCE_FIELDS;
11853
12719
  var init_dist = __esm({
11854
12720
  "../sdk/dist/index.js"() {
11855
- init_chunk_WXSLDWIA();
12721
+ init_chunk_YCASSXLL();
11856
12722
  init_chunk_QS6ZRQUZ();
12723
+ SEARCHABLE_EVENT_RULE_SOURCE_FIELDS = [
12724
+ "taskId",
12725
+ "dataTypeId",
12726
+ "routineId",
12727
+ "workflowId",
12728
+ "journeyStepId"
12729
+ ];
12730
+ [
12731
+ ...SEARCHABLE_EVENT_RULE_SOURCE_FIELDS,
12732
+ "calendarId",
12733
+ "calendarEventTypeId"
12734
+ ];
11857
12735
  }
11858
12736
  });
11859
12737
  function detectWorktreePorts() {
@@ -11865,7 +12743,7 @@ function detectWorktreePorts() {
11865
12743
  overridePath = candidate;
11866
12744
  break;
11867
12745
  }
11868
- const parent = dirname(dir);
12746
+ const parent = dirname$1(dir);
11869
12747
  if (parent === dir) break;
11870
12748
  dir = parent;
11871
12749
  }
@@ -12468,46 +13346,6 @@ function formatTimestamp(isoString) {
12468
13346
  if (diff < 6048e5) return `${Math.floor(diff / 864e5)}d ago`;
12469
13347
  return date.toLocaleDateString();
12470
13348
  }
12471
- function wrapText(text, width = 70) {
12472
- const words = text.split(" ");
12473
- const lines = [];
12474
- let currentLine = "";
12475
- for (const word of words) {
12476
- if (currentLine.length + word.length + 1 <= width) {
12477
- currentLine += (currentLine ? " " : "") + word;
12478
- } else {
12479
- if (currentLine) lines.push(currentLine);
12480
- currentLine = word;
12481
- }
12482
- }
12483
- if (currentLine) lines.push(currentLine);
12484
- return lines;
12485
- }
12486
- function printMessage(content, role, indent = " ") {
12487
- const roleColors = {
12488
- user: "\x1B[34m",
12489
- // Blue
12490
- assistant: "\x1B[32m",
12491
- // Green
12492
- system: "\x1B[90m"
12493
- // Gray
12494
- };
12495
- const resetColor = "\x1B[0m";
12496
- const color = roleColors[role] || resetColor;
12497
- const label = role === "user" ? "You" : role === "assistant" ? "Assistant" : "System";
12498
- console.log(`${indent}${color}[${label}]${resetColor}`);
12499
- const lines = content.split("\n");
12500
- for (const line of lines) {
12501
- const wrapped = wrapText(line, 70);
12502
- for (const wrappedLine of wrapped) {
12503
- console.log(`${indent} ${wrappedLine}`);
12504
- }
12505
- }
12506
- console.log("");
12507
- }
12508
- function clearScreen() {
12509
- process.stdout.write("\x1B[2J\x1B[H");
12510
- }
12511
13349
  var NEW_ITEM_MARKER;
12512
13350
  var init_ui = __esm({
12513
13351
  "src/cli-utils/ui.ts"() {
@@ -16612,11 +17450,11 @@ var require_util2 = __commonJS({
16612
17450
  var { isUint8Array } = __require("util/types");
16613
17451
  var { webidl } = require_webidl();
16614
17452
  var supportedHashes = [];
16615
- var crypto;
17453
+ var crypto2;
16616
17454
  try {
16617
- crypto = __require("crypto");
17455
+ crypto2 = __require("crypto");
16618
17456
  const possibleRelevantHashes = ["sha256", "sha384", "sha512"];
16619
- supportedHashes = crypto.getHashes().filter((hash) => possibleRelevantHashes.includes(hash));
17457
+ supportedHashes = crypto2.getHashes().filter((hash) => possibleRelevantHashes.includes(hash));
16620
17458
  } catch {
16621
17459
  }
16622
17460
  function responseURL(response) {
@@ -16888,7 +17726,7 @@ var require_util2 = __commonJS({
16888
17726
  }
16889
17727
  }
16890
17728
  function bytesMatch(bytes, metadataList) {
16891
- if (crypto === void 0) {
17729
+ if (crypto2 === void 0) {
16892
17730
  return true;
16893
17731
  }
16894
17732
  const parsedMetadata = parseMetadata(metadataList);
@@ -16903,7 +17741,7 @@ var require_util2 = __commonJS({
16903
17741
  for (const item of metadata) {
16904
17742
  const algorithm = item.algo;
16905
17743
  const expectedValue = item.hash;
16906
- let actualValue = crypto.createHash(algorithm).update(bytes).digest("base64");
17744
+ let actualValue = crypto2.createHash(algorithm).update(bytes).digest("base64");
16907
17745
  if (actualValue[actualValue.length - 1] === "=") {
16908
17746
  if (actualValue[actualValue.length - 2] === "=") {
16909
17747
  actualValue = actualValue.slice(0, -2);
@@ -17961,8 +18799,8 @@ var require_body = __commonJS({
17961
18799
  var { multipartFormDataParser } = require_formdata_parser();
17962
18800
  var random;
17963
18801
  try {
17964
- const crypto = __require("crypto");
17965
- random = (max) => crypto.randomInt(0, max);
18802
+ const crypto2 = __require("crypto");
18803
+ random = (max) => crypto2.randomInt(0, max);
17966
18804
  } catch {
17967
18805
  random = (max) => Math.floor(Math.random(max));
17968
18806
  }
@@ -27210,7 +28048,7 @@ var require_util4 = __commonJS({
27210
28048
  var { serializeAMimeType, parseMIMEType } = require_data_url();
27211
28049
  var { types } = __require("util");
27212
28050
  var { StringDecoder } = __require("string_decoder");
27213
- var { btoa } = __require("buffer");
28051
+ var { btoa: btoa2 } = __require("buffer");
27214
28052
  var staticPropertyDescriptors = {
27215
28053
  enumerable: true,
27216
28054
  writable: false,
@@ -27302,9 +28140,9 @@ var require_util4 = __commonJS({
27302
28140
  dataURL += ";base64,";
27303
28141
  const decoder = new StringDecoder("latin1");
27304
28142
  for (const chunk of bytes) {
27305
- dataURL += btoa(decoder.write(chunk));
28143
+ dataURL += btoa2(decoder.write(chunk));
27306
28144
  }
27307
- dataURL += btoa(decoder.end());
28145
+ dataURL += btoa2(decoder.end());
27308
28146
  return dataURL;
27309
28147
  }
27310
28148
  case "Text": {
@@ -29290,13 +30128,13 @@ var require_frame = __commonJS({
29290
30128
  "../../node_modules/undici/lib/web/websocket/frame.js"(exports$1, module) {
29291
30129
  var { maxUnsigned16Bit } = require_constants5();
29292
30130
  var BUFFER_SIZE = 16386;
29293
- var crypto;
30131
+ var crypto2;
29294
30132
  var buffer = null;
29295
30133
  var bufIdx = BUFFER_SIZE;
29296
30134
  try {
29297
- crypto = __require("crypto");
30135
+ crypto2 = __require("crypto");
29298
30136
  } catch {
29299
- crypto = {
30137
+ crypto2 = {
29300
30138
  // not full compatibility, but minimum.
29301
30139
  randomFillSync: function randomFillSync(buffer2, _offset, _size) {
29302
30140
  for (let i = 0; i < buffer2.length; ++i) {
@@ -29309,7 +30147,7 @@ var require_frame = __commonJS({
29309
30147
  function generateMask() {
29310
30148
  if (bufIdx === BUFFER_SIZE) {
29311
30149
  bufIdx = 0;
29312
- crypto.randomFillSync(buffer ??= Buffer.allocUnsafe(BUFFER_SIZE), 0, BUFFER_SIZE);
30150
+ crypto2.randomFillSync(buffer ??= Buffer.allocUnsafe(BUFFER_SIZE), 0, BUFFER_SIZE);
29313
30151
  }
29314
30152
  return [buffer[bufIdx++], buffer[bufIdx++], buffer[bufIdx++], buffer[bufIdx++]];
29315
30153
  }
@@ -29380,9 +30218,9 @@ var require_connection = __commonJS({
29380
30218
  var { Headers: Headers2, getHeadersList } = require_headers();
29381
30219
  var { getDecodeSplit } = require_util2();
29382
30220
  var { WebsocketFrameSend } = require_frame();
29383
- var crypto;
30221
+ var crypto2;
29384
30222
  try {
29385
- crypto = __require("crypto");
30223
+ crypto2 = __require("crypto");
29386
30224
  } catch {
29387
30225
  }
29388
30226
  function establishWebSocketConnection(url, protocols, client, ws, onEstablish, options) {
@@ -29402,7 +30240,7 @@ var require_connection = __commonJS({
29402
30240
  const headersList = getHeadersList(new Headers2(options.headers));
29403
30241
  request.headersList = headersList;
29404
30242
  }
29405
- const keyValue = crypto.randomBytes(16).toString("base64");
30243
+ const keyValue = crypto2.randomBytes(16).toString("base64");
29406
30244
  request.headersList.append("sec-websocket-key", keyValue);
29407
30245
  request.headersList.append("sec-websocket-version", "13");
29408
30246
  for (const protocol of protocols) {
@@ -29432,7 +30270,7 @@ var require_connection = __commonJS({
29432
30270
  return;
29433
30271
  }
29434
30272
  const secWSAccept = response.headersList.get("Sec-WebSocket-Accept");
29435
- const digest = crypto.createHash("sha1").update(keyValue + uid).digest("base64");
30273
+ const digest = crypto2.createHash("sha1").update(keyValue + uid).digest("base64");
29436
30274
  if (secWSAccept !== digest) {
29437
30275
  failWebsocketConnection(ws, "Incorrect hash received in Sec-WebSocket-Accept header.");
29438
30276
  return;
@@ -31164,32 +32002,31 @@ function createPinnedFetch(apiUrl, apiIp) {
31164
32002
  }
31165
32003
  function withAuditHeaders(fetchFn, headers2) {
31166
32004
  const { chatId, sessionId, toolCallId } = headers2;
31167
- if (chatId === void 0 && !sessionId && !toolCallId) {
31168
- return fetchFn;
31169
- }
31170
32005
  return async (input2, init) => {
31171
32006
  const reqHeaders = new Headers(init?.headers);
32007
+ const dynamicToolCallId = globalThis.__GRAVITY_RAIL_TOOL_CALL_ID__ || (typeof process !== "undefined" ? process.env.GRAVITY_RAIL_TOOL_CALL_ID : void 0);
31172
32008
  if (chatId !== void 0) {
31173
32009
  reqHeaders.set("X-GR-Chat-Id", String(chatId));
31174
32010
  }
31175
32011
  if (sessionId) {
31176
32012
  reqHeaders.set("X-GR-Session-Id", sessionId);
31177
32013
  }
31178
- if (toolCallId) {
31179
- reqHeaders.set("X-GR-Tool-Call-Id", toolCallId);
32014
+ if (dynamicToolCallId || toolCallId) {
32015
+ reqHeaders.set("X-GR-Tool-Call-Id", dynamicToolCallId || toolCallId || "");
31180
32016
  }
31181
32017
  return fetchFn(input2, { ...init, headers: reqHeaders });
31182
32018
  };
31183
32019
  }
31184
32020
  function createSandboxFetchFromEnv(apiUrl) {
31185
- const apiIp = process.env.GRAVITY_RAIL_API_IP;
32021
+ const env = typeof process !== "undefined" ? process.env : {};
32022
+ const apiIp = env.GRAVITY_RAIL_API_IP;
31186
32023
  let fetchFn = createPinnedFetch(apiUrl, apiIp);
31187
- const chatIdRaw = process.env.GRAVITY_RAIL_CHAT_ID;
32024
+ const chatIdRaw = env.GRAVITY_RAIL_CHAT_ID;
31188
32025
  const chatId = chatIdRaw ? Number(chatIdRaw) : void 0;
31189
32026
  return withAuditHeaders(fetchFn, {
31190
32027
  chatId: chatId !== void 0 && Number.isFinite(chatId) ? chatId : void 0,
31191
- sessionId: process.env.GRAVITY_RAIL_SESSION_ID,
31192
- toolCallId: process.env.GRAVITY_RAIL_TOOL_CALL_ID
32028
+ sessionId: env.GRAVITY_RAIL_SESSION_ID,
32029
+ toolCallId: env.GRAVITY_RAIL_TOOL_CALL_ID
31193
32030
  });
31194
32031
  }
31195
32032
  var import_undici;
@@ -31410,7 +32247,7 @@ async function accountVerifyPhoneCommand(hctx) {
31410
32247
  );
31411
32248
  }
31412
32249
  async function promptLine(question) {
31413
- const rl = readline6.createInterface({ input: stdin, output: stdout });
32250
+ const rl = readline5.createInterface({ input: stdin, output: stdout });
31414
32251
  try {
31415
32252
  return await rl.question(question) ?? "";
31416
32253
  } finally {
@@ -31884,6 +32721,11 @@ var CommandRegistry = class {
31884
32721
  const key = cmd.path.join(" ");
31885
32722
  this.commands.set(key, cmd);
31886
32723
  }
32724
+ registerCommands(commands3) {
32725
+ for (const cmd of commands3) {
32726
+ this.registerCommand(cmd);
32727
+ }
32728
+ }
31887
32729
  /** Resolve command words to a CommandDef using longest-match.
31888
32730
  * Supports {param} path segments that match any word and extract as pathParams. */
31889
32731
  resolve(words) {
@@ -31916,6 +32758,7 @@ var CommandRegistry = class {
31916
32758
  }
31917
32759
  /** Generate help text. If prefix given, show commands under that prefix. */
31918
32760
  getHelp(prefix) {
32761
+ const inSandbox = process.env.GRAVITY_RAIL_SANDBOX === "1";
31919
32762
  if (!prefix || prefix.length === 0) {
31920
32763
  return this.getTopLevelHelp();
31921
32764
  }
@@ -31952,18 +32795,21 @@ var CommandRegistry = class {
31952
32795
  `, "Commands:"];
31953
32796
  for (const cmd of matching.sort((a, b) => a.path.join(" ").localeCompare(b.path.join(" ")))) {
31954
32797
  const subPath = cmd.path.slice(prefix.length).join(" ") || cmd.path[cmd.path.length - 1];
31955
- lines.push(` ${subPath.padEnd(28)} ${cmd.description}`);
32798
+ const description = inSandbox ? sandboxHelpText(cmd.description) : cmd.description;
32799
+ lines.push(` ${subPath.padEnd(28)} ${description}`);
31956
32800
  }
31957
32801
  return lines.join("\n") + "\n";
31958
32802
  }
31959
32803
  getCommandHelp(cmd) {
31960
32804
  const cmdStr = cmd.path.join(" ");
31961
- const lines = [`${cmd.description}
32805
+ const inSandbox = process.env.GRAVITY_RAIL_SANDBOX === "1";
32806
+ const description = inSandbox ? sandboxHelpText(cmd.description) : cmd.description;
32807
+ const lines = [`${description}
31962
32808
  `, `Usage: gr ${cmdStr} [options]`];
31963
- if (cmd.requiresWorkspace) {
32809
+ if (cmd.requiresWorkspace && !inSandbox) {
31964
32810
  lines.push(" Requires: -w <workspace-uuid> (or --realm <workspace>/<member> in dev)");
31965
32811
  }
31966
- if (cmd.mutates) {
32812
+ if (cmd.mutates && !inSandbox) {
31967
32813
  lines.push(" Requires: --allow-write");
31968
32814
  }
31969
32815
  const action = cmd.path[cmd.path.length - 1] ?? "";
@@ -31985,7 +32831,7 @@ var CommandRegistry = class {
31985
32831
  if (cmd.examples && cmd.examples.length > 0) {
31986
32832
  lines.push("", "Examples:");
31987
32833
  for (const ex of cmd.examples) {
31988
- lines.push(` ${ex}`);
32834
+ lines.push(` ${inSandbox ? sandboxExample(ex) : ex}`);
31989
32835
  }
31990
32836
  }
31991
32837
  return lines.join("\n") + "\n";
@@ -32000,38 +32846,50 @@ var CommandRegistry = class {
32000
32846
  }
32001
32847
  getTopLevelHelp() {
32002
32848
  const lines = ["Usage: gr <command> [options]\n", "Commands:"];
32849
+ const inSandbox = process.env.GRAVITY_RAIL_SANDBOX === "1";
32003
32850
  const seen = /* @__PURE__ */ new Set();
32004
32851
  for (const domain of this.domains) {
32005
32852
  if (!seen.has(domain.name)) {
32006
32853
  seen.add(domain.name);
32007
- lines.push(` ${domain.name.padEnd(28)} ${domain.description}`);
32854
+ const description = inSandbox ? sandboxHelpText(domain.description) : domain.description;
32855
+ lines.push(` ${domain.name.padEnd(28)} ${description}`);
32008
32856
  }
32009
32857
  }
32010
32858
  for (const [, cmd] of this.commands) {
32011
32859
  const topWord = cmd.path[0];
32012
32860
  if (!seen.has(topWord) && cmd.path.length === 1) {
32013
32861
  seen.add(topWord);
32014
- lines.push(` ${topWord.padEnd(28)} ${cmd.description}`);
32862
+ const description = inSandbox ? sandboxHelpText(cmd.description) : cmd.description;
32863
+ lines.push(` ${topWord.padEnd(28)} ${description}`);
32015
32864
  }
32016
32865
  }
32017
- lines.push(
32866
+ const globalOptions = [
32018
32867
  "",
32019
32868
  "Global Options:",
32020
- " --env <env> Environment: dev, staging, prod (default: dev)",
32021
- " --realm <ws>/<member> Dev auth shortcut (dev only; sets -w automatically)",
32022
- " --api-url <url> API base URL (or GRAVITY_RAIL_API_URL)",
32023
- " -w, --workspace <uuid> Workspace UUID",
32869
+ ...!inSandbox ? [
32870
+ " --env <env> Environment: dev, staging, prod (default: dev)",
32871
+ " --realm <ws>/<member> Dev auth shortcut (dev only; sets -w automatically)",
32872
+ " --api-url <url> API base URL (or GRAVITY_RAIL_API_URL)",
32873
+ " -w, --workspace <uuid> Workspace UUID"
32874
+ ] : [],
32024
32875
  " -d, --data <json> JSON body (create/update and other write commands)",
32025
32876
  " -f, --file <path> JSON body from file",
32026
- " --allow-write Required for create/update/delete/archive",
32877
+ ...!inSandbox ? [" --allow-write Required for create/update/delete/archive"] : [],
32027
32878
  " -o, --output-format <fmt> Output format: json, jsonl, table (default: auto)",
32028
32879
  " -v, --verbose Verbose output to stderr",
32029
32880
  " --help Show help",
32030
32881
  " --version Show version"
32031
- );
32882
+ ];
32883
+ lines.push(...globalOptions);
32032
32884
  return lines.join("\n") + "\n";
32033
32885
  }
32034
32886
  };
32887
+ function sandboxHelpText(text) {
32888
+ return text.replace(/\byarn gr\b/g, "gr").replace(/\s--allow-write\b/g, "").replace(/\s--realm\s+(?:"[^"]+"|'[^']+'|<[^>]+>|\S+)/g, "").replace(/\s-w\s+(?:"[^"]+"|'[^']+'|<[^>]+>|\S+)/g, "");
32889
+ }
32890
+ function sandboxExample(example) {
32891
+ return sandboxHelpText(example);
32892
+ }
32035
32893
 
32036
32894
  // src/lib/types.ts
32037
32895
  function requireString(args, key) {
@@ -32195,7 +33053,21 @@ var agentTasksDomain = {
32195
33053
 
32196
33054
  // src/domains/agents.ts
32197
33055
  init_output();
33056
+ init_context();
32198
33057
  var COLUMNS = [COL.id(), COL.uuid(), COL.name(), COL.status(), COL.created()];
33058
+ var TOOL_COLUMNS = [
33059
+ COL.name(),
33060
+ { header: "DESCRIPTION", getValue: (item) => (item.description ?? "").slice(0, 60) }
33061
+ ];
33062
+ function normalizeChannel(channel) {
33063
+ const aliases = {
33064
+ phone: "phone-voice",
33065
+ voice: "phone-voice",
33066
+ sms: "phone-sms",
33067
+ web: "web-chat"
33068
+ };
33069
+ return aliases[channel] ?? channel;
33070
+ }
32199
33071
  var agentsDomain = {
32200
33072
  name: "agents",
32201
33073
  description: "Manage agents",
@@ -32212,7 +33084,37 @@ var agentsDomain = {
32212
33084
  unarchiveMethod: "unarchiveAgent",
32213
33085
  columns: COLUMNS,
32214
33086
  paginationSupport: "full"
32215
- })
33087
+ }),
33088
+ {
33089
+ path: ["agents", "resolve-tools"],
33090
+ description: "Show resolved runtime tools for an agent in a channel context. Channel accepts canonical values (phone-voice, web-voice, phone-sms, web-chat) or shorthand aliases: phone -> phone-voice, voice -> phone-voice, sms -> phone-sms, web -> web-chat. Unknown values are passed through unchanged.",
33091
+ requiresWorkspace: true,
33092
+ args: [
33093
+ { name: "id", description: "Agent ID", required: true },
33094
+ {
33095
+ name: "channel",
33096
+ description: "Channel to simulate. Canonical: phone-voice, web-voice, phone-sms, web-chat. Aliases: phone|voice -> phone-voice, sms -> phone-sms, web -> web-chat.",
33097
+ required: true
33098
+ },
33099
+ {
33100
+ name: "task-id",
33101
+ description: "Task ID whose workflow abilities to resolve",
33102
+ required: true
33103
+ }
33104
+ ],
33105
+ handler: async ({ ctx, workspace, args }) => {
33106
+ const result2 = await requireAuth(ctx).apiClient.resolveAgentTools(
33107
+ workspace,
33108
+ requireNumber(args, "id"),
33109
+ {
33110
+ channel: normalizeChannel(String(args.channel)),
33111
+ taskId: requireNumber(args, "task-id")
33112
+ }
33113
+ );
33114
+ const tools = result2.tools ?? result2;
33115
+ outputData(Array.isArray(tools) ? tools : [tools], ctx, TOOL_COLUMNS);
33116
+ }
33117
+ }
32216
33118
  ]
32217
33119
  };
32218
33120
 
@@ -33985,7 +34887,7 @@ var MESSAGE_COLUMNS4 = [
33985
34887
  COL.created()
33986
34888
  ];
33987
34889
  var TASK_COLUMNS = [COL.id(), COL.name(), COL.status()];
33988
- var TOOL_COLUMNS = [
34890
+ var TOOL_COLUMNS2 = [
33989
34891
  COL.name(),
33990
34892
  { header: "DESCRIPTION", getValue: (item) => (item.description ?? "").slice(0, 60) }
33991
34893
  ];
@@ -34093,7 +34995,7 @@ var assignmentsDomain = {
34093
34995
  requireNumber(args, "assignment-id")
34094
34996
  );
34095
34997
  const tools = result2.tools ?? result2;
34096
- outputData(Array.isArray(tools) ? tools : [tools], ctx, TOOL_COLUMNS);
34998
+ outputData(Array.isArray(tools) ? tools : [tools], ctx, TOOL_COLUMNS2);
34097
34999
  }
34098
35000
  }
34099
35001
  ]
@@ -36530,6 +37432,7 @@ var accessGrantsDomain = {
36530
37432
  {
36531
37433
  path: ["access-grants", "resolve"],
36532
37434
  description: "Resolve an access grant",
37435
+ mutates: true,
36533
37436
  requiresWorkspace: true,
36534
37437
  args: [{ name: "id", description: "Access grant ID", required: true }],
36535
37438
  handler: async ({ ctx, workspace, args, data }) => {
@@ -37139,7 +38042,7 @@ init_errors();
37139
38042
  init_output();
37140
38043
  init_context();
37141
38044
  var COLUMNS17 = [COL.id(), COL.name(), COL.description(), COL.enabled()];
37142
- var TOOL_COLUMNS2 = [COL.id(), COL.name(), COL.description()];
38045
+ var TOOL_COLUMNS3 = [COL.id(), COL.name(), COL.description()];
37143
38046
  var customToolkitsDomain = {
37144
38047
  name: "custom-toolkits",
37145
38048
  description: "Manage custom toolkits and their tools",
@@ -37197,7 +38100,7 @@ var customToolkitsDomain = {
37197
38100
  toolkitId,
37198
38101
  data
37199
38102
  );
37200
- outputSingle(result2, ctx, TOOL_COLUMNS2);
38103
+ outputSingle(result2, ctx, TOOL_COLUMNS3);
37201
38104
  }
37202
38105
  },
37203
38106
  {
@@ -37219,7 +38122,7 @@ var customToolkitsDomain = {
37219
38122
  toolId,
37220
38123
  data
37221
38124
  );
37222
- outputSingle(result2, ctx, TOOL_COLUMNS2);
38125
+ outputSingle(result2, ctx, TOOL_COLUMNS3);
37223
38126
  }
37224
38127
  },
37225
38128
  {
@@ -38459,6 +39362,50 @@ function parseCallerRole(value) {
38459
39362
  }
38460
39363
  return VALID_CALLER_ROLES.has(value) ? value : void 0;
38461
39364
  }
39365
+ var PERMISSION_USE2 = 1;
39366
+ function evaluateWorkflowMemberRoleAccess(memberRoleId, memberRoleAccess) {
39367
+ if (memberRoleAccess === void 0) {
39368
+ return { outcome: "skip", detail: "workflow memberRoleAccess not available" };
39369
+ }
39370
+ if (memberRoleAccess.length === 0) {
39371
+ return { outcome: "allow", detail: "no workflow role restrictions configured" };
39372
+ }
39373
+ if (memberRoleId === void 0) {
39374
+ return {
39375
+ outcome: "skip",
39376
+ detail: "caller member role unknown \u2014 cannot evaluate role gate"
39377
+ };
39378
+ }
39379
+ const hasUse = memberRoleAccess.some(
39380
+ (entry) => entry.memberRoleId === memberRoleId && (entry.accessMode & PERMISSION_USE2) === PERMISSION_USE2
39381
+ );
39382
+ if (hasUse) {
39383
+ return { outcome: "allow", detail: `memberRoleId=${memberRoleId} has USE on workflow` };
39384
+ }
39385
+ return {
39386
+ outcome: "deny",
39387
+ detail: `memberRoleId=${memberRoleId} lacks USE in workflow memberRoleAccess`
39388
+ };
39389
+ }
39390
+ function parseWorkflowMemberRoleAccess(workflow) {
39391
+ const raw = workflow.memberRoleAccess;
39392
+ if (!Array.isArray(raw)) {
39393
+ return [];
39394
+ }
39395
+ const entries = [];
39396
+ for (const item of raw) {
39397
+ if (!item || typeof item !== "object") {
39398
+ continue;
39399
+ }
39400
+ const row = item;
39401
+ const memberRoleId = typeof row.memberRoleId === "number" ? row.memberRoleId : Number(row.memberRoleId);
39402
+ const accessMode = typeof row.accessMode === "number" ? row.accessMode : Number(row.accessMode);
39403
+ if (Number.isFinite(memberRoleId) && Number.isFinite(accessMode)) {
39404
+ entries.push({ memberRoleId, accessMode });
39405
+ }
39406
+ }
39407
+ return entries;
39408
+ }
38462
39409
  function inferCallerRole(phone, opts) {
38463
39410
  if (opts.asRole) {
38464
39411
  return opts.asRole;
@@ -38585,6 +39532,32 @@ function simulateInboundRouting(phone, opts = {}) {
38585
39532
  return finish("no_inbound_workflow", false, true, steps, recommendations, callerRole);
38586
39533
  }
38587
39534
  steps.push({ step: "inbound_workflow", outcome: "ok", detail: `workflowId=${workflowId}` });
39535
+ const callerMemberRoleId = callerRole === "member" ? opts.matchedMemberRoleId : callerRole === "anonymous" ? phone.anonymousMemberRoleId ?? void 0 : void 0;
39536
+ const roleAccess = evaluateWorkflowMemberRoleAccess(
39537
+ callerMemberRoleId,
39538
+ opts.workflowMemberRoleAccess
39539
+ );
39540
+ if (roleAccess.outcome === "deny") {
39541
+ steps.push({
39542
+ step: "workflow_member_role_access",
39543
+ outcome: "reject",
39544
+ detail: roleAccess.detail
39545
+ });
39546
+ recommendations.push(
39547
+ "Grant the caller's member role USE access on the inbound workflow (workflow memberRoleAccess or `gr member-roles update` workflowAccess)"
39548
+ );
39549
+ return finish("workflow_member_role_denied", false, true, steps, recommendations, callerRole);
39550
+ }
39551
+ steps.push({
39552
+ step: "workflow_member_role_access",
39553
+ outcome: roleAccess.outcome === "skip" ? "skipped" : "ok",
39554
+ detail: roleAccess.detail
39555
+ });
39556
+ if (roleAccess.outcome === "skip" && callerMemberRoleId === void 0 && opts.workflowMemberRoleAccess !== void 0 && opts.workflowMemberRoleAccess.length > 0) {
39557
+ recommendations.push(
39558
+ "Workflow has member role restrictions but caller memberRoleId was not resolved \u2014 re-run with --as +E.164 (caller phone) so the role gate can be evaluated against real data"
39559
+ );
39560
+ }
38588
39561
  steps.push({ step: "chat_create", outcome: "create_phone_voice_chat" });
38589
39562
  steps.push({ step: "assistant", outcome: "connect_media_stream" });
38590
39563
  return finish("ai_voice_chat", true, true, steps, recommendations, callerRole);
@@ -38601,6 +39574,7 @@ function finish(code, createsChat, createsPhoneCall, steps, recommendations, cal
38601
39574
  voicemail_record: "Record voicemail",
38602
39575
  play_message_hangup: "Play off-hours message, hang up",
38603
39576
  no_inbound_workflow: "Play unavailable message (no inbound workflow)",
39577
+ workflow_member_role_denied: "Reject \u2014 caller member role lacks workflow USE (memberRoleAccess)",
38604
39578
  ai_voice_chat: "Create chat + connect AI voice"
38605
39579
  };
38606
39580
  return {
@@ -38756,7 +39730,9 @@ function normalizeCallerE164(phone) {
38756
39730
  var MEMBER_SEARCH_PAGE_SIZE = 100;
38757
39731
  async function resolveMemberByCallerPhone(client, workspace, callerE164) {
38758
39732
  const normalized = normalizeCallerE164(callerE164);
38759
- const candidates = [normalized, callerE164.trim()].filter(
39733
+ const digits = callerE164.replace(/\D/g, "");
39734
+ const nsn = digits.length === 11 && digits.startsWith("1") ? digits.slice(1) : digits;
39735
+ const candidates = [normalized, callerE164.trim(), digits, nsn].filter(
38760
39736
  (v, i, arr) => Boolean(v) && arr.indexOf(v) === i
38761
39737
  );
38762
39738
  const matchInRows = (rows) => {
@@ -38801,6 +39777,25 @@ async function resolveMemberByCallerPhone(client, workspace, callerE164) {
38801
39777
  return void 0;
38802
39778
  }
38803
39779
 
39780
+ // src/lib/phone-numbers/workflow-role-access.ts
39781
+ async function loadInboundWorkflowMemberRoleAccess(client, workspace, defaultWorkflowId) {
39782
+ const workflowId = typeof defaultWorkflowId === "number" ? defaultWorkflowId : defaultWorkflowId === null || defaultWorkflowId === void 0 ? void 0 : Number(defaultWorkflowId);
39783
+ if (workflowId === void 0 || !Number.isFinite(workflowId)) {
39784
+ return void 0;
39785
+ }
39786
+ try {
39787
+ const workflow = await client.getWorkflow(workspace, workflowId);
39788
+ return parseWorkflowMemberRoleAccess(workflow);
39789
+ } catch (err) {
39790
+ const reason = err instanceof Error ? err.message : String(err);
39791
+ process.stderr.write(
39792
+ `[diagnose] Could not fetch workflow ${workflowId} memberRoleAccess \u2014 role gate will be skipped (${reason})
39793
+ `
39794
+ );
39795
+ return void 0;
39796
+ }
39797
+ }
39798
+
38804
39799
  // src/domains/phone-numbers.ts
38805
39800
  function asPhoneRecord(value) {
38806
39801
  return value;
@@ -38859,9 +39854,8 @@ var phoneNumbersDomain = {
38859
39854
  const client = requireAuth(ctx).apiClient;
38860
39855
  const id = requireNumber(args, "id");
38861
39856
  const phone = asPhoneRecord(await client.getPhoneNumber(workspace, id));
38862
- if (args.raw) {
38863
- process.stdout.write(`${JSON.stringify(phone, null, 2)}
38864
- `);
39857
+ if (args.raw || ctx.outputFormat !== "table") {
39858
+ outputSingle(phone, ctx);
38865
39859
  return;
38866
39860
  }
38867
39861
  const outboundUsers = await findOutboundPhoneUsers(client, workspace, phone);
@@ -39035,21 +40029,34 @@ Setup complete: id=${phone.id} uuid=${phone.uuid}
39035
40029
  const asRole = parseCallerRole(args["as-role"]);
39036
40030
  let hasMemberMatch = asRole === "member";
39037
40031
  let matchedMemberId;
40032
+ let matchedMemberRoleId;
39038
40033
  let matchedMemberPhoneType;
39039
40034
  if (!asRole && typeof args.as === "string") {
39040
40035
  const match = await resolveMemberByCallerPhone(client, workspace, args.as);
39041
40036
  if (match) {
39042
40037
  hasMemberMatch = true;
39043
40038
  matchedMemberId = match.memberId;
40039
+ matchedMemberRoleId = match.memberRoleId;
39044
40040
  matchedMemberPhoneType = match.phoneType;
39045
40041
  }
39046
40042
  }
40043
+ const workflowMemberRoleAccess = await loadInboundWorkflowMemberRoleAccess(
40044
+ client,
40045
+ workspace,
40046
+ phone.defaultWorkflowId
40047
+ );
39047
40048
  const sim = simulateInboundRouting(phone, {
39048
40049
  asRole,
39049
40050
  hasMemberMatch,
39050
40051
  matchedMemberId,
39051
- matchedMemberPhoneType
40052
+ matchedMemberRoleId,
40053
+ matchedMemberPhoneType,
40054
+ workflowMemberRoleAccess
39052
40055
  });
40056
+ if (ctx.outputFormat !== "table") {
40057
+ outputSingle({ phoneNumberId: id, simulation: sim }, ctx);
40058
+ return;
40059
+ }
39053
40060
  process.stdout.write(`${formatRoutingSimulation(sim, phone)}
39054
40061
  `);
39055
40062
  }
@@ -39071,10 +40078,28 @@ Setup complete: id=${phone.id} uuid=${phone.uuid}
39071
40078
  const id = requireNumber(args, "id");
39072
40079
  const role = requireCallerRole(args, "as-role");
39073
40080
  const phone = asPhoneRecord(await client.getPhoneNumber(workspace, id));
40081
+ const workflowMemberRoleAccess = await loadInboundWorkflowMemberRoleAccess(
40082
+ client,
40083
+ workspace,
40084
+ phone.defaultWorkflowId
40085
+ );
39074
40086
  const sim = simulateInboundRouting(phone, {
39075
40087
  asRole: role,
39076
- hasMemberMatch: role === "member"
40088
+ hasMemberMatch: role === "member",
40089
+ workflowMemberRoleAccess
39077
40090
  });
40091
+ if (ctx.outputFormat !== "table") {
40092
+ outputSingle(
40093
+ {
40094
+ phoneNumberId: id,
40095
+ callerRole: role,
40096
+ finalBehavior: sim.finalBehavior,
40097
+ simulation: sim
40098
+ },
40099
+ ctx
40100
+ );
40101
+ return;
40102
+ }
39078
40103
  process.stdout.write(
39079
40104
  `If a caller in role "${role}" dials this line right now:
39080
40105
  \u2192 ${sim.finalBehavior}
@@ -39100,17 +40125,26 @@ ${formatRoutingSimulation(sim, phone)}
39100
40125
  const asRole = parseCallerRole(args["as-role"]);
39101
40126
  let hasMemberMatch = asRole === "member";
39102
40127
  let matchedMemberId;
40128
+ let matchedMemberRoleId;
39103
40129
  if (!asRole && typeof args.as === "string") {
39104
40130
  const match = await resolveMemberByCallerPhone(client, workspace, args.as);
39105
40131
  if (match) {
39106
40132
  hasMemberMatch = true;
39107
40133
  matchedMemberId = match.memberId;
40134
+ matchedMemberRoleId = match.memberRoleId;
39108
40135
  }
39109
40136
  }
40137
+ const workflowMemberRoleAccess = await loadInboundWorkflowMemberRoleAccess(
40138
+ client,
40139
+ workspace,
40140
+ phone.defaultWorkflowId
40141
+ );
39110
40142
  const sim = simulateInboundRouting(phone, {
39111
40143
  asRole,
39112
40144
  hasMemberMatch,
39113
- matchedMemberId
40145
+ matchedMemberId,
40146
+ matchedMemberRoleId,
40147
+ workflowMemberRoleAccess
39114
40148
  });
39115
40149
  process.stdout.write(
39116
40150
  `${JSON.stringify({ phoneNumberId: id, simulation: sim }, null, 2)}
@@ -39154,11 +40188,15 @@ ${formatRoutingSimulation(sim, phone)}
39154
40188
  { inbound: true }
39155
40189
  );
39156
40190
  const inbound = result2.items ?? [];
39157
- process.stdout.write(`Inbound calls (most recent page): ${inbound.length} shown
40191
+ if (ctx.outputFormat === "table") {
40192
+ process.stdout.write(`Inbound calls (most recent page): ${inbound.length} shown
39158
40193
  `);
39159
- process.stdout.write(
39160
- "Tip: gr phone-numbers diagnose --id <id> --as +1\u2026 simulates routing without a live call.\n"
39161
- );
40194
+ process.stdout.write(
40195
+ "Tip: gr phone-numbers diagnose --id <id> --as +1\u2026 simulates routing without a live call.\n"
40196
+ );
40197
+ } else {
40198
+ stderr2(`Inbound calls (most recent page): ${inbound.length} shown`);
40199
+ }
39162
40200
  outputData(inbound, ctx);
39163
40201
  }
39164
40202
  },
@@ -41480,9 +42518,6 @@ function registerPublicDomains(registry) {
41480
42518
  registry.register(billingPortalDomain);
41481
42519
  }
41482
42520
 
41483
- // src/lib.ts
41484
- init_concierge_api();
41485
-
41486
42521
  // src/commands/auth-browser.ts
41487
42522
  init_output();
41488
42523
  async function authBrowserCommand(ctx, args) {
@@ -41527,11 +42562,10 @@ function openUrl(url) {
41527
42562
  });
41528
42563
  }
41529
42564
 
41530
- // src/commands/concierge.ts
42565
+ // src/commands/manage.ts
41531
42566
  init_cli_utils();
41532
- init_concierge_api();
41533
- init_context();
41534
42567
  init_errors();
42568
+ init_context();
41535
42569
  function buildCliConciergeAppContext() {
41536
42570
  const shell = process.env.SHELL ? path3.basename(process.env.SHELL) : void 0;
41537
42571
  return {
@@ -41841,13 +42875,19 @@ async function runConciergeAguiLoop(client, initialMessages, onEvent, opts) {
41841
42875
  if (!hitlPayload) {
41842
42876
  break;
41843
42877
  }
41844
- const next = await handleCliHitlInterrupt(hitlPayload, {
41845
- allowWrite: opts.allowWrite,
41846
- autoApprove: opts.autoApprove,
41847
- trustCwd: opts.trustCwd,
41848
- trustDir: opts.trustDir,
41849
- nonInteractive: opts.nonInteractive
41850
- });
42878
+ opts.onHitlPromptStart?.();
42879
+ let next;
42880
+ try {
42881
+ next = await handleCliHitlInterrupt(hitlPayload, {
42882
+ allowWrite: opts.allowWrite,
42883
+ autoApprove: opts.autoApprove,
42884
+ trustCwd: opts.trustCwd,
42885
+ trustDir: opts.trustDir,
42886
+ nonInteractive: opts.nonInteractive
42887
+ });
42888
+ } finally {
42889
+ opts.onHitlPromptEnd?.();
42890
+ }
41851
42891
  if (!next) {
41852
42892
  process.stderr.write(
41853
42893
  " [HITL] Unsupported interrupt in CLI \u2014 open app.gravityrail.com/setup to continue.\n"
@@ -42116,6 +43156,19 @@ function isToolCall(item) {
42116
43156
  function isToolResult(item) {
42117
43157
  return "kind" in item && item.kind === "tool_result";
42118
43158
  }
43159
+ function toolResultLooksFailed(content) {
43160
+ const trimmed = content.trim();
43161
+ if (!trimmed) return false;
43162
+ if (/^error[:\s]/i.test(trimmed)) return true;
43163
+ try {
43164
+ const parsed = JSON.parse(trimmed);
43165
+ if (parsed.ok === false) return true;
43166
+ if (typeof parsed.error === "string" && parsed.error.length > 0) return true;
43167
+ if (typeof parsed.status === "string" && parsed.status.toLowerCase() === "error") return true;
43168
+ } catch {
43169
+ }
43170
+ return false;
43171
+ }
42119
43172
  function getTruncationLabel(reason, truncatedAtMs) {
42120
43173
  const timeStr = truncatedAtMs ? ` at ${(truncatedAtMs / 1e3).toFixed(1)}s` : "";
42121
43174
  switch (reason) {
@@ -42149,6 +43202,8 @@ var CLEAR_EOL = `${CSI}K`;
42149
43202
  var RESET = `${CSI}0m`;
42150
43203
  var MOUSE_ON = `${CSI}?1000h${CSI}?1006h`;
42151
43204
  var MOUSE_OFF = `${CSI}?1000l${CSI}?1006l`;
43205
+ var BRACKETED_PASTE_ON = `${CSI}?2004h`;
43206
+ var BRACKETED_PASTE_OFF = `${CSI}?2004l`;
42152
43207
  var BLUE = `${CSI}34m`;
42153
43208
  var GREEN = `${CSI}32m`;
42154
43209
  var GRAY = `${CSI}90m`;
@@ -42157,6 +43212,11 @@ var ORANGE = `${CSI}38;5;208m`;
42157
43212
  var LIGHT_BLUE = `${CSI}38;5;117m`;
42158
43213
  var DIM = `${CSI}2m`;
42159
43214
  var DIM_ITALIC_GRAY = `${CSI}2;3;90m`;
43215
+ var RED = `${CSI}31m`;
43216
+ var CYAN = `${CSI}36m`;
43217
+ var MAX_INPUT_ROWS = 6;
43218
+ var INPUT_LABEL = "You: ";
43219
+ var INPUT_LABEL_WIDTH = 5;
42160
43220
  function moveTo(row, col) {
42161
43221
  return `${CSI}${row};${col}H`;
42162
43222
  }
@@ -42181,6 +43241,11 @@ var ChatTUI = class {
42181
43241
  // Escape sequence accumulator for raw stdin parsing
42182
43242
  escBuf = "";
42183
43243
  escTimer = null;
43244
+ // Run / inference status (title bar)
43245
+ runState = "idle";
43246
+ activeToolName = "";
43247
+ pausedForPrompt = false;
43248
+ turnInProgress = false;
42184
43249
  constructor(options) {
42185
43250
  this.options = options;
42186
43251
  this.debugPanelVisible = !!options.debug;
@@ -42192,8 +43257,8 @@ var ChatTUI = class {
42192
43257
  // ─── Lifecycle ──────────────────────────────────────────────────────
42193
43258
  start() {
42194
43259
  this.updateDimensions();
42195
- process.stdout.write(ALT_SCREEN_ON + MOUSE_ON);
42196
- process.stdout.write(`${CSI}1;${Math.max(1, this.rows - 2)}r`);
43260
+ process.stdout.write(ALT_SCREEN_ON + MOUSE_ON + BRACKETED_PASTE_ON);
43261
+ this.applyScrollRegion();
42197
43262
  process.stdin.setEncoding("utf8");
42198
43263
  if (process.stdin.isTTY) process.stdin.setRawMode(true);
42199
43264
  process.stdin.on("data", this.onData);
@@ -42236,6 +43301,7 @@ var ChatTUI = class {
42236
43301
  streamStart() {
42237
43302
  this.isStreaming = true;
42238
43303
  this.streamContent = "";
43304
+ this.runState = "streaming";
42239
43305
  this.scrollOffset = 0;
42240
43306
  this.dirty();
42241
43307
  }
@@ -42251,8 +43317,42 @@ var ChatTUI = class {
42251
43317
  this.streamContent = "";
42252
43318
  this.dirty();
42253
43319
  }
43320
+ runStarted() {
43321
+ this.turnInProgress = true;
43322
+ this.runState = "thinking";
43323
+ this.activeToolName = "";
43324
+ this.dirty();
43325
+ }
43326
+ runFinished() {
43327
+ this.turnInProgress = false;
43328
+ this.runState = "idle";
43329
+ this.activeToolName = "";
43330
+ this.dirty();
43331
+ }
43332
+ /** Temporarily leave alt-screen for an external prompt (HITL). */
43333
+ pauseForPrompt() {
43334
+ if (!this.started || this.pausedForPrompt) return;
43335
+ this.pausedForPrompt = true;
43336
+ process.stdin.removeListener("data", this.onData);
43337
+ if (process.stdin.isTTY) process.stdin.setRawMode(false);
43338
+ process.stdout.write(
43339
+ `${MOUSE_OFF}${BRACKETED_PASTE_OFF}${CSI}r${ALT_SCREEN_OFF}${SHOW_CURSOR}`
43340
+ );
43341
+ }
43342
+ /** Re-enter alt-screen after an external prompt. */
43343
+ resumeAfterPrompt() {
43344
+ if (!this.started || !this.pausedForPrompt) return;
43345
+ this.pausedForPrompt = false;
43346
+ process.stdout.write(ALT_SCREEN_ON + MOUSE_ON + BRACKETED_PASTE_ON);
43347
+ this.applyScrollRegion();
43348
+ if (process.stdin.isTTY) process.stdin.setRawMode(true);
43349
+ process.stdin.on("data", this.onData);
43350
+ this.render();
43351
+ }
42254
43352
  toolCallStart(id, name) {
42255
43353
  this.items.push({ kind: "tool_call", id, name, args: "", done: false });
43354
+ this.runState = "tool_running";
43355
+ this.activeToolName = name;
42256
43356
  this.dirty();
42257
43357
  }
42258
43358
  toolCallArgs(id, delta) {
@@ -42305,7 +43405,12 @@ var ChatTUI = class {
42305
43405
  this.dirty();
42306
43406
  }
42307
43407
  toolCallResult(toolCallId, toolName, content) {
42308
- this.items.push({ kind: "tool_result", toolCallId, toolName, content });
43408
+ const failed = toolResultLooksFailed(content);
43409
+ this.items.push({ kind: "tool_result", toolCallId, toolName, content, failed });
43410
+ if (!this.isStreaming) {
43411
+ this.runState = "thinking";
43412
+ this.activeToolName = "";
43413
+ }
42309
43414
  this.dirty();
42310
43415
  }
42311
43416
  /** Find the tool name for a given tool call ID */
@@ -42358,7 +43463,9 @@ var ChatTUI = class {
42358
43463
  this.scheduleRender();
42359
43464
  }
42360
43465
  restoreTerminal = () => {
42361
- process.stdout.write(`${MOUSE_OFF}${CSI}r${ALT_SCREEN_OFF}${SHOW_CURSOR}`);
43466
+ process.stdout.write(
43467
+ `${MOUSE_OFF}${BRACKETED_PASTE_OFF}${CSI}r${ALT_SCREEN_OFF}${SHOW_CURSOR}`
43468
+ );
42362
43469
  };
42363
43470
  updateDimensions() {
42364
43471
  this.rows = process.stdout.rows || 24;
@@ -42374,11 +43481,32 @@ var ChatTUI = class {
42374
43481
  if (!this.debugVisible) return 0;
42375
43482
  return this.cols - this.chatWidth() - 1;
42376
43483
  }
43484
+ titleRows() {
43485
+ return this.options.title || this.options.subtitle ? 1 : 0;
43486
+ }
43487
+ inputRows() {
43488
+ const lines = this.inputBuffer.split("\n").length;
43489
+ return Math.min(MAX_INPUT_ROWS, Math.max(1, lines));
43490
+ }
43491
+ footerRows() {
43492
+ return 1 + this.inputRows();
43493
+ }
43494
+ messageAreaTop() {
43495
+ return 1 + this.titleRows();
43496
+ }
43497
+ messageAreaBottom() {
43498
+ return this.rows - this.footerRows();
43499
+ }
43500
+ applyScrollRegion() {
43501
+ const top = this.messageAreaTop();
43502
+ const bottom = Math.max(top, this.messageAreaBottom());
43503
+ process.stdout.write(`${CSI}${top};${bottom}r`);
43504
+ }
42377
43505
  scrollHeight() {
42378
- return Math.max(1, this.rows - 2);
43506
+ return Math.max(1, this.messageAreaBottom() - this.messageAreaTop() + 1);
42379
43507
  }
42380
43508
  pageSize() {
42381
- return Math.max(1, this.rows - 4);
43509
+ return Math.max(1, this.scrollHeight() - 2);
42382
43510
  }
42383
43511
  // ─── Scroll ───────────────────────────────────────────────────────
42384
43512
  scrollUp(lines) {
@@ -42444,6 +43572,11 @@ var ChatTUI = class {
42444
43572
  }
42445
43573
  /** Handle a parsed CSI sequence: params is everything between \x1B[ and the final char */
42446
43574
  handleCSI(params, code) {
43575
+ if (params === "201~") {
43576
+ this.scrollToBottom();
43577
+ this.dirty();
43578
+ return;
43579
+ }
42447
43580
  if (params.startsWith("<") && (code === "M" || code === "m")) {
42448
43581
  if (code === "m") return;
42449
43582
  const parts = params.slice(1).split(";");
@@ -42525,22 +43658,31 @@ var ChatTUI = class {
42525
43658
  this.handleEnter();
42526
43659
  return;
42527
43660
  }
43661
+ if (code === 10) {
43662
+ this.inputBuffer += "\n";
43663
+ this.dirty();
43664
+ return;
43665
+ }
42528
43666
  if (code === 127 || code === 8) {
42529
43667
  if (this.inputBuffer.length > 0) {
42530
43668
  this.inputBuffer = this.inputBuffer.slice(0, -1);
42531
- this.renderInputLine();
43669
+ this.dirty();
42532
43670
  }
42533
43671
  return;
42534
43672
  }
42535
43673
  if (code < 32) return;
42536
43674
  this.inputBuffer += ch;
42537
- this.renderInputLine();
43675
+ this.dirty();
42538
43676
  }
42539
43677
  handleEnter() {
43678
+ if (this.turnInProgress) {
43679
+ this.dirty();
43680
+ return;
43681
+ }
42540
43682
  const text = this.inputBuffer.trim();
42541
43683
  this.inputBuffer = "";
42542
43684
  if (!text) {
42543
- this.renderInputLine();
43685
+ this.dirty();
42544
43686
  return;
42545
43687
  }
42546
43688
  if (text.toLowerCase() === "exit" || text.toLowerCase() === "quit") {
@@ -42557,7 +43699,7 @@ var ChatTUI = class {
42557
43699
  // ─── Events ───────────────────────────────────────────────────────
42558
43700
  onResize = () => {
42559
43701
  this.updateDimensions();
42560
- process.stdout.write(`${CSI}1;${Math.max(1, this.rows - 2)}r`);
43702
+ this.applyScrollRegion();
42561
43703
  this.displayLinesCache = null;
42562
43704
  this.debugLinesCache = null;
42563
43705
  this.render();
@@ -42599,19 +43741,24 @@ var ChatTUI = class {
42599
43741
  visible = displayLines.slice(start, end);
42600
43742
  }
42601
43743
  const buf = [HIDE_CURSOR];
43744
+ const msgTop = this.messageAreaTop();
43745
+ if (this.titleRows()) {
43746
+ buf.push(moveTo(1, 1), this.buildTitleBar(), CLEAR_EOL);
43747
+ }
42602
43748
  if (this.debugVisible) {
42603
- this.renderSplitScreen(buf, visible, sh);
43749
+ this.renderSplitScreen(buf, visible, sh, msgTop);
42604
43750
  } else {
42605
43751
  for (let i = 0; i < sh; i++) {
42606
- buf.push(moveTo(i + 1, 1), visible[i] || "", CLEAR_EOL);
43752
+ buf.push(moveTo(msgTop + i, 1), visible[i] || "", CLEAR_EOL);
42607
43753
  }
42608
43754
  }
42609
- buf.push(moveTo(this.rows - 1, 1), this.buildSeparator(), CLEAR_EOL);
42610
- buf.push(moveTo(this.rows, 1), `${BLUE}You:${RESET} ${this.inputBuffer}${CLEAR_EOL}`);
43755
+ const sepRow = this.rows - this.inputRows();
43756
+ buf.push(moveTo(sepRow, 1), this.buildSeparator(), CLEAR_EOL);
43757
+ this.renderInputArea(buf, sepRow + 1);
42611
43758
  buf.push(SHOW_CURSOR);
42612
43759
  process.stdout.write(buf.join(""));
42613
43760
  }
42614
- renderSplitScreen(buf, chatVisible, sh) {
43761
+ renderSplitScreen(buf, chatVisible, sh, msgTop = 1) {
42615
43762
  const cw = this.chatWidth();
42616
43763
  const dw = this.debugWidth();
42617
43764
  const divCol = cw + 1;
@@ -42627,21 +43774,68 @@ var ChatTUI = class {
42627
43774
  const chatLine = truncateAnsi(chatVisible[i] || "", cw);
42628
43775
  const debugLine = truncateAnsi(debugVisible[i] || "", dw);
42629
43776
  buf.push(
42630
- moveTo(i + 1, 1),
43777
+ moveTo(msgTop + i, 1),
42631
43778
  chatLine,
42632
43779
  CLEAR_EOL,
42633
43780
  // clear to end handles rest, but we need to position divider
42634
- moveTo(i + 1, divCol),
43781
+ moveTo(msgTop + i, divCol),
42635
43782
  `${DIM}\u2502${RESET}`,
42636
43783
  debugLine
42637
43784
  );
42638
43785
  buf.push(CLEAR_EOL);
42639
43786
  }
42640
43787
  }
42641
- renderInputLine() {
42642
- process.stdout.write(
42643
- `${moveTo(this.rows, 1)}${BLUE}You:${RESET} ${this.inputBuffer}${CLEAR_EOL}`
42644
- );
43788
+ renderInputArea(buf, startRow) {
43789
+ const inputRows = this.inputRows();
43790
+ const width = this.chatWidth();
43791
+ const contentWidth = Math.max(1, width - INPUT_LABEL_WIDTH);
43792
+ const inputLines = this.wrapInputLines(this.inputBuffer, contentWidth, inputRows);
43793
+ for (let i = 0; i < inputRows; i++) {
43794
+ const row = startRow + i;
43795
+ const line = inputLines[i] ?? "";
43796
+ const prefix = i === 0 ? `${BLUE}${INPUT_LABEL}${RESET} ` : " ".repeat(INPUT_LABEL_WIDTH);
43797
+ buf.push(moveTo(row, 1), prefix, line, CLEAR_EOL);
43798
+ }
43799
+ }
43800
+ wrapInputLines(text, maxWidth, maxRows) {
43801
+ const rawLines = text.split("\n");
43802
+ const wrapped = [];
43803
+ for (const raw of rawLines) {
43804
+ for (const wl of this.wrapText(raw, maxWidth)) {
43805
+ wrapped.push(wl);
43806
+ }
43807
+ }
43808
+ if (!wrapped.length) wrapped.push("");
43809
+ if (wrapped.length > maxRows) {
43810
+ const trimmed = wrapped.slice(wrapped.length - maxRows);
43811
+ trimmed[0] = "\u2026" + trimmed[0].slice(1);
43812
+ return trimmed;
43813
+ }
43814
+ return wrapped;
43815
+ }
43816
+ buildTitleBar() {
43817
+ const parts = [];
43818
+ if (this.options.title) {
43819
+ parts.push(`${CYAN}${this.options.title}${RESET}`);
43820
+ }
43821
+ if (this.options.subtitle) {
43822
+ parts.push(`${DIM}${this.options.subtitle}${RESET}`);
43823
+ }
43824
+ let status = "";
43825
+ switch (this.runState) {
43826
+ case "thinking":
43827
+ status = `${YELLOW}Thinking\u2026${RESET}`;
43828
+ break;
43829
+ case "tool_running":
43830
+ status = `${YELLOW}Running ${this.activeToolName}\u2026${RESET}`;
43831
+ break;
43832
+ case "streaming":
43833
+ status = `${GREEN}Writing\u2026${RESET}`;
43834
+ break;
43835
+ }
43836
+ if (status) parts.push(status);
43837
+ const line = parts.join(` ${DIM}|${RESET} `);
43838
+ return truncateAnsi(line, this.cols);
42645
43839
  }
42646
43840
  // ─── Separator ────────────────────────────────────────────────────
42647
43841
  buildSeparator() {
@@ -42656,6 +43850,7 @@ var ChatTUI = class {
42656
43850
  if (this.options.debug) {
42657
43851
  hints.push(`^D ${this.debugPanelVisible ? "hide" : "show"} debug`);
42658
43852
  }
43853
+ hints.push("Enter send");
42659
43854
  const lineWidth = Math.min(this.cols, 60);
42660
43855
  if (!hints.length) {
42661
43856
  return `${GRAY}${"\u2500".repeat(lineWidth)}${RESET}`;
@@ -42686,8 +43881,9 @@ var ChatTUI = class {
42686
43881
  return lines;
42687
43882
  }
42688
43883
  appendToolCallLines(lines, tc, width) {
42689
- const status = tc.done ? "Called" : "Calling";
42690
- const summary = ` ${GRAY}${status} ${tc.name}${tc.done ? "" : "..."}${RESET}`;
43884
+ const status = tc.done ? "\u2713" : "\u2026";
43885
+ const verb = tc.done ? "Called" : "Calling";
43886
+ const summary = ` ${tc.done ? GREEN : YELLOW}${status}${RESET} ${GRAY}${verb} ${tc.name}${RESET}`;
42691
43887
  if (!this.expandDetails) {
42692
43888
  lines.push(summary);
42693
43889
  return;
@@ -42708,14 +43904,15 @@ var ChatTUI = class {
42708
43904
  }
42709
43905
  }
42710
43906
  appendToolResultLines(lines, tr, width) {
43907
+ const mark = tr.failed ? `${RED}\u2717${RESET}` : `${GREEN}\u2713${RESET}`;
42711
43908
  if (!this.expandDetails) {
42712
- const maxLen = width - 10;
43909
+ const maxLen = width - 12;
42713
43910
  const preview = tr.content.replace(/\n/g, " ").slice(0, maxLen);
42714
43911
  const truncated = preview.length < tr.content.length ? "..." : "";
42715
- lines.push(` ${GRAY}\u2192 ${tr.toolName}: ${preview}${truncated}${RESET}`);
43912
+ lines.push(` ${mark} ${GRAY}${tr.toolName}: ${preview}${truncated}${RESET}`);
42716
43913
  return;
42717
43914
  }
42718
- lines.push(` ${GRAY}\u2192 ${tr.toolName} result:${RESET}`);
43915
+ lines.push(` ${mark} ${GRAY}${tr.toolName} result:${RESET}`);
42719
43916
  let formatted = tr.content;
42720
43917
  try {
42721
43918
  formatted = JSON.stringify(JSON.parse(tr.content), null, 2);
@@ -42767,7 +43964,12 @@ var ChatTUI = class {
42767
43964
  const labelWidth = 12;
42768
43965
  const indent = " ".repeat(labelWidth);
42769
43966
  if (!this.streamContent) {
42770
- lines.push(label);
43967
+ if (this.runState === "thinking" || this.runState === "tool_running") {
43968
+ const hint = this.runState === "tool_running" && this.activeToolName ? `Running ${this.activeToolName}\u2026` : "Thinking\u2026";
43969
+ lines.push(`${label}${YELLOW}${hint}${RESET}`);
43970
+ } else {
43971
+ lines.push(label);
43972
+ }
42771
43973
  return;
42772
43974
  }
42773
43975
  let first = true;
@@ -42884,6 +44086,58 @@ function buildDebugSummary(_direction, msg) {
42884
44086
  }
42885
44087
  return type;
42886
44088
  }
44089
+
44090
+ // src/lib/agui-tui-events.ts
44091
+ init_agui();
44092
+ function handleAguiEvent(tui, event) {
44093
+ const type = event.type?.toLowerCase() ?? "";
44094
+ switch (type) {
44095
+ case "run_started":
44096
+ tui.runStarted();
44097
+ break;
44098
+ case "run_finished":
44099
+ tui.runFinished();
44100
+ break;
44101
+ case "text_message_start":
44102
+ tui.streamStart();
44103
+ break;
44104
+ case "text_message_content": {
44105
+ const delta = getTextDelta(event);
44106
+ if (delta) tui.streamDelta(delta);
44107
+ break;
44108
+ }
44109
+ case "text_message_end":
44110
+ tui.streamEnd();
44111
+ break;
44112
+ case "tool_call_start":
44113
+ tui.toolCallStart(
44114
+ event.toolCallId ?? "",
44115
+ event.toolCallName ?? event.name ?? "tool"
44116
+ );
44117
+ break;
44118
+ case "tool_call_args":
44119
+ if (event.toolCallId && event.delta) {
44120
+ tui.toolCallArgs(event.toolCallId, event.delta);
44121
+ }
44122
+ break;
44123
+ case "tool_call_end":
44124
+ if (event.toolCallId) tui.toolCallEnd(event.toolCallId);
44125
+ break;
44126
+ case "tool_call_result": {
44127
+ const toolCallId = event.toolCallId ?? "";
44128
+ const toolName = tui.findToolCallName(toolCallId);
44129
+ const content = typeof event.content === "string" ? event.content : typeof event.result === "string" ? event.result : JSON.stringify(event.result ?? event.content ?? "");
44130
+ tui.toolCallResult(toolCallId, toolName, content);
44131
+ break;
44132
+ }
44133
+ case "run_error": {
44134
+ const errorMsg = getErrorMessage(event);
44135
+ if (errorMsg) tui.showError(errorMsg);
44136
+ tui.runFinished();
44137
+ break;
44138
+ }
44139
+ }
44140
+ }
42887
44141
  var SAMPLE_RATE = 24e3;
42888
44142
  var MIC_CHUNK_BYTES = 4800;
42889
44143
  function checkSoxAvailable() {
@@ -43254,6 +44508,7 @@ async function singleTurnChatSession(session, message, debug, autoApprove = fals
43254
44508
  {
43255
44509
  autoApprove,
43256
44510
  allowWrite: allowWrite || !!session.allowWrite,
44511
+ debug,
43257
44512
  trustCwd: session.trustCwd,
43258
44513
  trustDir: session.trustDir,
43259
44514
  nonInteractive: true
@@ -43303,99 +44558,81 @@ async function interactiveChatSession(session, debug, autoApprove, allowWrite) {
43303
44558
  model: session.model,
43304
44559
  appContext: session.appContext
43305
44560
  });
43306
- clearScreen();
43307
- console.log("=".repeat(60));
43308
- console.log(session.label);
43309
- console.log("=".repeat(60));
43310
- console.log(`Chat: ${session.chatTitle}`);
43311
- console.log("Type your message and press Enter. Type 'exit' or Ctrl+C to quit.");
43312
- console.log("=".repeat(60));
43313
- console.log("");
43314
44561
  const existingMessages = await session.loadMessages();
43315
- if (existingMessages.length > 0) {
43316
- console.log("\x1B[90m--- Previous messages ---\x1B[0m\n");
43317
- for (const msg of existingMessages.slice(-10)) {
43318
- const text = typeof msg.content === "string" ? msg.content : "";
43319
- if (text && text.trim()) {
43320
- printMessage(text, msg.role);
44562
+ const history = buildHistory(existingMessages);
44563
+ const conversationMessages = buildConversationMessages(existingMessages);
44564
+ let tui;
44565
+ const sendTurn = async (text) => {
44566
+ conversationMessages.push({ role: "user", content: text });
44567
+ let assistantContent = "";
44568
+ try {
44569
+ tui.runStarted();
44570
+ const { streamText } = await runConciergeAguiLoop(
44571
+ aguiClient,
44572
+ conversationMessages,
44573
+ (event) => {
44574
+ handleAguiEvent(tui, event);
44575
+ const type = event.type?.toLowerCase() ?? "";
44576
+ if (type === "text_message_content" && event.delta) {
44577
+ assistantContent += event.delta;
44578
+ }
44579
+ const errorMsg = getErrorMessage(event);
44580
+ if (errorMsg) tui.showError(errorMsg);
44581
+ },
44582
+ {
44583
+ autoApprove,
44584
+ allowWrite: allowWrite || !!session.allowWrite,
44585
+ debug,
44586
+ trustCwd: session.trustCwd,
44587
+ trustDir: session.trustDir,
44588
+ onHitlPromptStart: () => tui.pauseForPrompt(),
44589
+ onHitlPromptEnd: () => tui.resumeAfterPrompt()
44590
+ }
44591
+ );
44592
+ if (streamText && !assistantContent) {
44593
+ assistantContent = streamText;
44594
+ }
44595
+ if (assistantContent) {
44596
+ conversationMessages.push({ role: "assistant", content: assistantContent });
43321
44597
  }
44598
+ } catch (error) {
44599
+ tui.showError(error instanceof Error ? error.message : String(error));
44600
+ } finally {
44601
+ tui.runFinished();
43322
44602
  }
43323
- console.log("\x1B[90m--- End of history ---\x1B[0m\n");
43324
- }
43325
- const conversationMessages = [];
43326
- for (const msg of existingMessages.slice(-10)) {
44603
+ };
44604
+ await new Promise((resolve2) => {
44605
+ tui = new ChatTUI({
44606
+ title: session.label,
44607
+ subtitle: session.chatTitle,
44608
+ onSend: (text) => {
44609
+ void sendTurn(text);
44610
+ },
44611
+ onExit: () => {
44612
+ tui.stop();
44613
+ resolve2();
44614
+ },
44615
+ debug,
44616
+ env: session.ctx.env
44617
+ });
44618
+ tui.loadHistory(history);
44619
+ tui.start();
44620
+ });
44621
+ }
44622
+ function buildConversationMessages(messages) {
44623
+ const out = [];
44624
+ for (const msg of messages) {
43327
44625
  const text = typeof msg.content === "string" ? msg.content : "";
43328
- if (text && text.trim() && (msg.role === "user" || msg.role === "assistant")) {
43329
- conversationMessages.push({ role: msg.role, content: text });
44626
+ if (text.trim() && (msg.role === "user" || msg.role === "assistant")) {
44627
+ out.push({ role: msg.role, content: text });
43330
44628
  }
43331
44629
  }
43332
- const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
43333
- return new Promise((resolve2) => {
43334
- const prompt = () => {
43335
- rl.question("\x1B[34mYou:\x1B[0m ", async (input2) => {
43336
- const trimmed = input2.trim();
43337
- if (!trimmed) {
43338
- prompt();
43339
- return;
43340
- }
43341
- if (trimmed.toLowerCase() === "exit" || trimmed.toLowerCase() === "quit") {
43342
- console.log("\nGoodbye!");
43343
- rl.close();
43344
- return;
43345
- }
43346
- conversationMessages.push({ role: "user", content: trimmed });
43347
- process.stdout.write("\n\x1B[32mAssistant:\x1B[0m ");
43348
- let assistantContent = "";
43349
- try {
43350
- const { streamText } = await runConciergeAguiLoop(
43351
- aguiClient,
43352
- conversationMessages,
43353
- (event) => {
43354
- const delta = getTextDelta(event);
43355
- if (delta) {
43356
- process.stdout.write(delta);
43357
- assistantContent += delta;
43358
- }
43359
- const errorMsg = getErrorMessage(event);
43360
- if (errorMsg) console.log(`
43361
- \x1B[31mError: ${errorMsg}\x1B[0m`);
43362
- },
43363
- {
43364
- autoApprove,
43365
- allowWrite: allowWrite || !!session.allowWrite,
43366
- debug,
43367
- trustCwd: session.trustCwd,
43368
- trustDir: session.trustDir
43369
- }
43370
- );
43371
- if (streamText && !assistantContent) {
43372
- assistantContent = streamText;
43373
- process.stdout.write(streamText);
43374
- }
43375
- if (assistantContent) {
43376
- conversationMessages.push({ role: "assistant", content: assistantContent });
43377
- }
43378
- console.log("\n");
43379
- } catch (error) {
43380
- console.log(
43381
- `
43382
- \x1B[31mError: ${error instanceof Error ? error.message : error}\x1B[0m
43383
- `
43384
- );
43385
- }
43386
- prompt();
43387
- });
43388
- };
43389
- rl.on("close", () => {
43390
- console.log("\nGoodbye!");
43391
- resolve2();
43392
- });
43393
- prompt();
43394
- });
44630
+ return out;
43395
44631
  }
43396
- function buildHistory(messages) {
44632
+ function buildHistory(messages, limit) {
43397
44633
  const history = [];
43398
- for (const msg of messages.slice(-30)) {
44634
+ const slice = limit ? messages.slice(-limit) : messages;
44635
+ for (const msg of slice) {
43399
44636
  const text = typeof msg.content === "string" ? msg.content : "";
43400
44637
  if (msg.role === "user" || msg.role === "assistant") {
43401
44638
  if (text.trim()) {
@@ -43467,7 +44704,7 @@ async function realtimeChatSession(session, vad, debug) {
43467
44704
  throw new CLIError(`Failed to connect: ${err instanceof Error ? err.message : err}`);
43468
44705
  }
43469
44706
  const existingMessages = await session.loadMessages();
43470
- const history = buildHistory(existingMessages);
44707
+ const history = buildHistory(existingMessages, 30);
43471
44708
  const tui = new ChatTUI({
43472
44709
  onSend: (text) => {
43473
44710
  client.sendTextMessage(text);
@@ -43532,7 +44769,7 @@ Connecting to ${session.label.toLowerCase()}...
43532
44769
  throw new CLIError(`Failed to connect: ${err instanceof Error ? err.message : err}`);
43533
44770
  }
43534
44771
  const existingMessages = await session.loadMessages();
43535
- const history = buildHistory(existingMessages);
44772
+ const history = buildHistory(existingMessages, 30);
43536
44773
  const mic = new MicCapture((pcm16) => {
43537
44774
  if (!client.isConnected()) return;
43538
44775
  client.sendAudio(pcm16);
@@ -43627,7 +44864,164 @@ async function listAudioDevices() {
43627
44864
  }
43628
44865
  }
43629
44866
 
44867
+ // src/lib/chat-history.ts
44868
+ var PAGE_SIZE = 100;
44869
+ var HARD_CAP = 2e3;
44870
+ async function loadAllChatMessages(ctx, workspaceUuid, chatId) {
44871
+ const items = [];
44872
+ let offset = 0;
44873
+ while (items.length < HARD_CAP) {
44874
+ const batch = await ctx.apiClient.getChatMessages(workspaceUuid, chatId, PAGE_SIZE, offset).catch(() => []);
44875
+ if (!batch.length) break;
44876
+ items.push(...batch);
44877
+ if (batch.length < PAGE_SIZE) break;
44878
+ offset += batch.length;
44879
+ }
44880
+ return items;
44881
+ }
44882
+
44883
+ // src/commands/manage.ts
44884
+ async function manageCommand(hctx) {
44885
+ const ctx = requireAuth(hctx.ctx);
44886
+ const { workspace, args } = hctx;
44887
+ const asMember = typeof args["as-member"] === "string" ? args["as-member"] : void 0;
44888
+ const chatIdArg = typeof args["chat-id"] === "string" ? args["chat-id"] : void 0;
44889
+ const message = typeof args.message === "string" ? args.message : void 0;
44890
+ const chat = await getOrCreateChat(ctx, workspace, chatIdArg, asMember, "manager", !!message);
44891
+ const session = buildWorkspaceSession(ctx, workspace, chat, "Workspace Manager", {
44892
+ appContext: buildCliConciergeAppContext(),
44893
+ allowWrite: true,
44894
+ trustCwd: !!args["trust-cwd"],
44895
+ trustDir: typeof args["trust-dir"] === "string" ? args["trust-dir"] : void 0
44896
+ });
44897
+ process.stderr.write(`Chat #${session.chatId}
44898
+ `);
44899
+ await runChatSession(session, args);
44900
+ process.stderr.write(`Chat #${session.chatId}
44901
+ `);
44902
+ }
44903
+ async function chatCommand(hctx) {
44904
+ const ctx = requireAuth(hctx.ctx);
44905
+ const { workspace, args } = hctx;
44906
+ const chatIdArg = typeof args["chat-id"] === "string" ? args["chat-id"] : void 0;
44907
+ const workflowId = typeof args.workflow === "string" ? args.workflow : void 0;
44908
+ const memberId = typeof args.member === "string" ? args.member : void 0;
44909
+ let chat;
44910
+ if (chatIdArg) {
44911
+ const id = Number(chatIdArg);
44912
+ if (isNaN(id)) throw new CLIError("--chat-id must be a number");
44913
+ chat = await ctx.apiClient.getChat(workspace, id);
44914
+ } else if (workflowId) {
44915
+ chat = await createAssignmentChat(ctx.apiClient, workspace, Number(workflowId), memberId);
44916
+ } else if (memberId) {
44917
+ chat = await createMemberChat(ctx.apiClient, workspace, memberId);
44918
+ } else {
44919
+ throw new CLIError(
44920
+ 'Specify --workflow <id>, --member <id>, or --chat-id <id>.\nUse "gr manage" for workspace manager chats.'
44921
+ );
44922
+ }
44923
+ const session = buildWorkspaceSession(ctx, workspace, chat, "Chat");
44924
+ await runChatSession(session, args);
44925
+ }
44926
+ function buildWorkspaceSession(ctx, workspace, chat, label, extra) {
44927
+ const wsBase = ctx.envConfig.apiUrl.replace(/^https:/, "wss:").replace(/^http:/, "ws:");
44928
+ return {
44929
+ ctx,
44930
+ workspaceUuid: workspace,
44931
+ chatId: chat.id,
44932
+ chatUuid: chat.uuid,
44933
+ chatTitle: chat.title || chat.uuid,
44934
+ aguiEndpointUrl: `${ctx.envConfig.apiUrl}/api/v2/w/${workspace}/web-chat/${chat.id}/chat/agui`,
44935
+ wsUrl: `${wsBase}/api/v2/w/${workspace}/realtime/stream-ws`,
44936
+ loadMessages: () => loadAllChatMessages(ctx, workspace, chat.id),
44937
+ label,
44938
+ model: "manager",
44939
+ ...extra
44940
+ };
44941
+ }
44942
+ async function getOrCreateChat(ctx, workspace, chatIdArg, asMemberId, chatType, skipSelection = false) {
44943
+ if (chatIdArg) {
44944
+ const chatId = Number(chatIdArg);
44945
+ if (isNaN(chatId)) throw new CLIError("--chat-id must be a number");
44946
+ return ctx.apiClient.getChat(workspace, chatId);
44947
+ }
44948
+ if (skipSelection) {
44949
+ return createManagerChat(ctx.apiClient, workspace, asMemberId);
44950
+ }
44951
+ const chatsResponse = await ctx.apiClient.getChats(workspace, {
44952
+ chatType,
44953
+ sortBy: "updatedAt",
44954
+ sortOrder: "desc",
44955
+ pageSize: 20
44956
+ });
44957
+ const chats = chatsResponse.items || [];
44958
+ const { item: selectedChat, isNew } = await selectFromList(chats, {
44959
+ title: "Select a chat or create a new one",
44960
+ labelFn: (chat) => chat.title || `Chat ${chat.uuid.slice(0, 8)}...`,
44961
+ detailFn: (chat) => {
44962
+ const time = formatTimestamp(chat.updatedAt);
44963
+ const msgCount = chat.messageCount || 0;
44964
+ return `${msgCount} msg${msgCount !== 1 ? "s" : ""} - ${time}`;
44965
+ },
44966
+ emptyMessage: "No existing chats.",
44967
+ allowNew: true,
44968
+ newLabel: "+ Start new chat"
44969
+ });
44970
+ if (!selectedChat && !isNew) {
44971
+ throw new CLIError("No chat selected.");
44972
+ }
44973
+ if (isNew) {
44974
+ return createManagerChat(ctx.apiClient, workspace, asMemberId);
44975
+ }
44976
+ return selectedChat;
44977
+ }
44978
+ async function createManagerChat(apiClient, workspace, asMemberId) {
44979
+ const data = {
44980
+ chatType: "manager",
44981
+ channel: "web-chat"
44982
+ };
44983
+ if (asMemberId) {
44984
+ data.memberId = Number(asMemberId);
44985
+ }
44986
+ const chat = await apiClient.createChat(workspace, data);
44987
+ process.stderr.write(`Created chat #${chat.id}
44988
+ `);
44989
+ return chat;
44990
+ }
44991
+ async function createAssignmentChat(apiClient, workspace, workflowId, asMemberId) {
44992
+ if (isNaN(workflowId)) throw new CLIError("--workflow must be a number");
44993
+ const data = {
44994
+ chatType: "assignment",
44995
+ channel: "web-chat",
44996
+ workflowId
44997
+ };
44998
+ if (asMemberId) {
44999
+ data.memberId = Number(asMemberId);
45000
+ }
45001
+ const chat = await apiClient.createChat(workspace, data);
45002
+ process.stderr.write(`Created assignment chat #${chat.id} (workflow ${workflowId})
45003
+ `);
45004
+ return chat;
45005
+ }
45006
+ async function createMemberChat(apiClient, workspace, memberId) {
45007
+ const id = Number(memberId);
45008
+ if (isNaN(id)) throw new CLIError("--member must be a number");
45009
+ const data = {
45010
+ chatType: "member",
45011
+ channel: "web-chat",
45012
+ memberId: id
45013
+ };
45014
+ const chat = await apiClient.createChat(workspace, data);
45015
+ process.stderr.write(`Created DM chat #${chat.id} (member ${memberId})
45016
+ `);
45017
+ return chat;
45018
+ }
45019
+
43630
45020
  // src/commands/concierge.ts
45021
+ init_cli_utils();
45022
+ init_concierge_api();
45023
+ init_context();
45024
+ init_errors();
43631
45025
  async function conciergeOutboundCommand(hctx) {
43632
45026
  const ctx = requireAuth(hctx.ctx);
43633
45027
  const { args } = hctx;
@@ -43726,6 +45120,63 @@ async function getOrCreateConciergeChat(ctx, chatIdArg, skipSelection) {
43726
45120
  return selectedChat;
43727
45121
  }
43728
45122
 
45123
+ // src/commands/dev.ts
45124
+ init_errors();
45125
+ init_output();
45126
+ async function devImportLocalCommand(ctx, workspace) {
45127
+ stderr2(`Exporting workspace ${workspace}...`);
45128
+ const exportData = await ctx.apiClient.exportWorkspace(workspace);
45129
+ stderr2("Export successful!");
45130
+ stderr2(` Workflows: ${(exportData.workflows || []).length}`);
45131
+ stderr2(` Tasks: ${(exportData.tasks || []).length}`);
45132
+ stderr2(` Data Types: ${(exportData.dataTypes || []).length}`);
45133
+ stderr2(` Sites: ${(exportData.sites || []).length}`);
45134
+ const slug = workspace.slice(0, 8);
45135
+ const importCacheDir = join(ctx.credentialsManager.getCacheDir(), "imports");
45136
+ if (!existsSync(importCacheDir)) {
45137
+ mkdirSync(importCacheDir, { recursive: true });
45138
+ }
45139
+ const filename = `ws-${slug}-${workspace}.json`;
45140
+ const filepath = join(importCacheDir, filename);
45141
+ writeFileSync(filepath, JSON.stringify(exportData, null, 2));
45142
+ stderr2(`Saved to: ${filepath}`);
45143
+ stderr2("Running dev:restore...");
45144
+ const rootDir = findProjectRoot();
45145
+ const relativePath = filepath.replace(rootDir + "/", "");
45146
+ try {
45147
+ const result2 = execSync(`yarn dev:restore ${relativePath}`, {
45148
+ cwd: rootDir,
45149
+ stdio: "pipe",
45150
+ encoding: "utf-8"
45151
+ });
45152
+ process.stderr.write(result2);
45153
+ const failed = result2.includes("Failed/Skipped: ") && !result2.includes("Failed/Skipped: 0") || result2.includes("Successfully restored: 0");
45154
+ if (failed) throw new CLIError("Import failed");
45155
+ } catch (error) {
45156
+ if (error instanceof CLIError) throw error;
45157
+ const execError = error;
45158
+ if (execError.stdout) process.stderr.write(execError.stdout);
45159
+ if (execError.stderr) process.stderr.write(execError.stderr);
45160
+ throw new CLIError("dev:restore failed");
45161
+ }
45162
+ stderr2(`Import complete: ${workspace}`);
45163
+ }
45164
+ function findProjectRoot() {
45165
+ let dir = process.cwd();
45166
+ while (dir !== "/") {
45167
+ const pkgPath = join(dir, "package.json");
45168
+ if (existsSync(pkgPath)) {
45169
+ try {
45170
+ const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
45171
+ if (pkg.workspaces) return dir;
45172
+ } catch {
45173
+ }
45174
+ }
45175
+ dir = join(dir, "..");
45176
+ }
45177
+ return process.cwd();
45178
+ }
45179
+
43729
45180
  // src/commands/get-started.ts
43730
45181
  init_context();
43731
45182
  var WEB_SETUP = "https://app.gravityrail.com/setup";
@@ -43826,63 +45277,6 @@ async function getStartedCommand(hctx) {
43826
45277
  process.stdout.write(LLM_GUIDE);
43827
45278
  }
43828
45279
 
43829
- // src/commands/dev.ts
43830
- init_errors();
43831
- init_output();
43832
- async function devImportLocalCommand(ctx, workspace) {
43833
- stderr2(`Exporting workspace ${workspace}...`);
43834
- const exportData = await ctx.apiClient.exportWorkspace(workspace);
43835
- stderr2("Export successful!");
43836
- stderr2(` Workflows: ${(exportData.workflows || []).length}`);
43837
- stderr2(` Tasks: ${(exportData.tasks || []).length}`);
43838
- stderr2(` Data Types: ${(exportData.dataTypes || []).length}`);
43839
- stderr2(` Sites: ${(exportData.sites || []).length}`);
43840
- const slug = workspace.slice(0, 8);
43841
- const importCacheDir = join(ctx.credentialsManager.getCacheDir(), "imports");
43842
- if (!existsSync(importCacheDir)) {
43843
- mkdirSync(importCacheDir, { recursive: true });
43844
- }
43845
- const filename = `ws-${slug}-${workspace}.json`;
43846
- const filepath = join(importCacheDir, filename);
43847
- writeFileSync(filepath, JSON.stringify(exportData, null, 2));
43848
- stderr2(`Saved to: ${filepath}`);
43849
- stderr2("Running dev:restore...");
43850
- const rootDir = findProjectRoot();
43851
- const relativePath = filepath.replace(rootDir + "/", "");
43852
- try {
43853
- const result2 = execSync(`yarn dev:restore ${relativePath}`, {
43854
- cwd: rootDir,
43855
- stdio: "pipe",
43856
- encoding: "utf-8"
43857
- });
43858
- process.stderr.write(result2);
43859
- const failed = result2.includes("Failed/Skipped: ") && !result2.includes("Failed/Skipped: 0") || result2.includes("Successfully restored: 0");
43860
- if (failed) throw new CLIError("Import failed");
43861
- } catch (error) {
43862
- if (error instanceof CLIError) throw error;
43863
- const execError = error;
43864
- if (execError.stdout) process.stderr.write(execError.stdout);
43865
- if (execError.stderr) process.stderr.write(execError.stderr);
43866
- throw new CLIError("dev:restore failed");
43867
- }
43868
- stderr2(`Import complete: ${workspace}`);
43869
- }
43870
- function findProjectRoot() {
43871
- let dir = process.cwd();
43872
- while (dir !== "/") {
43873
- const pkgPath = join(dir, "package.json");
43874
- if (existsSync(pkgPath)) {
43875
- try {
43876
- const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
43877
- if (pkg.workspaces) return dir;
43878
- } catch {
43879
- }
43880
- }
43881
- dir = join(dir, "..");
43882
- }
43883
- return process.cwd();
43884
- }
43885
-
43886
45280
  // src/commands/login.ts
43887
45281
  init_dist();
43888
45282
  init_cli_utils();
@@ -43902,146 +45296,6 @@ async function logoutCommand(ctx) {
43902
45296
  stderr2(`Credentials cleared for ${ctx.env}`);
43903
45297
  }
43904
45298
 
43905
- // src/commands/manage.ts
43906
- init_cli_utils();
43907
- init_errors();
43908
- init_context();
43909
- async function manageCommand(hctx) {
43910
- const ctx = requireAuth(hctx.ctx);
43911
- const { workspace, args } = hctx;
43912
- const asMember = typeof args["as-member"] === "string" ? args["as-member"] : void 0;
43913
- const chatIdArg = typeof args["chat-id"] === "string" ? args["chat-id"] : void 0;
43914
- const message = typeof args.message === "string" ? args.message : void 0;
43915
- const chat = await getOrCreateChat(ctx, workspace, chatIdArg, asMember, "manager", !!message);
43916
- const session = buildWorkspaceSession(ctx, workspace, chat, "Workspace Manager", {
43917
- appContext: buildCliConciergeAppContext(),
43918
- allowWrite: true,
43919
- trustCwd: !!args["trust-cwd"],
43920
- trustDir: typeof args["trust-dir"] === "string" ? args["trust-dir"] : void 0
43921
- });
43922
- process.stderr.write(`Chat #${session.chatId}
43923
- `);
43924
- await runChatSession(session, args);
43925
- process.stderr.write(`Chat #${session.chatId}
43926
- `);
43927
- }
43928
- async function chatCommand(hctx) {
43929
- const ctx = requireAuth(hctx.ctx);
43930
- const { workspace, args } = hctx;
43931
- const chatIdArg = typeof args["chat-id"] === "string" ? args["chat-id"] : void 0;
43932
- const workflowId = typeof args.workflow === "string" ? args.workflow : void 0;
43933
- const memberId = typeof args.member === "string" ? args.member : void 0;
43934
- let chat;
43935
- if (chatIdArg) {
43936
- const id = Number(chatIdArg);
43937
- if (isNaN(id)) throw new CLIError("--chat-id must be a number");
43938
- chat = await ctx.apiClient.getChat(workspace, id);
43939
- } else if (workflowId) {
43940
- chat = await createAssignmentChat(ctx.apiClient, workspace, Number(workflowId), memberId);
43941
- } else if (memberId) {
43942
- chat = await createMemberChat(ctx.apiClient, workspace, memberId);
43943
- } else {
43944
- throw new CLIError(
43945
- 'Specify --workflow <id>, --member <id>, or --chat-id <id>.\nUse "gr manage" for workspace manager chats.'
43946
- );
43947
- }
43948
- const session = buildWorkspaceSession(ctx, workspace, chat, "Chat");
43949
- await runChatSession(session, args);
43950
- }
43951
- function buildWorkspaceSession(ctx, workspace, chat, label, extra) {
43952
- const wsBase = ctx.envConfig.apiUrl.replace(/^https:/, "wss:").replace(/^http:/, "ws:");
43953
- return {
43954
- ctx,
43955
- workspaceUuid: workspace,
43956
- chatId: chat.id,
43957
- chatUuid: chat.uuid,
43958
- chatTitle: chat.title || chat.uuid,
43959
- aguiEndpointUrl: `${ctx.envConfig.apiUrl}/api/v2/w/${workspace}/web-chat/${chat.id}/chat/agui`,
43960
- wsUrl: `${wsBase}/api/v2/w/${workspace}/realtime/stream-ws`,
43961
- loadMessages: () => ctx.apiClient.getChatMessages(workspace, chat.id, 50).catch(() => []),
43962
- label,
43963
- model: "manager",
43964
- ...extra
43965
- };
43966
- }
43967
- async function getOrCreateChat(ctx, workspace, chatIdArg, asMemberId, chatType, skipSelection = false) {
43968
- if (chatIdArg) {
43969
- const chatId = Number(chatIdArg);
43970
- if (isNaN(chatId)) throw new CLIError("--chat-id must be a number");
43971
- return ctx.apiClient.getChat(workspace, chatId);
43972
- }
43973
- if (skipSelection) {
43974
- return createManagerChat(ctx.apiClient, workspace, asMemberId);
43975
- }
43976
- const chatsResponse = await ctx.apiClient.getChats(workspace, {
43977
- chatType,
43978
- sortBy: "updatedAt",
43979
- sortOrder: "desc",
43980
- pageSize: 20
43981
- });
43982
- const chats = chatsResponse.items || [];
43983
- const { item: selectedChat, isNew } = await selectFromList(chats, {
43984
- title: "Select a chat or create a new one",
43985
- labelFn: (chat) => chat.title || `Chat ${chat.uuid.slice(0, 8)}...`,
43986
- detailFn: (chat) => {
43987
- const time = formatTimestamp(chat.updatedAt);
43988
- const msgCount = chat.messageCount || 0;
43989
- return `${msgCount} msg${msgCount !== 1 ? "s" : ""} - ${time}`;
43990
- },
43991
- emptyMessage: "No existing chats.",
43992
- allowNew: true,
43993
- newLabel: "+ Start new chat"
43994
- });
43995
- if (!selectedChat && !isNew) {
43996
- throw new CLIError("No chat selected.");
43997
- }
43998
- if (isNew) {
43999
- return createManagerChat(ctx.apiClient, workspace, asMemberId);
44000
- }
44001
- return selectedChat;
44002
- }
44003
- async function createManagerChat(apiClient, workspace, asMemberId) {
44004
- const data = {
44005
- chatType: "manager",
44006
- channel: "web-chat"
44007
- };
44008
- if (asMemberId) {
44009
- data.memberId = Number(asMemberId);
44010
- }
44011
- const chat = await apiClient.createChat(workspace, data);
44012
- process.stderr.write(`Created chat #${chat.id}
44013
- `);
44014
- return chat;
44015
- }
44016
- async function createAssignmentChat(apiClient, workspace, workflowId, asMemberId) {
44017
- if (isNaN(workflowId)) throw new CLIError("--workflow must be a number");
44018
- const data = {
44019
- chatType: "assignment",
44020
- channel: "web-chat",
44021
- workflowId
44022
- };
44023
- if (asMemberId) {
44024
- data.memberId = Number(asMemberId);
44025
- }
44026
- const chat = await apiClient.createChat(workspace, data);
44027
- process.stderr.write(`Created assignment chat #${chat.id} (workflow ${workflowId})
44028
- `);
44029
- return chat;
44030
- }
44031
- async function createMemberChat(apiClient, workspace, memberId) {
44032
- const id = Number(memberId);
44033
- if (isNaN(id)) throw new CLIError("--member must be a number");
44034
- const data = {
44035
- chatType: "member",
44036
- channel: "web-chat",
44037
- memberId: id
44038
- };
44039
- const chat = await apiClient.createChat(workspace, data);
44040
- process.stderr.write(`Created DM chat #${chat.id} (member ${memberId})
44041
- `);
44042
- return chat;
44043
- }
44044
-
44045
45299
  // src/commands/organizations.ts
44046
45300
  init_output();
44047
45301
  var COLUMNS34 = [
@@ -44072,26 +45326,26 @@ async function whoamiCommand(ctx) {
44072
45326
  outputSingle(account, ctx, columns);
44073
45327
  }
44074
45328
 
44075
- // src/register-special-commands.ts
45329
+ // src/top-level-commands.ts
44076
45330
  init_context();
44077
- function registerSpecialCommands(registry) {
44078
- registry.registerCommand({
45331
+ var topLevelCommands = [
45332
+ {
44079
45333
  path: ["login"],
44080
45334
  description: "Authenticate via OAuth",
44081
45335
  requiresAuth: false,
44082
45336
  handler: async ({ ctx }) => {
44083
45337
  await loginCommand(ctx);
44084
45338
  }
44085
- });
44086
- registry.registerCommand({
45339
+ },
45340
+ {
44087
45341
  path: ["logout"],
44088
45342
  description: "Clear cached credentials",
44089
45343
  requiresAuth: false,
44090
45344
  handler: async ({ ctx }) => {
44091
45345
  await logoutCommand(ctx);
44092
45346
  }
44093
- });
44094
- registry.registerCommand({
45347
+ },
45348
+ {
44095
45349
  path: ["auth", "browser"],
44096
45350
  description: "Open an authenticated browser session using CLI credentials",
44097
45351
  args: [
@@ -44100,8 +45354,8 @@ function registerSpecialCommands(registry) {
44100
45354
  handler: async ({ ctx, args }) => {
44101
45355
  await authBrowserCommand(requireAuth(ctx), args);
44102
45356
  }
44103
- });
44104
- registry.registerCommand({
45357
+ },
45358
+ {
44105
45359
  path: ["manage"],
44106
45360
  description: "Interactive workspace manager chat (text, realtime, or voice)",
44107
45361
  requiresWorkspace: true,
@@ -44135,8 +45389,8 @@ function registerSpecialCommands(registry) {
44135
45389
  handler: async (hctx) => {
44136
45390
  await manageCommand(hctx);
44137
45391
  }
44138
- });
44139
- registry.registerCommand({
45392
+ },
45393
+ {
44140
45394
  path: ["chat"],
44141
45395
  description: "Chat with a workflow, member, or existing chat (text, realtime, or voice)",
44142
45396
  requiresWorkspace: true,
@@ -44162,8 +45416,8 @@ function registerSpecialCommands(registry) {
44162
45416
  handler: async (hctx) => {
44163
45417
  await chatCommand(hctx);
44164
45418
  }
44165
- });
44166
- registry.registerCommand({
45419
+ },
45420
+ {
44167
45421
  path: ["get-started"],
44168
45422
  description: "Bootstrap instructions for new users and LLM agents",
44169
45423
  requiresAuth: false,
@@ -44181,8 +45435,8 @@ function registerSpecialCommands(registry) {
44181
45435
  handler: async (hctx) => {
44182
45436
  await getStartedCommand(hctx);
44183
45437
  }
44184
- });
44185
- registry.registerCommand({
45438
+ },
45439
+ {
44186
45440
  path: ["setup"],
44187
45441
  description: "Alias for get-started \u2014 bootstrap instructions",
44188
45442
  requiresAuth: false,
@@ -44193,8 +45447,8 @@ function registerSpecialCommands(registry) {
44193
45447
  handler: async (hctx) => {
44194
45448
  await getStartedCommand(hctx);
44195
45449
  }
44196
- });
44197
- registry.registerCommand({
45450
+ },
45451
+ {
44198
45452
  path: ["concierge"],
44199
45453
  description: "Call or SMS your verified phone via the Concierge (server-side)",
44200
45454
  requiresWorkspace: false,
@@ -44206,8 +45460,8 @@ function registerSpecialCommands(registry) {
44206
45460
  handler: async (hctx) => {
44207
45461
  await conciergeOutboundCommand(hctx);
44208
45462
  }
44209
- });
44210
- registry.registerCommand({
45463
+ },
45464
+ {
44211
45465
  path: ["account", "verify-phone"],
44212
45466
  description: "Verify your account phone for concierge chat --call / --sms",
44213
45467
  requiresWorkspace: false,
@@ -44217,8 +45471,8 @@ function registerSpecialCommands(registry) {
44217
45471
  const { accountVerifyPhoneCommand: accountVerifyPhoneCommand2 } = await Promise.resolve().then(() => (init_account_verify_phone(), account_verify_phone_exports));
44218
45472
  await accountVerifyPhoneCommand2(hctx);
44219
45473
  }
44220
- });
44221
- registry.registerCommand({
45474
+ },
45475
+ {
44222
45476
  path: ["concierge", "chat"],
44223
45477
  description: "Interactive concierge chat (text, realtime, or voice)",
44224
45478
  requiresWorkspace: false,
@@ -44261,48 +45515,51 @@ function registerSpecialCommands(registry) {
44261
45515
  handler: async (hctx) => {
44262
45516
  await conciergeCommand(hctx);
44263
45517
  }
44264
- });
44265
- registry.registerCommand({
45518
+ },
45519
+ {
44266
45520
  path: ["dev", "import-local"],
44267
45521
  description: "Import remote workspace locally",
44268
45522
  requiresWorkspace: true,
44269
45523
  handler: async ({ ctx, workspace }) => {
44270
45524
  await devImportLocalCommand(requireAuth(ctx), workspace);
44271
45525
  }
44272
- });
44273
- registry.registerCommand({
45526
+ },
45527
+ {
44274
45528
  path: ["whoami"],
44275
45529
  description: "Show current user info",
44276
45530
  handler: async ({ ctx }) => {
44277
45531
  await whoamiCommand(requireAuth(ctx));
44278
45532
  }
44279
- });
44280
- registry.registerCommand({
45533
+ },
45534
+ {
44281
45535
  path: ["organizations", "list"],
44282
45536
  description: "List organizations",
44283
45537
  handler: async ({ ctx }) => {
44284
45538
  await organizationsListCommand(requireAuth(ctx));
44285
45539
  }
44286
- });
44287
- registry.registerCommand({
45540
+ },
45541
+ {
44288
45542
  path: ["orgs", "list"],
44289
45543
  description: "List organizations",
44290
45544
  handler: async ({ ctx }) => {
44291
45545
  await organizationsListCommand(requireAuth(ctx));
44292
45546
  }
44293
- });
44294
- }
45547
+ }
45548
+ ];
45549
+
45550
+ // src/lib.ts
45551
+ init_concierge_api();
44295
45552
 
44296
45553
  // package.json
44297
45554
  var package_default = {
44298
- version: "0.7.2"};
45555
+ version: "0.7.3"};
44299
45556
 
44300
45557
  // src/gr.ts
44301
45558
  var VERSION = package_default.version;
44302
45559
  function createRegistry() {
44303
45560
  const registry = new CommandRegistry();
44304
45561
  registerPublicDomains(registry);
44305
- registerSpecialCommands(registry);
45562
+ registry.registerCommands(topLevelCommands);
44306
45563
  return registry;
44307
45564
  }
44308
45565
  function parseGlobalOptions(argv) {
@@ -44409,7 +45666,8 @@ async function main() {
44409
45666
  workspace: ""
44410
45667
  };
44411
45668
  }
44412
- if (cmd.mutates && !opts.allowWrite) {
45669
+ const inSandbox = process.env.GRAVITY_RAIL_SANDBOX === "1";
45670
+ if (cmd.mutates && !opts.allowWrite && !inSandbox) {
44413
45671
  process.stderr.write(
44414
45672
  `Error: "${commandWords.join(" ")}" is a write operation. Pass --allow-write to execute.
44415
45673
  `