@qcobro/common 1.11.3 → 1.11.4

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 (173) hide show
  1. package/dist/config.d.ts +307 -0
  2. package/dist/config.d.ts.map +1 -0
  3. package/{src/config.ts → dist/config.js} +123 -154
  4. package/dist/config.js.map +1 -0
  5. package/dist/errors/ValidationError.d.ts +27 -0
  6. package/dist/errors/ValidationError.d.ts.map +1 -0
  7. package/dist/errors/ValidationError.js +52 -0
  8. package/dist/errors/ValidationError.js.map +1 -0
  9. package/{src/errors/index.ts → dist/errors/index.d.ts} +1 -0
  10. package/dist/errors/index.d.ts.map +1 -0
  11. package/dist/errors/index.js +2 -0
  12. package/dist/errors/index.js.map +1 -0
  13. package/dist/index.d.ts +19 -0
  14. package/dist/index.d.ts.map +1 -0
  15. package/{src/index.ts → dist/index.js} +2 -5
  16. package/dist/index.js.map +1 -0
  17. package/dist/schemas/agentTemplates.d.ts +73 -0
  18. package/dist/schemas/agentTemplates.d.ts.map +1 -0
  19. package/dist/schemas/agentTemplates.js +90 -0
  20. package/dist/schemas/agentTemplates.js.map +1 -0
  21. package/dist/schemas/apiKeys.d.ts +17 -0
  22. package/dist/schemas/apiKeys.d.ts.map +1 -0
  23. package/{src/schemas/apiKeys.ts → dist/schemas/apiKeys.js} +11 -16
  24. package/dist/schemas/apiKeys.js.map +1 -0
  25. package/dist/schemas/auth.d.ts +74 -0
  26. package/dist/schemas/auth.d.ts.map +1 -0
  27. package/dist/schemas/auth.js +53 -0
  28. package/dist/schemas/auth.js.map +1 -0
  29. package/dist/schemas/campaigns.d.ts +61 -0
  30. package/dist/schemas/campaigns.d.ts.map +1 -0
  31. package/{src/schemas/campaigns.ts → dist/schemas/campaigns.js} +20 -32
  32. package/dist/schemas/campaigns.js.map +1 -0
  33. package/dist/schemas/contactLog.d.ts +121 -0
  34. package/dist/schemas/contactLog.d.ts.map +1 -0
  35. package/dist/schemas/contactLog.js +83 -0
  36. package/dist/schemas/contactLog.js.map +1 -0
  37. package/dist/schemas/dispatch.d.ts +51 -0
  38. package/dist/schemas/dispatch.d.ts.map +1 -0
  39. package/{src/schemas/dispatch.ts → dist/schemas/dispatch.js} +55 -61
  40. package/dist/schemas/dispatch.js.map +1 -0
  41. package/dist/schemas/email.d.ts +38 -0
  42. package/dist/schemas/email.d.ts.map +1 -0
  43. package/dist/schemas/email.js +34 -0
  44. package/dist/schemas/email.js.map +1 -0
  45. package/dist/schemas/index.d.ts +16 -0
  46. package/dist/schemas/index.d.ts.map +1 -0
  47. package/{src/schemas/index.ts → dist/schemas/index.js} +1 -0
  48. package/dist/schemas/index.js.map +1 -0
  49. package/dist/schemas/insight.d.ts +25 -0
  50. package/dist/schemas/insight.d.ts.map +1 -0
  51. package/{src/schemas/insight.ts → dist/schemas/insight.js} +6 -9
  52. package/dist/schemas/insight.js.map +1 -0
  53. package/dist/schemas/portfolios.d.ts +65 -0
  54. package/dist/schemas/portfolios.d.ts.map +1 -0
  55. package/dist/schemas/portfolios.js +40 -0
  56. package/dist/schemas/portfolios.js.map +1 -0
  57. package/dist/schemas/userSettings.d.ts +25 -0
  58. package/dist/schemas/userSettings.d.ts.map +1 -0
  59. package/{src/schemas/userSettings.ts → dist/schemas/userSettings.js} +4 -9
  60. package/dist/schemas/userSettings.js.map +1 -0
  61. package/dist/schemas/users.d.ts +7 -0
  62. package/dist/schemas/users.d.ts.map +1 -0
  63. package/dist/schemas/users.js +6 -0
  64. package/dist/schemas/users.js.map +1 -0
  65. package/dist/schemas/voiceEvent.d.ts +37 -0
  66. package/dist/schemas/voiceEvent.d.ts.map +1 -0
  67. package/dist/schemas/voiceEvent.js +35 -0
  68. package/dist/schemas/voiceEvent.js.map +1 -0
  69. package/dist/schemas/whatsApp.d.ts +76 -0
  70. package/dist/schemas/whatsApp.d.ts.map +1 -0
  71. package/dist/schemas/whatsApp.js +85 -0
  72. package/dist/schemas/whatsApp.js.map +1 -0
  73. package/dist/schemas/workspaceSettings.d.ts +27 -0
  74. package/dist/schemas/workspaceSettings.d.ts.map +1 -0
  75. package/{src/schemas/workspaceSettings.ts → dist/schemas/workspaceSettings.js} +6 -11
  76. package/dist/schemas/workspaceSettings.js.map +1 -0
  77. package/dist/schemas/workspaces.d.ts +50 -0
  78. package/dist/schemas/workspaces.d.ts.map +1 -0
  79. package/dist/schemas/workspaces.js +36 -0
  80. package/dist/schemas/workspaces.js.map +1 -0
  81. package/dist/types/agentTemplates.d.ts +119 -0
  82. package/dist/types/agentTemplates.d.ts.map +1 -0
  83. package/dist/types/agentTemplates.js +2 -0
  84. package/dist/types/agentTemplates.js.map +1 -0
  85. package/dist/types/campaigns.d.ts +257 -0
  86. package/dist/types/campaigns.d.ts.map +1 -0
  87. package/dist/types/campaigns.js +2 -0
  88. package/dist/types/campaigns.js.map +1 -0
  89. package/dist/types/dispatch.d.ts +168 -0
  90. package/dist/types/dispatch.d.ts.map +1 -0
  91. package/dist/types/dispatch.js +8 -0
  92. package/dist/types/dispatch.js.map +1 -0
  93. package/dist/types/email.d.ts +65 -0
  94. package/dist/types/email.d.ts.map +1 -0
  95. package/dist/types/email.js +7 -0
  96. package/dist/types/email.js.map +1 -0
  97. package/{src/types/engine.ts → dist/types/engine.d.ts} +23 -46
  98. package/dist/types/engine.d.ts.map +1 -0
  99. package/dist/types/engine.js +10 -0
  100. package/dist/types/engine.js.map +1 -0
  101. package/dist/types/index.d.ts +12 -0
  102. package/dist/types/index.d.ts.map +1 -0
  103. package/{src/types/index.ts → dist/types/index.js} +1 -0
  104. package/dist/types/index.js.map +1 -0
  105. package/{src/types/insight.ts → dist/types/insight.d.ts} +10 -8
  106. package/dist/types/insight.d.ts.map +1 -0
  107. package/dist/types/insight.js +2 -0
  108. package/dist/types/insight.js.map +1 -0
  109. package/dist/types/portfolios.d.ts +153 -0
  110. package/dist/types/portfolios.d.ts.map +1 -0
  111. package/dist/types/portfolios.js +2 -0
  112. package/dist/types/portfolios.js.map +1 -0
  113. package/dist/types/userSettings.d.ts +25 -0
  114. package/dist/types/userSettings.d.ts.map +1 -0
  115. package/dist/types/userSettings.js +2 -0
  116. package/dist/types/userSettings.js.map +1 -0
  117. package/dist/types/voiceApplication.d.ts +32 -0
  118. package/dist/types/voiceApplication.d.ts.map +1 -0
  119. package/dist/types/voiceApplication.js +7 -0
  120. package/dist/types/voiceApplication.js.map +1 -0
  121. package/dist/types/whatsApp.d.ts +97 -0
  122. package/dist/types/whatsApp.d.ts.map +1 -0
  123. package/dist/types/whatsApp.js +2 -0
  124. package/dist/types/whatsApp.js.map +1 -0
  125. package/dist/types/workspaceSettings.d.ts +26 -0
  126. package/dist/types/workspaceSettings.d.ts.map +1 -0
  127. package/dist/types/workspaceSettings.js +2 -0
  128. package/dist/types/workspaceSettings.js.map +1 -0
  129. package/dist/utils/index.d.ts +4 -0
  130. package/dist/utils/index.d.ts.map +1 -0
  131. package/dist/utils/index.js +4 -0
  132. package/dist/utils/index.js.map +1 -0
  133. package/{src/utils/outreach.ts → dist/utils/outreach.d.ts} +7 -32
  134. package/dist/utils/outreach.d.ts.map +1 -0
  135. package/dist/utils/outreach.js +49 -0
  136. package/dist/utils/outreach.js.map +1 -0
  137. package/dist/utils/time.d.ts +25 -0
  138. package/dist/utils/time.d.ts.map +1 -0
  139. package/dist/utils/time.js +52 -0
  140. package/dist/utils/time.js.map +1 -0
  141. package/dist/utils/withErrorHandlingAndValidation.d.ts +18 -0
  142. package/dist/utils/withErrorHandlingAndValidation.d.ts.map +1 -0
  143. package/{src/utils/withErrorHandlingAndValidation.ts → dist/utils/withErrorHandlingAndValidation.js} +9 -15
  144. package/dist/utils/withErrorHandlingAndValidation.js.map +1 -0
  145. package/package.json +4 -1
  146. package/CHANGELOG.md +0 -115
  147. package/src/config.test.ts +0 -19
  148. package/src/errors/ValidationError.test.ts +0 -38
  149. package/src/errors/ValidationError.ts +0 -68
  150. package/src/schemas/agentTemplates.ts +0 -100
  151. package/src/schemas/apiKeys.test.ts +0 -38
  152. package/src/schemas/auth.ts +0 -76
  153. package/src/schemas/contactLog.ts +0 -96
  154. package/src/schemas/email.ts +0 -37
  155. package/src/schemas/portfolios.ts +0 -49
  156. package/src/schemas/users.ts +0 -7
  157. package/src/schemas/voiceEvent.ts +0 -45
  158. package/src/schemas/whatsApp.ts +0 -101
  159. package/src/schemas/workspaces.ts +0 -53
  160. package/src/types/agentTemplates.ts +0 -104
  161. package/src/types/campaigns.ts +0 -210
  162. package/src/types/dispatch.ts +0 -160
  163. package/src/types/email.ts +0 -66
  164. package/src/types/portfolios.ts +0 -128
  165. package/src/types/userSettings.ts +0 -21
  166. package/src/types/voiceApplication.ts +0 -29
  167. package/src/types/whatsApp.ts +0 -82
  168. package/src/types/workspaceSettings.ts +0 -22
  169. package/src/utils/index.ts +0 -14
  170. package/src/utils/outreach.test.ts +0 -83
  171. package/src/utils/time.ts +0 -66
  172. package/src/utils/withErrorHandlingAndValidation.test.ts +0 -33
  173. package/tsconfig.json +0 -9
@@ -1,38 +0,0 @@
1
- import { describe, it } from "node:test";
2
- import assert from "node:assert/strict";
3
- import { createApiKeySchema, apiKeyRefSchema } from "./apiKeys.js";
4
-
5
- describe("createApiKeySchema", () => {
6
- it("defaults the role to admin with no expiry", () => {
7
- const parsed = createApiKeySchema.parse({});
8
- assert.equal(parsed.role, "WORKSPACE_ADMIN");
9
- assert.equal(parsed.expiresAt, undefined);
10
- });
11
-
12
- it("accepts an admin role with a future expiry", () => {
13
- const future = Date.now() + 86_400_000;
14
- const parsed = createApiKeySchema.parse({ role: "WORKSPACE_ADMIN", expiresAt: future });
15
- assert.equal(parsed.role, "WORKSPACE_ADMIN");
16
- assert.equal(parsed.expiresAt, future);
17
- });
18
-
19
- it("rejects member/owner roles — Identity only issues admin keys", () => {
20
- assert.equal(createApiKeySchema.safeParse({ role: "WORKSPACE_MEMBER" }).success, false);
21
- assert.equal(createApiKeySchema.safeParse({ role: "WORKSPACE_OWNER" }).success, false);
22
- });
23
-
24
- it("rejects an expiry in the past", () => {
25
- const result = createApiKeySchema.safeParse({ expiresAt: Date.now() - 1000 });
26
- assert.equal(result.success, false);
27
- if (!result.success) {
28
- assert.match(result.error.issues[0].message, /future/);
29
- }
30
- });
31
- });
32
-
33
- describe("apiKeyRefSchema", () => {
34
- it("requires a non-empty ref", () => {
35
- assert.equal(apiKeyRefSchema.safeParse({ ref: "" }).success, false);
36
- assert.equal(apiKeyRefSchema.safeParse({ ref: "ak_1" }).success, true);
37
- });
38
- });
@@ -1,76 +0,0 @@
1
- import { z } from "zod";
2
-
3
- export const signUpSchema = z.object({
4
- name: z.string().min(1).max(60),
5
- email: z.email(),
6
- password: z.string().min(8).max(128),
7
- phone: z.string().max(20).optional(),
8
- avatar: z.string().max(255).optional()
9
- });
10
- export type SignUpInput = z.infer<typeof signUpSchema>;
11
-
12
- export const loginSchema = z.object({
13
- email: z.email(),
14
- password: z.string().min(1),
15
- twoFactorCode: z.string().optional()
16
- });
17
- export type LoginInput = z.infer<typeof loginSchema>;
18
-
19
- export const refreshTokenSchema = z.object({
20
- refreshToken: z.string().min(1)
21
- });
22
- export type RefreshTokenInput = z.infer<typeof refreshTokenSchema>;
23
-
24
- // Exchange a workspace API key (accessKeyId + accessKeySecret) for tokens.
25
- // Used by unattended, server-to-server integrations (e.g. the SDK's
26
- // loginWithApiKey) that cannot perform an interactive credentials login.
27
- export const apiKeyLoginSchema = z.object({
28
- accessKeyId: z.string().min(1),
29
- accessKeySecret: z.string().min(1)
30
- });
31
- export type ApiKeyLoginInput = z.infer<typeof apiKeyLoginSchema>;
32
-
33
- export const sendResetPasswordCodeSchema = z.object({
34
- username: z.email(),
35
- resetPasswordUrl: z.string().url()
36
- });
37
- export type SendResetPasswordCodeInput = z.infer<typeof sendResetPasswordCodeSchema>;
38
-
39
- export const resetPasswordSchema = z.object({
40
- username: z.email(),
41
- password: z.string().min(8).max(128),
42
- verificationCode: z.string().min(1)
43
- });
44
- export type ResetPasswordInput = z.infer<typeof resetPasswordSchema>;
45
-
46
- export const contactTypeEnum = z.enum(["EMAIL", "PHONE"]);
47
- export type ContactType = z.infer<typeof contactTypeEnum>;
48
-
49
- export const sendVerificationCodeSchema = z.object({
50
- contactType: contactTypeEnum,
51
- value: z.string().min(1)
52
- });
53
- export type SendVerificationCodeInput = z.infer<typeof sendVerificationCodeSchema>;
54
-
55
- export const verifyCodeSchema = z.object({
56
- username: z.email(),
57
- contactType: contactTypeEnum,
58
- value: z.string().min(1),
59
- verificationCode: z.string().min(1)
60
- });
61
- export type VerifyCodeInput = z.infer<typeof verifyCodeSchema>;
62
-
63
- // Identity currently supports a single OAuth2 provider.
64
- export const oauthProviderEnum = z.enum(["GITHUB"]);
65
- export type OauthProvider = z.infer<typeof oauthProviderEnum>;
66
-
67
- export const oauthSignInSchema = z.object({
68
- provider: oauthProviderEnum,
69
- code: z.string().min(1)
70
- });
71
- export type OauthSignInInput = z.infer<typeof oauthSignInSchema>;
72
-
73
- export const oauthSignUpSchema = z.object({
74
- code: z.string().min(1)
75
- });
76
- export type OauthSignUpInput = z.infer<typeof oauthSignUpSchema>;
@@ -1,96 +0,0 @@
1
- import { z } from "zod";
2
- import { agentTypeSchema } from "./agentTemplates.js";
3
-
4
- export const contactOutcomeSchema = z.enum([
5
- "DELIVERED",
6
- "NOT_DELIVERED",
7
- "NO_ANSWER",
8
- "PAYMENT_PROMISE",
9
- "PARTIAL_PAYMENT_AGREED",
10
- "NEW_TERMS",
11
- "CALLBACK_REQUESTED",
12
- "DISPUTE_RAISED",
13
- "INFORMATION_REQUEST",
14
- "RESOLVED",
15
- "PAID",
16
- "WRONG_NUMBER",
17
- "OPT_OUT",
18
- "REFUSED",
19
- "OTHER"
20
- ]);
21
- export type ContactOutcome = z.infer<typeof contactOutcomeSchema>;
22
-
23
- export const aiSentimentSchema = z.enum(["POSITIVE", "NEUTRAL", "NEGATIVE", "HOSTILE"]);
24
- export type AiSentiment = z.infer<typeof aiSentimentSchema>;
25
-
26
- /**
27
- * PaymentPromise is the only outcome QCobro tracks with a lifecycle, because a payment
28
- * is the only commitment it can verify. DUE is derived (PENDING past its dueDate), not a
29
- * stored status. There is intentionally no "broken" status — an unpaid promise stays on
30
- * the worklist until an operator resolves it. EXPIRED is set when the account leaves its
31
- * portfolio.
32
- */
33
- export const paymentPromiseStatusSchema = z.enum(["PENDING", "MET", "EXPIRED", "CANCELLED"]);
34
- export type PaymentPromiseStatus = z.infer<typeof paymentPromiseStatusSchema>;
35
-
36
- export const createContactLogSchema = z.object({
37
- portfolioAccountId: z.string().min(1),
38
- campaignId: z.string().min(1).optional(),
39
- /** Agent template used (campaign dispatch or ad-hoc follow-up). */
40
- agentTemplateId: z.string().min(1).optional(),
41
- /** Set when this gestión is an ad-hoc follow-up on a specific PaymentPromise. */
42
- paymentPromiseId: z.string().min(1).optional(),
43
- agentType: agentTypeSchema,
44
- contactedAt: z.string().min(1),
45
- durationSeconds: z.number().int().nonnegative().optional(),
46
- outcome: contactOutcomeSchema,
47
- notes: z.string().optional(),
48
- debtAmountSnapshot: z.number().nonnegative().optional(),
49
- aiSummary: z.string().optional(),
50
- aiSentiment: aiSentimentSchema.optional(),
51
- aiDebtReason: z.string().optional(),
52
- aiResult: z.string().optional(),
53
- aiNextStep: z.string().optional(),
54
- intentMetadata: z.record(z.string(), z.unknown()).optional(),
55
- channelData: z.record(z.string(), z.unknown()).optional(),
56
- /**
57
- * Provider call ref (voice) / message sid (sms) for the dispatch-time attempt.
58
- * When present, `recordOutcome` upserts the gestión keyed by it (one row per
59
- * attempt, enriched by the async callback) instead of inserting a duplicate.
60
- */
61
- providerRef: z.string().min(1).optional()
62
- });
63
- export type CreateContactLogInput = z.infer<typeof createContactLogSchema>;
64
-
65
- /**
66
- * Input to reserve a campaign attempt before the provider call (the engine's
67
- * at-most-once step). Increments the attempt counters; writes no gestión.
68
- */
69
- export const reserveAttemptSchema = z.object({
70
- campaignId: z.string().min(1).optional(),
71
- portfolioAccountId: z.string().min(1),
72
- /** When the attempt is being made (ISO). */
73
- at: z.string().min(1)
74
- });
75
- export type ReserveAttemptInput = z.infer<typeof reserveAttemptSchema>;
76
-
77
- /**
78
- * Operator resolution of a payment promise. A promise leaves PENDING only by explicit
79
- * action: `MET` (paid — v1 is manual-only, no trusted payment signal) or `CANCELLED`.
80
- * `EXPIRED` is set by the system when the account leaves its portfolio, not here.
81
- */
82
- export const updatePaymentPromiseSchema = z.object({
83
- id: z.string().min(1),
84
- status: z.enum(["MET", "CANCELLED"])
85
- });
86
- export type UpdatePaymentPromiseInput = z.infer<typeof updatePaymentPromiseSchema>;
87
-
88
- /**
89
- * Follow up on a payment promise with an ad-hoc agent dispatch (no campaign). Writes a
90
- * gestión with `campaignId` null, the chosen `agentTemplateId`, and a link to the promise.
91
- */
92
- export const followUpPaymentPromiseSchema = z.object({
93
- paymentPromiseId: z.string().min(1),
94
- agentTemplateId: z.string().min(1)
95
- });
96
- export type FollowUpPaymentPromiseInput = z.infer<typeof followUpPaymentPromiseSchema>;
@@ -1,37 +0,0 @@
1
- import { z } from "zod";
2
-
3
- /**
4
- * The structured decision the EMAIL autopilot returns for an inbound reply. Validated so a
5
- * model can't drive the loop with malformed output. `outcome` mirrors the contact-log
6
- * outcomes; `objective` carries promise details when the reply implies one.
7
- */
8
- export const emailAutopilotDecisionSchema = z.object({
9
- action: z.enum(["reply", "ignore", "resolve", "escalate"]),
10
- replyBody: z.string().optional(),
11
- outcome: z.string().optional(),
12
- objective: z
13
- .object({
14
- type: z.string(),
15
- amount: z.number().optional(),
16
- dueDate: z.string().optional(),
17
- note: z.string().optional()
18
- })
19
- .nullish()
20
- });
21
-
22
- /**
23
- * Normalized inbound email from the provider webhook. The provider payload is mapped to
24
- * this before ingestion so the function stays provider-agnostic.
25
- */
26
- export const inboundEmailSchema = z.object({
27
- from: z.string().min(1),
28
- to: z.array(z.string()).default([]),
29
- subject: z.string().optional(),
30
- text: z.string().default(""),
31
- messageId: z.string().optional(),
32
- inReplyTo: z.string().optional(),
33
- references: z.array(z.string()).optional(),
34
- headers: z.record(z.string(), z.string()).optional()
35
- });
36
-
37
- export type InboundEmailInput = z.infer<typeof inboundEmailSchema>;
@@ -1,49 +0,0 @@
1
- import { z } from "zod";
2
-
3
- export const createPortfolioSchema = z.object({
4
- name: z.string().min(1).max(120),
5
- clientId: z.string().min(1).max(120)
6
- });
7
- export type CreatePortfolioInput = z.infer<typeof createPortfolioSchema>;
8
-
9
- export const updatePortfolioSchema = z.object({
10
- id: z.string().min(1),
11
- name: z.string().min(1).max(120).optional(),
12
- // `archived` toggles the portfolio's archived state: true sets `archivedAt` to
13
- // now, false clears it (restore). There is no separate status concept.
14
- archived: z.boolean().optional()
15
- });
16
- export type UpdatePortfolioInput = z.infer<typeof updatePortfolioSchema>;
17
-
18
- export const deletePortfolioSchema = z.object({
19
- id: z.string().min(1)
20
- });
21
- export type DeletePortfolioInput = z.infer<typeof deletePortfolioSchema>;
22
-
23
- export const accountRowSchema = z.object({
24
- externalId: z.string().min(1),
25
- fullName: z.string().min(1),
26
- phone: z.string().optional(),
27
- email: z.string().email().optional(),
28
- preferredLanguage: z.string().optional(),
29
- bestTimeToCall: z.string().optional(),
30
- customerSegment: z.string().optional(),
31
- principalAmount: z.number().nonnegative().default(0),
32
- termsAmount: z.number().nonnegative().default(0),
33
- termsFrequency: z.string().optional(),
34
- termsLength: z.number().int().nonnegative().default(0),
35
- outstandingBalance: z.number().nonnegative(),
36
- daysPastDue: z.number().int().nonnegative().default(0),
37
- missedInstallments: z.number().int().nonnegative().default(0),
38
- lastPaymentDate: z.string().optional(),
39
- lastPaymentAmount: z.number().nonnegative().optional(),
40
- negotiationOptions: z.string().optional()
41
- });
42
- export type AccountRowInput = z.infer<typeof accountRowSchema>;
43
-
44
- export const syncAccountsInputSchema = z.object({
45
- portfolioId: z.string().min(1),
46
- mode: z.enum(["APPEND_ONLY", "UPDATE_EXISTING", "REPLACE"]),
47
- rows: z.array(accountRowSchema).min(1)
48
- });
49
- export type SyncAccountsInput = z.infer<typeof syncAccountsInputSchema>;
@@ -1,7 +0,0 @@
1
- import { z } from "zod";
2
-
3
- export const updateProfileSchema = z.object({
4
- name: z.string().min(1).max(60).optional(),
5
- phone: z.string().max(20).optional()
6
- });
7
- export type UpdateProfileInput = z.infer<typeof updateProfileSchema>;
@@ -1,45 +0,0 @@
1
- import { z } from "zod";
2
-
3
- /**
4
- * Events emitted by the Fonoster autopilot events-hook for a Voz IA call.
5
- * `conversation.started` lets us capture partial data even if the call never ends
6
- * cleanly; `conversation.ended` carries the transcript and recording.
7
- */
8
- export const voiceEventTypeSchema = z.enum(["conversation.started", "conversation.ended"]);
9
- export type VoiceEventType = z.infer<typeof voiceEventTypeSchema>;
10
-
11
- /**
12
- * A raw chat-history entry from the autopilot: `{ ai: text }` (our agent) or
13
- * `{ human: text }` (the customer). Kept permissive — only the ai/human keys are read.
14
- */
15
- export const voiceChatMessageSchema = z.record(z.string(), z.unknown());
16
-
17
- export const voiceConversationEventSchema = z.object({
18
- eventType: voiceEventTypeSchema,
19
- appRef: z.string().min(1),
20
- callRef: z.string().min(1),
21
- phone: z.string().min(1),
22
- chatHistory: z.array(voiceChatMessageSchema).optional(),
23
- recordingUrl: z.string().optional(),
24
- durationSeconds: z.number().int().nonnegative().optional()
25
- });
26
- export type VoiceConversationEvent = z.infer<typeof voiceConversationEventSchema>;
27
-
28
- /** A normalized transcript line stored in `channelData.transcript` for the console. */
29
- export interface TranscriptLine {
30
- role: "agent" | "customer";
31
- text: string;
32
- }
33
-
34
- /** Normalize autopilot chatHistory into ordered console transcript lines. */
35
- export function normalizeChatHistory(
36
- chatHistory: ReadonlyArray<Record<string, unknown>> | undefined
37
- ): TranscriptLine[] {
38
- if (!chatHistory) return [];
39
- const lines: TranscriptLine[] = [];
40
- for (const entry of chatHistory) {
41
- if (typeof entry.ai === "string") lines.push({ role: "agent", text: entry.ai });
42
- else if (typeof entry.human === "string") lines.push({ role: "customer", text: entry.human });
43
- }
44
- return lines;
45
- }
@@ -1,101 +0,0 @@
1
- import { z } from "zod";
2
-
3
- /**
4
- * WhatsApp integration contracts: the per-workspace WABA credentials and its sender
5
- * numbers, plus the inbound Meta webhook body. This is QCobro's first tenant-provided
6
- * secret — the `accessToken` is encrypted at rest (cloak) and never returned to clients.
7
- *
8
- * The webhook schema is a focused port of `../mikro/mods/common/src/schemas/whatsapp.ts`,
9
- * trimmed to what QCobro ingests (customer messages, delivery/opt-out statuses) and
10
- * extended with `metadata.phone_number_id` so events resolve to a workspace/sender.
11
- */
12
-
13
- /** What a sender number can do. `messaging` now; `calling` reserved for WhatsApp Voice (future). */
14
- export const whatsAppCapabilitiesSchema = z.object({
15
- messaging: z.boolean(),
16
- calling: z.boolean()
17
- });
18
- export type WhatsAppCapabilities = z.infer<typeof whatsAppCapabilitiesSchema>;
19
-
20
- /** Connect (or update) the workspace's WABA. The token is the tenant secret. */
21
- export const upsertWhatsAppIntegrationSchema = z.object({
22
- wabaId: z.string().min(1),
23
- accessToken: z.string().min(1),
24
- /** Token echoed back during Meta's webhook verify-token handshake. */
25
- verifyToken: z.string().min(1),
26
- /** Meta template-send language for this workspace (e.g. `es_DO`); the single source for
27
- * the WhatsApp send language. Kept with the WhatsApp config rather than in WorkspaceSettings. */
28
- defaultLanguage: z.string().min(1)
29
- });
30
- export type UpsertWhatsAppIntegrationInput = z.infer<typeof upsertWhatsAppIntegrationSchema>;
31
-
32
- /** Add a sender number to the workspace's integration. */
33
- export const addWhatsAppSenderNumberSchema = z.object({
34
- /** Meta per-number messaging endpoint id. Globally unique across the deployment. */
35
- phoneNumberId: z.string().min(1),
36
- /** E.164 display number for the UI. */
37
- displayNumber: z.string().min(1),
38
- /** Operator label, e.g. "Cobranza Suave". */
39
- label: z.string().min(1)
40
- });
41
- export type AddWhatsAppSenderNumberInput = z.infer<typeof addWhatsAppSenderNumberSchema>;
42
-
43
- export const removeWhatsAppSenderNumberSchema = z.object({
44
- phoneNumberId: z.string().min(1)
45
- });
46
- export type RemoveWhatsAppSenderNumberInput = z.infer<typeof removeWhatsAppSenderNumberSchema>;
47
-
48
- // ── Inbound webhook body (Meta Cloud API) ─────────────────────────────────────
49
-
50
- const whatsAppInboundMessageSchema = z.object({
51
- from: z.string(),
52
- id: z.string(),
53
- timestamp: z.string(),
54
- type: z.string(),
55
- text: z.object({ body: z.string() }).optional()
56
- });
57
-
58
- /** Delivery/read/opt-out status callbacks. `errors` carries opt-out/block signals (code 131050 etc.). */
59
- const whatsAppStatusSchema = z.object({
60
- id: z.string(),
61
- status: z.string(),
62
- recipient_id: z.string().optional(),
63
- timestamp: z.string().optional(),
64
- errors: z
65
- .array(z.object({ code: z.number().optional(), title: z.string().optional() }))
66
- .optional()
67
- });
68
-
69
- const whatsAppChangeValueSchema = z.object({
70
- messaging_product: z.string().optional(),
71
- metadata: z
72
- .object({
73
- display_phone_number: z.string().optional(),
74
- /** Resolves the event to a `WhatsAppSenderNumber` (and thus a workspace). */
75
- phone_number_id: z.string()
76
- })
77
- .optional(),
78
- messages: z.array(whatsAppInboundMessageSchema).optional(),
79
- statuses: z.array(whatsAppStatusSchema).optional(),
80
- // Quality-rating callbacks: phone_number_id is at the value root, not under metadata.
81
- phone_number_id: z.string().optional(),
82
- event: z.string().optional(),
83
- new_quality_rating: z.string().optional()
84
- });
85
-
86
- const whatsAppChangeSchema = z.object({
87
- field: z.string().optional(),
88
- value: whatsAppChangeValueSchema.optional()
89
- });
90
-
91
- const whatsAppEntrySchema = z.object({
92
- id: z.string().optional(),
93
- changes: z.array(whatsAppChangeSchema).optional()
94
- });
95
-
96
- /** The full inbound webhook body. Lenient on unknown fields Meta may add. */
97
- export const whatsAppWebhookSchema = z.object({
98
- object: z.string().optional(),
99
- entry: z.array(whatsAppEntrySchema).optional()
100
- });
101
- export type WhatsAppWebhookBody = z.infer<typeof whatsAppWebhookSchema>;
@@ -1,53 +0,0 @@
1
- import { z } from "zod";
2
- import { currencySchema } from "./workspaceSettings.js";
3
-
4
- export const createWorkspaceSchema = z.object({
5
- name: z.string().min(1).max(60),
6
- currency: currencySchema,
7
- timezone: z.string().min(1)
8
- });
9
- export type CreateWorkspaceInput = z.infer<typeof createWorkspaceSchema>;
10
-
11
- export const getWorkspaceSchema = z.object({
12
- ref: z.string().min(1)
13
- });
14
- export type GetWorkspaceInput = z.infer<typeof getWorkspaceSchema>;
15
-
16
- export const updateWorkspaceSchema = z.object({
17
- ref: z.string().min(1),
18
- name: z.string().min(1).max(60)
19
- });
20
- export type UpdateWorkspaceInput = z.infer<typeof updateWorkspaceSchema>;
21
-
22
- export const deleteWorkspaceSchema = z.object({
23
- ref: z.string().min(1)
24
- });
25
- export type DeleteWorkspaceInput = z.infer<typeof deleteWorkspaceSchema>;
26
-
27
- export const workspaceRoleEnum = z.enum(["WORKSPACE_ADMIN", "WORKSPACE_MEMBER"]);
28
- export type WorkspaceRole = z.infer<typeof workspaceRoleEnum>;
29
-
30
- export const inviteMemberSchema = z.object({
31
- email: z.email(),
32
- role: workspaceRoleEnum.default("WORKSPACE_MEMBER"),
33
- // Identity's inviteUserToWorkspace requires a name; keep the apiserver
34
- // contract in sync so a missing name fails validation with a clear message
35
- // instead of an opaque gRPC error.
36
- name: z.string().min(1).max(60)
37
- });
38
- export type InviteMemberInput = z.infer<typeof inviteMemberSchema>;
39
-
40
- export const removeMemberSchema = z.object({
41
- userRef: z.string().min(1)
42
- });
43
- export type RemoveMemberInput = z.infer<typeof removeMemberSchema>;
44
-
45
- export const resendInvitationSchema = z.object({
46
- userRef: z.string().min(1)
47
- });
48
- export type ResendInvitationInput = z.infer<typeof resendInvitationSchema>;
49
-
50
- export const acceptInvitationSchema = z.object({
51
- token: z.string().min(1)
52
- });
53
- export type AcceptInvitationInput = z.infer<typeof acceptInvitationSchema>;
@@ -1,104 +0,0 @@
1
- import type {
2
- AgentType,
3
- CreateAgentTemplateInput,
4
- UpdateAgentTemplateInput,
5
- DeleteAgentTemplateInput
6
- } from "../schemas/agentTemplates.js";
7
-
8
- export interface AgentTemplateRecord {
9
- id: string;
10
- workspaceRef: string;
11
- name: string;
12
- type: AgentType;
13
- archivedAt: Date | null;
14
- createdAt: Date;
15
- updatedAt: Date;
16
- }
17
-
18
- export interface VoiceAiConfigRecord {
19
- templateId: string;
20
- fonosterAppName: string;
21
- fonosterAppRef: string | null;
22
- voice: string;
23
- systemPrompt: string;
24
- firstMessage: string | null;
25
- language: string;
26
- }
27
-
28
- export interface VoicePrerecordedConfigRecord {
29
- templateId: string;
30
- fonosterAppName: string;
31
- fonosterAppRef: string | null;
32
- voice: string;
33
- script: string;
34
- language: string;
35
- }
36
-
37
- export interface SmsConfigRecord {
38
- templateId: string;
39
- messageBody: string;
40
- senderId: string | null;
41
- }
42
-
43
- export interface EmailConfigRecord {
44
- templateId: string;
45
- subject: string;
46
- messageBody: string;
47
- fromName: string;
48
- fromEmail: string;
49
- }
50
-
51
- export interface WhatsAppConfigRecord {
52
- templateId: string;
53
- templateName: string;
54
- messageBody: string;
55
- }
56
-
57
- /** A child-config delegate exposing the create/read/update calls the functions use. */
58
- interface ChildConfigDelegate<R> {
59
- create(args: { data: Record<string, unknown> }): Promise<R>;
60
- update(args: { where: { templateId: string }; data: Record<string, unknown> }): Promise<R>;
61
- findUnique(args: { where: { templateId: string } }): Promise<R | null>;
62
- }
63
-
64
- export interface AgentTemplateClient {
65
- agentTemplate: {
66
- findMany(args: {
67
- where: { workspaceRef: string; type?: AgentType; archivedAt?: Date | null };
68
- orderBy?: { createdAt: "asc" | "desc" };
69
- }): Promise<AgentTemplateRecord[]>;
70
-
71
- findFirst(args: {
72
- where: { id: string; workspaceRef: string };
73
- }): Promise<AgentTemplateRecord | null>;
74
-
75
- findFirstOrThrow(args: {
76
- where: { id: string; workspaceRef: string };
77
- }): Promise<AgentTemplateRecord>;
78
-
79
- create(args: { data: Record<string, unknown> }): Promise<AgentTemplateRecord>;
80
-
81
- update(args: {
82
- where: { id: string };
83
- data: Record<string, unknown>;
84
- }): Promise<AgentTemplateRecord>;
85
-
86
- delete(args: { where: { id: string } }): Promise<AgentTemplateRecord>;
87
- };
88
-
89
- voiceAiConfig: ChildConfigDelegate<VoiceAiConfigRecord>;
90
- voicePrerecordedConfig: ChildConfigDelegate<VoicePrerecordedConfigRecord>;
91
- smsConfig: ChildConfigDelegate<SmsConfigRecord>;
92
- emailConfig: ChildConfigDelegate<EmailConfigRecord>;
93
- whatsAppConfig: ChildConfigDelegate<WhatsAppConfigRecord>;
94
-
95
- campaign: {
96
- count(args: {
97
- where: { agentTemplateId: string; status?: { not: "ARCHIVED" } };
98
- }): Promise<number>;
99
- };
100
-
101
- $transaction<T>(fn: (tx: AgentTemplateClient) => Promise<T>): Promise<T>;
102
- }
103
-
104
- export type { CreateAgentTemplateInput, UpdateAgentTemplateInput, DeleteAgentTemplateInput };