@wayai/cli 0.3.219 → 0.3.221

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/index.js CHANGED
@@ -5283,25 +5283,6 @@ var init_chunk_VXEAR36B = __esm({
5283
5283
  }
5284
5284
  });
5285
5285
 
5286
- // ../../packages/core/dist/chunk-GPM7PE44.js
5287
- var bootstrapQuery;
5288
- var init_chunk_GPM7PE44 = __esm({
5289
- "../../packages/core/dist/chunk-GPM7PE44.js"() {
5290
- "use strict";
5291
- init_zod();
5292
- bootstrapQuery = external_exports.object({
5293
- active_hub_id: external_exports.string().uuid().optional(),
5294
- active_conversation_id: external_exports.string().uuid().optional(),
5295
- active_nav: external_exports.enum(["chat", "task", "support"]).optional(),
5296
- /**
5297
- * The people thread the URL names (`/chat/threads/:threadId`, gh #4661): the snapshot
5298
- * preloads it as `people.active_thread` when the viewer is a member.
5299
- */
5300
- active_thread_id: external_exports.string().uuid().optional()
5301
- });
5302
- }
5303
- });
5304
-
5305
5286
  // ../../packages/core/dist/chunk-VORPHGDT.js
5306
5287
  var PERMISSIONS;
5307
5288
  var init_chunk_VORPHGDT = __esm({
@@ -5517,34 +5498,6 @@ var init_chunk_ZVXO3XL6 = __esm({
5517
5498
  }
5518
5499
  });
5519
5500
 
5520
- // ../../packages/core/dist/chunk-ZXK6N2HN.js
5521
- var PEOPLE_MODERATION_NOTE_MAX_LENGTH, ADMIN_PEOPLE_REPORTS_PAGE_MAX, ADMIN_PEOPLE_REPORTS_PAGE_DEFAULT, PEOPLE_SUSPENDED_REASON, peopleModerationActionSchema, moderationNoteSchema, adminPeopleReportListQuery, adminPeopleReportIdParam, adminPeopleMessageRemovalBody, adminPeopleSuspendBody, adminPeopleNoteBody;
5522
- var init_chunk_ZXK6N2HN = __esm({
5523
- "../../packages/core/dist/chunk-ZXK6N2HN.js"() {
5524
- "use strict";
5525
- init_chunk_ZVXO3XL6();
5526
- init_chunk_HZ6CADSY();
5527
- init_zod();
5528
- PEOPLE_MODERATION_NOTE_MAX_LENGTH = 500;
5529
- ADMIN_PEOPLE_REPORTS_PAGE_MAX = 100;
5530
- ADMIN_PEOPLE_REPORTS_PAGE_DEFAULT = 50;
5531
- PEOPLE_SUSPENDED_REASON = "suspended";
5532
- peopleModerationActionSchema = external_exports.enum(["remove_message", "suspend", "unsuspend", "dismiss"]);
5533
- moderationNoteSchema = optionalTrimmedText(PEOPLE_MODERATION_NOTE_MAX_LENGTH);
5534
- adminPeopleReportListQuery = external_exports.object({
5535
- pending: external_exports.enum(["true", "false"]).optional().transform((value) => value === "true"),
5536
- /** Lower bound on `created_at`. */
5537
- since: timestampSchema.optional(),
5538
- limit: external_exports.coerce.number().int().min(1).max(ADMIN_PEOPLE_REPORTS_PAGE_MAX).default(ADMIN_PEOPLE_REPORTS_PAGE_DEFAULT),
5539
- offset: external_exports.coerce.number().int().min(0).default(0)
5540
- });
5541
- adminPeopleReportIdParam = external_exports.object({ reportId: uuidSchema });
5542
- adminPeopleMessageRemovalBody = external_exports.object({ report_id: uuidSchema, message_id: uuidSchema.optional(), note: moderationNoteSchema }).strict();
5543
- adminPeopleSuspendBody = external_exports.object({ report_id: uuidSchema.optional(), note: moderationNoteSchema }).strict();
5544
- adminPeopleNoteBody = external_exports.object({ note: moderationNoteSchema }).strict();
5545
- }
5546
- });
5547
-
5548
5501
  // ../../packages/core/dist/chunk-Y7CFCYX4.js
5549
5502
  var PEOPLE_REPORT_DETAILS_MAX_LENGTH, peopleReportReasonSchema, reportDetailsSchema, reportFields, peopleReportBody;
5550
5503
  var init_chunk_Y7CFCYX4 = __esm({
@@ -5947,57 +5900,21 @@ var init_chunk_IPDOHAZ5 = __esm({
5947
5900
  }
5948
5901
  });
5949
5902
 
5950
- // ../../packages/core/dist/chunk-SY6PLCPK.js
5951
- var jsonSchemaSchema, hubUserIdentity, stateValueEntry, getHubUserContextResponse, updateHubUserBody, updateHubUserResponse, unlockHubUserNameResponse, stateResetParams, stateResetResponse;
5952
- var init_chunk_SY6PLCPK = __esm({
5953
- "../../packages/core/dist/chunk-SY6PLCPK.js"() {
5903
+ // ../../packages/core/dist/chunk-GPM7PE44.js
5904
+ var bootstrapQuery;
5905
+ var init_chunk_GPM7PE44 = __esm({
5906
+ "../../packages/core/dist/chunk-GPM7PE44.js"() {
5954
5907
  "use strict";
5955
- init_chunk_6TSQ5HXC();
5956
5908
  init_zod();
5957
- jsonSchemaSchema = external_exports.record(external_exports.unknown());
5958
- hubUserIdentity = external_exports.object({
5959
- user_id: external_exports.string().nullable(),
5960
- user_name: external_exports.string().nullable(),
5961
- user_email: external_exports.string().nullable(),
5962
- user_name_locked: external_exports.boolean(),
5963
- created_at: external_exports.string(),
5964
- updated_at: external_exports.string().nullable(),
5965
- hub_user_id: external_exports.string().optional(),
5966
- enabled: external_exports.boolean().optional(),
5967
- hub_team_id: external_exports.string().nullable().optional(),
5968
- source: external_exports.enum(["grant", "auto"]).optional()
5969
- });
5970
- stateValueEntry = external_exports.object({
5971
- state_slug: external_exports.string(),
5972
- state_name: external_exports.string(),
5973
- state_description: external_exports.string().nullable().optional(),
5974
- scope: external_exports.enum(["user", "conversation"]),
5975
- json_schema: jsonSchemaSchema,
5976
- initial_value: external_exports.unknown(),
5977
- value: external_exports.unknown(),
5978
- is_reserved: external_exports.boolean()
5979
- });
5980
- getHubUserContextResponse = external_exports.object({
5981
- user: hubUserIdentity,
5982
- user_states: external_exports.array(stateValueEntry),
5983
- conversation_states: external_exports.array(stateValueEntry)
5984
- });
5985
- updateHubUserBody = external_exports.object({
5986
- // Non-empty, non-null. `.nullable()` here would bypass `.min(1)` and let an
5987
- // admin arm the lock on a null name — see hub-do.ts updateHubUser null-guard.
5988
- user_name: external_exports.string().min(1).max(120)
5989
- });
5990
- updateHubUserResponse = external_exports.object({
5991
- user: hubUserIdentity
5992
- });
5993
- unlockHubUserNameResponse = external_exports.object({
5994
- user: hubUserIdentity
5995
- });
5996
- stateResetParams = external_exports.object({
5997
- stateSlug: slugSchema
5998
- });
5999
- stateResetResponse = external_exports.object({
6000
- ok: external_exports.literal(true)
5909
+ bootstrapQuery = external_exports.object({
5910
+ active_hub_id: external_exports.string().uuid().optional(),
5911
+ active_conversation_id: external_exports.string().uuid().optional(),
5912
+ active_nav: external_exports.enum(["chat", "task", "support"]).optional(),
5913
+ /**
5914
+ * The people thread the URL names (`/chat/threads/:threadId`, gh #4661): the snapshot
5915
+ * preloads it as `people.active_thread` when the viewer is a member.
5916
+ */
5917
+ active_thread_id: external_exports.string().uuid().optional()
6001
5918
  });
6002
5919
  }
6003
5920
  });
@@ -6106,98 +6023,31 @@ var init_chunk_FPSDNS2E = __esm({
6106
6023
  }
6107
6024
  });
6108
6025
 
6109
- // ../../packages/core/dist/chunk-LKBSHANA.js
6110
- var DESKTOP_SHELL_VERSION_RE, DESKTOP_PLATFORMS, DESKTOP_FLAVORS, desktopShellInfoSchema, DESKTOP_PRESENCE_STATES, desktopPresenceSchema, desktopUpdateSchema, DESKTOP_SIGN_IN_URL_MAX_LENGTH, DESKTOP_APP_PATH_MAX_LENGTH, desktopAppPathSchema, DESKTOP_NOTIFICATION_KINDS, DESKTOP_NOTIFICATION_TITLE_MAX_LENGTH, DESKTOP_NOTIFICATION_BODY_MAX_LENGTH, notificationTitleSchema, notificationBodySchema, desktopNotificationSchema, DESKTOP_BADGE_MAX_COUNT, DESKTOP_BADGE_LABEL_MAX_LENGTH, desktopBadgeSchema, desktopNavigateSchema, desktopSettingsSchema, desktopSettingsChangeSchema, desktopBridgeArgsSchemas;
6111
- var init_chunk_LKBSHANA = __esm({
6112
- "../../packages/core/dist/chunk-LKBSHANA.js"() {
6026
+ // ../../packages/core/dist/chunk-ZXK6N2HN.js
6027
+ var PEOPLE_MODERATION_NOTE_MAX_LENGTH, ADMIN_PEOPLE_REPORTS_PAGE_MAX, ADMIN_PEOPLE_REPORTS_PAGE_DEFAULT, PEOPLE_SUSPENDED_REASON, peopleModerationActionSchema, moderationNoteSchema, adminPeopleReportListQuery, adminPeopleReportIdParam, adminPeopleMessageRemovalBody, adminPeopleSuspendBody, adminPeopleNoteBody;
6028
+ var init_chunk_ZXK6N2HN = __esm({
6029
+ "../../packages/core/dist/chunk-ZXK6N2HN.js"() {
6113
6030
  "use strict";
6031
+ init_chunk_ZVXO3XL6();
6032
+ init_chunk_HZ6CADSY();
6114
6033
  init_zod();
6115
- DESKTOP_SHELL_VERSION_RE = /^(0|[1-9]\d{0,5})\.(0|[1-9]\d{0,5})\.(0|[1-9]\d{0,5})(-[0-9A-Za-z.-]{1,32})?$/;
6116
- DESKTOP_PLATFORMS = ["darwin", "win32"];
6117
- DESKTOP_FLAVORS = ["production", "development"];
6118
- desktopShellInfoSchema = external_exports.object({
6119
- /** The shell's own release version, independent of the web deploy. */
6120
- shellVersion: external_exports.string().regex(DESKTOP_SHELL_VERSION_RE),
6121
- /** The Electron runtime the shell was built with. */
6122
- electronVersion: external_exports.string().regex(/^\d{1,4}\.\d{1,4}\.\d{1,4}(-[0-9A-Za-z.-]{1,32})?$/),
6123
- platform: external_exports.enum(DESKTOP_PLATFORMS),
6124
- /** CPU architecture as Node reports it (`arm64`, `x64`). */
6125
- arch: external_exports.string().regex(/^[a-z0-9_]{1,16}$/),
6126
- flavor: external_exports.enum(DESKTOP_FLAVORS),
6127
- /**
6128
- * Present, and true, when the shell runs from the Microsoft Store's package: the Store updates it,
6129
- * and Windows alone opens it at login (the package's startup task, which the person turns on in
6130
- * Windows' settings). An optional field, so no new `bridgeVersion`: an older page ignores it, and
6131
- * its absence is every other shell.
6132
- */
6133
- store: external_exports.literal(true).optional()
6134
- });
6135
- DESKTOP_PRESENCE_STATES = ["present", "away"];
6136
- desktopPresenceSchema = external_exports.object({
6137
- presence: external_exports.enum(DESKTOP_PRESENCE_STATES),
6138
- mainWindow: external_exports.object({
6139
- shown: external_exports.boolean(),
6140
- focused: external_exports.boolean()
6141
- })
6142
- });
6143
- desktopUpdateSchema = external_exports.object({
6144
- ready: external_exports.object({
6145
- version: external_exports.string().regex(DESKTOP_SHELL_VERSION_RE),
6146
- offerRestart: external_exports.boolean()
6147
- }).nullable()
6148
- });
6149
- DESKTOP_SIGN_IN_URL_MAX_LENGTH = 4096;
6150
- DESKTOP_APP_PATH_MAX_LENGTH = 512;
6151
- desktopAppPathSchema = external_exports.string().max(DESKTOP_APP_PATH_MAX_LENGTH).regex(/^\/(?![/\\])[^\s\\]*$/);
6152
- DESKTOP_NOTIFICATION_KINDS = ["handoff", "message", "summary"];
6153
- DESKTOP_NOTIFICATION_TITLE_MAX_LENGTH = 200;
6154
- DESKTOP_NOTIFICATION_BODY_MAX_LENGTH = 500;
6155
- notificationTitleSchema = external_exports.string().min(1).max(DESKTOP_NOTIFICATION_TITLE_MAX_LENGTH);
6156
- notificationBodySchema = external_exports.string().max(DESKTOP_NOTIFICATION_BODY_MAX_LENGTH);
6157
- desktopNotificationSchema = external_exports.object({
6158
- kind: external_exports.enum(DESKTOP_NOTIFICATION_KINDS),
6159
- title: notificationTitleSchema,
6160
- body: notificationBodySchema,
6161
- path: desktopAppPathSchema,
6162
- withoutPreview: external_exports.object({ title: notificationTitleSchema, body: notificationBodySchema }).optional()
6163
- });
6164
- DESKTOP_BADGE_MAX_COUNT = 1e6;
6165
- DESKTOP_BADGE_LABEL_MAX_LENGTH = 200;
6166
- desktopBadgeSchema = external_exports.object({
6167
- count: external_exports.number().int().min(0).max(DESKTOP_BADGE_MAX_COUNT),
6168
- label: external_exports.string().max(DESKTOP_BADGE_LABEL_MAX_LENGTH)
6169
- });
6170
- desktopNavigateSchema = external_exports.object({
6171
- path: desktopAppPathSchema
6172
- });
6173
- desktopSettingsSchema = external_exports.object({
6174
- /** The app opens when the person logs in to the computer: the operating system's own login item. */
6175
- openAtLogin: external_exports.boolean(),
6176
- /** Closing the window keeps the app running in the tray (true), or quits it (false). */
6177
- closeToTray: external_exports.boolean(),
6178
- /** The shell shows notifications (true), or none (false). The badge is not a notification. */
6179
- notifications: external_exports.boolean(),
6180
- /**
6181
- * A customer message's notification shows the customer's name and words, where the platform
6182
- * allows them at all (`desktopShowsCustomerWords`: macOS); elsewhere the shell never shows them.
6183
- */
6184
- messagePreview: external_exports.boolean()
6185
- });
6186
- desktopSettingsChangeSchema = desktopSettingsSchema.partial().strict().refine((change) => Object.values(change).every((value) => typeof value === "boolean"), {
6187
- message: "each setting changed is true or false"
6034
+ PEOPLE_MODERATION_NOTE_MAX_LENGTH = 500;
6035
+ ADMIN_PEOPLE_REPORTS_PAGE_MAX = 100;
6036
+ ADMIN_PEOPLE_REPORTS_PAGE_DEFAULT = 50;
6037
+ PEOPLE_SUSPENDED_REASON = "suspended";
6038
+ peopleModerationActionSchema = external_exports.enum(["remove_message", "suspend", "unsuspend", "dismiss"]);
6039
+ moderationNoteSchema = optionalTrimmedText(PEOPLE_MODERATION_NOTE_MAX_LENGTH);
6040
+ adminPeopleReportListQuery = external_exports.object({
6041
+ pending: external_exports.enum(["true", "false"]).optional().transform((value) => value === "true"),
6042
+ /** Lower bound on `created_at`. */
6043
+ since: timestampSchema.optional(),
6044
+ limit: external_exports.coerce.number().int().min(1).max(ADMIN_PEOPLE_REPORTS_PAGE_MAX).default(ADMIN_PEOPLE_REPORTS_PAGE_DEFAULT),
6045
+ offset: external_exports.coerce.number().int().min(0).default(0)
6188
6046
  });
6189
- desktopBridgeArgsSchemas = {
6190
- getShellInfo: external_exports.tuple([]),
6191
- getPresence: external_exports.tuple([]),
6192
- openSignIn: external_exports.tuple([external_exports.string().max(DESKTOP_SIGN_IN_URL_MAX_LENGTH)]),
6193
- getUpdate: external_exports.tuple([]),
6194
- restartToUpdate: external_exports.tuple([]),
6195
- notify: external_exports.tuple([desktopNotificationSchema]),
6196
- setBadge: external_exports.tuple([desktopBadgeSchema]),
6197
- clearAll: external_exports.tuple([]),
6198
- getSettings: external_exports.tuple([]),
6199
- setSettings: external_exports.tuple([desktopSettingsChangeSchema])
6200
- };
6047
+ adminPeopleReportIdParam = external_exports.object({ reportId: uuidSchema });
6048
+ adminPeopleMessageRemovalBody = external_exports.object({ report_id: uuidSchema, message_id: uuidSchema.optional(), note: moderationNoteSchema }).strict();
6049
+ adminPeopleSuspendBody = external_exports.object({ report_id: uuidSchema.optional(), note: moderationNoteSchema }).strict();
6050
+ adminPeopleNoteBody = external_exports.object({ note: moderationNoteSchema }).strict();
6201
6051
  }
6202
6052
  });
6203
6053
 
@@ -7582,58 +7432,58 @@ var init_chunk_EA23LSDS = __esm({
7582
7432
  }
7583
7433
  });
7584
7434
 
7585
- // ../../packages/core/dist/chunk-3O5XTDI2.js
7586
- var CONSULT_THREAD_STATUSES, consultThreadStatus, CONSULT_THREAD_TITLE_MAX, consultThreadTitle, consultThreadSummary, listConsultThreadsQuery, listConsultThreadsResponse, createConsultThreadBody, createConsultThreadResponse, consultThreadIdParam, updateConsultThreadBody, updateConsultThreadResponse, CONSULT_AWAIT_TIMEOUT_MS;
7587
- var init_chunk_3O5XTDI2 = __esm({
7588
- "../../packages/core/dist/chunk-3O5XTDI2.js"() {
7435
+ // ../../packages/core/dist/chunk-SY6PLCPK.js
7436
+ var jsonSchemaSchema, hubUserIdentity, stateValueEntry, getHubUserContextResponse, updateHubUserBody, updateHubUserResponse, unlockHubUserNameResponse, stateResetParams, stateResetResponse;
7437
+ var init_chunk_SY6PLCPK = __esm({
7438
+ "../../packages/core/dist/chunk-SY6PLCPK.js"() {
7589
7439
  "use strict";
7440
+ init_chunk_6TSQ5HXC();
7590
7441
  init_zod();
7591
- CONSULT_THREAD_STATUSES = ["open", "awaiting", "resolved", "cancelled_at_close"];
7592
- consultThreadStatus = external_exports.enum(CONSULT_THREAD_STATUSES);
7593
- CONSULT_THREAD_TITLE_MAX = 120;
7594
- consultThreadTitle = external_exports.string().trim().min(1).max(CONSULT_THREAD_TITLE_MAX);
7595
- consultThreadSummary = external_exports.object({
7596
- consult_thread_id: external_exports.string(),
7597
- conversation_id: external_exports.string(),
7598
- initiator_type: external_exports.enum(["team", "agent"]),
7599
- initiator_id: external_exports.string(),
7600
- engaged_agent_id: external_exports.string().nullable(),
7601
- engaged_agent_name: external_exports.string().nullable(),
7602
- title: external_exports.string().nullable(),
7603
- status: consultThreadStatus,
7604
- created_at: external_exports.string()
7442
+ jsonSchemaSchema = external_exports.record(external_exports.unknown());
7443
+ hubUserIdentity = external_exports.object({
7444
+ user_id: external_exports.string().nullable(),
7445
+ user_name: external_exports.string().nullable(),
7446
+ user_email: external_exports.string().nullable(),
7447
+ user_name_locked: external_exports.boolean(),
7448
+ created_at: external_exports.string(),
7449
+ updated_at: external_exports.string().nullable(),
7450
+ hub_user_id: external_exports.string().optional(),
7451
+ enabled: external_exports.boolean().optional(),
7452
+ hub_team_id: external_exports.string().nullable().optional(),
7453
+ source: external_exports.enum(["grant", "auto"]).optional()
7605
7454
  });
7606
- listConsultThreadsQuery = external_exports.object({
7607
- hub_id: external_exports.string().uuid()
7455
+ stateValueEntry = external_exports.object({
7456
+ state_slug: external_exports.string(),
7457
+ state_name: external_exports.string(),
7458
+ state_description: external_exports.string().nullable().optional(),
7459
+ scope: external_exports.enum(["user", "conversation"]),
7460
+ json_schema: jsonSchemaSchema,
7461
+ initial_value: external_exports.unknown(),
7462
+ value: external_exports.unknown(),
7463
+ is_reserved: external_exports.boolean()
7608
7464
  });
7609
- listConsultThreadsResponse = external_exports.object({
7610
- threads: external_exports.array(consultThreadSummary)
7465
+ getHubUserContextResponse = external_exports.object({
7466
+ user: hubUserIdentity,
7467
+ user_states: external_exports.array(stateValueEntry),
7468
+ conversation_states: external_exports.array(stateValueEntry)
7611
7469
  });
7612
- createConsultThreadBody = external_exports.object({
7613
- hub_id: external_exports.string().uuid(),
7614
- title: consultThreadTitle.optional(),
7615
- // Optionally engage a consultant on creation. Validated server-side against the
7616
- // hub's `consultant`-role agents; a non-consultant / unknown id is rejected.
7617
- engaged_agent_id: external_exports.string().uuid().optional()
7470
+ updateHubUserBody = external_exports.object({
7471
+ // Non-empty, non-null. `.nullable()` here would bypass `.min(1)` and let an
7472
+ // admin arm the lock on a null name — see hub-do.ts updateHubUser null-guard.
7473
+ user_name: external_exports.string().min(1).max(120)
7618
7474
  });
7619
- createConsultThreadResponse = external_exports.object({
7620
- thread: consultThreadSummary
7475
+ updateHubUserResponse = external_exports.object({
7476
+ user: hubUserIdentity
7621
7477
  });
7622
- consultThreadIdParam = external_exports.object({
7623
- id: external_exports.string().uuid(),
7624
- threadId: external_exports.string().uuid()
7478
+ unlockHubUserNameResponse = external_exports.object({
7479
+ user: hubUserIdentity
7625
7480
  });
7626
- updateConsultThreadBody = external_exports.object({
7627
- hub_id: external_exports.string().uuid(),
7628
- title: consultThreadTitle.optional(),
7629
- engaged_agent_id: external_exports.string().uuid().optional()
7630
- }).refine((v) => v.title !== void 0 || v.engaged_agent_id !== void 0, {
7631
- message: "Provide a title and/or an engaged_agent_id to update"
7481
+ stateResetParams = external_exports.object({
7482
+ stateSlug: slugSchema
7632
7483
  });
7633
- updateConsultThreadResponse = external_exports.object({
7634
- thread: consultThreadSummary
7484
+ stateResetResponse = external_exports.object({
7485
+ ok: external_exports.literal(true)
7635
7486
  });
7636
- CONSULT_AWAIT_TIMEOUT_MS = 15 * 6e4;
7637
7487
  }
7638
7488
  });
7639
7489
 
@@ -7694,15 +7544,15 @@ var init_chunk_MH4O3YEX = __esm({
7694
7544
  }
7695
7545
  });
7696
7546
 
7697
- // ../../packages/core/dist/chunk-VBUWGVFY.js
7547
+ // ../../packages/core/dist/chunk-LDSABSRL.js
7698
7548
  function catalogToolSideEffects(toolName) {
7699
7549
  const sideEffects = CATALOG_SIDE_EFFECTS.get(toolName);
7700
7550
  if (sideEffects === void 0) return "unknown";
7701
7551
  return sideEffects ? "side_effects" : "none";
7702
7552
  }
7703
7553
  var NATIVE_TOOL_SCHEMAS, WAYAI_CONNECTOR, SANDBOX_AGENT_ROLES, BASE_NATIVE_TOOLS, NATIVE_TOOLS, CATALOG_SIDE_EFFECTS;
7704
- var init_chunk_VBUWGVFY = __esm({
7705
- "../../packages/core/dist/chunk-VBUWGVFY.js"() {
7554
+ var init_chunk_LDSABSRL = __esm({
7555
+ "../../packages/core/dist/chunk-LDSABSRL.js"() {
7706
7556
  "use strict";
7707
7557
  init_chunk_DHPUPI4Y();
7708
7558
  NATIVE_TOOL_SCHEMAS = {
@@ -8582,8 +8432,8 @@ var init_chunk_VBUWGVFY = __esm({
8582
8432
  SANDBOX_AGENT_ROLES = [...PILOT_TRACK_ROLES, ...COPILOT_TRACK_ROLES];
8583
8433
  BASE_NATIVE_TOOLS = [
8584
8434
  // --- Wayai core tools ---
8585
- { tool_native_id: "nt-001", tool_name: "transfer_to_agent", tool_display_name: "Transfer to Agent", tool_description: "Transfer the conversation to another AI agent", connector_id: WAYAI_CONNECTOR, operation: "transfer_to_agent", tool_method: "internal", tool_group: "Native Tools", is_delegation: true, is_auto_set: false, execution_config: null, side_effects: false, replay: "reconcile" },
8586
- { tool_native_id: "nt-002", tool_name: "transfer_to_team", tool_display_name: "Transfer to Team", tool_description: "Escalate conversation to a human support team", connector_id: WAYAI_CONNECTOR, operation: "transfer_to_team", tool_method: "internal", tool_group: "Native Tools", is_delegation: true, is_auto_set: false, execution_config: null, side_effects: false, replay: "reconcile" },
8435
+ { tool_native_id: "nt-001", tool_name: "transfer_to_agent", tool_display_name: "Transfer to Agent", tool_description: "Transfer the conversation to another AI agent", connector_id: WAYAI_CONNECTOR, operation: "transfer_to_agent", tool_method: "internal", tool_group: "Native Tools", is_delegation: true, is_auto_set: false, execution_config: null, side_effects: false, replay: "keyed" },
8436
+ { tool_native_id: "nt-002", tool_name: "transfer_to_team", tool_display_name: "Transfer to Team", tool_description: "Escalate conversation to a human support team", connector_id: WAYAI_CONNECTOR, operation: "transfer_to_team", tool_method: "internal", tool_group: "Native Tools", is_delegation: true, is_auto_set: false, execution_config: null, side_effects: false, replay: "keyed" },
8587
8437
  { tool_native_id: "nt-003", tool_name: "close_conversation", tool_display_name: "Close Conversation", tool_description: "Close and end the current conversation", connector_id: WAYAI_CONNECTOR, operation: "close_conversation", tool_method: "internal", tool_group: "Native Tools", is_delegation: false, is_auto_set: false, execution_config: null, side_effects: true, replay: "keyed" },
8588
8438
  { tool_native_id: "nt-004", tool_name: "update_kanban_status", tool_display_name: "Update Kanban Status", tool_description: "Update the kanban status of the conversation", connector_id: WAYAI_CONNECTOR, operation: "update_kanban_status", tool_method: "internal", tool_group: "Native Tools", is_delegation: false, is_auto_set: false, execution_config: null, side_effects: false, replay: "rerun" },
8589
8439
  { tool_native_id: "nt-005", tool_name: "schedule_followup", tool_display_name: "Schedule Follow-up", tool_description: "Schedule a follow-up message for the conversation", connector_id: WAYAI_CONNECTOR, operation: "schedule_followup", tool_method: "internal", tool_group: "Native Tools", is_delegation: false, is_auto_set: true, execution_config: null, side_effects: true, replay: "keyed" },
@@ -8592,7 +8442,7 @@ var init_chunk_VBUWGVFY = __esm({
8592
8442
  { tool_native_id: "nt-008", tool_name: "get_state", tool_display_name: "Get State", tool_description: "Retrieve conversation or user state values", connector_id: WAYAI_CONNECTOR, operation: "get_state", tool_method: "internal", tool_group: "Native Tools", is_delegation: false, is_auto_set: false, execution_config: null, side_effects: false, replay: "rerun" },
8593
8443
  { tool_native_id: "nt-009", tool_name: "reset_state", tool_display_name: "Reset State", tool_description: "Reset conversation or user state to initial values", connector_id: WAYAI_CONNECTOR, operation: "reset_state", tool_method: "internal", tool_group: "Native Tools", is_delegation: false, is_auto_set: false, execution_config: null, side_effects: false, replay: "rerun" },
8594
8444
  { tool_native_id: "nt-010", tool_name: "set_state_path", tool_display_name: "Set State Path", tool_description: "Set a specific path within state object", connector_id: WAYAI_CONNECTOR, operation: "set_state_path", tool_method: "internal", tool_group: "Native Tools", is_delegation: false, is_auto_set: false, execution_config: null, side_effects: false, replay: "rerun" },
8595
- { tool_native_id: "nt-011", tool_name: "consult_agent", tool_display_name: "Consult Agent", tool_description: "Consult an advisor agent for advice without transferring", connector_id: WAYAI_CONNECTOR, operation: "consult_agent", tool_method: "internal", tool_group: "Native Tools", is_delegation: false, is_auto_set: false, execution_config: null, side_effects: false, replay: "reconcile" },
8445
+ { tool_native_id: "nt-011", tool_name: "consult_agent", tool_display_name: "Consult Agent", tool_description: "Consult an advisor agent for advice without transferring", connector_id: WAYAI_CONNECTOR, operation: "consult_agent", tool_method: "internal", tool_group: "Native Tools", is_delegation: false, is_auto_set: false, execution_config: null, side_effects: false, replay: "keyed" },
8596
8446
  { tool_native_id: "nt-013", tool_name: "read_skill", tool_display_name: "Read Skill", tool_description: "Read the full specification of a skill", connector_id: WAYAI_CONNECTOR, operation: "read_skill", tool_method: "internal", tool_group: "Native Tools", is_delegation: false, is_auto_set: false, execution_config: null, side_effects: false, replay: "rerun" },
8597
8447
  { tool_native_id: "nt-014", tool_name: "read_skill_file", tool_display_name: "Read Skill File", tool_description: "Read a specific file within a skill", connector_id: WAYAI_CONNECTOR, operation: "read_skill_file", tool_method: "internal", tool_group: "Native Tools", is_delegation: false, is_auto_set: false, execution_config: null, side_effects: false, replay: "rerun" },
8598
8448
  { tool_native_id: "nt-015", tool_name: "read_file", tool_display_name: "Read File", tool_description: "Read the contents of a resource file", connector_id: WAYAI_CONNECTOR, operation: "read_file", tool_method: "internal", tool_group: "Native Tools", is_delegation: false, is_auto_set: false, execution_config: null, side_effects: false, replay: "rerun" },
@@ -8640,7 +8490,7 @@ var init_chunk_VBUWGVFY = __esm({
8640
8490
  // collect (and, for a consultant target, the `allow_consultant_chain` opt-in). A
8641
8491
  // live button that only ever errors is worse than no button. Assign via `wayai push`
8642
8492
  // until the picker ships.
8643
- { tool_native_id: "nt-026", tool_name: "start_consult_thread", tool_display_name: "Start Consult Thread", tool_description: "Ask a configured consultant (or partner hub) a question in a visible consult thread", connector_id: WAYAI_CONNECTOR, operation: "start_consult_thread", tool_method: "internal", tool_group: "Native Tools", is_delegation: true, is_auto_set: false, execution_config: null, side_effects: true, replay: "reconcile", ui_assignable: false },
8493
+ { tool_native_id: "nt-026", tool_name: "start_consult_thread", tool_display_name: "Start Consult Thread", tool_description: "Ask a configured consultant (or partner hub) a question in a visible consult thread", connector_id: WAYAI_CONNECTOR, operation: "start_consult_thread", tool_method: "internal", tool_group: "Native Tools", is_delegation: true, is_auto_set: false, execution_config: null, side_effects: true, replay: "keyed", ui_assignable: false },
8644
8494
  // One drill-down listing for every file namespace, replacing `list_resource_files`
8645
8495
  // (nt-016) and `list_resource_folders` (nt-017). Fully visible: it needs no
8646
8496
  // configuration the Add dialog cannot collect — the mounts an agent may browse
@@ -8914,7 +8764,7 @@ var init_chunk_T7KQKDET = __esm({
8914
8764
  }
8915
8765
  });
8916
8766
 
8917
- // ../../packages/core/dist/chunk-6WCPZ26B.js
8767
+ // ../../packages/core/dist/chunk-7EGDXEYG.js
8918
8768
  function resolveMonitorTrigger(monitorConfig) {
8919
8769
  if (!monitorConfig || typeof monitorConfig !== "object") return "idle";
8920
8770
  const raw = monitorConfig.trigger;
@@ -9220,10 +9070,10 @@ function refineMonitorRulesStructuredOutput(body, ctx) {
9220
9070
  if (refusal2) ctx.addIssue({ code: external_exports.ZodIssueCode.custom, path: ["response_format"], message: refusal2 });
9221
9071
  }
9222
9072
  var NATIVE_TOOL_NAMES, previousConversationsCountField, summarizationThresholdField, flagConditionSchema, MONITOR_TRIGGERS, monitorTriggerSchema, AUTOMATION_GATE_TRIGGERS, NON_FIRING_TRIGGERS, MONITOR_FIRING_TRIGGERS, MONITOR_DELAY_SECONDS_MIN, MONITOR_IDLE_DELAY_REQUIRED_MESSAGE, MONITOR_HISTORY_MESSAGES_MAX, monitorHistoryMessagesSchema, monitorIncludeToolResultsSchema, MONITOR_INPUT_SHAPING_KEYS, MONITOR_INPUT_SHAPING_SCHEMAS, MONITOR_INPUT_SHAPING_IDLE_MESSAGE, monitorArgumentSourceSchema, MONITOR_NOTE_TEMPLATE_MAX, MONITOR_STEER_NOTE_MAX, MONITOR_GATE_AGENT_NAME_MAX, monitorActionSchema, monitorRuleSchema, MONITOR_RULE_KEYS, MONITOR_RULE_SCHEMAS, MONITOR_RULE_TRIGGERS, MONITOR_RULE_TRIGGER_MESSAGE, CALL_UTTERANCE_SPEAKERS, callUtteranceSpeakerSchema, MONITOR_CALL_KEYS, MONITOR_CALL_SCHEMAS, MONITOR_CALL_KEY_MESSAGE, CALL_STEERING_MIN_CONFIDENCE, CALL_UTTERANCE_RULE_NOT_CONFIDENT_MESSAGE, CALL_UTTERANCE_FALLBACK_MESSAGE, CALL_UTTERANCE_FLAG_CONDITIONS_MESSAGE, CALL_STEER_NOTE_BLANK_MESSAGE, MONITOR_USER_MESSAGE_ACTION_KINDS, MONITOR_ASSISTANT_REPLY_ACTION_KINDS, MONITOR_CALL_UTTERANCE_ACTION_KINDS, MONITOR_AUTOMATION_FIRE_ACTION_KINDS, MONITOR_AUTOMATION_ITEM_ACTION_KINDS, INSERT_NOTE_TOOL_NAME, RUN_MONITOR_TOOL_NAME, MONITOR_RULE_ALLOWED_NATIVE_TOOLS, MONITOR_RULE_REENTRY_TOOLS, MONITOR_RULE_REENTRY_TRACKS, AUTOMATION_FIRE_FLAG_CONDITIONS_MESSAGE, AUTOMATION_FIRE_INPUT_SHAPING_MESSAGE, AUTOMATION_ITEM_FLAG_CONDITIONS_MESSAGE, AUTOMATION_ITEM_INPUT_SHAPING_MESSAGE, AUTOMATION_GATE_KEY_MESSAGES, monitorConfigField, flagConditionsField, agentIdParam, listAgentsQuery, agentConnectionsQuery, createAgentBody, updateAgentBody, AGENT_PARAMETER_TYPES, AGENT_PARAMETER_NAME_REGEX, agentParameterCreateSchema, MAX_AGENT_PARAMETERS_PER_REQUEST, createAgentParametersBody;
9223
- var init_chunk_6WCPZ26B = __esm({
9224
- "../../packages/core/dist/chunk-6WCPZ26B.js"() {
9073
+ var init_chunk_7EGDXEYG = __esm({
9074
+ "../../packages/core/dist/chunk-7EGDXEYG.js"() {
9225
9075
  "use strict";
9226
- init_chunk_VBUWGVFY();
9076
+ init_chunk_LDSABSRL();
9227
9077
  init_chunk_IBL7FANV();
9228
9078
  init_chunk_PFDZEKDE();
9229
9079
  init_chunk_HZ6CADSY();
@@ -9446,12 +9296,12 @@ var init_chunk_6WCPZ26B = __esm({
9446
9296
  }
9447
9297
  });
9448
9298
 
9449
- // ../../packages/core/dist/chunk-YVHDDEQV.js
9299
+ // ../../packages/core/dist/chunk-3OWAWA5B.js
9450
9300
  var conversationIdParam, conversationHubQuery, claimBody, releaseBody, transferBody, closeBody, additionalContextPayloadSchema, kanbanUpdateBody, annotateConversationBody, observabilityParams, observabilityListParams, deleteUserConversationsBody, deleteUserConversationsResponse, sendMessageBody, listConversationsQuery, flagSourceSchema, getConversationsResponse, getConversationDetailParams, getConversationDetailQuery, getConversationDetailResponse, listWhatsAppTemplatesQuery, sendWhatsAppTemplateBody;
9451
- var init_chunk_YVHDDEQV = __esm({
9452
- "../../packages/core/dist/chunk-YVHDDEQV.js"() {
9301
+ var init_chunk_3OWAWA5B = __esm({
9302
+ "../../packages/core/dist/chunk-3OWAWA5B.js"() {
9453
9303
  "use strict";
9454
- init_chunk_6WCPZ26B();
9304
+ init_chunk_7EGDXEYG();
9455
9305
  init_chunk_HZ6CADSY();
9456
9306
  init_chunk_DHPUPI4Y();
9457
9307
  init_zod();
@@ -9748,115 +9598,98 @@ var init_chunk_KSTYTQ7I = __esm({
9748
9598
  }
9749
9599
  });
9750
9600
 
9751
- // ../../packages/core/dist/chunk-7CYHPF35.js
9752
- var appMessageSenderType, appMessageReceiverType, apiChannelMessage, apiChannelMessageBody, appMessageBody, appMessageResponse;
9753
- var init_chunk_7CYHPF35 = __esm({
9754
- "../../packages/core/dist/chunk-7CYHPF35.js"() {
9601
+ // ../../packages/core/dist/chunk-LKBSHANA.js
9602
+ var DESKTOP_SHELL_VERSION_RE, DESKTOP_PLATFORMS, DESKTOP_FLAVORS, desktopShellInfoSchema, DESKTOP_PRESENCE_STATES, desktopPresenceSchema, desktopUpdateSchema, DESKTOP_SIGN_IN_URL_MAX_LENGTH, DESKTOP_APP_PATH_MAX_LENGTH, desktopAppPathSchema, DESKTOP_NOTIFICATION_KINDS, DESKTOP_NOTIFICATION_TITLE_MAX_LENGTH, DESKTOP_NOTIFICATION_BODY_MAX_LENGTH, notificationTitleSchema, notificationBodySchema, desktopNotificationSchema, DESKTOP_BADGE_MAX_COUNT, DESKTOP_BADGE_LABEL_MAX_LENGTH, desktopBadgeSchema, desktopNavigateSchema, desktopSettingsSchema, desktopSettingsChangeSchema, desktopBridgeArgsSchemas;
9603
+ var init_chunk_LKBSHANA = __esm({
9604
+ "../../packages/core/dist/chunk-LKBSHANA.js"() {
9755
9605
  "use strict";
9756
- init_chunk_HZ6CADSY();
9757
9606
  init_zod();
9758
- appMessageSenderType = external_exports.enum(["user", "team"]);
9759
- appMessageReceiverType = external_exports.enum(["user", "team", "agent", "assistant"]).transform((v) => v === "assistant" ? "agent" : v);
9760
- apiChannelMessage = external_exports.object({
9761
- text: clientOptionalString,
9762
- attachments: external_exports.array(messageAttachment).max(MAX_ATTACHMENTS_PER_MESSAGE).nullish().transform((v) => v ?? void 0)
9763
- }).refine((m) => m.text && m.text.length > 0 || m.attachments && m.attachments.length > 0, {
9764
- message: "message must have text or at least one attachment"
9607
+ DESKTOP_SHELL_VERSION_RE = /^(0|[1-9]\d{0,5})\.(0|[1-9]\d{0,5})\.(0|[1-9]\d{0,5})(-[0-9A-Za-z.-]{1,32})?$/;
9608
+ DESKTOP_PLATFORMS = ["darwin", "win32"];
9609
+ DESKTOP_FLAVORS = ["production", "development"];
9610
+ desktopShellInfoSchema = external_exports.object({
9611
+ /** The shell's own release version, independent of the web deploy. */
9612
+ shellVersion: external_exports.string().regex(DESKTOP_SHELL_VERSION_RE),
9613
+ /** The Electron runtime the shell was built with. */
9614
+ electronVersion: external_exports.string().regex(/^\d{1,4}\.\d{1,4}\.\d{1,4}(-[0-9A-Za-z.-]{1,32})?$/),
9615
+ platform: external_exports.enum(DESKTOP_PLATFORMS),
9616
+ /** CPU architecture as Node reports it (`arm64`, `x64`). */
9617
+ arch: external_exports.string().regex(/^[a-z0-9_]{1,16}$/),
9618
+ flavor: external_exports.enum(DESKTOP_FLAVORS),
9619
+ /**
9620
+ * Present, and true, when the shell runs from the Microsoft Store's package: the Store updates it,
9621
+ * and Windows alone opens it at login (the package's startup task, which the person turns on in
9622
+ * Windows' settings). An optional field, so no new `bridgeVersion`: an older page ignores it, and
9623
+ * its absence is every other shell.
9624
+ */
9625
+ store: external_exports.literal(true).optional()
9765
9626
  });
9766
- apiChannelMessageBody = external_exports.object({
9767
- // Correlation id (task hubs): new → new conversation, repeat → continue. min 1 so an
9768
- // empty string can't masquerade as a ref. Mutually exclusive with conversation_id.
9769
- external_ref: external_exports.string().min(1).max(256).optional(),
9770
- // Continue a specific WayAI conversation (authorized against the hub/channel + owner).
9771
- // UUID-validated here (unlike the app channel, whose client we control): allocation
9772
- // only treats a UUID-shaped id as a provided conversation, so a malformed id would
9773
- // otherwise skip the owner guard and silently MINT a new conversation instead of
9774
- // rejecting. A format 400 is shape-only — not an existence oracle (a valid-but-unknown
9775
- // UUID still collapses to the opaque authorization error downstream).
9776
- conversation_id: external_exports.string().uuid().optional(),
9777
- // On-behalf-of end-user identity. Absent → per-connection service principal (task-hub
9778
- // only; chat hub rejects with 422 in the route).
9779
- user: external_exports.object({
9780
- id: external_exports.string().min(1),
9781
- email: clientOptionalString,
9782
- name: clientOptionalString
9783
- }).optional(),
9784
- message: apiChannelMessage,
9785
- // Idempotency key: maps to channel_message_sid, deduped within one conversation
9786
- // (ConversationDO.storeMessage). A retried POST resolves to the same conversation (a chat
9787
- // hub's user, the external_ref, the conversation_id, or on a task hub with neither, this key
9788
- // scoped by the sender), so it echoes the original message_id and skips billing / turn
9789
- // dispatch. A failed store answers a retryable 503 only when this key is set; without it a
9790
- // retry could store the message twice, so it answers 400.
9791
- client_message_id: external_exports.string().min(1).max(256).optional()
9792
- }).refine((b) => !(b.external_ref && b.conversation_id), {
9793
- message: "provide external_ref or conversation_id, not both",
9794
- path: ["external_ref"]
9627
+ DESKTOP_PRESENCE_STATES = ["present", "away"];
9628
+ desktopPresenceSchema = external_exports.object({
9629
+ presence: external_exports.enum(DESKTOP_PRESENCE_STATES),
9630
+ mainWindow: external_exports.object({
9631
+ shown: external_exports.boolean(),
9632
+ focused: external_exports.boolean()
9633
+ })
9795
9634
  });
9796
- appMessageBody = external_exports.object({
9797
- // Message content — three historical aliases. All optional: an attachment-only
9798
- // or voice-only message carries no text.
9799
- content: clientOptionalString,
9800
- message_text: clientOptionalString,
9801
- message_body: clientOptionalString,
9802
- // Conversation context. Ids are plain strings rather than `.uuid()` on purpose:
9803
- // they are AUTHORIZED downstream, which is the stronger guarantee — a well-formed
9804
- // uuid belonging to another tenant must fail just as hard as junk. `hub_id` is
9805
- // gated by `assertHubEndUserAccess` (gh #3286) and `conversation_id` by HubDO's
9806
- // conversation_index owner check (gh #2781, #3281). The route's own falsy guards
9807
- // ('hub_id is required') still reject an empty one.
9808
- hub_id: clientOptionalString,
9809
- channel_id: clientOptionalString,
9810
- conversation_id: clientOptionalString,
9811
- hub_type: external_exports.enum(["chat", "task"]).nullish().transform((v) => v ?? void 0),
9812
- // Stable idempotency key for one explicit task-hub launcher. HubDO scopes it
9813
- // to the authenticated user and resolves retries/tabs to one conversation.
9814
- task_start_id: external_exports.string().uuid().nullish().transform((v) => v ?? void 0),
9815
- // Routing.
9816
- sender_type: appMessageSenderType.nullish().transform((v) => v ?? void 0),
9817
- receiver_type: appMessageReceiverType.nullish().transform((v) => v ?? void 0),
9818
- // Only meaningful on a team send, where `validateAppTeamSendContext` proves the
9819
- // caller may send to this receiver. Absent on a team send to a conversation with no
9820
- // person, which names its `conversation_id` instead. The end-user branch ignores it —
9821
- // see the receiver derivation in the route.
9822
- user_receiver_id: clientOptionalString,
9823
- // ── Internal consult (consultant-agents PR 2 — H1.0) ──────────────────────
9824
- // A team member handling a customer conversation can tag a `consultant`-role
9825
- // agent for a PRIVATE, team-only exchange that never reaches the customer. A
9826
- // consult send is a team send with `receiver_type: 'agent'` targeting the
9827
- // consultant; `user_receiver_id` identifies the customer whose conversation this is
9828
- // (and is authorized by `validateAppTeamSendContext`, exactly as a team→user send is),
9829
- // and is absent, as on a team→user send, when the conversation has no person. The consultant is resolved from `agent_receiver_id`
9830
- // when supplied, else from an `@mention` parsed out of the message text against
9831
- // the hub's consultant agents. `consult_thread_id` continues an existing thread;
9832
- // absent, the route creates/reuses the single implicit thread. These fields are
9833
- // inert on every non-consult send (end-user send, team→user send).
9834
- agent_receiver_id: clientOptionalString,
9835
- consult_thread_id: clientOptionalString,
9836
- is_first_message: clientOptionalBoolean,
9837
- end_conversation: clientOptionalBoolean,
9838
- // Pre-generated by the client so the optimistic bubble and the stored row share
9839
- // a key (transcription live-updates land on the same row instead of duplicating).
9840
- message_id: clientOptionalString,
9841
- attachments: external_exports.array(messageAttachment).max(MAX_ATTACHMENTS_PER_MESSAGE).nullish().transform((v) => v ?? void 0),
9842
- // Base64-encoded audio for STT. Size-capped in the route (the cap is a byte
9843
- // budget tied to the /channels/* bodyLimit, not a shape rule).
9844
- audio_file: clientOptionalString
9635
+ desktopUpdateSchema = external_exports.object({
9636
+ ready: external_exports.object({
9637
+ version: external_exports.string().regex(DESKTOP_SHELL_VERSION_RE),
9638
+ offerRestart: external_exports.boolean()
9639
+ }).nullable()
9845
9640
  });
9846
- appMessageResponse = external_exports.object({
9847
- success: external_exports.boolean(),
9848
- message: external_exports.string(),
9849
- result: external_exports.object({
9850
- conversation_id: external_exports.string().optional(),
9851
- message_id: external_exports.string().optional(),
9852
- status: external_exports.string().optional(),
9853
- files: external_exports.array(external_exports.record(external_exports.string(), external_exports.unknown())).optional(),
9854
- // True when this request reused a task-start/message id already accepted by
9855
- // the server. Clients must replace their optimistic payload with a fresh
9856
- // authoritative read because another tab may have won with different text.
9857
- deduped: external_exports.boolean().optional()
9858
- }).optional()
9641
+ DESKTOP_SIGN_IN_URL_MAX_LENGTH = 4096;
9642
+ DESKTOP_APP_PATH_MAX_LENGTH = 512;
9643
+ desktopAppPathSchema = external_exports.string().max(DESKTOP_APP_PATH_MAX_LENGTH).regex(/^\/(?![/\\])[^\s\\]*$/);
9644
+ DESKTOP_NOTIFICATION_KINDS = ["handoff", "message", "summary"];
9645
+ DESKTOP_NOTIFICATION_TITLE_MAX_LENGTH = 200;
9646
+ DESKTOP_NOTIFICATION_BODY_MAX_LENGTH = 500;
9647
+ notificationTitleSchema = external_exports.string().min(1).max(DESKTOP_NOTIFICATION_TITLE_MAX_LENGTH);
9648
+ notificationBodySchema = external_exports.string().max(DESKTOP_NOTIFICATION_BODY_MAX_LENGTH);
9649
+ desktopNotificationSchema = external_exports.object({
9650
+ kind: external_exports.enum(DESKTOP_NOTIFICATION_KINDS),
9651
+ title: notificationTitleSchema,
9652
+ body: notificationBodySchema,
9653
+ path: desktopAppPathSchema,
9654
+ withoutPreview: external_exports.object({ title: notificationTitleSchema, body: notificationBodySchema }).optional()
9655
+ });
9656
+ DESKTOP_BADGE_MAX_COUNT = 1e6;
9657
+ DESKTOP_BADGE_LABEL_MAX_LENGTH = 200;
9658
+ desktopBadgeSchema = external_exports.object({
9659
+ count: external_exports.number().int().min(0).max(DESKTOP_BADGE_MAX_COUNT),
9660
+ label: external_exports.string().max(DESKTOP_BADGE_LABEL_MAX_LENGTH)
9661
+ });
9662
+ desktopNavigateSchema = external_exports.object({
9663
+ path: desktopAppPathSchema
9664
+ });
9665
+ desktopSettingsSchema = external_exports.object({
9666
+ /** The app opens when the person logs in to the computer: the operating system's own login item. */
9667
+ openAtLogin: external_exports.boolean(),
9668
+ /** Closing the window keeps the app running in the tray (true), or quits it (false). */
9669
+ closeToTray: external_exports.boolean(),
9670
+ /** The shell shows notifications (true), or none (false). The badge is not a notification. */
9671
+ notifications: external_exports.boolean(),
9672
+ /**
9673
+ * A customer message's notification shows the customer's name and words, where the platform
9674
+ * allows them at all (`desktopShowsCustomerWords`: macOS); elsewhere the shell never shows them.
9675
+ */
9676
+ messagePreview: external_exports.boolean()
9677
+ });
9678
+ desktopSettingsChangeSchema = desktopSettingsSchema.partial().strict().refine((change) => Object.values(change).every((value) => typeof value === "boolean"), {
9679
+ message: "each setting changed is true or false"
9859
9680
  });
9681
+ desktopBridgeArgsSchemas = {
9682
+ getShellInfo: external_exports.tuple([]),
9683
+ getPresence: external_exports.tuple([]),
9684
+ openSignIn: external_exports.tuple([external_exports.string().max(DESKTOP_SIGN_IN_URL_MAX_LENGTH)]),
9685
+ getUpdate: external_exports.tuple([]),
9686
+ restartToUpdate: external_exports.tuple([]),
9687
+ notify: external_exports.tuple([desktopNotificationSchema]),
9688
+ setBadge: external_exports.tuple([desktopBadgeSchema]),
9689
+ clearAll: external_exports.tuple([]),
9690
+ getSettings: external_exports.tuple([]),
9691
+ setSettings: external_exports.tuple([desktopSettingsChangeSchema])
9692
+ };
9860
9693
  }
9861
9694
  });
9862
9695
 
@@ -9924,7 +9757,7 @@ var init_chunk_BPCNB5RT = __esm({
9924
9757
  }
9925
9758
  });
9926
9759
 
9927
- // ../../packages/core/dist/chunk-5KFFZX2J.js
9760
+ // ../../packages/core/dist/chunk-ROS7PLDY.js
9928
9761
  function idempotencyHeaderRefusal(value) {
9929
9762
  if (typeof value !== "string" || !/^[A-Za-z0-9][A-Za-z0-9-]{0,63}$/.test(value)) {
9930
9763
  return "idempotency_header must be a header name: letters, digits and dashes, at most 64";
@@ -9935,10 +9768,10 @@ function idempotencyHeaderRefusal(value) {
9935
9768
  return null;
9936
9769
  }
9937
9770
  var CATALOG_REPLAY, REPLAY_OVERRIDES, RESERVED_HEADERS;
9938
- var init_chunk_5KFFZX2J = __esm({
9939
- "../../packages/core/dist/chunk-5KFFZX2J.js"() {
9771
+ var init_chunk_ROS7PLDY = __esm({
9772
+ "../../packages/core/dist/chunk-ROS7PLDY.js"() {
9940
9773
  "use strict";
9941
- init_chunk_VBUWGVFY();
9774
+ init_chunk_LDSABSRL();
9942
9775
  CATALOG_REPLAY = new Map(
9943
9776
  NATIVE_TOOLS.map((tool) => [tool.tool_name, tool.replay])
9944
9777
  );
@@ -10171,7 +10004,7 @@ var init_chunk_WEXVYJ5H = __esm({
10171
10004
  }
10172
10005
  });
10173
10006
 
10174
- // ../../packages/core/dist/chunk-D26NGKIY.js
10007
+ // ../../packages/core/dist/chunk-AFIQ3FEW.js
10175
10008
  function refineToolConfig(value, ctx) {
10176
10009
  const raw = value.tool_config;
10177
10010
  if (raw == null) return;
@@ -10207,10 +10040,10 @@ function refineToolConfig(value, ctx) {
10207
10040
  }
10208
10041
  }
10209
10042
  var toolIdParam, listToolsQuery, toolAgentQuery, deleteToolQuery, toolConnectionsQuery, nativeToolIdSchema, CONTEXT_BOUNDARIES, contextBoundarySchema, addNativeToolBody, addMcpToolBody, toolReplaySettingsFields, toolReplaySettingsSchema, createCustomToolBody, updateCustomToolBody, updateToolExecutionConfigBody;
10210
- var init_chunk_D26NGKIY = __esm({
10211
- "../../packages/core/dist/chunk-D26NGKIY.js"() {
10043
+ var init_chunk_AFIQ3FEW = __esm({
10044
+ "../../packages/core/dist/chunk-AFIQ3FEW.js"() {
10212
10045
  "use strict";
10213
- init_chunk_5KFFZX2J();
10046
+ init_chunk_ROS7PLDY();
10214
10047
  init_chunk_WEXVYJ5H();
10215
10048
  init_chunk_HZ6CADSY();
10216
10049
  init_zod();
@@ -10321,7 +10154,7 @@ var init_chunk_2ISUBJG7 = __esm({
10321
10154
  }
10322
10155
  });
10323
10156
 
10324
- // ../../packages/core/dist/chunk-7MRZJN4O.js
10157
+ // ../../packages/core/dist/chunk-623SRYWZ.js
10325
10158
  function describeRole(role) {
10326
10159
  if (typeof role === "string") {
10327
10160
  return JSON.stringify(role.length > ROLE_ECHO_MAX ? `${role.slice(0, ROLE_ECHO_MAX)}\u2026` : role);
@@ -10495,8 +10328,8 @@ function terminalRunCount(counts) {
10495
10328
  return counts.successful_runs + counts.failed_runs;
10496
10329
  }
10497
10330
  var evalIdParam, sessionIdParam, scenarioSetIdParam, hubIdQuery, EVAL_FIXTURE_NAME_MAX_LENGTH, evalFixtureOverrideSchema, runSessionQuery, runJourneyQuery, EVAL_INPUT_ROLES, EVAL_INPUT_ROLE_LIST, ROLE_ECHO_MAX, EVAL_INITIAL_STATE_SCOPES, MAX_INITIAL_STATE_ENTRIES, evalInitialStateEntry, evalCustomerContactIdSchema, evalBody, EVAL_LIST_MAX_LIMIT, evalListLimit, getEvalsQuery, toggleEvalBody, bulkToggleEvalsBody, pacingConfigSchema, EVAL_MAX_SELECTED_SCENARIOS, evalScenarioSelectionEntrySchema, evalScenarioSelectionSchema, sessionConfigSchema, createSessionBody, getSessionsQuery, getSessionResultsQuery, getSessionRunsQuery, evalAnalyticsQuery, getSessionCostQuery, compareSessionsQuery, evalsSqlBody, evalsSqlSchemaQuery, exportResultsQuery, validateEvalBody, hubAgentsQuery, createScenarioSetBody, updateScenarioSetBody, scenarioSetsHubQuery, createScenarioFromConversationBody, createJourneyFromConversationBody, evalAttachmentRef, turnMayCarryAttachments, ATTACHMENTS_USER_ONLY_MESSAGE, journeyIdParam, journeyToolCallSchema, journeyTurnSchema, journeyStepOverrideSchema, fixtureField, createJourneyBody, updateJourneyBody, evalSessionConfigResponseSchema, evalSessionResponseSchema, evalSessionListConfigSchema, evalSessionListItemSchema, seedReleaseStatusSchema, EVAL_SESSION_NOT_QUIESCENT;
10498
- var init_chunk_7MRZJN4O = __esm({
10499
- "../../packages/core/dist/chunk-7MRZJN4O.js"() {
10331
+ var init_chunk_623SRYWZ = __esm({
10332
+ "../../packages/core/dist/chunk-623SRYWZ.js"() {
10500
10333
  "use strict";
10501
10334
  init_chunk_4LXDRTO4();
10502
10335
  init_chunk_LZDVDC2S();
@@ -11582,7 +11415,7 @@ var init_chunk_6NI5RAM4 = __esm({
11582
11415
  }
11583
11416
  });
11584
11417
 
11585
- // ../../packages/core/dist/chunk-DBQLPVOO.js
11418
+ // ../../packages/core/dist/chunk-NYIIBG23.js
11586
11419
  function refineHubAsCodeCustomTools(config, ctx) {
11587
11420
  const agents = config.agents;
11588
11421
  if (!Array.isArray(agents)) return;
@@ -11726,14 +11559,22 @@ function refineHubAsCodeEvals(config, ctx) {
11726
11559
  message: `eval "${entry?.name ?? "<unnamed>"}": ${initialStateError}`
11727
11560
  });
11728
11561
  }
11729
- const customerError = evalCustomerContactIdError(entry);
11730
- if (customerError) {
11731
- ctx.addIssue({
11732
- code: external_exports.ZodIssueCode.custom,
11733
- path: ["evals", e, "customer_contact_id"],
11734
- message: `eval "${entry?.name ?? "<unnamed>"}": ${customerError}`
11735
- });
11736
- }
11562
+ }
11563
+ }
11564
+ function refineHubAsCodeCustomers(config, ctx) {
11565
+ for (const [key, kind] of [["evals", "eval"], ["journeys", "journey"]]) {
11566
+ const entries = config[key];
11567
+ if (!Array.isArray(entries)) continue;
11568
+ entries.forEach((entry, i) => {
11569
+ const error = evalCustomerContactIdError(entry);
11570
+ if (error) {
11571
+ ctx.addIssue({
11572
+ code: external_exports.ZodIssueCode.custom,
11573
+ path: [key, i, "customer_contact_id"],
11574
+ message: `${kind} "${entry?.name ?? "<unnamed>"}": ${error}`
11575
+ });
11576
+ }
11577
+ });
11737
11578
  }
11738
11579
  }
11739
11580
  function refineHubAsCodeEvalAttachments(config, ctx) {
@@ -12110,12 +11951,12 @@ function refineHubAsCodeMonitorRulesOutput(config, ctx) {
12110
11951
  });
12111
11952
  }
12112
11953
  var MAX_10MB_BASE64_ENCODED_BYTES, MAX_EVAL_ATTACHMENT_ENCODED_BYTES, MAX_EVAL_ATTACHMENT_CARRIERS, MAX_EVAL_ATTACHMENT_AGGREGATE_ENCODED_BYTES, MAX_RESOURCE_ENCODED_BYTES, MAX_HUB_AS_CODE_RESOURCES, MAX_HUB_AS_CODE_RESOURCE_FILES, MAX_RESOURCE_AGGREGATE_ENCODED_BYTES, MAX_CI_CONFIG_BODY_BYTES, MAX_CALL_OPENING_CARRIERS, MAX_CALL_OPENING_AGGREGATE_ENCODED_BYTES, hubAsCodeStateSchema, hubAsCodeResourceFileSchema, hubAsCodeResourceSchema, uuidPattern, ciUuidSchema, boundedHubAsCodeResourcesSchema, hubAsCodeConfigSchema, ciPullHubIdParam, ciBranchParam, ciPullQuery, ciHubsQuery, ciLookupQuery, ciBranchesQuery, ciSyncBody, ciPushBody, ciDiffBody, ciPublishBody, ciPublishPreviewBody, ciSyncMcpBody, ciOrgResourcesParam, orgResourcesConfigSchema, ciOrgResourcesPushBody, ciOrgResourcesDiffBody, CI_APPLY_ENTITY_KINDS, CI_APPLY_OPERATIONS, ciApplyErrorBaseSchema, ciApplyErrorSchema, ciSyncCountSchema, ciSyncChangesSchema, ciSyncWarningSchema, ciSyncResponseSchema;
12113
- var init_chunk_DBQLPVOO = __esm({
12114
- "../../packages/core/dist/chunk-DBQLPVOO.js"() {
11954
+ var init_chunk_NYIIBG23 = __esm({
11955
+ "../../packages/core/dist/chunk-NYIIBG23.js"() {
12115
11956
  "use strict";
12116
- init_chunk_D26NGKIY();
12117
- init_chunk_7MRZJN4O();
12118
- init_chunk_6WCPZ26B();
11957
+ init_chunk_AFIQ3FEW();
11958
+ init_chunk_623SRYWZ();
11959
+ init_chunk_7EGDXEYG();
12119
11960
  init_chunk_LBDH7LCG();
12120
11961
  init_chunk_4LXDRTO4();
12121
11962
  init_chunk_T4Q5COKJ();
@@ -12219,6 +12060,7 @@ var init_chunk_DBQLPVOO = __esm({
12219
12060
  refineHubAsCodeLanes(config, ctx);
12220
12061
  refineHubAsCodePresentation(config, ctx);
12221
12062
  refineHubAsCodeEvals(config, ctx);
12063
+ refineHubAsCodeCustomers(config, ctx);
12222
12064
  refineHubAsCodeEvalAttachments(config, ctx);
12223
12065
  refineHubAsCodeCallOpenings(config, ctx);
12224
12066
  refineHubAsCodeResources(config, ctx);
@@ -12551,7 +12393,7 @@ var init_chunk_6J742GLA = __esm({
12551
12393
  }
12552
12394
  });
12553
12395
 
12554
- // ../../packages/core/dist/chunk-JR2ITK6N.js
12396
+ // ../../packages/core/dist/chunk-3HSB6J4J.js
12555
12397
  function normalizeContactPhone(raw) {
12556
12398
  const compact = raw.trim().replace(/[\s\-.()]/g, "");
12557
12399
  const withPlus = compact.startsWith("00") ? `+${compact.slice(2)}` : compact;
@@ -12563,9 +12405,9 @@ function normalizeContactLabel(raw) {
12563
12405
  function importRowLabels(row, batchLabels) {
12564
12406
  return [.../* @__PURE__ */ new Set([...row.labels ?? [], ...batchLabels ?? []])];
12565
12407
  }
12566
- var CONTACT_ENVIRONMENTS, CONTACT_NAME_MAX, CONTACT_EMAIL_MAX, CONTACT_PHONE_INPUT_MAX, CONTACT_INSTAGRAM_SID_MAX, CONTACT_METADATA_MAX_BYTES, CONTACT_LABEL_MAX, CONTACT_LABELS_MAX, CONTACT_SCOPE_TAGS_MAX, CONTACT_PAGE_MAX, CONTACT_IMPORT_BATCH_MAX, CONTACT_SEARCH_MAX, CONTACT_LIST_NAME_MAX, CONTACT_LIST_NAME_REGEX, CONTACT_LIST_DESCRIPTION_MAX, CONTACT_LIST_FILTER_MAX, CONTACT_LIST_PINS_PER_REQUEST_MAX, SUPPRESSION_SCOPES, SUPPRESSION_ID_REGEX, contactName, contactPhone, contactEmail, contactInstagramSid, contactLabel, contactLabels, contactMetadata, scopeTagIds, contactVisibilitySchema, hasIdentity, IDENTITY_REQUIRED, contactBookOrgQuery, contactBookContactParam, contactBookListParam, contactBookHubParam, contactBookPageQuery, listContactBookContactsQuery, listHubContactBookContactsQuery, contactBookLinkCandidatesQuery, listContactBookListMembersQuery, contactRowFields, createContactBookContactBody, updateContactBookContactBody, contactImportRowSchema, importContactBookContactsBody, linkContactBookContactBody, listName, contactListFilterSchema, createContactBookListBody, updateContactBookListBody, updateContactBookListPinsBody, suppressionIdentitySchema, createContactBookSuppressionBody, contactBookSuppressionParam, listContactBookSuppressionsQuery, contactBookEmailUnsubscribeTokenSchema, contactBookEmailUnsubscribeQuery, orgListReferenceSchema;
12567
- var init_chunk_JR2ITK6N = __esm({
12568
- "../../packages/core/dist/chunk-JR2ITK6N.js"() {
12408
+ var CONTACT_ENVIRONMENTS, CONTACT_NAME_MAX, CONTACT_EMAIL_MAX, CONTACT_PHONE_INPUT_MAX, CONTACT_INSTAGRAM_SID_MAX, CONTACT_METADATA_MAX_BYTES, CONTACT_LABEL_MAX, CONTACT_LABELS_MAX, CONTACT_SCOPE_TAGS_MAX, CONTACT_PAGE_MAX, CONTACT_IMPORT_BATCH_MAX, CONTACT_SEARCH_MAX, CONTACT_LIST_NAME_MAX, CONTACT_LIST_NAME_REGEX, CONTACT_LIST_DESCRIPTION_MAX, CONTACT_LIST_FILTER_MAX, CONTACT_LIST_PINS_PER_REQUEST_MAX, SUPPRESSION_SCOPES, SUPPRESSION_ID_REGEX, contactName, contactPhone, contactEmail, contactInstagramSid, contactLabel, contactLabels, contactMetadata, scopeTagIds, contactVisibilitySchema, hasIdentity, IDENTITY_REQUIRED, contactBookOrgQuery, contactBookContactParam, contactBookListParam, contactBookHubParam, contactBookPageQuery, listContactBookContactsQuery, listHubContactBookContactsQuery, contactBookLinkCandidatesQuery, listContactBookListMembersQuery, contactRowFields, createContactBookContactBody, updateContactBookContactBody, contactImportRowSchema, importContactBookContactsBody, linkContactBookContactBody, CONTACT_CUSTOMER_BASE_ID_PATTERN, baseId, recordId, linkContactCustomerBody, unlinkContactCustomerQuery, listName, contactListFilterSchema, createContactBookListBody, updateContactBookListBody, updateContactBookListPinsBody, suppressionIdentitySchema, createContactBookSuppressionBody, contactBookSuppressionParam, listContactBookSuppressionsQuery, contactBookEmailUnsubscribeTokenSchema, contactBookEmailUnsubscribeQuery, orgListReferenceSchema;
12409
+ var init_chunk_3HSB6J4J = __esm({
12410
+ "../../packages/core/dist/chunk-3HSB6J4J.js"() {
12569
12411
  "use strict";
12570
12412
  init_zod();
12571
12413
  CONTACT_ENVIRONMENTS = ["production", "preview", "all"];
@@ -12684,6 +12526,16 @@ var init_chunk_JR2ITK6N = __esm({
12684
12526
  linkContactBookContactBody = external_exports.object({
12685
12527
  user_id: external_exports.string().min(1).max(128)
12686
12528
  }).strict();
12529
+ CONTACT_CUSTOMER_BASE_ID_PATTERN = /^[A-Za-z0-9_-]{1,128}$/;
12530
+ baseId = external_exports.string().regex(CONTACT_CUSTOMER_BASE_ID_PATTERN, { message: "Must be a base id" });
12531
+ recordId = external_exports.string().regex(/^[a-zA-Z0-9][a-zA-Z0-9_\-.:]{0,254}$/, { message: "Must be a record id" });
12532
+ linkContactCustomerBody = external_exports.object({
12533
+ base_id: baseId,
12534
+ record_id: recordId
12535
+ }).strict();
12536
+ unlinkContactCustomerQuery = contactBookOrgQuery.extend({
12537
+ base_id: baseId
12538
+ });
12687
12539
  listName = external_exports.string().trim().min(1).max(CONTACT_LIST_NAME_MAX).regex(CONTACT_LIST_NAME_REGEX, {
12688
12540
  message: 'Must be lowercase alphanumeric with hyphens (e.g. "vip-customers")'
12689
12541
  });
@@ -12726,14 +12578,14 @@ var init_chunk_JR2ITK6N = __esm({
12726
12578
  }
12727
12579
  });
12728
12580
 
12729
- // ../../packages/core/dist/chunk-EA2IJGKN.js
12581
+ // ../../packages/core/dist/chunk-XCDUP42J.js
12730
12582
  var COMMUNITIES_PER_ORG_MAX, COMMUNITY_NAME_MAX_LENGTH, COMMUNITY_REGISTRY_CLOSED_REASON, COMMUNITY_MEMBERS_MAX, COMMUNITY_ADMISSIONS, COMMUNITY_ACCESS_MAX, COMMUNITY_ACCESS_ADD_MAX, COMMUNITY_ACCESS_FULL_REASON, COMMUNITY_JOIN_SOURCE_MAX_LENGTH, COMMUNITY_JOIN_FLOW_TOKEN_MAX_LENGTH, COMMUNITY_ROOMS_MAX, COMMUNITY_ROOM_NAME_MAX_LENGTH, COMMUNITY_MESSAGE_MAX_LENGTH, COMMUNITY_MESSAGES_PAGE_SIZE, COMMUNITY_ATTACHMENT_URLS_MAX, COMMUNITY_POST_TITLE_MAX_LENGTH, COMMUNITY_POST_SEARCH_MAX_LENGTH, COMMUNITY_MEMBER_STATUSES, COMMUNITY_RULES_MAX_LENGTH, COMMUNITY_SLOW_MODE_MAX_SECONDS, COMMUNITY_COURSES_LABEL_MAX_LENGTH, COMMUNITY_LIVE_TICKET_PREFIX, COMMUNITY_STATS_DAYS, communityNameSchema, adminCreateCommunityBody, communityIdParam, communityJoinTokenSchema, communityJoinSourceSchema, communityJoinPreviewQuery, communityJoinBody, communityRoomKindSchema, communityRoomNameSchema, communityRoomIdParam, communityMessageIdParam, communityRoomCreateBody, communityRoomUpdateBody, communityMessagesQuery, communityMessageBodySchema, communityPostTitleSchema, communityAttachmentUploadSchema, communitySendBody, communityEditBody, communityPostIdParam, communityPostsQuery, communityAnswerBody, communityReadBody, communityAttachmentUrlsBody, communityPersonParam, communityOrgParam, communityPeopleQuery, communityCoursesLabelSchema, communityAdmissionSchema, communitySettingsBody, communityAccessEmailSchema, communityAccessAddBody, communityAccessQuery, communityAccessIdParam, communityBanBody, communityLockBody, communityPinBody, communityModLogQuery, communityReportsQuery, communityReportIdParam, communityLiveTicketSchema, communityLiveQuery, communityMuteBody, communityEmailUnsubscribeTokenSchema, communityEmailUnsubscribeQuery;
12731
- var init_chunk_EA2IJGKN = __esm({
12732
- "../../packages/core/dist/chunk-EA2IJGKN.js"() {
12583
+ var init_chunk_XCDUP42J = __esm({
12584
+ "../../packages/core/dist/chunk-XCDUP42J.js"() {
12733
12585
  "use strict";
12734
12586
  init_chunk_6J742GLA();
12735
12587
  init_chunk_ZVXO3XL6();
12736
- init_chunk_JR2ITK6N();
12588
+ init_chunk_3HSB6J4J();
12737
12589
  init_chunk_HZ6CADSY();
12738
12590
  init_zod();
12739
12591
  COMMUNITIES_PER_ORG_MAX = 10;
@@ -12834,7 +12686,7 @@ var init_chunk_EA2IJGKN = __esm({
12834
12686
  }
12835
12687
  });
12836
12688
 
12837
- // ../../packages/core/dist/chunk-QAWIPRNA.js
12689
+ // ../../packages/core/dist/chunk-3KYTITOR.js
12838
12690
  function parseCommunityLessonVideoUrl(url) {
12839
12691
  const parts = /^https?:\/\/([^/?#]+)([^?#]*)(?:\?([^#]*))?(?:#.*)?$/i.exec(url.trim());
12840
12692
  if (!parts) return null;
@@ -12860,10 +12712,10 @@ function communityLessonVideoWatchUrl(video) {
12860
12712
  }
12861
12713
  }
12862
12714
  var COMMUNITY_COURSES_MAX, COMMUNITY_COURSE_MODULES_MAX, COMMUNITY_COURSE_LESSONS_MAX, COMMUNITY_LESSONS_MAX, COMMUNITY_COURSE_TITLE_MAX_LENGTH, COMMUNITY_COURSE_DESCRIPTION_MAX_LENGTH, COMMUNITY_LESSON_BODY_MAX_LENGTH, COMMUNITY_LESSON_LINKS_MAX, COMMUNITY_LESSON_URL_MAX_LENGTH, YOUTUBE_ID, YOUTUBE_HOSTS, YOUTU_BE, YOUTUBE_ID_PATH, communityCourseIdParam, communityCourseModuleIdParam, communityLessonIdParam, communityCourseTitleSchema, communityCourseDescriptionSchema, communityCoursePositionSchema, communityLessonVideoUrlSchema, communityLessonLinkSchema, communityLessonLinksSchema, communityLessonBodySchema, communityCourseCreateBody, communityCourseUpdateBody, communityModuleCreateBody, communityModuleUpdateBody, communityLessonCreateBody, communityLessonUpdateBody;
12863
- var init_chunk_QAWIPRNA = __esm({
12864
- "../../packages/core/dist/chunk-QAWIPRNA.js"() {
12715
+ var init_chunk_3KYTITOR = __esm({
12716
+ "../../packages/core/dist/chunk-3KYTITOR.js"() {
12865
12717
  "use strict";
12866
- init_chunk_EA2IJGKN();
12718
+ init_chunk_XCDUP42J();
12867
12719
  init_chunk_HZ6CADSY();
12868
12720
  init_zod();
12869
12721
  COMMUNITY_COURSES_MAX = 20;
@@ -12945,29 +12797,58 @@ var init_chunk_YULHXJ5M = __esm({
12945
12797
  }
12946
12798
  });
12947
12799
 
12948
- // ../../packages/core/dist/chunk-UEJOG2Q7.js
12949
- var archiveHubIdParam, archiveConversationParams, archiveListQuery, archiveMessageObservabilityParams;
12950
- var init_chunk_UEJOG2Q7 = __esm({
12951
- "../../packages/core/dist/chunk-UEJOG2Q7.js"() {
12800
+ // ../../packages/core/dist/chunk-V4FRPRH5.js
12801
+ var CONSULT_THREAD_STATUSES, consultThreadStatus, CONSULT_THREAD_TITLE_MAX, consultThreadTitle, consultThreadSummary, listConsultThreadsQuery, listConsultThreadsResponse, createConsultThreadBody, createConsultThreadResponse, consultThreadIdParam, updateConsultThreadBody, updateConsultThreadResponse, CONSULT_AWAIT_TIMEOUT_MS;
12802
+ var init_chunk_V4FRPRH5 = __esm({
12803
+ "../../packages/core/dist/chunk-V4FRPRH5.js"() {
12952
12804
  "use strict";
12953
12805
  init_zod();
12954
- archiveHubIdParam = external_exports.object({
12955
- hubId: external_exports.string().uuid()
12806
+ CONSULT_THREAD_STATUSES = ["open", "awaiting", "resolved", "cancelled_at_close"];
12807
+ consultThreadStatus = external_exports.enum(CONSULT_THREAD_STATUSES);
12808
+ CONSULT_THREAD_TITLE_MAX = 120;
12809
+ consultThreadTitle = external_exports.string().trim().min(1).max(CONSULT_THREAD_TITLE_MAX);
12810
+ consultThreadSummary = external_exports.object({
12811
+ consult_thread_id: external_exports.string(),
12812
+ conversation_id: external_exports.string(),
12813
+ initiator_type: external_exports.enum(["team", "agent"]),
12814
+ initiator_id: external_exports.string(),
12815
+ engaged_agent_id: external_exports.string().nullable(),
12816
+ engaged_agent_name: external_exports.string().nullable(),
12817
+ title: external_exports.string().nullable(),
12818
+ status: consultThreadStatus,
12819
+ created_at: external_exports.string()
12956
12820
  });
12957
- archiveConversationParams = external_exports.object({
12958
- hubId: external_exports.string().uuid(),
12959
- conversationId: external_exports.string().uuid()
12821
+ listConsultThreadsQuery = external_exports.object({
12822
+ hub_id: external_exports.string().uuid()
12960
12823
  });
12961
- archiveListQuery = external_exports.object({
12962
- user_id: external_exports.string().optional(),
12963
- start: external_exports.string().optional(),
12964
- end: external_exports.string().optional(),
12965
- page: external_exports.string().regex(/^\d+$/).optional(),
12966
- page_size: external_exports.string().regex(/^\d+$/).optional()
12824
+ listConsultThreadsResponse = external_exports.object({
12825
+ threads: external_exports.array(consultThreadSummary)
12967
12826
  });
12968
- archiveMessageObservabilityParams = archiveConversationParams.extend({
12969
- messageId: external_exports.string().uuid()
12827
+ createConsultThreadBody = external_exports.object({
12828
+ hub_id: external_exports.string().uuid(),
12829
+ title: consultThreadTitle.optional(),
12830
+ // Optionally engage a consultant on creation. Validated server-side against the
12831
+ // hub's `consultant`-role agents; a non-consultant / unknown id is rejected.
12832
+ engaged_agent_id: external_exports.string().uuid().optional()
12833
+ });
12834
+ createConsultThreadResponse = external_exports.object({
12835
+ thread: consultThreadSummary
12836
+ });
12837
+ consultThreadIdParam = external_exports.object({
12838
+ id: external_exports.string().uuid(),
12839
+ threadId: external_exports.string().uuid()
12840
+ });
12841
+ updateConsultThreadBody = external_exports.object({
12842
+ hub_id: external_exports.string().uuid(),
12843
+ title: consultThreadTitle.optional(),
12844
+ engaged_agent_id: external_exports.string().uuid().optional()
12845
+ }).refine((v) => v.title !== void 0 || v.engaged_agent_id !== void 0, {
12846
+ message: "Provide a title and/or an engaged_agent_id to update"
12847
+ });
12848
+ updateConsultThreadResponse = external_exports.object({
12849
+ thread: consultThreadSummary
12970
12850
  });
12851
+ CONSULT_AWAIT_TIMEOUT_MS = 15 * 6e4;
12971
12852
  }
12972
12853
  });
12973
12854
 
@@ -13050,15 +12931,15 @@ var init_chunk_ZHJEQBXJ = __esm({
13050
12931
  }
13051
12932
  });
13052
12933
 
13053
- // ../../packages/core/dist/chunk-WNWIYFR3.js
12934
+ // ../../packages/core/dist/chunk-LQY2OCQL.js
13054
12935
  function filterNamesAnything(filter) {
13055
12936
  return filter.labels.length + filter.scope_tag_ids.length > 0;
13056
12937
  }
13057
12938
  var hubListNameSchema, HUB_LIST_FILTER_REQUIRED, hubContactListFilterSchema, hubContactListIdParam, hubContactListHubQuery, description, createHubContactListBody, updateHubContactListBody;
13058
- var init_chunk_WNWIYFR3 = __esm({
13059
- "../../packages/core/dist/chunk-WNWIYFR3.js"() {
12939
+ var init_chunk_LQY2OCQL = __esm({
12940
+ "../../packages/core/dist/chunk-LQY2OCQL.js"() {
13060
12941
  "use strict";
13061
- init_chunk_JR2ITK6N();
12942
+ init_chunk_3HSB6J4J();
13062
12943
  init_zod();
13063
12944
  hubListNameSchema = orgListReferenceSchema;
13064
12945
  HUB_LIST_FILTER_REQUIRED = "A hub list names at least one label or scope tag";
@@ -13100,14 +12981,14 @@ var init_chunk_F3JHI4Y4 = __esm({
13100
12981
  }
13101
12982
  });
13102
12983
 
13103
- // ../../packages/core/dist/chunk-ALUW3KZS.js
12984
+ // ../../packages/core/dist/chunk-GCKAPAPC.js
13104
12985
  var AUTOMATION_TRIGGER_TYPES, AUTOMATION_EVENT_TYPES, AUTOMATION_TARGET_TYPES, AUTOMATION_ACTION_TYPES, AUTOMATION_CHANNEL_TYPES, AUTOMATION_PURPOSES, AUTOMATION_NAME_MAX, AUTOMATION_DESCRIPTION_MAX, AUTOMATION_INSTRUCTIONS_MAX, AUTOMATION_TEXT_MAX, AUTOMATION_CRON_MAX, AUTOMATION_WEBHOOK_AUTHS, AUTOMATION_WEBHOOK_HEADERS, AUTOMATION_WEBHOOK_BODY_MAX_BYTES, AUTOMATION_WEBHOOK_HEADER_NAME_MAX, WEBHOOK_RESERVED_HEADERS, automationTriggerSchema, automationTargetSchema, automationActionSchema, automationGateSchema, automationName, automationDescription, automationIdParam, automationHubQuery, automationWebhookParams, AUTOMATION_RUNS_PAGE_MAX, listAutomationRunsQuery, createAutomationBody, updateAutomationBody, AUTOMATION_ALERT_CATEGORIES, AUTOMATION_BLOCKED_ALERT_CATEGORY, automationEventSubscriberParam;
13105
- var init_chunk_ALUW3KZS = __esm({
13106
- "../../packages/core/dist/chunk-ALUW3KZS.js"() {
12986
+ var init_chunk_GCKAPAPC = __esm({
12987
+ "../../packages/core/dist/chunk-GCKAPAPC.js"() {
13107
12988
  "use strict";
13108
- init_chunk_WNWIYFR3();
13109
- init_chunk_6WCPZ26B();
13110
- init_chunk_JR2ITK6N();
12989
+ init_chunk_LQY2OCQL();
12990
+ init_chunk_7EGDXEYG();
12991
+ init_chunk_3HSB6J4J();
13111
12992
  init_chunk_F3JHI4Y4();
13112
12993
  init_chunk_DHPUPI4Y();
13113
12994
  init_chunk_T7KQKDET();
@@ -13357,6 +13238,118 @@ var init_chunk_ZJJ5ODOD = __esm({
13357
13238
  }
13358
13239
  });
13359
13240
 
13241
+ // ../../packages/core/dist/chunk-7CYHPF35.js
13242
+ var appMessageSenderType, appMessageReceiverType, apiChannelMessage, apiChannelMessageBody, appMessageBody, appMessageResponse;
13243
+ var init_chunk_7CYHPF35 = __esm({
13244
+ "../../packages/core/dist/chunk-7CYHPF35.js"() {
13245
+ "use strict";
13246
+ init_chunk_HZ6CADSY();
13247
+ init_zod();
13248
+ appMessageSenderType = external_exports.enum(["user", "team"]);
13249
+ appMessageReceiverType = external_exports.enum(["user", "team", "agent", "assistant"]).transform((v) => v === "assistant" ? "agent" : v);
13250
+ apiChannelMessage = external_exports.object({
13251
+ text: clientOptionalString,
13252
+ attachments: external_exports.array(messageAttachment).max(MAX_ATTACHMENTS_PER_MESSAGE).nullish().transform((v) => v ?? void 0)
13253
+ }).refine((m) => m.text && m.text.length > 0 || m.attachments && m.attachments.length > 0, {
13254
+ message: "message must have text or at least one attachment"
13255
+ });
13256
+ apiChannelMessageBody = external_exports.object({
13257
+ // Correlation id (task hubs): new → new conversation, repeat → continue. min 1 so an
13258
+ // empty string can't masquerade as a ref. Mutually exclusive with conversation_id.
13259
+ external_ref: external_exports.string().min(1).max(256).optional(),
13260
+ // Continue a specific WayAI conversation (authorized against the hub/channel + owner).
13261
+ // UUID-validated here (unlike the app channel, whose client we control): allocation
13262
+ // only treats a UUID-shaped id as a provided conversation, so a malformed id would
13263
+ // otherwise skip the owner guard and silently MINT a new conversation instead of
13264
+ // rejecting. A format 400 is shape-only — not an existence oracle (a valid-but-unknown
13265
+ // UUID still collapses to the opaque authorization error downstream).
13266
+ conversation_id: external_exports.string().uuid().optional(),
13267
+ // On-behalf-of end-user identity. Absent → per-connection service principal (task-hub
13268
+ // only; chat hub rejects with 422 in the route).
13269
+ user: external_exports.object({
13270
+ id: external_exports.string().min(1),
13271
+ email: clientOptionalString,
13272
+ name: clientOptionalString
13273
+ }).optional(),
13274
+ message: apiChannelMessage,
13275
+ // Idempotency key: maps to channel_message_sid, deduped within one conversation
13276
+ // (ConversationDO.storeMessage). A retried POST resolves to the same conversation (a chat
13277
+ // hub's user, the external_ref, the conversation_id, or on a task hub with neither, this key
13278
+ // scoped by the sender), so it echoes the original message_id and skips billing / turn
13279
+ // dispatch. A failed store answers a retryable 503 only when this key is set; without it a
13280
+ // retry could store the message twice, so it answers 400.
13281
+ client_message_id: external_exports.string().min(1).max(256).optional()
13282
+ }).refine((b) => !(b.external_ref && b.conversation_id), {
13283
+ message: "provide external_ref or conversation_id, not both",
13284
+ path: ["external_ref"]
13285
+ });
13286
+ appMessageBody = external_exports.object({
13287
+ // Message content — three historical aliases. All optional: an attachment-only
13288
+ // or voice-only message carries no text.
13289
+ content: clientOptionalString,
13290
+ message_text: clientOptionalString,
13291
+ message_body: clientOptionalString,
13292
+ // Conversation context. Ids are plain strings rather than `.uuid()` on purpose:
13293
+ // they are AUTHORIZED downstream, which is the stronger guarantee — a well-formed
13294
+ // uuid belonging to another tenant must fail just as hard as junk. `hub_id` is
13295
+ // gated by `assertHubEndUserAccess` (gh #3286) and `conversation_id` by HubDO's
13296
+ // conversation_index owner check (gh #2781, #3281). The route's own falsy guards
13297
+ // ('hub_id is required') still reject an empty one.
13298
+ hub_id: clientOptionalString,
13299
+ channel_id: clientOptionalString,
13300
+ conversation_id: clientOptionalString,
13301
+ hub_type: external_exports.enum(["chat", "task"]).nullish().transform((v) => v ?? void 0),
13302
+ // Stable idempotency key for one explicit task-hub launcher. HubDO scopes it
13303
+ // to the authenticated user and resolves retries/tabs to one conversation.
13304
+ task_start_id: external_exports.string().uuid().nullish().transform((v) => v ?? void 0),
13305
+ // Routing.
13306
+ sender_type: appMessageSenderType.nullish().transform((v) => v ?? void 0),
13307
+ receiver_type: appMessageReceiverType.nullish().transform((v) => v ?? void 0),
13308
+ // Only meaningful on a team send, where `validateAppTeamSendContext` proves the
13309
+ // caller may send to this receiver. Absent on a team send to a conversation with no
13310
+ // person, which names its `conversation_id` instead. The end-user branch ignores it —
13311
+ // see the receiver derivation in the route.
13312
+ user_receiver_id: clientOptionalString,
13313
+ // ── Internal consult (consultant-agents PR 2 — H1.0) ──────────────────────
13314
+ // A team member handling a customer conversation can tag a `consultant`-role
13315
+ // agent for a PRIVATE, team-only exchange that never reaches the customer. A
13316
+ // consult send is a team send with `receiver_type: 'agent'` targeting the
13317
+ // consultant; `user_receiver_id` identifies the customer whose conversation this is
13318
+ // (and is authorized by `validateAppTeamSendContext`, exactly as a team→user send is),
13319
+ // and is absent, as on a team→user send, when the conversation has no person. The consultant is resolved from `agent_receiver_id`
13320
+ // when supplied, else from an `@mention` parsed out of the message text against
13321
+ // the hub's consultant agents. `consult_thread_id` continues an existing thread;
13322
+ // absent, the route creates/reuses the single implicit thread. These fields are
13323
+ // inert on every non-consult send (end-user send, team→user send).
13324
+ agent_receiver_id: clientOptionalString,
13325
+ consult_thread_id: clientOptionalString,
13326
+ is_first_message: clientOptionalBoolean,
13327
+ end_conversation: clientOptionalBoolean,
13328
+ // Pre-generated by the client so the optimistic bubble and the stored row share
13329
+ // a key (transcription live-updates land on the same row instead of duplicating).
13330
+ message_id: clientOptionalString,
13331
+ attachments: external_exports.array(messageAttachment).max(MAX_ATTACHMENTS_PER_MESSAGE).nullish().transform((v) => v ?? void 0),
13332
+ // Base64-encoded audio for STT. Size-capped in the route (the cap is a byte
13333
+ // budget tied to the /channels/* bodyLimit, not a shape rule).
13334
+ audio_file: clientOptionalString
13335
+ });
13336
+ appMessageResponse = external_exports.object({
13337
+ success: external_exports.boolean(),
13338
+ message: external_exports.string(),
13339
+ result: external_exports.object({
13340
+ conversation_id: external_exports.string().optional(),
13341
+ message_id: external_exports.string().optional(),
13342
+ status: external_exports.string().optional(),
13343
+ files: external_exports.array(external_exports.record(external_exports.string(), external_exports.unknown())).optional(),
13344
+ // True when this request reused a task-start/message id already accepted by
13345
+ // the server. Clients must replace their optimistic payload with a fresh
13346
+ // authoritative read because another tab may have won with different text.
13347
+ deduped: external_exports.boolean().optional()
13348
+ }).optional()
13349
+ });
13350
+ }
13351
+ });
13352
+
13360
13353
  // ../../packages/core/dist/chunk-NVKU5PPQ.js
13361
13354
  var ADMIN_SKILL_NAME_REGEX, adminSkillNameParam;
13362
13355
  var init_chunk_NVKU5PPQ = __esm({
@@ -13999,6 +13992,32 @@ var init_chunk_2PZIF56U = __esm({
13999
13992
  }
14000
13993
  });
14001
13994
 
13995
+ // ../../packages/core/dist/chunk-UEJOG2Q7.js
13996
+ var archiveHubIdParam, archiveConversationParams, archiveListQuery, archiveMessageObservabilityParams;
13997
+ var init_chunk_UEJOG2Q7 = __esm({
13998
+ "../../packages/core/dist/chunk-UEJOG2Q7.js"() {
13999
+ "use strict";
14000
+ init_zod();
14001
+ archiveHubIdParam = external_exports.object({
14002
+ hubId: external_exports.string().uuid()
14003
+ });
14004
+ archiveConversationParams = external_exports.object({
14005
+ hubId: external_exports.string().uuid(),
14006
+ conversationId: external_exports.string().uuid()
14007
+ });
14008
+ archiveListQuery = external_exports.object({
14009
+ user_id: external_exports.string().optional(),
14010
+ start: external_exports.string().optional(),
14011
+ end: external_exports.string().optional(),
14012
+ page: external_exports.string().regex(/^\d+$/).optional(),
14013
+ page_size: external_exports.string().regex(/^\d+$/).optional()
14014
+ });
14015
+ archiveMessageObservabilityParams = archiveConversationParams.extend({
14016
+ messageId: external_exports.string().uuid()
14017
+ });
14018
+ }
14019
+ });
14020
+
14002
14021
  // ../../packages/core/dist/chunk-SOJMWM63.js
14003
14022
  var init_chunk_SOJMWM63 = __esm({
14004
14023
  "../../packages/core/dist/chunk-SOJMWM63.js"() {
@@ -14221,57 +14240,56 @@ var init_contracts = __esm({
14221
14240
  init_chunk_SXDX4GHS();
14222
14241
  init_chunk_FK6HBXM7();
14223
14242
  init_chunk_VXEAR36B();
14224
- init_chunk_GPM7PE44();
14225
14243
  init_chunk_DGKMMFIR();
14226
14244
  init_chunk_ZC6YGHNX();
14227
14245
  init_chunk_ACKF2MVU();
14228
- init_chunk_ZXK6N2HN();
14229
14246
  init_chunk_Y7CFCYX4();
14230
14247
  init_chunk_5DGHIY7L();
14231
14248
  init_chunk_BVQE66I2();
14232
14249
  init_chunk_BEOHBREG();
14233
14250
  init_chunk_IPDOHAZ5();
14234
- init_chunk_SY6PLCPK();
14251
+ init_chunk_GPM7PE44();
14235
14252
  init_chunk_YUZFHVB2();
14236
14253
  init_chunk_34LE6P7E();
14237
14254
  init_chunk_FPSDNS2E();
14238
- init_chunk_LKBSHANA();
14255
+ init_chunk_ZXK6N2HN();
14239
14256
  init_chunk_VOC3AGY4();
14240
14257
  init_chunk_C4HEZ7ZI();
14241
14258
  init_chunk_IR2NOSI3();
14242
14259
  init_chunk_EA23LSDS();
14243
- init_chunk_3O5XTDI2();
14260
+ init_chunk_SY6PLCPK();
14244
14261
  init_chunk_LWMLR2WI();
14245
14262
  init_chunk_ACGAI25T();
14246
14263
  init_chunk_MH4O3YEX();
14247
- init_chunk_YVHDDEQV();
14264
+ init_chunk_3OWAWA5B();
14248
14265
  init_chunk_KSTYTQ7I();
14249
- init_chunk_7CYHPF35();
14266
+ init_chunk_LKBSHANA();
14250
14267
  init_chunk_BPCNB5RT();
14251
- init_chunk_DBQLPVOO();
14252
- init_chunk_D26NGKIY();
14253
- init_chunk_7MRZJN4O();
14268
+ init_chunk_NYIIBG23();
14269
+ init_chunk_AFIQ3FEW();
14270
+ init_chunk_623SRYWZ();
14254
14271
  init_chunk_JDJ4EUOL();
14255
- init_chunk_QAWIPRNA();
14256
- init_chunk_EA2IJGKN();
14272
+ init_chunk_3KYTITOR();
14273
+ init_chunk_XCDUP42J();
14257
14274
  init_chunk_6J742GLA();
14258
14275
  init_chunk_ZVXO3XL6();
14259
14276
  init_chunk_YULHXJ5M();
14260
- init_chunk_UEJOG2Q7();
14277
+ init_chunk_V4FRPRH5();
14261
14278
  init_chunk_ZHJEQBXJ();
14262
- init_chunk_ALUW3KZS();
14263
- init_chunk_WNWIYFR3();
14264
- init_chunk_6WCPZ26B();
14265
- init_chunk_JR2ITK6N();
14279
+ init_chunk_GCKAPAPC();
14280
+ init_chunk_LQY2OCQL();
14281
+ init_chunk_7EGDXEYG();
14282
+ init_chunk_3HSB6J4J();
14266
14283
  init_chunk_IG6QBZMA();
14267
14284
  init_chunk_ZJJ5ODOD();
14268
14285
  init_chunk_PZPOUXJR();
14269
14286
  init_chunk_LBDH7LCG();
14270
14287
  init_chunk_4LXDRTO4();
14271
14288
  init_chunk_E4DIIOOE();
14289
+ init_chunk_7CYHPF35();
14272
14290
  init_chunk_FMXFEZN4();
14273
- init_chunk_5KFFZX2J();
14274
- init_chunk_VBUWGVFY();
14291
+ init_chunk_ROS7PLDY();
14292
+ init_chunk_LDSABSRL();
14275
14293
  init_chunk_NVKU5PPQ();
14276
14294
  init_chunk_2FCLSQSQ();
14277
14295
  init_chunk_FECLIZTY();
@@ -14283,6 +14301,7 @@ var init_contracts = __esm({
14283
14301
  init_chunk_ACN6GXU6();
14284
14302
  init_chunk_OMPT4ZHR();
14285
14303
  init_chunk_2PZIF56U();
14304
+ init_chunk_UEJOG2Q7();
14286
14305
  init_chunk_SOJMWM63();
14287
14306
  init_chunk_WEXVYJ5H();
14288
14307
  init_chunk_LZDVDC2S();
@@ -14474,6 +14493,19 @@ var init_api_client = __esm({
14474
14493
  }
14475
14494
  // The org-admin community routes (gh #5003, `wayai communities`): an owner or admin of the
14476
14495
  // community's org, on an interactive session only — a scoped token is refused with 403.
14496
+ /**
14497
+ * Link a contact to its customer record, a root record of one of the org's bases (#5083 RK2 A3).
14498
+ * A browser sign-in only: the route refuses an API token.
14499
+ */
14500
+ async linkContactCustomer(orgId, contactId, body) {
14501
+ const qs = new URLSearchParams({ organization_id: orgId });
14502
+ return this.request("PUT", `/api/contact-book/contacts/${encodeURIComponent(contactId)}/customer?${qs}`, body);
14503
+ }
14504
+ /** Unlink a contact from its customer record in one base (owner decision 142). A browser sign-in only. */
14505
+ async unlinkContactCustomer(orgId, contactId, baseId2) {
14506
+ const qs = new URLSearchParams({ organization_id: orgId, base_id: baseId2 });
14507
+ return this.request("DELETE", `/api/contact-book/contacts/${encodeURIComponent(contactId)}/customer?${qs}`);
14508
+ }
14477
14509
  async listOrgCommunities(orgId) {
14478
14510
  return this.request("GET", `/api/communities/orgs/${encodeURIComponent(orgId)}`);
14479
14511
  }
@@ -17307,6 +17339,7 @@ var init_utils = __esm({
17307
17339
  "conversations",
17308
17340
  "alerts",
17309
17341
  "communities",
17342
+ "contacts",
17310
17343
  "knowledge"
17311
17344
  ]);
17312
17345
  HELP_AND_VERSION = ["help", "--help", "-h", "--version", "-v"];
@@ -17314,6 +17347,7 @@ var init_utils = __esm({
17314
17347
  ["pull", "all"],
17315
17348
  ["push", "all"],
17316
17349
  ["communities", "all"],
17350
+ ["contacts", "all"],
17317
17351
  ["knowledge", "all"],
17318
17352
  ["use", "selectors"],
17319
17353
  ["unbind", "selectors"],
@@ -20387,6 +20421,13 @@ function parseJourneyYaml(filePath2, relPath, hubFolder, bytesByHash) {
20387
20421
  }
20388
20422
  const variables = parseVariablesMap(data.variables, `Journey "${journeyName}" in ${relPath}`);
20389
20423
  if (variables) journeyEntry.variables = variables;
20424
+ const customer = parseFixtureField(
20425
+ data.customer_contact_id,
20426
+ `Journey "${journeyName}" in ${relPath}`,
20427
+ "customer_contact_id",
20428
+ "the customer's contact id"
20429
+ );
20430
+ if (customer) journeyEntry.customer_contact_id = customer;
20390
20431
  const fixture = parseFixtureField(data.fixture, `Journey "${journeyName}" in ${relPath}`, "fixture");
20391
20432
  if (fixture) journeyEntry.fixture = fixture;
20392
20433
  const targetBase = parseFixtureField(data.target_base, `Journey "${journeyName}" in ${relPath}`, "target_base");
@@ -20769,6 +20810,9 @@ function buildJourneyYamlObject(journeyEntry, slug) {
20769
20810
  if (typeof journeyEntry.target_base === "string" && journeyEntry.target_base.trim()) {
20770
20811
  out.target_base = journeyEntry.target_base.trim();
20771
20812
  }
20813
+ if (typeof journeyEntry.customer_contact_id === "string" && journeyEntry.customer_contact_id) {
20814
+ out.customer_contact_id = journeyEntry.customer_contact_id;
20815
+ }
20772
20816
  if (journeyEntry.variables && Object.keys(journeyEntry.variables).length > 0) {
20773
20817
  out.variables = journeyEntry.variables;
20774
20818
  }
@@ -21665,12 +21709,12 @@ function writeBaseFolder(folder, meta, config) {
21665
21709
  }
21666
21710
  return delta;
21667
21711
  }
21668
- function markProductionMirror(folder, baseId) {
21712
+ function markProductionMirror(folder, baseId2) {
21669
21713
  const file = path21.join(folder, BASE_META_FILE);
21670
21714
  try {
21671
21715
  const body = readFileNoFollow(folder, file)?.toString("utf-8");
21672
21716
  if (body === void 0 || body.startsWith(MIRROR_MARKER_PREFIX)) return;
21673
- const banner = `${MIRROR_MARKER_PREFIX} "${baseId}". Edits are ignored; \`wayai push\` refuses it. Edit the linked preview instead.
21717
+ const banner = `${MIRROR_MARKER_PREFIX} "${baseId2}". Edits are ignored; \`wayai push\` refuses it. Edit the linked preview instead.
21674
21718
  `;
21675
21719
  writeFileNoFollow(folder, file, Buffer.from(banner + body, "utf-8"));
21676
21720
  } catch {
@@ -21796,10 +21840,10 @@ function createPreview(client, originId, opts) {
21796
21840
  ...opts.analytics ? { analytics: opts.analytics } : {}
21797
21841
  });
21798
21842
  }
21799
- function deleteEntity(client, baseId, kind, id) {
21843
+ function deleteEntity(client, baseId2, kind, id) {
21800
21844
  return client.request(
21801
21845
  "DELETE",
21802
- `/v1/${pathSegment(baseId, "base id")}/${ENTITY_DIRS[kind]}/${pathSegment(id, `${kind} id`)}`
21846
+ `/v1/${pathSegment(baseId2, "base id")}/${ENTITY_DIRS[kind]}/${pathSegment(id, `${kind} id`)}`
21803
21847
  );
21804
21848
  }
21805
21849
  var init_api = __esm({
@@ -21998,40 +22042,40 @@ async function pullBase(gitRootOrNull, selector, args2) {
21998
22042
  const gitRoot = requireGitRoot(gitRootOrNull);
21999
22043
  const target = resolveBaseTarget(gitRoot, selector);
22000
22044
  const basesDir = resolveBasesDir(gitRoot);
22001
- const baseId = targetBaseId(target, selector);
22002
- if (!baseId) {
22045
+ const baseId2 = targetBaseId(target, selector);
22046
+ if (!baseId2) {
22003
22047
  throw expected(
22004
22048
  `Could not determine the base id for ${target.folder}. Pass the base id explicitly.`
22005
22049
  );
22006
22050
  }
22007
22051
  const client = await createDataClient();
22008
22052
  console.log("Fetching base configuration...");
22009
- const record = await getBaseRecord(client, baseId);
22053
+ const record = await getBaseRecord(client, baseId2);
22010
22054
  if (record.environment === "production") {
22011
- const folder = await writeProductionMirror(client, basesDir, record.id ?? baseId, record);
22055
+ const folder = await writeProductionMirror(client, basesDir, record.id ?? baseId2, record);
22012
22056
  console.log(`Production base mirrored (read-only) \u2192 ${folder}`);
22013
22057
  return;
22014
22058
  }
22015
- assertInScope("bases", baseId);
22059
+ assertInScope("bases", baseId2);
22016
22060
  if (target.exists && !autoConfirm) {
22017
22061
  const ok = await confirm(
22018
- `Overwrite local files in ${path23.relative(gitRoot, target.folder)} with the server config for "${sanitizeTerminalText(baseId)}"?`
22062
+ `Overwrite local files in ${path23.relative(gitRoot, target.folder)} with the server config for "${sanitizeTerminalText(baseId2)}"?`
22019
22063
  );
22020
22064
  if (!ok) {
22021
22065
  console.log("Cancelled.");
22022
22066
  return;
22023
22067
  }
22024
22068
  }
22025
- const config = await getConfig(client, baseId);
22069
+ const config = await getConfig(client, baseId2);
22026
22070
  const isFirstPull = !target.exists;
22027
- const delta = writeBaseFolder(target.folder, metaFromRecord(record, baseId), config);
22071
+ const delta = writeBaseFolder(target.folder, metaFromRecord(record, baseId2), config);
22028
22072
  console.log(`Base configuration written to ${target.folder}`);
22029
22073
  console.log(
22030
22074
  ` ${ENTITY_KINDS.map((kind) => `${(config[kind] ?? []).length} ${kind}`).join(", ")}`
22031
22075
  );
22032
22076
  if (!isFirstPull) printLocalFileChanges(delta);
22033
22077
  console.log(" Credential values are not written. Manage them with `wayai bases credentials`.");
22034
- seedScopeIfEmpty("bases", baseId);
22078
+ seedScopeIfEmpty("bases", baseId2);
22035
22079
  if (record.origin_base_id) {
22036
22080
  await mirrorLinkedProduction(client, basesDir, record.origin_base_id);
22037
22081
  }
@@ -22101,25 +22145,25 @@ async function pushBase(gitRootOrNull, selector, args2) {
22101
22145
  return;
22102
22146
  }
22103
22147
  const client = await createDataClient();
22104
- let baseId = meta.base_id;
22105
- if (!baseId) {
22148
+ let baseId2 = meta.base_id;
22149
+ if (!baseId2) {
22106
22150
  const created = await createDeclaredPreview(client, target, parsed, autoConfirm);
22107
22151
  if (!created) return;
22108
- baseId = created;
22152
+ baseId2 = created;
22109
22153
  } else {
22110
- const record = await getBaseRecord(client, baseId);
22154
+ const record = await getBaseRecord(client, baseId2);
22111
22155
  if (record.environment && record.environment !== "preview") {
22112
22156
  throw expected(
22113
- `"${sanitizeTerminalText(baseId)}" is a ${sanitizeTerminalText(record.environment)} base. Push operates on previews \u2014 promote with \`wayai bases promote\`.`
22157
+ `"${sanitizeTerminalText(baseId2)}" is a ${sanitizeTerminalText(record.environment)} base. Push operates on previews \u2014 promote with \`wayai bases promote\`.`
22114
22158
  );
22115
22159
  }
22116
- assertInScope("bases", baseId);
22160
+ assertInScope("bases", baseId2);
22117
22161
  }
22118
- const diff = await diffConfig(client, baseId, config);
22162
+ const diff = await diffConfig(client, baseId2, config);
22119
22163
  printLintWarnings(diff.warnings);
22120
22164
  if (isDiffEmpty(diff)) {
22121
- console.log(`No changes \u2014 preview "${sanitizeTerminalText(baseId)}" already matches your files.`);
22122
- if (!dryRun) seedScopeIfEmpty("bases", baseId);
22165
+ console.log(`No changes \u2014 preview "${sanitizeTerminalText(baseId2)}" already matches your files.`);
22166
+ if (!dryRun) seedScopeIfEmpty("bases", baseId2);
22123
22167
  return;
22124
22168
  }
22125
22169
  console.log(renderDiff(diff));
@@ -22129,13 +22173,13 @@ async function pushBase(gitRootOrNull, selector, args2) {
22129
22173
  }
22130
22174
  if (!autoConfirm) {
22131
22175
  const ok = await confirm(`
22132
- Apply these changes to preview "${sanitizeTerminalText(baseId)}"?`);
22176
+ Apply these changes to preview "${sanitizeTerminalText(baseId2)}"?`);
22133
22177
  if (!ok) {
22134
22178
  console.log("Cancelled.");
22135
22179
  return;
22136
22180
  }
22137
22181
  }
22138
- const result = await applyConfig(client, baseId, config);
22182
+ const result = await applyConfig(client, baseId2, config);
22139
22183
  const secretGroups = [
22140
22184
  ["trigger", result.new_trigger_secrets],
22141
22185
  ["inbound webhook", result.new_inbound_webhook_secrets]
@@ -22162,7 +22206,7 @@ ${RED}${removals.length} ${word} not in your files were left on the base. Re-run
22162
22206
  Delete ${removals.length} server ${word} not in your files? Record types cascade to their records.`
22163
22207
  )) {
22164
22208
  for (const removal of removals) {
22165
- await deleteEntity(client, baseId, removal.kind, removal.id);
22209
+ await deleteEntity(client, baseId2, removal.kind, removal.id);
22166
22210
  console.log(` - deleted ${removal.kind} ${sanitizeTerminalText(removal.id)}`);
22167
22211
  }
22168
22212
  } else {
@@ -22170,8 +22214,8 @@ Delete ${removals.length} server ${word} not in your files? Record types cascade
22170
22214
  }
22171
22215
  }
22172
22216
  console.log(`
22173
- Pushed to preview "${sanitizeTerminalText(baseId)}".`);
22174
- seedScopeIfEmpty("bases", baseId);
22217
+ Pushed to preview "${sanitizeTerminalText(baseId2)}".`);
22218
+ seedScopeIfEmpty("bases", baseId2);
22175
22219
  }
22176
22220
  var init_sync = __esm({
22177
22221
  "src/data/config-as-code/sync.ts"() {
@@ -27572,9 +27616,9 @@ async function conversationsCommand(args2) {
27572
27616
  if (result.partial || result.hubs_queried === 0) process.exit(1);
27573
27617
  return;
27574
27618
  }
27575
- for (const failure of result.errors) {
27576
- const where = failure.scope_kind === "hub" ? `hub ${sanitizeTerminalText(failure.hub_name || failure.hub_id || "")} (${failure.hub_id})` : `organization ${failure.organization_id}`;
27577
- console.error(`Could not read ${where}: ${sanitizeTerminalText(failure.error)}`);
27619
+ for (const failure2 of result.errors) {
27620
+ const where = failure2.scope_kind === "hub" ? `hub ${sanitizeTerminalText(failure2.hub_name || failure2.hub_id || "")} (${failure2.hub_id})` : `organization ${failure2.organization_id}`;
27621
+ console.error(`Could not read ${where}: ${sanitizeTerminalText(failure2.error)}`);
27578
27622
  }
27579
27623
  if (result.hubs_queried === 0) {
27580
27624
  console.error(
@@ -33071,6 +33115,122 @@ These commands need a browser sign-in (\`wayai login\`). An API token
33071
33115
  }
33072
33116
  });
33073
33117
 
33118
+ // src/commands/contacts.ts
33119
+ var contacts_exports = {};
33120
+ __export(contacts_exports, {
33121
+ contactsCommand: () => contactsCommand
33122
+ });
33123
+ import { parseArgs as parseArgs22 } from "util";
33124
+ function usageError2(message) {
33125
+ return expected(`${message}
33126
+
33127
+ ${USAGE3}`);
33128
+ }
33129
+ function parse2(args2) {
33130
+ try {
33131
+ return parseArgs22({
33132
+ args: args2,
33133
+ options: {
33134
+ org: { type: "string" },
33135
+ base: { type: "string" },
33136
+ record: { type: "string" },
33137
+ json: { type: "boolean" }
33138
+ },
33139
+ allowPositionals: true,
33140
+ strict: true
33141
+ });
33142
+ } catch (err) {
33143
+ throw usageError2(err instanceof Error ? err.message : String(err));
33144
+ }
33145
+ }
33146
+ function resolveOrgId2(flag) {
33147
+ if (flag !== void 0) {
33148
+ if (!UUID_RE3.test(flag)) throw expected(`Invalid --org ${JSON.stringify(flag)}: expected an organization id (a UUID).`);
33149
+ return flag;
33150
+ }
33151
+ const bound = readRepoConfigUnlessBlocked()?.organization_id;
33152
+ if (bound) return bound;
33153
+ throw expected("No organization: pass --org <org_id>, or run this inside a workspace scoped with `wayai init`.");
33154
+ }
33155
+ function failure(err, accessToken) {
33156
+ if (!(err instanceof ApiError)) return err;
33157
+ if (err.status === 403 && identifyTokenType(accessToken) === "way_token") {
33158
+ const override2 = envTokenOverride() ? " WAYAI_TOKEN is set in this shell and is sent instead of your sign-in: unset it first." : "";
33159
+ return expected(
33160
+ `A contact's customer record is linked from a browser sign-in only, and this login is an API token. Run \`wayai login\` (without --token).${override2}`
33161
+ );
33162
+ }
33163
+ if (err.status >= 400 && err.status < 500) return expected(sanitizeTerminalText(extractApiMessage(err)));
33164
+ return err;
33165
+ }
33166
+ async function contactsCommand(args2) {
33167
+ if (wantsHelp(args2) || args2.length === 0) {
33168
+ console.log(USAGE3);
33169
+ return;
33170
+ }
33171
+ const { values, positionals } = parse2(args2);
33172
+ const [sub, contactId, ...extra] = positionals;
33173
+ if (!SUBCOMMANDS2.includes(sub)) throw usageError2(`Unknown subcommand ${JSON.stringify(sub)}.`);
33174
+ if (contactId === void 0 || extra.length > 0) throw usageError2(`${sub} takes one <contact_id>.`);
33175
+ if (!UUID_RE3.test(contactId)) throw usageError2(`Invalid <contact_id> ${JSON.stringify(contactId)}: expected a contact id (a UUID).`);
33176
+ if (!values.base) throw usageError2(`${sub} needs --base <base_id>.`);
33177
+ if (!isValidBaseId(values.base)) throw usageError2(`Invalid --base ${JSON.stringify(values.base)}: a base id is ${BASE_ID_RULE}.`);
33178
+ if (sub === "link-customer" && !values.record) throw usageError2("link-customer needs --record <record_id>.");
33179
+ if (sub === "unlink-customer" && values.record !== void 0) throw usageError2("--record applies only to link-customer.");
33180
+ const orgId = resolveOrgId2(values.org);
33181
+ const { config, accessToken } = await requireAuth();
33182
+ const api = new ApiClient({ apiUrl: config.api_url, accessToken, onUnauthorized: () => getAccessToken(config) });
33183
+ let customer;
33184
+ try {
33185
+ ({ customer } = sub === "link-customer" ? await api.linkContactCustomer(orgId, contactId, { base_id: values.base, record_id: values.record }) : await api.unlinkContactCustomer(orgId, contactId, values.base));
33186
+ } catch (err) {
33187
+ throw failure(err, accessToken);
33188
+ }
33189
+ if (values.json) {
33190
+ console.log(JSON.stringify(customer, null, 2));
33191
+ return;
33192
+ }
33193
+ const where = `base ${sanitizeTerminalText(customer.base_id)} (${sanitizeTerminalText(customer.record_type)})`;
33194
+ console.log(sub === "link-customer" ? `Contact ${customer.contact_id} is linked to customer record ${sanitizeTerminalText(customer.record_id)} in ${where}.` : `Contact ${customer.contact_id} is unlinked from customer record ${sanitizeTerminalText(customer.record_id)} in ${where}; the record keeps the contact id under ${customer.external_source}.`);
33195
+ }
33196
+ var USAGE3, SUBCOMMANDS2;
33197
+ var init_contacts = __esm({
33198
+ "src/commands/contacts.ts"() {
33199
+ "use strict";
33200
+ init_auth();
33201
+ init_api_client();
33202
+ init_errors2();
33203
+ init_expected();
33204
+ init_repo_config();
33205
+ init_terminal_output();
33206
+ init_token_store();
33207
+ init_base_id();
33208
+ init_utils();
33209
+ USAGE3 = `
33210
+ wayai contacts \u2014 a contact's customer record in one of the organization's bases
33211
+
33212
+ Usage:
33213
+ wayai contacts link-customer <contact_id> --base <base_id> --record <record_id> [--org <org_id>] [--json]
33214
+ wayai contacts unlink-customer <contact_id> --base <base_id> [--org <org_id>] [--json]
33215
+
33216
+ link-customer Make the record the contact's customer record: a conversation with the
33217
+ contact (its WhatsApp phone, Instagram id or app account) then serves that
33218
+ customer through a customer-scoped toolset. The record is one of the base's
33219
+ customer record type (x-customer-scope role root), holding no external key
33220
+ or the contact id under another source. A record keyed under another
33221
+ external_id is refused: re-keying it would orphan its owned records.
33222
+ unlink-customer Unlink the contact's customer record in the base. The record keeps the
33223
+ contact id under the source wayai_contact_unlinked, so its owned records stay
33224
+ its own, and link-customer on the same record links it again.
33225
+
33226
+ The organization is --org, else this repo's (wayai-ws/wayai.yaml). You must be an
33227
+ organization admin. These commands need a browser sign-in (\`wayai login\`): an API
33228
+ token (\`wayai login --token\`, or WAYAI_TOKEN) is refused.
33229
+ `.trim();
33230
+ SUBCOMMANDS2 = ["link-customer", "unlink-customer"];
33231
+ }
33232
+ });
33233
+
33074
33234
  // ../../packages/core/dist/contracts/rekor-toolset.js
33075
33235
  var init_rekor_toolset = __esm({
33076
33236
  "../../packages/core/dist/contracts/rekor-toolset.js"() {
@@ -34040,14 +34200,14 @@ var init_plan = __esm({
34040
34200
 
34041
34201
  // src/knowledge/migrate.ts
34042
34202
  import { isDeepStrictEqual as isDeepStrictEqual3 } from "util";
34043
- async function resolveBases(kb, baseId) {
34044
- const base = await kb.getBase(baseId);
34045
- if (!base || base.deleted) throw expected(`Base "${safe(baseId)}" not found in this organization.`);
34203
+ async function resolveBases(kb, baseId2) {
34204
+ const base = await kb.getBase(baseId2);
34205
+ if (!base || base.deleted) throw expected(`Base "${safe(baseId2)}" not found in this organization.`);
34046
34206
  if (base.environment === "preview") {
34047
34207
  const origin = base.origin_base_id ? await kb.getBase(base.origin_base_id) : null;
34048
34208
  if (!origin || origin.deleted || origin.environment !== "production") {
34049
34209
  throw expected(
34050
- `Base "${safe(baseId)}" is a preview with no production origin, so its file types can never be promoted. Name the production knowledge base, or a preview created from it.`
34210
+ `Base "${safe(baseId2)}" is a preview with no production origin, so its file types can never be promoted. Name the production knowledge base, or a preview created from it.`
34051
34211
  );
34052
34212
  }
34053
34213
  return { production: origin.id, preview: base.id };
@@ -34060,7 +34220,7 @@ async function resolveBases(kb, baseId) {
34060
34220
  }
34061
34221
  if (previews.length !== 1) {
34062
34222
  throw expected(
34063
- previews.length === 0 ? `Base "${safe(baseId)}" has no preview to write its file types in. Create one with \`wayai bases create-preview ${safe(baseId)} --name <name>\`.` : `Base "${safe(baseId)}" has ${previews.length} previews (${previews.map(safe).join(", ")}). Pass the one to write its file types in as --base.`
34223
+ previews.length === 0 ? `Base "${safe(baseId2)}" has no preview to write its file types in. Create one with \`wayai bases create-preview ${safe(baseId2)} --name <name>\`.` : `Base "${safe(baseId2)}" has ${previews.length} previews (${previews.map(safe).join(", ")}). Pass the one to write its file types in as --base.`
34064
34224
  );
34065
34225
  }
34066
34226
  return { production: base.id, preview: previews[0] };
@@ -34513,28 +34673,28 @@ __export(knowledge_exports, {
34513
34673
  knowledgeCommand: () => knowledgeCommand,
34514
34674
  parseKnowledgeArgs: () => parseKnowledgeArgs
34515
34675
  });
34516
- import { parseArgs as parseArgs22 } from "util";
34517
- function usageError2(message) {
34676
+ import { parseArgs as parseArgs23 } from "util";
34677
+ function usageError3(message) {
34518
34678
  return expected(`${message}
34519
- ${USAGE3}`);
34679
+ ${USAGE4}`);
34520
34680
  }
34521
34681
  function readArgs(args2) {
34522
34682
  try {
34523
- return parseArgs22({ args: args2, options: OPTIONS, allowPositionals: true, strict: true });
34683
+ return parseArgs23({ args: args2, options: OPTIONS, allowPositionals: true, strict: true });
34524
34684
  } catch (err) {
34525
- throw usageError2(err instanceof Error ? err.message : String(err));
34685
+ throw usageError3(err instanceof Error ? err.message : String(err));
34526
34686
  }
34527
34687
  }
34528
34688
  function parseKnowledgeArgs(args2) {
34529
34689
  const { values, positionals } = readArgs(args2);
34530
34690
  const [verb, ...extra] = positionals;
34531
- if (verb !== "migrate") throw usageError2(verb === void 0 ? "No subcommand given." : `Unknown subcommand ${JSON.stringify(verb)}.`);
34532
- if (extra.length > 0) throw usageError2(`Unexpected argument ${JSON.stringify(extra[0])}.`);
34533
- if (!values.org) throw usageError2("--org <org_id> is required.");
34534
- if (!UUID_RE3.test(values.org)) throw usageError2(`Invalid --org ${JSON.stringify(values.org)}: expected an organization id (a UUID).`);
34535
- if (!values.base) throw usageError2("--base <knowledge base> is required.");
34691
+ if (verb !== "migrate") throw usageError3(verb === void 0 ? "No subcommand given." : `Unknown subcommand ${JSON.stringify(verb)}.`);
34692
+ if (extra.length > 0) throw usageError3(`Unexpected argument ${JSON.stringify(extra[0])}.`);
34693
+ if (!values.org) throw usageError3("--org <org_id> is required.");
34694
+ if (!UUID_RE3.test(values.org)) throw usageError3(`Invalid --org ${JSON.stringify(values.org)}: expected an organization id (a UUID).`);
34695
+ if (!values.base) throw usageError3("--base <knowledge base> is required.");
34536
34696
  if (values.hub !== void 0 && !UUID_RE3.test(values.hub)) {
34537
- throw usageError2(`Invalid --hub ${JSON.stringify(values.hub)}: expected a hub id (a UUID).`);
34697
+ throw usageError3(`Invalid --hub ${JSON.stringify(values.hub)}: expected a hub id (a UUID).`);
34538
34698
  }
34539
34699
  return {
34540
34700
  orgId: values.org,
@@ -34546,12 +34706,12 @@ function parseKnowledgeArgs(args2) {
34546
34706
  }
34547
34707
  async function knowledgeCommand(args2) {
34548
34708
  if (wantsHelp(args2) || args2.length === 0) {
34549
- console.log(USAGE3);
34709
+ console.log(USAGE4);
34550
34710
  return;
34551
34711
  }
34552
34712
  const options = parseKnowledgeArgs(args2);
34553
34713
  if (!options.dryRun && !options.yes && !isInteractive()) {
34554
- throw usageError2("It asks before it writes; pass -y when not running in a terminal, or --dry-run.");
34714
+ throw usageError3("It asks before it writes; pass -y when not running in a terminal, or --dry-run.");
34555
34715
  }
34556
34716
  const { config, accessToken } = await requireAuth();
34557
34717
  const api = new ApiClient({ apiUrl: config.api_url, accessToken, onUnauthorized: () => getAccessToken(config) });
@@ -34561,7 +34721,7 @@ async function knowledgeCommand(args2) {
34561
34721
  confirm
34562
34722
  });
34563
34723
  }
34564
- var USAGE3, OPTIONS;
34724
+ var USAGE4, OPTIONS;
34565
34725
  var init_knowledge = __esm({
34566
34726
  "src/commands/knowledge.ts"() {
34567
34727
  "use strict";
@@ -34573,7 +34733,7 @@ var init_knowledge = __esm({
34573
34733
  init_helpers();
34574
34734
  init_migrate2();
34575
34735
  init_remote();
34576
- USAGE3 = `
34736
+ USAGE4 = `
34577
34737
  wayai knowledge migrate \u2014 move knowledge resources into the organization's knowledge base
34578
34738
 
34579
34739
  Usage:
@@ -35244,8 +35404,8 @@ function parseScopedTargetFlags(flagArgs, usage3, opts = {}) {
35244
35404
  return { body: { scope: "hub", hub_id: hubId, dry_run: dryRun }, targetLabel: `hub ${hubId}`, dryRun, yes, jsonOutput };
35245
35405
  }
35246
35406
  async function runRepairTeamOrphans(flagArgs) {
35247
- const USAGE4 = "wayai admin hubs repair-team-orphans --all | --org <org_id> | --hub <hub_id> [--dry-run] [--yes] [--json]";
35248
- const { body, targetLabel, dryRun, yes, jsonOutput } = parseScopedTargetFlags(flagArgs, USAGE4);
35407
+ const USAGE5 = "wayai admin hubs repair-team-orphans --all | --org <org_id> | --hub <hub_id> [--dry-run] [--yes] [--json]";
35408
+ const { body, targetLabel, dryRun, yes, jsonOutput } = parseScopedTargetFlags(flagArgs, USAGE5);
35249
35409
  if (!dryRun && !yes && !jsonOutput) {
35250
35410
  console.log(`About to PURGE dangling team references in: ${targetLabel}.`);
35251
35411
  console.log("Memberships pointing at a deleted team are removed (HubDO + UserDO mirror); conversations pinned to one are unassigned.");
@@ -35291,7 +35451,7 @@ async function runRepairTeamOrphans(flagArgs) {
35291
35451
  }
35292
35452
  }
35293
35453
  async function runRepairBranchingOrphans(flagArgs) {
35294
- const USAGE4 = "wayai admin hubs repair-branching-orphans --all | --org <org_id> | --hub <hub_id> [--id <type>:<id> ...] [--dry-run] [--yes] [--json]";
35454
+ const USAGE5 = "wayai admin hubs repair-branching-orphans --all | --org <org_id> | --hub <hub_id> [--id <type>:<id> ...] [--dry-run] [--yes] [--json]";
35295
35455
  const targets = [];
35296
35456
  const scopeArgs = [];
35297
35457
  for (let i = 0; i < flagArgs.length; i++) {
@@ -35309,10 +35469,10 @@ async function runRepairBranchingOrphans(flagArgs) {
35309
35469
  }
35310
35470
  targets.push({ entity_type: entityType, entity_id: entityId });
35311
35471
  }
35312
- const { body, targetLabel, dryRun, yes, jsonOutput } = parseScopedTargetFlags(scopeArgs, USAGE4);
35472
+ const { body, targetLabel, dryRun, yes, jsonOutput } = parseScopedTargetFlags(scopeArgs, USAGE5);
35313
35473
  if (targets.length > 0 && body.scope !== "hub") {
35314
35474
  console.error("--id deletes rows of ONE production hub: combine it with --hub <hub_id>.");
35315
- console.error(USAGE4);
35475
+ console.error(USAGE5);
35316
35476
  process.exit(1);
35317
35477
  }
35318
35478
  if (targets.length > 0 && !dryRun && !yes && !jsonOutput) {
@@ -35374,8 +35534,8 @@ async function runRepairBranchingOrphans(flagArgs) {
35374
35534
  }
35375
35535
  }
35376
35536
  async function runRepairLegacyOrgGrants(flagArgs) {
35377
- const USAGE4 = "wayai admin orgs repair-legacy-grants --all | --org <org_id> [--dry-run] [--yes] [--json]";
35378
- const scoped = parseScopedTargetFlags(flagArgs, USAGE4, {
35537
+ const USAGE5 = "wayai admin orgs repair-legacy-grants --all | --org <org_id> [--dry-run] [--yes] [--json]";
35538
+ const scoped = parseScopedTargetFlags(flagArgs, USAGE5, {
35379
35539
  scopes: ["all", "org"],
35380
35540
  allLabel: "ALL organizations (platform-wide)"
35381
35541
  });
@@ -35427,8 +35587,8 @@ async function runRepairLegacyOrgGrants(flagArgs) {
35427
35587
  }
35428
35588
  }
35429
35589
  async function runHarnessMassDestroy(flagArgs) {
35430
- const USAGE4 = "wayai admin harness mass-destroy --all | --org <org_id> | --hub <hub_id> [--dry-run] [--yes] [--json]";
35431
- const { body, targetLabel, dryRun, yes, jsonOutput } = parseScopedTargetFlags(flagArgs, USAGE4);
35590
+ const USAGE5 = "wayai admin harness mass-destroy --all | --org <org_id> | --hub <hub_id> [--dry-run] [--yes] [--json]";
35591
+ const { body, targetLabel, dryRun, yes, jsonOutput } = parseScopedTargetFlags(flagArgs, USAGE5);
35432
35592
  if (!dryRun && !yes && !jsonOutput) {
35433
35593
  console.log(`About to REAP every live harness session / token / slot in: ${targetLabel}.`);
35434
35594
  console.log("This destroys running harness sessions and revokes their tokens. Run with --dry-run first to see the blast radius.");
@@ -37722,8 +37882,8 @@ function buildBasesReportCommand() {
37722
37882
  if (opts.errorMessage) body.error_message = opts.errorMessage;
37723
37883
  if (opts.context) body.context = opts.context;
37724
37884
  if (opts.reporterEmail) body.reporter_email = opts.reporterEmail;
37725
- const baseId = opts.baseId ?? findBase(this) ?? process.env.WAYAI_BASE;
37726
- if (baseId) body.base_id = baseId;
37885
+ const baseId2 = opts.baseId ?? findBase(this) ?? process.env.WAYAI_BASE;
37886
+ if (baseId2) body.base_id = baseId2;
37727
37887
  if (opts.recordType) body.record_type = opts.recordType;
37728
37888
  if (opts.recordId) body.record_id = opts.recordId;
37729
37889
  if (opts.externalId) body.external_id = opts.externalId;
@@ -38567,28 +38727,28 @@ function buildBasesCommand() {
38567
38727
  bases.command("use <base>").description(
38568
38728
  "Deprecated alias of `wayai use bases/<id>` \u2014 scope this worktree to a base"
38569
38729
  ).action(async function(selector) {
38570
- const baseId = resolveBaseSelectorToId(findGitRoot(), selector);
38730
+ const baseId2 = resolveBaseSelectorToId(findGitRoot(), selector);
38571
38731
  const previous = readScope().bases;
38572
- const changed = previous.length !== 1 || previous[0] !== baseId;
38732
+ const changed = previous.length !== 1 || previous[0] !== baseId2;
38573
38733
  if (changed) {
38574
38734
  try {
38575
- setScopeAxis("bases", [baseId]);
38735
+ setScopeAxis("bases", [baseId2]);
38576
38736
  } catch (err) {
38577
38737
  throw expected(err instanceof Error ? err.message : String(err));
38578
38738
  }
38579
38739
  }
38580
38740
  if (outputFormat(this) === "json") {
38581
38741
  printOutput(
38582
- { base_id: baseId, previous_base_id: previous[0] ?? null, changed },
38742
+ { base_id: baseId2, previous_base_id: previous[0] ?? null, changed },
38583
38743
  "json"
38584
38744
  );
38585
38745
  return;
38586
38746
  }
38587
38747
  if (!changed) {
38588
- console.log(`Worktree already bound to base ${baseId}.`);
38748
+ console.log(`Worktree already bound to base ${baseId2}.`);
38589
38749
  } else {
38590
38750
  console.log(
38591
- previous.length > 0 ? `Worktree rebound: ${previous.join(", ")} -> ${baseId}.` : `Worktree bound to base ${baseId}.`
38751
+ previous.length > 0 ? `Worktree rebound: ${previous.join(", ")} -> ${baseId2}.` : `Worktree bound to base ${baseId2}.`
38592
38752
  );
38593
38753
  }
38594
38754
  });
@@ -41017,6 +41177,11 @@ async function main() {
41017
41177
  await communitiesCommand2(args);
41018
41178
  break;
41019
41179
  }
41180
+ case "contacts": {
41181
+ const { contactsCommand: contactsCommand2 } = await Promise.resolve().then(() => (init_contacts(), contacts_exports));
41182
+ await contactsCommand2(args);
41183
+ break;
41184
+ }
41020
41185
  case "knowledge": {
41021
41186
  const { knowledgeCommand: knowledgeCommand2 } = await Promise.resolve().then(() => (init_knowledge(), knowledge_exports));
41022
41187
  await knowledgeCommand2(args);
@@ -41111,6 +41276,7 @@ Commands:
41111
41276
  sync-mcp Re-discover an MCP connection's tools (refresh stale schemas)
41112
41277
  list List organizations and hubs
41113
41278
  communities An organization's communities: list, join link (get/rotate/off), stats, access list (list/add/remove) \u2014 \`wayai communities --help\`
41279
+ contacts Link a contact to its customer record in a base, or unlink it (browser sign-in only) \u2014 \`wayai contacts --help\`
41114
41280
  knowledge migrate Move an organization's knowledge resources, then a hub's (--hub), into its knowledge base as file types and files \u2014 \`wayai knowledge --help\`
41115
41281
  report create Report a platform bug (submits to the triage queue)
41116
41282
  report edit Amend your own pending report (title/description/error/steps/context)