@tickernelz/paperclip-pro 2026.1002.8 → 2026.1004.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -52,7 +52,7 @@ function clampIssueRequestDepth(value) {
52
52
  if (typeof value !== "number" || !Number.isFinite(value)) return 0;
53
53
  return Math.min(MAX_ISSUE_REQUEST_DEPTH, Math.max(0, Math.floor(value)));
54
54
  }
55
- var COMPANY_STATUSES, DEPLOYMENT_MODES, DEPLOYMENT_EXPOSURES, BIND_MODES, AUTH_BASE_URL_MODES, AGENT_STATUSES, AGENT_ADAPTER_TYPES, AGENT_ROLES, AGENT_ICON_NAMES, PROJECT_ICON_NAMES, ISSUE_STATUSES, INBOX_MINE_ISSUE_STATUSES, INBOX_MINE_ISSUE_STATUS_FILTER, ISSUE_PRIORITIES, ISSUE_REVIEW_POLICIES, ISSUE_WORK_MODES, ISSUE_HARNESS_KINDS, MAX_ISSUE_REQUEST_DEPTH, SUMMARY_SLOT_SCOPE_KINDS, SUMMARY_SLOT_KEYS, SUMMARY_SLOT_STATUSES, ISSUE_COMMENT_AUTHOR_TYPES, ISSUE_COMMENT_DELIVERY_MODES, ISSUE_COMMENT_PRESENTATION_KINDS, ISSUE_COMMENT_PRESENTATION_TONES, ISSUE_COMMENT_PRESENTATION_DENSITIES, ISSUE_COMMENT_METADATA_ROW_TYPES, ISSUE_THREAD_INTERACTION_KINDS, ISSUE_THREAD_INTERACTION_CANONICAL_RESOLVER_POLICIES, ISSUE_THREAD_INTERACTION_LEGACY_RESOLVER_POLICY_ALIASES, ISSUE_THREAD_INTERACTION_RESOLVER_POLICIES, ISSUE_THREAD_INTERACTION_RESOLVER_POLICY_PROVENANCES, ISSUE_THREAD_INTERACTION_EFFECTIVE_RESOLVER_POLICY_SOURCES, REQUEST_CHECKBOX_CONFIRMATION_OPTION_LIMIT, REQUEST_ITEM_VERDICTS_ITEM_LIMIT, ISSUE_THREAD_INTERACTION_STATUSES, ISSUE_THREAD_INTERACTION_CONTINUATION_POLICIES, ISSUE_WATCHDOG_DISCOVERY_KINDS, ISSUE_SURFACE_VISIBILITIES, ISSUE_RECOVERY_ACTION_KINDS, ISSUE_RECOVERY_ACTION_STATUSES, ISSUE_RECOVERY_ACTION_OWNER_TYPES, ISSUE_RECOVERY_ACTION_OUTCOMES, ISSUE_TREE_CONTROL_MODES, ISSUE_TREE_HOLD_RELEASE_POLICY_STRATEGIES, ISSUE_CONTINUATION_SUMMARY_DOCUMENT_KEY, PIPELINE_CASE_BODY_DOCUMENT_KEY, SYSTEM_ISSUE_DOCUMENT_KEYS, SYSTEM_ISSUE_DOCUMENT_KEY_SET, DOCUMENT_ANNOTATION_THREAD_STATUSES, DOCUMENT_ANNOTATION_ANCHOR_STATES, DOCUMENT_ANNOTATION_ANCHOR_CONFIDENCES, EXTERNAL_OBJECT_STATUS_CATEGORIES, EXTERNAL_OBJECT_STATUS_TONES, EXTERNAL_OBJECT_LIVENESS_STATES, EXTERNAL_OBJECT_MENTION_SOURCE_KINDS, EXTERNAL_OBJECT_MENTION_CONFIDENCES, ISSUE_EXECUTION_POLICY_MODES, ISSUE_EXECUTION_STAGE_TYPES, ISSUE_MONITOR_SCHEDULED_BY, ISSUE_EXECUTION_MONITOR_KINDS, ISSUE_EXECUTION_MONITOR_RECOVERY_POLICIES, ISSUE_EXECUTION_STATE_STATUSES, ISSUE_EXECUTION_MONITOR_STATE_STATUSES, ISSUE_EXECUTION_MONITOR_CLEAR_REASONS, ISSUE_EXECUTION_DECISION_OUTCOMES, GOAL_LEVELS, GOAL_STATUSES, PROJECT_STATUSES, ENVIRONMENT_DRIVERS, ENVIRONMENT_STATUSES, ENVIRONMENT_LEASE_STATUSES, ENVIRONMENT_LEASE_CLEANUP_STATUSES, ENVIRONMENT_CUSTOM_IMAGE_TEMPLATE_KINDS, ENVIRONMENT_CUSTOM_IMAGE_TEMPLATE_STATUSES, ENVIRONMENT_CUSTOM_IMAGE_SETUP_SESSION_STATUSES, ENVIRONMENT_CUSTOM_IMAGE_SETUP_CONNECTION_TYPES, ROUTINE_STATUSES, ROUTINE_CONCURRENCY_POLICIES, ROUTINE_CATCH_UP_POLICIES, ROUTINE_ACTIVITY_GATE_POLICIES, ROUTINE_ACTIVITY_GATE_SCOPES, ROUTINE_TRIGGER_KINDS, ROUTINE_TRIGGER_SIGNING_MODES, ROUTINE_VARIABLE_TYPES, APPROVAL_TYPES, SECRET_PROVIDERS, SECRET_PROVIDER_CONFIG_STATUSES, SECRET_STATUSES, SECRET_MANAGED_MODES, SECRET_BINDING_TARGET_TYPES, SECRET_PROJECTION_CLASSES, STORAGE_PROVIDERS, BILLING_TYPES, COST_STATUSES, FINANCE_EVENT_KINDS, FINANCE_DIRECTIONS, FINANCE_UNITS, BUDGET_SCOPE_TYPES, BUDGET_METRICS, BUDGET_WINDOW_KINDS, BUDGET_INCIDENT_RESOLUTION_ACTIONS, HUMAN_COMPANY_MEMBERSHIP_ROLES, INVITE_JOIN_TYPES, JOIN_REQUEST_TYPES, JOIN_REQUEST_STATUSES, PERMISSION_KEYS, TOOL_APPLICATION_TYPES, TOOL_APPLICATION_STATUSES, TOOL_CONNECTION_KINDS, TOOL_CONNECTION_HEALTH_STATUSES, TOOL_CATALOG_ENTRY_KINDS, TOOL_CATALOG_ENTRY_STATUSES, TOOL_RISK_LEVELS, TOOL_PROFILE_STATUSES, TOOL_PROFILE_DEFAULT_ACTIONS, TOOL_PROFILE_ENTRY_SELECTOR_TYPES, TOOL_PROFILE_ENTRY_EFFECTS, TOOL_PROFILE_BINDING_TARGET_TYPES, TOOL_MCP_GATEWAY_STATUSES, TOOL_MCP_GATEWAY_DEFAULT_PROFILE_MODES, TOOL_MCP_GATEWAY_CONTEXT_SCOPE_TYPES, TOOL_MCP_GATEWAY_TOKEN_SUBJECT_TYPES, TOOL_MCP_GATEWAY_TOKEN_ACTIONS, CONNECTION_TOKEN_ISSUANCE_PATHS, TOOL_POLICY_TYPES, TOOL_POLICY_DECISIONS, TOOL_INVOCATION_STATUSES, TOOL_INVOCATION_APPROVAL_STATES, TOOL_ACTION_REQUEST_STATUSES, TOOL_AUDIT_EVENT_TYPES, TOOL_AUDIT_OUTCOMES, TOOL_RUNTIME_KINDS, TOOL_RUNTIME_SLOT_STATUSES, TOOL_RATE_LIMIT_WINDOW_KINDS, PLUGIN_STATUSES, PLUGIN_CATEGORIES, PLUGIN_CAPABILITIES, PLUGIN_DATABASE_CORE_READ_TABLES, PLUGIN_API_ROUTE_METHODS, PLUGIN_API_ROUTE_AUTH_MODES, PLUGIN_API_ROUTE_CHECKOUT_POLICIES, PLUGIN_UI_SLOT_TYPES, WORKSPACE_OVERVIEW_DEFAULT_LIMIT, WORKSPACE_OVERVIEW_MAX_LIMIT, PLUGIN_RESERVED_COMPANY_ROUTE_SEGMENTS, PLUGIN_RESERVED_COMPANY_SETTINGS_ROUTE_SEGMENTS, PLUGIN_LAUNCHER_PLACEMENT_ZONES, PLUGIN_LAUNCHER_ACTIONS, PLUGIN_LAUNCHER_BOUNDS, PLUGIN_LAUNCHER_RENDER_ENVIRONMENTS, PLUGIN_UI_SLOT_ENTITY_TYPES, PLUGIN_STATE_SCOPE_KINDS;
55
+ var COMPANY_STATUSES, DEPLOYMENT_MODES, DEPLOYMENT_EXPOSURES, BIND_MODES, AUTH_BASE_URL_MODES, AGENT_STATUSES, AGENT_ADAPTER_TYPES, AGENT_ROLES, AGENT_ICON_NAMES, PROJECT_ICON_NAMES, ISSUE_STATUSES, INBOX_MINE_ISSUE_STATUSES, INBOX_MINE_ISSUE_STATUS_FILTER, ISSUE_PRIORITIES, ISSUE_REVIEW_POLICIES, ISSUE_WORK_MODES, ISSUE_HARNESS_KINDS, MAX_ISSUE_REQUEST_DEPTH, SUMMARY_SLOT_SCOPE_KINDS, SUMMARY_SLOT_KEYS, SUMMARY_SLOT_STATUSES, ISSUE_COMMENT_AUTHOR_TYPES, ISSUE_COMMENT_DELIVERY_MODES, ISSUE_COMMENT_PRESENTATION_KINDS, ISSUE_COMMENT_PRESENTATION_TONES, ISSUE_COMMENT_PRESENTATION_DENSITIES, ISSUE_COMMENT_METADATA_ROW_TYPES, ISSUE_THREAD_INTERACTION_KINDS, ISSUE_THREAD_INTERACTION_REQUESTABLE_RESOLVER_POLICIES, ISSUE_THREAD_INTERACTION_CANONICAL_RESOLVER_POLICIES, ISSUE_THREAD_INTERACTION_LEGACY_RESOLVER_POLICY_ALIASES, ISSUE_THREAD_INTERACTION_RESOLVER_POLICIES, ISSUE_THREAD_INTERACTION_RESOLVER_POLICY_PROVENANCES, ISSUE_THREAD_INTERACTION_EFFECTIVE_RESOLVER_POLICY_SOURCES, REQUEST_CHECKBOX_CONFIRMATION_OPTION_LIMIT, REQUEST_ITEM_VERDICTS_ITEM_LIMIT, ISSUE_THREAD_INTERACTION_STATUSES, ISSUE_THREAD_INTERACTION_CONTINUATION_POLICIES, ISSUE_WATCHDOG_DISCOVERY_KINDS, ISSUE_SURFACE_VISIBILITIES, ISSUE_RECOVERY_ACTION_KINDS, ISSUE_RECOVERY_ACTION_STATUSES, ISSUE_RECOVERY_ACTION_OWNER_TYPES, ISSUE_RECOVERY_ACTION_OUTCOMES, ISSUE_TREE_CONTROL_MODES, ISSUE_TREE_HOLD_RELEASE_POLICY_STRATEGIES, ISSUE_CONTINUATION_SUMMARY_DOCUMENT_KEY, PIPELINE_CASE_BODY_DOCUMENT_KEY, SYSTEM_ISSUE_DOCUMENT_KEYS, SYSTEM_ISSUE_DOCUMENT_KEY_SET, DOCUMENT_ANNOTATION_THREAD_STATUSES, DOCUMENT_ANNOTATION_ANCHOR_STATES, DOCUMENT_ANNOTATION_ANCHOR_CONFIDENCES, EXTERNAL_OBJECT_STATUS_CATEGORIES, EXTERNAL_OBJECT_STATUS_TONES, EXTERNAL_OBJECT_LIVENESS_STATES, EXTERNAL_OBJECT_MENTION_SOURCE_KINDS, EXTERNAL_OBJECT_MENTION_CONFIDENCES, ISSUE_EXECUTION_POLICY_MODES, ISSUE_EXECUTION_STAGE_TYPES, ISSUE_MONITOR_SCHEDULED_BY, ISSUE_EXECUTION_MONITOR_KINDS, ISSUE_EXECUTION_MONITOR_RECOVERY_POLICIES, ISSUE_EXECUTION_STATE_STATUSES, ISSUE_EXECUTION_MONITOR_STATE_STATUSES, ISSUE_EXECUTION_MONITOR_CLEAR_REASONS, ISSUE_EXECUTION_DECISION_OUTCOMES, GOAL_LEVELS, GOAL_STATUSES, PROJECT_STATUSES, ENVIRONMENT_DRIVERS, ENVIRONMENT_STATUSES, ENVIRONMENT_LEASE_STATUSES, ENVIRONMENT_LEASE_CLEANUP_STATUSES, ENVIRONMENT_CUSTOM_IMAGE_TEMPLATE_KINDS, ENVIRONMENT_CUSTOM_IMAGE_TEMPLATE_STATUSES, ENVIRONMENT_CUSTOM_IMAGE_SETUP_SESSION_STATUSES, ENVIRONMENT_CUSTOM_IMAGE_SETUP_CONNECTION_TYPES, ROUTINE_STATUSES, ROUTINE_CONCURRENCY_POLICIES, ROUTINE_CATCH_UP_POLICIES, ROUTINE_ACTIVITY_GATE_POLICIES, ROUTINE_ACTIVITY_GATE_SCOPES, ROUTINE_TRIGGER_KINDS, ROUTINE_TRIGGER_SIGNING_MODES, ROUTINE_VARIABLE_TYPES, APPROVAL_TYPES, SECRET_PROVIDERS, SECRET_PROVIDER_CONFIG_STATUSES, SECRET_STATUSES, SECRET_MANAGED_MODES, SECRET_BINDING_TARGET_TYPES, SECRET_PROJECTION_CLASSES, STORAGE_PROVIDERS, BILLING_TYPES, COST_STATUSES, FINANCE_EVENT_KINDS, FINANCE_DIRECTIONS, FINANCE_UNITS, BUDGET_SCOPE_TYPES, BUDGET_METRICS, BUDGET_WINDOW_KINDS, BUDGET_INCIDENT_RESOLUTION_ACTIONS, HUMAN_COMPANY_MEMBERSHIP_ROLES, INVITE_JOIN_TYPES, JOIN_REQUEST_TYPES, JOIN_REQUEST_STATUSES, PERMISSION_KEYS, TOOL_APPLICATION_TYPES, TOOL_APPLICATION_STATUSES, TOOL_CONNECTION_KINDS, TOOL_CONNECTION_HEALTH_STATUSES, TOOL_CATALOG_ENTRY_KINDS, TOOL_CATALOG_ENTRY_STATUSES, TOOL_RISK_LEVELS, TOOL_PROFILE_STATUSES, TOOL_PROFILE_DEFAULT_ACTIONS, TOOL_PROFILE_ENTRY_SELECTOR_TYPES, TOOL_PROFILE_ENTRY_EFFECTS, TOOL_PROFILE_BINDING_TARGET_TYPES, TOOL_MCP_GATEWAY_STATUSES, TOOL_MCP_GATEWAY_DEFAULT_PROFILE_MODES, TOOL_MCP_GATEWAY_CONTEXT_SCOPE_TYPES, TOOL_MCP_GATEWAY_TOKEN_SUBJECT_TYPES, TOOL_MCP_GATEWAY_TOKEN_ACTIONS, CONNECTION_TOKEN_ISSUANCE_PATHS, TOOL_POLICY_TYPES, TOOL_POLICY_DECISIONS, TOOL_INVOCATION_STATUSES, TOOL_INVOCATION_APPROVAL_STATES, TOOL_ACTION_REQUEST_STATUSES, TOOL_AUDIT_EVENT_TYPES, TOOL_AUDIT_OUTCOMES, TOOL_RUNTIME_KINDS, TOOL_RUNTIME_SLOT_STATUSES, TOOL_RATE_LIMIT_WINDOW_KINDS, PLUGIN_STATUSES, PLUGIN_CATEGORIES, PLUGIN_CAPABILITIES, PLUGIN_DATABASE_CORE_READ_TABLES, PLUGIN_API_ROUTE_METHODS, PLUGIN_API_ROUTE_AUTH_MODES, PLUGIN_API_ROUTE_CHECKOUT_POLICIES, PLUGIN_UI_SLOT_TYPES, WORKSPACE_OVERVIEW_DEFAULT_LIMIT, WORKSPACE_OVERVIEW_MAX_LIMIT, PLUGIN_RESERVED_COMPANY_ROUTE_SEGMENTS, PLUGIN_RESERVED_COMPANY_SETTINGS_ROUTE_SEGMENTS, PLUGIN_LAUNCHER_PLACEMENT_ZONES, PLUGIN_LAUNCHER_ACTIONS, PLUGIN_LAUNCHER_BOUNDS, PLUGIN_LAUNCHER_RENDER_ENVIRONMENTS, PLUGIN_UI_SLOT_ENTITY_TYPES, PLUGIN_STATE_SCOPE_KINDS;
56
56
  var init_constants = __esm({
57
57
  "../packages/shared/src/constants.ts"() {
58
58
  "use strict";
@@ -238,17 +238,21 @@ var init_constants = __esm({
238
238
  "request_item_verdicts",
239
239
  "connection_intent"
240
240
  ];
241
- ISSUE_THREAD_INTERACTION_CANONICAL_RESOLVER_POLICIES = [
241
+ ISSUE_THREAD_INTERACTION_REQUESTABLE_RESOLVER_POLICIES = [
242
242
  "anyone",
243
243
  "not_creator",
244
244
  "human_only"
245
245
  ];
246
+ ISSUE_THREAD_INTERACTION_CANONICAL_RESOLVER_POLICIES = [
247
+ ...ISSUE_THREAD_INTERACTION_REQUESTABLE_RESOLVER_POLICIES,
248
+ "chat_endpoint_owner"
249
+ ];
246
250
  ISSUE_THREAD_INTERACTION_LEGACY_RESOLVER_POLICY_ALIASES = [
247
251
  "board_or_agents",
248
252
  "board_only"
249
253
  ];
250
254
  ISSUE_THREAD_INTERACTION_RESOLVER_POLICIES = [
251
- ...ISSUE_THREAD_INTERACTION_CANONICAL_RESOLVER_POLICIES,
255
+ ...ISSUE_THREAD_INTERACTION_REQUESTABLE_RESOLVER_POLICIES,
252
256
  ...ISSUE_THREAD_INTERACTION_LEGACY_RESOLVER_POLICY_ALIASES
253
257
  ];
254
258
  ISSUE_THREAD_INTERACTION_RESOLVER_POLICY_PROVENANCES = [
@@ -2289,6 +2293,83 @@ var init_imessage_photon = __esm({
2289
2293
  }
2290
2294
  });
2291
2295
 
2296
+ // ../packages/shared/src/app-definitions/openwa.json
2297
+ var openwa_default;
2298
+ var init_openwa = __esm({
2299
+ "../packages/shared/src/app-definitions/openwa.json"() {
2300
+ openwa_default = {
2301
+ schemaVersion: 1,
2302
+ slug: "openwa",
2303
+ name: "OpenWA",
2304
+ description: "Let the owner and people on a WhatsApp number work with one Paperclip agent through a self-hosted OpenWA gateway.",
2305
+ categories: [
2306
+ "communication"
2307
+ ],
2308
+ featured: false,
2309
+ branding: {
2310
+ logoUrl: "/brands/apps/openwa.svg"
2311
+ },
2312
+ urlPatterns: [
2313
+ "https://github.com/rmyndharis/OpenWA*"
2314
+ ],
2315
+ methods: [
2316
+ {
2317
+ key: "chat-agent",
2318
+ label: "Chat with an agent",
2319
+ purpose: "channel",
2320
+ provider: "openwa",
2321
+ transport: "chat_sdk",
2322
+ auth: "api_key",
2323
+ ownershipModes: [
2324
+ "customer"
2325
+ ],
2326
+ whenToUse: "Let people in OpenWA start and continue work with one Paperclip agent.",
2327
+ credentialFields: [
2328
+ {
2329
+ key: "baseUrl",
2330
+ label: "Gateway URL",
2331
+ type: "text",
2332
+ required: true,
2333
+ placeholder: "http://localhost:2785",
2334
+ secret: false,
2335
+ helperMd: "The OpenWA gateway origin. Loopback addresses are allowed for self-hosted gateways."
2336
+ },
2337
+ {
2338
+ key: "apiKey",
2339
+ label: "Operator API key",
2340
+ type: "password",
2341
+ required: true,
2342
+ placeholder: "OpenWA operator key scoped to one session",
2343
+ secret: true,
2344
+ helperMd: "Create an operator key whose allowedSessions contains only the agent's session and no allowedChats."
2345
+ },
2346
+ {
2347
+ key: "adminApiKey",
2348
+ label: "Admin API key",
2349
+ type: "password",
2350
+ required: false,
2351
+ placeholder: "Optional unscoped admin key",
2352
+ secret: true,
2353
+ advanced: true,
2354
+ helperMd: "Only needed when gateway admin tools are enabled in Settings."
2355
+ }
2356
+ ],
2357
+ guidanceMd: "Connect a self-hosted OpenWA gateway session. Paperclip inspects the gateway read-only, then asks you to confirm that send pacing is enabled and that Paperclip is the only client sending as the session before an owner sends a test WhatsApp message.",
2358
+ consoleLinks: {
2359
+ register: "https://github.com/rmyndharis/OpenWA",
2360
+ docs: "https://github.com/rmyndharis/OpenWA"
2361
+ },
2362
+ riskTier: "S3",
2363
+ requiredResourceFilters: [
2364
+ "direct_message",
2365
+ "group_chat"
2366
+ ]
2367
+ }
2368
+ ]
2369
+ };
2370
+ }
2371
+ });
2372
+
2292
2373
  // ../packages/shared/src/app-definitions/telegram.json
2293
2374
  var telegram_default;
2294
2375
  var init_telegram = __esm({
@@ -8065,6 +8146,7 @@ var init_app_definitions_generated = __esm({
8065
8146
  init_slack();
8066
8147
  init_microsoft_teams();
8067
8148
  init_imessage_photon();
8149
+ init_openwa();
8068
8150
  init_telegram();
8069
8151
  init_discord();
8070
8152
  init_notion();
@@ -8131,7 +8213,7 @@ var init_app_definitions_generated = __esm({
8131
8213
  init_openai();
8132
8214
  init_openrouter();
8133
8215
  init_xai();
8134
- APP_DEFINITIONS = [agentmail_default, zapier_default, arcade_default, executor_default, railway_default, github_default, slack_default, microsoft_teams_default, imessage_photon_default, telegram_default, discord_default, notion_default, posthog_default, linear_default, context7_default, shopify_default, composio_default, oauth_generic_default, api_key_generic_default, sentry_default, vercel_default, anthropic_default, jira_default, airtable_default, beehiiv_default, bitly_default, candid_default, cloudflare_default, cloudinary_default, coda_default, hugging_face_default, kernel_default, local_falcon_default, make_default, manufact_default, miro_default, netlify_default, oreilly_default, planetscale_default, resend_default, ticktick_default, todoist_default, webflow_default, wix_default, brex_default, clickhouse_default, egnyte_default, embat_default, mixpanel_default, postman_default, razorpay_default, sanity_default, stripe_default, supabase_default, ticket_tailor_default, asana_default, box_default, mem0_default, pagerduty_default, similarweb_default, xero_default, youcom_default, fireflies_default, gmail_default, google_drive_default, google_docs_default, google_sheets_default, google_slides_default, google_calendar_default, google_chat_default, google_people_default, google_workspace_search_default, openai_default, openrouter_default, xai_default];
8216
+ APP_DEFINITIONS = [agentmail_default, zapier_default, arcade_default, executor_default, railway_default, github_default, slack_default, microsoft_teams_default, imessage_photon_default, openwa_default, telegram_default, discord_default, notion_default, posthog_default, linear_default, context7_default, shopify_default, composio_default, oauth_generic_default, api_key_generic_default, sentry_default, vercel_default, anthropic_default, jira_default, airtable_default, beehiiv_default, bitly_default, candid_default, cloudflare_default, cloudinary_default, coda_default, hugging_face_default, kernel_default, local_falcon_default, make_default, manufact_default, miro_default, netlify_default, oreilly_default, planetscale_default, resend_default, ticktick_default, todoist_default, webflow_default, wix_default, brex_default, clickhouse_default, egnyte_default, embat_default, mixpanel_default, postman_default, razorpay_default, sanity_default, stripe_default, supabase_default, ticket_tailor_default, asana_default, box_default, mem0_default, pagerduty_default, similarweb_default, xero_default, youcom_default, fireflies_default, gmail_default, google_drive_default, google_docs_default, google_sheets_default, google_slides_default, google_calendar_default, google_chat_default, google_people_default, google_workspace_search_default, openai_default, openrouter_default, xai_default];
8135
8217
  }
8136
8218
  });
8137
8219
 
@@ -8250,7 +8332,8 @@ var init_app_definitions = __esm({
8250
8332
  "discord",
8251
8333
  "microsoft-teams",
8252
8334
  "telegram",
8253
- "imessage-photon"
8335
+ "imessage-photon",
8336
+ "openwa"
8254
8337
  ]);
8255
8338
  CONNECTABLE_APP_DEFINITIONS = APP_DEFINITIONS.filter(
8256
8339
  (app) => CONNECTABLE_APP_SLUGS.has(app.slug)
@@ -9720,7 +9803,7 @@ var init_issue = __esm({
9720
9803
  issueThreadInteractionKindSchema = z16.enum(
9721
9804
  ISSUE_THREAD_INTERACTION_KINDS
9722
9805
  );
9723
- issueThreadInteractionCanonicalResolverPolicySchema = z16.enum(ISSUE_THREAD_INTERACTION_CANONICAL_RESOLVER_POLICIES).describe("Canonical resolver audience: anyone, not_creator, or human_only.");
9806
+ issueThreadInteractionCanonicalResolverPolicySchema = z16.enum(ISSUE_THREAD_INTERACTION_CANONICAL_RESOLVER_POLICIES).describe("Canonical resolver audience: anyone, not_creator, human_only, or chat_endpoint_owner (server-assigned to OpenWA approval cards).");
9724
9807
  issueThreadInteractionResolverPolicySchema = z16.enum(ISSUE_THREAD_INTERACTION_RESOLVER_POLICIES).describe(
9725
9808
  "Resolver audience. Use anyone, not_creator, or human_only; board_or_agents and board_only are deprecated compatibility aliases."
9726
9809
  );
@@ -10094,7 +10177,8 @@ var init_issue = __esm({
10094
10177
  supersedeOnUserComment: z16.boolean().optional(),
10095
10178
  target: requestConfirmationTargetSchema.nullable().optional(),
10096
10179
  toolAction: requestConfirmationToolActionPayloadSchema.optional(),
10097
- secretProposal: requestConfirmationSecretProposalPayloadSchema.optional()
10180
+ secretProposal: requestConfirmationSecretProposalPayloadSchema.optional(),
10181
+ openwaApprovalRequestId: z16.string().uuid().optional()
10098
10182
  });
10099
10183
  requestCheckboxConfirmationOptionSchema = z16.object({
10100
10184
  id: z16.string().trim().min(1).max(120),
@@ -12857,7 +12941,7 @@ var init_app_definition = __esm({
12857
12941
  if (v.type === "select" && (!v.options || v.options.length === 0)) c.addIssue({ code: "custom", message: "Select fields need options", path: ["options"] });
12858
12942
  if (v.hidden && v.defaultValue === void 0) c.addIssue({ code: "custom", message: "Hidden fields need defaults", path: ["defaultValue"] });
12859
12943
  });
12860
- connectionMethodDefSchema = z22.object({ key: z22.string().min(1), label: z22.string().min(1).optional(), purpose: z22.union([toolConnectionPurposeSchema, z22.literal("ai")]).optional(), provider: z22.enum(["slack", "github", "discord", "microsoft-teams", "telegram", "agentmail", "imessage-photon"]).optional(), transport: z22.union([toolConnectionTransportSchema, z22.literal("runtime_auth")]), ai: aiConnectionMetadataSchema.optional(), auth: z22.enum(["oauth", "api_key", "none"]), oauthStrategy: z22.enum(["paperclip_cloud_connector", "paperclip_id_connector"]).optional(), connectorProfile: z22.string().regex(/^[a-z0-9]+(?:[.-][a-z0-9]+)*$/).optional(), capabilityProfile: z22.object({ key: z22.string().min(1), label: z22.string().min(1), description: z22.string().min(1).optional() }).optional(), grantKinds: z22.array(connectionGrantKindSchema).min(1).optional(), ownershipModes: z22.array(toolConnectionOwnershipSchema).min(1), whenToUse: z22.string().min(1), defaults: z22.object({ serverUrl: z22.string().url().optional(), serverUrlTemplate: z22.string().regex(/^https:\/\//).optional(), discoveryUrl: z22.string().url().nullable().optional(), serviceHost: z22.string().optional(), templateKey: z22.string().optional(), authorizationEndpoint: z22.string().url().optional(), tokenEndpoint: z22.string().url().optional(), metadataUrl: z22.string().url().optional(), scopesHint: z22.array(z22.string()).optional(), oauthAuthorizationParams: z22.object({ access_type: z22.literal("offline").optional(), prompt: z22.literal("consent").optional() }).optional(), toolArgumentDefaults: z22.record(z22.string(), z22.unknown()).optional() }).optional(), tenantFields: z22.array(field).optional(), extensionFields: z22.array(field).optional(), configRequirements: z22.object({ atLeastOneOf: z22.array(z22.string().min(1)).min(1).optional() }).optional(), credentialFields: z22.array(field).optional(), keyPlacement: z22.object({ location: z22.enum(["header", "query", "body_json", "env"]), name: z22.string().min(1), prefix: z22.string().nullable().optional() }).optional(), credentialSources: z22.object({ vercelConnect: z22.object({ services: z22.array(z22.string().min(1)).min(1), principalModes: z22.array(z22.enum(["app", "user"])).min(1), scopes: z22.array(z22.string().min(1)).min(1), header: z22.object({ name: z22.string().min(1), prefix: z22.string().nullable().optional() }) }).optional() }).optional(), guidanceMd: z22.string().min(1), consoleLinks: z22.object({ register: z22.string().url().optional(), keys: z22.string().url().optional(), settings: z22.string().url().optional(), docs: z22.string().url().optional() }).optional(), warnings: z22.array(z22.string()).optional(), variants: z22.array(z22.object({ key: z22.string(), label: z22.string(), whenToUse: z22.string(), tenantFields: z22.array(field).optional() })).optional(), riskTier: z22.enum(["S1", "S2", "S3", "S4"]), requiredResourceFilters: z22.array(z22.string()).optional() }).superRefine((v, c) => {
12944
+ connectionMethodDefSchema = z22.object({ key: z22.string().min(1), label: z22.string().min(1).optional(), purpose: z22.union([toolConnectionPurposeSchema, z22.literal("ai")]).optional(), provider: z22.enum(["slack", "github", "discord", "microsoft-teams", "telegram", "agentmail", "imessage-photon", "openwa"]).optional(), transport: z22.union([toolConnectionTransportSchema, z22.literal("runtime_auth")]), ai: aiConnectionMetadataSchema.optional(), auth: z22.enum(["oauth", "api_key", "none"]), oauthStrategy: z22.enum(["paperclip_cloud_connector", "paperclip_id_connector"]).optional(), connectorProfile: z22.string().regex(/^[a-z0-9]+(?:[.-][a-z0-9]+)*$/).optional(), capabilityProfile: z22.object({ key: z22.string().min(1), label: z22.string().min(1), description: z22.string().min(1).optional() }).optional(), grantKinds: z22.array(connectionGrantKindSchema).min(1).optional(), ownershipModes: z22.array(toolConnectionOwnershipSchema).min(1), whenToUse: z22.string().min(1), defaults: z22.object({ serverUrl: z22.string().url().optional(), serverUrlTemplate: z22.string().regex(/^https:\/\//).optional(), discoveryUrl: z22.string().url().nullable().optional(), serviceHost: z22.string().optional(), templateKey: z22.string().optional(), authorizationEndpoint: z22.string().url().optional(), tokenEndpoint: z22.string().url().optional(), metadataUrl: z22.string().url().optional(), scopesHint: z22.array(z22.string()).optional(), oauthAuthorizationParams: z22.object({ access_type: z22.literal("offline").optional(), prompt: z22.literal("consent").optional() }).optional(), toolArgumentDefaults: z22.record(z22.string(), z22.unknown()).optional() }).optional(), tenantFields: z22.array(field).optional(), extensionFields: z22.array(field).optional(), configRequirements: z22.object({ atLeastOneOf: z22.array(z22.string().min(1)).min(1).optional() }).optional(), credentialFields: z22.array(field).optional(), keyPlacement: z22.object({ location: z22.enum(["header", "query", "body_json", "env"]), name: z22.string().min(1), prefix: z22.string().nullable().optional() }).optional(), credentialSources: z22.object({ vercelConnect: z22.object({ services: z22.array(z22.string().min(1)).min(1), principalModes: z22.array(z22.enum(["app", "user"])).min(1), scopes: z22.array(z22.string().min(1)).min(1), header: z22.object({ name: z22.string().min(1), prefix: z22.string().nullable().optional() }) }).optional() }).optional(), guidanceMd: z22.string().min(1), consoleLinks: z22.object({ register: z22.string().url().optional(), keys: z22.string().url().optional(), settings: z22.string().url().optional(), docs: z22.string().url().optional() }).optional(), warnings: z22.array(z22.string()).optional(), variants: z22.array(z22.object({ key: z22.string(), label: z22.string(), whenToUse: z22.string(), tenantFields: z22.array(field).optional() })).optional(), riskTier: z22.enum(["S1", "S2", "S3", "S4"]), requiredResourceFilters: z22.array(z22.string()).optional() }).superRefine((v, c) => {
12861
12945
  if (v.transport === "runtime_auth" !== Boolean(v.ai)) c.addIssue({ code: "custom", message: "Runtime authentication requires AI metadata and AI metadata requires runtime_auth", path: ["ai"] });
12862
12946
  if (v.ai && !AI_CONNECTION_CAPABILITIES[v.ai.provider].methods[v.ai.method]) c.addIssue({ code: "custom", message: "Unsupported AI sign-in method", path: ["ai", "method"] });
12863
12947
  if (v.ai && v.auth !== (v.ai.method === "subscription" ? "oauth" : "api_key")) c.addIssue({ code: "custom", message: "AI sign-in method must match authentication", path: ["auth"] });
@@ -12888,7 +12972,7 @@ var init_app_definition = __esm({
12888
12972
  });
12889
12973
 
12890
12974
  // ../packages/shared/src/types/chat-channels.ts
12891
- var CHAT_PROVIDERS, CHAT_ENDPOINT_STATUSES, CHAT_CONCURRENCY_POLICIES, CHAT_EVENT_KINDS, CHAT_DELIVERY_STATES, CHAT_PUBLICATION_STATES, CHAT_FILE_TRANSFER_PHASES, CHAT_PRINCIPAL_KINDS, CHAT_IDENTITY_LINK_STATUSES, CHAT_RESOURCE_AVAILABILITIES;
12975
+ var CHAT_PROVIDERS, CHAT_ENDPOINT_STATUSES, CHAT_CONCURRENCY_POLICIES, CHAT_EVENT_KINDS, CHAT_DELIVERY_STATES, CHAT_PUBLICATION_STATES, CHAT_FILE_TRANSFER_PHASES, CHAT_PRINCIPAL_KINDS, CHAT_IDENTITY_LINK_STATUSES, CHAT_RESOURCE_AVAILABILITIES, CHAT_INFLIGHT_MODES, OPENWA_NUMBER_MODES, OPENWA_SENDER_POLICY_MODES, OPENWA_REPLY_POLICIES, OPENWA_CHAT_ACTIVATIONS, OPENWA_GATEWAY_ADMIN_TOOL_LEVELS, OPENWA_APPROVAL_CATEGORIES, OPENWA_GRANT_CATEGORIES, CHAT_SENDER_RULE_LISTS, CHAT_OWNER_APPROVAL_STATUSES;
12892
12976
  var init_chat_channels = __esm({
12893
12977
  "../packages/shared/src/types/chat-channels.ts"() {
12894
12978
  "use strict";
@@ -12899,7 +12983,8 @@ var init_chat_channels = __esm({
12899
12983
  "microsoft-teams",
12900
12984
  "telegram",
12901
12985
  "agentmail",
12902
- "imessage-photon"
12986
+ "imessage-photon",
12987
+ "openwa"
12903
12988
  ];
12904
12989
  CHAT_ENDPOINT_STATUSES = [
12905
12990
  "draft",
@@ -12982,6 +13067,26 @@ var init_chat_channels = __esm({
12982
13067
  "unavailable",
12983
13068
  "removed"
12984
13069
  ];
13070
+ CHAT_INFLIGHT_MODES = ["steer", "queue"];
13071
+ OPENWA_NUMBER_MODES = ["agent_number", "owner_number"];
13072
+ OPENWA_SENDER_POLICY_MODES = ["all", "allowlist", "denylist"];
13073
+ OPENWA_REPLY_POLICIES = ["allowed", "ask_owner", "owner_absent_only"];
13074
+ OPENWA_CHAT_ACTIVATIONS = ["auto", "on", "off"];
13075
+ OPENWA_GATEWAY_ADMIN_TOOL_LEVELS = ["off", "read", "full"];
13076
+ OPENWA_APPROVAL_CATEGORIES = [
13077
+ "create_task",
13078
+ "external_tools",
13079
+ "cross_chat_send",
13080
+ "wa_admin",
13081
+ "gateway_admin"
13082
+ ];
13083
+ OPENWA_GRANT_CATEGORIES = [
13084
+ ...OPENWA_APPROVAL_CATEGORIES,
13085
+ "reply_outside_allowlist",
13086
+ "reply"
13087
+ ];
13088
+ CHAT_SENDER_RULE_LISTS = ["allow", "deny"];
13089
+ CHAT_OWNER_APPROVAL_STATUSES = ["pending", "approved", "rejected", "cancelled"];
12985
13090
  }
12986
13091
  });
12987
13092
 
@@ -13133,7 +13238,20 @@ var init_chat_github2 = __esm({
13133
13238
 
13134
13239
  // ../packages/shared/src/validators/chat-channels.ts
13135
13240
  import { z as z24 } from "zod";
13136
- var chatProviderSchema, chatEndpointStatusSchema, chatConcurrencyPolicySchema, chatEventKindSchema, chatDeliveryStateSchema, chatPublicationStateSchema, chatPrincipalKindSchema, chatIdentityLinkStatusSchema, chatResourceAvailabilitySchema, microsoftTeamsCredentialIdSchema, chatEndpointCredentialsSchema, createChatEndpointSchema, slackAppConfigurationSchema, updateChatEndpointSchema, photonProjectIdSchema, photonLineIdSchema, photonChannelConfigurationSchema, inspectPhotonProjectSchema, configureChatEndpointSchema, replaceChatEndpointResourcesSchema, publishChatCommentSchema, publishChatBoardMessageSchema, publishChatPublicationSchema, resolveChatPublicationSchema, resolveChatActionSchema, createChatIdentityLinkIntentSchema, confirmChatIdentityLinkSchema, replayChatDeliverySchema, chatPublicEndpointIdSchema;
13241
+ function openwaDefaultTriggerRules(numberMode) {
13242
+ const agentNumber = numberMode === "agent_number";
13243
+ return {
13244
+ directMessage: agentNumber,
13245
+ agentMentioned: agentNumber,
13246
+ replyToAgent: true,
13247
+ commandPrefix: { enabled: !agentNumber, prefix: OPENWA_DEFAULT_COMMAND_PREFIX },
13248
+ selfChat: !agentNumber,
13249
+ ownerMentionedAbsent: true,
13250
+ keywords: [],
13251
+ allMessages: false
13252
+ };
13253
+ }
13254
+ var chatProviderSchema, chatEndpointStatusSchema, chatConcurrencyPolicySchema, chatEventKindSchema, chatDeliveryStateSchema, chatPublicationStateSchema, chatPrincipalKindSchema, chatIdentityLinkStatusSchema, chatResourceAvailabilitySchema, microsoftTeamsCredentialIdSchema, chatEndpointCredentialsSchema, createChatEndpointSchema, slackAppConfigurationSchema, updateChatEndpointSchema, photonProjectIdSchema, photonLineIdSchema, photonChannelConfigurationSchema, inspectPhotonProjectSchema, openwaBaseUrlSchema, openwaSessionIdSchema, openwaApiKeyInputSchema, inspectOpenwaGatewaySchema, openwaChannelConfigurationSchema, configureChatEndpointSchema, replaceChatEndpointResourcesSchema, publishChatCommentSchema, publishChatBoardMessageSchema, publishChatPublicationSchema, resolveChatPublicationSchema, resolveChatActionSchema, createChatIdentityLinkIntentSchema, confirmChatIdentityLinkSchema, replayChatDeliverySchema, chatInflightModeSchema, openwaNumberModeSchema, openwaSenderPolicyModeSchema, openwaReplyPolicySchema, openwaChatActivationSchema, openwaGatewayAdminToolLevelSchema, OPENWA_DEFAULT_COMMAND_PREFIX, OPENWA_DEFAULT_OWNER_NUMBER_PREFIX, OPENWA_CUSTOM_INSTRUCTIONS_MAX_LENGTH, OPENWA_CHAT_NOTE_MAX_LENGTH, openwaCommandPrefixSchema, openwaKeywordsSchema, openwaAbsenceSecondsSchema, openwaTriggerRulesInputSchema, openwaEndpointPolicySchema, openwaTriggerOverridesSchema, openwaChatSettingsSchema, openwaE164Schema, addOpenwaOwnerSchema, createOpenwaSenderRuleSchema, updateOpenwaChatSettingsSchema, updateOpenwaEndpointPolicySchema, resolveOpenwaApprovalSchema, listOpenwaApprovalsQuerySchema, chatPublicEndpointIdSchema;
13137
13255
  var init_chat_channels2 = __esm({
13138
13256
  "../packages/shared/src/validators/chat-channels.ts"() {
13139
13257
  "use strict";
@@ -13205,6 +13323,33 @@ var init_chat_channels2 = __esm({
13205
13323
  projectId: photonProjectIdSchema,
13206
13324
  projectSecret: z24.string().min(1).max(4096)
13207
13325
  }).strict();
13326
+ openwaBaseUrlSchema = z24.string().trim().min(1).max(2048).transform((value, ctx) => {
13327
+ let url;
13328
+ try {
13329
+ url = new URL(value);
13330
+ } catch {
13331
+ ctx.addIssue({ code: z24.ZodIssueCode.custom, message: "Enter the OpenWA gateway URL, for example http://localhost:2785" });
13332
+ return z24.NEVER;
13333
+ }
13334
+ if (url.protocol !== "http:" && url.protocol !== "https:" || url.username || url.password || url.pathname !== "/" && url.pathname !== "" || url.search || url.hash) {
13335
+ ctx.addIssue({ code: z24.ZodIssueCode.custom, message: "Use only the gateway origin: http(s)://host:port, without a path, query, or credentials" });
13336
+ return z24.NEVER;
13337
+ }
13338
+ return url.origin;
13339
+ });
13340
+ openwaSessionIdSchema = z24.string().trim().min(1).max(128).regex(/^[A-Za-z0-9_-]+$/);
13341
+ openwaApiKeyInputSchema = z24.string().trim().min(1).max(4096);
13342
+ inspectOpenwaGatewaySchema = z24.object({
13343
+ baseUrl: openwaBaseUrlSchema,
13344
+ apiKey: openwaApiKeyInputSchema,
13345
+ adminApiKey: openwaApiKeyInputSchema.optional()
13346
+ }).strict();
13347
+ openwaChannelConfigurationSchema = z24.object({
13348
+ baseUrl: openwaBaseUrlSchema,
13349
+ sessionId: openwaSessionIdSchema,
13350
+ numberMode: z24.enum(OPENWA_NUMBER_MODES).default("agent_number"),
13351
+ attestations: z24.object({ pacing: z24.boolean(), soleClient: z24.boolean() }).strict()
13352
+ }).strict();
13208
13353
  configureChatEndpointSchema = z24.object({
13209
13354
  action: z24.enum([
13210
13355
  "configure",
@@ -13215,9 +13360,10 @@ var init_chat_channels2 = __esm({
13215
13360
  "remove"
13216
13361
  ]),
13217
13362
  credentials: chatEndpointCredentialsSchema.optional(),
13218
- photon: photonChannelConfigurationSchema.optional()
13363
+ photon: photonChannelConfigurationSchema.optional(),
13364
+ openwa: openwaChannelConfigurationSchema.optional()
13219
13365
  }).strict().superRefine((value, ctx) => {
13220
- if ((value.credentials || value.photon) && value.action !== "configure" && value.action !== "reconnect") {
13366
+ if ((value.credentials || value.photon || value.openwa) && value.action !== "configure" && value.action !== "reconnect") {
13221
13367
  ctx.addIssue({
13222
13368
  code: z24.ZodIssueCode.custom,
13223
13369
  path: ["credentials"],
@@ -13264,6 +13410,111 @@ var init_chat_channels2 = __esm({
13264
13410
  token: z24.string().min(32).max(4096)
13265
13411
  }).strict();
13266
13412
  replayChatDeliverySchema = z24.object({}).strict();
13413
+ chatInflightModeSchema = z24.enum(CHAT_INFLIGHT_MODES);
13414
+ openwaNumberModeSchema = z24.enum(OPENWA_NUMBER_MODES);
13415
+ openwaSenderPolicyModeSchema = z24.enum(OPENWA_SENDER_POLICY_MODES);
13416
+ openwaReplyPolicySchema = z24.enum(OPENWA_REPLY_POLICIES);
13417
+ openwaChatActivationSchema = z24.enum(OPENWA_CHAT_ACTIVATIONS);
13418
+ openwaGatewayAdminToolLevelSchema = z24.enum(OPENWA_GATEWAY_ADMIN_TOOL_LEVELS);
13419
+ OPENWA_DEFAULT_COMMAND_PREFIX = "/ai";
13420
+ OPENWA_DEFAULT_OWNER_NUMBER_PREFIX = "\u{1F916} *Assistant:*";
13421
+ OPENWA_CUSTOM_INSTRUCTIONS_MAX_LENGTH = 8e3;
13422
+ OPENWA_CHAT_NOTE_MAX_LENGTH = 2e3;
13423
+ openwaCommandPrefixSchema = z24.string().trim().min(1).max(32).regex(/^\S+$/);
13424
+ openwaKeywordsSchema = z24.array(z24.string().trim().min(1).max(100)).max(50);
13425
+ openwaAbsenceSecondsSchema = z24.number().int().min(10).max(86400);
13426
+ openwaTriggerRulesInputSchema = z24.object({
13427
+ directMessage: z24.boolean().optional(),
13428
+ agentMentioned: z24.boolean().optional(),
13429
+ replyToAgent: z24.boolean().optional(),
13430
+ commandPrefix: z24.object({
13431
+ enabled: z24.boolean().optional(),
13432
+ prefix: openwaCommandPrefixSchema.optional()
13433
+ }).strict().optional(),
13434
+ selfChat: z24.boolean().optional(),
13435
+ ownerMentionedAbsent: z24.boolean().optional(),
13436
+ keywords: openwaKeywordsSchema.optional(),
13437
+ allMessages: z24.boolean().optional()
13438
+ }).strict();
13439
+ openwaEndpointPolicySchema = z24.object({
13440
+ numberMode: openwaNumberModeSchema.default("agent_number"),
13441
+ senderPolicyMode: openwaSenderPolicyModeSchema.default("allowlist"),
13442
+ replyPolicy: openwaReplyPolicySchema.default("allowed"),
13443
+ triggers: openwaTriggerRulesInputSchema.optional(),
13444
+ absenceSeconds: openwaAbsenceSecondsSchema.default(120),
13445
+ approvals: z24.object({
13446
+ createTask: z24.boolean().default(true),
13447
+ externalTools: z24.boolean().default(true),
13448
+ crossChatSend: z24.boolean().default(true),
13449
+ waAdmin: z24.boolean().default(true),
13450
+ gatewayAdmin: z24.boolean().default(true),
13451
+ reminderMinutes: z24.number().int().min(1).max(1440).default(30),
13452
+ maxReminders: z24.number().int().min(0).max(10).default(3),
13453
+ grantTtlHours: z24.number().int().min(1).max(720).default(24)
13454
+ }).strict().prefault({}),
13455
+ rotateAfterIdleHours: z24.number().int().min(1).max(720).default(24),
13456
+ progressNudgeSeconds: z24.number().int().min(0).max(3600).default(60),
13457
+ typingIndicator: z24.boolean().default(true),
13458
+ ownerNumberPrefix: z24.object({
13459
+ enabled: z24.boolean().default(true),
13460
+ text: z24.string().trim().min(1).max(64).default(OPENWA_DEFAULT_OWNER_NUMBER_PREFIX)
13461
+ }).strict().prefault({}),
13462
+ gatewayAdminTools: openwaGatewayAdminToolLevelSchema.default("off"),
13463
+ customInstructions: multilineTextSchema.pipe(z24.string().trim().max(OPENWA_CUSTOM_INSTRUCTIONS_MAX_LENGTH)).default(""),
13464
+ auditContentRetentionDays: z24.number().int().min(1).max(3650).default(90),
13465
+ attestations: z24.object({
13466
+ pacing: z24.boolean().default(false),
13467
+ soleClient: z24.boolean().default(false)
13468
+ }).strict().prefault({})
13469
+ }).strict().transform((value) => {
13470
+ const defaults3 = openwaDefaultTriggerRules(value.numberMode);
13471
+ const triggers = value.triggers ?? {};
13472
+ return {
13473
+ ...value,
13474
+ triggers: {
13475
+ directMessage: triggers.directMessage ?? defaults3.directMessage,
13476
+ agentMentioned: triggers.agentMentioned ?? defaults3.agentMentioned,
13477
+ replyToAgent: triggers.replyToAgent ?? defaults3.replyToAgent,
13478
+ commandPrefix: {
13479
+ enabled: triggers.commandPrefix?.enabled ?? defaults3.commandPrefix.enabled,
13480
+ prefix: triggers.commandPrefix?.prefix ?? defaults3.commandPrefix.prefix
13481
+ },
13482
+ selfChat: triggers.selfChat ?? defaults3.selfChat,
13483
+ ownerMentionedAbsent: triggers.ownerMentionedAbsent ?? defaults3.ownerMentionedAbsent,
13484
+ keywords: triggers.keywords ?? defaults3.keywords,
13485
+ allMessages: triggers.allMessages ?? defaults3.allMessages
13486
+ }
13487
+ };
13488
+ });
13489
+ openwaTriggerOverridesSchema = openwaTriggerRulesInputSchema;
13490
+ openwaChatSettingsSchema = z24.object({
13491
+ activation: openwaChatActivationSchema.default("auto"),
13492
+ triggers: openwaTriggerOverridesSchema.optional(),
13493
+ absenceSeconds: openwaAbsenceSecondsSchema.optional(),
13494
+ replyPolicy: openwaReplyPolicySchema.optional(),
13495
+ note: multilineTextSchema.pipe(z24.string().trim().max(OPENWA_CHAT_NOTE_MAX_LENGTH)).optional()
13496
+ }).strict();
13497
+ openwaE164Schema = z24.string().trim().regex(/^\+[1-9][0-9]{6,14}$/, "Use an E.164 number such as +6281234567890");
13498
+ addOpenwaOwnerSchema = z24.object({
13499
+ e164: openwaE164Schema,
13500
+ expiresInSeconds: z24.number().int().min(300).max(86400).default(1800)
13501
+ }).strict();
13502
+ createOpenwaSenderRuleSchema = z24.object({
13503
+ list: z24.enum(CHAT_SENDER_RULE_LISTS),
13504
+ e164: openwaE164Schema,
13505
+ label: z24.string().trim().min(1).max(120).optional()
13506
+ }).strict();
13507
+ updateOpenwaChatSettingsSchema = z24.object({
13508
+ chatId: z24.string().trim().regex(/^[A-Za-z0-9._-]{1,128}@(c\.us|g\.us|lid)$/),
13509
+ label: z24.string().trim().min(1).max(512).optional(),
13510
+ settings: openwaChatSettingsSchema
13511
+ }).strict();
13512
+ updateOpenwaEndpointPolicySchema = z24.looseObject({ inflightMode: chatInflightModeSchema.optional() });
13513
+ resolveOpenwaApprovalSchema = z24.object({
13514
+ decision: z24.enum(["approve", "reject"]),
13515
+ reason: z24.string().trim().min(1).max(2e3).optional()
13516
+ }).strict();
13517
+ listOpenwaApprovalsQuerySchema = z24.object({ status: z24.enum(CHAT_OWNER_APPROVAL_STATUSES).optional() }).strict();
13267
13518
  chatPublicEndpointIdSchema = z24.string().regex(/^[a-zA-Z0-9_-]{32,128}$/);
13268
13519
  }
13269
13520
  });
@@ -13431,7 +13682,7 @@ var init_smoke_lab = __esm({
13431
13682
  });
13432
13683
 
13433
13684
  // ../packages/shared/src/types/instance.ts
13434
- var DAILY_RETENTION_PRESETS, WEEKLY_RETENTION_PRESETS, MONTHLY_RETENTION_PRESETS, DEFAULT_BACKUP_RETENTION, DEFAULT_MESSAGE_DELIVERY;
13685
+ var DAILY_RETENTION_PRESETS, WEEKLY_RETENTION_PRESETS, MONTHLY_RETENTION_PRESETS, DEFAULT_BACKUP_RETENTION, SPEECH_TO_TEXT_DEFAULTS, DEFAULT_MESSAGE_DELIVERY;
13435
13686
  var init_instance = __esm({
13436
13687
  "../packages/shared/src/types/instance.ts"() {
13437
13688
  "use strict";
@@ -13443,6 +13694,14 @@ var init_instance = __esm({
13443
13694
  weeklyWeeks: 4,
13444
13695
  monthlyMonths: 1
13445
13696
  };
13697
+ SPEECH_TO_TEXT_DEFAULTS = {
13698
+ enabled: false,
13699
+ baseUrl: "",
13700
+ model: "",
13701
+ apiKeyEnvVar: "",
13702
+ maxAudioSeconds: 600,
13703
+ sttWaitSeconds: 15
13704
+ };
13446
13705
  DEFAULT_MESSAGE_DELIVERY = "steer";
13447
13706
  }
13448
13707
  });
@@ -13971,7 +14230,19 @@ function presetSchema(presets, label2) {
13971
14230
  { message: `${label2} must be one of: ${presets.join(", ")}` }
13972
14231
  );
13973
14232
  }
13974
- var messageDeliverySchema, backupRetentionPolicySchema, instanceGeneralSettingsSchema, patchInstanceGeneralSettingsSchema, instanceExperimentalSettingsSchema, patchInstanceExperimentalSettingsSchema, managedSettingMetadataSchema, instanceExperimentalSettingsWithManagedSchema, patchInstanceSettingsSchema, MAX_TASK_DRAIN_TTL_MS, startTaskDrainRequestSchema, instanceSettingsSchema;
14233
+ function isSpeechToTextBaseUrl(value) {
14234
+ if (value === "") return true;
14235
+ let url;
14236
+ try {
14237
+ url = new URL(value);
14238
+ } catch {
14239
+ return false;
14240
+ }
14241
+ if (url.protocol !== "http:" && url.protocol !== "https:") return false;
14242
+ if (url.username || url.password || url.search || url.hash) return false;
14243
+ return ["/", "/v1", "/v1/"].includes(url.pathname);
14244
+ }
14245
+ var messageDeliverySchema, backupRetentionPolicySchema, speechToTextSettingsSchema, instanceGeneralSettingsSchema, patchInstanceGeneralSettingsSchema, instanceExperimentalSettingsSchema, patchInstanceExperimentalSettingsSchema, managedSettingMetadataSchema, instanceExperimentalSettingsWithManagedSchema, patchInstanceSettingsSchema, MAX_TASK_DRAIN_TTL_MS, startTaskDrainRequestSchema, instanceSettingsSchema;
13975
14246
  var init_instance2 = __esm({
13976
14247
  "../packages/shared/src/validators/instance.ts"() {
13977
14248
  "use strict";
@@ -13985,6 +14256,20 @@ var init_instance2 = __esm({
13985
14256
  weeklyWeeks: presetSchema(WEEKLY_RETENTION_PRESETS, "weeklyWeeks").default(DEFAULT_BACKUP_RETENTION.weeklyWeeks),
13986
14257
  monthlyMonths: presetSchema(MONTHLY_RETENTION_PRESETS, "monthlyMonths").default(DEFAULT_BACKUP_RETENTION.monthlyMonths)
13987
14258
  });
14259
+ speechToTextSettingsSchema = z33.object({
14260
+ enabled: z33.boolean().default(SPEECH_TO_TEXT_DEFAULTS.enabled),
14261
+ baseUrl: z33.string().trim().max(2048).refine(isSpeechToTextBaseUrl, {
14262
+ message: "Speech-to-text base URL must be an http(s) origin or end at /v1, without credentials, query or fragment"
14263
+ }).default(SPEECH_TO_TEXT_DEFAULTS.baseUrl),
14264
+ model: z33.string().trim().max(200).default(SPEECH_TO_TEXT_DEFAULTS.model),
14265
+ apiKeyEnvVar: z33.string().trim().max(128).regex(/^(?:[A-Za-z_][A-Za-z0-9_]*)?$/, {
14266
+ message: "Speech-to-text API key must name a server environment variable, not hold the key itself"
14267
+ }).default(SPEECH_TO_TEXT_DEFAULTS.apiKeyEnvVar),
14268
+ maxAudioSeconds: z33.number().int().min(1).max(7200).default(SPEECH_TO_TEXT_DEFAULTS.maxAudioSeconds),
14269
+ sttWaitSeconds: z33.number().int().min(1).max(120).default(SPEECH_TO_TEXT_DEFAULTS.sttWaitSeconds)
14270
+ }).strict().refine((value) => !value.enabled || value.baseUrl !== "" && value.model !== "" && value.apiKeyEnvVar !== "", {
14271
+ message: "Speech-to-text needs a base URL, a model and an API key environment variable before it can be enabled"
14272
+ });
13988
14273
  instanceGeneralSettingsSchema = z33.object({
13989
14274
  censorUsernameInLogs: z33.boolean().default(false),
13990
14275
  keyboardShortcuts: z33.boolean().default(false),
@@ -13993,6 +14278,7 @@ var init_instance2 = __esm({
13993
14278
  ),
13994
14279
  backupRetention: backupRetentionPolicySchema.default(DEFAULT_BACKUP_RETENTION),
13995
14280
  defaultMessageDelivery: messageDeliverySchema.default(DEFAULT_MESSAGE_DELIVERY),
14281
+ speechToText: speechToTextSettingsSchema.default(SPEECH_TO_TEXT_DEFAULTS),
13996
14282
  // Execution policy. Absent/"any" = unrestricted; "kubernetes" forces the
13997
14283
  // Kubernetes sandbox provider and denies local/ssh execution (cloud_tenant).
13998
14284
  executionMode: z33.enum(["kubernetes", "any"]).optional()
@@ -17458,6 +17744,7 @@ var init_settings_visibility = __esm({
17458
17744
  "instance.general.keyboardShortcuts",
17459
17745
  "instance.general.backupRetention",
17460
17746
  "instance.general.feedbackDataSharingPreference",
17747
+ "instance.general.speechToText",
17461
17748
  "instance.general.signOut"
17462
17749
  ];
17463
17750
  HIDEABLE_WORKSPACE_SECTIONS = ["workspaces.isolation"];
@@ -18091,6 +18378,190 @@ var init_slack_tools = __esm({
18091
18378
  }
18092
18379
  });
18093
18380
 
18381
+ // ../packages/shared/src/openwa-tools.ts
18382
+ import { z as z69 } from "zod";
18383
+ function tool2(name, risk, description, shape, refine) {
18384
+ const base = z69.object(shape).strict();
18385
+ const schema = refine ? base.superRefine(refine) : base;
18386
+ const { $schema: _schema, ...inputSchema } = z69.toJSONSchema(schema, { io: "input" });
18387
+ return { name: `openwa_${name}`, risk, description, schema, inputSchema };
18388
+ }
18389
+ var OPENWA_SEND_KINDS, chat, e164, messageId, mention, triggerIds, operation, cursor2, GRANT_CATEGORIES, OPENWA_APPROVAL_MESSAGE_MAX_LENGTH, MEDIA_KINDS, senderRule, OPENWA_TOOLS, openwaToolCallSchema;
18390
+ var init_openwa_tools = __esm({
18391
+ "../packages/shared/src/openwa-tools.ts"() {
18392
+ "use strict";
18393
+ init_chat_channels2();
18394
+ OPENWA_SEND_KINDS = ["text", "image", "video", "audio", "voice", "document", "sticker", "location", "contact", "poll"];
18395
+ chat = z69.string().min(3).max(200).optional().describe("chatRef, group id or E.164 number; default: origin chat");
18396
+ e164 = z69.string().regex(/^\+?[1-9]\d{6,14}$/);
18397
+ messageId = z69.string().min(1).max(200);
18398
+ mention = z69.string().regex(/^(\+?[1-9]\d{6,14}|openwa:[A-Za-z0-9-]{1,64}:\d{5,25}@(c\.us|lid))$/);
18399
+ triggerIds = z69.array(z69.string().uuid()).min(1).max(50);
18400
+ operation = z69.string().min(1).max(100);
18401
+ cursor2 = z69.string().min(1).max(200).optional();
18402
+ GRANT_CATEGORIES = ["create_task", "external_tools", "cross_chat_send", "wa_admin", "gateway_admin", "reply_outside_allowlist", "reply"];
18403
+ OPENWA_APPROVAL_MESSAGE_MAX_LENGTH = 3500;
18404
+ MEDIA_KINDS = /* @__PURE__ */ new Set(["image", "video", "audio", "voice", "document", "sticker"]);
18405
+ senderRule = z69.object({ list: z69.enum(["allow", "deny"]), number: e164 }).strict();
18406
+ OPENWA_TOOLS = [
18407
+ tool2(
18408
+ "send",
18409
+ "write",
18410
+ "Send to a WhatsApp chat (default origin chat). text is markdown. Media comes from a task attachment. mentions: E.164 numbers or DM chatRefs; @tokens are added for you. Retry only with the same idempotencyKey; an uncertain send is reconciled, never resent.",
18411
+ {
18412
+ chat,
18413
+ kind: z69.enum(OPENWA_SEND_KINDS).optional(),
18414
+ text: z69.string().min(1).max(2e4).optional(),
18415
+ attachmentId: z69.string().uuid().optional(),
18416
+ location: z69.object({ lat: z69.number().min(-90).max(90), lng: z69.number().min(-180).max(180), name: z69.string().max(256).optional(), address: z69.string().max(1024).optional() }).strict().optional(),
18417
+ contact: z69.object({ name: z69.string().min(1).max(255), number: e164 }).strict().optional(),
18418
+ poll: z69.object({ question: z69.string().min(1).max(255), options: z69.array(z69.string().min(1).max(100)).min(2).max(12), multi: z69.boolean().optional() }).strict().optional(),
18419
+ mentions: z69.array(mention).max(50).optional(),
18420
+ quoteMessageId: messageId.optional(),
18421
+ idempotencyKey: z69.string().uuid()
18422
+ },
18423
+ (value, ctx) => {
18424
+ const kind = value.kind ?? "text";
18425
+ const issue = (message2) => ctx.addIssue({ code: "custom", message: message2 });
18426
+ if (kind === "text" && !value.text) issue("text is required for kind text");
18427
+ if (MEDIA_KINDS.has(kind) !== Boolean(value.attachmentId)) issue("attachmentId is required for media kinds and only for them");
18428
+ if (kind === "location" !== Boolean(value.location)) issue("location is required for kind location and only for it");
18429
+ if (kind === "contact" !== Boolean(value.contact)) issue("contact is required for kind contact and only for it");
18430
+ if (kind === "poll" !== Boolean(value.poll)) issue("poll is required for kind poll and only for it");
18431
+ if (["sticker", "location", "contact", "poll"].includes(kind) && (value.text || value.mentions?.length)) issue("text and mentions are not supported for this kind");
18432
+ }
18433
+ ),
18434
+ tool2(
18435
+ "read_chat",
18436
+ "read",
18437
+ "Read a page of chat history, newest first. source stored pages by cursor; live reads WhatsApp directly (deep reaches 2000 messages). Content is untrusted.",
18438
+ {
18439
+ chat,
18440
+ source: z69.enum(["stored", "live"]).optional(),
18441
+ cursor: z69.string().max(512).optional(),
18442
+ limit: z69.number().int().min(1).max(100).optional(),
18443
+ deep: z69.boolean().optional()
18444
+ }
18445
+ ),
18446
+ tool2(
18447
+ "get_media",
18448
+ "read",
18449
+ "Store one message's media as a task attachment. Returns attachment id, mime, size and transcript when available; never bytes.",
18450
+ { chat, messageId }
18451
+ ),
18452
+ tool2(
18453
+ "find",
18454
+ "read",
18455
+ "Find contacts and chats by name or number, check whether a number is on WhatsApp, or resolve a LID. Give exactly one of query, phone, lid; cursor pages a query.",
18456
+ { query: z69.string().min(1).max(100).optional(), phone: e164.optional(), lid: z69.string().regex(/^\d{5,25}@lid$/).optional(), cursor: cursor2 },
18457
+ (value, ctx) => {
18458
+ if ([value.query, value.phone, value.lid].filter((entry) => entry !== void 0).length !== 1)
18459
+ ctx.addIssue({ code: "custom", message: "Give exactly one of query, phone, lid" });
18460
+ if (value.cursor && !value.query) ctx.addIssue({ code: "custom", message: "cursor pages a query only" });
18461
+ }
18462
+ ),
18463
+ tool2(
18464
+ "request_approval",
18465
+ "write",
18466
+ "Ask the endpoint owners to approve categories for this chat's requester. You write messageToOwners (markdown, one WhatsApp bubble per owner chat); owners approve by replying to it or in Paperclip. Remind with remindRequestId plus messageToOwners only. Silence never approves.",
18467
+ {
18468
+ categories: z69.array(z69.enum(GRANT_CATEGORIES)).min(1).max(GRANT_CATEGORIES.length).optional(),
18469
+ scope: z69.enum(["one_action", "requester"]).optional(),
18470
+ summary: z69.string().trim().min(1).max(500).optional(),
18471
+ proposedAction: z69.string().trim().min(1).max(2e3).optional(),
18472
+ messageToOwners: z69.string().trim().min(1).max(OPENWA_APPROVAL_MESSAGE_MAX_LENGTH),
18473
+ remindRequestId: z69.string().uuid().optional(),
18474
+ idempotencyKey: z69.string().uuid()
18475
+ },
18476
+ (value, ctx) => {
18477
+ const issue = (message2) => ctx.addIssue({ code: "custom", message: message2 });
18478
+ if (value.remindRequestId) {
18479
+ if (value.categories || value.scope || value.summary || value.proposedAction) issue("A reminder takes only remindRequestId and messageToOwners");
18480
+ } else if (!value.categories || !value.summary || !value.proposedAction) issue("categories, summary and proposedAction are required");
18481
+ if (value.categories && new Set(value.categories).size !== value.categories.length) issue("categories must be unique");
18482
+ }
18483
+ ),
18484
+ tool2(
18485
+ "approval_resolve",
18486
+ "write",
18487
+ "Record the owner's decision on an approval request. Only in the run started by that owner's reply to the request bubble. clarify keeps it pending.",
18488
+ {
18489
+ requestId: z69.string().uuid(),
18490
+ decision: z69.enum(["approve", "reject", "clarify"]),
18491
+ conditions: z69.string().trim().min(1).max(2e3).optional()
18492
+ }
18493
+ ),
18494
+ tool2(
18495
+ "stay_silent",
18496
+ "write",
18497
+ "Deliberately leave triggers unanswered: marks the listed (default all visible pending) triggers silenced.",
18498
+ { triggerIds: triggerIds.optional() }
18499
+ ),
18500
+ tool2(
18501
+ "handoff",
18502
+ "write",
18503
+ "Hand owner triggers to a follow-up owner run carrying your note.",
18504
+ { triggerIds, note: z69.string().min(1).max(2e3) }
18505
+ ),
18506
+ tool2(
18507
+ "catalog",
18508
+ "read",
18509
+ "List OpenWA gateway operations with category and availability on this engine and key. Filter by category or text; page with cursor.",
18510
+ {
18511
+ category: z69.enum(["read", "write", "wa_admin", "gateway_admin", "paperclip"]).optional(),
18512
+ query: z69.string().min(1).max(100).optional(),
18513
+ cursor: cursor2
18514
+ }
18515
+ ),
18516
+ tool2(
18517
+ "endpoint_config",
18518
+ "write",
18519
+ "Owner-triggered runs only: change sender allow/deny lists, one chat's settings (default origin chat; null clears an override), approval toggles and reminders, or custom instructions. Empty call reads them. Credentials, number mode, owners and gateway admin level stay in Paperclip.",
18520
+ {
18521
+ senders: z69.object({
18522
+ add: z69.array(senderRule.extend({ label: z69.string().trim().min(1).max(120).optional() })).max(50).optional(),
18523
+ remove: z69.array(senderRule).max(50).optional()
18524
+ }).strict().optional(),
18525
+ chat,
18526
+ chatSettings: z69.object({
18527
+ activation: openwaChatActivationSchema.optional(),
18528
+ triggers: openwaTriggerOverridesSchema.nullable().optional(),
18529
+ absenceSeconds: z69.number().int().min(10).max(86400).nullable().optional(),
18530
+ replyPolicy: openwaReplyPolicySchema.nullable().optional(),
18531
+ note: z69.string().max(OPENWA_CHAT_NOTE_MAX_LENGTH).nullable().optional()
18532
+ }).strict().optional(),
18533
+ approvals: z69.object({
18534
+ createTask: z69.boolean().optional(),
18535
+ externalTools: z69.boolean().optional(),
18536
+ crossChatSend: z69.boolean().optional(),
18537
+ waAdmin: z69.boolean().optional(),
18538
+ gatewayAdmin: z69.boolean().optional(),
18539
+ reminderMinutes: z69.number().int().min(1).max(1440).optional(),
18540
+ maxReminders: z69.number().int().min(0).max(10).optional()
18541
+ }).strict().optional(),
18542
+ customInstructions: z69.string().max(OPENWA_CUSTOM_INSTRUCTIONS_MAX_LENGTH).optional()
18543
+ }
18544
+ ),
18545
+ tool2("describe", "read", "Argument schema and gates of one operation from openwa_catalog.", { operation }),
18546
+ tool2(
18547
+ "call",
18548
+ "write",
18549
+ "Run one catalog operation. args follow openwa_describe; the session is implied. Non-read operations need an idempotencyKey; retry only with the same key.",
18550
+ {
18551
+ operation,
18552
+ args: z69.record(z69.string(), z69.unknown()).optional(),
18553
+ idempotencyKey: z69.string().uuid().optional(),
18554
+ cursor: cursor2
18555
+ }
18556
+ )
18557
+ ];
18558
+ openwaToolCallSchema = z69.object({
18559
+ tool: z69.string().min(1).max(100),
18560
+ arguments: z69.record(z69.string(), z69.unknown())
18561
+ }).strict();
18562
+ }
18563
+ });
18564
+
18094
18565
  // ../packages/shared/src/index.ts
18095
18566
  var init_src = __esm({
18096
18567
  "../packages/shared/src/index.ts"() {
@@ -18190,6 +18661,7 @@ var init_src = __esm({
18190
18661
  init_remote_mcp_connectors();
18191
18662
  init_retired_composio();
18192
18663
  init_slack_tools();
18664
+ init_openwa_tools();
18193
18665
  }
18194
18666
  });
18195
18667
 
@@ -23734,13 +24206,15 @@ import {
23734
24206
  uniqueIndex as uniqueIndex42,
23735
24207
  uuid as uuid59
23736
24208
  } from "drizzle-orm/pg-core";
23737
- var chatEndpoints, chatEndpointResources, chatExternalPrincipals, chatIdentityLinks, chatConversations, chatDeliveries, chatPublications, chatMessageLinks, chatActions, chatAgentRoutes, chatEndpointLeases, chatSdkState;
24209
+ var chatEndpoints, chatEndpointResources, chatExternalPrincipals, chatIdentityLinks, chatConversations, chatDeliveries, chatPublications, chatMessageLinks, chatActions, chatAgentRoutes, chatEndpointLeases, chatSdkState, chatEndpointOwners, chatSenderRules, chatScheduledWakes, chatOwnerApprovalRequests, chatOutboundMessages, chatOwnerApprovalBubbles, chatOwnerGrants, chatAuditEntries;
23738
24210
  var init_chat_channels3 = __esm({
23739
24211
  "../packages/db/src/schema/chat_channels.ts"() {
23740
24212
  "use strict";
23741
24213
  init_agents();
23742
24214
  init_companies();
24215
+ init_heartbeat_runs();
23743
24216
  init_issue_comments();
24217
+ init_issue_thread_interactions();
23744
24218
  init_issues();
23745
24219
  init_tool_access3();
23746
24220
  chatEndpoints = pgTable60(
@@ -23784,6 +24258,9 @@ var init_chat_channels3 = __esm({
23784
24258
  proactiveDirectMessages: false
23785
24259
  }),
23786
24260
  setup: jsonb42("setup").$type().notNull().default({ step: "provider_setup" }),
24261
+ policy: jsonb42("policy").$type().notNull().default({}),
24262
+ policyRevision: integer24("policy_revision").notNull().default(0),
24263
+ inflightMode: text64("inflight_mode").$type().notNull().default("queue"),
23787
24264
  healthMessage: text64("health_message"),
23788
24265
  lastEventAt: timestamp61("last_event_at", { withTimezone: true }),
23789
24266
  lastPublicationAt: timestamp61("last_publication_at", { withTimezone: true }),
@@ -23799,7 +24276,15 @@ var init_chat_channels3 = __esm({
23799
24276
  check3("chat_endpoints_email_policy_check", sql18`${table.provider} <> 'agentmail' or (${table.publicationMode} = 'explicit' and ${table.externalExecutionPolicy} = 'agent')`),
23800
24277
  check3(
23801
24278
  "chat_endpoints_provider_check",
23802
- sql18`${table.provider} in ('slack', 'github', 'discord', 'microsoft-teams', 'telegram', 'agentmail', 'imessage-photon')`
24279
+ sql18`${table.provider} in ('slack', 'github', 'discord', 'microsoft-teams', 'telegram', 'agentmail', 'imessage-photon', 'openwa')`
24280
+ ),
24281
+ check3(
24282
+ "chat_endpoints_inflight_mode_check",
24283
+ sql18`${table.inflightMode} in ('steer', 'queue')`
24284
+ ),
24285
+ check3(
24286
+ "chat_endpoints_policy_revision_check",
24287
+ sql18`${table.policyRevision} >= 0`
23803
24288
  ),
23804
24289
  check3(
23805
24290
  "chat_endpoints_status_check",
@@ -23835,6 +24320,8 @@ var init_chat_channels3 = __esm({
23835
24320
  // where concurrent setup in two guilds could otherwise claim that bot for
23836
24321
  // two Paperclip agents after both application-level prechecks passed.
23837
24322
  uniqueIndex42("chat_endpoints_photon_number_uq").on(table.botExternalId).where(sql18`${table.provider} = 'imessage-photon' and ${table.status} <> 'archived' and ${table.botExternalId} is not null`),
24323
+ uniqueIndex42("chat_endpoints_openwa_account_uq").on(table.providerAccountId).where(sql18`${table.provider} = 'openwa' and ${table.status} <> 'archived' and ${table.providerAccountId} is not null`),
24324
+ uniqueIndex42("chat_endpoints_openwa_number_uq").on(table.botExternalId).where(sql18`${table.provider} = 'openwa' and ${table.status} <> 'archived' and ${table.botExternalId} is not null`),
23838
24325
  uniqueIndex42("chat_endpoints_live_discord_bot_external_uq").on(table.provider, table.botExternalId).where(
23839
24326
  sql18`${table.provider} = 'discord'
23840
24327
  and ${table.status} in ('verifying', 'active', 'paused', 'attention')
@@ -23885,6 +24372,7 @@ var init_chat_channels3 = __esm({
23885
24372
  availability: text64("availability").$type().notNull().default("available"),
23886
24373
  enabled: boolean9("enabled").notNull().default(false),
23887
24374
  metadata: jsonb42("metadata").$type().notNull().default({}),
24375
+ settings: jsonb42("settings").$type().notNull().default({}),
23888
24376
  createdAt: timestamp61("created_at", { withTimezone: true }).notNull().defaultNow(),
23889
24377
  updatedAt: timestamp61("updated_at", { withTimezone: true }).notNull().defaultNow()
23890
24378
  },
@@ -23926,6 +24414,7 @@ var init_chat_channels3 = __esm({
23926
24414
  handle: text64("handle"),
23927
24415
  avatarUrl: text64("avatar_url"),
23928
24416
  isBot: boolean9("is_bot").notNull().default(false),
24417
+ alternateExternalIds: text64("alternate_external_ids").array().notNull().default(sql18`'{}'::text[]`),
23929
24418
  lastSeenAt: timestamp61("last_seen_at", { withTimezone: true }),
23930
24419
  createdAt: timestamp61("created_at", { withTimezone: true }).notNull().defaultNow(),
23931
24420
  updatedAt: timestamp61("updated_at", { withTimezone: true }).notNull().defaultNow()
@@ -23933,7 +24422,7 @@ var init_chat_channels3 = __esm({
23933
24422
  (table) => [
23934
24423
  check3(
23935
24424
  "chat_external_principals_provider_check",
23936
- sql18`${table.provider} in ('slack', 'github', 'discord', 'microsoft-teams', 'telegram', 'agentmail', 'imessage-photon')`
24425
+ sql18`${table.provider} in ('slack', 'github', 'discord', 'microsoft-teams', 'telegram', 'agentmail', 'imessage-photon', 'openwa')`
23937
24426
  ),
23938
24427
  check3(
23939
24428
  "chat_external_principals_kind_check",
@@ -23981,6 +24470,7 @@ var init_chat_channels3 = __esm({
23981
24470
  table.endpointId,
23982
24471
  table.principalId
23983
24472
  ),
24473
+ unique7("chat_identity_links_company_id_uq").on(table.companyId, table.id),
23984
24474
  foreignKey2({
23985
24475
  columns: [table.companyId, table.endpointId],
23986
24476
  foreignColumns: [chatEndpoints.companyId, chatEndpoints.id],
@@ -24081,6 +24571,9 @@ var init_chat_channels3 = __esm({
24081
24571
  attempts: integer24("attempts").notNull().default(0),
24082
24572
  redactedError: text64("redacted_error"),
24083
24573
  nextAttemptAt: timestamp61("next_attempt_at", { withTimezone: true }),
24574
+ triggerClass: text64("trigger_class").$type(),
24575
+ principalRole: text64("principal_role").$type(),
24576
+ answerState: text64("answer_state").$type(),
24084
24577
  receivedAt: timestamp61("received_at", { withTimezone: true }).notNull().defaultNow(),
24085
24578
  processedAt: timestamp61("processed_at", { withTimezone: true }),
24086
24579
  createdAt: timestamp61("created_at", { withTimezone: true }).notNull().defaultNow(),
@@ -24091,7 +24584,20 @@ var init_chat_channels3 = __esm({
24091
24584
  "chat_deliveries_state_check",
24092
24585
  sql18`${table.state} in ('received', 'filtered', 'processing', 'processed', 'retry', 'failed')`
24093
24586
  ),
24587
+ check3(
24588
+ "chat_deliveries_trigger_class_check",
24589
+ sql18`${table.triggerClass} is null or ${table.triggerClass} in ('owner', 'other', 'grant')`
24590
+ ),
24591
+ check3(
24592
+ "chat_deliveries_principal_role_check",
24593
+ sql18`${table.principalRole} is null or ${table.principalRole} in ('owner', 'allowed', 'outside_allowlist', 'denylisted')`
24594
+ ),
24595
+ check3(
24596
+ "chat_deliveries_answer_state_check",
24597
+ sql18`${table.answerState} is null or ${table.answerState} in ('pending', 'answered', 'silenced', 'handed_off')`
24598
+ ),
24094
24599
  index53("chat_deliveries_work_idx").on(table.state, table.nextAttemptAt),
24600
+ index53("chat_deliveries_pending_answer_idx").on(table.endpointId, table.conversationId, table.receivedAt).where(sql18`${table.answerState} = 'pending'`),
24095
24601
  unique7("chat_deliveries_company_id_uq").on(table.companyId, table.id),
24096
24602
  uniqueIndex42("chat_deliveries_event_uq").on(
24097
24603
  table.endpointId,
@@ -24372,6 +24878,391 @@ var init_chat_channels3 = __esm({
24372
24878
  }).onDelete("cascade")
24373
24879
  ]
24374
24880
  );
24881
+ chatEndpointOwners = pgTable60(
24882
+ "chat_endpoint_owners",
24883
+ {
24884
+ id: uuid59("id").primaryKey().defaultRandom(),
24885
+ companyId: uuid59("company_id").notNull().references(() => companies.id, { onDelete: "cascade" }),
24886
+ endpointId: uuid59("endpoint_id").notNull(),
24887
+ identityLinkId: uuid59("identity_link_id").notNull(),
24888
+ addedByUserId: text64("added_by_user_id"),
24889
+ createdAt: timestamp61("created_at", { withTimezone: true }).notNull().defaultNow(),
24890
+ updatedAt: timestamp61("updated_at", { withTimezone: true }).notNull().defaultNow()
24891
+ },
24892
+ (table) => [
24893
+ uniqueIndex42("chat_endpoint_owners_link_uq").on(
24894
+ table.endpointId,
24895
+ table.identityLinkId
24896
+ ),
24897
+ unique7("chat_endpoint_owners_company_id_uq").on(table.companyId, table.id),
24898
+ foreignKey2({
24899
+ columns: [table.companyId, table.endpointId],
24900
+ foreignColumns: [chatEndpoints.companyId, chatEndpoints.id],
24901
+ name: "chat_endpoint_owners_company_endpoint_fk"
24902
+ }).onDelete("cascade"),
24903
+ foreignKey2({
24904
+ columns: [table.companyId, table.identityLinkId],
24905
+ foreignColumns: [chatIdentityLinks.companyId, chatIdentityLinks.id],
24906
+ name: "chat_endpoint_owners_company_identity_link_fk"
24907
+ }).onDelete("cascade")
24908
+ ]
24909
+ );
24910
+ chatSenderRules = pgTable60(
24911
+ "chat_sender_rules",
24912
+ {
24913
+ id: uuid59("id").primaryKey().defaultRandom(),
24914
+ companyId: uuid59("company_id").notNull().references(() => companies.id, { onDelete: "cascade" }),
24915
+ endpointId: uuid59("endpoint_id").notNull(),
24916
+ list: text64("list").$type().notNull(),
24917
+ e164: text64("e164").notNull(),
24918
+ label: text64("label"),
24919
+ createdByUserId: text64("created_by_user_id"),
24920
+ createdByPrincipalId: uuid59("created_by_principal_id").references(
24921
+ () => chatExternalPrincipals.id,
24922
+ { onDelete: "set null" }
24923
+ ),
24924
+ createdAt: timestamp61("created_at", { withTimezone: true }).notNull().defaultNow(),
24925
+ updatedAt: timestamp61("updated_at", { withTimezone: true }).notNull().defaultNow()
24926
+ },
24927
+ (table) => [
24928
+ check3("chat_sender_rules_list_check", sql18`${table.list} in ('allow', 'deny')`),
24929
+ check3("chat_sender_rules_e164_check", sql18`${table.e164} ~ '^[+][1-9][0-9]{6,14}$'`),
24930
+ uniqueIndex42("chat_sender_rules_entry_uq").on(
24931
+ table.endpointId,
24932
+ table.list,
24933
+ table.e164
24934
+ ),
24935
+ foreignKey2({
24936
+ columns: [table.companyId, table.endpointId],
24937
+ foreignColumns: [chatEndpoints.companyId, chatEndpoints.id],
24938
+ name: "chat_sender_rules_company_endpoint_fk"
24939
+ }).onDelete("cascade"),
24940
+ foreignKey2({
24941
+ columns: [table.companyId, table.createdByPrincipalId],
24942
+ foreignColumns: [chatExternalPrincipals.companyId, chatExternalPrincipals.id],
24943
+ name: "chat_sender_rules_company_principal_fk"
24944
+ })
24945
+ ]
24946
+ );
24947
+ chatScheduledWakes = pgTable60(
24948
+ "chat_scheduled_wakes",
24949
+ {
24950
+ id: uuid59("id").primaryKey().defaultRandom(),
24951
+ companyId: uuid59("company_id").notNull().references(() => companies.id, { onDelete: "cascade" }),
24952
+ endpointId: uuid59("endpoint_id").notNull(),
24953
+ chatKey: text64("chat_key").notNull(),
24954
+ kind: text64("kind").$type().notNull(),
24955
+ fireAt: timestamp61("fire_at", { withTimezone: true }).notNull(),
24956
+ state: text64("state").$type().notNull().default("pending"),
24957
+ relatedId: uuid59("related_id"),
24958
+ payload: jsonb42("payload").$type().notNull().default({}),
24959
+ createdAt: timestamp61("created_at", { withTimezone: true }).notNull().defaultNow(),
24960
+ updatedAt: timestamp61("updated_at", { withTimezone: true }).notNull().defaultNow()
24961
+ },
24962
+ (table) => [
24963
+ check3(
24964
+ "chat_scheduled_wakes_kind_check",
24965
+ sql18`${table.kind} in ('owner_absent', 'approval_reminder')`
24966
+ ),
24967
+ check3(
24968
+ "chat_scheduled_wakes_state_check",
24969
+ sql18`${table.state} in ('pending', 'fired', 'cancelled')`
24970
+ ),
24971
+ index53("chat_scheduled_wakes_pending_fire_idx").on(table.fireAt).where(sql18`${table.state} = 'pending'`),
24972
+ uniqueIndex42("chat_scheduled_wakes_pending_absent_uq").on(table.endpointId, table.chatKey).where(sql18`${table.kind} = 'owner_absent' and ${table.state} = 'pending'`),
24973
+ foreignKey2({
24974
+ columns: [table.companyId, table.endpointId],
24975
+ foreignColumns: [chatEndpoints.companyId, chatEndpoints.id],
24976
+ name: "chat_scheduled_wakes_company_endpoint_fk"
24977
+ }).onDelete("cascade")
24978
+ ]
24979
+ );
24980
+ chatOwnerApprovalRequests = pgTable60(
24981
+ "chat_owner_approval_requests",
24982
+ {
24983
+ id: uuid59("id").primaryKey().defaultRandom(),
24984
+ companyId: uuid59("company_id").notNull().references(() => companies.id, { onDelete: "cascade" }),
24985
+ endpointId: uuid59("endpoint_id").notNull(),
24986
+ originChatKey: text64("origin_chat_key").notNull(),
24987
+ originConversationId: uuid59("origin_conversation_id").references(
24988
+ () => chatConversations.id,
24989
+ { onDelete: "set null" }
24990
+ ),
24991
+ interactionId: uuid59("interaction_id").references(
24992
+ () => issueThreadInteractions.id,
24993
+ { onDelete: "set null" }
24994
+ ),
24995
+ requestedByPrincipalId: uuid59("requested_by_principal_id").references(
24996
+ () => chatExternalPrincipals.id,
24997
+ { onDelete: "set null" }
24998
+ ),
24999
+ requestedInRunId: uuid59("requested_in_run_id").references(
25000
+ () => heartbeatRuns.id,
25001
+ { onDelete: "set null" }
25002
+ ),
25003
+ categories: text64("categories").array().$type().notNull(),
25004
+ scope: text64("scope").$type().notNull(),
25005
+ summary: text64("summary").notNull(),
25006
+ proposedAction: text64("proposed_action").notNull(),
25007
+ status: text64("status").$type().notNull().default("pending"),
25008
+ reminderCount: integer24("reminder_count").notNull().default(0),
25009
+ resolvedVia: text64("resolved_via").$type(),
25010
+ resolvedByUserId: text64("resolved_by_user_id"),
25011
+ ownerText: text64("owner_text"),
25012
+ agentConditions: text64("agent_conditions"),
25013
+ resolvedAt: timestamp61("resolved_at", { withTimezone: true }),
25014
+ createdAt: timestamp61("created_at", { withTimezone: true }).notNull().defaultNow(),
25015
+ updatedAt: timestamp61("updated_at", { withTimezone: true }).notNull().defaultNow()
25016
+ },
25017
+ (table) => [
25018
+ check3(
25019
+ "chat_owner_approval_requests_categories_check",
25020
+ sql18`cardinality(${table.categories}) > 0 and ${table.categories} <@ array['create_task', 'external_tools', 'cross_chat_send', 'wa_admin', 'gateway_admin', 'reply_outside_allowlist', 'reply']::text[]`
25021
+ ),
25022
+ check3(
25023
+ "chat_owner_approval_requests_scope_check",
25024
+ sql18`${table.scope} in ('one_action', 'requester')`
25025
+ ),
25026
+ check3(
25027
+ "chat_owner_approval_requests_status_check",
25028
+ sql18`${table.status} in ('pending', 'approved', 'rejected', 'cancelled')`
25029
+ ),
25030
+ check3(
25031
+ "chat_owner_approval_requests_resolved_via_check",
25032
+ sql18`${table.resolvedVia} is null or ${table.resolvedVia} in ('whatsapp', 'paperclip')`
25033
+ ),
25034
+ check3(
25035
+ "chat_owner_approval_requests_reminder_count_check",
25036
+ sql18`${table.reminderCount} >= 0`
25037
+ ),
25038
+ index53("chat_owner_approval_requests_status_idx").on(
25039
+ table.endpointId,
25040
+ table.status
25041
+ ),
25042
+ unique7("chat_owner_approval_requests_company_id_uq").on(
25043
+ table.companyId,
25044
+ table.id
25045
+ ),
25046
+ foreignKey2({
25047
+ columns: [table.companyId, table.endpointId],
25048
+ foreignColumns: [chatEndpoints.companyId, chatEndpoints.id],
25049
+ name: "chat_owner_approval_requests_company_endpoint_fk"
25050
+ }).onDelete("cascade"),
25051
+ foreignKey2({
25052
+ columns: [table.companyId, table.originConversationId],
25053
+ foreignColumns: [chatConversations.companyId, chatConversations.id],
25054
+ name: "chat_owner_approval_requests_company_conversation_fk"
25055
+ }),
25056
+ foreignKey2({
25057
+ columns: [table.companyId, table.requestedByPrincipalId],
25058
+ foreignColumns: [chatExternalPrincipals.companyId, chatExternalPrincipals.id],
25059
+ name: "chat_owner_approval_requests_company_principal_fk"
25060
+ })
25061
+ ]
25062
+ );
25063
+ chatOutboundMessages = pgTable60(
25064
+ "chat_outbound_messages",
25065
+ {
25066
+ id: uuid59("id").primaryKey().defaultRandom(),
25067
+ companyId: uuid59("company_id").notNull().references(() => companies.id, { onDelete: "cascade" }),
25068
+ endpointId: uuid59("endpoint_id").notNull(),
25069
+ chatKey: text64("chat_key").notNull(),
25070
+ source: text64("source").$type().notNull(),
25071
+ runId: uuid59("run_id").references(() => heartbeatRuns.id, {
25072
+ onDelete: "set null"
25073
+ }),
25074
+ providerMessageId: text64("provider_message_id"),
25075
+ state: text64("state").$type().notNull().default("pending"),
25076
+ bodyHash: text64("body_hash").notNull(),
25077
+ clientNonce: text64("client_nonce").notNull(),
25078
+ sentAt: timestamp61("sent_at", { withTimezone: true }),
25079
+ createdAt: timestamp61("created_at", { withTimezone: true }).notNull().defaultNow(),
25080
+ updatedAt: timestamp61("updated_at", { withTimezone: true }).notNull().defaultNow()
25081
+ },
25082
+ (table) => [
25083
+ check3(
25084
+ "chat_outbound_messages_source_check",
25085
+ sql18`${table.source} in ('tool', 'publication', 'approval')`
25086
+ ),
25087
+ check3(
25088
+ "chat_outbound_messages_state_check",
25089
+ sql18`${table.state} in ('pending', 'sent', 'uncertain', 'failed')`
25090
+ ),
25091
+ uniqueIndex42("chat_outbound_messages_provider_message_uq").on(table.endpointId, table.providerMessageId).where(sql18`${table.providerMessageId} is not null`),
25092
+ index53("chat_outbound_messages_chat_state_idx").on(
25093
+ table.endpointId,
25094
+ table.chatKey,
25095
+ table.state
25096
+ ),
25097
+ index53("chat_outbound_messages_sent_at_idx").on(
25098
+ table.endpointId,
25099
+ table.sentAt
25100
+ ),
25101
+ unique7("chat_outbound_messages_company_id_uq").on(table.companyId, table.id),
25102
+ foreignKey2({
25103
+ columns: [table.companyId, table.endpointId],
25104
+ foreignColumns: [chatEndpoints.companyId, chatEndpoints.id],
25105
+ name: "chat_outbound_messages_company_endpoint_fk"
25106
+ }).onDelete("cascade")
25107
+ ]
25108
+ );
25109
+ chatOwnerApprovalBubbles = pgTable60(
25110
+ "chat_owner_approval_bubbles",
25111
+ {
25112
+ id: uuid59("id").primaryKey().defaultRandom(),
25113
+ companyId: uuid59("company_id").notNull().references(() => companies.id, { onDelete: "cascade" }),
25114
+ endpointId: uuid59("endpoint_id").notNull(),
25115
+ requestId: uuid59("request_id").notNull(),
25116
+ ownerId: uuid59("owner_id").notNull(),
25117
+ outboundMessageId: uuid59("outbound_message_id").notNull(),
25118
+ createdAt: timestamp61("created_at", { withTimezone: true }).notNull().defaultNow(),
25119
+ updatedAt: timestamp61("updated_at", { withTimezone: true }).notNull().defaultNow()
25120
+ },
25121
+ (table) => [
25122
+ uniqueIndex42("chat_owner_approval_bubbles_outbound_uq").on(
25123
+ table.endpointId,
25124
+ table.outboundMessageId
25125
+ ),
25126
+ index53("chat_owner_approval_bubbles_request_idx").on(table.requestId),
25127
+ foreignKey2({
25128
+ columns: [table.companyId, table.endpointId],
25129
+ foreignColumns: [chatEndpoints.companyId, chatEndpoints.id],
25130
+ name: "chat_owner_approval_bubbles_company_endpoint_fk"
25131
+ }).onDelete("cascade"),
25132
+ foreignKey2({
25133
+ columns: [table.companyId, table.requestId],
25134
+ foreignColumns: [chatOwnerApprovalRequests.companyId, chatOwnerApprovalRequests.id],
25135
+ name: "chat_owner_approval_bubbles_company_request_fk"
25136
+ }).onDelete("cascade"),
25137
+ foreignKey2({
25138
+ columns: [table.companyId, table.ownerId],
25139
+ foreignColumns: [chatEndpointOwners.companyId, chatEndpointOwners.id],
25140
+ name: "chat_owner_approval_bubbles_company_owner_fk"
25141
+ }).onDelete("cascade"),
25142
+ foreignKey2({
25143
+ columns: [table.companyId, table.outboundMessageId],
25144
+ foreignColumns: [chatOutboundMessages.companyId, chatOutboundMessages.id],
25145
+ name: "chat_owner_approval_bubbles_company_outbound_fk"
25146
+ }).onDelete("cascade")
25147
+ ]
25148
+ );
25149
+ chatOwnerGrants = pgTable60(
25150
+ "chat_owner_grants",
25151
+ {
25152
+ id: uuid59("id").primaryKey().defaultRandom(),
25153
+ companyId: uuid59("company_id").notNull().references(() => companies.id, { onDelete: "cascade" }),
25154
+ endpointId: uuid59("endpoint_id").notNull(),
25155
+ requestId: uuid59("request_id").notNull(),
25156
+ originChatKey: text64("origin_chat_key").notNull(),
25157
+ requesterPrincipalId: uuid59("requester_principal_id").references(
25158
+ () => chatExternalPrincipals.id,
25159
+ { onDelete: "set null" }
25160
+ ),
25161
+ category: text64("category").$type().notNull(),
25162
+ scope: text64("scope").$type().notNull(),
25163
+ status: text64("status").$type().notNull().default("live"),
25164
+ approvedByUserId: text64("approved_by_user_id"),
25165
+ approvedVia: text64("approved_via").$type().notNull(),
25166
+ expiresAt: timestamp61("expires_at", { withTimezone: true }).notNull(),
25167
+ consumedAt: timestamp61("consumed_at", { withTimezone: true }),
25168
+ consumedByRunId: uuid59("consumed_by_run_id").references(
25169
+ () => heartbeatRuns.id,
25170
+ { onDelete: "set null" }
25171
+ ),
25172
+ createdAt: timestamp61("created_at", { withTimezone: true }).notNull().defaultNow(),
25173
+ updatedAt: timestamp61("updated_at", { withTimezone: true }).notNull().defaultNow()
25174
+ },
25175
+ (table) => [
25176
+ check3(
25177
+ "chat_owner_grants_category_check",
25178
+ sql18`${table.category} in ('create_task', 'external_tools', 'cross_chat_send', 'wa_admin', 'gateway_admin', 'reply_outside_allowlist', 'reply')`
25179
+ ),
25180
+ check3(
25181
+ "chat_owner_grants_scope_check",
25182
+ sql18`${table.scope} in ('one_action', 'requester')`
25183
+ ),
25184
+ check3(
25185
+ "chat_owner_grants_status_check",
25186
+ sql18`${table.status} in ('live', 'consumed', 'revoked', 'expired')`
25187
+ ),
25188
+ check3(
25189
+ "chat_owner_grants_approved_via_check",
25190
+ sql18`${table.approvedVia} in ('whatsapp', 'paperclip')`
25191
+ ),
25192
+ index53("chat_owner_grants_lookup_idx").on(
25193
+ table.endpointId,
25194
+ table.originChatKey,
25195
+ table.requesterPrincipalId,
25196
+ table.status
25197
+ ),
25198
+ index53("chat_owner_grants_request_idx").on(table.requestId),
25199
+ foreignKey2({
25200
+ columns: [table.companyId, table.endpointId],
25201
+ foreignColumns: [chatEndpoints.companyId, chatEndpoints.id],
25202
+ name: "chat_owner_grants_company_endpoint_fk"
25203
+ }).onDelete("cascade"),
25204
+ foreignKey2({
25205
+ columns: [table.companyId, table.requestId],
25206
+ foreignColumns: [chatOwnerApprovalRequests.companyId, chatOwnerApprovalRequests.id],
25207
+ name: "chat_owner_grants_company_request_fk"
25208
+ }).onDelete("cascade"),
25209
+ foreignKey2({
25210
+ columns: [table.companyId, table.requesterPrincipalId],
25211
+ foreignColumns: [chatExternalPrincipals.companyId, chatExternalPrincipals.id],
25212
+ name: "chat_owner_grants_company_principal_fk"
25213
+ })
25214
+ ]
25215
+ );
25216
+ chatAuditEntries = pgTable60(
25217
+ "chat_audit_entries",
25218
+ {
25219
+ id: uuid59("id").primaryKey().defaultRandom(),
25220
+ companyId: uuid59("company_id").notNull().references(() => companies.id, { onDelete: "cascade" }),
25221
+ endpointId: uuid59("endpoint_id").notNull(),
25222
+ conversationId: uuid59("conversation_id").references(
25223
+ () => chatConversations.id,
25224
+ { onDelete: "set null" }
25225
+ ),
25226
+ chatKey: text64("chat_key"),
25227
+ kind: text64("kind").$type().notNull(),
25228
+ actorKind: text64("actor_kind").$type().notNull(),
25229
+ actorRef: text64("actor_ref"),
25230
+ runId: uuid59("run_id").references(() => heartbeatRuns.id, {
25231
+ onDelete: "set null"
25232
+ }),
25233
+ metadata: jsonb42("metadata").$type().notNull().default({}),
25234
+ content: jsonb42("content").$type(),
25235
+ contentPurgeAt: timestamp61("content_purge_at", { withTimezone: true }),
25236
+ occurredAt: timestamp61("occurred_at", { withTimezone: true }).notNull().defaultNow(),
25237
+ createdAt: timestamp61("created_at", { withTimezone: true }).notNull().defaultNow(),
25238
+ updatedAt: timestamp61("updated_at", { withTimezone: true }).notNull().defaultNow()
25239
+ },
25240
+ (table) => [
25241
+ check3(
25242
+ "chat_audit_entries_kind_check",
25243
+ sql18`${table.kind} in ('trigger_admitted', 'trigger_filtered', 'message_sent', 'publication_suppressed', 'tool_called', 'approval_requested', 'approval_reminded', 'approval_resolved', 'approval_cancelled', 'config_changed', 'group_added', 'group_left', 'session_health')`
25244
+ ),
25245
+ check3(
25246
+ "chat_audit_entries_actor_kind_check",
25247
+ sql18`${table.actorKind} in ('user', 'agent', 'chat_principal', 'system')`
25248
+ ),
25249
+ index53("chat_audit_entries_endpoint_occurred_idx").on(
25250
+ table.endpointId,
25251
+ table.occurredAt.desc()
25252
+ ),
25253
+ index53("chat_audit_entries_content_purge_idx").on(table.contentPurgeAt).where(sql18`${table.content} is not null`),
25254
+ foreignKey2({
25255
+ columns: [table.companyId, table.endpointId],
25256
+ foreignColumns: [chatEndpoints.companyId, chatEndpoints.id],
25257
+ name: "chat_audit_entries_company_endpoint_fk"
25258
+ }).onDelete("cascade"),
25259
+ foreignKey2({
25260
+ columns: [table.companyId, table.conversationId],
25261
+ foreignColumns: [chatConversations.companyId, chatConversations.id],
25262
+ name: "chat_audit_entries_company_conversation_fk"
25263
+ })
25264
+ ]
25265
+ );
24375
25266
  }
24376
25267
  });
24377
25268
 
@@ -29452,10 +30343,12 @@ __export(schema_exports, {
29452
30343
  cases: () => cases,
29453
30344
  chatActions: () => chatActions,
29454
30345
  chatAgentRoutes: () => chatAgentRoutes,
30346
+ chatAuditEntries: () => chatAuditEntries,
29455
30347
  chatConversations: () => chatConversations,
29456
30348
  chatDeliveries: () => chatDeliveries,
29457
30349
  chatDiscordCommandOwners: () => chatDiscordCommandOwners,
29458
30350
  chatEndpointLeases: () => chatEndpointLeases,
30351
+ chatEndpointOwners: () => chatEndpointOwners,
29459
30352
  chatEndpointResources: () => chatEndpointResources,
29460
30353
  chatEndpoints: () => chatEndpoints,
29461
30354
  chatExternalPrincipals: () => chatExternalPrincipals,
@@ -29464,8 +30357,14 @@ __export(schema_exports, {
29464
30357
  chatGitHubReviews: () => chatGitHubReviews,
29465
30358
  chatIdentityLinks: () => chatIdentityLinks,
29466
30359
  chatMessageLinks: () => chatMessageLinks,
30360
+ chatOutboundMessages: () => chatOutboundMessages,
30361
+ chatOwnerApprovalBubbles: () => chatOwnerApprovalBubbles,
30362
+ chatOwnerApprovalRequests: () => chatOwnerApprovalRequests,
30363
+ chatOwnerGrants: () => chatOwnerGrants,
29467
30364
  chatPublications: () => chatPublications,
30365
+ chatScheduledWakes: () => chatScheduledWakes,
29468
30366
  chatSdkState: () => chatSdkState,
30367
+ chatSenderRules: () => chatSenderRules,
29469
30368
  chatTeamsFileTransfers: () => chatTeamsFileTransfers,
29470
30369
  chatTelegramDraftIds: () => chatTelegramDraftIds,
29471
30370
  cliAuthChallenges: () => cliAuthChallenges,
@@ -37443,10 +38342,12 @@ __export(src_exports, {
37443
38342
  cases: () => cases,
37444
38343
  chatActions: () => chatActions,
37445
38344
  chatAgentRoutes: () => chatAgentRoutes,
38345
+ chatAuditEntries: () => chatAuditEntries,
37446
38346
  chatConversations: () => chatConversations,
37447
38347
  chatDeliveries: () => chatDeliveries,
37448
38348
  chatDiscordCommandOwners: () => chatDiscordCommandOwners,
37449
38349
  chatEndpointLeases: () => chatEndpointLeases,
38350
+ chatEndpointOwners: () => chatEndpointOwners,
37450
38351
  chatEndpointResources: () => chatEndpointResources,
37451
38352
  chatEndpoints: () => chatEndpoints,
37452
38353
  chatExternalPrincipals: () => chatExternalPrincipals,
@@ -37455,8 +38356,14 @@ __export(src_exports, {
37455
38356
  chatGitHubReviews: () => chatGitHubReviews,
37456
38357
  chatIdentityLinks: () => chatIdentityLinks,
37457
38358
  chatMessageLinks: () => chatMessageLinks,
38359
+ chatOutboundMessages: () => chatOutboundMessages,
38360
+ chatOwnerApprovalBubbles: () => chatOwnerApprovalBubbles,
38361
+ chatOwnerApprovalRequests: () => chatOwnerApprovalRequests,
38362
+ chatOwnerGrants: () => chatOwnerGrants,
37458
38363
  chatPublications: () => chatPublications,
38364
+ chatScheduledWakes: () => chatScheduledWakes,
37459
38365
  chatSdkState: () => chatSdkState,
38366
+ chatSenderRules: () => chatSenderRules,
37460
38367
  chatTeamsFileTransfers: () => chatTeamsFileTransfers,
37461
38368
  chatTelegramDraftIds: () => chatTelegramDraftIds,
37462
38369
  cliAuthChallenges: () => cliAuthChallenges,
@@ -41416,10 +42323,10 @@ function detectInstallMode(executablePath = process.argv[1] ?? "", paths = resol
41416
42323
  const normalized = resolved.split(path26.sep).join("/");
41417
42324
  if (normalized.includes("/.npm/_npx/") || normalized.includes("/node_modules/.cache/npx/")) return "npx";
41418
42325
  if (normalized.includes("/node_modules/@tickernelz/paperclip-pro/")) return "global-npm";
41419
- let cursor2 = path26.dirname(resolved);
41420
- while (cursor2 !== path26.dirname(cursor2)) {
41421
- if (fs22.existsSync(path26.join(cursor2, ".git"))) return "source";
41422
- cursor2 = path26.dirname(cursor2);
42326
+ let cursor3 = path26.dirname(resolved);
42327
+ while (cursor3 !== path26.dirname(cursor3)) {
42328
+ if (fs22.existsSync(path26.join(cursor3, ".git"))) return "source";
42329
+ cursor3 = path26.dirname(cursor3);
41423
42330
  }
41424
42331
  return "unknown";
41425
42332
  }
@@ -49051,7 +49958,7 @@ function printToolCallEventTopLevel(parsed) {
49051
49958
  console.log(pc20.yellow(`tool_call: ${toolName}${subtype ? ` (${subtype})` : ""}`));
49052
49959
  }
49053
49960
  function printLegacyToolEvent(part) {
49054
- const tool2 = asString4(part.tool, "tool");
49961
+ const tool3 = asString4(part.tool, "tool");
49055
49962
  const callId = asString4(part.callID, asString4(part.id, ""));
49056
49963
  const state = asRecord2(part.state);
49057
49964
  const status = asString4(state?.status);
@@ -49060,7 +49967,7 @@ function printLegacyToolEvent(part) {
49060
49967
  const metadata = asRecord2(state?.metadata);
49061
49968
  const exit = asNumber3(metadata?.exit, NaN);
49062
49969
  const isError = status === "failed" || status === "error" || status === "cancelled" || Number.isFinite(exit) && exit !== 0;
49063
- console.log(pc20.yellow(`tool_call: ${tool2}${callId ? ` (${callId})` : ""}`));
49970
+ console.log(pc20.yellow(`tool_call: ${tool3}${callId ? ` (${callId})` : ""}`));
49064
49971
  if (input2 !== void 0) {
49065
49972
  try {
49066
49973
  console.log(pc20.gray(JSON.stringify(input2, null, 2)));
@@ -49804,13 +50711,13 @@ function printOpenCodeStreamEvent(raw, _debug) {
49804
50711
  }
49805
50712
  if (type === "tool_use") {
49806
50713
  const part = asRecord7(parsed.part);
49807
- const tool2 = asString9(part?.tool, "tool");
50714
+ const tool3 = asString9(part?.tool, "tool");
49808
50715
  const callID = asString9(part?.callID);
49809
50716
  const state = asRecord7(part?.state);
49810
50717
  const status = asString9(state?.status);
49811
50718
  const isError = status === "error";
49812
50719
  const metadata = asRecord7(state?.metadata);
49813
- console.log(pc26.yellow(`tool_call: ${tool2}${callID ? ` (${callID})` : ""}`));
50720
+ console.log(pc26.yellow(`tool_call: ${tool3}${callID ? ` (${callID})` : ""}`));
49814
50721
  if (status) {
49815
50722
  const metaParts = [`status=${status}`];
49816
50723
  if (metadata) {
@@ -50023,9 +50930,9 @@ function balancedObjectEnd(line, start) {
50023
50930
  function salvageRedactedEvents(line) {
50024
50931
  if (!line.includes(REDACTED_LOG_MARKER)) return [];
50025
50932
  const events = [];
50026
- let cursor2 = line.indexOf(REDACTED_LOG_MARKER);
50027
- while (cursor2 >= 0 && events.length < SALVAGE_MAX_EVENTS) {
50028
- const start = line.indexOf(SALVAGE_EVENT_PREFIX, cursor2 + REDACTED_LOG_MARKER.length);
50933
+ let cursor3 = line.indexOf(REDACTED_LOG_MARKER);
50934
+ while (cursor3 >= 0 && events.length < SALVAGE_MAX_EVENTS) {
50935
+ const start = line.indexOf(SALVAGE_EVENT_PREFIX, cursor3 + REDACTED_LOG_MARKER.length);
50029
50936
  if (start < 0) break;
50030
50937
  const end = balancedObjectEnd(line, start);
50031
50938
  if (end > start) {
@@ -50036,7 +50943,7 @@ function salvageRedactedEvents(line) {
50036
50943
  break;
50037
50944
  }
50038
50945
  }
50039
- cursor2 = line.indexOf(REDACTED_LOG_MARKER, start);
50946
+ cursor3 = line.indexOf(REDACTED_LOG_MARKER, start);
50040
50947
  }
50041
50948
  return events;
50042
50949
  }
@@ -51729,7 +52636,7 @@ import * as p21 from "@clack/prompts";
51729
52636
  import pc34 from "picocolors";
51730
52637
 
51731
52638
  // ../packages/shared/src/company-import-transfer.ts
51732
- import { z as z69 } from "zod";
52639
+ import { z as z70 } from "zod";
51733
52640
  var COMPANY_IMPORT_TRANSFERS_ROUTE_PATH = "/import/transfers";
51734
52641
  var COMPANY_IMPORT_TRANSFERS_API_PATH = `/api/companies${COMPANY_IMPORT_TRANSFERS_ROUTE_PATH}`;
51735
52642
  function companyImportTransferPath(transferId) {
@@ -51746,16 +52653,16 @@ function companyImportTransferApplyPath(transferId) {
51746
52653
  }
51747
52654
  var COMPANY_IMPORT_TRANSFER_MAX_PARTS = 4096;
51748
52655
  var SHA256_HEX_RE = /^[0-9a-f]{64}$/;
51749
- var companyImportTransferDeclaredPartSchema = z69.object({
51750
- index: z69.number().int().min(0),
51751
- byteSize: z69.number().int().min(1),
51752
- sha256: z69.string().regex(SHA256_HEX_RE, "sha256 must be 64 lowercase hex characters").describe("sha256 of this part, 64 lowercase hex characters")
52656
+ var companyImportTransferDeclaredPartSchema = z70.object({
52657
+ index: z70.number().int().min(0),
52658
+ byteSize: z70.number().int().min(1),
52659
+ sha256: z70.string().regex(SHA256_HEX_RE, "sha256 must be 64 lowercase hex characters").describe("sha256 of this part, 64 lowercase hex characters")
51753
52660
  });
51754
- var companyImportTransferDeclarationSchema = z69.object({
51755
- totalBytes: z69.number().int().min(1),
51756
- zipSha256: z69.string().regex(SHA256_HEX_RE, "sha256 must be 64 lowercase hex characters").describe("sha256 of the whole .zip, 64 lowercase hex characters"),
51757
- partSizeBytes: z69.number().int().min(1),
51758
- parts: z69.array(companyImportTransferDeclaredPartSchema).min(1).max(COMPANY_IMPORT_TRANSFER_MAX_PARTS)
52661
+ var companyImportTransferDeclarationSchema = z70.object({
52662
+ totalBytes: z70.number().int().min(1),
52663
+ zipSha256: z70.string().regex(SHA256_HEX_RE, "sha256 must be 64 lowercase hex characters").describe("sha256 of the whole .zip, 64 lowercase hex characters"),
52664
+ partSizeBytes: z70.number().int().min(1),
52665
+ parts: z70.array(companyImportTransferDeclaredPartSchema).min(1).max(COMPANY_IMPORT_TRANSFER_MAX_PARTS)
51759
52666
  });
51760
52667
  function buildAlreadyImportedMessage(company) {
51761
52668
  const location = company ? ` The earlier import landed in the company "${company.name ?? company.id}"${company.issuePrefix ? ` (${company.issuePrefix})` : ""} \u2014 open it from the company switcher.` : "";
@@ -51810,23 +52717,23 @@ function validateCentralDirectory(bytes, eocdOffset, localHeaderCount) {
51810
52717
  );
51811
52718
  }
51812
52719
  const directoryEnd = centralDirectoryStart + centralDirectorySize;
51813
- let cursor2 = centralDirectoryStart;
52720
+ let cursor3 = centralDirectoryStart;
51814
52721
  let recordCount = 0;
51815
- while (cursor2 < directoryEnd) {
51816
- if (cursor2 + 46 > directoryEnd || readUint32(bytes, cursor2) !== CENTRAL_DIRECTORY_SIGNATURE) {
52722
+ while (cursor3 < directoryEnd) {
52723
+ if (cursor3 + 46 > directoryEnd || readUint32(bytes, cursor3) !== CENTRAL_DIRECTORY_SIGNATURE) {
51817
52724
  throw new Error("Invalid zip archive: malformed central directory record.");
51818
52725
  }
51819
- const fileNameLength = readUint16(bytes, cursor2 + 28);
51820
- const extraFieldLength = readUint16(bytes, cursor2 + 30);
51821
- const commentLength = readUint16(bytes, cursor2 + 32);
51822
- const localHeaderOffset = readUint32(bytes, cursor2 + 42);
52726
+ const fileNameLength = readUint16(bytes, cursor3 + 28);
52727
+ const extraFieldLength = readUint16(bytes, cursor3 + 30);
52728
+ const commentLength = readUint16(bytes, cursor3 + 32);
52729
+ const localHeaderOffset = readUint32(bytes, cursor3 + 42);
51823
52730
  if (localHeaderOffset + 4 > bytes.length || readUint32(bytes, localHeaderOffset) !== LOCAL_FILE_SIGNATURE) {
51824
52731
  throw new Error("Invalid zip archive: central directory references a missing local entry.");
51825
52732
  }
51826
- cursor2 += 46 + fileNameLength + extraFieldLength + commentLength;
52733
+ cursor3 += 46 + fileNameLength + extraFieldLength + commentLength;
51827
52734
  recordCount += 1;
51828
52735
  }
51829
- if (cursor2 !== directoryEnd) {
52736
+ if (cursor3 !== directoryEnd) {
51830
52737
  throw new Error("Invalid zip archive: central directory size does not match its records.");
51831
52738
  }
51832
52739
  if (recordCount !== declaredEntryCount || recordCount !== localHeaderCount) {
@@ -54937,9 +55844,9 @@ function kimiSkillsHome() {
54937
55844
  const base = fromEnv && fromEnv.length > 0 ? fromEnv : path41.join(os10.homedir(), ".kimi-code");
54938
55845
  return path41.join(base, "skills");
54939
55846
  }
54940
- async function installSkillsForTarget(sourceSkillsDir, targetSkillsDir, tool2) {
55847
+ async function installSkillsForTarget(sourceSkillsDir, targetSkillsDir, tool3) {
54941
55848
  const summary = {
54942
- tool: tool2,
55849
+ tool: tool3,
54943
55850
  target: targetSkillsDir,
54944
55851
  linked: [],
54945
55852
  removed: [],