@lostgradient/weft 0.13.0 → 0.15.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 (114) hide show
  1. package/README.md +3 -8
  2. package/dist/cli/generated/operation-catalog.snapshot.json +977 -77
  3. package/dist/cli/generated/operation-client.generated.d.ts +14 -21
  4. package/dist/cli/help-text.d.ts +3 -3
  5. package/dist/cli/help-text.js +4 -4
  6. package/dist/cli/operation-catalog-snapshot.d.ts +1 -1
  7. package/dist/cli/schedule.js +1 -3
  8. package/dist/cli/serve-registrations.d.ts +3 -3
  9. package/dist/cli/serve-registrations.js +2 -2
  10. package/dist/cli/shutdown.d.ts +11 -0
  11. package/dist/cli/shutdown.js +25 -0
  12. package/dist/cli/validate.d.ts +1 -1
  13. package/dist/cli/version-check.d.ts +1 -1
  14. package/dist/cli/version-check.js +1 -1
  15. package/dist/cli-main.js +10 -29
  16. package/dist/client/http-client-storage.js +7 -35
  17. package/dist/client/http-request.d.ts +8 -9
  18. package/dist/client/http-request.js +3 -25
  19. package/dist/core/aggregate-validation.d.ts +2 -5
  20. package/dist/core/aggregate-validation.js +2 -10
  21. package/dist/core/atomic-state.js +21 -24
  22. package/dist/core/context/parallel-operations.d.ts +0 -2
  23. package/dist/core/context/parallel-operations.js +0 -7
  24. package/dist/core/engine/callback-checkpoint-persistence.d.ts +2 -0
  25. package/dist/core/engine/callback-checkpoint-persistence.js +6 -3
  26. package/dist/core/engine/callback-creators.js +4 -22
  27. package/dist/core/engine/checkpoint-io.d.ts +1 -1
  28. package/dist/core/engine/operations-coordination.js +1 -1
  29. package/dist/core/engine/parallel-dispatch.d.ts +1 -1
  30. package/dist/core/engine/parallel-dispatch.js +1 -1
  31. package/dist/core/engine/review-list-entries.d.ts +1 -1
  32. package/dist/core/engine/review-list-entries.js +6 -30
  33. package/dist/core/engine/schedules.js +4 -1
  34. package/dist/core/engine/timeline-coordinator-detail.d.ts +1 -1
  35. package/dist/core/inline-execution-strategy.js +8 -46
  36. package/dist/core/list-filter-validation.d.ts +2 -5
  37. package/dist/core/list-filter-validation.js +2 -10
  38. package/dist/core/review/index.d.ts +87 -0
  39. package/dist/core/review/index.js +29 -0
  40. package/dist/core/types/schedules.d.ts +13 -31
  41. package/dist/core/validation-issues.d.ts +13 -0
  42. package/dist/core/validation-issues.js +9 -0
  43. package/dist/diagnostics/validate.d.ts +9 -30
  44. package/dist/diagnostics/validate.js +83 -21
  45. package/dist/diagnostics/version-check.d.ts +2 -2
  46. package/dist/http.js +2 -2
  47. package/dist/indexeddb.js +1 -1
  48. package/dist/mcp/session.js +2 -10
  49. package/dist/mcp/tools.js +2 -10
  50. package/dist/mcp/tuple-list-equality.d.ts +1 -0
  51. package/dist/mcp/tuple-list-equality.js +12 -0
  52. package/dist/server/openapi-error-responses.js +0 -14
  53. package/dist/server/operation-catalog/index.d.ts +1 -1
  54. package/dist/server/operation-catalog/raise-fault.d.ts +2 -1
  55. package/dist/server/operation-catalog/types.d.ts +3 -2
  56. package/dist/server/operation-fault.d.ts +1 -4
  57. package/dist/server/operation-fault.js +1 -1
  58. package/dist/server/operation-registry.d.ts +2 -31
  59. package/dist/server/operations/bulk-filter-helpers.d.ts +17 -17
  60. package/dist/server/operations/bulk-filter-helpers.js +16 -37
  61. package/dist/server/operations/bulk-mutate-workflow-tags.d.ts +27 -27
  62. package/dist/server/operations/bulk-signal-workflows.d.ts +26 -26
  63. package/dist/server/operations/create-schedule.js +7 -19
  64. package/dist/server/operations/event-stream-contracts.d.ts +20 -0
  65. package/dist/server/operations/event-stream-contracts.js +67 -0
  66. package/dist/server/operations/fleet-events-sse.js +21 -50
  67. package/dist/server/operations/fleet-events-subscription.js +8 -12
  68. package/dist/server/operations/list-reviews.js +2 -19
  69. package/dist/server/operations/list-workflows.d.ts +43 -43
  70. package/dist/server/operations/list-workflows.js +9 -30
  71. package/dist/server/operations/purge-workflows.d.ts +11 -11
  72. package/dist/server/operations/recover-all.js +1 -10
  73. package/dist/server/operations/schedule-rest-body.d.ts +11 -0
  74. package/dist/server/operations/schedule-rest-body.js +28 -0
  75. package/dist/server/operations/single-workflow-control-operation.d.ts +2 -1
  76. package/dist/server/operations/update-schedule.js +7 -19
  77. package/dist/server/operations/workflow-events-sse.js +29 -67
  78. package/dist/server/operations/workflow-events-subscription.js +9 -27
  79. package/dist/server/runtime/task-polling.js +3 -5
  80. package/dist/server/task-state.d.ts +2 -8
  81. package/dist/server/task-state.js +10 -7
  82. package/dist/storage/bounded-ndjson-response.d.ts +5 -0
  83. package/dist/storage/bounded-ndjson-response.js +33 -0
  84. package/dist/storage/bun-sql.js +52 -49
  85. package/dist/storage/conditional-batch-body.d.ts +7 -0
  86. package/dist/storage/conditional-batch-body.js +14 -0
  87. package/dist/storage/http.js +5 -37
  88. package/dist/storage/lmdb.js +1 -1
  89. package/dist/storage/memory.js +1 -1
  90. package/dist/storage/neon.d.ts +3 -16
  91. package/dist/storage/neon.js +2 -2
  92. package/dist/storage/node-sqlite-loader.d.ts +2 -2
  93. package/dist/storage/node-sqlite.js +32 -17
  94. package/dist/storage/postgres.js +1 -1
  95. package/dist/storage/resolve.js +1 -1
  96. package/dist/storage/scoped-storage.js +1 -1
  97. package/dist/storage/turso.js +1 -1
  98. package/dist/version.d.ts +1 -1
  99. package/dist/version.js +1 -1
  100. package/dist/web-extension.js +1 -1
  101. package/dist/worker/execute-with-interceptors.d.ts +1 -1
  102. package/dist/worker/execute-with-interceptors.js +2 -2
  103. package/dist/worker/index.js +5 -5
  104. package/dist/worker/long-poll.js +3 -4
  105. package/dist/worker/protocol-messages.d.ts +11 -19
  106. package/dist/worker/protocol-schemas.d.ts +8 -8
  107. package/dist/worker/protocol-schemas.js +4 -4
  108. package/dist/worker/protocol-task-result.d.ts +1 -0
  109. package/dist/worker/protocol-task-result.js +1 -3
  110. package/dist/worker/protocol.js +1 -1
  111. package/dist/worker/registry/types.d.ts +2 -7
  112. package/dist/worker/registry.d.ts +3 -9
  113. package/dist/worker/registry.js +2 -5
  114. package/package.json +1 -1
@@ -92,7 +92,7 @@ export declare const REMOTE_WORKER_MESSAGE_SCHEMAS: {
92
92
  readonly oneOf: readonly [{
93
93
  readonly type: "object";
94
94
  readonly additionalProperties: false;
95
- readonly required: readonly ["type", "operationId", "status", "value"];
95
+ readonly required: readonly ["type", "operationId", "status", "value", "attemptToken"];
96
96
  readonly properties: {
97
97
  readonly type: {
98
98
  readonly const: "taskResult";
@@ -113,7 +113,7 @@ export declare const REMOTE_WORKER_MESSAGE_SCHEMAS: {
113
113
  }, {
114
114
  readonly type: "object";
115
115
  readonly additionalProperties: false;
116
- readonly required: readonly ["type", "operationId", "status", "error"];
116
+ readonly required: readonly ["type", "operationId", "status", "error", "attemptToken"];
117
117
  readonly properties: {
118
118
  readonly type: {
119
119
  readonly const: "taskResult";
@@ -136,7 +136,7 @@ export declare const REMOTE_WORKER_MESSAGE_SCHEMAS: {
136
136
  }, {
137
137
  readonly type: "object";
138
138
  readonly additionalProperties: false;
139
- readonly required: readonly ["type", "operationId", "status", "error"];
139
+ readonly required: readonly ["type", "operationId", "status", "error", "attemptToken"];
140
140
  readonly properties: {
141
141
  readonly type: {
142
142
  readonly const: "taskResult";
@@ -164,7 +164,7 @@ export declare const REMOTE_WORKER_MESSAGE_SCHEMAS: {
164
164
  readonly task: {
165
165
  readonly type: "object";
166
166
  readonly additionalProperties: false;
167
- readonly required: readonly ["type", "operationId", "activityName", "input"];
167
+ readonly required: readonly ["type", "operationId", "activityName", "input", "attemptToken"];
168
168
  readonly properties: {
169
169
  readonly type: {
170
170
  readonly const: "task";
@@ -398,7 +398,7 @@ export declare const REMOTE_WORKER_PROTOCOL_JSON_SCHEMA: {
398
398
  readonly oneOf: readonly [{
399
399
  readonly type: "object";
400
400
  readonly additionalProperties: false;
401
- readonly required: readonly ["type", "operationId", "status", "value"];
401
+ readonly required: readonly ["type", "operationId", "status", "value", "attemptToken"];
402
402
  readonly properties: {
403
403
  readonly type: {
404
404
  readonly const: "taskResult";
@@ -419,7 +419,7 @@ export declare const REMOTE_WORKER_PROTOCOL_JSON_SCHEMA: {
419
419
  }, {
420
420
  readonly type: "object";
421
421
  readonly additionalProperties: false;
422
- readonly required: readonly ["type", "operationId", "status", "error"];
422
+ readonly required: readonly ["type", "operationId", "status", "error", "attemptToken"];
423
423
  readonly properties: {
424
424
  readonly type: {
425
425
  readonly const: "taskResult";
@@ -442,7 +442,7 @@ export declare const REMOTE_WORKER_PROTOCOL_JSON_SCHEMA: {
442
442
  }, {
443
443
  readonly type: "object";
444
444
  readonly additionalProperties: false;
445
- readonly required: readonly ["type", "operationId", "status", "error"];
445
+ readonly required: readonly ["type", "operationId", "status", "error", "attemptToken"];
446
446
  readonly properties: {
447
447
  readonly type: {
448
448
  readonly const: "taskResult";
@@ -470,7 +470,7 @@ export declare const REMOTE_WORKER_PROTOCOL_JSON_SCHEMA: {
470
470
  readonly task: {
471
471
  readonly type: "object";
472
472
  readonly additionalProperties: false;
473
- readonly required: readonly ["type", "operationId", "activityName", "input"];
473
+ readonly required: readonly ["type", "operationId", "activityName", "input", "attemptToken"];
474
474
  readonly properties: {
475
475
  readonly type: {
476
476
  readonly const: "task";
@@ -47,7 +47,7 @@ export const REMOTE_WORKER_MESSAGE_SCHEMAS = {
47
47
  {
48
48
  type: "object",
49
49
  additionalProperties: !1,
50
- required: ["type", "operationId", "status", "value"],
50
+ required: ["type", "operationId", "status", "value", "attemptToken"],
51
51
  properties: {
52
52
  type: { const: "taskResult" },
53
53
  operationId: { type: "string", minLength: 1 },
@@ -59,7 +59,7 @@ export const REMOTE_WORKER_MESSAGE_SCHEMAS = {
59
59
  {
60
60
  type: "object",
61
61
  additionalProperties: !1,
62
- required: ["type", "operationId", "status", "error"],
62
+ required: ["type", "operationId", "status", "error", "attemptToken"],
63
63
  properties: {
64
64
  type: { const: "taskResult" },
65
65
  operationId: { type: "string", minLength: 1 },
@@ -71,7 +71,7 @@ export const REMOTE_WORKER_MESSAGE_SCHEMAS = {
71
71
  {
72
72
  type: "object",
73
73
  additionalProperties: !1,
74
- required: ["type", "operationId", "status", "error"],
74
+ required: ["type", "operationId", "status", "error", "attemptToken"],
75
75
  properties: {
76
76
  type: { const: "taskResult" },
77
77
  operationId: { type: "string", minLength: 1 },
@@ -86,7 +86,7 @@ export const REMOTE_WORKER_MESSAGE_SCHEMAS = {
86
86
  task: {
87
87
  type: "object",
88
88
  additionalProperties: !1,
89
- required: ["type", "operationId", "activityName", "input"],
89
+ required: ["type", "operationId", "activityName", "input", "attemptToken"],
90
90
  properties: {
91
91
  type: { const: "task" },
92
92
  operationId: { type: "string", minLength: 1 },
@@ -20,6 +20,7 @@ import type { CancelledTaskResultMessage, CompletedTaskResultMessage, FailedTask
20
20
  *
21
21
  * const message: TaskResultMessage = {
22
22
  * type: 'taskResult', operationId: 'op-1', status: 'completed', value: { ok: true },
23
+ * attemptToken: 'attempt-token',
23
24
  * };
24
25
  * ```
25
26
  */
@@ -5,10 +5,8 @@ import {
5
5
  } from "./protocol-internals.js";
6
6
  function parseEchoedAttemptToken(record) {
7
7
  const attemptToken = record.attemptToken;
8
- if (attemptToken === void 0)
9
- return { ok: !0, message: {} };
10
8
  if (!isNonEmptyString(attemptToken))
11
- return protocolFailure("invalid_message", "taskResult.attemptToken must be a non-empty string when present");
9
+ return protocolFailure("invalid_message", "taskResult.attemptToken must be a non-empty string");
12
10
  return { ok: !0, message: { attemptToken } };
13
11
  }
14
12
  function parseCompletedTaskResult(operationId, record) {
@@ -1,2 +1,2 @@
1
1
  // @bun
2
- var t=import.meta.require,l=(z,B,D)=>{if(B!=null){if(typeof B!=="object"&&typeof B!=="function")throw TypeError('Object expected to be assigned to "using" declaration');let X;if(D)X=B[Symbol.asyncDispose];if(X===void 0)X=B[Symbol.dispose];if(typeof X!=="function")throw TypeError("Object not disposable");z.push([D,X,B])}else if(D)z.push([D]);return B},a=(z,B,D)=>{let X=(U)=>B=D?new SuppressedError(U,B,"An error was suppressed during disposal"):(D=!0,U),Z=(U)=>{while(U=z.pop())try{var L=U[1]&&U[1].call(U[2]);if(U[0])return Promise.resolve(L).then(Z,(G)=>(X(G),Z()))}catch(G){X(G)}if(D)throw B};return Z()};function b(z){return z!==null&&typeof z==="object"&&!Array.isArray(z)}function $(z){if(z===null||typeof z==="string"||typeof z==="boolean"||typeof z==="number"&&Number.isFinite(z))return!0;if(Array.isArray(z))return z.every($);if(!b(z))return!1;return Object.values(z).every($)}function Y(z){return typeof z==="string"&&z.length>0}function J(z){return Array.isArray(z)&&z.every(Y)}function w(z){if(!b(z))return!1;return Object.values(z).every((B)=>typeof B==="string")}function q(z){if(!b(z))return!1;return Object.values(z).every($)}function H(z){return typeof z==="number"&&Number.isFinite(z)}function Q(z,B,D){return{ok:!1,error:{code:z,message:B,...D!==void 0?{requestedProtocolVersion:D}:{}}}}function f(z,B,D){let X={};for(let[Z,U,L,G]of D){let j=B[Z];if(j===void 0){if(U)return{ok:!1,error:Q(z,G)};continue}if(!L(j))return{ok:!1,error:Q(z,G)};X[Z]=j}return{ok:!0,values:X}}var x=2,h=2,M=2,I=[2];var K={$ref:"#/$defs/jsonValue"},A={type:"object",additionalProperties:K},P={type:"object",additionalProperties:{type:"string"}},F={const:x},N={register:{type:"object",additionalProperties:!1,required:["type","protocolVersion","workerId","activities"],properties:{type:{const:"register"},protocolVersion:F,workerId:{type:"string",minLength:1},activities:{type:"array",items:{type:"string",minLength:1}},concurrency:{type:"number",minimum:1,maximum:1000},queue:{type:"string",minLength:1},deploymentName:{type:"string",minLength:1},buildId:{type:"string",minLength:1},runtimeVersion:{type:"string",minLength:1},gitSha:{type:"string",minLength:1},startedAt:{type:"number"},capabilities:A}},heartbeat:{type:"object",additionalProperties:!1,required:["type","workerId"],properties:{type:{const:"heartbeat"},workerId:{type:"string",minLength:1}}},taskResult:{oneOf:[{type:"object",additionalProperties:!1,required:["type","operationId","status","value"],properties:{type:{const:"taskResult"},operationId:{type:"string",minLength:1},status:{const:"completed"},value:K,attemptToken:{type:"string",minLength:1}}},{type:"object",additionalProperties:!1,required:["type","operationId","status","error"],properties:{type:{const:"taskResult"},operationId:{type:"string",minLength:1},status:{const:"failed"},error:{type:"string"},attemptToken:{type:"string",minLength:1}}},{type:"object",additionalProperties:!1,required:["type","operationId","status","error"],properties:{type:{const:"taskResult"},operationId:{type:"string",minLength:1},status:{const:"cancelled"},error:{type:"string"},cancelled:{const:!0},attemptToken:{type:"string",minLength:1}}}]},task:{type:"object",additionalProperties:!1,required:["type","operationId","activityName","input"],properties:{type:{const:"task"},operationId:{type:"string",minLength:1},activityName:{type:"string",minLength:1},input:K,attempt:{type:"number",minimum:1},headers:P,workflowExecutionToken:{type:"string",minLength:1},attemptToken:{type:"string",minLength:1}}},cancel:{type:"object",additionalProperties:!1,required:["type","operationId"],properties:{type:{const:"cancel"},operationId:{type:"string",minLength:1}}},shutdown:{type:"object",additionalProperties:!1,required:["type"],properties:{type:{const:"shutdown"}}},registerAck:{type:"object",additionalProperties:!1,required:["type","protocolVersion","workerId","queue","activities","concurrency"],properties:{type:{const:"registerAck"},protocolVersion:F,workerId:{type:"string",minLength:1},queue:{type:"string",minLength:1},activities:{type:"array",items:{type:"string",minLength:1}},concurrency:{type:"number",minimum:1,maximum:1000}}},registerError:{type:"object",additionalProperties:!1,required:["type","code","message","supportedProtocolVersions"],properties:{type:{const:"registerError"},code:{enum:["invalid_registration","unsupported_protocol_version"]},message:{type:"string"},supportedProtocolVersions:{type:"array",items:F},requestedProtocolVersion:{type:"number"}}},protocolError:{type:"object",additionalProperties:!1,required:["type","code","message"],properties:{type:{const:"protocolError"},code:{enum:["invalid_json","invalid_message","unknown_message_type","registration_required"]},message:{type:"string"}}}},g={$schema:"https://json-schema.org/draft/2020-12/schema",$id:"https://weft.dev/schemas/remote-worker-protocol.v1.json",title:"Weft RemoteWorker Protocol v1",oneOf:Object.keys(N).map((z)=>({$ref:`#/$defs/messages/${z}`})),$defs:{jsonValue:{oneOf:[{type:"null"},{type:"boolean"},{type:"number"},{type:"string"},{type:"array",items:{$ref:"#/$defs/jsonValue"}},{type:"object",additionalProperties:{$ref:"#/$defs/jsonValue"}}]},jsonObject:A,messages:N}};function C(z){let B=z.attemptToken;if(B===void 0)return{ok:!0,message:{}};if(!Y(B))return Q("invalid_message","taskResult.attemptToken must be a non-empty string when present");return{ok:!0,message:{attemptToken:B}}}function _(z,B){let D=B.value;if(!$(D))return Q("invalid_message","completed taskResult.value must be valid JSON");let X=C(B);if(!X.ok)return X;return{ok:!0,message:{type:"taskResult",operationId:z,status:"completed",value:D,...X.message}}}function y(z,B){let D=B.error;if(typeof D!=="string")return Q("invalid_message","failed taskResult.error must be a string");let X=C(B);if(!X.ok)return X;return{ok:!0,message:{type:"taskResult",operationId:z,status:"failed",error:D,...X.message}}}function T(z,B){let D=B.error;if(typeof D!=="string")return Q("invalid_message","cancelled taskResult.error must be a string");let X=B.cancelled;if(X!==void 0&&X!==!0)return Q("invalid_message","taskResult.cancelled must be true when present");let Z=C(B);if(!Z.ok)return Z;return{ok:!0,message:{type:"taskResult",operationId:z,status:"cancelled",error:D,...X===!0?{cancelled:X}:{},...Z.message}}}var O={completed:_,failed:y,cancelled:T};function V(z){return z==="completed"||z==="failed"||z==="cancelled"}function W(z){let B=z.operationId;if(!Y(B))return Q("invalid_message","taskResult.operationId must be a non-empty string");let D=z.status;if(!V(D))return Q("invalid_message","taskResult.status must be completed, failed, or cancelled");return O[D](B,z)}var S=new Set(["register","heartbeat","taskResult"]),k=new Set(["registerAck","registerError","protocolError","task","cancel","shutdown"]);function E(z){if(z===x)return{ok:!0,message:z};let B=H(z)?z:void 0;return Q("unsupported_protocol_version",`Unsupported RemoteWorker protocol version: ${String(z)}`,B)}var m=[["workerId",!0,Y,"register.workerId must be a non-empty string"],["activities",!0,J,"register.activities must be an array of non-empty strings"],["concurrency",!1,H,"register.concurrency must be a finite number"],["queue",!1,Y,"register.queue must be a non-empty string"],["deploymentName",!1,Y,"register.deploymentName must be a non-empty string when present"],["buildId",!1,Y,"register.buildId must be a non-empty string when present"],["runtimeVersion",!1,Y,"register.runtimeVersion must be a non-empty string when present"],["gitSha",!1,Y,"register.gitSha must be a non-empty string when present"],["startedAt",!1,H,"register.startedAt must be a finite number when present"],["capabilities",!1,q,"register.capabilities must be a JSON object when present"]];function R(z){let B=E(z.protocolVersion);if(!B.ok)return B;let D=f("invalid_registration",z,m);if(!D.ok)return D.error;return{ok:!0,message:{type:"register",protocolVersion:B.message,...D.values}}}function p(z){let B=z.workerId;if(!Y(B))return Q("invalid_message","heartbeat.workerId must be a non-empty string");return{ok:!0,message:{type:"heartbeat",workerId:B}}}var n=[["operationId",!0,Y,"task.operationId must be a non-empty string"],["activityName",!0,Y,"task.activityName must be a non-empty string"],["input",!0,$,"task.input must be valid JSON"],["attempt",!1,H,"task.attempt must be a finite number"],["headers",!1,w,"task.headers must be a string map"],["workflowExecutionToken",!1,Y,"task.workflowExecutionToken must be a non-empty string"],["attemptToken",!1,Y,"task.attemptToken must be a non-empty string"]];function i(z){let B=f("invalid_message",z,n);if(!B.ok)return B.error;return{ok:!0,message:{type:"task",...B.values}}}function v(z){let B=z.operationId;if(!Y(B))return Q("invalid_message","cancel.operationId must be a non-empty string");return{ok:!0,message:{type:"cancel",operationId:B}}}function d(){return{ok:!0,message:{type:"shutdown"}}}function u(z){let B=z.protocolVersion;if(B!==x)return Q("invalid_message",`registerAck.protocolVersion must be ${String(x)}`);let{workerId:D,queue:X,activities:Z,concurrency:U}=z;if(!Y(D))return Q("invalid_message","registerAck.workerId must be a non-empty string");if(!Y(X))return Q("invalid_message","registerAck.queue must be a non-empty string");if(!J(Z))return Q("invalid_message","registerAck.activities must be a string array");if(typeof U!=="number"||!Number.isFinite(U))return Q("invalid_message","registerAck.concurrency must be a finite number");return{ok:!0,message:{type:"registerAck",protocolVersion:B,workerId:D,queue:X,activities:Z,concurrency:U}}}function s(z){let{code:B,message:D,supportedProtocolVersions:X,requestedProtocolVersion:Z}=z;if(B!=="invalid_registration"&&B!=="unsupported_protocol_version")return Q("invalid_message","registerError.code is not recognized");if(typeof D!=="string")return Q("invalid_message","registerError.message must be a string");if(!Array.isArray(X)||!X.every((L)=>L===x))return Q("invalid_message","registerError.supportedProtocolVersions is invalid");if(Z!==void 0&&!H(Z))return Q("invalid_message","registerError.requestedProtocolVersion must be a finite number");return{ok:!0,message:{type:"registerError",code:B,message:D,supportedProtocolVersions:X,...Z!==void 0?{requestedProtocolVersion:Z}:{}}}}function c(z){let{code:B,message:D}=z;if(B!=="invalid_json"&&B!=="invalid_message"&&B!=="unknown_message_type"&&B!=="registration_required")return Q("invalid_message","protocolError.code is not recognized");if(typeof D!=="string")return Q("invalid_message","protocolError.message must be a string");return{ok:!0,message:{type:"protocolError",code:B,message:D}}}function $z(z){if(!b(z))return Q("invalid_message","Worker protocol message must be a JSON object");let B=z.type;if(typeof B!=="string")return Q("invalid_message","Worker protocol message.type must be a string");if(!S.has(B))return Q("unknown_message_type",`Unknown worker message type: ${B}`);switch(B){case"register":return R(z);case"heartbeat":return p(z);case"taskResult":return W(z);default:return Q("unknown_message_type",`Unknown worker message type: ${B}`)}}function xz(z){if(!b(z))return Q("invalid_message","Server protocol message must be a JSON object");let B=z.type;if(typeof B!=="string")return Q("invalid_message","Server protocol message.type must be a string");if(!k.has(B))return Q("unknown_message_type",`Unknown server message type: ${B}`);switch(B){case"registerAck":return u(z);case"registerError":return s(z);case"protocolError":return c(z);case"task":return i(z);case"cancel":return v(z);case"shutdown":return d();default:return Q("unknown_message_type",`Unknown server message type: ${B}`)}}export{$z as parseWorkerToServerMessage,xz as parseServerToWorkerMessage,$ as isRemoteWorkerJsonValue,I as REMOTE_WORKER_SUPPORTED_PROTOCOL_VERSIONS,x as REMOTE_WORKER_PROTOCOL_VERSION,g as REMOTE_WORKER_PROTOCOL_JSON_SCHEMA,h as REMOTE_WORKER_MIN_PROTOCOL_VERSION,N as REMOTE_WORKER_MESSAGE_SCHEMAS,M as REMOTE_WORKER_MAX_PROTOCOL_VERSION};
2
+ var c=import.meta.require,l=(z,B,D)=>{if(B!=null){if(typeof B!=="object"&&typeof B!=="function")throw TypeError('Object expected to be assigned to "using" declaration');let X;if(D)X=B[Symbol.asyncDispose];if(X===void 0)X=B[Symbol.dispose];if(typeof X!=="function")throw TypeError("Object not disposable");z.push([D,X,B])}else if(D)z.push([D]);return B},a=(z,B,D)=>{let X=(U)=>B=D?new SuppressedError(U,B,"An error was suppressed during disposal"):(D=!0,U),Z=(U)=>{while(U=z.pop())try{var L=U[1]&&U[1].call(U[2]);if(U[0])return Promise.resolve(L).then(Z,(G)=>(X(G),Z()))}catch(G){X(G)}if(D)throw B};return Z()};function b(z){return z!==null&&typeof z==="object"&&!Array.isArray(z)}function $(z){if(z===null||typeof z==="string"||typeof z==="boolean"||typeof z==="number"&&Number.isFinite(z))return!0;if(Array.isArray(z))return z.every($);if(!b(z))return!1;return Object.values(z).every($)}function Y(z){return typeof z==="string"&&z.length>0}function J(z){return Array.isArray(z)&&z.every(Y)}function w(z){if(!b(z))return!1;return Object.values(z).every((B)=>typeof B==="string")}function q(z){if(!b(z))return!1;return Object.values(z).every($)}function H(z){return typeof z==="number"&&Number.isFinite(z)}function Q(z,B,D){return{ok:!1,error:{code:z,message:B,...D!==void 0?{requestedProtocolVersion:D}:{}}}}function f(z,B,D){let X={};for(let[Z,U,L,G]of D){let j=B[Z];if(j===void 0){if(U)return{ok:!1,error:Q(z,G)};continue}if(!L(j))return{ok:!1,error:Q(z,G)};X[Z]=j}return{ok:!0,values:X}}var x=2,h=2,M=2,I=[2];var K={$ref:"#/$defs/jsonValue"},A={type:"object",additionalProperties:K},P={type:"object",additionalProperties:{type:"string"}},F={const:x},N={register:{type:"object",additionalProperties:!1,required:["type","protocolVersion","workerId","activities"],properties:{type:{const:"register"},protocolVersion:F,workerId:{type:"string",minLength:1},activities:{type:"array",items:{type:"string",minLength:1}},concurrency:{type:"number",minimum:1,maximum:1000},queue:{type:"string",minLength:1},deploymentName:{type:"string",minLength:1},buildId:{type:"string",minLength:1},runtimeVersion:{type:"string",minLength:1},gitSha:{type:"string",minLength:1},startedAt:{type:"number"},capabilities:A}},heartbeat:{type:"object",additionalProperties:!1,required:["type","workerId"],properties:{type:{const:"heartbeat"},workerId:{type:"string",minLength:1}}},taskResult:{oneOf:[{type:"object",additionalProperties:!1,required:["type","operationId","status","value","attemptToken"],properties:{type:{const:"taskResult"},operationId:{type:"string",minLength:1},status:{const:"completed"},value:K,attemptToken:{type:"string",minLength:1}}},{type:"object",additionalProperties:!1,required:["type","operationId","status","error","attemptToken"],properties:{type:{const:"taskResult"},operationId:{type:"string",minLength:1},status:{const:"failed"},error:{type:"string"},attemptToken:{type:"string",minLength:1}}},{type:"object",additionalProperties:!1,required:["type","operationId","status","error","attemptToken"],properties:{type:{const:"taskResult"},operationId:{type:"string",minLength:1},status:{const:"cancelled"},error:{type:"string"},cancelled:{const:!0},attemptToken:{type:"string",minLength:1}}}]},task:{type:"object",additionalProperties:!1,required:["type","operationId","activityName","input","attemptToken"],properties:{type:{const:"task"},operationId:{type:"string",minLength:1},activityName:{type:"string",minLength:1},input:K,attempt:{type:"number",minimum:1},headers:P,workflowExecutionToken:{type:"string",minLength:1},attemptToken:{type:"string",minLength:1}}},cancel:{type:"object",additionalProperties:!1,required:["type","operationId"],properties:{type:{const:"cancel"},operationId:{type:"string",minLength:1}}},shutdown:{type:"object",additionalProperties:!1,required:["type"],properties:{type:{const:"shutdown"}}},registerAck:{type:"object",additionalProperties:!1,required:["type","protocolVersion","workerId","queue","activities","concurrency"],properties:{type:{const:"registerAck"},protocolVersion:F,workerId:{type:"string",minLength:1},queue:{type:"string",minLength:1},activities:{type:"array",items:{type:"string",minLength:1}},concurrency:{type:"number",minimum:1,maximum:1000}}},registerError:{type:"object",additionalProperties:!1,required:["type","code","message","supportedProtocolVersions"],properties:{type:{const:"registerError"},code:{enum:["invalid_registration","unsupported_protocol_version"]},message:{type:"string"},supportedProtocolVersions:{type:"array",items:F},requestedProtocolVersion:{type:"number"}}},protocolError:{type:"object",additionalProperties:!1,required:["type","code","message"],properties:{type:{const:"protocolError"},code:{enum:["invalid_json","invalid_message","unknown_message_type","registration_required"]},message:{type:"string"}}}},g={$schema:"https://json-schema.org/draft/2020-12/schema",$id:"https://weft.dev/schemas/remote-worker-protocol.v1.json",title:"Weft RemoteWorker Protocol v1",oneOf:Object.keys(N).map((z)=>({$ref:`#/$defs/messages/${z}`})),$defs:{jsonValue:{oneOf:[{type:"null"},{type:"boolean"},{type:"number"},{type:"string"},{type:"array",items:{$ref:"#/$defs/jsonValue"}},{type:"object",additionalProperties:{$ref:"#/$defs/jsonValue"}}]},jsonObject:A,messages:N}};function C(z){let B=z.attemptToken;if(!Y(B))return Q("invalid_message","taskResult.attemptToken must be a non-empty string");return{ok:!0,message:{attemptToken:B}}}function _(z,B){let D=B.value;if(!$(D))return Q("invalid_message","completed taskResult.value must be valid JSON");let X=C(B);if(!X.ok)return X;return{ok:!0,message:{type:"taskResult",operationId:z,status:"completed",value:D,...X.message}}}function T(z,B){let D=B.error;if(typeof D!=="string")return Q("invalid_message","failed taskResult.error must be a string");let X=C(B);if(!X.ok)return X;return{ok:!0,message:{type:"taskResult",operationId:z,status:"failed",error:D,...X.message}}}function y(z,B){let D=B.error;if(typeof D!=="string")return Q("invalid_message","cancelled taskResult.error must be a string");let X=B.cancelled;if(X!==void 0&&X!==!0)return Q("invalid_message","taskResult.cancelled must be true when present");let Z=C(B);if(!Z.ok)return Z;return{ok:!0,message:{type:"taskResult",operationId:z,status:"cancelled",error:D,...X===!0?{cancelled:X}:{},...Z.message}}}var O={completed:_,failed:T,cancelled:y};function V(z){return z==="completed"||z==="failed"||z==="cancelled"}function W(z){let B=z.operationId;if(!Y(B))return Q("invalid_message","taskResult.operationId must be a non-empty string");let D=z.status;if(!V(D))return Q("invalid_message","taskResult.status must be completed, failed, or cancelled");return O[D](B,z)}var S=new Set(["register","heartbeat","taskResult"]),k=new Set(["registerAck","registerError","protocolError","task","cancel","shutdown"]);function E(z){if(z===x)return{ok:!0,message:z};let B=H(z)?z:void 0;return Q("unsupported_protocol_version",`Unsupported RemoteWorker protocol version: ${String(z)}`,B)}var m=[["workerId",!0,Y,"register.workerId must be a non-empty string"],["activities",!0,J,"register.activities must be an array of non-empty strings"],["concurrency",!1,H,"register.concurrency must be a finite number"],["queue",!1,Y,"register.queue must be a non-empty string"],["deploymentName",!1,Y,"register.deploymentName must be a non-empty string when present"],["buildId",!1,Y,"register.buildId must be a non-empty string when present"],["runtimeVersion",!1,Y,"register.runtimeVersion must be a non-empty string when present"],["gitSha",!1,Y,"register.gitSha must be a non-empty string when present"],["startedAt",!1,H,"register.startedAt must be a finite number when present"],["capabilities",!1,q,"register.capabilities must be a JSON object when present"]];function R(z){let B=E(z.protocolVersion);if(!B.ok)return B;let D=f("invalid_registration",z,m);if(!D.ok)return D.error;return{ok:!0,message:{type:"register",protocolVersion:B.message,...D.values}}}function p(z){let B=z.workerId;if(!Y(B))return Q("invalid_message","heartbeat.workerId must be a non-empty string");return{ok:!0,message:{type:"heartbeat",workerId:B}}}var n=[["operationId",!0,Y,"task.operationId must be a non-empty string"],["activityName",!0,Y,"task.activityName must be a non-empty string"],["input",!0,$,"task.input must be valid JSON"],["attempt",!1,H,"task.attempt must be a finite number"],["headers",!1,w,"task.headers must be a string map"],["workflowExecutionToken",!1,Y,"task.workflowExecutionToken must be a non-empty string"],["attemptToken",!0,Y,"task.attemptToken must be a non-empty string"]];function i(z){let B=f("invalid_message",z,n);if(!B.ok)return B.error;return{ok:!0,message:{type:"task",...B.values}}}function v(z){let B=z.operationId;if(!Y(B))return Q("invalid_message","cancel.operationId must be a non-empty string");return{ok:!0,message:{type:"cancel",operationId:B}}}function d(){return{ok:!0,message:{type:"shutdown"}}}function u(z){let B=z.protocolVersion;if(B!==x)return Q("invalid_message",`registerAck.protocolVersion must be ${String(x)}`);let{workerId:D,queue:X,activities:Z,concurrency:U}=z;if(!Y(D))return Q("invalid_message","registerAck.workerId must be a non-empty string");if(!Y(X))return Q("invalid_message","registerAck.queue must be a non-empty string");if(!J(Z))return Q("invalid_message","registerAck.activities must be a string array");if(typeof U!=="number"||!Number.isFinite(U))return Q("invalid_message","registerAck.concurrency must be a finite number");return{ok:!0,message:{type:"registerAck",protocolVersion:B,workerId:D,queue:X,activities:Z,concurrency:U}}}function s(z){let{code:B,message:D,supportedProtocolVersions:X,requestedProtocolVersion:Z}=z;if(B!=="invalid_registration"&&B!=="unsupported_protocol_version")return Q("invalid_message","registerError.code is not recognized");if(typeof D!=="string")return Q("invalid_message","registerError.message must be a string");if(!Array.isArray(X)||!X.every((L)=>L===x))return Q("invalid_message","registerError.supportedProtocolVersions is invalid");if(Z!==void 0&&!H(Z))return Q("invalid_message","registerError.requestedProtocolVersion must be a finite number");return{ok:!0,message:{type:"registerError",code:B,message:D,supportedProtocolVersions:X,...Z!==void 0?{requestedProtocolVersion:Z}:{}}}}function t(z){let{code:B,message:D}=z;if(B!=="invalid_json"&&B!=="invalid_message"&&B!=="unknown_message_type"&&B!=="registration_required")return Q("invalid_message","protocolError.code is not recognized");if(typeof D!=="string")return Q("invalid_message","protocolError.message must be a string");return{ok:!0,message:{type:"protocolError",code:B,message:D}}}function $z(z){if(!b(z))return Q("invalid_message","Worker protocol message must be a JSON object");let B=z.type;if(typeof B!=="string")return Q("invalid_message","Worker protocol message.type must be a string");if(!S.has(B))return Q("unknown_message_type",`Unknown worker message type: ${B}`);switch(B){case"register":return R(z);case"heartbeat":return p(z);case"taskResult":return W(z);default:return Q("unknown_message_type",`Unknown worker message type: ${B}`)}}function xz(z){if(!b(z))return Q("invalid_message","Server protocol message must be a JSON object");let B=z.type;if(typeof B!=="string")return Q("invalid_message","Server protocol message.type must be a string");if(!k.has(B))return Q("unknown_message_type",`Unknown server message type: ${B}`);switch(B){case"registerAck":return u(z);case"registerError":return s(z);case"protocolError":return t(z);case"task":return i(z);case"cancel":return v(z);case"shutdown":return d();default:return Q("unknown_message_type",`Unknown server message type: ${B}`)}}export{$z as parseWorkerToServerMessage,xz as parseServerToWorkerMessage,$ as isRemoteWorkerJsonValue,I as REMOTE_WORKER_SUPPORTED_PROTOCOL_VERSIONS,x as REMOTE_WORKER_PROTOCOL_VERSION,g as REMOTE_WORKER_PROTOCOL_JSON_SCHEMA,h as REMOTE_WORKER_MIN_PROTOCOL_VERSION,N as REMOTE_WORKER_MESSAGE_SCHEMAS,M as REMOTE_WORKER_MAX_PROTOCOL_VERSION};
@@ -116,13 +116,8 @@ export interface InFlightTask {
116
116
  visibilityTimeout: number;
117
117
  /** Optional fair-share partition key the task was assigned under. */
118
118
  fairShareKey?: string;
119
- /**
120
- * Unique, unguessable token for this dispatch attempt. The WebSocket completion
121
- * handler compares the worker's echoed token against this in-memory value (after
122
- * the workerId ownership guard) to reject a stale completion from an earlier
123
- * attempt reassigned to the same worker.
124
- */
125
- attemptToken?: string;
119
+ /** Unique, unguessable token for this dispatch attempt. */
120
+ attemptToken: string;
126
121
  }
127
122
  export interface WorkerRegistryOptions {
128
123
  /** Routing policy used by {@link WorkerRegistry.findWorker}. Default: `'least-loaded'`. */
@@ -45,7 +45,7 @@ export declare class WorkerRegistry {
45
45
  */
46
46
  findWorker(activityName: string, options?: RoutingOptions): WorkerInfo | undefined;
47
47
  /** Track a task assignment with a visibility timeout deadline. */
48
- assignTask(workerId: string, operationId: string, visibilityTimeout: number, fairShareKey?: string, attemptToken?: string): void;
48
+ assignTask(workerId: string, operationId: string, visibilityTimeout: number, fairShareKey: string | undefined, attemptToken: string): void;
49
49
  /** Return tasks whose deadline has passed and remove them from tracking. */
50
50
  checkExpiredTasks(now: number): InFlightTask[];
51
51
  /**
@@ -63,15 +63,9 @@ export declare class WorkerRegistry {
63
63
  * to reject a stale completion from an EARLIER attempt that was reassigned to the
64
64
  * same worker — the only case the workerId guard alone cannot catch.
65
65
  *
66
- * The token check is purely additive, so a worker that predates the field is
67
- * never refused (no protocol version bump): it fires only when the tracked
68
- * task has a stored token AND the completion echoes one AND they differ. A
69
- * token-less task matches any echo, and an absent echo falls back to the
70
- * workerId-only guard that already passed. The defended case — a stale earlier
71
- * attempt — always echoes the OLD token it was dispatched with (present, wrong),
72
- * so it is still rejected.
66
+ * The workerId and token must both match the current assignment exactly.
73
67
  */
74
- isAssignedToAttempt(operationId: string, workerId: string, attemptToken: string | undefined): boolean;
68
+ isAssignedToAttempt(operationId: string, workerId: string, attemptToken: string): boolean;
75
69
  /** Check whether an operation is currently assigned to a worker. */
76
70
  isAssigned(operationId: string): boolean;
77
71
  /** Look up an in-flight task by operationId in O(1). */
@@ -114,10 +114,9 @@ export class WorkerRegistry {
114
114
  operationId,
115
115
  workerId,
116
116
  deadline,
117
- visibilityTimeout
117
+ visibilityTimeout,
118
+ attemptToken
118
119
  };
119
- if (attemptToken !== void 0)
120
- task.attemptToken = attemptToken;
121
120
  if (fairShareKey !== void 0) {
122
121
  task.fairShareKey = fairShareKey;
123
122
  this.#fairShareCounts.increment(workerId, fairShareKey);
@@ -157,8 +156,6 @@ export class WorkerRegistry {
157
156
  const task = this.#inFlightTasks.get(operationId);
158
157
  if (task === void 0 || task.workerId !== workerId)
159
158
  return !1;
160
- if (task.attemptToken === void 0 || attemptToken === void 0)
161
- return !0;
162
159
  return task.attemptToken === attemptToken;
163
160
  }
164
161
  isAssigned(operationId) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lostgradient/weft",
3
- "version": "0.13.0",
3
+ "version": "0.15.0",
4
4
  "description": "A Bun-native durable execution engine with pluggable key-value storage.",
5
5
  "keywords": [
6
6
  "bun",