@runtypelabs/sdk 1.23.0 → 1.24.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +80 -2
- package/dist/index.d.cts +8 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.mjs +80 -2
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -469,6 +469,53 @@ var FlowResult = class {
|
|
|
469
469
|
};
|
|
470
470
|
|
|
471
471
|
// src/flows-namespace.ts
|
|
472
|
+
function isRecord(value) {
|
|
473
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
474
|
+
}
|
|
475
|
+
function normalizeConfig(config) {
|
|
476
|
+
if (!isRecord(config)) return {};
|
|
477
|
+
const normalized = {};
|
|
478
|
+
for (const key of Object.keys(config).sort()) {
|
|
479
|
+
const value = config[key];
|
|
480
|
+
if (value === void 0) continue;
|
|
481
|
+
if (value !== null && typeof value === "object" && !Array.isArray(value)) {
|
|
482
|
+
normalized[key] = normalizeConfig(value);
|
|
483
|
+
} else if (Array.isArray(value)) {
|
|
484
|
+
normalized[key] = value.map((item) => {
|
|
485
|
+
if (item !== null && typeof item === "object" && !Array.isArray(item)) {
|
|
486
|
+
return normalizeConfig(item);
|
|
487
|
+
}
|
|
488
|
+
return item;
|
|
489
|
+
});
|
|
490
|
+
} else {
|
|
491
|
+
normalized[key] = value;
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
return normalized;
|
|
495
|
+
}
|
|
496
|
+
function normalizeStepForHash(step) {
|
|
497
|
+
const stepObj = isRecord(step) ? step : {};
|
|
498
|
+
return {
|
|
499
|
+
type: typeof stepObj.type === "string" ? stepObj.type : "",
|
|
500
|
+
name: typeof stepObj.name === "string" ? stepObj.name : "",
|
|
501
|
+
enabled: stepObj.enabled !== false,
|
|
502
|
+
...typeof stepObj.when === "string" ? { when: stepObj.when } : {},
|
|
503
|
+
config: normalizeConfig(stepObj.config),
|
|
504
|
+
order: typeof stepObj.order === "number" ? stepObj.order : 0
|
|
505
|
+
};
|
|
506
|
+
}
|
|
507
|
+
async function computeFlowContentHash(steps) {
|
|
508
|
+
const normalized = [...steps].sort((a, b) => {
|
|
509
|
+
const orderA = isRecord(a) && typeof a.order === "number" ? a.order : 0;
|
|
510
|
+
const orderB = isRecord(b) && typeof b.order === "number" ? b.order : 0;
|
|
511
|
+
return orderA - orderB;
|
|
512
|
+
}).map(normalizeStepForHash);
|
|
513
|
+
const serialized = JSON.stringify(normalized);
|
|
514
|
+
const encoded = new TextEncoder().encode(serialized);
|
|
515
|
+
const hashBuffer = await crypto.subtle.digest("SHA-256", encoded);
|
|
516
|
+
const hashArray = new Uint8Array(hashBuffer);
|
|
517
|
+
return Array.from(hashArray).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
518
|
+
}
|
|
472
519
|
var FlowsNamespace = class {
|
|
473
520
|
constructor(getClient) {
|
|
474
521
|
this.getClient = getClient;
|
|
@@ -914,7 +961,7 @@ var RuntypeFlowBuilder = class {
|
|
|
914
961
|
}
|
|
915
962
|
config.options = { ...config.options, streamResponse: true };
|
|
916
963
|
const client = this.getClient();
|
|
917
|
-
const response = await
|
|
964
|
+
const response = await this.dispatchWithPersistedFlow(client, config);
|
|
918
965
|
const result = new FlowResult(response);
|
|
919
966
|
if (callbacks) {
|
|
920
967
|
await result.stream(callbacks);
|
|
@@ -943,7 +990,7 @@ var RuntypeFlowBuilder = class {
|
|
|
943
990
|
}
|
|
944
991
|
config.options = { ...config.options, streamResponse: true };
|
|
945
992
|
const client = this.getClient();
|
|
946
|
-
const response = await
|
|
993
|
+
const response = await this.dispatchWithPersistedFlow(client, config);
|
|
947
994
|
const result = new FlowResult(response);
|
|
948
995
|
await result.getSummary();
|
|
949
996
|
return result;
|
|
@@ -1127,6 +1174,37 @@ var RuntypeFlowBuilder = class {
|
|
|
1127
1174
|
// ============================================================================
|
|
1128
1175
|
// Private Helpers
|
|
1129
1176
|
// ============================================================================
|
|
1177
|
+
/**
|
|
1178
|
+
* Persisted flow protocol (APQ-style): send hash-only first, retry with
|
|
1179
|
+
* full definition on FLOW_DEFINITION_REQUIRED. For non-upsert modes,
|
|
1180
|
+
* dispatches directly.
|
|
1181
|
+
*/
|
|
1182
|
+
async dispatchWithPersistedFlow(client, config) {
|
|
1183
|
+
if (this.mode !== "upsert" || !this.steps.length) {
|
|
1184
|
+
return client.dispatch(config);
|
|
1185
|
+
}
|
|
1186
|
+
const contentHash = await this.computeContentHash();
|
|
1187
|
+
const hashOnlyConfig = {
|
|
1188
|
+
...config,
|
|
1189
|
+
flow: { name: config.flow.name, contentHash }
|
|
1190
|
+
};
|
|
1191
|
+
try {
|
|
1192
|
+
return await client.dispatch(hashOnlyConfig);
|
|
1193
|
+
} catch (err) {
|
|
1194
|
+
const is422 = err != null && typeof err === "object" && "statusCode" in err && err.statusCode === 422 || err instanceof Error && /\b422\b/.test(err.message);
|
|
1195
|
+
if (!is422) {
|
|
1196
|
+
throw err;
|
|
1197
|
+
}
|
|
1198
|
+
}
|
|
1199
|
+
const fullConfig = {
|
|
1200
|
+
...config,
|
|
1201
|
+
flow: { ...config.flow, contentHash }
|
|
1202
|
+
};
|
|
1203
|
+
return client.dispatch(fullConfig);
|
|
1204
|
+
}
|
|
1205
|
+
async computeContentHash() {
|
|
1206
|
+
return computeFlowContentHash(this.steps);
|
|
1207
|
+
}
|
|
1130
1208
|
addStep(type, name, config, enabled = true) {
|
|
1131
1209
|
this.stepCounter++;
|
|
1132
1210
|
const cleanConfig = {};
|
package/dist/index.d.cts
CHANGED
|
@@ -1383,6 +1383,7 @@ interface DispatchRequest {
|
|
|
1383
1383
|
flow: {
|
|
1384
1384
|
id?: string;
|
|
1385
1385
|
name?: string;
|
|
1386
|
+
contentHash?: string;
|
|
1386
1387
|
steps?: Array<any>;
|
|
1387
1388
|
};
|
|
1388
1389
|
messages?: Array<{
|
|
@@ -1935,6 +1936,13 @@ declare class RuntypeFlowBuilder {
|
|
|
1935
1936
|
*/
|
|
1936
1937
|
runWithLocalTools(localTools: Record<string, (args: unknown) => Promise<unknown>>, callbacks?: StreamCallbacks): Promise<FlowResult>;
|
|
1937
1938
|
build(): DispatchRequest;
|
|
1939
|
+
/**
|
|
1940
|
+
* Persisted flow protocol (APQ-style): send hash-only first, retry with
|
|
1941
|
+
* full definition on FLOW_DEFINITION_REQUIRED. For non-upsert modes,
|
|
1942
|
+
* dispatches directly.
|
|
1943
|
+
*/
|
|
1944
|
+
private dispatchWithPersistedFlow;
|
|
1945
|
+
private computeContentHash;
|
|
1938
1946
|
private addStep;
|
|
1939
1947
|
}
|
|
1940
1948
|
|
package/dist/index.d.ts
CHANGED
|
@@ -1383,6 +1383,7 @@ interface DispatchRequest {
|
|
|
1383
1383
|
flow: {
|
|
1384
1384
|
id?: string;
|
|
1385
1385
|
name?: string;
|
|
1386
|
+
contentHash?: string;
|
|
1386
1387
|
steps?: Array<any>;
|
|
1387
1388
|
};
|
|
1388
1389
|
messages?: Array<{
|
|
@@ -1935,6 +1936,13 @@ declare class RuntypeFlowBuilder {
|
|
|
1935
1936
|
*/
|
|
1936
1937
|
runWithLocalTools(localTools: Record<string, (args: unknown) => Promise<unknown>>, callbacks?: StreamCallbacks): Promise<FlowResult>;
|
|
1937
1938
|
build(): DispatchRequest;
|
|
1939
|
+
/**
|
|
1940
|
+
* Persisted flow protocol (APQ-style): send hash-only first, retry with
|
|
1941
|
+
* full definition on FLOW_DEFINITION_REQUIRED. For non-upsert modes,
|
|
1942
|
+
* dispatches directly.
|
|
1943
|
+
*/
|
|
1944
|
+
private dispatchWithPersistedFlow;
|
|
1945
|
+
private computeContentHash;
|
|
1938
1946
|
private addStep;
|
|
1939
1947
|
}
|
|
1940
1948
|
|
package/dist/index.mjs
CHANGED
|
@@ -397,6 +397,53 @@ var FlowResult = class {
|
|
|
397
397
|
};
|
|
398
398
|
|
|
399
399
|
// src/flows-namespace.ts
|
|
400
|
+
function isRecord(value) {
|
|
401
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
402
|
+
}
|
|
403
|
+
function normalizeConfig(config) {
|
|
404
|
+
if (!isRecord(config)) return {};
|
|
405
|
+
const normalized = {};
|
|
406
|
+
for (const key of Object.keys(config).sort()) {
|
|
407
|
+
const value = config[key];
|
|
408
|
+
if (value === void 0) continue;
|
|
409
|
+
if (value !== null && typeof value === "object" && !Array.isArray(value)) {
|
|
410
|
+
normalized[key] = normalizeConfig(value);
|
|
411
|
+
} else if (Array.isArray(value)) {
|
|
412
|
+
normalized[key] = value.map((item) => {
|
|
413
|
+
if (item !== null && typeof item === "object" && !Array.isArray(item)) {
|
|
414
|
+
return normalizeConfig(item);
|
|
415
|
+
}
|
|
416
|
+
return item;
|
|
417
|
+
});
|
|
418
|
+
} else {
|
|
419
|
+
normalized[key] = value;
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
return normalized;
|
|
423
|
+
}
|
|
424
|
+
function normalizeStepForHash(step) {
|
|
425
|
+
const stepObj = isRecord(step) ? step : {};
|
|
426
|
+
return {
|
|
427
|
+
type: typeof stepObj.type === "string" ? stepObj.type : "",
|
|
428
|
+
name: typeof stepObj.name === "string" ? stepObj.name : "",
|
|
429
|
+
enabled: stepObj.enabled !== false,
|
|
430
|
+
...typeof stepObj.when === "string" ? { when: stepObj.when } : {},
|
|
431
|
+
config: normalizeConfig(stepObj.config),
|
|
432
|
+
order: typeof stepObj.order === "number" ? stepObj.order : 0
|
|
433
|
+
};
|
|
434
|
+
}
|
|
435
|
+
async function computeFlowContentHash(steps) {
|
|
436
|
+
const normalized = [...steps].sort((a, b) => {
|
|
437
|
+
const orderA = isRecord(a) && typeof a.order === "number" ? a.order : 0;
|
|
438
|
+
const orderB = isRecord(b) && typeof b.order === "number" ? b.order : 0;
|
|
439
|
+
return orderA - orderB;
|
|
440
|
+
}).map(normalizeStepForHash);
|
|
441
|
+
const serialized = JSON.stringify(normalized);
|
|
442
|
+
const encoded = new TextEncoder().encode(serialized);
|
|
443
|
+
const hashBuffer = await crypto.subtle.digest("SHA-256", encoded);
|
|
444
|
+
const hashArray = new Uint8Array(hashBuffer);
|
|
445
|
+
return Array.from(hashArray).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
446
|
+
}
|
|
400
447
|
var FlowsNamespace = class {
|
|
401
448
|
constructor(getClient) {
|
|
402
449
|
this.getClient = getClient;
|
|
@@ -842,7 +889,7 @@ var RuntypeFlowBuilder = class {
|
|
|
842
889
|
}
|
|
843
890
|
config.options = { ...config.options, streamResponse: true };
|
|
844
891
|
const client = this.getClient();
|
|
845
|
-
const response = await
|
|
892
|
+
const response = await this.dispatchWithPersistedFlow(client, config);
|
|
846
893
|
const result = new FlowResult(response);
|
|
847
894
|
if (callbacks) {
|
|
848
895
|
await result.stream(callbacks);
|
|
@@ -871,7 +918,7 @@ var RuntypeFlowBuilder = class {
|
|
|
871
918
|
}
|
|
872
919
|
config.options = { ...config.options, streamResponse: true };
|
|
873
920
|
const client = this.getClient();
|
|
874
|
-
const response = await
|
|
921
|
+
const response = await this.dispatchWithPersistedFlow(client, config);
|
|
875
922
|
const result = new FlowResult(response);
|
|
876
923
|
await result.getSummary();
|
|
877
924
|
return result;
|
|
@@ -1055,6 +1102,37 @@ var RuntypeFlowBuilder = class {
|
|
|
1055
1102
|
// ============================================================================
|
|
1056
1103
|
// Private Helpers
|
|
1057
1104
|
// ============================================================================
|
|
1105
|
+
/**
|
|
1106
|
+
* Persisted flow protocol (APQ-style): send hash-only first, retry with
|
|
1107
|
+
* full definition on FLOW_DEFINITION_REQUIRED. For non-upsert modes,
|
|
1108
|
+
* dispatches directly.
|
|
1109
|
+
*/
|
|
1110
|
+
async dispatchWithPersistedFlow(client, config) {
|
|
1111
|
+
if (this.mode !== "upsert" || !this.steps.length) {
|
|
1112
|
+
return client.dispatch(config);
|
|
1113
|
+
}
|
|
1114
|
+
const contentHash = await this.computeContentHash();
|
|
1115
|
+
const hashOnlyConfig = {
|
|
1116
|
+
...config,
|
|
1117
|
+
flow: { name: config.flow.name, contentHash }
|
|
1118
|
+
};
|
|
1119
|
+
try {
|
|
1120
|
+
return await client.dispatch(hashOnlyConfig);
|
|
1121
|
+
} catch (err) {
|
|
1122
|
+
const is422 = err != null && typeof err === "object" && "statusCode" in err && err.statusCode === 422 || err instanceof Error && /\b422\b/.test(err.message);
|
|
1123
|
+
if (!is422) {
|
|
1124
|
+
throw err;
|
|
1125
|
+
}
|
|
1126
|
+
}
|
|
1127
|
+
const fullConfig = {
|
|
1128
|
+
...config,
|
|
1129
|
+
flow: { ...config.flow, contentHash }
|
|
1130
|
+
};
|
|
1131
|
+
return client.dispatch(fullConfig);
|
|
1132
|
+
}
|
|
1133
|
+
async computeContentHash() {
|
|
1134
|
+
return computeFlowContentHash(this.steps);
|
|
1135
|
+
}
|
|
1058
1136
|
addStep(type, name, config, enabled = true) {
|
|
1059
1137
|
this.stepCounter++;
|
|
1060
1138
|
const cleanConfig = {};
|
package/package.json
CHANGED