@noodleseed/one 0.176.0 → 0.178.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (73) hide show
  1. package/dist/commands/solutions-activity.d.ts.map +1 -1
  2. package/dist/commands/solutions-activity.js +9 -35
  3. package/dist/commands/solutions-activity.js.map +1 -1
  4. package/dist/commands/solutions-conversations.d.ts +6 -0
  5. package/dist/commands/solutions-conversations.d.ts.map +1 -0
  6. package/dist/commands/solutions-conversations.js +191 -0
  7. package/dist/commands/solutions-conversations.js.map +1 -0
  8. package/dist/commands/solutions-history.d.ts +9 -0
  9. package/dist/commands/solutions-history.d.ts.map +1 -0
  10. package/dist/commands/solutions-history.js +166 -0
  11. package/dist/commands/solutions-history.js.map +1 -0
  12. package/dist/commands/solutions-ops.d.ts.map +1 -1
  13. package/dist/commands/solutions-ops.js +6 -0
  14. package/dist/commands/solutions-ops.js.map +1 -1
  15. package/dist/commands/whatsapp-ops.d.ts.map +1 -1
  16. package/dist/commands/whatsapp-ops.js +0 -7
  17. package/dist/commands/whatsapp-ops.js.map +1 -1
  18. package/node_modules/@noodle-borg/agent-kit/dist/generated/example-files.js +1 -1
  19. package/node_modules/@noodle-borg/agent-kit/dist/skill-embedded-assistant-ref.js +14 -0
  20. package/node_modules/@noodle-borg/agent-kit/package.json +1 -1
  21. package/node_modules/@noodle-borg/assistant-gateway/dist/public-surface.d.ts +6 -0
  22. package/node_modules/@noodle-borg/assistant-gateway/dist/public-surface.js +5 -2
  23. package/node_modules/@noodle-borg/assistant-gateway/package.json +1 -1
  24. package/node_modules/@noodle-borg/authoring/dist/assistant.d.ts +18 -0
  25. package/node_modules/@noodle-borg/authoring/dist/assistant.js +14 -1
  26. package/node_modules/@noodle-borg/cli-catalog/dist/catalog-data-channels.js +0 -3
  27. package/node_modules/@noodle-borg/cli-catalog/dist/catalog-data-solution-conversations.js +142 -0
  28. package/node_modules/@noodle-borg/cli-catalog/dist/catalog-data-solution-history.js +82 -0
  29. package/node_modules/@noodle-borg/cli-catalog/dist/catalog-data-solutions.js +5 -42
  30. package/node_modules/@noodle-borg/compiler/dist/manifest/schema.d.ts +8 -0
  31. package/node_modules/@noodle-borg/compiler/dist/manifest/schema.js +7 -0
  32. package/node_modules/@noodle-borg/service/dist/application-activity.js +76 -21
  33. package/node_modules/@noodle-borg/service/dist/application-history-settings.js +108 -0
  34. package/node_modules/@noodle-borg/service/dist/assistant-composition.js +11 -2
  35. package/node_modules/@noodle-borg/service/dist/channels/composition.js +10 -1
  36. package/node_modules/@noodle-borg/service/dist/channels/provider.js +40 -4
  37. package/node_modules/@noodle-borg/service/dist/channels/runtime.js +31 -5
  38. package/node_modules/@noodle-borg/service/dist/conversation-history/capture.js +63 -7
  39. package/node_modules/@noodle-borg/service/dist/conversation-history/contracts.js +13 -0
  40. package/node_modules/@noodle-borg/service/dist/conversation-history/customer.js +118 -0
  41. package/node_modules/@noodle-borg/service/dist/conversation-history/operator.js +293 -0
  42. package/node_modules/@noodle-borg/service/dist/routes/assistant-conversations.js +52 -0
  43. package/node_modules/@noodle-borg/service/dist/routes/assistant-dispatch.js +6 -0
  44. package/node_modules/@noodle-borg/service/dist/routes/assistant-elevation.js +3 -0
  45. package/node_modules/@noodle-borg/service/dist/routes/assistant-interaction-stream.js +2 -1
  46. package/node_modules/@noodle-borg/service/dist/routes/assistant-interactions.js +6 -11
  47. package/node_modules/@noodle-borg/service/dist/routes/assistant-public-session.js +6 -0
  48. package/node_modules/@noodle-borg/service/dist/routes/assistant-route-http.js +16 -0
  49. package/node_modules/@noodle-borg/service/dist/routes/assistant.js +5 -17
  50. package/node_modules/@noodle-borg/service/dist/routes/business-information-activity.js +6 -5
  51. package/node_modules/@noodle-borg/service/dist/routes/business-information-conversations.js +90 -0
  52. package/node_modules/@noodle-borg/service/dist/routes/business-information-dispatch.js +7 -2
  53. package/node_modules/@noodle-borg/service/dist/routes/business-information-paths.js +20 -2
  54. package/node_modules/@noodle-borg/service/dist/routes/business-information.js +4 -0
  55. package/node_modules/@noodle-borg/service/dist/routes/whatsapp.js +0 -10
  56. package/node_modules/@noodle-borg/service/dist/service-history-projections.js +52 -0
  57. package/node_modules/@noodle-borg/service/dist/service-resource-cleanup.js +32 -0
  58. package/node_modules/@noodle-borg/service/dist/service.js +6 -9
  59. package/node_modules/@noodle-borg/service/package.json +1 -1
  60. package/node_modules/@noodle-borg/wire-contracts/dist/application-activity.d.ts +0 -28
  61. package/node_modules/@noodle-borg/wire-contracts/dist/application-activity.js +0 -18
  62. package/node_modules/@noodle-borg/wire-contracts/dist/application-history-settings.d.ts +190 -0
  63. package/node_modules/@noodle-borg/wire-contracts/dist/application-history-settings.js +92 -0
  64. package/node_modules/@noodle-borg/wire-contracts/dist/assistant.d.ts +3 -0
  65. package/node_modules/@noodle-borg/wire-contracts/dist/assistant.js +6 -0
  66. package/node_modules/@noodle-borg/wire-contracts/dist/conversation-history.d.ts +523 -0
  67. package/node_modules/@noodle-borg/wire-contracts/dist/conversation-history.js +192 -0
  68. package/node_modules/@noodle-borg/wire-contracts/dist/index.d.ts +2 -0
  69. package/node_modules/@noodle-borg/wire-contracts/dist/index.js +2 -0
  70. package/node_modules/@noodle-borg/wire-contracts/dist/whatsapp.d.ts +2 -2
  71. package/node_modules/@noodleseed/assistant/README.md +19 -0
  72. package/node_modules/@noodleseed/assistant/package.json +1 -1
  73. package/package.json +2 -2
@@ -0,0 +1,90 @@
1
+ import { readJsonBody, sendJson } from '@noodle-borg/transport-http';
2
+ import { ConversationReviewRequestSchema } from '@noodle-borg/wire-contracts';
3
+ import { ConversationHistoryError, } from '../conversation-history/operator.js';
4
+ import { requireIdentity, requireInstallationPermission, } from './business-information.js';
5
+ /**
6
+ * ADR 0241 decision 10: readers see text; reviewing and noting need the record-handling permissions an
7
+ * Operator holds; only export and erasure need Owner/Administrator authority.
8
+ */
9
+ const PERMISSIONS = {
10
+ list: 'records:read',
11
+ show: 'records:read',
12
+ export: 'records:export',
13
+ forget: 'records:delete',
14
+ };
15
+ const METHODS = { list: ['GET'], show: ['GET', 'PATCH'], export: ['GET'], forget: ['POST'] };
16
+ export async function handleApplicationConversations(req, res, url, ref, deps) {
17
+ const route = ref.conversationAction ?? 'list';
18
+ const methods = METHODS[route];
19
+ if (!methods.includes(req.method ?? '')) {
20
+ res.setHeader('allow', methods.join(', '));
21
+ return sendJson(res, 405, { error: 'method not allowed' });
22
+ }
23
+ const action = req.method === 'PATCH' ? 'review' : route;
24
+ const identity = await requireIdentity(req, res, deps);
25
+ if (identity === false)
26
+ return;
27
+ // A review's permissions follow its fields, so it is read-authorized before its body is parsed.
28
+ let permissions = [PERMISSIONS[route]];
29
+ const authorize = async () => {
30
+ const [last = PERMISSIONS[route], ...earlier] = [...permissions].reverse();
31
+ for (const permission of earlier)
32
+ if (!(await requireInstallationPermission(res, ref, identity, permission, deps)))
33
+ return false;
34
+ return requireInstallationPermission(res, ref, identity, last, deps);
35
+ };
36
+ const authorized = await authorize();
37
+ if (!authorized)
38
+ return;
39
+ res.setHeader('cache-control', 'private, no-store');
40
+ try {
41
+ if (!deps.conversations)
42
+ throw new ConversationHistoryError('conversation_unavailable');
43
+ let body;
44
+ if (req.method !== 'GET') {
45
+ const parsed = await readJsonBody(req, deps.maxBody);
46
+ if (!parsed.ok)
47
+ return sendJson(res, parsed.status, { error: parsed.error });
48
+ body = parsed.value;
49
+ if (action === 'review') {
50
+ const review = ConversationReviewRequestSchema.safeParse(body);
51
+ if (!review.success)
52
+ throw new ConversationHistoryError('conversation_invalid');
53
+ permissions = [
54
+ ...(review.data.reviewStatus === undefined ? [] : ['records:status']),
55
+ ...(review.data.note === undefined ? [] : ['records:note']),
56
+ ];
57
+ }
58
+ if (!(await authorize()))
59
+ return;
60
+ }
61
+ const fence = permissions.at(-1) ?? PERMISSIONS[route];
62
+ const result = await deps.conversations.project(authorized.scope, action, {
63
+ parameters: [...url.searchParams.entries()],
64
+ ...(ref.conversationId === undefined ? {} : { conversationId: ref.conversationId }),
65
+ body,
66
+ actor: identity.subject,
67
+ ...(deps.forgetWhatsApp ? { forgetWorkingMemory: deps.forgetWhatsApp } : {}),
68
+ }, (operation) => deps.store.staff.run(authorized.scope, identity.subject, fence, operation));
69
+ for (const event of result.audits)
70
+ await deps.audit?.emit({
71
+ ...event,
72
+ org: ref.org,
73
+ app: authorized.scope.app,
74
+ env: authorized.scope.env,
75
+ actorSubject: identity.subject,
76
+ });
77
+ if (await authorize())
78
+ sendJson(res, 200, result.response);
79
+ }
80
+ catch (error) {
81
+ if (!(error instanceof ConversationHistoryError))
82
+ throw error;
83
+ sendJson(res, error.code === 'conversation_not_found'
84
+ ? 404
85
+ : error.code === 'conversation_unavailable'
86
+ ? 503
87
+ : 400, { code: error.code, error: error.message });
88
+ }
89
+ }
90
+ //# sourceMappingURL=business-information-conversations.js.map
@@ -9,9 +9,10 @@ import { SourceCapacityError } from '../business-information/source-custody-budg
9
9
  import { BusinessWorkspaceError } from '../business-workspaces/contracts.js';
10
10
  import { respondRouteError } from '../http-util.js';
11
11
  import { handleBusinessGrants, handleManagedRecords, handleSolutionCatalog, handleSolutionInstallations, } from './business-information.js';
12
- import { handleApplicationActivity, } from './business-information-activity.js';
12
+ import { handleApplicationActivity } from './business-information-activity.js';
13
13
  import { handleBusinessChannels, } from './business-information-channels.js';
14
14
  import { handleApplicationConnectionCallback, handleApplicationConnections, } from './business-information-connections.js';
15
+ import { handleApplicationConversations, } from './business-information-conversations.js';
15
16
  import { handleBusinessNotice, handleOrganizationAgreement, } from './business-information-notice.js';
16
17
  import { handleSolutionInstallationOptions } from './business-information-onboarding.js';
17
18
  import { handleBusinessPage, handlePublicBusinessPage } from './business-information-pages.js';
@@ -78,9 +79,13 @@ export function dispatchBusinessInformationRoutes(req, res, url, deps) {
78
79
  return run(req, res, deps, () => handleNativeRecordLifecycle(req, res, installationRef, deps));
79
80
  if (installationRef.action === 'notice')
80
81
  return run(req, res, deps, () => handleBusinessNotice(req, res, installationRef, deps));
81
- if ((installationRef.action === 'activity' || installationRef.action === 'coordination') &&
82
+ if ((installationRef.action === 'activity' ||
83
+ installationRef.action === 'history' ||
84
+ installationRef.action === 'coordination') &&
82
85
  installationRef.collection === undefined)
83
86
  return run(req, res, deps, () => handleApplicationActivity(req, res, url, installationRef, deps));
87
+ if (installationRef.action === 'conversations')
88
+ return run(req, res, deps, () => handleApplicationConversations(req, res, url, installationRef, deps));
84
89
  if (installationRef.action === 'connections')
85
90
  return run(req, res, deps, () => handleApplicationConnections(req, res, installationRef, deps));
86
91
  if (installationRef.action === 'settings') {
@@ -27,7 +27,23 @@ export function parseSolutionInstallationPath(pathname) {
27
27
  ...(connectionAction === undefined ? {} : { connectionAction }),
28
28
  };
29
29
  }
30
- const application = /^\/v1\/orgs\/([^/]+)\/solution-installations\/([^/]+)\/(activate|settings|notice|record-lifecycle|channels|operations\/coordination(?:\/resolve)?|activity(?:\/(?:settings|export|preview))?)$/.exec(pathname);
30
+ const conversations = /^\/v1\/orgs\/([^/]+)\/solution-installations\/([^/]+)\/conversations(?:\/(export|forget|cv_[A-Za-z0-9_-]{8,64}))?$/.exec(pathname);
31
+ if (conversations !== null) {
32
+ const org = decoded(conversations, 1), installationId = decoded(conversations, 2), segment = conversations[3];
33
+ return org === undefined || installationId === undefined
34
+ ? undefined
35
+ : {
36
+ org,
37
+ installationId,
38
+ action: 'conversations',
39
+ ...(segment === undefined
40
+ ? { conversationAction: 'list' }
41
+ : segment === 'export' || segment === 'forget'
42
+ ? { conversationAction: segment }
43
+ : { conversationAction: 'show', conversationId: segment }),
44
+ };
45
+ }
46
+ const application = /^\/v1\/orgs\/([^/]+)\/solution-installations\/([^/]+)\/(activate|settings|notice|record-lifecycle|channels|operations\/coordination(?:\/resolve)?|history\/settings|activity(?:\/(?:export|preview))?)$/.exec(pathname);
31
47
  if (application !== null) {
32
48
  const org = decoded(application, 1);
33
49
  const installationId = decoded(application, 2);
@@ -40,7 +56,9 @@ export function parseSolutionInstallationPath(pathname) {
40
56
  ? 'coordination'
41
57
  : application[3]?.startsWith('activity')
42
58
  ? 'activity'
43
- : application[3],
59
+ : application[3] === 'history/settings'
60
+ ? 'history'
61
+ : application[3],
44
62
  };
45
63
  }
46
64
  let match = /^\/v1\/orgs\/([^/]+)\/solution-installations$/.exec(pathname);
@@ -68,6 +68,10 @@ export async function handleSolutionInstallations(req, res, ref, deps) {
68
68
  code: 'installation_conflict',
69
69
  });
70
70
  }
71
+ // Only a created installation opts in (ADR 0241 decision 8), before activation can read the setting.
72
+ // Without a verified allowance it stays not enabled: recording nothing is the safe failure.
73
+ if (result.disposition === 'created')
74
+ await deps.activity?.initializeHistory(result.installation.scope).catch(() => false);
71
75
  const grant = await resolveBusinessStaffGrant(deps, result.installation.scope, identity.subject);
72
76
  if (grant === undefined || grant.revokedAt !== undefined) {
73
77
  return sendForbidden(res, 'business grant required');
@@ -209,16 +209,6 @@ async function operate(req, res, url, tenant, path, runtime, grants) {
209
209
  }
210
210
  return respond(res, wire.WhatsAppCooldownResponseSchema, await channels.cooldown(id, value));
211
211
  }
212
- if (kind === 'participants' &&
213
- value &&
214
- participant.test(value) &&
215
- action === 'forget' &&
216
- req.method === 'POST') {
217
- await body(req, wire.WhatsAppEmptyRequestSchema);
218
- await channels.forget(id, value, identity.subject, idempotency);
219
- await audit('conversation_forgotten');
220
- return sendJson(res, 200, { ok: true });
221
- }
222
212
  if (kind === 'events' &&
223
213
  (!value || eventId.test(value)) &&
224
214
  (read || (action === 'reconcile' && req.method === 'POST'))) {
@@ -0,0 +1,52 @@
1
+ import { randomBytes } from 'node:crypto';
2
+ import { ActivityPolicyError, ApplicationActivity } from './application-activity.js';
3
+ import { historyDisabledSurfaces } from './application-history-settings.js';
4
+ import { ApplicationConversations } from './conversation-history/operator.js';
5
+ /** Installation history projections over the optional durable stores the service was given. */
6
+ export function createHistoryProjections(options, moduleHost, installations, registry) {
7
+ const history = options.conversationHistory;
8
+ const activity = options.operationEvidence === undefined
9
+ ? undefined
10
+ : new ApplicationActivity({
11
+ ...options.operationEvidence,
12
+ allowance: async (org, request) => moduleHost.resolveActivityHistoryAllowance?.(org, request),
13
+ ...(history === undefined ? {} : { conversationHistory: history.store }),
14
+ historyDisabledSurfaces: async (scope) => historyDisabledSurfaces((await registry.getActiveByTenant(scope))?.served.artifact.server.assistant),
15
+ });
16
+ const conversationPolicy = history?.policy ?? settingsConversationPolicy(installations, activity);
17
+ const conversations = history === undefined
18
+ ? undefined
19
+ : new ApplicationConversations({
20
+ store: history.store,
21
+ policy: conversationPolicy,
22
+ identityKey: history.identityKey ?? randomBytes(32).toString('hex'),
23
+ ...(options.clock === undefined
24
+ ? {}
25
+ : { now: () => options.clock?.().getTime() ?? Date.now() }),
26
+ });
27
+ return { activity, conversations, conversationPolicy };
28
+ }
29
+ /**
30
+ * Capture follows the installation history setting under the live plan allowance (ADR 0241). A tenant
31
+ * with no single installation, setting opt-in or verified allowance records nothing, and the read never
32
+ * creates a setting.
33
+ */
34
+ function settingsConversationPolicy(installations, activity) {
35
+ return async (tenant) => {
36
+ if (!installations || !activity)
37
+ return undefined;
38
+ const matching = (await installations.listInstallations(tenant.org)).filter((item) => item.scope.app === tenant.app && item.scope.env === tenant.env);
39
+ const installation = matching.length === 1 ? matching[0] : undefined;
40
+ if (!installation)
41
+ return undefined;
42
+ try {
43
+ return await activity.conversationPolicy(installation.scope);
44
+ }
45
+ catch (error) {
46
+ if (error instanceof ActivityPolicyError)
47
+ return undefined;
48
+ throw error;
49
+ }
50
+ };
51
+ }
52
+ //# sourceMappingURL=service-history-projections.js.map
@@ -24,6 +24,38 @@ export async function closeServiceResources(input) {
24
24
  if (errors.length > 0)
25
25
  throw new AggregateError(errors, 'service resource cleanup failed');
26
26
  }
27
+ /**
28
+ * Clean up after a failed boot without letting a cleanup failure replace the error that aborted startup:
29
+ * operators must see the bind or boot cause, while the cleanup failure is still logged.
30
+ */
31
+ export async function cleanupAfterStartupFailure(logger, phase, cleanup) {
32
+ try {
33
+ await cleanup();
34
+ }
35
+ catch (error) {
36
+ const code = firstErrorCode(error);
37
+ logger.error('service.startup_cleanup_failed', {
38
+ phase,
39
+ name: error instanceof Error ? error.name : 'unknown',
40
+ ...(code === undefined ? {} : { code }),
41
+ });
42
+ }
43
+ }
44
+ /** The first scalar driver/system code, searching nested cleanup aggregates depth-first. */
45
+ function firstErrorCode(error, depth = 0) {
46
+ if (typeof error !== 'object' || error === null || depth > 4)
47
+ return undefined;
48
+ if ('code' in error && typeof error.code === 'string')
49
+ return error.code;
50
+ if (!(error instanceof AggregateError))
51
+ return undefined;
52
+ for (const nested of error.errors) {
53
+ const code = firstErrorCode(nested, depth + 1);
54
+ if (code !== undefined)
55
+ return code;
56
+ }
57
+ return undefined;
58
+ }
27
59
  export function listenHttpServer(http, port, host) {
28
60
  return new Promise((resolve, reject) => {
29
61
  const onError = (error) => {
@@ -6,7 +6,6 @@ import { capabilityOperatorRoute } from '@noodle-borg/managed-capabilities';
6
6
  import { OPENAI_APPS_CHALLENGE_PATH } from '@noodle-borg/module';
7
7
  import { applySecurityHeaders, createMcpRouter, enforceHttps, noopLogger, sendJson, } from '@noodle-borg/transport-http';
8
8
  import { AnonymousConsumerLimiter, createAdmissionGate } from './admission.js';
9
- import { ApplicationActivity } from './application-activity.js';
10
9
  import { createApplicationServingRuntime } from './application-runtime-target.js';
11
10
  import { createArchivePreflight } from './archive-preflight.js';
12
11
  import { ArchiveSweeper, resolveArchiveRetentionDays } from './archive-sweeper.js';
@@ -15,7 +14,7 @@ import { assistantRouteDependencies } from './assistant-composition.js';
15
14
  import { resolveBuildInfo } from './build-info.js';
16
15
  import { createBusinessInformationRuntime, resolvePrivateInstallationDefinition, } from './business-information-runtime.js';
17
16
  import { serviceCapabilityReport } from './capabilities.js';
18
- import { createWhatsAppRuntime } from './channels/composition.js';
17
+ import { createWhatsAppRuntime, whatsappBusinessRoutes } from './channels/composition.js';
19
18
  import { rejectIncompatibleCli } from './client-compatibility.js';
20
19
  import { createDataPlaneMembershipAuthorizer } from './data-plane-membership.js';
21
20
  import { DEVELOPER_MCP_PATH, handleDeveloperMcpRequest } from './developer-mcp/mount.js';
@@ -55,6 +54,7 @@ import { handleRollback } from './routes/rollback.js';
55
54
  import { createServicePrincipalDispatcher } from './routes/service-principals-dispatch.js';
56
55
  import { createServiceProbeDispatcher } from './routes/service-probes.js';
57
56
  import { dispatchWhatsAppRoutes } from './routes/whatsapp.js';
57
+ import { createHistoryProjections } from './service-history-projections.js';
58
58
  import { servicePrincipalDataPlaneHooks } from './service-principal-data-plane.js';
59
59
  import { InMemoryAlertRuleStore } from './store/alert-rules.js';
60
60
  import { StdoutAuditSink } from './store/audit.js';
@@ -95,12 +95,7 @@ export function createServiceHandler(registry, options = {}) {
95
95
  activeAudit = audit;
96
96
  const { publicTenantRouting } = mcp.mcpRoutingOptions(options, controlPlane);
97
97
  const resolveEndpointOptions = (org) => mcp.endpointUrlOptionsForOrg(options, controlPlane, org);
98
- const activity = options.operationEvidence === undefined
99
- ? undefined
100
- : new ApplicationActivity({
101
- ...options.operationEvidence,
102
- allowance: async (org, request) => moduleHost.resolveActivityHistoryAllowance?.(org, request),
103
- });
98
+ const { activity, conversations, conversationPolicy } = createHistoryProjections(options, moduleHost, businessInformationStore, registry);
104
99
  const withIntentMode = createIntentTargetResolver(intentSettings, intentPreviewOrgs);
105
100
  const { activateInstallation, readInstallationActivation, resolveRuntimeTarget, businessOnboarding, } = createApplicationServingRuntime(registry, providerOptions, controlPlane, audit, activity);
106
101
  const runtimeTarget = async (target) => target === undefined ? undefined : resolveRuntimeTarget(target);
@@ -197,6 +192,7 @@ export function createServiceHandler(registry, options = {}) {
197
192
  maxBody,
198
193
  serviceBase: (request) => options.publicBaseUrl ?? baseFromRequest(request, tls),
199
194
  logger,
195
+ conversationPolicy,
200
196
  });
201
197
  const whatsapp = createWhatsAppRuntime(options.whatsapp, assistantDeps, {
202
198
  allowance: moduleHost.resolveActivityHistoryAllowance,
@@ -307,13 +303,14 @@ export function createServiceHandler(registry, options = {}) {
307
303
  dispatchBusinessInformationRoutes(req, res, url, {
308
304
  pageOrigin: options.businessPageOrigin,
309
305
  pageServiceUrl: options.publicBaseUrl,
310
- ...(whatsapp ? { readWhatsApp: whatsapp.projection.bind(whatsapp) } : {}),
306
+ ...whatsappBusinessRoutes(whatsapp),
311
307
  store: businessInformationStore,
312
308
  ...(options.businessAuthoring ? { workspaces: options.businessAuthoring.workspaces } : {}),
313
309
  ...(businessOnboarding ? { businessOnboarding } : {}),
314
310
  activateInstallation,
315
311
  readInstallationActivation,
316
312
  ...(activity === undefined ? {} : { activity }),
313
+ ...(conversations === undefined ? {} : { conversations }),
317
314
  ...(options.connectionRuntime === undefined
318
315
  ? {}
319
316
  : {
@@ -41,7 +41,7 @@
41
41
  "@noodle-borg/managed-capabilities": "0.0.0",
42
42
  "@modelcontextprotocol/sdk": "^1.29.0",
43
43
  "@noodle-borg/admission-limits": "0.0.0",
44
- "@noodle-borg/agent-kit": "0.107.0",
44
+ "@noodle-borg/agent-kit": "0.108.0",
45
45
  "@noodle-borg/app-package": "0.0.0",
46
46
  "@noodle-borg/assistant-gateway": "0.0.0",
47
47
  "@noodle-borg/auth": "0.0.0",
@@ -42,25 +42,6 @@ export declare const ApplicationActivityListResponseSchema: z.ZodObject<{
42
42
  historyDays: z.ZodNumber;
43
43
  }, z.core.$strict>;
44
44
  }, z.core.$strict>;
45
- export declare const ApplicationActivitySettingsSchema: z.ZodObject<{
46
- revision: z.ZodString;
47
- retentionDays: z.ZodNumber;
48
- maximumDays: z.ZodNumber;
49
- canEdit: z.ZodBoolean;
50
- }, z.core.$strict>;
51
- export declare const ApplicationActivitySettingsResponseSchema: z.ZodObject<{
52
- ok: z.ZodLiteral<true>;
53
- data: z.ZodObject<{
54
- revision: z.ZodString;
55
- retentionDays: z.ZodNumber;
56
- maximumDays: z.ZodNumber;
57
- canEdit: z.ZodBoolean;
58
- }, z.core.$strict>;
59
- }, z.core.$strict>;
60
- export declare const ApplicationActivitySettingsSaveRequestSchema: z.ZodObject<{
61
- expectedRevision: z.ZodString;
62
- retentionDays: z.ZodNumber;
63
- }, z.core.$strict>;
64
45
  /** Clients tolerate additive response fields; writes and server output remain strict. */
65
46
  export declare const ApplicationActivityListClientResponseSchema: z.ZodObject<{
66
47
  ok: z.ZodLiteral<true>;
@@ -87,15 +68,6 @@ export declare const ApplicationActivityListClientResponseSchema: z.ZodObject<{
87
68
  historyDays: z.ZodNumber;
88
69
  }, z.core.$strip>;
89
70
  }, z.core.$strip>;
90
- export declare const ApplicationActivitySettingsClientResponseSchema: z.ZodObject<{
91
- ok: z.ZodLiteral<true>;
92
- data: z.ZodObject<{
93
- revision: z.ZodString;
94
- retentionDays: z.ZodNumber;
95
- maximumDays: z.ZodNumber;
96
- canEdit: z.ZodBoolean;
97
- }, z.core.$strip>;
98
- }, z.core.$strip>;
99
71
  export declare const ApplicationActivityPreviewResponseSchema: z.ZodObject<{
100
72
  ok: z.ZodLiteral<true>;
101
73
  data: z.ZodDiscriminatedUnion<[z.ZodObject<{
@@ -18,20 +18,6 @@ export const ApplicationActivityListResponseSchema = z.strictObject({
18
18
  historyDays: z.number().int().min(1).max(365),
19
19
  }),
20
20
  });
21
- export const ApplicationActivitySettingsSchema = z.strictObject({
22
- revision: z.string().regex(/^[a-f0-9]{64}$/),
23
- retentionDays: z.number().int().min(1).max(365),
24
- maximumDays: z.number().int().min(1).max(365),
25
- canEdit: z.boolean(),
26
- });
27
- export const ApplicationActivitySettingsResponseSchema = z.strictObject({
28
- ok: z.literal(true),
29
- data: ApplicationActivitySettingsSchema,
30
- });
31
- export const ApplicationActivitySettingsSaveRequestSchema = z.strictObject({
32
- expectedRevision: z.string().regex(/^[a-f0-9]{64}$/),
33
- retentionDays: z.number().int().min(1).max(365),
34
- });
35
21
  /** Clients tolerate additive response fields; writes and server output remain strict. */
36
22
  export const ApplicationActivityListClientResponseSchema = z.object({
37
23
  ok: z.literal(true),
@@ -45,10 +31,6 @@ export const ApplicationActivityListClientResponseSchema = z.object({
45
31
  .max(100),
46
32
  }),
47
33
  });
48
- export const ApplicationActivitySettingsClientResponseSchema = z.object({
49
- ok: z.literal(true),
50
- data: z.object(ApplicationActivitySettingsSchema.shape),
51
- });
52
34
  const ActivityPreviewScenarioSchema = z.strictObject({
53
35
  id: z.string().min(1).max(128),
54
36
  label: z.string().min(1).max(128),
@@ -0,0 +1,190 @@
1
+ import { z } from 'zod';
2
+ export declare const HistorySourcesSchema: z.ZodObject<{
3
+ websiteVisitors: z.ZodBoolean;
4
+ signedInCustomers: z.ZodBoolean;
5
+ whatsapp: z.ZodBoolean;
6
+ }, z.core.$strict>;
7
+ /** A surface the application declared `history: false` on, named by its authoring constructor. */
8
+ export declare const ApplicationHistoryDisabledSurfaceSchema: z.ZodEnum<{
9
+ publicWebsite: "publicWebsite";
10
+ authenticatedWebsite: "authenticatedWebsite";
11
+ publicMessaging: "publicMessaging";
12
+ }>;
13
+ export declare const ApplicationHistorySettingsSchema: z.ZodObject<{
14
+ revision: z.ZodString;
15
+ canEdit: z.ZodBoolean;
16
+ activity: z.ZodObject<{
17
+ retentionDays: z.ZodNumber;
18
+ maximumDays: z.ZodNumber;
19
+ defaultDays: z.ZodNumber;
20
+ }, z.core.$strict>;
21
+ conversations: z.ZodObject<{
22
+ state: z.ZodEnum<{
23
+ not_enabled: "not_enabled";
24
+ off: "off";
25
+ on: "on";
26
+ }>;
27
+ retentionDays: z.ZodOptional<z.ZodNumber>;
28
+ sources: z.ZodObject<{
29
+ websiteVisitors: z.ZodBoolean;
30
+ signedInCustomers: z.ZodBoolean;
31
+ whatsapp: z.ZodBoolean;
32
+ }, z.core.$strict>;
33
+ disabledByApplication: z.ZodOptional<z.ZodArray<z.ZodEnum<{
34
+ publicWebsite: "publicWebsite";
35
+ authenticatedWebsite: "authenticatedWebsite";
36
+ publicMessaging: "publicMessaging";
37
+ }>>>;
38
+ }, z.core.$strict>;
39
+ }, z.core.$strict>;
40
+ export declare const ApplicationHistorySettingsResponseSchema: z.ZodObject<{
41
+ ok: z.ZodLiteral<true>;
42
+ data: z.ZodObject<{
43
+ revision: z.ZodString;
44
+ canEdit: z.ZodBoolean;
45
+ activity: z.ZodObject<{
46
+ retentionDays: z.ZodNumber;
47
+ maximumDays: z.ZodNumber;
48
+ defaultDays: z.ZodNumber;
49
+ }, z.core.$strict>;
50
+ conversations: z.ZodObject<{
51
+ state: z.ZodEnum<{
52
+ not_enabled: "not_enabled";
53
+ off: "off";
54
+ on: "on";
55
+ }>;
56
+ retentionDays: z.ZodOptional<z.ZodNumber>;
57
+ sources: z.ZodObject<{
58
+ websiteVisitors: z.ZodBoolean;
59
+ signedInCustomers: z.ZodBoolean;
60
+ whatsapp: z.ZodBoolean;
61
+ }, z.core.$strict>;
62
+ disabledByApplication: z.ZodOptional<z.ZodArray<z.ZodEnum<{
63
+ publicWebsite: "publicWebsite";
64
+ authenticatedWebsite: "authenticatedWebsite";
65
+ publicMessaging: "publicMessaging";
66
+ }>>>;
67
+ }, z.core.$strict>;
68
+ }, z.core.$strict>;
69
+ }, z.core.$strict>;
70
+ /** Omitted fields keep their value; `dryRun` reports the effect without saving. */
71
+ export declare const ApplicationHistorySettingsSaveRequestSchema: z.ZodObject<{
72
+ expectedRevision: z.ZodString;
73
+ activityDays: z.ZodOptional<z.ZodNumber>;
74
+ conversations: z.ZodOptional<z.ZodUnion<readonly [z.ZodObject<{
75
+ retentionDays: z.ZodNumber;
76
+ }, z.core.$strict>, z.ZodLiteral<"off">]>>;
77
+ sources: z.ZodOptional<z.ZodObject<{
78
+ websiteVisitors: z.ZodOptional<z.ZodBoolean>;
79
+ signedInCustomers: z.ZodOptional<z.ZodBoolean>;
80
+ whatsapp: z.ZodOptional<z.ZodBoolean>;
81
+ }, z.core.$strict>>;
82
+ dryRun: z.ZodOptional<z.ZodBoolean>;
83
+ }, z.core.$strict>;
84
+ export declare const ApplicationHistorySettingsSaveResponseSchema: z.ZodObject<{
85
+ ok: z.ZodLiteral<true>;
86
+ data: z.ZodObject<{
87
+ dryRun: z.ZodBoolean;
88
+ shortensConversations: z.ZodBoolean;
89
+ impact: z.ZodObject<{
90
+ conversations: z.ZodNumber;
91
+ items: z.ZodNumber;
92
+ }, z.core.$strict>;
93
+ settings: z.ZodObject<{
94
+ revision: z.ZodString;
95
+ canEdit: z.ZodBoolean;
96
+ activity: z.ZodObject<{
97
+ retentionDays: z.ZodNumber;
98
+ maximumDays: z.ZodNumber;
99
+ defaultDays: z.ZodNumber;
100
+ }, z.core.$strict>;
101
+ conversations: z.ZodObject<{
102
+ state: z.ZodEnum<{
103
+ not_enabled: "not_enabled";
104
+ off: "off";
105
+ on: "on";
106
+ }>;
107
+ retentionDays: z.ZodOptional<z.ZodNumber>;
108
+ sources: z.ZodObject<{
109
+ websiteVisitors: z.ZodBoolean;
110
+ signedInCustomers: z.ZodBoolean;
111
+ whatsapp: z.ZodBoolean;
112
+ }, z.core.$strict>;
113
+ disabledByApplication: z.ZodOptional<z.ZodArray<z.ZodEnum<{
114
+ publicWebsite: "publicWebsite";
115
+ authenticatedWebsite: "authenticatedWebsite";
116
+ publicMessaging: "publicMessaging";
117
+ }>>>;
118
+ }, z.core.$strict>;
119
+ }, z.core.$strict>;
120
+ }, z.core.$strict>;
121
+ }, z.core.$strict>;
122
+ export declare const ApplicationHistorySettingsClientResponseSchema: z.ZodObject<{
123
+ ok: z.ZodLiteral<true>;
124
+ data: z.ZodObject<{
125
+ activity: z.ZodObject<{
126
+ retentionDays: z.ZodNumber;
127
+ maximumDays: z.ZodNumber;
128
+ defaultDays: z.ZodNumber;
129
+ }, z.core.$strip>;
130
+ conversations: z.ZodObject<{
131
+ sources: z.ZodObject<{
132
+ websiteVisitors: z.ZodBoolean;
133
+ signedInCustomers: z.ZodBoolean;
134
+ whatsapp: z.ZodBoolean;
135
+ }, z.core.$strip>;
136
+ state: z.ZodEnum<{
137
+ not_enabled: "not_enabled";
138
+ off: "off";
139
+ on: "on";
140
+ }>;
141
+ retentionDays: z.ZodOptional<z.ZodNumber>;
142
+ disabledByApplication: z.ZodOptional<z.ZodArray<z.ZodEnum<{
143
+ publicWebsite: "publicWebsite";
144
+ authenticatedWebsite: "authenticatedWebsite";
145
+ publicMessaging: "publicMessaging";
146
+ }>>>;
147
+ }, z.core.$strip>;
148
+ revision: z.ZodString;
149
+ canEdit: z.ZodBoolean;
150
+ }, z.core.$strip>;
151
+ }, z.core.$strip>;
152
+ export declare const ApplicationHistorySettingsSaveClientResponseSchema: z.ZodObject<{
153
+ ok: z.ZodLiteral<true>;
154
+ data: z.ZodObject<{
155
+ impact: z.ZodObject<{
156
+ conversations: z.ZodNumber;
157
+ items: z.ZodNumber;
158
+ }, z.core.$strip>;
159
+ settings: z.ZodObject<{
160
+ activity: z.ZodObject<{
161
+ retentionDays: z.ZodNumber;
162
+ maximumDays: z.ZodNumber;
163
+ defaultDays: z.ZodNumber;
164
+ }, z.core.$strip>;
165
+ conversations: z.ZodObject<{
166
+ sources: z.ZodObject<{
167
+ websiteVisitors: z.ZodBoolean;
168
+ signedInCustomers: z.ZodBoolean;
169
+ whatsapp: z.ZodBoolean;
170
+ }, z.core.$strip>;
171
+ state: z.ZodEnum<{
172
+ not_enabled: "not_enabled";
173
+ off: "off";
174
+ on: "on";
175
+ }>;
176
+ retentionDays: z.ZodOptional<z.ZodNumber>;
177
+ disabledByApplication: z.ZodOptional<z.ZodArray<z.ZodEnum<{
178
+ publicWebsite: "publicWebsite";
179
+ authenticatedWebsite: "authenticatedWebsite";
180
+ publicMessaging: "publicMessaging";
181
+ }>>>;
182
+ }, z.core.$strip>;
183
+ revision: z.ZodString;
184
+ canEdit: z.ZodBoolean;
185
+ }, z.core.$strip>;
186
+ dryRun: z.ZodBoolean;
187
+ shortensConversations: z.ZodBoolean;
188
+ }, z.core.$strip>;
189
+ }, z.core.$strip>;
190
+ //# sourceMappingURL=application-history-settings.d.ts.map