avantgate 1.3.0 → 1.5.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.
- package/README.md +8 -3
- package/dist/agent/index.mjs +12 -279
- package/dist/agent/types.d.ts +5 -1
- package/dist/agent/types.d.ts.map +1 -1
- package/dist/chunk-4XWO3NZW.mjs +303 -0
- package/dist/chunk-5VA3EKPJ.mjs +344 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +531 -0
- package/dist/index.mjs +17 -3
- package/dist/workflow/define-workflow.d.ts +3 -0
- package/dist/workflow/define-workflow.d.ts.map +1 -0
- package/dist/workflow/engine.d.ts +3 -0
- package/dist/workflow/engine.d.ts.map +1 -0
- package/dist/workflow/errors.d.ts +31 -0
- package/dist/workflow/errors.d.ts.map +1 -0
- package/dist/workflow/index.d.ts +5 -0
- package/dist/workflow/index.d.ts.map +1 -0
- package/dist/workflow/index.js +611 -0
- package/dist/workflow/index.mjs +17 -0
- package/dist/workflow/types.d.ts +67 -0
- package/dist/workflow/types.d.ts.map +1 -0
- package/package.json +9 -3
- package/dist/chunk-DVCF4CSV.mjs +0 -56
package/dist/index.js
CHANGED
|
@@ -33,12 +33,18 @@ __export(index_exports, {
|
|
|
33
33
|
PromptRegistry: () => PromptRegistry,
|
|
34
34
|
PromptTemplate: () => PromptTemplate,
|
|
35
35
|
SEED_MODEL_PRICES: () => SEED_MODEL_PRICES,
|
|
36
|
+
WorkflowAbortSignal: () => WorkflowAbortSignal,
|
|
37
|
+
WorkflowSagaRollbackError: () => WorkflowSagaRollbackError,
|
|
38
|
+
WorkflowValidationError: () => WorkflowValidationError,
|
|
36
39
|
ZenLLMControlLayer: () => AvantGateControlLayer,
|
|
37
40
|
calculateCostUSD: () => calculateCostUSD,
|
|
38
41
|
createAvantGate: () => createAvantGate,
|
|
39
42
|
createHttpProviderClient: () => createHttpProviderClient,
|
|
40
43
|
createLLMControlLayer: () => createLLMControlLayer,
|
|
44
|
+
defineWorkflow: () => defineWorkflow,
|
|
45
|
+
executeWorkflow: () => executeWorkflow,
|
|
41
46
|
extractAndCleanJSON: () => extractAndCleanJSON,
|
|
47
|
+
isWorkflowAbortSignal: () => isWorkflowAbortSignal,
|
|
42
48
|
resolveModelPrice: () => resolveModelPrice,
|
|
43
49
|
resolveModelPriceAsync: () => resolveModelPriceAsync,
|
|
44
50
|
sanitizePII: () => sanitizePII,
|
|
@@ -1629,6 +1635,525 @@ var PromptRegistry = class {
|
|
|
1629
1635
|
this.registry.clear();
|
|
1630
1636
|
}
|
|
1631
1637
|
};
|
|
1638
|
+
|
|
1639
|
+
// src/agent/errors.ts
|
|
1640
|
+
var StepSuspendedError = class extends Error {
|
|
1641
|
+
stepId;
|
|
1642
|
+
workflowId;
|
|
1643
|
+
metadata;
|
|
1644
|
+
constructor(stepId, workflowId, metadata) {
|
|
1645
|
+
super(`Step execution suspended for human approval: [${workflowId}::${stepId}]`);
|
|
1646
|
+
this.name = "StepSuspendedError";
|
|
1647
|
+
this.stepId = stepId;
|
|
1648
|
+
this.workflowId = workflowId;
|
|
1649
|
+
this.metadata = metadata;
|
|
1650
|
+
}
|
|
1651
|
+
};
|
|
1652
|
+
var PiiLeakError = class extends Error {
|
|
1653
|
+
toolName;
|
|
1654
|
+
maskedCount;
|
|
1655
|
+
constructor(toolName, maskedCount) {
|
|
1656
|
+
super(`PII leak detected in tool output for "${toolName}" (${maskedCount} occurrences detected).`);
|
|
1657
|
+
this.name = "PiiLeakError";
|
|
1658
|
+
this.toolName = toolName;
|
|
1659
|
+
this.maskedCount = maskedCount;
|
|
1660
|
+
}
|
|
1661
|
+
};
|
|
1662
|
+
var ToolAccessDeniedError = class extends Error {
|
|
1663
|
+
toolName;
|
|
1664
|
+
requiredRole;
|
|
1665
|
+
reason;
|
|
1666
|
+
constructor(toolName, reasonOrRole) {
|
|
1667
|
+
const isRole = Boolean(reasonOrRole && !reasonOrRole.includes(" "));
|
|
1668
|
+
const roleMsg = isRole ? ` (requires role "${reasonOrRole}")` : "";
|
|
1669
|
+
const reasonMsg = reasonOrRole && !isRole ? `: ${reasonOrRole}` : "";
|
|
1670
|
+
super(`Access denied for tool "${toolName}"${roleMsg}${reasonMsg}.`);
|
|
1671
|
+
this.name = "ToolAccessDeniedError";
|
|
1672
|
+
this.toolName = toolName;
|
|
1673
|
+
if (isRole) {
|
|
1674
|
+
this.requiredRole = reasonOrRole;
|
|
1675
|
+
} else {
|
|
1676
|
+
this.reason = reasonOrRole;
|
|
1677
|
+
}
|
|
1678
|
+
}
|
|
1679
|
+
};
|
|
1680
|
+
var DtoValidationError = class extends Error {
|
|
1681
|
+
toolName;
|
|
1682
|
+
issues;
|
|
1683
|
+
constructor(toolName, message, issues = []) {
|
|
1684
|
+
super(`LLM DTO validation failed for tool "${toolName}": ${message}`);
|
|
1685
|
+
this.name = "DtoValidationError";
|
|
1686
|
+
this.toolName = toolName;
|
|
1687
|
+
this.issues = issues;
|
|
1688
|
+
}
|
|
1689
|
+
};
|
|
1690
|
+
|
|
1691
|
+
// src/agent/guardrails.ts
|
|
1692
|
+
function sanitizeString(value) {
|
|
1693
|
+
const result = sanitizePII(value);
|
|
1694
|
+
return { text: result.text, count: result.maskedCount };
|
|
1695
|
+
}
|
|
1696
|
+
function sanitizeArray(items, options, visited) {
|
|
1697
|
+
let totalCount = 0;
|
|
1698
|
+
const sanitized = items.map((item) => {
|
|
1699
|
+
const res = recursivelySanitize(item, options, visited);
|
|
1700
|
+
totalCount += res.count;
|
|
1701
|
+
return res.sanitized;
|
|
1702
|
+
});
|
|
1703
|
+
return { sanitized, count: totalCount };
|
|
1704
|
+
}
|
|
1705
|
+
function sanitizeObject(target, options, visited) {
|
|
1706
|
+
let totalCount = 0;
|
|
1707
|
+
const copy = {};
|
|
1708
|
+
for (const [key, val] of Object.entries(target)) {
|
|
1709
|
+
const res = recursivelySanitize(val, options, visited);
|
|
1710
|
+
copy[key] = res.sanitized;
|
|
1711
|
+
totalCount += res.count;
|
|
1712
|
+
}
|
|
1713
|
+
return { sanitized: copy, count: totalCount };
|
|
1714
|
+
}
|
|
1715
|
+
function recursivelySanitize(data, options, visited = /* @__PURE__ */ new WeakSet()) {
|
|
1716
|
+
if (typeof data === "string") {
|
|
1717
|
+
const res = sanitizeString(data);
|
|
1718
|
+
return { sanitized: res.text, count: res.count };
|
|
1719
|
+
}
|
|
1720
|
+
if (data !== null && typeof data === "object") {
|
|
1721
|
+
if (visited.has(data)) {
|
|
1722
|
+
return { sanitized: "[CIRCULAR_REFERENCE]", count: 0 };
|
|
1723
|
+
}
|
|
1724
|
+
visited.add(data);
|
|
1725
|
+
if (Array.isArray(data)) {
|
|
1726
|
+
return sanitizeArray(data, options, visited);
|
|
1727
|
+
}
|
|
1728
|
+
return sanitizeObject(data, options, visited);
|
|
1729
|
+
}
|
|
1730
|
+
return { sanitized: data, count: 0 };
|
|
1731
|
+
}
|
|
1732
|
+
function auditToolResult(data, options) {
|
|
1733
|
+
const { sanitized, count } = recursivelySanitize(data, options);
|
|
1734
|
+
if (options.throwOnPii && count > 0) {
|
|
1735
|
+
throw new PiiLeakError(options.toolName, count);
|
|
1736
|
+
}
|
|
1737
|
+
return {
|
|
1738
|
+
sanitizedData: sanitized,
|
|
1739
|
+
maskedCount: count
|
|
1740
|
+
};
|
|
1741
|
+
}
|
|
1742
|
+
|
|
1743
|
+
// src/agent/isolated-tool.ts
|
|
1744
|
+
async function verifyDataAccessGuard(guard, args, context, toolIdentifier) {
|
|
1745
|
+
if (!guard) {
|
|
1746
|
+
return;
|
|
1747
|
+
}
|
|
1748
|
+
const isAllowed = await guard(args, context);
|
|
1749
|
+
if (!isAllowed) {
|
|
1750
|
+
throw new ToolAccessDeniedError(toolIdentifier, "Access denied by data access guard");
|
|
1751
|
+
}
|
|
1752
|
+
}
|
|
1753
|
+
async function resolveInvalidationTags(config, args, rawResult, context) {
|
|
1754
|
+
if (!config.invalidationTags) {
|
|
1755
|
+
return void 0;
|
|
1756
|
+
}
|
|
1757
|
+
const tags = typeof config.invalidationTags === "function" ? await config.invalidationTags(args, rawResult) : config.invalidationTags;
|
|
1758
|
+
if (tags && tags.length > 0 && context?.onInvalidationTags) {
|
|
1759
|
+
await context.onInvalidationTags(tags);
|
|
1760
|
+
}
|
|
1761
|
+
return tags;
|
|
1762
|
+
}
|
|
1763
|
+
async function dispatchClientData(rawResult, callback) {
|
|
1764
|
+
if (!callback) {
|
|
1765
|
+
return;
|
|
1766
|
+
}
|
|
1767
|
+
await callback(rawResult);
|
|
1768
|
+
}
|
|
1769
|
+
async function produceLlmPayload(rawResult, args, context, transformer) {
|
|
1770
|
+
if (transformer) {
|
|
1771
|
+
return await transformer(rawResult, args, context);
|
|
1772
|
+
}
|
|
1773
|
+
return rawResult;
|
|
1774
|
+
}
|
|
1775
|
+
function validateLlmDto(payload, schema, toolIdentifier) {
|
|
1776
|
+
const parseResult = schema.safeParse(payload);
|
|
1777
|
+
if (!parseResult.success) {
|
|
1778
|
+
const issues = parseResult.error.issues ?? [];
|
|
1779
|
+
const errorMessages = issues.map((issue) => `${issue.path.join(".") || "root"}: ${issue.message}`).join(", ");
|
|
1780
|
+
throw new DtoValidationError(
|
|
1781
|
+
toolIdentifier,
|
|
1782
|
+
errorMessages,
|
|
1783
|
+
issues
|
|
1784
|
+
);
|
|
1785
|
+
}
|
|
1786
|
+
return parseResult.data;
|
|
1787
|
+
}
|
|
1788
|
+
function protectLlmPayload(payload, toolIdentifier, sanitizePii = true, throwOnPii = false) {
|
|
1789
|
+
if (!sanitizePii) {
|
|
1790
|
+
return { sanitized: payload, count: 0 };
|
|
1791
|
+
}
|
|
1792
|
+
const { sanitizedData, maskedCount } = auditToolResult(payload, {
|
|
1793
|
+
toolName: toolIdentifier,
|
|
1794
|
+
throwOnPii
|
|
1795
|
+
});
|
|
1796
|
+
return { sanitized: sanitizedData, count: maskedCount };
|
|
1797
|
+
}
|
|
1798
|
+
async function processLlmPayload(rawResult, args, context, config, toolIdentifier) {
|
|
1799
|
+
let payload = await produceLlmPayload(rawResult, args, context, config.llmDto);
|
|
1800
|
+
if (config.llmDtoSchema) {
|
|
1801
|
+
payload = validateLlmDto(payload, config.llmDtoSchema, toolIdentifier);
|
|
1802
|
+
}
|
|
1803
|
+
return protectLlmPayload(
|
|
1804
|
+
payload,
|
|
1805
|
+
toolIdentifier,
|
|
1806
|
+
config.sanitizePii !== false,
|
|
1807
|
+
config.throwOnPii === true
|
|
1808
|
+
);
|
|
1809
|
+
}
|
|
1810
|
+
function createIsolatedTool(config) {
|
|
1811
|
+
const toolId = config.id || config.name;
|
|
1812
|
+
const toolAlias = config.alias;
|
|
1813
|
+
const clientCallback = config.clientDto;
|
|
1814
|
+
const toolIdentifier = toolAlias || config.name;
|
|
1815
|
+
const toolImpact = config.impact ?? "READ_ONLY";
|
|
1816
|
+
const requireApproval = config.requireApproval ?? toolImpact === "DESTRUCTIVE";
|
|
1817
|
+
const tool = {
|
|
1818
|
+
description: config.description,
|
|
1819
|
+
parameters: config.parameters,
|
|
1820
|
+
_toolId: toolId,
|
|
1821
|
+
_toolName: config.name,
|
|
1822
|
+
_toolAlias: toolAlias,
|
|
1823
|
+
_isIsolated: true,
|
|
1824
|
+
_cacheTTL: config.cacheTTL,
|
|
1825
|
+
_domain: config.domain,
|
|
1826
|
+
_resource: config.resource,
|
|
1827
|
+
_roles: config.roles ? Object.freeze([...config.roles]) : void 0,
|
|
1828
|
+
_impact: toolImpact,
|
|
1829
|
+
_requireApproval: requireApproval,
|
|
1830
|
+
_lastPiiFilteredCount: 0,
|
|
1831
|
+
_lastInvalidationTags: void 0,
|
|
1832
|
+
async execute(args, context) {
|
|
1833
|
+
const updatedContext = {
|
|
1834
|
+
...context,
|
|
1835
|
+
callChain: context?.callChain ?? Object.freeze([toolId])
|
|
1836
|
+
};
|
|
1837
|
+
await verifyDataAccessGuard(
|
|
1838
|
+
config.dataAccessGuard,
|
|
1839
|
+
args,
|
|
1840
|
+
updatedContext,
|
|
1841
|
+
toolIdentifier
|
|
1842
|
+
);
|
|
1843
|
+
const rawResult = await config.execute(args, updatedContext);
|
|
1844
|
+
const tags = await resolveInvalidationTags(
|
|
1845
|
+
config,
|
|
1846
|
+
args,
|
|
1847
|
+
rawResult,
|
|
1848
|
+
updatedContext
|
|
1849
|
+
);
|
|
1850
|
+
if (tags) {
|
|
1851
|
+
tool._lastInvalidationTags = tags;
|
|
1852
|
+
}
|
|
1853
|
+
await dispatchClientData(rawResult, clientCallback);
|
|
1854
|
+
const protection = await processLlmPayload(
|
|
1855
|
+
rawResult,
|
|
1856
|
+
args,
|
|
1857
|
+
updatedContext,
|
|
1858
|
+
config,
|
|
1859
|
+
toolIdentifier
|
|
1860
|
+
);
|
|
1861
|
+
tool._lastPiiFilteredCount = protection.count;
|
|
1862
|
+
return protection.sanitized;
|
|
1863
|
+
}
|
|
1864
|
+
};
|
|
1865
|
+
return tool;
|
|
1866
|
+
}
|
|
1867
|
+
|
|
1868
|
+
// src/workflow/errors.ts
|
|
1869
|
+
var WorkflowSagaRollbackError = class extends Error {
|
|
1870
|
+
workflowId;
|
|
1871
|
+
failedStepId;
|
|
1872
|
+
originalError;
|
|
1873
|
+
compensatedSteps;
|
|
1874
|
+
failedCompensations;
|
|
1875
|
+
constructor(params) {
|
|
1876
|
+
const errorDetails = params.originalError instanceof Error ? params.originalError.message : String(params.originalError);
|
|
1877
|
+
super(
|
|
1878
|
+
`\xC9chec de l'\xE9tape '${params.failedStepId}' dans le workflow '${params.workflowId}'. Rollback Saga ex\xE9cut\xE9 sur [${params.compensatedSteps.join(", ")}]. Cause initiale: ${errorDetails}`
|
|
1879
|
+
);
|
|
1880
|
+
this.name = "WorkflowSagaRollbackError";
|
|
1881
|
+
this.workflowId = params.workflowId;
|
|
1882
|
+
this.failedStepId = params.failedStepId;
|
|
1883
|
+
this.originalError = params.originalError;
|
|
1884
|
+
this.compensatedSteps = params.compensatedSteps;
|
|
1885
|
+
this.failedCompensations = params.failedCompensations ?? [];
|
|
1886
|
+
}
|
|
1887
|
+
};
|
|
1888
|
+
var WorkflowValidationError = class extends Error {
|
|
1889
|
+
workflowId;
|
|
1890
|
+
issues;
|
|
1891
|
+
constructor(workflowId, issues) {
|
|
1892
|
+
super(`Validation des entr\xE9es \xE9chou\xE9e pour le workflow '${workflowId}'.`);
|
|
1893
|
+
this.name = "WorkflowValidationError";
|
|
1894
|
+
this.workflowId = workflowId;
|
|
1895
|
+
this.issues = issues;
|
|
1896
|
+
}
|
|
1897
|
+
};
|
|
1898
|
+
var WorkflowAbortSignal = class extends Error {
|
|
1899
|
+
__isWorkflowAbort = true;
|
|
1900
|
+
reason;
|
|
1901
|
+
payload;
|
|
1902
|
+
constructor(reason, payload) {
|
|
1903
|
+
super(`Workflow aborted: ${reason}`);
|
|
1904
|
+
this.name = "WorkflowAbortSignal";
|
|
1905
|
+
this.reason = reason;
|
|
1906
|
+
this.payload = payload;
|
|
1907
|
+
}
|
|
1908
|
+
};
|
|
1909
|
+
var isWorkflowAbortSignal = (value) => {
|
|
1910
|
+
return typeof value === "object" && value !== null && value.__isWorkflowAbort === true;
|
|
1911
|
+
};
|
|
1912
|
+
|
|
1913
|
+
// src/workflow/engine.ts
|
|
1914
|
+
var generateRunId = (workflowId) => {
|
|
1915
|
+
const timestamp = Date.now();
|
|
1916
|
+
const randomSuffix = Math.random().toString(36).substring(2, 9);
|
|
1917
|
+
return `run_${workflowId}_${timestamp}_${randomSuffix}`;
|
|
1918
|
+
};
|
|
1919
|
+
var validateInput = (config, input) => {
|
|
1920
|
+
const parseResult = config.inputSchema.safeParse(input);
|
|
1921
|
+
if (!parseResult.success) {
|
|
1922
|
+
throw new WorkflowValidationError(config.id, parseResult.error.issues);
|
|
1923
|
+
}
|
|
1924
|
+
return parseResult.data;
|
|
1925
|
+
};
|
|
1926
|
+
var createStepContext = (params) => {
|
|
1927
|
+
const { workflowId, stepId, runId, context, stepResults } = params;
|
|
1928
|
+
return {
|
|
1929
|
+
workflowId,
|
|
1930
|
+
stepId,
|
|
1931
|
+
runId,
|
|
1932
|
+
tenantId: context?.tenantId,
|
|
1933
|
+
userId: context?.userId,
|
|
1934
|
+
services: context?.services ?? {},
|
|
1935
|
+
storage: context?.storage,
|
|
1936
|
+
getStepResult: (id) => stepResults[id],
|
|
1937
|
+
waitForApproval: async (options) => {
|
|
1938
|
+
if (context?.storage) {
|
|
1939
|
+
const existing = await context.storage.getStep(workflowId, stepId);
|
|
1940
|
+
if (existing && existing.status === "COMPLETED") {
|
|
1941
|
+
return existing.result ?? options?.defaultResult;
|
|
1942
|
+
}
|
|
1943
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
1944
|
+
await context.storage.saveStep({
|
|
1945
|
+
workflowId,
|
|
1946
|
+
stepId,
|
|
1947
|
+
runId,
|
|
1948
|
+
status: "WAITING_APPROVAL",
|
|
1949
|
+
metadata: options?.metadata,
|
|
1950
|
+
createdAt: now,
|
|
1951
|
+
updatedAt: now
|
|
1952
|
+
});
|
|
1953
|
+
}
|
|
1954
|
+
throw new StepSuspendedError(stepId, workflowId, options?.prompt);
|
|
1955
|
+
},
|
|
1956
|
+
abort: (reason, payload) => {
|
|
1957
|
+
throw new WorkflowAbortSignal(reason, payload);
|
|
1958
|
+
}
|
|
1959
|
+
};
|
|
1960
|
+
};
|
|
1961
|
+
var rollbackSaga = async (params) => {
|
|
1962
|
+
const {
|
|
1963
|
+
workflowId,
|
|
1964
|
+
failedStepId,
|
|
1965
|
+
originalError,
|
|
1966
|
+
completedSteps,
|
|
1967
|
+
input,
|
|
1968
|
+
runId,
|
|
1969
|
+
context,
|
|
1970
|
+
stepResults
|
|
1971
|
+
} = params;
|
|
1972
|
+
const compensatedSteps = [];
|
|
1973
|
+
const failedCompensations = [];
|
|
1974
|
+
for (let i = completedSteps.length - 1; i >= 0; i--) {
|
|
1975
|
+
const { step, result } = completedSteps[i];
|
|
1976
|
+
if (!step.compensate) {
|
|
1977
|
+
continue;
|
|
1978
|
+
}
|
|
1979
|
+
const stepCtx = createStepContext({
|
|
1980
|
+
workflowId,
|
|
1981
|
+
stepId: step.id,
|
|
1982
|
+
runId,
|
|
1983
|
+
context,
|
|
1984
|
+
stepResults
|
|
1985
|
+
});
|
|
1986
|
+
try {
|
|
1987
|
+
await step.compensate(result, input, stepCtx);
|
|
1988
|
+
compensatedSteps.push(step.id);
|
|
1989
|
+
if (context?.storage) {
|
|
1990
|
+
await context.storage.updateStepStatus(workflowId, step.id, "FAILED", {
|
|
1991
|
+
metadata: { compensated: true }
|
|
1992
|
+
});
|
|
1993
|
+
}
|
|
1994
|
+
} catch (compensationError) {
|
|
1995
|
+
failedCompensations.push({ stepId: step.id, error: compensationError });
|
|
1996
|
+
}
|
|
1997
|
+
}
|
|
1998
|
+
throw new WorkflowSagaRollbackError({
|
|
1999
|
+
workflowId,
|
|
2000
|
+
failedStepId,
|
|
2001
|
+
originalError,
|
|
2002
|
+
compensatedSteps,
|
|
2003
|
+
failedCompensations
|
|
2004
|
+
});
|
|
2005
|
+
};
|
|
2006
|
+
var executeWorkflow = async (config, rawInput, context) => {
|
|
2007
|
+
const input = validateInput(config, rawInput);
|
|
2008
|
+
const runId = context?.runId ?? generateRunId(config.id);
|
|
2009
|
+
const stepResults = {};
|
|
2010
|
+
const completedSteps = [];
|
|
2011
|
+
const handleAbort = async (stepId, signal) => {
|
|
2012
|
+
stepResults[stepId] = {
|
|
2013
|
+
aborted: true,
|
|
2014
|
+
reason: signal.reason,
|
|
2015
|
+
payload: signal.payload
|
|
2016
|
+
};
|
|
2017
|
+
if (context?.storage) {
|
|
2018
|
+
await context.storage.updateStepStatus(config.id, stepId, "ABORTED", {
|
|
2019
|
+
result: signal.payload,
|
|
2020
|
+
metadata: { abortReason: signal.reason }
|
|
2021
|
+
});
|
|
2022
|
+
}
|
|
2023
|
+
const abortOutput = signal.payload ?? {
|
|
2024
|
+
aborted: true,
|
|
2025
|
+
reason: signal.reason
|
|
2026
|
+
};
|
|
2027
|
+
return {
|
|
2028
|
+
workflowId: config.id,
|
|
2029
|
+
runId,
|
|
2030
|
+
status: "ABORTED",
|
|
2031
|
+
stepResults,
|
|
2032
|
+
abortReason: signal.reason,
|
|
2033
|
+
abortPayload: signal.payload,
|
|
2034
|
+
output: abortOutput
|
|
2035
|
+
};
|
|
2036
|
+
};
|
|
2037
|
+
for (const step of config.steps) {
|
|
2038
|
+
const stepCtx = createStepContext({
|
|
2039
|
+
workflowId: config.id,
|
|
2040
|
+
stepId: step.id,
|
|
2041
|
+
runId,
|
|
2042
|
+
context,
|
|
2043
|
+
stepResults
|
|
2044
|
+
});
|
|
2045
|
+
try {
|
|
2046
|
+
const result = await step.execute(input, stepCtx);
|
|
2047
|
+
if (isWorkflowAbortSignal(result)) {
|
|
2048
|
+
return await handleAbort(step.id, result);
|
|
2049
|
+
}
|
|
2050
|
+
stepResults[step.id] = result;
|
|
2051
|
+
completedSteps.push({ step, result });
|
|
2052
|
+
if (context?.storage) {
|
|
2053
|
+
await context.storage.updateStepStatus(config.id, step.id, "COMPLETED", { result });
|
|
2054
|
+
}
|
|
2055
|
+
} catch (error) {
|
|
2056
|
+
if (error instanceof StepSuspendedError) {
|
|
2057
|
+
return {
|
|
2058
|
+
workflowId: config.id,
|
|
2059
|
+
runId,
|
|
2060
|
+
status: "WAITING_APPROVAL",
|
|
2061
|
+
stepResults
|
|
2062
|
+
};
|
|
2063
|
+
}
|
|
2064
|
+
if (isWorkflowAbortSignal(error)) {
|
|
2065
|
+
return await handleAbort(step.id, error);
|
|
2066
|
+
}
|
|
2067
|
+
await rollbackSaga({
|
|
2068
|
+
workflowId: config.id,
|
|
2069
|
+
failedStepId: step.id,
|
|
2070
|
+
originalError: error,
|
|
2071
|
+
completedSteps,
|
|
2072
|
+
input,
|
|
2073
|
+
runId,
|
|
2074
|
+
context,
|
|
2075
|
+
stepResults
|
|
2076
|
+
});
|
|
2077
|
+
}
|
|
2078
|
+
}
|
|
2079
|
+
const finalOutput = config.outputDto ? config.outputDto(stepResults, input) : stepResults;
|
|
2080
|
+
return {
|
|
2081
|
+
workflowId: config.id,
|
|
2082
|
+
runId,
|
|
2083
|
+
status: "COMPLETED",
|
|
2084
|
+
stepResults,
|
|
2085
|
+
output: finalOutput
|
|
2086
|
+
};
|
|
2087
|
+
};
|
|
2088
|
+
|
|
2089
|
+
// src/workflow/define-workflow.ts
|
|
2090
|
+
var resolveWorkflowImpact = (config, options) => {
|
|
2091
|
+
if (options?.impact) {
|
|
2092
|
+
return options.impact;
|
|
2093
|
+
}
|
|
2094
|
+
return config.impact ?? "MUTATIVE";
|
|
2095
|
+
};
|
|
2096
|
+
var resolveRequireApproval = (impact, options) => {
|
|
2097
|
+
if (options?.requireApproval !== void 0) {
|
|
2098
|
+
return options.requireApproval;
|
|
2099
|
+
}
|
|
2100
|
+
return impact === "DESTRUCTIVE";
|
|
2101
|
+
};
|
|
2102
|
+
var buildToolExecutionContext = (options, toolCtx) => {
|
|
2103
|
+
const tenantId = typeof toolCtx?.tenantId === "string" ? toolCtx.tenantId : options?.defaultContext?.tenantId;
|
|
2104
|
+
const userId = typeof toolCtx?.userId === "string" ? toolCtx.userId : options?.defaultContext?.userId;
|
|
2105
|
+
return {
|
|
2106
|
+
tenantId,
|
|
2107
|
+
userId,
|
|
2108
|
+
services: options?.defaultContext?.services ?? {},
|
|
2109
|
+
storage: options?.storage ?? options?.defaultContext?.storage
|
|
2110
|
+
};
|
|
2111
|
+
};
|
|
2112
|
+
var defineWorkflow = (config) => {
|
|
2113
|
+
const workflowImpact = config.impact ?? "MUTATIVE";
|
|
2114
|
+
return {
|
|
2115
|
+
id: config.id,
|
|
2116
|
+
name: config.name,
|
|
2117
|
+
description: config.description,
|
|
2118
|
+
impact: workflowImpact,
|
|
2119
|
+
roles: config.roles,
|
|
2120
|
+
config,
|
|
2121
|
+
execute: async (input, context) => {
|
|
2122
|
+
return await executeWorkflow(config, input, context);
|
|
2123
|
+
},
|
|
2124
|
+
asTool: (options) => {
|
|
2125
|
+
const impact = resolveWorkflowImpact(config, options);
|
|
2126
|
+
const requireApproval = resolveRequireApproval(impact, options);
|
|
2127
|
+
const tool = createIsolatedTool({
|
|
2128
|
+
name: config.id,
|
|
2129
|
+
description: config.description ?? config.name,
|
|
2130
|
+
roles: config.roles,
|
|
2131
|
+
impact,
|
|
2132
|
+
requireApproval,
|
|
2133
|
+
parameters: config.inputSchema,
|
|
2134
|
+
invalidationTags: typeof config.invalidationTags === "function" ? async (args, res) => {
|
|
2135
|
+
const resolver = config.invalidationTags;
|
|
2136
|
+
return await resolver(args, res ?? {});
|
|
2137
|
+
} : config.invalidationTags,
|
|
2138
|
+
execute: async (args, toolCtx) => {
|
|
2139
|
+
const executionContext = buildToolExecutionContext(options, toolCtx);
|
|
2140
|
+
const result = await executeWorkflow(config, args, executionContext);
|
|
2141
|
+
return result.output;
|
|
2142
|
+
},
|
|
2143
|
+
llmDto: (result) => result
|
|
2144
|
+
});
|
|
2145
|
+
Object.assign(tool, {
|
|
2146
|
+
_isWorkflow: true,
|
|
2147
|
+
workflowId: config.id,
|
|
2148
|
+
workflowConfig: {
|
|
2149
|
+
totalSteps: config.steps.length,
|
|
2150
|
+
impact
|
|
2151
|
+
}
|
|
2152
|
+
});
|
|
2153
|
+
return tool;
|
|
2154
|
+
}
|
|
2155
|
+
};
|
|
2156
|
+
};
|
|
1632
2157
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1633
2158
|
0 && (module.exports = {
|
|
1634
2159
|
AvantGateBudgetExceededError,
|
|
@@ -1644,12 +2169,18 @@ var PromptRegistry = class {
|
|
|
1644
2169
|
PromptRegistry,
|
|
1645
2170
|
PromptTemplate,
|
|
1646
2171
|
SEED_MODEL_PRICES,
|
|
2172
|
+
WorkflowAbortSignal,
|
|
2173
|
+
WorkflowSagaRollbackError,
|
|
2174
|
+
WorkflowValidationError,
|
|
1647
2175
|
ZenLLMControlLayer,
|
|
1648
2176
|
calculateCostUSD,
|
|
1649
2177
|
createAvantGate,
|
|
1650
2178
|
createHttpProviderClient,
|
|
1651
2179
|
createLLMControlLayer,
|
|
2180
|
+
defineWorkflow,
|
|
2181
|
+
executeWorkflow,
|
|
1652
2182
|
extractAndCleanJSON,
|
|
2183
|
+
isWorkflowAbortSignal,
|
|
1653
2184
|
resolveModelPrice,
|
|
1654
2185
|
resolveModelPriceAsync,
|
|
1655
2186
|
sanitizePII,
|
package/dist/index.mjs
CHANGED
|
@@ -1,10 +1,18 @@
|
|
|
1
|
-
import {
|
|
2
|
-
sanitizePII
|
|
3
|
-
} from "./chunk-DVCF4CSV.mjs";
|
|
4
1
|
import {
|
|
5
2
|
extractAndCleanJSON,
|
|
6
3
|
validateWithZod
|
|
7
4
|
} from "./chunk-CO26LNFD.mjs";
|
|
5
|
+
import {
|
|
6
|
+
WorkflowAbortSignal,
|
|
7
|
+
WorkflowSagaRollbackError,
|
|
8
|
+
WorkflowValidationError,
|
|
9
|
+
defineWorkflow,
|
|
10
|
+
executeWorkflow,
|
|
11
|
+
isWorkflowAbortSignal
|
|
12
|
+
} from "./chunk-4XWO3NZW.mjs";
|
|
13
|
+
import {
|
|
14
|
+
sanitizePII
|
|
15
|
+
} from "./chunk-5VA3EKPJ.mjs";
|
|
8
16
|
|
|
9
17
|
// src/types.ts
|
|
10
18
|
var ConfigurationError = class extends Error {
|
|
@@ -1043,12 +1051,18 @@ export {
|
|
|
1043
1051
|
PromptRegistry,
|
|
1044
1052
|
PromptTemplate,
|
|
1045
1053
|
SEED_MODEL_PRICES,
|
|
1054
|
+
WorkflowAbortSignal,
|
|
1055
|
+
WorkflowSagaRollbackError,
|
|
1056
|
+
WorkflowValidationError,
|
|
1046
1057
|
AvantGateControlLayer as ZenLLMControlLayer,
|
|
1047
1058
|
calculateCostUSD,
|
|
1048
1059
|
createAvantGate,
|
|
1049
1060
|
createHttpProviderClient,
|
|
1050
1061
|
createLLMControlLayer,
|
|
1062
|
+
defineWorkflow,
|
|
1063
|
+
executeWorkflow,
|
|
1051
1064
|
extractAndCleanJSON,
|
|
1065
|
+
isWorkflowAbortSignal,
|
|
1052
1066
|
resolveModelPrice,
|
|
1053
1067
|
resolveModelPriceAsync,
|
|
1054
1068
|
sanitizePII,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"define-workflow.d.ts","sourceRoot":"","sources":["../../src/workflow/define-workflow.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAEV,cAAc,EAGd,gBAAgB,EACjB,MAAM,SAAS,CAAC;AAmCjB,eAAO,MAAM,cAAc,GAAI,MAAM,GAAG,GAAG,EAAE,OAAO,GAAG,GAAG,EACxD,QAAQ,cAAc,CAAC,MAAM,EAAE,OAAO,CAAC,KACtC,gBAAgB,CAAC,MAAM,EAAE,OAAO,CA8DlC,CAAA"}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type { WorkflowConfig, WorkflowExecutionContext, WorkflowExecutionResult } from "./types";
|
|
2
|
+
export declare const executeWorkflow: <TInput, TOutput>(config: WorkflowConfig<TInput, TOutput>, rawInput: TInput, context?: WorkflowExecutionContext) => Promise<WorkflowExecutionResult<TOutput>>;
|
|
3
|
+
//# sourceMappingURL=engine.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../../src/workflow/engine.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EACV,cAAc,EACd,wBAAwB,EACxB,uBAAuB,EAGxB,MAAM,SAAS,CAAC;AAyHjB,eAAO,MAAM,eAAe,GAAU,MAAM,EAAE,OAAO,EACnD,QAAQ,cAAc,CAAC,MAAM,EAAE,OAAO,CAAC,EACvC,UAAU,MAAM,EAChB,UAAU,wBAAwB,KACjC,OAAO,CAAC,uBAAuB,CAAC,OAAO,CAAC,CAmG1C,CAAA"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
export interface FailedCompensationRecord {
|
|
2
|
+
stepId: string;
|
|
3
|
+
error: unknown;
|
|
4
|
+
}
|
|
5
|
+
export declare class WorkflowSagaRollbackError extends Error {
|
|
6
|
+
readonly workflowId: string;
|
|
7
|
+
readonly failedStepId: string;
|
|
8
|
+
readonly originalError: unknown;
|
|
9
|
+
readonly compensatedSteps: string[];
|
|
10
|
+
readonly failedCompensations: FailedCompensationRecord[];
|
|
11
|
+
constructor(params: {
|
|
12
|
+
workflowId: string;
|
|
13
|
+
failedStepId: string;
|
|
14
|
+
originalError: unknown;
|
|
15
|
+
compensatedSteps: string[];
|
|
16
|
+
failedCompensations?: FailedCompensationRecord[];
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
export declare class WorkflowValidationError extends Error {
|
|
20
|
+
readonly workflowId: string;
|
|
21
|
+
readonly issues: unknown[];
|
|
22
|
+
constructor(workflowId: string, issues: unknown[]);
|
|
23
|
+
}
|
|
24
|
+
export declare class WorkflowAbortSignal<TPayload = unknown> extends Error {
|
|
25
|
+
readonly __isWorkflowAbort = true;
|
|
26
|
+
readonly reason: string;
|
|
27
|
+
readonly payload?: TPayload;
|
|
28
|
+
constructor(reason: string, payload?: TPayload);
|
|
29
|
+
}
|
|
30
|
+
export declare const isWorkflowAbortSignal: (value: unknown) => value is WorkflowAbortSignal;
|
|
31
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/workflow/errors.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,wBAAwB;IACvC,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,OAAO,CAAC;CAChB;AAED,qBAAa,yBAA0B,SAAQ,KAAK;IAClD,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAC;IAChC,QAAQ,CAAC,gBAAgB,EAAE,MAAM,EAAE,CAAC;IACpC,QAAQ,CAAC,mBAAmB,EAAE,wBAAwB,EAAE,CAAC;gBAE7C,MAAM,EAAE;QAClB,UAAU,EAAE,MAAM,CAAC;QACnB,YAAY,EAAE,MAAM,CAAC;QACrB,aAAa,EAAE,OAAO,CAAC;QACvB,gBAAgB,EAAE,MAAM,EAAE,CAAC;QAC3B,mBAAmB,CAAC,EAAE,wBAAwB,EAAE,CAAC;KAClD;CAiBF;AAED,qBAAa,uBAAwB,SAAQ,KAAK;IAChD,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC;gBAEf,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE;CAMlD;AAED,qBAAa,mBAAmB,CAAC,QAAQ,GAAG,OAAO,CAAE,SAAQ,KAAK;IAChE,QAAQ,CAAC,iBAAiB,QAAQ;IAClC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,OAAO,CAAC,EAAE,QAAQ,CAAC;gBAEhB,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,QAAQ;CAM/C;AAED,eAAO,MAAM,qBAAqB,GAAI,OAAO,OAAO,KAAG,KAAK,IAAI,mBAM/D,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { defineWorkflow } from "./define-workflow";
|
|
2
|
+
export { executeWorkflow } from "./engine";
|
|
3
|
+
export { WorkflowSagaRollbackError, WorkflowValidationError, WorkflowAbortSignal, isWorkflowAbortSignal, type FailedCompensationRecord, } from "./errors";
|
|
4
|
+
export type { WorkflowAsToolOptions, WorkflowConfig, WorkflowExecutionContext, WorkflowExecutionResult, WorkflowInstance, WorkflowStepConfig, WorkflowStepContext, } from "./types";
|
|
5
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/workflow/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAC3C,OAAO,EACL,yBAAyB,EACzB,uBAAuB,EACvB,mBAAmB,EACnB,qBAAqB,EACrB,KAAK,wBAAwB,GAC9B,MAAM,UAAU,CAAC;AAClB,YAAY,EACV,qBAAqB,EACrB,cAAc,EACd,wBAAwB,EACxB,uBAAuB,EACvB,gBAAgB,EAChB,kBAAkB,EAClB,mBAAmB,GACpB,MAAM,SAAS,CAAC"}
|