reploid 0.0.0-stage → 0.1.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 (233) hide show
  1. package/apps/poolday/config/chat-files.json +27 -0
  2. package/apps/poolday/config/partition-generation.js +21 -0
  3. package/apps/poolday/config/partition-policy.json +74 -0
  4. package/apps/poolday/config/partition-releases.json +3 -0
  5. package/apps/poolday/config/work-profile.json +122 -0
  6. package/apps/poolday/host/chat-view.js +47 -0
  7. package/apps/poolday/host/earning/client.js +199 -0
  8. package/apps/poolday/host/earning/contribution.js +168 -0
  9. package/apps/poolday/host/partition-release.js +33 -0
  10. package/apps/poolday/host/work-partition-artifact-source.js +37 -0
  11. package/apps/poolday/host/work-partition-capsule.js +39 -0
  12. package/apps/poolday/host/work-partition-plan.js +167 -0
  13. package/apps/poolday/host/work-partition-tokenizer-guard.js +21 -0
  14. package/apps/poolday/infrastructure/model-storage-lock.js +22 -0
  15. package/apps/poolday/infrastructure/pack-release-storage.js +52 -0
  16. package/apps/poolday/pool/pack-operation.js +161 -0
  17. package/apps/poolday/pool/pack-release-policy.js +44 -0
  18. package/apps/poolday/pool/peer-pack-data-channel.js +217 -0
  19. package/apps/poolday/providers/work-adapter.js +67 -0
  20. package/apps/poolday/providers/work-device.js +33 -0
  21. package/apps/poolday/providers/work-generation-completion.js +55 -0
  22. package/apps/poolday/providers/work-provider.js +209 -0
  23. package/apps/poolday/providers/work-resident-provider.js +113 -0
  24. package/deploy/artifacts/doppler-gpu-0.7.1.tgz +0 -0
  25. package/docs/fleet-service.md +214 -0
  26. package/docs/native-participant.md +534 -0
  27. package/native-delivery.json +1174 -0
  28. package/package.json +29 -4
  29. package/packages/reploid/src/artifacts/binary.js +25 -0
  30. package/packages/reploid/src/artifacts/canonical-json.js +23 -0
  31. package/packages/reploid/src/artifacts/custody/exchange.js +402 -0
  32. package/packages/reploid/src/artifacts/custody/piece-acquisition.js +70 -0
  33. package/packages/reploid/src/artifacts/custody/runtime.js +404 -0
  34. package/packages/reploid/src/artifacts/custody/supply-budget.js +19 -0
  35. package/packages/reploid/src/artifacts/custody-certificate.js +123 -0
  36. package/packages/reploid/src/artifacts/delivery-attestation.js +64 -0
  37. package/packages/reploid/src/artifacts/generation-terminal.js +36 -0
  38. package/packages/reploid/src/artifacts/identity.js +91 -0
  39. package/packages/reploid/src/artifacts/participant-proofs.js +159 -0
  40. package/packages/reploid/src/artifacts/receipt.js +131 -0
  41. package/packages/reploid/src/artifacts/signatures.js +94 -0
  42. package/packages/reploid/src/artifacts/whole-model-receipt.js +42 -0
  43. package/packages/reploid/src/cancellation.js +44 -0
  44. package/packages/reploid/src/config/defaults.json +110 -0
  45. package/packages/reploid/src/config/index.js +209 -0
  46. package/packages/reploid/src/config/request-overrides.json +9 -0
  47. package/packages/reploid/src/config/transport-defaults.json +7 -0
  48. package/packages/reploid/src/hashing.js +30 -0
  49. package/packages/reploid/src/measurement/capacity-utilization.js +321 -0
  50. package/packages/reploid/src/measurement/index.js +5 -0
  51. package/packages/reploid/src/measurement/readiness-records.js +310 -0
  52. package/packages/reploid/src/mesh/computer-identity.js +50 -0
  53. package/packages/reploid/src/mesh/computer-identity.policy.json +8 -0
  54. package/packages/reploid/src/mesh/contribution.js +141 -0
  55. package/packages/reploid/src/mesh/generation-recovery.js +58 -0
  56. package/packages/reploid/src/mesh/gpu-signature-shader.js +27 -0
  57. package/packages/reploid/src/mesh/gpu-signature.js +136 -0
  58. package/packages/reploid/src/mesh/gpu-signature.policy.json +11 -0
  59. package/packages/reploid/src/mesh/index.js +66 -0
  60. package/packages/reploid/src/mesh/partitions/automatic-ordered-partitions.js +540 -0
  61. package/packages/reploid/src/mesh/partitions/automatic-partitions.js +298 -0
  62. package/packages/reploid/src/mesh/partitions/partition-attempt-evidence.js +282 -0
  63. package/packages/reploid/src/mesh/partitions/partition-attempt-queue-policy.json +6 -0
  64. package/packages/reploid/src/mesh/partitions/partition-attempt-queue.js +112 -0
  65. package/packages/reploid/src/mesh/partitions/partition-canonical-contract.js +167 -0
  66. package/packages/reploid/src/mesh/partitions/partition-canonical-execution.js +168 -0
  67. package/packages/reploid/src/mesh/partitions/partition-chat-canonical.js +49 -0
  68. package/packages/reploid/src/mesh/partitions/partition-chat.js +125 -0
  69. package/packages/reploid/src/mesh/partitions/partition-contract.js +192 -0
  70. package/packages/reploid/src/mesh/partitions/partition-device-admission.js +96 -0
  71. package/packages/reploid/src/mesh/partitions/partition-discovery.js +96 -0
  72. package/packages/reploid/src/mesh/partitions/partition-entry-publication.js +183 -0
  73. package/packages/reploid/src/mesh/partitions/partition-entry.js +434 -0
  74. package/packages/reploid/src/mesh/partitions/partition-generation-request.js +33 -0
  75. package/packages/reploid/src/mesh/partitions/partition-grants.js +277 -0
  76. package/packages/reploid/src/mesh/partitions/partition-link.js +103 -0
  77. package/packages/reploid/src/mesh/partitions/partition-network.js +109 -0
  78. package/packages/reploid/src/mesh/partitions/partition-ordered-chat.js +290 -0
  79. package/packages/reploid/src/mesh/partitions/partition-ordered-peer.js +415 -0
  80. package/packages/reploid/src/mesh/partitions/partition-ordered-publication.js +100 -0
  81. package/packages/reploid/src/mesh/partitions/partition-peer.js +314 -0
  82. package/packages/reploid/src/mesh/partitions/partition-placement.js +143 -0
  83. package/packages/reploid/src/mesh/partitions/partition-preparation-progress.js +25 -0
  84. package/packages/reploid/src/mesh/partitions/partition-receiver-policy.json +7 -0
  85. package/packages/reploid/src/mesh/partitions/partition-reservations.js +75 -0
  86. package/packages/reploid/src/mesh/partitions/partition-route-envelope-policy.json +16 -0
  87. package/packages/reploid/src/mesh/partitions/partition-route-envelope.js +74 -0
  88. package/packages/reploid/src/mesh/partitions/partition-route-execution.js +409 -0
  89. package/packages/reploid/src/mesh/partitions/partition-route-network.js +179 -0
  90. package/packages/reploid/src/mesh/partitions/partition-route-ranking.js +268 -0
  91. package/packages/reploid/src/mesh/partitions/partition-runner.js +319 -0
  92. package/packages/reploid/src/mesh/partitions/partition-stage-assignment.js +109 -0
  93. package/packages/reploid/src/mesh/partitions/partition-stage-commit.js +103 -0
  94. package/packages/reploid/src/mesh/partitions/partition-step-receiver.js +291 -0
  95. package/packages/reploid/src/mesh/partitions/partition-summary.js +122 -0
  96. package/packages/reploid/src/mesh/partitions/preparation-owner.js +40 -0
  97. package/packages/reploid/src/mesh/partitions/resident-error-codes.json +10 -0
  98. package/packages/reploid/src/mesh/partitions/resident-partition.js +333 -0
  99. package/packages/reploid/src/mesh/partitions/resident-route.js +46 -0
  100. package/packages/reploid/src/mesh/partitions/signed-resident-factory.js +59 -0
  101. package/packages/reploid/src/mesh/peer-generation.js +896 -0
  102. package/packages/reploid/src/mesh/peer-identity.js +87 -0
  103. package/packages/reploid/src/mesh/placement-beliefs.js +107 -0
  104. package/packages/reploid/src/mesh/preparation-progress.js +46 -0
  105. package/packages/reploid/src/mesh/provider-hardware.js +11 -0
  106. package/packages/reploid/src/mesh/remote-generation-requests.js +53 -0
  107. package/packages/reploid/src/mesh/swarm-coordination.js +140 -0
  108. package/packages/reploid/src/mesh/web-access-network.js +112 -0
  109. package/packages/reploid/src/mesh/web-access-policy.json +17 -0
  110. package/packages/reploid/src/retrieval/citations.js +156 -0
  111. package/packages/reploid/src/retrieval/claim-support.js +113 -0
  112. package/packages/reploid/src/retrieval/costs.js +101 -0
  113. package/packages/reploid/src/retrieval/fixed-provider.js +34 -0
  114. package/packages/reploid/src/retrieval/index.js +20 -0
  115. package/packages/reploid/src/retrieval/lexical-support.js +27 -0
  116. package/packages/reploid/src/retrieval/model-reviewer.js +67 -0
  117. package/packages/reploid/src/retrieval/page-fetch.json +10 -0
  118. package/packages/reploid/src/retrieval/page-text.js +182 -0
  119. package/packages/reploid/src/retrieval/passage.js +37 -0
  120. package/packages/reploid/src/retrieval/policy.json +14 -0
  121. package/packages/reploid/src/retrieval/retrieval.js +23 -0
  122. package/packages/reploid/src/retrieval/review-queue.js +76 -0
  123. package/packages/reploid/src/retrieval/sources.js +263 -0
  124. package/packages/reploid/src/retrieval/support-review.js +155 -0
  125. package/packages/reploid/src/retrieval/text.js +21 -0
  126. package/packages/reploid/src/rules/contribution.rules.json +8 -0
  127. package/packages/reploid/src/rules/routing.rules.json +24 -0
  128. package/packages/reploid/src/transport/assignment.js +571 -0
  129. package/packages/reploid/src/transport/bounded-channel-writer.js +46 -0
  130. package/packages/reploid/src/transport/index.js +11 -0
  131. package/packages/reploid/src/transport/introduction-admission.js +24 -0
  132. package/packages/reploid/src/transport/introduction-bootstrap.js +112 -0
  133. package/packages/reploid/src/transport/introduction-policy.json +12 -0
  134. package/packages/reploid/src/transport/introduction-records.js +90 -0
  135. package/packages/reploid/src/transport/introductions.js +209 -0
  136. package/packages/reploid/src/transport/partition-data-channel.js +421 -0
  137. package/packages/reploid/src/transport/partition-errors.json +16 -0
  138. package/packages/reploid/src/transport/retry-policy.js +36 -0
  139. package/packages/reploid/src/transport/room.js +502 -0
  140. package/packages/reploid/src/transport/sdp-fingerprint.js +5 -0
  141. package/packages/reploid/src/transport/signaling.js +571 -0
  142. package/packages/reploid/src/transport/swarm.js +1247 -0
  143. package/packages/reploid/src/transport/tool-offer-channel.js +137 -0
  144. package/server/browser-roots.js +42 -0
  145. package/server/browser-web-worker.js +94 -0
  146. package/server/chat-completions.js +45 -0
  147. package/server/fleet/browser-bridge.js +145 -0
  148. package/server/fleet/contract.js +42 -0
  149. package/server/fleet/credit-evidence.js +103 -0
  150. package/server/fleet/credit-recovery.js +175 -0
  151. package/server/fleet/credits.js +178 -0
  152. package/server/fleet/execution-admission.js +32 -0
  153. package/server/fleet/native-host.js +817 -0
  154. package/server/fleet/placement.js +132 -0
  155. package/server/fleet/requester.js +346 -0
  156. package/server/fleet/service.js +311 -0
  157. package/server/fleet/terminal-policy.js +83 -0
  158. package/server/fleet/text-api.js +94 -0
  159. package/server/hashing.js +35 -0
  160. package/server/http-request-owner.js +49 -0
  161. package/server/messages.js +57 -0
  162. package/server/native-canonical-epochs.js +90 -0
  163. package/server/native-change-log.js +40 -0
  164. package/server/native-earning.js +203 -0
  165. package/server/native-generation-journal.js +46 -0
  166. package/server/native-model-config.js +57 -0
  167. package/server/native-model-files.js +382 -0
  168. package/server/native-model-origin.js +54 -0
  169. package/server/native-model-origins.json +12 -0
  170. package/server/native-node.js +83 -0
  171. package/server/native-owner/controls.js +162 -0
  172. package/server/native-owner/monitor.js +251 -0
  173. package/server/native-owner/policy.js +273 -0
  174. package/server/native-owner/rate.js +92 -0
  175. package/server/native-participant.js +866 -0
  176. package/server/native-readiness-log.js +30 -0
  177. package/server/native-release-storage.js +64 -0
  178. package/server/native-shader-cache.js +369 -0
  179. package/server/native-supply-budget.js +66 -0
  180. package/server/native-whole-earning.js +67 -0
  181. package/server/native-whole-model-fill.js +182 -0
  182. package/server/native-whole-model.js +130 -0
  183. package/server/public-web-worker.js +66 -0
  184. package/server/responses.js +92 -0
  185. package/server/search/errors.js +47 -0
  186. package/server/search/page-fetch.js +185 -0
  187. package/server/text-api.js +83 -0
  188. package/server/text-recovery.js +45 -0
  189. package/server/text-request-options.js +23 -0
  190. package/server/text-requester.js +231 -0
  191. package/server/token-auth.js +9 -0
  192. package/server/whole-model-requester.js +99 -0
  193. package/shared/config/chat-models.json +4685 -0
  194. package/shared/config/doppler-execution-contracts.js +32 -0
  195. package/shared/config/doppler-execution-contracts.json +43 -0
  196. package/shared/config/doppler-generation-contract.js +223 -0
  197. package/shared/config/doppler-local-models.js +79 -0
  198. package/shared/config/doppler-package.json +7 -0
  199. package/shared/config/model-manifests/a0dc69e917133a82780823d17fc771c0f6b882d7c86c571deeaef45be2ff108b.json +6434 -0
  200. package/shared/config/model-manifests/e985e3cdad60d0cb57d84b436161e66ab5b3f6589a168de6f00b4610e5f1fb59.json +16534 -0
  201. package/shared/config/model-manifests/fa6eb7bbc3ba63571f8cede780b877d9272bde948697af93dd3d33837cb46137.json +7175 -0
  202. package/shared/config/model-pieces/qwen-0-8b-pieces.json +1506 -0
  203. package/shared/config/model-pieces/qwen-2b-pieces.json +4800 -0
  204. package/shared/config/model-pieces/qwen35b-q4_0-pieces.json +28880 -0
  205. package/shared/config/reploid-library.json +49 -0
  206. package/shared/config/swarm-bootstrap.json +21 -0
  207. package/shared/infrastructure/doppler-runtime-service.js +261 -0
  208. package/shared/pool/executable-pack.js +87 -0
  209. package/shared/pool/pack-operation-adapters.js +124 -0
  210. package/shared/pool/pack-operation-policy.js +75 -0
  211. package/shared/pool/pool-config.json +2280 -0
  212. package/shared/vendor/reploid/adapters/doppler-session.js +372 -0
  213. package/shared/vendor/reploid/artifacts/binary.js +25 -0
  214. package/shared/vendor/reploid/artifacts/canonical-json.js +23 -0
  215. package/shared/vendor/reploid/artifacts/delivery-attestation.js +64 -0
  216. package/shared/vendor/reploid/artifacts/identity.js +91 -0
  217. package/shared/vendor/reploid/artifacts/manifest-identity.js +17 -0
  218. package/shared/vendor/reploid/artifacts/participant-proofs.js +159 -0
  219. package/shared/vendor/reploid/artifacts/signatures.js +94 -0
  220. package/shared/vendor/reploid/config/defaults.json +110 -0
  221. package/shared/vendor/reploid/config/index.js +209 -0
  222. package/shared/vendor/reploid/config/request-overrides.json +9 -0
  223. package/shared/vendor/reploid/hashing.js +30 -0
  224. package/shared/vendor/reploid/mesh/generation-context-cache.js +97 -0
  225. package/shared/vendor/reploid/mesh/partitions/partition-attempt-evidence.js +282 -0
  226. package/shared/vendor/reploid/mesh/partitions/partition-contract.js +192 -0
  227. package/shared/vendor/reploid/mesh/partitions/partition-receiver-policy.json +7 -0
  228. package/shared/vendor/reploid/mesh/partitions/partition-route-ranking.js +268 -0
  229. package/shared/vendor/reploid/mesh/preparation-progress.js +46 -0
  230. package/shared/vendor/reploid/mesh/provider-hardware.js +11 -0
  231. package/shared/vendor/reploid/rules/routing.rules.json +24 -0
  232. package/shared/vendor/reploid/transport/partition-errors.json +16 -0
  233. package/README.md +0 -3
@@ -0,0 +1,434 @@
1
+ import { generationRequest, requireGenerationCapability, tokenUsage } from './partition-generation-request.js';
2
+ import { createPartitionDataChannel } from '../../transport/partition-data-channel.js';
3
+ import { assertPartition as assert, assertCapacity, canonicalPartitionJson, canonicalRouteAttemptBinding, sameRouteAttemptIdentity } from './partition-contract.js';
4
+ import { partitionActivity, summarizePartitionExecution } from './partition-summary.js';
5
+ import { createEntryPublicationScope, entryPublicationEnvelope, entryPublicationPort, matchingEntryPublication,
6
+ validateEntryPublicationContext } from './partition-entry-publication.js';
7
+ import { validateOrderedPublicationContext } from './partition-ordered-publication.js';
8
+ import { isChargeBindingShape } from './partition-attempt-evidence.js';
9
+
10
+ /** Requester-to-A channel. This module imports no tokenizer, tensor codec or GPU runtime.
11
+ * The host authenticates the channel and grants input disclosure to both stages.
12
+ * A's chat port owns the A-to-B execution channel; activation bytes never enter here.
13
+ * An ordered input may carry the requester's signed charge binding; the coordinator then
14
+ * returns each output with its final-stage receipt and carries the requester's
15
+ * acknowledgment back to the route.
16
+ * An ordered requester that opts in with `attemptState` receives the coordinator's admission
17
+ * state (`queued` while it waits for route capacity, `executing` once admitted); nothing else.
18
+ */
19
+ export const ATTEMPT_STATE_SCHEMA = 'reploid.partition-attempt-state/v1';
20
+ const ATTEMPT_STATES = Object.freeze(['queued', 'executing']);
21
+ export function createPartitionEntry({ channel, localParticipantId, remoteParticipantId,
22
+ service = null, canonical = false, ordered = false, authorize, limits, inputLimits, now = Date.now }) {
23
+ assert(typeof authorize === 'function' && ['maxInputCharacters', 'maxOutputCharacters', 'maxAttempts',
24
+ 'maxConcurrentAttempts', 'descriptorTtlMs'].every(key => Number.isSafeInteger(inputLimits?.[key]) && inputLimits[key] > 0),
25
+ 'Entry authorization and input budgets required');
26
+ assert(typeof ordered === 'boolean' && !(ordered && canonical), 'Explicit distinct ordinary ordered entry capability required');
27
+ assert(typeof canonical === 'boolean', 'Explicit canonical entry capability required');
28
+ const policy = structuredClone(inputLimits), active = new Map(), retired = new Set();
29
+ const deliveries = new Map(), unsettledPublications = new Set();
30
+ let draining = false, closed = false, descriptor = null, observedAt = 0;
31
+ const orderedInput = m => m?.schema === 'reploid.partition-input/v3';
32
+ const coordinator = m => orderedInput(m) ? m.coordinatorId : m.participantA;
33
+ const attempt = m => canonicalRouteAttemptBinding({ schema: 'reploid.partition-attempt/v2',
34
+ route: m.route, threadId: m.threadId, attemptId: m.attemptId,
35
+ requesterId: m.requesterId, placementGeneration: m.placementGeneration });
36
+ function validGeneration(m) {
37
+ try { return !generationRequest(m.generationRequest) || m.schema !== 'reploid.partition-input/v2'; } catch { return false; }
38
+ }
39
+ function validMode(m) {
40
+ if (m.activity !== undefined && (!orderedInput(m) || m.activity !== 'reploid.partition-activity/v1')) return false;
41
+ if (m.attemptState !== undefined && (!orderedInput(m) || m.attemptState !== ATTEMPT_STATE_SCHEMA)) return false;
42
+ if (orderedInput(m)) {
43
+ try {
44
+ return ordered && (m.disclosureExpiresAt === undefined || Number.isSafeInteger(m.disclosureExpiresAt) && m.disclosureExpiresAt > now()) && m.canonical === undefined && m.participantA === undefined && m.participantB === undefined
45
+ && (m.publication === undefined || !!validateOrderedPublicationContext(m.publication))
46
+ && attempt(m).route.stages[0].participantId === m.coordinatorId
47
+ && m.route.modelId === m.modelId && m.route.modelIdentity === m.modelIdentity && m.route.planId === m.planId;
48
+ } catch { return false; }
49
+ }
50
+ return (m?.schema === 'reploid.partition-input/v1' && m.canonical === undefined && m.route === undefined
51
+ || canonical && m?.schema === 'reploid.partition-input/v2' && !!validateEntryPublicationContext(m.canonical, m))
52
+ && m.participantA !== m.participantB;
53
+ }
54
+ const validCharge = m => m.charge === undefined || orderedInput(m) && isChargeBindingShape(m.charge, m);
55
+ const valid = m => m?.operation === 'generate' && validMode(m) && validGeneration(m) && validCharge(m) && m.requesterId !== coordinator(m)
56
+ && typeof m.attemptId === 'string' && m.attemptId.length <= 128
57
+ && typeof m.threadId === 'string' && m.threadId.length <= 128
58
+ && Number.isSafeInteger(m.placementGeneration) && m.placementGeneration >= 0
59
+ && Array.isArray(m.messages) && m.messages.length > 0
60
+ && m.messages.every(row => ['system', 'user', 'assistant'].includes(row.role) && typeof row.content === 'string')
61
+ && JSON.stringify(m.messages).length <= policy.maxInputCharacters;
62
+ const endpoint = createPartitionDataChannel({ channel, localParticipantId, remoteParticipantId, limits,
63
+ async authorize({ action, metadata, byteLength }) {
64
+ if (byteLength !== 0) return false;
65
+ if (metadata.operation === 'describe') return true;
66
+ if (metadata.operation === 'publication') {
67
+ const sending = action === 'send' || action === 'accept';
68
+ const request = (sending ? active : deliveries).get(metadata.attemptId)?.request;
69
+ return (canonical || ordered) && !!request && matchingEntryPublication(metadata, request)
70
+ && request.requesterId === (sending ? remoteParticipantId : localParticipantId)
71
+ && await authorize(structuredClone(request), { action }) === true;
72
+ }
73
+ if (metadata.operation === 'state') {
74
+ // Admission state only, bound to an opted-in ordered attempt in flight on this channel.
75
+ const sending = action === 'send' || action === 'accept';
76
+ const request = (sending ? active : deliveries).get(metadata.attemptId)?.request;
77
+ return !!request && orderedInput(request) && request.attemptState === ATTEMPT_STATE_SCHEMA
78
+ && metadata.requesterId === request.requesterId && metadata.requesterId === (sending ? remoteParticipantId : localParticipantId)
79
+ && metadata.coordinatorId === request.coordinatorId && metadata.threadId === request.threadId
80
+ && sameRouteAttemptIdentity(metadata.identity, attempt(request)) && ATTEMPT_STATES.includes(metadata.status);
81
+ }
82
+ if (metadata.operation === 'closed') {
83
+ const sending = action === 'send' || action === 'accept';
84
+ const request = (sending ? active : deliveries).get(metadata.attemptId)?.request;
85
+ return !!request?.charge && sameRouteAttemptIdentity(metadata.identity, attempt(request))
86
+ && metadata.requesterId === request.requesterId && metadata.coordinatorId === request.coordinatorId;
87
+ }
88
+ if (metadata.operation === 'output') {
89
+ const sending = action === 'send' || action === 'accept';
90
+ const request = sending ? active.get(metadata.attemptId)?.request : deliveries.get(metadata.attemptId)?.request;
91
+ return !!request && orderedInput(request) && request.charge !== undefined && metadata.requesterId === request.requesterId
92
+ && metadata.requesterId === (sending ? remoteParticipantId : localParticipantId)
93
+ && metadata.coordinatorId === request.coordinatorId && metadata.threadId === request.threadId
94
+ && sameRouteAttemptIdentity(metadata.identity, attempt(request)) && Number.isSafeInteger(metadata.step) && metadata.step >= 0
95
+ && typeof metadata.delta === 'string' && metadata.delta.length <= policy.maxOutputCharacters && typeof metadata.done === 'boolean'
96
+ && (metadata.receipt === null || !!metadata.receipt && typeof metadata.receipt === 'object' && !Array.isArray(metadata.receipt));
97
+ }
98
+ if (metadata.operation === 'delta' || metadata.operation === 'usage') {
99
+ const sending = action === 'send' || action === 'accept';
100
+ const request = sending ? active.get(metadata.attemptId)?.request : deliveries.get(metadata.attemptId)?.request;
101
+ return !!request && request.schema !== 'reploid.partition-input/v2'
102
+ && (!orderedInput(request) || request.disclosureExpiresAt === undefined || request.disclosureExpiresAt > now()) && metadata.requesterId === request.requesterId
103
+ && (orderedInput(request) ? metadata.coordinatorId === request.coordinatorId
104
+ && sameRouteAttemptIdentity(metadata.identity, attempt(request)) : metadata.participantA === request.participantA) && metadata.threadId === request.threadId
105
+ && metadata.requesterId === (sending ? remoteParticipantId : localParticipantId)
106
+ && (metadata.activity === undefined || request.activity === 'reploid.partition-activity/v1'
107
+ && orderedInput(request) && sameRouteAttemptIdentity(metadata.activity?.identity, attempt(request)))
108
+ && (metadata.operation === 'usage' ? !!request.generationRequest
109
+ && canonicalPartitionJson(metadata.generationRequest) === canonicalPartitionJson(request.generationRequest)
110
+ && metadata.usage?.outputTokens === 0
111
+ && canonicalPartitionJson(metadata.usage) === canonicalPartitionJson(tokenUsage(metadata.usage?.inputTokens, 0, request.generationRequest))
112
+ : Number.isSafeInteger(metadata.sequence) && metadata.sequence >= 0
113
+ && typeof metadata.text === 'string' && metadata.text.length <= policy.maxOutputCharacters);
114
+ }
115
+ const outgoing = action === 'send' || action === 'accept';
116
+ if (!valid(metadata) || metadata.requesterId !== (outgoing ? localParticipantId : remoteParticipantId)
117
+ || coordinator(metadata) !== (outgoing ? remoteParticipantId : localParticipantId)) return false;
118
+ // Recheck input permission before transfer and output disclosure, not readiness
119
+ // after completion: draining must still let admitted work finish.
120
+ return await authorize(structuredClone(metadata), { action }) === true;
121
+ },
122
+ async serve(m, _bytes, { signal }) {
123
+ if (m.operation === 'publication') {
124
+ const scope = deliveries.get(m.attemptId)?.publication;
125
+ assert(scope, 'Requester publication owner unavailable');
126
+ return scope.call(m.method, m.body);
127
+ }
128
+ if (m.operation === 'state') {
129
+ const delivery = deliveries.get(m.attemptId);
130
+ assert(delivery, 'Unexpected attempt state');
131
+ await delivery.onState?.(m.status); return { received: true };
132
+ }
133
+ if (m.operation === 'closed') {
134
+ const delivery = deliveries.get(m.attemptId);
135
+ assert(delivery, 'Unexpected accounting closure');
136
+ delivery.accountingClosed.resolve(m.settlement ?? null);
137
+ return { received: true };
138
+ }
139
+ if (m.operation === 'output') {
140
+ // The requester's own port decides whether this output is acknowledged; only its signed answer returns.
141
+ const delivery = deliveries.get(m.attemptId);
142
+ assert(delivery, 'Unexpected attempt output');
143
+ const acknowledged = await delivery.onOutput?.({ step: m.step, delta: m.delta, done: m.done, receipt: structuredClone(m.receipt) });
144
+ return { received: true, acknowledged: acknowledged ?? null };
145
+ }
146
+ if (m.operation === 'usage') {
147
+ const delivery = deliveries.get(m.attemptId);
148
+ assert(delivery && !delivery.usage && delivery.sequence === 0, 'Unexpected or duplicate input token usage');
149
+ delivery.usage = structuredClone(m.usage);
150
+ await delivery.onUsage?.(structuredClone(m.usage)); return {received: true};
151
+ }
152
+ if (m.operation === 'delta') {
153
+ const delivery = deliveries.get(m.attemptId);
154
+ assert(delivery && (!delivery.request.generationRequest || delivery.usage) && m.sequence === delivery.sequence, 'Stream delta is stale or out of order');
155
+ if (m.activity) {
156
+ const activity = partitionActivity(m.activity, attempt(delivery.request), delivery.activity, true);
157
+ delivery.activity = activity;
158
+ await delivery.onActivity?.(structuredClone(activity));
159
+ }
160
+ delivery.characters += m.text.length;
161
+ assert(delivery.characters <= policy.maxOutputCharacters, 'Stream output budget exhausted');
162
+ delivery.sequence++; if (orderedInput(delivery.request)) delivery.content += m.text; delivery.onDelta?.(m.text); return { received: true };
163
+ }
164
+ if (m.operation === 'describe') {
165
+ if (service && !draining && !closed) await service.refresh({ signal });
166
+ const models = service?.getModels() || [];
167
+ return { models: structuredClone(models), accepting: !!service && !draining && !closed,
168
+ slots: draining || closed ? 0 : policy.maxConcurrentAttempts - active.size };
169
+ }
170
+ // A draining, closed or full entry is unavailable capacity for this requester, never a generic failure.
171
+ assertCapacity(service && !draining && !closed && active.size < policy.maxConcurrentAttempts);
172
+ assert(!retired.has(m.attemptId), 'Entry attempt already used');
173
+ assertCapacity(retired.size < policy.maxAttempts);
174
+ const model = service.getModels().find(model => model.id === m.modelId && model.identity === m.modelIdentity
175
+ && model.partition?.planId === m.planId && (orderedInput(m)
176
+ ? model.partition.schema === 'reploid.partition-selection/v2' && model.partition.coordinatorId === m.coordinatorId
177
+ && canonicalPartitionJson(model.partition.route) === canonicalPartitionJson(m.route)
178
+ : model.partition.participantA === m.participantA && model.partition.participantB === m.participantB)
179
+ && model.availability === 'ready');
180
+ assertCapacity(model);
181
+ const requested = requireGenerationCapability(model, m.generationRequest, m.schema === 'reploid.partition-input/v2');
182
+ const isCanonical = m.schema === 'reploid.partition-input/v2';
183
+ if (isCanonical) {
184
+ assert(model.canonical && ['coordinatorEpoch', 'routeId', 'generation', 'stages', 'vocabSize'].every(key =>
185
+ canonicalPartitionJson(model.canonical[key]) === canonicalPartitionJson(m.canonical[key])),
186
+ 'Canonical entry placement changed');
187
+ }
188
+ // Ordered inputs carrying a requester context publish through the same requester-owned RPC.
189
+ const orderedPublished = orderedInput(m) && m.publication !== undefined;
190
+ const publicationCall = (method, body) => endpoint.request(entryPublicationEnvelope(m, method, body),
191
+ new Uint8Array(), { signal });
192
+ const publication = isCanonical || orderedPublished ? entryPublicationPort(publicationCall) : undefined;
193
+ retired.add(m.attemptId);
194
+ const admission = { request: structuredClone(m), operation: null };
195
+ active.set(m.attemptId, admission);
196
+ let delivery = Promise.resolve(), sequence = 0, activity = null, acceptingCallbacks = true;
197
+ const operation = Promise.resolve().then(() => service.generate({ meshId: m.meshId, participantId: m.requesterId,
198
+ threadId: m.threadId, attemptId: m.attemptId, placementGeneration: m.placementGeneration,
199
+ model, ...(requested ? {generationRequest: requested} : {}), ...(orderedInput(m) && m.disclosureExpiresAt !== undefined ? {disclosureExpiresAt:m.disclosureExpiresAt} : {}), ...(isCanonical ? { canonical: structuredClone(m.canonical) } : {}),
200
+ ...(orderedPublished ? { publication: structuredClone(m.publication) } : {}), ...(m.charge !== undefined ? { charge: structuredClone(m.charge) } : {}),
201
+ messages: structuredClone(m.messages), permissions: { sharingScope: 'approved-partition-path' } },
202
+ { signal, publication, requestApproval: async () => authorize(structuredClone(m), { action: 'execute' }),
203
+ ...(m.charge !== undefined ? { onOutput(record) {
204
+ if (!acceptingCallbacks) return null;
205
+ return endpoint.request({ operation: 'output', requesterId: m.requesterId, coordinatorId: m.coordinatorId, identity: attempt(m),
206
+ threadId: m.threadId, attemptId: m.attemptId, step: record.step, delta: record.delta, done: record.done, receipt: record.receipt ?? null },
207
+ new Uint8Array()).then(response => response?.acknowledged ?? null);
208
+ } } : {}),
209
+ onState(value) {
210
+ // Older requesters did not opt in; an opted-in one learns only queued/executing for this attempt.
211
+ if (m.attemptState === undefined || !acceptingCallbacks || !ATTEMPT_STATES.includes(value?.status)
212
+ || value.threadId !== m.threadId || value.attemptId !== m.attemptId) return;
213
+ const metadata = { operation: 'state', requesterId: m.requesterId, coordinatorId: m.coordinatorId, identity: attempt(m),
214
+ threadId: m.threadId, attemptId: m.attemptId, status: value.status };
215
+ delivery = delivery.then(() => endpoint.request(metadata, new Uint8Array(), { signal }));
216
+ delivery.catch(() => {});
217
+ }, onActivity(value) {
218
+ if (m.activity === undefined) return; // Older requesters did not opt in to this event.
219
+ assert(acceptingCallbacks && orderedInput(m) && value.threadId === m.threadId && value.attemptId === m.attemptId, 'Unbound or late partition activity');
220
+ activity = partitionActivity(value, attempt(m), activity);
221
+ }, onUsage(value) {
222
+ assert(requested && value.threadId === m.threadId && value.attemptId === m.attemptId, 'Unbound provider usage');
223
+ const usage = tokenUsage(value.inputTokens, value.outputTokens, requested);
224
+ assert(value.outputTokens === 0 && value.schema === usage.schema, 'Initial usage must precede sampling');
225
+ const metadata = {operation:'usage', requesterId:m.requesterId,
226
+ ...(orderedInput(m) ? {coordinatorId:m.coordinatorId, identity:attempt(m)} : {participantA:m.participantA}),
227
+ threadId:m.threadId, attemptId:m.attemptId, generationRequest:requested, usage};
228
+ delivery = delivery.then(() => endpoint.request(metadata, new Uint8Array(), {signal}));
229
+ delivery.catch(() => {}); return delivery;
230
+ }, onDelta({ text }) {
231
+ if (isCanonical || orderedPublished) return; // Requester projects the durable publication RPC, never this raw callback.
232
+ const delta = { operation: 'delta', requesterId: m.requesterId,
233
+ ...(orderedInput(m) ? { coordinatorId: m.coordinatorId, identity: attempt(m) } : { participantA: m.participantA }),
234
+ threadId: m.threadId, attemptId: m.attemptId, sequence: sequence++, text,
235
+ ...(activity ? {activity:structuredClone(activity)} : {}) };
236
+ delivery = delivery.then(() => endpoint.request(delta, new Uint8Array(), { signal }));
237
+ delivery.catch(() => {});
238
+ } }));
239
+ admission.operation = operation;
240
+ let settlement = null;
241
+ try {
242
+ const result = await operation;
243
+ settlement = result.execution?.settlement ?? null;
244
+ acceptingCallbacks = false;
245
+ await delivery;
246
+ assert(typeof result.content === 'string' && result.content.length <= policy.maxOutputCharacters
247
+ && (orderedInput(m) ? sameRouteAttemptIdentity(result.execution?.identity, attempt(m))
248
+ : result.execution?.requesterId === m.requesterId && result.execution.attemptId === m.attemptId
249
+ && result.execution.placementGeneration === m.placementGeneration), 'Execution returned an unbound result');
250
+ return { content: result.content, ...(activity ? {activity:structuredClone(activity)} : {}), ...(requested ? {usage: result.usage} : {}), execution: summarizePartitionExecution(result.execution) };
251
+ } catch (error) {
252
+ settlement ??= error.partitionSettlement ?? null;
253
+ throw error;
254
+ } finally {
255
+ acceptingCallbacks = false;
256
+ if (m.charge) await endpoint.request({ operation: 'closed', requesterId: m.requesterId, coordinatorId: m.coordinatorId,
257
+ identity: attempt(m), attemptId: m.attemptId, settlement }, new Uint8Array()).catch(() => {});
258
+ active.delete(m.attemptId);
259
+ }
260
+ },
261
+ });
262
+ return Object.freeze({
263
+ id: remoteParticipantId,
264
+ getState() { return { ready: !closed && unsettledPublications.size === 0 && now() - observedAt < policy.descriptorTtlMs
265
+ && descriptor?.accepting === true && descriptor.slots > 0,
266
+ descriptor: structuredClone(descriptor), observedAt, receipt: endpoint.getReceipt() }; },
267
+ async refresh({ signal } = {}) {
268
+ descriptor = await endpoint.request({ operation: 'describe' }, new Uint8Array(), { signal });
269
+ assert(Array.isArray(descriptor.models) && Number.isSafeInteger(descriptor.slots) && descriptor.slots >= 0,
270
+ 'Invalid entry descriptor');
271
+ observedAt = now(); return this.getState();
272
+ },
273
+ async generate(request, { signal, onDelta, onUsage, onActivity, onOutput, onState, publication, onPublished } = {}) {
274
+ assertCapacity(!closed && this.getState().ready);
275
+ assert(request.charge === undefined || typeof onOutput === 'function', 'A charged ordered input needs its acknowledgment port');
276
+ const isCanonical = request.canonical !== undefined, isOrdered = request.route !== undefined;
277
+ assert(!isOrdered || ordered && !isCanonical, 'Ordered entry capability unavailable');
278
+ assert(!isCanonical || canonical, 'Canonical entry capability unavailable');
279
+ assert((publication !== undefined) === (isCanonical || isOrdered && request.publication !== undefined),
280
+ 'Publication owner requires its explicit canonical or ordered requester context');
281
+ const metadata = { ...structuredClone(request), operation: 'generate',
282
+ schema: isOrdered ? 'reploid.partition-input/v3' : isCanonical ? 'reploid.partition-input/v2' : 'reploid.partition-input/v1',
283
+ ...(isOrdered && typeof onActivity === 'function' ? {activity:'reploid.partition-activity/v1'} : {}),
284
+ ...(isOrdered && typeof onState === 'function' ? { attemptState: ATTEMPT_STATE_SCHEMA } : {}),
285
+ requesterId: localParticipantId, ...(isOrdered ? { coordinatorId: remoteParticipantId } : { participantA: remoteParticipantId }) };
286
+ assert(!deliveries.has(metadata.attemptId), 'Entry attempt already streaming');
287
+ assert(valid(metadata), 'Invalid partition entry input');
288
+ const scope = publication !== undefined ? createEntryPublicationScope({ request: metadata, owner: publication, onPublished,
289
+ authorize: () => authorize(structuredClone(metadata), { action: 'publish' }),
290
+ maxControlBytes: limits.maxControlBytes, maxOutputCharacters: policy.maxOutputCharacters }) : null;
291
+ const accountingClosed = Promise.withResolvers();
292
+ deliveries.set(metadata.attemptId, { accountingClosed, request: metadata, sequence: 0, characters: 0, content: '', onDelta, onUsage, onActivity, onOutput, onState, activity:null, usage:null, publication: scope });
293
+ let result;
294
+ let failure = null;
295
+ try {
296
+ result = await endpoint.request(metadata, new Uint8Array(), { signal });
297
+ assert(typeof result.content === 'string' && result.content.length <= policy.maxOutputCharacters
298
+ && (isOrdered ? sameRouteAttemptIdentity(result.execution?.identity, attempt(metadata))
299
+ : ['requesterId', 'participantA', 'participantB', 'modelId', 'modelIdentity', 'planId', 'threadId',
300
+ 'attemptId', 'placementGeneration'].every(key => result.execution?.[key] === metadata[key])),
301
+ 'Entry response identity mismatch');
302
+ const currentDelivery = deliveries.get(metadata.attemptId);
303
+ let finalActivityNotification = null;
304
+ if (result.activity) {
305
+ assert(metadata.activity === 'reploid.partition-activity/v1', 'Unrequested execution activity');
306
+ if (currentDelivery.activity?.sequence === result.activity.sequence) {
307
+ assert(canonicalPartitionJson(currentDelivery.activity) === canonicalPartitionJson(result.activity), 'Final activity changed an observed sample');
308
+ } else {
309
+ const finalActivity = partitionActivity(result.activity, attempt(metadata), currentDelivery.activity, true);
310
+ finalActivityNotification = finalActivity;
311
+ }
312
+ }
313
+ const observedActivity = finalActivityNotification ?? currentDelivery.activity;
314
+ if (observedActivity) assert(canonicalPartitionJson(result.execution.stepSummary.stages) === canonicalPartitionJson(observedActivity.stepSummary.stages)
315
+ && result.execution.stepSummary.count === observedActivity.stepSummary.count, 'Final execution differs from observed activity');
316
+ if (metadata.generationRequest) {
317
+ const observed = deliveries.get(metadata.attemptId).usage;
318
+ assert(observed && result.usage?.inputTokens === observed.inputTokens
319
+ && result.usage.outputTokens === result.execution?.stepSummary?.count
320
+ && canonicalPartitionJson(result.usage) === canonicalPartitionJson(tokenUsage(result.usage.inputTokens, result.usage.outputTokens, metadata.generationRequest)),
321
+ 'Final token usage differs from admitted observed input');
322
+ }
323
+ if (isOrdered && !scope) assert(result.content === deliveries.get(metadata.attemptId).content, 'Ordered result differs from delivered text');
324
+ if (scope) {
325
+ const projection = scope.getProjection();
326
+ assert(projection.count > 0 && projection.terminal && result.content === projection.content, 'Entry result differs from durable publication');
327
+ }
328
+ if (finalActivityNotification) {
329
+ currentDelivery.activity = finalActivityNotification;
330
+ await onActivity?.(structuredClone(finalActivityNotification));
331
+ }
332
+ }
333
+ catch (error) { failure = error; }
334
+ finally {
335
+ // Cancellation stops generation, not already-issued signed output receipts. Keep their
336
+ // receiving port until the coordinator closes accounting, or the channel's bounded wait.
337
+ if (failure && metadata.charge) {
338
+ let timer;
339
+ try {
340
+ const settlement = await Promise.race([accountingClosed.promise,
341
+ new Promise(resolve => { timer = setTimeout(() => resolve(null), limits.timeoutMs); })]);
342
+ if (settlement && typeof failure === 'object') failure.partitionSettlement = settlement;
343
+ } finally { clearTimeout(timer); }
344
+ }
345
+ try { await scope?.close({ cancel: failure !== null }); }
346
+ catch (error) {
347
+ unsettledPublications.add(scope);
348
+ failure = failure ? new AggregateError([failure, error], 'Entry execution and publication cancellation failed') : error;
349
+ }
350
+ deliveries.delete(metadata.attemptId);
351
+ }
352
+ if (failure) throw failure;
353
+ return result;
354
+ },
355
+ async drain() { draining = true; await Promise.allSettled([...active.values()].map(item => item.operation)); },
356
+ async close() {
357
+ closed = true; endpoint.close();
358
+ const scopes = [...new Set([...unsettledPublications, ...[...deliveries.values()].map(item => item.publication).filter(Boolean)])];
359
+ const closing = await Promise.allSettled(scopes.map(async scope => {
360
+ unsettledPublications.add(scope);
361
+ await scope.close({ cancel: true }); unsettledPublications.delete(scope);
362
+ }));
363
+ await Promise.allSettled([...active.values()].map(item => item.operation));
364
+ const failures = closing.filter(item => item.status === 'rejected').map(item => item.reason);
365
+ if (failures.length) throw new AggregateError(failures, 'Entry publication cancellation did not settle');
366
+ deliveries.clear();
367
+ },
368
+ });
369
+ }
370
+
371
+ /** Bounded retry starts a new generation attempt on an explicitly authorized path.
372
+ * No partial generation state is fabricated or merged across owners.
373
+ */
374
+ export function createPartitionRequester({ entries, requesterId, meshId, modelId, modelIdentity, planId,
375
+ maxPlacements, ordered = false, authorize, onAttempt = () => {}, newId = () => crypto.randomUUID(), now = () => performance.now() }) {
376
+ assert(typeof ordered === 'boolean' && typeof entries === 'function' && typeof authorize === 'function'
377
+ && Number.isSafeInteger(maxPlacements) && maxPlacements > 0, 'Explicit requester placement policy required');
378
+ return Object.freeze({
379
+ async generate({ messages, threadId, disclosureExpiresAt, generationRequest: requested }, { signal, onDelta, onUsage, onActivity } = {}) {
380
+ assert(disclosureExpiresAt === undefined || ordered && Number.isSafeInteger(disclosureExpiresAt) && disclosureExpiresAt > Date.now(),
381
+ 'Requester disclosure deadline expired or invalid');
382
+ messages = structuredClone(messages);
383
+ requested = generationRequest(requested);
384
+ const attempted = new Set(), failures = [], started = now();
385
+ for (let generation = 0; generation < maxPlacements; generation++) {
386
+ signal?.throwIfAborted();
387
+ let selected = null;
388
+ for (const entry of entries()) {
389
+ if (attempted.has(entry.id)) continue;
390
+ try {
391
+ const state = await entry.refresh({ signal });
392
+ const model = state.descriptor?.models.find(m => m.id === modelId && m.identity === modelIdentity
393
+ && m.partition?.planId === planId && m.availability === 'ready'
394
+ && (ordered ? m.partition.schema === 'reploid.partition-selection/v2' && m.partition.coordinatorId === entry.id
395
+ : m.partition.route === undefined));
396
+ if (!state.ready || !model) continue;
397
+ requireGenerationCapability(model, requested);
398
+ const placement = { requesterId, modelId, modelIdentity, planId,
399
+ ...(requested ? {generationRequest: requested} : {}),
400
+ ...(disclosureExpiresAt !== undefined ? {disclosureExpiresAt} : {}),
401
+ ...(ordered ? {coordinatorId: entry.id, route: structuredClone(model.partition.route)}
402
+ : {participantA: entry.id, participantB: model.partition.participantB}) };
403
+ if (ordered) {
404
+ const binding = canonicalRouteAttemptBinding({schema:'reploid.partition-attempt/v2', threadId,
405
+ attemptId:'placement-validation', requesterId, placementGeneration:generation, route:placement.route});
406
+ assert(binding.route.stages[0].participantId === entry.id && binding.route.modelId === modelId
407
+ && binding.route.modelIdentity === modelIdentity && binding.route.planId === planId, 'Requester route model or coordinator mismatch');
408
+ }
409
+ if (await authorize(structuredClone(placement)) === true) { selected = { entry, placement }; break; }
410
+ } catch (error) { signal?.throwIfAborted(); failures.push({ ...(ordered ? {coordinatorId:entry.id} : {participantA:entry.id}), error: String(error.message) }); }
411
+ }
412
+ assert(selected, 'No authorized prepared partition path is available');
413
+ attempted.add(selected.entry.id);
414
+ const request = { ...selected.placement, meshId, threadId, messages: structuredClone(messages),
415
+ attemptId: newId(), placementGeneration: generation };
416
+ onAttempt({ ...structuredClone(request), messages: undefined, phase: generation ? 'restarting' : 'executing' });
417
+ let published = false;
418
+ try {
419
+ const result = await selected.entry.generate(request, { signal,
420
+ ...(onActivity ? {onActivity: activity => { published = true; return onActivity({threadId,attemptId:request.attemptId,...activity}); }} : {}),
421
+ onUsage: usage => { published = true; return onUsage?.(usage); },
422
+ onDelta: text => { published = true; return onDelta?.({text,threadId,attemptId:request.attemptId,placementGeneration:generation}); } });
423
+ return { ...result, recovery: { attempts: generation + 1, failures, elapsedMs: now() - started,
424
+ stateTransfer: 'new-attempt-from-authorized-input' } };
425
+ } catch (error) {
426
+ if (published) throw error;
427
+ signal?.throwIfAborted(); failures.push({ ...(ordered ? {coordinatorId:selected.entry.id} : {participantA:selected.entry.id}), attemptId: request.attemptId, error: String(error.message) });
428
+ onAttempt({ attemptId: request.attemptId, placementGeneration: generation, phase: 'failed', error: String(error.message) });
429
+ }
430
+ }
431
+ throw new AggregateError(failures.map(f => new Error(f.error)), 'Prepared partition attempts exhausted');
432
+ },
433
+ });
434
+ }
@@ -0,0 +1,33 @@
1
+ import { assertPartition as assert } from './partition-contract.js';
2
+
3
+ export const TEXT_GENERATION_CAPABILITY = Object.freeze({ schema: 'reploid.text-generation/v1', usage: 'raw-model-tokens/v1' });
4
+
5
+ /** Optional caller ceiling, not a sampling override or a new generation policy. */
6
+ export function generationRequest(value) {
7
+ if (value === undefined) return undefined;
8
+ assert(value && typeof value === 'object' && !Array.isArray(value)
9
+ && Object.keys(value).length === 3 && value.schema === 'reploid.partition-generation-request/v1'
10
+ && value.usage === 'raw-model-tokens/v1' && Number.isSafeInteger(value.maxOutputTokens) && value.maxOutputTokens > 0,
11
+ 'Invalid caller token limit or usage contract');
12
+ return Object.freeze({ schema: value.schema, maxOutputTokens: value.maxOutputTokens, usage: value.usage });
13
+ }
14
+ export function requireGenerationCapability(model, requested, canonical = false) {
15
+ const value = generationRequest(requested);
16
+ if (value) assert(!canonical && model?.textGeneration?.schema === TEXT_GENERATION_CAPABILITY.schema
17
+ && model.textGeneration.usage === TEXT_GENERATION_CAPABILITY.usage, 'Prepared route lacks caller token limit and usage capability');
18
+ return value;
19
+ }
20
+ export function boundedGeneration(settings, requested) {
21
+ const value = generationRequest(requested);
22
+ if (!value) return settings;
23
+ assert(value.maxOutputTokens <= settings.maxTokens, 'Caller token limit exceeds the prepared generation allocation');
24
+ return { ...settings, maxTokens: value.maxOutputTokens };
25
+ }
26
+ /** Counts the provider's actual template tokenization and raw sampled tokens,
27
+ * including any terminal token. No counts are inferred from visible text. */
28
+ export function tokenUsage(inputTokens, outputTokens, requested) {
29
+ const value = generationRequest(requested);
30
+ assert(value && Number.isSafeInteger(inputTokens) && inputTokens > 0 && Number.isSafeInteger(outputTokens)
31
+ && outputTokens >= 0 && outputTokens <= value.maxOutputTokens, 'Invalid provider token usage');
32
+ return Object.freeze({ schema: value.usage, inputTokens, outputTokens });
33
+ }