@pithy-sh/support 0.5.1 → 0.6.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.
Files changed (173) hide show
  1. package/README.md +8 -0
  2. package/dist/audit/actions.d.ts +9 -0
  3. package/dist/audit/actions.d.ts.map +1 -1
  4. package/dist/audit/actions.js +9 -0
  5. package/dist/capability.d.ts +2 -1
  6. package/dist/capability.d.ts.map +1 -1
  7. package/dist/capability.js +30 -6
  8. package/dist/config/config.d.ts +63 -2
  9. package/dist/config/config.d.ts.map +1 -1
  10. package/dist/config/config.js +63 -5
  11. package/dist/data/assignment.d.ts +43 -0
  12. package/dist/data/assignment.d.ts.map +1 -0
  13. package/dist/data/assignment.js +38 -0
  14. package/dist/data/embedding.d.ts +21 -0
  15. package/dist/data/embedding.d.ts.map +1 -0
  16. package/dist/data/embedding.js +23 -0
  17. package/dist/data/tables.d.ts +28 -0
  18. package/dist/data/tables.d.ts.map +1 -1
  19. package/dist/data/tables.js +10 -2
  20. package/dist/data/thread.d.ts +9 -4
  21. package/dist/data/thread.d.ts.map +1 -1
  22. package/dist/data/thread.js +9 -4
  23. package/dist/http/guards.d.ts +32 -14
  24. package/dist/http/guards.d.ts.map +1 -1
  25. package/dist/http/guards.js +44 -16
  26. package/dist/http/handlers.d.ts +35 -2
  27. package/dist/http/handlers.d.ts.map +1 -1
  28. package/dist/http/handlers.js +81 -8
  29. package/dist/http/resolve.d.ts +8 -0
  30. package/dist/http/resolve.d.ts.map +1 -1
  31. package/dist/http/resolve.js +20 -1
  32. package/dist/http/responses.d.ts +355 -0
  33. package/dist/http/responses.d.ts.map +1 -1
  34. package/dist/http/responses.js +64 -2
  35. package/dist/http/routes.d.ts +25 -11
  36. package/dist/http/routes.d.ts.map +1 -1
  37. package/dist/http/routes.js +34 -5
  38. package/dist/http/schemas.d.ts +67 -3
  39. package/dist/http/schemas.d.ts.map +1 -1
  40. package/dist/http/schemas.js +44 -5
  41. package/dist/http/scopes.d.ts +10 -5
  42. package/dist/http/scopes.d.ts.map +1 -1
  43. package/dist/http/scopes.js +42 -6
  44. package/dist/http/views.d.ts +9 -1
  45. package/dist/http/views.d.ts.map +1 -1
  46. package/dist/http/views.js +40 -1
  47. package/dist/inbound/ingest.d.ts +1 -1
  48. package/dist/inbound/ingest.d.ts.map +1 -1
  49. package/dist/inbound/ingest.js +3 -1
  50. package/dist/index.d.ts +5 -3
  51. package/dist/index.d.ts.map +1 -1
  52. package/dist/index.js +6 -4
  53. package/dist/migrations/0002_assignment.d.ts +20 -0
  54. package/dist/migrations/0002_assignment.d.ts.map +1 -0
  55. package/dist/migrations/0002_assignment.js +45 -0
  56. package/dist/migrations/0003_embeddings.d.ts +15 -0
  57. package/dist/migrations/0003_embeddings.d.ts.map +1 -0
  58. package/dist/migrations/0003_embeddings.js +23 -0
  59. package/dist/migrations/set.d.ts +13 -0
  60. package/dist/migrations/set.d.ts.map +1 -0
  61. package/dist/migrations/set.js +21 -0
  62. package/dist/presence/room.d.ts +35 -0
  63. package/dist/presence/room.d.ts.map +1 -0
  64. package/dist/presence/room.js +66 -0
  65. package/dist/provision/provisionSupport.d.ts +32 -0
  66. package/dist/provision/provisionSupport.d.ts.map +1 -1
  67. package/dist/provision/provisionSupport.js +10 -2
  68. package/dist/provision/resolveSupportConfig.d.ts.map +1 -1
  69. package/dist/provision/resolveSupportConfig.js +13 -2
  70. package/dist/purge/contribution.d.ts +49 -0
  71. package/dist/purge/contribution.d.ts.map +1 -0
  72. package/dist/purge/contribution.js +164 -0
  73. package/dist/secret/registry.d.ts +26 -2
  74. package/dist/secret/registry.d.ts.map +1 -1
  75. package/dist/secret/registry.js +15 -3
  76. package/dist/semantic/documents.d.ts +21 -0
  77. package/dist/semantic/documents.d.ts.map +1 -0
  78. package/dist/semantic/documents.js +128 -0
  79. package/dist/semantic/embed.d.ts +59 -0
  80. package/dist/semantic/embed.d.ts.map +1 -0
  81. package/dist/semantic/embed.js +59 -0
  82. package/dist/semantic/messageIndex.d.ts +46 -0
  83. package/dist/semantic/messageIndex.d.ts.map +1 -0
  84. package/dist/semantic/messageIndex.js +67 -0
  85. package/dist/semantic/query.d.ts +37 -0
  86. package/dist/semantic/query.d.ts.map +1 -0
  87. package/dist/semantic/query.js +46 -0
  88. package/dist/staff/staff.d.ts +22 -0
  89. package/dist/staff/staff.d.ts.map +1 -0
  90. package/dist/staff/staff.js +64 -0
  91. package/dist/store/assignment.d.ts +63 -0
  92. package/dist/store/assignment.d.ts.map +1 -0
  93. package/dist/store/assignment.js +86 -0
  94. package/dist/store/hybrid.d.ts +134 -0
  95. package/dist/store/hybrid.d.ts.map +1 -0
  96. package/dist/store/hybrid.js +185 -0
  97. package/dist/store/paging.d.ts +10 -0
  98. package/dist/store/paging.d.ts.map +1 -1
  99. package/dist/store/paging.js +11 -1
  100. package/dist/store/provisionIndex.d.ts +21 -0
  101. package/dist/store/provisionIndex.d.ts.map +1 -0
  102. package/dist/store/provisionIndex.js +36 -0
  103. package/dist/store/search.d.ts +18 -9
  104. package/dist/store/search.d.ts.map +1 -1
  105. package/dist/store/search.js +36 -34
  106. package/dist/store/searchIndex.d.ts +4 -4
  107. package/dist/store/searchIndex.js +4 -4
  108. package/dist/store/threads.d.ts +174 -8
  109. package/dist/store/threads.d.ts.map +1 -1
  110. package/dist/store/threads.js +33 -40
  111. package/dist/submission/submit.d.ts +1 -1
  112. package/dist/submission/submit.d.ts.map +1 -1
  113. package/dist/submission/submit.js +2 -1
  114. package/dist/test-utils/seed.d.ts +33 -0
  115. package/dist/test-utils/seed.d.ts.map +1 -0
  116. package/dist/test-utils/seed.js +102 -0
  117. package/dist/test-utils/semantic.d.ts +21 -0
  118. package/dist/test-utils/semantic.d.ts.map +1 -0
  119. package/dist/test-utils/semantic.js +107 -0
  120. package/dist/version.generated.d.ts +1 -1
  121. package/dist/version.generated.js +1 -1
  122. package/dist/workflows/specs.d.ts +23 -0
  123. package/dist/workflows/specs.d.ts.map +1 -1
  124. package/dist/workflows/specs.js +27 -7
  125. package/dist/workflows/worker.d.ts +15 -2
  126. package/dist/workflows/worker.d.ts.map +1 -1
  127. package/dist/workflows/worker.js +48 -4
  128. package/package.json +9 -7
  129. package/pithy.manifest.json +21 -3
  130. package/src/audit/actions.ts +9 -0
  131. package/src/capability.ts +43 -4
  132. package/src/config/config.ts +104 -5
  133. package/src/data/assignment.ts +55 -0
  134. package/src/data/embedding.ts +27 -0
  135. package/src/data/tables.ts +8 -0
  136. package/src/data/thread.ts +26 -4
  137. package/src/http/guards.ts +52 -15
  138. package/src/http/handlers.ts +125 -4
  139. package/src/http/resolve.ts +19 -0
  140. package/src/http/responses.ts +154 -0
  141. package/src/http/routes.ts +98 -12
  142. package/src/http/schemas.ts +117 -28
  143. package/src/http/scopes.ts +43 -6
  144. package/src/http/views.ts +44 -0
  145. package/src/inbound/ingest.ts +5 -2
  146. package/src/index.ts +5 -0
  147. package/src/migrations/0002_assignment.ts +65 -0
  148. package/src/migrations/0003_embeddings.ts +29 -0
  149. package/src/migrations/set.ts +21 -0
  150. package/src/presence/room.ts +94 -0
  151. package/src/provision/provisionSupport.ts +33 -1
  152. package/src/provision/resolveSupportConfig.ts +24 -13
  153. package/src/purge/contribution.ts +294 -0
  154. package/src/secret/registry.ts +17 -2
  155. package/src/semantic/documents.ts +178 -0
  156. package/src/semantic/embed.ts +99 -0
  157. package/src/semantic/messageIndex.ts +74 -0
  158. package/src/semantic/query.ts +66 -0
  159. package/src/staff/staff.ts +128 -0
  160. package/src/store/assignment.ts +179 -0
  161. package/src/store/hybrid.ts +314 -0
  162. package/src/store/paging.ts +14 -0
  163. package/src/store/provisionIndex.ts +46 -0
  164. package/src/store/search.ts +58 -37
  165. package/src/store/searchIndex.ts +4 -4
  166. package/src/store/threads.ts +91 -91
  167. package/src/submission/submit.ts +3 -2
  168. package/src/test-utils/seed.ts +141 -0
  169. package/src/test-utils/semantic.ts +110 -0
  170. package/src/version.generated.ts +1 -1
  171. package/src/workflows/specs.ts +34 -0
  172. package/src/workflows/worker.ts +84 -8
  173. package/src/workflows/wrangler.jsonc +8 -3
@@ -4,15 +4,23 @@
4
4
  import { WorkflowEntrypoint, type WorkflowEvent, type WorkflowStep } from "cloudflare:workers";
5
5
  import { NonRetryableError } from "cloudflare:workflows";
6
6
  import type { D1Database } from "@cloudflare/workers-types";
7
+ import { pithyCommandOf } from "@pithy-sh/core/src/cli/command";
8
+ import { createWorkerLogger } from "@pithy-sh/core/src/logger/worker";
7
9
  import { classifiedSteps } from "@pithy-sh/core/src/workflow/faults";
8
10
  import { workflowHostEntry } from "@pithy-sh/core/src/workflow/hostEntry";
11
+ import type { VectorAi } from "@pithy-sh/vector/src/embed/embed";
12
+ import type { VectorStore } from "@pithy-sh/vector/src/index/index";
13
+ import { type ReprocessReport, reprocessIndex } from "@pithy-sh/vector/src/workflows/reprocess";
9
14
  import type { SupportAi } from "../ai/classify";
10
15
  import { SupportConfig } from "../config/config";
11
16
  import { resolveCategories } from "../data/categories";
12
17
  import { supportDatabase } from "../data/tables";
18
+ import { supportMessageDocuments } from "../semantic/documents";
19
+ import { runEmbedding } from "../semantic/embed";
20
+ import { supportMessageIndex } from "../semantic/messageIndex";
13
21
  import { runClassification } from "./classify";
14
22
  import { supportWorkflowRetry } from "./retryPolicy";
15
- import { SUPPORT_CAPABILITY } from "./specs";
23
+ import { SUPPORT_CAPABILITY, SupportReprocessParams } from "./specs";
16
24
 
17
25
  /**
18
26
  * The prebuilt support worker. `pithy support provision` deploys one per environment; the adopter
@@ -35,20 +43,27 @@ import { SUPPORT_CAPABILITY } from "./specs";
35
43
  * `@pithy-sh/core/src/workflow/hostEntry`.
36
44
  */
37
45
 
38
- /** The support worker's env: the app database, the AI binding, and the serialized config. */
46
+ /** The support worker's env: the app database, the AI binding, the message index, and the serialized config. */
39
47
  export interface SupportWorkerEnv {
40
48
  /** The app database the support tables live in. */
41
49
  DB: D1Database;
42
- /** The Workers AI binding. */
50
+ /** The Workers AI binding — classification and embedding both run on it. */
43
51
  AI: SupportAi;
52
+ /** The semantic message index. Bound only when `search.semantic` is on. */
53
+ SUPPORT_VECTORIZE?: VectorStore;
44
54
  /** The resolved support config as a JSON string, filled at provision. */
45
55
  SUPPORT_CONFIG?: string;
46
56
  }
47
57
 
58
+ /** Parse the config this worker was deployed with. Absent falls back to the defaults. */
59
+ function workerConfig(env: SupportWorkerEnv): SupportConfig {
60
+ return SupportConfig.parse(env.SUPPORT_CONFIG ? JSON.parse(env.SUPPORT_CONFIG) : {});
61
+ }
62
+
48
63
  /** Classify one stored message and write the result. */
49
64
  export class SupportClassifyWorkflow extends WorkflowEntrypoint<SupportWorkerEnv, { messageId: string }> {
50
65
  override async run(event: WorkflowEvent<{ messageId: string }>, step: WorkflowStep): Promise<void> {
51
- const config = SupportConfig.parse(this.env.SUPPORT_CONFIG ? JSON.parse(this.env.SUPPORT_CONFIG) : {});
66
+ const config = workerConfig(this.env);
52
67
  const deps = {
53
68
  db: supportDatabase(this.env.DB),
54
69
  ai: this.env.AI,
@@ -65,10 +80,71 @@ export class SupportClassifyWorkflow extends WorkflowEntrypoint<SupportWorkerEnv
65
80
  // Under `supportWorkflowRetry`: a model that could not be reached re-drives, and everything else
66
81
  // fails at once. `classifyMessage` already refuses to throw on a bad *answer*, so the only fault
67
82
  // that reaches this classifier as retryable is the binding not answering. See `retryPolicy.ts`.
68
- await classifiedSteps(step, supportWorkflowRetry, NonRetryableError).do(
69
- `classify-${event.payload.messageId}`,
70
- async () => {
71
- await runClassification(deps, event.payload.messageId);
83
+ if (config.ai.enabled) {
84
+ await classifiedSteps(step, supportWorkflowRetry, NonRetryableError).do(
85
+ `classify-${event.payload.messageId}`,
86
+ async () => {
87
+ await runClassification(deps, event.payload.messageId);
88
+ },
89
+ );
90
+ }
91
+
92
+ // Then the message index, when semantic search is on. Its own step, after the classification, and
93
+ // never fatal: `runEmbedding` reports a failure rather than throwing it, so the message stays stored and
94
+ // classified and is missing from semantic results only, until a reprocess picks it up.
95
+ const index = supportMessageIndex(config.search);
96
+ if (index) {
97
+ // Through the classifier like every step, though `runEmbedding` reports a failure rather than throwing one.
98
+ await classifiedSteps(step, supportWorkflowRetry, NonRetryableError).do(`embed-${event.payload.messageId}`, () =>
99
+ runEmbedding(
100
+ {
101
+ db: deps.db,
102
+ ai: this.env.AI as unknown as VectorAi,
103
+ store: this.env.SUPPORT_VECTORIZE,
104
+ index,
105
+ now: () => new Date(),
106
+ log: createWorkerLogger({ name: `${SUPPORT_CAPABILITY}:embed` }),
107
+ },
108
+ event.payload.messageId,
109
+ ),
110
+ );
111
+ }
112
+ }
113
+ }
114
+
115
+ /**
116
+ * Re-embed the semantic message index — `@pithy-sh/vector`'s own reprocess orchestration, over support's
117
+ * `DocumentStore`, one journalled page per step. `pithy vector reprocess --index support-messages` starts it,
118
+ * and so does `pithy support provision` once, to backfill an index it just created.
119
+ */
120
+ export class SupportReprocessWorkflow extends WorkflowEntrypoint<SupportWorkerEnv, SupportReprocessParams> {
121
+ override async run(event: WorkflowEvent<SupportReprocessParams>, step: WorkflowStep): Promise<ReprocessReport> {
122
+ const params = SupportReprocessParams.parse(event.payload);
123
+ const index = supportMessageIndex(workerConfig(this.env).search);
124
+ if (!index) {
125
+ throw new NonRetryableError(
126
+ "support/reprocess: search.semantic is off in this worker's config, so there is no message index to re-embed",
127
+ );
128
+ }
129
+ const store = this.env.SUPPORT_VECTORIZE;
130
+ if (!store) {
131
+ throw new NonRetryableError(
132
+ `support/reprocess: the SUPPORT_VECTORIZE binding is absent; run \`${pithyCommandOf("support provision", {}, { runtime: true })}\` to bind the index`,
133
+ );
134
+ }
135
+ return reprocessIndex(
136
+ {
137
+ documents: supportMessageDocuments(supportDatabase(this.env.DB), { store }),
138
+ store,
139
+ ai: this.env.AI as unknown as VectorAi,
140
+ index,
141
+ indexName: params.index,
142
+ now: () => new Date(),
143
+ },
144
+ classifiedSteps(step, supportWorkflowRetry, NonRetryableError),
145
+ {
146
+ ...(params.all !== undefined ? { all: params.all } : {}),
147
+ ...(params.pageSize !== undefined ? { pageSize: params.pageSize } : {}),
72
148
  },
73
149
  );
74
150
  }
@@ -30,10 +30,15 @@
30
30
  // and their customers' support mail never leaves their account.
31
31
  "ai": { "binding": "AI" },
32
32
 
33
- // The classification Workflow this worker hosts. `class_name` matches the exported
34
- // WorkflowEntrypoint subclass; `binding` is what the app worker dispatches to after storing a message.
33
+ // The Workflows this worker hosts. `class_name` matches the exported WorkflowEntrypoint subclass;
34
+ // `SUPPORT_CLASSIFY` is what the app worker dispatches to after storing a message, and `SUPPORT_REPROCESS`
35
+ // re-embeds the semantic message index when `pithy vector reprocess --index support-messages` starts it.
36
+ // When `search.semantic` is on, provisioning adds a `vectorize` entry binding `SUPPORT_VECTORIZE` to this
37
+ // environment's `<project>-<env>-support-messages` index; the template carries none, because most inboxes
38
+ // have no index.
35
39
  "workflows": [
36
- { "binding": "SUPPORT_CLASSIFY", "name": "pithy-support-classify", "class_name": "SupportClassifyWorkflow" }
40
+ { "binding": "SUPPORT_CLASSIFY", "name": "pithy-support-classify", "class_name": "SupportClassifyWorkflow" },
41
+ { "binding": "SUPPORT_REPROCESS", "name": "pithy-support-reprocess", "class_name": "SupportReprocessWorkflow" }
37
42
  ],
38
43
 
39
44
  "vars": {