@opengeni/worker-bundle 1.0.0-canary.1 → 1.0.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 (244) hide show
  1. package/dist/activities/agent-run-admission.d.ts +3 -1
  2. package/dist/activities/agent-turn/admission.d.ts +24 -3
  3. package/dist/activities/agent-turn/agent-build.d.ts +4 -0
  4. package/dist/activities/agent-turn/claude-usage-observer.d.ts +58 -0
  5. package/dist/activities/agent-turn/code-search.d.ts +60 -0
  6. package/dist/activities/agent-turn/codex-capacity.d.ts +13 -0
  7. package/dist/activities/agent-turn/codex-plan-entitlement.d.ts +105 -0
  8. package/dist/activities/agent-turn/codex.d.ts +3 -2
  9. package/dist/activities/agent-turn/compaction-prep.d.ts +21 -5
  10. package/dist/activities/agent-turn/credential-leases.d.ts +19 -33
  11. package/dist/activities/agent-turn/credential-restriction.d.ts +3 -0
  12. package/dist/activities/agent-turn/errors.d.ts +82 -11
  13. package/dist/activities/agent-turn/failure-settlement.d.ts +6 -3
  14. package/dist/activities/agent-turn/final-reply.d.ts +18 -0
  15. package/dist/activities/agent-turn/finalization-monitor.d.ts +17 -0
  16. package/dist/activities/agent-turn/finalization.d.ts +4 -2
  17. package/dist/activities/agent-turn/github-repository-bindings.d.ts +2 -0
  18. package/dist/activities/agent-turn/governance-model.d.ts +9 -2
  19. package/dist/activities/agent-turn/history-sink.d.ts +2 -0
  20. package/dist/activities/agent-turn/history.d.ts +2 -0
  21. package/dist/activities/agent-turn/input-wait-reply.d.ts +41 -0
  22. package/dist/activities/agent-turn/media-artifacts.d.ts +5 -3
  23. package/dist/activities/agent-turn/model-call-admission.d.ts +15 -0
  24. package/dist/activities/agent-turn/model-usage.d.ts +6 -0
  25. package/dist/activities/agent-turn/model-wire-dispatch.d.ts +15 -0
  26. package/dist/activities/agent-turn/optional-repositories.d.ts +59 -0
  27. package/dist/activities/agent-turn/provider-dispatch-barrier.d.ts +12 -1
  28. package/dist/activities/agent-turn/quiescence.d.ts +7 -7
  29. package/dist/activities/agent-turn/recovery-warning.d.ts +9 -0
  30. package/dist/activities/agent-turn/refresh-credentials.d.ts +6 -0
  31. package/dist/activities/agent-turn/run-credentials.d.ts +8 -3
  32. package/dist/activities/agent-turn/sandbox-establish.d.ts +2 -1
  33. package/dist/activities/agent-turn/sandbox-provision.d.ts +3 -1
  34. package/dist/activities/agent-turn/sandbox-route.d.ts +3 -20
  35. package/dist/activities/agent-turn/sandbox-runtime.d.ts +2 -2
  36. package/dist/activities/agent-turn/session-title.d.ts +34 -2
  37. package/dist/activities/agent-turn/skill-checkout.d.ts +25 -6
  38. package/dist/activities/agent-turn/skill-read.d.ts +70 -2
  39. package/dist/activities/agent-turn/skill-remove.d.ts +14 -0
  40. package/dist/activities/agent-turn/skill-search.d.ts +3 -1
  41. package/dist/activities/agent-turn/skill-tools.d.ts +15 -2
  42. package/dist/activities/agent-turn/skill-transfer.d.ts +18 -6
  43. package/dist/activities/agent-turn/stream-attempt.d.ts +7 -3
  44. package/dist/activities/agent-turn/subscription-lease.d.ts +38 -0
  45. package/dist/activities/agent-turn/tool-environment.d.ts +56 -6
  46. package/dist/activities/agent-turn/tool-policy.d.ts +43 -0
  47. package/dist/activities/agent-turn/turn-context.d.ts +29 -0
  48. package/dist/activities/agent-turn/turn-sandbox-access.d.ts +3 -0
  49. package/dist/activities/agent-turn/xai-capacity.d.ts +2 -1
  50. package/dist/activities/automations.d.ts +3 -1
  51. package/dist/activities/browser-deadline-checkpoint.d.ts +29 -0
  52. package/dist/activities/codemode-dispatcher.d.ts +9 -2
  53. package/dist/activities/codex-capacity.d.ts +18 -2
  54. package/dist/activities/codex-rotation.d.ts +7 -1
  55. package/dist/activities/context-compaction.d.ts +16 -2
  56. package/dist/activities/gmail-files.d.ts +32 -0
  57. package/dist/activities/goals.d.ts +8 -0
  58. package/dist/activities/knowledge-indexing.d.ts +19 -0
  59. package/dist/activities/mcp-account-routes.d.ts +3 -0
  60. package/dist/activities/mcp-credentials.d.ts +12 -13
  61. package/dist/activities/mcp-operation-authority.d.ts +0 -5
  62. package/dist/activities/model-call-fact-reconciler.d.ts +34 -0
  63. package/dist/activities/open-suffix-resume.d.ts +13 -0
  64. package/dist/activities/parent-wake.d.ts +6 -12
  65. package/dist/activities/retained-screenshots.d.ts +7 -2
  66. package/dist/activities/rig-verification.d.ts +2 -3
  67. package/dist/activities/run-credential-renewal.d.ts +1 -0
  68. package/dist/activities/run-credentials.d.ts +15 -3
  69. package/dist/activities/sandbox-images.d.ts +1 -1
  70. package/dist/activities/sandbox-lease.d.ts +47 -9
  71. package/dist/activities/scheduled-tasks.d.ts +4 -35
  72. package/dist/activities/session-state.d.ts +70 -3
  73. package/dist/activities/types.d.ts +55 -6
  74. package/dist/activities/workspace-capture.d.ts +2 -0
  75. package/dist/activities/workspace-credential-provider.d.ts +46 -0
  76. package/dist/{activities-control-HMFGSKC5.js → activities-control-BNPTRTOE.js} +1896 -418
  77. package/dist/activities-control-BNPTRTOE.js.map +1 -0
  78. package/dist/activities-control.d.ts +182 -4
  79. package/dist/{activities-turn-AP67JADS.js → activities-turn-5LGZOSVU.js} +4476 -1327
  80. package/dist/activities-turn-5LGZOSVU.js.map +1 -0
  81. package/dist/activities.d.ts +182 -4
  82. package/dist/artifact-materializer-entry.js +5 -2
  83. package/dist/artifact-materializer-entry.js.map +1 -1
  84. package/dist/artifact-outbox-entry.js +5 -2
  85. package/dist/artifact-outbox-entry.js.map +1 -1
  86. package/dist/browser-deadline-checkpoint-contract.d.ts +2 -0
  87. package/dist/{chunk-A4XQWVZK.js → chunk-3ZTRWDMN.js} +307 -4
  88. package/dist/chunk-3ZTRWDMN.js.map +1 -0
  89. package/dist/{chunk-RAMNYSAW.js → chunk-4ER3YXOT.js} +22 -4
  90. package/dist/chunk-4ER3YXOT.js.map +1 -0
  91. package/dist/{chunk-CYITU5UH.js → chunk-LJX7Z2KP.js} +1445 -343
  92. package/dist/chunk-LJX7Z2KP.js.map +1 -0
  93. package/dist/editable-artifact-materializer-service.d.ts +2 -2
  94. package/dist/editable-artifact-outbox-service.d.ts +2 -2
  95. package/dist/host-export-pump.d.ts +3 -1
  96. package/dist/host-export.d.ts +1 -1
  97. package/dist/host-export.js +1 -1
  98. package/dist/http.d.ts +1 -1
  99. package/dist/index.d.ts +95 -3
  100. package/dist/index.js +137 -43
  101. package/dist/index.js.map +1 -1
  102. package/dist/observability-metrics.d.ts +118 -8
  103. package/dist/retained-process-diagnostics.d.ts +4 -0
  104. package/dist/retained-process-retry.d.ts +7 -0
  105. package/dist/sandbox-resume.d.ts +55 -13
  106. package/dist/sandbox-routing.d.ts +5 -3
  107. package/dist/sandbox-snapshot-diagnostics.d.ts +20 -0
  108. package/dist/session-event-fanout.d.ts +6 -0
  109. package/dist/warm-capture-holder.d.ts +3 -0
  110. package/dist/worker-service-lifecycle.d.ts +12 -0
  111. package/dist/workflow-bundle.js +273 -41
  112. package/dist/workflows/activities.d.ts +1 -1
  113. package/dist/workflows/browser-deadline-checkpoint.d.ts +9 -0
  114. package/dist/workflows/scheduled-tasks.d.ts +4 -0
  115. package/dist/workflows/session.d.ts +36 -0
  116. package/dist/workflows.d.ts +1 -0
  117. package/package.json +21 -19
  118. package/src/activities/agent-run-admission.ts +17 -1
  119. package/src/activities/agent-turn/admission.ts +66 -3
  120. package/src/activities/agent-turn/agent-build.ts +84 -10
  121. package/src/activities/agent-turn/claim.ts +186 -43
  122. package/src/activities/agent-turn/claude-usage-observer.ts +221 -0
  123. package/src/activities/agent-turn/code-search.ts +275 -0
  124. package/src/activities/agent-turn/codex-capacity.ts +172 -8
  125. package/src/activities/agent-turn/codex-plan-entitlement.ts +254 -0
  126. package/src/activities/agent-turn/codex.ts +13 -5
  127. package/src/activities/agent-turn/compaction-prep.ts +170 -102
  128. package/src/activities/agent-turn/credential-leases.ts +122 -216
  129. package/src/activities/agent-turn/credential-restriction.ts +14 -0
  130. package/src/activities/agent-turn/errors.ts +647 -48
  131. package/src/activities/agent-turn/failure-settlement.ts +682 -130
  132. package/src/activities/agent-turn/final-reply.ts +46 -0
  133. package/src/activities/agent-turn/finalization-monitor.ts +120 -0
  134. package/src/activities/agent-turn/finalization.ts +146 -43
  135. package/src/activities/agent-turn/github-repository-bindings.ts +3 -1
  136. package/src/activities/agent-turn/governance-model.ts +69 -28
  137. package/src/activities/agent-turn/history-sink.ts +16 -2
  138. package/src/activities/agent-turn/history.ts +38 -11
  139. package/src/activities/agent-turn/input-wait-reply.ts +103 -0
  140. package/src/activities/agent-turn/knowledge-source-tools.ts +2 -0
  141. package/src/activities/agent-turn/media-artifacts.ts +2 -1
  142. package/src/activities/agent-turn/model-call-admission.ts +94 -0
  143. package/src/activities/agent-turn/model-usage.ts +64 -3
  144. package/src/activities/agent-turn/model-wire-dispatch.ts +27 -0
  145. package/src/activities/agent-turn/optional-repositories.ts +224 -0
  146. package/src/activities/agent-turn/provider-dispatch-barrier.ts +22 -0
  147. package/src/activities/agent-turn/quiescence.ts +10 -7
  148. package/src/activities/agent-turn/recovery-warning.ts +16 -0
  149. package/src/activities/agent-turn/refresh-credentials.ts +44 -0
  150. package/src/activities/agent-turn/run-credentials.ts +116 -55
  151. package/src/activities/agent-turn/run.ts +320 -93
  152. package/src/activities/agent-turn/sandbox-establish.ts +84 -8
  153. package/src/activities/agent-turn/sandbox-provision.ts +3 -1
  154. package/src/activities/agent-turn/sandbox-route.ts +4 -21
  155. package/src/activities/agent-turn/sandbox-runtime.ts +343 -18
  156. package/src/activities/agent-turn/session-title.ts +81 -5
  157. package/src/activities/agent-turn/skill-checkout.ts +111 -24
  158. package/src/activities/agent-turn/skill-install.ts +1 -1
  159. package/src/activities/agent-turn/skill-read.ts +374 -28
  160. package/src/activities/agent-turn/skill-remove.ts +46 -0
  161. package/src/activities/agent-turn/skill-save.ts +1 -1
  162. package/src/activities/agent-turn/skill-search.ts +10 -1
  163. package/src/activities/agent-turn/skill-selection.ts +4 -0
  164. package/src/activities/agent-turn/skill-tools.ts +112 -18
  165. package/src/activities/agent-turn/skill-transfer.ts +68 -23
  166. package/src/activities/agent-turn/stream-attempt.ts +313 -77
  167. package/src/activities/agent-turn/subscription-lease.ts +115 -0
  168. package/src/activities/agent-turn/tool-environment.ts +316 -167
  169. package/src/activities/agent-turn/tool-policy.ts +80 -1
  170. package/src/activities/agent-turn/turn-context.ts +35 -0
  171. package/src/activities/agent-turn/turn-sandbox-access.ts +7 -1
  172. package/src/activities/agent-turn/xai-capacity.ts +94 -51
  173. package/src/activities/automations.ts +76 -4
  174. package/src/activities/browser-deadline-checkpoint.ts +279 -0
  175. package/src/activities/capabilities.ts +108 -11
  176. package/src/activities/codemode-dispatcher.ts +36 -8
  177. package/src/activities/codex-capacity.ts +60 -25
  178. package/src/activities/codex-rotation.ts +39 -17
  179. package/src/activities/context-compaction.ts +75 -18
  180. package/src/activities/gmail-files.ts +88 -0
  181. package/src/activities/goals.ts +116 -121
  182. package/src/activities/google-drive-publication.ts +1 -3
  183. package/src/activities/image-generation-operation.ts +1 -1
  184. package/src/activities/knowledge-indexing.ts +269 -15
  185. package/src/activities/knowledge-source-sync.ts +10 -0
  186. package/src/activities/mcp-account-routes.ts +17 -0
  187. package/src/activities/mcp-credentials.ts +83 -194
  188. package/src/activities/mcp-operation-authority.ts +16 -41
  189. package/src/activities/model-call-fact-reconciler.ts +112 -0
  190. package/src/activities/open-suffix-resume.ts +15 -2
  191. package/src/activities/parent-wake.ts +46 -21
  192. package/src/activities/retained-screenshots.ts +82 -11
  193. package/src/activities/rig-verification.ts +38 -37
  194. package/src/activities/run-credential-renewal.ts +13 -1
  195. package/src/activities/run-credentials.ts +59 -17
  196. package/src/activities/run-input.ts +25 -16
  197. package/src/activities/sandbox-images.ts +0 -1
  198. package/src/activities/sandbox-lease.ts +798 -82
  199. package/src/activities/scheduled-tasks.ts +550 -178
  200. package/src/activities/session-state.ts +245 -6
  201. package/src/activities/site-auth-maintenance.ts +3 -0
  202. package/src/activities/types.ts +72 -5
  203. package/src/activities/workflow-wake.ts +2 -17
  204. package/src/activities/workspace-capture.ts +13 -2
  205. package/src/activities/workspace-credential-provider.ts +283 -0
  206. package/src/activities-control.ts +4 -0
  207. package/src/activities-turn.ts +5 -0
  208. package/src/activities.ts +13 -0
  209. package/src/activity-services.ts +16 -4
  210. package/src/browser-deadline-checkpoint-contract.ts +5 -0
  211. package/src/editable-artifact-hint-broker.ts +3 -0
  212. package/src/editable-artifact-materializer-service.ts +7 -3
  213. package/src/editable-artifact-outbox-service.ts +4 -4
  214. package/src/github-rest-mcp.ts +1 -2
  215. package/src/host-export-pump.ts +26 -4
  216. package/src/host-export.ts +3 -0
  217. package/src/http.ts +4 -2
  218. package/src/index.ts +99 -37
  219. package/src/observability-metrics.ts +510 -5
  220. package/src/personal-github-git-credentials.ts +2 -1
  221. package/src/pr-review-credentials.ts +1 -3
  222. package/src/retained-process-diagnostics.ts +50 -0
  223. package/src/retained-process-retry.ts +36 -0
  224. package/src/sandbox-resume.ts +388 -101
  225. package/src/sandbox-routing.ts +150 -25
  226. package/src/sandbox-snapshot-diagnostics.ts +112 -0
  227. package/src/session-event-fanout.ts +23 -0
  228. package/src/warm-capture-holder.ts +15 -0
  229. package/src/worker-service-lifecycle.ts +53 -0
  230. package/src/workflows/activities.ts +16 -1
  231. package/src/workflows/browser-deadline-checkpoint.ts +50 -0
  232. package/src/workflows/file-upload-reaper.ts +2 -0
  233. package/src/workflows/scheduled-tasks.ts +26 -13
  234. package/src/workflows/session.ts +242 -22
  235. package/src/workflows.ts +4 -0
  236. package/dist/activities/agent-turn/knowledge-sources.d.ts +0 -20
  237. package/dist/activities/packs.d.ts +0 -55
  238. package/dist/activities-control-HMFGSKC5.js.map +0 -1
  239. package/dist/activities-turn-AP67JADS.js.map +0 -1
  240. package/dist/chunk-A4XQWVZK.js.map +0 -1
  241. package/dist/chunk-CYITU5UH.js.map +0 -1
  242. package/dist/chunk-RAMNYSAW.js.map +0 -1
  243. package/src/activities/agent-turn/knowledge-sources.ts +0 -86
  244. package/src/activities/packs.ts +0 -166
@@ -1,28 +1,140 @@
1
1
  import { configuredStaticUsageLimits } from "@opengeni/config";
2
+ import { documentEmbeddingCostMicros, paidDocumentEmbedding } from "@opengeni/core";
2
3
  import {
4
+ applyCreditDebitAfterUse,
3
5
  appendKnowledgeIndexChunks,
4
6
  claimKnowledgeIndexJobs,
7
+ checkWorkspaceAllowance,
5
8
  completeKnowledgeIndexJob,
6
9
  continueKnowledgeIndexJob,
10
+ creditDebitAttributionMetadata,
7
11
  deferKnowledgeIndexJob,
12
+ freezeKnowledgeIndexBillingMode,
8
13
  getBillingBalance,
14
+ guardPaidKnowledgeIndexPublication,
15
+ knowledgeIndexBillingActivationTime,
9
16
  readKnowledgeIndexSource,
10
17
  recordUsageEvent,
11
18
  sumUsageQuantity,
12
19
  withWorkspaceUsageLock,
20
+ waitKnowledgeIndexForFunding,
13
21
  } from "@opengeni/db";
14
22
  import type { DocumentServices } from "@opengeni/documents";
15
23
  import type { ControlActivityServices } from "./types";
16
24
 
25
+ /** The configured monthly indexed-chunk limit, not a provider failure. */
26
+ export class KnowledgeIndexUsageLimitError extends Error {
27
+ constructor() {
28
+ super("monthly document indexing limit reached");
29
+ this.name = "KnowledgeIndexUsageLimitError";
30
+ }
31
+ }
32
+
33
+ export type KnowledgeIndexFailureStage = "embedding" | "processing";
34
+
35
+ /**
36
+ * Content-free classification for a deferred Knowledge index batch. Only
37
+ * protocol constants, an HTTP status, and a PostgreSQL SQLSTATE are retained;
38
+ * provider messages, bodies, SQL, and identifiers never leave the process.
39
+ * Outside the embedding call, only a PostgreSQL error in the cause chain is
40
+ * attributed to the database; any other failure stays a worker failure.
41
+ */
42
+ export function knowledgeIndexFailureDiagnostic(
43
+ stage: KnowledgeIndexFailureStage,
44
+ error: unknown,
45
+ ): {
46
+ errorClass: "KnowledgeIndexOperationError";
47
+ errorCode:
48
+ | "knowledge_index_usage_limit_reached"
49
+ | "knowledge_index_embedding_failed"
50
+ | "knowledge_index_persistence_failed"
51
+ | "knowledge_index_failed";
52
+ origin: "worker" | "db";
53
+ status?: number;
54
+ sqlState?: string;
55
+ } {
56
+ if (error instanceof KnowledgeIndexUsageLimitError) {
57
+ return {
58
+ errorClass: "KnowledgeIndexOperationError",
59
+ errorCode: "knowledge_index_usage_limit_reached",
60
+ origin: "worker",
61
+ };
62
+ }
63
+ if (stage === "embedding") {
64
+ const status = ownValue(error, "status");
65
+ return {
66
+ errorClass: "KnowledgeIndexOperationError",
67
+ errorCode: "knowledge_index_embedding_failed",
68
+ origin: "worker",
69
+ ...(typeof status === "number" && Number.isInteger(status) && status >= 100 && status <= 599
70
+ ? { status }
71
+ : {}),
72
+ };
73
+ }
74
+ const postgres = postgresErrorState(error);
75
+ if (!postgres) {
76
+ return {
77
+ errorClass: "KnowledgeIndexOperationError",
78
+ errorCode: "knowledge_index_failed",
79
+ origin: "worker",
80
+ };
81
+ }
82
+ return {
83
+ errorClass: "KnowledgeIndexOperationError",
84
+ errorCode: "knowledge_index_persistence_failed",
85
+ origin: "db",
86
+ ...(postgres.sqlState ? { sqlState: postgres.sqlState } : {}),
87
+ };
88
+ }
89
+
90
+ function ownValue(value: unknown, key: string): unknown {
91
+ try {
92
+ if (!value || typeof value !== "object") return undefined;
93
+ const descriptor = Object.getOwnPropertyDescriptor(value, key);
94
+ return descriptor && "value" in descriptor ? descriptor.value : undefined;
95
+ } catch {
96
+ return undefined;
97
+ }
98
+ }
99
+
100
+ /** The nearest PostgreSQL error in a short cause chain, with its SQLSTATE
101
+ * when that is a well-formed five-character code. */
102
+ function postgresErrorState(error: unknown): { sqlState?: string } | undefined {
103
+ let current = error;
104
+ for (let depth = 0; depth < 4 && current && typeof current === "object"; depth += 1) {
105
+ if (ownValue(current, "name") === "PostgresError") {
106
+ const code = ownValue(current, "code");
107
+ return typeof code === "string" && /^[0-9A-Z]{5}$/.test(code) ? { sqlState: code } : {};
108
+ }
109
+ current = ownValue(current, "cause");
110
+ }
111
+ return undefined;
112
+ }
113
+
17
114
  export function createKnowledgeIndexingActivities(
18
115
  services: () => Promise<ControlActivityServices>,
19
116
  resolveDocumentServices?: () => Promise<DocumentServices>,
20
117
  ) {
118
+ // Unpaid modes retain a conservative first-poll cutoff; paid mode uses the
119
+ // operator's explicit timestamp so process restarts cannot change eligibility.
120
+ let activationTime: Promise<Date> | undefined;
21
121
  return {
22
122
  indexKnowledge: async () => {
23
123
  const result = { completed: 0, advanced: 0, deferred: 0, unavailable: 0 };
24
124
  if (!resolveDocumentServices) return result;
25
125
  const { db, settings, observability } = await services();
126
+ let policyActivatedAt: Date;
127
+ if (paidDocumentEmbedding(settings)) {
128
+ if (!settings.documentEmbeddingCreditsActivatedAt)
129
+ throw new Error("paid Knowledge embedding requires an activation cutoff");
130
+ policyActivatedAt = new Date(settings.documentEmbeddingCreditsActivatedAt);
131
+ } else {
132
+ activationTime ??= knowledgeIndexBillingActivationTime(db).catch((error) => {
133
+ activationTime = undefined;
134
+ throw error;
135
+ });
136
+ policyActivatedAt = await activationTime;
137
+ }
26
138
  const { embedder } = await resolveDocumentServices();
27
139
  const { knowledgeIndexChunks } = await import("@opengeni/documents");
28
140
  const claims = await claimKnowledgeIndexJobs(db, {
@@ -31,15 +143,16 @@ export function createKnowledgeIndexingActivities(
31
143
  limit: 2,
32
144
  });
33
145
  for (const claim of claims) {
146
+ let stage: KnowledgeIndexFailureStage = "processing";
34
147
  try {
35
148
  const source = await readKnowledgeIndexSource(db, claim);
36
149
  if (!source) {
37
150
  result.unavailable++;
38
151
  continue;
39
152
  }
40
- // Reuse the existing embedding budget and usage ledger. Each batch's
41
- // checkpoint and charge commit together, so a restart never charges
42
- // twice for an accepted projection. Canonical text is never changed.
153
+ // The checkpoint, usage and post-use debit commit together. A new
154
+ // generation requires funding once; committed batches may finish even
155
+ // if their accumulated cost takes the balance below zero.
43
156
  await withWorkspaceUsageLock(db, source.billingWorkspaceId, async (lockedDb) => {
44
157
  const current = await readKnowledgeIndexSource(lockedDb, claim);
45
158
  if (!current) {
@@ -57,9 +170,69 @@ export function createKnowledgeIndexingActivities(
57
170
  chunks.push(chunk);
58
171
  }
59
172
  if (chunks.length) {
60
- if (settings.billingMode === "stripe" || settings.usageLimitsMode === "managed") {
173
+ const frozenPolicy = await freezeKnowledgeIndexBillingMode(
174
+ lockedDb,
175
+ claim,
176
+ // Deterministic embeddings incur no provider charge; a valid
177
+ // credits-mode config with zero tariff must still index them.
178
+ // OpenAI shadow keeps its price snapshot for internal estimates.
179
+ settings.documentEmbeddingProvider === "openai"
180
+ ? (settings.documentEmbeddingBillingMode ?? "usage_only")
181
+ : "usage_only",
182
+ policyActivatedAt,
183
+ settings.documentEmbeddingRateMicrosPerMillionBytes ?? 0,
184
+ );
185
+ if (frozenPolicy.mode === "awaiting_review") {
186
+ result.deferred++;
187
+ return;
188
+ }
189
+ if (frozenPolicy.mode === "obsolete") {
190
+ result.unavailable++;
191
+ return;
192
+ }
193
+ // An already-priced generation cannot become free when the
194
+ // operator turns off paid embedding. Retain its checkpoint and
195
+ // retry only after paid mode is restored; never call the provider
196
+ // or append a batch that the live policy would not debit.
197
+ if (frozenPolicy.mode === "credits" && !paidDocumentEmbedding(settings)) {
198
+ await deferKnowledgeIndexJob(lockedDb, claim);
199
+ result.deferred++;
200
+ return;
201
+ }
202
+ const paid = frozenPolicy.mode === "credits";
203
+ if (paid && claim.billingAttribution.kind === "unknown") {
204
+ // Unknown legacy/source-preparation causality is not service.
205
+ // Keep the checkpoint without making an uncountable paid call.
206
+ observability.warn("Paid Knowledge indexing awaits initiating attribution", {
207
+ errorCode: "knowledge_index_attribution_unavailable",
208
+ });
209
+ await deferKnowledgeIndexJob(lockedDb, claim);
210
+ result.deferred++;
211
+ return;
212
+ }
213
+ if (paid && current.nextIndex === 0) {
61
214
  const balance = await getBillingBalance(lockedDb, claim.accountId);
62
- if (balance.balanceMicros <= 0) throw new Error("insufficient OpenGeni credits");
215
+ if (balance.balanceMicros <= 0) {
216
+ await waitKnowledgeIndexForFunding(lockedDb, claim);
217
+ result.deferred++;
218
+ return;
219
+ }
220
+ }
221
+ if (paid) {
222
+ const refusal = await checkWorkspaceAllowance(lockedDb, {
223
+ accountId: claim.accountId,
224
+ workspaceId: current.billingWorkspaceId,
225
+ subjectId:
226
+ claim.billingAttribution.kind === "turn" ||
227
+ claim.billingAttribution.kind === "human"
228
+ ? claim.billingAttribution.initiatingHumanSubjectId
229
+ : null,
230
+ });
231
+ if (refusal) {
232
+ await deferKnowledgeIndexJob(lockedDb, claim);
233
+ result.deferred++;
234
+ return;
235
+ }
63
236
  }
64
237
  if (settings.usageLimitsMode === "static" || settings.usageLimitsMode === "managed") {
65
238
  const limit =
@@ -71,13 +244,29 @@ export function createKnowledgeIndexingActivities(
71
244
  eventType: "document.indexed",
72
245
  since: new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), 1)),
73
246
  });
74
- if (used + chunks.length > limit)
75
- throw new Error("monthly document indexing limit reached");
247
+ if (used + chunks.length > limit) throw new KnowledgeIndexUsageLimitError();
76
248
  }
77
249
  }
78
- const vectors = await embedder.embedMany(chunks.map((chunk) => chunk.embeddingInput));
250
+ const inputs = chunks.map((chunk) => chunk.embeddingInput);
251
+ const bytes = inputs.reduce(
252
+ (sum, input) => sum + Buffer.byteLength(input, "utf8"),
253
+ 0,
254
+ );
255
+ stage = "embedding";
256
+ const vectors = await embedder.embedMany(inputs);
79
257
  if (vectors.length !== chunks.length)
80
258
  throw new Error("Incomplete Knowledge embeddings");
259
+ stage = "processing";
260
+ // A reviewer may have rejected this revision during the provider
261
+ // call. The DB guard holds its publication row through settlement.
262
+ if (paid) {
263
+ const publication = await guardPaidKnowledgeIndexPublication(lockedDb, claim);
264
+ if (publication !== "published") {
265
+ if (publication === "obsolete") result.unavailable++;
266
+ else result.deferred++;
267
+ return;
268
+ }
269
+ }
81
270
  const appended = await appendKnowledgeIndexChunks(
82
271
  lockedDb,
83
272
  claim,
@@ -98,6 +287,64 @@ export function createKnowledgeIndexingActivities(
98
287
  sourceResourceId: claim.revisionId,
99
288
  idempotencyKey: `knowledge.indexed:${claim.revisionId}:${claim.generation}:${current.nextIndex}`,
100
289
  });
290
+ await recordUsageEvent(lockedDb, {
291
+ accountId: claim.accountId,
292
+ workspaceId: current.billingWorkspaceId,
293
+ eventType: "document.embedding_bytes",
294
+ quantity: bytes,
295
+ unit: "byte",
296
+ sourceResourceType: "knowledge_revision",
297
+ sourceResourceId: claim.revisionId,
298
+ idempotencyKey: `knowledge.embedding_bytes:${claim.revisionId}:${claim.generation}:${current.nextIndex}`,
299
+ });
300
+ if (frozenPolicy.mode === "shadow" && frozenPolicy.rateMicrosPerMillionBytes > 0) {
301
+ const estimate = documentEmbeddingCostMicros(
302
+ {
303
+ ...settings,
304
+ documentEmbeddingRateMicrosPerMillionBytes:
305
+ frozenPolicy.rateMicrosPerMillionBytes,
306
+ },
307
+ bytes,
308
+ );
309
+ if (estimate > 0)
310
+ await recordUsageEvent(lockedDb, {
311
+ accountId: claim.accountId,
312
+ workspaceId: current.billingWorkspaceId,
313
+ eventType: "document.embedding_shadow_estimate",
314
+ quantity: estimate,
315
+ unit: "micro_usd",
316
+ sourceResourceType: "knowledge_revision",
317
+ sourceResourceId: claim.revisionId,
318
+ idempotencyKey: `knowledge.embedding_shadow:${claim.revisionId}:${claim.generation}:${current.nextIndex}`,
319
+ });
320
+ }
321
+ if (paid) {
322
+ const cost = documentEmbeddingCostMicros(
323
+ {
324
+ ...settings,
325
+ documentEmbeddingRateMicrosPerMillionBytes:
326
+ frozenPolicy.rateMicrosPerMillionBytes,
327
+ },
328
+ bytes,
329
+ );
330
+ if (cost > 0)
331
+ await applyCreditDebitAfterUse(lockedDb, {
332
+ accountId: claim.accountId,
333
+ workspaceId: current.billingWorkspaceId,
334
+ type: "document_embedding_debit",
335
+ amountMicros: cost,
336
+ sourceType: "knowledge_revision",
337
+ sourceId: claim.revisionId,
338
+ idempotencyKey: `knowledge.embedding:${claim.revisionId}:${claim.generation}:${current.nextIndex}`,
339
+ metadata: {
340
+ ...creditDebitAttributionMetadata(claim.billingAttribution),
341
+ model: claim.model,
342
+ bytes,
343
+ chunks: chunks.length,
344
+ rateMicrosPerMillionBytes: frozenPolicy.rateMicrosPerMillionBytes,
345
+ },
346
+ });
347
+ }
101
348
  }
102
349
  if (more) {
103
350
  await continueKnowledgeIndexJob(lockedDb, claim);
@@ -112,16 +359,23 @@ export function createKnowledgeIndexingActivities(
112
359
  else result.unavailable++;
113
360
  }
114
361
  });
115
- } catch {
362
+ } catch (error) {
116
363
  // Provider failures retain the last completed projection. The durable
117
364
  // queue owns retry/backoff; do not retry an entire activity implicitly.
118
- await deferKnowledgeIndexJob(db, claim).catch(() => undefined);
119
- result.deferred++;
120
- observability.warn("Knowledge indexing batch deferred", {
121
- accountId: claim.accountId,
122
- entryId: claim.entryId,
123
- revisionId: claim.revisionId,
365
+ // The stored reason stays the SQL lifecycle's fixed code; the log
366
+ // carries the content-free class/code of the actual cause.
367
+ observability.warn(
368
+ "Knowledge indexing batch deferred",
369
+ knowledgeIndexFailureDiagnostic(stage, error),
370
+ );
371
+ await deferKnowledgeIndexJob(db, claim).catch((deferError: unknown) => {
372
+ const deferDiagnostic = knowledgeIndexFailureDiagnostic("processing", deferError);
373
+ observability.warn("Knowledge indexing batch deferral failed", {
374
+ ...deferDiagnostic,
375
+ errorCode: "knowledge_index_defer_failed",
376
+ });
124
377
  });
378
+ result.deferred++;
125
379
  }
126
380
  }
127
381
  return result;
@@ -1,3 +1,7 @@
1
+ import {
2
+ ATLASSIAN_NATIVE_RETIRED_REASON,
3
+ isRetiredNativeAtlassianSource,
4
+ } from "@opengeni/contracts/atlassian-native-retirement";
1
5
  import { isDeepStrictEqual } from "node:util";
2
6
  import { AsyncLocalStorage } from "node:async_hooks";
3
7
  import { scheduledTaskKnowledgeSource } from "@opengeni/contracts";
@@ -243,6 +247,12 @@ export function createKnowledgeSourceSyncActivities(
243
247
  ) {
244
248
  return { action: "failed", bufferedWake: false };
245
249
  }
250
+ if (isRetiredNativeAtlassianSource(action))
251
+ return {
252
+ action: "failed",
253
+ bufferedWake: false,
254
+ errorCode: ATLASSIAN_NATIVE_RETIRED_REASON,
255
+ };
246
256
  boundSource = action;
247
257
  await authorize();
248
258
  await ensureKnowledgeSourceSyncState(db, task);
@@ -0,0 +1,17 @@
1
+ import type { McpConnectionAccountBinding, ToolAuthNeededPayload } from "@opengeni/contracts";
2
+
3
+ export function accountRouteAuthNeededPayload(
4
+ payload: ToolAuthNeededPayload,
5
+ bindings: readonly McpConnectionAccountBinding[] | null | undefined,
6
+ ): ToolAuthNeededPayload {
7
+ const binding = bindings?.find((candidate) => candidate.serverId === payload.serverId);
8
+ return binding
9
+ ? {
10
+ ...payload,
11
+ canonicalServerId: binding.canonicalServerId,
12
+ connectionSubjectScope: binding.subjectScope,
13
+ }
14
+ : payload;
15
+ }
16
+
17
+ export { expandMcpAccountRoutes, expandApiIntegrationAccountRoutes } from "@opengeni/core";