@agentguard-run/spend 0.4.4 → 0.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.
Files changed (37) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/README.md +23 -0
  3. package/dist/index.d.ts +9 -1
  4. package/dist/index.d.ts.map +1 -1
  5. package/dist/index.js +19 -3
  6. package/dist/index.js.map +1 -1
  7. package/dist/workflow/chain-validator.d.ts +4 -0
  8. package/dist/workflow/chain-validator.d.ts.map +1 -0
  9. package/dist/workflow/chain-validator.js +37 -0
  10. package/dist/workflow/chain-validator.js.map +1 -0
  11. package/dist/workflow/context.d.ts +46 -0
  12. package/dist/workflow/context.d.ts.map +1 -0
  13. package/dist/workflow/context.js +360 -0
  14. package/dist/workflow/context.js.map +1 -0
  15. package/dist/workflow/errors.d.ts +43 -0
  16. package/dist/workflow/errors.d.ts.map +1 -0
  17. package/dist/workflow/errors.js +40 -0
  18. package/dist/workflow/errors.js.map +1 -0
  19. package/dist/workflow/index.d.ts +6 -0
  20. package/dist/workflow/index.d.ts.map +1 -0
  21. package/dist/workflow/index.js +20 -0
  22. package/dist/workflow/index.js.map +1 -0
  23. package/dist/workflow/receipt.d.ts +23 -0
  24. package/dist/workflow/receipt.d.ts.map +1 -0
  25. package/dist/workflow/receipt.js +60 -0
  26. package/dist/workflow/receipt.js.map +1 -0
  27. package/dist/workflow/types.d.ts +74 -0
  28. package/dist/workflow/types.d.ts.map +1 -0
  29. package/dist/workflow/types.js +3 -0
  30. package/dist/workflow/types.js.map +1 -0
  31. package/package.json +10 -3
  32. package/src/workflow/chain-validator.ts +35 -0
  33. package/src/workflow/context.ts +418 -0
  34. package/src/workflow/errors.ts +27 -0
  35. package/src/workflow/index.ts +18 -0
  36. package/src/workflow/receipt.ts +73 -0
  37. package/src/workflow/types.ts +88 -0
package/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.5.0
4
+
5
+ - Added the workflow primitive: one budget envelope, one duration cap, resumable checkpoints, and signed receipt chains across multi-step agent runs.
6
+ - Added receipt schema v2 fields for workflow_id, parent_receipt_id, chain_validation_hash, checkpoints, and reviewer cascade evidence.
7
+ - Added SDK chain validation helpers and workflow-specific error types.
8
+
3
9
  ## 0.4.4
4
10
 
5
11
  - Added the functional-use disclaimer to README, package metadata, LICENSE addendum, CLI first-run notice, and /llms.txt surfaces.
package/README.md CHANGED
@@ -87,6 +87,29 @@ const response = await guardedClient.chat.completions.create({
87
87
  Then run your agent. AgentGuard decides locally before any provider call starts, signs the receipt, and applies allow, downgrade, shadow, or block.
88
88
 
89
89
 
90
+
91
+ ## Workflow-level caps
92
+
93
+ Use `agentguard.workflow()` when one agent run spans many outcomes and needs one shared budget envelope. The SDK signs each step as receipt schema v2, writes checkpoints, and validates the prior chain before resume.
94
+
95
+ ```ts
96
+ import { agentguard } from '@agentguard-run/spend';
97
+
98
+ await agentguard.workflow({
99
+ name: 'migrate_legacy_payments',
100
+ budget_cap_usd: 500,
101
+ duration_cap_hours: 72,
102
+ checkpoint_every_outcomes: 50,
103
+ resume_if_exists: true,
104
+ }, async (workflow) => {
105
+ for (const record of records) {
106
+ await workflow.outcome('migrate_payment', () => migratePayment(record));
107
+ }
108
+ });
109
+ ```
110
+
111
+ Share the public replay URL at `https://agentguard.run/verify/workflow/<workflow_id>`.
112
+
90
113
  ## Need help configuring? Run `agentguard advisor`
91
114
 
92
115
  `agentguard advisor` uses your OpenRouter key, or any OpenAI-compatible endpoint you pass with `--base-url`, to run a local setup dialogue in your terminal. AgentGuard infrastructure never sees the prompts, completions, keys, policy details, or session log.
package/dist/index.d.ts CHANGED
@@ -5,6 +5,7 @@
5
5
  * (App. Nos. 63/983,615; 63/983,621; 63/983,843; 63/984,626;
6
6
  * 64/071,781; 64/071,789).
7
7
  */
8
+ import { workflow as runWorkflow } from './workflow/context';
8
9
  export type { SpendAction, SpendWindow, Provider, EnforcementMode, CapabilityTier, SpendCap, SpendScope, SpendPolicy, CallContext, SpendDecision, SignedDecisionLogEntry, SpendStore, DecisionLogStore, } from './types';
9
10
  export { getModelCost, setCostOverride, clearCostOverrides, computeCallCents, inferProvider, listCostOverrides, loadPersistedCostOverrides, persistCostOverrides, knownModelCosts, type ModelCost, } from './cost-table';
10
11
  export { evaluatePolicy, buildScopeKey, adjustPolicyWindowSpend, enforcePolicyLicenseGates, findCustomKeywordWatchlists, BUILT_IN_KEYWORD_WATCHLISTS } from './policy';
@@ -13,6 +14,10 @@ export { InMemorySpendStore } from './store-memory';
13
14
  export { AgentGuardLicenseRequiredError, validateLicenseKey, validateAndRegisterLicense, readConfiguredLicenseKey, writeConfiguredLicenseKey, clearConfiguredLicenseKey, licenseKeyFingerprint, type AgentGuardLicenseStatus, type AgentGuardLicenseFeatures, type AgentGuardTier, } from './license';
14
15
  export { telemetryStatus, enableTelemetry, disableTelemetry, resetTelemetryInstallId, recordTelemetryEvent, type TelemetryStatus, } from './telemetry';
15
16
  export { fetchCatalog, getCachedCatalog, syncPricingIntoCostTable, persistOverrides, modelCostFromOpenRouter, type OpenRouterCatalog, type OpenRouterModel, type SyncPricingResult, } from './openrouter-catalog';
17
+ export { workflow, WorkflowContext } from './workflow/context';
18
+ export { computeChainHash, validateReceiptChain } from './workflow/chain-validator';
19
+ export { AgentGuardBudgetCapError, AgentGuardChainCorruptError, AgentGuardDurationCapError, AgentGuardWorkflowStateError, } from './workflow/errors';
20
+ export type { ChainValidationResult, CheckpointReceipt, ReceiptV2, ReviewerCascadeEvidence, WorkflowConfig, WorkflowState, WorkflowStatus, } from './workflow/types';
16
21
  export { AdvisorConversation, buildBusinessProfile, buildPolicyFromProfile, projectedSavings, type AdvisorBusinessProfile, type ProjectedSavings, } from './advisor/conversation';
17
22
  export { createAdvisorClient, resolveAdvisorApiKey, type AdvisorClient, type AdvisorProvider } from './advisor/llm-client';
18
23
  export { createAdvisorSessionLogger, writeAdvisorOutputs, type AdvisorOutputs } from './advisor/output';
@@ -20,7 +25,10 @@ export { SpendGuard, withSpendGuard, AgentGuardBlockedError, type SpendGuardConf
20
25
  export { withSpendGuardAnthropic, type AnthropicBindingOptions } from './bindings/anthropic';
21
26
  export { withSpendGuardBedrock, type BedrockBindingOptions } from './bindings/bedrock';
22
27
  export { DEFAULT_LOCALE, SUPPORTED_LOCALES, TRANSLATIONS, type SupportedLocale, resolveLocale, t, formatBlockedTrace, type BlockedTraceArgs, } from './i18n';
23
- export declare const AGENTGUARD_SPEND_VERSION = "0.4.4";
28
+ export declare const AGENTGUARD_SPEND_VERSION = "0.5.0";
29
+ export declare const agentguard: {
30
+ workflow: typeof runWorkflow;
31
+ };
24
32
  /** Patent marking. 35 U.S.C. § 287 constructive notice. */
25
33
  export declare const PATENT_NOTICE: string;
26
34
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAKH,YAAY,EACV,WAAW,EACX,WAAW,EACX,QAAQ,EACR,eAAe,EACf,cAAc,EACd,QAAQ,EACR,UAAU,EACV,WAAW,EACX,WAAW,EACX,aAAa,EACb,sBAAsB,EACtB,UAAU,EACV,gBAAgB,GACjB,MAAM,SAAS,CAAC;AAGjB,OAAO,EACL,YAAY,EACZ,eAAe,EACf,kBAAkB,EAClB,gBAAgB,EAChB,aAAa,EACb,iBAAiB,EACjB,0BAA0B,EAC1B,oBAAoB,EACpB,eAAe,EACf,KAAK,SAAS,GACf,MAAM,cAAc,CAAC;AAGtB,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,uBAAuB,EAAE,yBAAyB,EAAE,2BAA2B,EAAE,2BAA2B,EAAE,MAAM,UAAU,CAAC;AAGvK,OAAO,EACL,aAAa,EACb,SAAS,EACT,gBAAgB,EAChB,wBAAwB,EACxB,YAAY,EACZ,WAAW,EACX,WAAW,EACX,qBAAqB,EACrB,wBAAwB,GACzB,MAAM,gBAAgB,CAAC;AAGxB,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAGpD,OAAO,EACL,8BAA8B,EAC9B,kBAAkB,EAClB,0BAA0B,EAC1B,wBAAwB,EACxB,yBAAyB,EACzB,yBAAyB,EACzB,qBAAqB,EACrB,KAAK,uBAAuB,EAC5B,KAAK,yBAAyB,EAC9B,KAAK,cAAc,GACpB,MAAM,WAAW,CAAC;AAGnB,OAAO,EACL,eAAe,EACf,eAAe,EACf,gBAAgB,EAChB,uBAAuB,EACvB,oBAAoB,EACpB,KAAK,eAAe,GACrB,MAAM,aAAa,CAAC;AAGrB,OAAO,EACL,YAAY,EACZ,gBAAgB,EAChB,wBAAwB,EACxB,gBAAgB,EAChB,uBAAuB,EACvB,KAAK,iBAAiB,EACtB,KAAK,eAAe,EACpB,KAAK,iBAAiB,GACvB,MAAM,sBAAsB,CAAC;AAI9B,OAAO,EACL,mBAAmB,EACnB,oBAAoB,EACpB,sBAAsB,EACtB,gBAAgB,EAChB,KAAK,sBAAsB,EAC3B,KAAK,gBAAgB,GACtB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,KAAK,aAAa,EAAE,KAAK,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAC3H,OAAO,EAAE,0BAA0B,EAAE,mBAAmB,EAAE,KAAK,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAGxG,OAAO,EACL,UAAU,EACV,cAAc,EACd,sBAAsB,EACtB,KAAK,gBAAgB,EACrB,KAAK,oBAAoB,EACzB,KAAK,uBAAuB,EAC5B,KAAK,sBAAsB,GAC5B,MAAM,eAAe,CAAC;AAEvB,OAAO,EAAE,uBAAuB,EAAE,KAAK,uBAAuB,EAAE,MAAM,sBAAsB,CAAC;AAC7F,OAAO,EAAE,qBAAqB,EAAE,KAAK,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAGvF,OAAO,EACL,cAAc,EACd,iBAAiB,EACjB,YAAY,EACZ,KAAK,eAAe,EACpB,aAAa,EACb,CAAC,EACD,kBAAkB,EAClB,KAAK,gBAAgB,GACtB,MAAM,QAAQ,CAAC;AAEhB,eAAO,MAAM,wBAAwB,UAAU,CAAC;AAEhD,2DAA2D;AAC3D,eAAO,MAAM,aAAa,QAG8B,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -7,9 +7,10 @@
7
7
  * 64/071,781; 64/071,789).
8
8
  */
9
9
  Object.defineProperty(exports, "__esModule", { value: true });
10
- exports.writeAdvisorOutputs = exports.createAdvisorSessionLogger = exports.resolveAdvisorApiKey = exports.createAdvisorClient = exports.projectedSavings = exports.buildPolicyFromProfile = exports.buildBusinessProfile = exports.AdvisorConversation = exports.modelCostFromOpenRouter = exports.persistOverrides = exports.syncPricingIntoCostTable = exports.getCachedCatalog = exports.fetchCatalog = exports.recordTelemetryEvent = exports.resetTelemetryInstallId = exports.disableTelemetry = exports.enableTelemetry = exports.telemetryStatus = exports.licenseKeyFingerprint = exports.clearConfiguredLicenseKey = exports.writeConfiguredLicenseKey = exports.readConfiguredLicenseKey = exports.validateAndRegisterLicense = exports.validateLicenseKey = exports.AgentGuardLicenseRequiredError = exports.InMemorySpendStore = exports.InMemoryDecisionLogStore = exports.GENESIS_PREVIOUS_HASH = exports.verifyChain = exports.verifyEntry = exports.signDecision = exports.computeSignerFingerprint = exports.computeEntryHash = exports.sha256Hex = exports.canonicalJson = exports.BUILT_IN_KEYWORD_WATCHLISTS = exports.findCustomKeywordWatchlists = exports.enforcePolicyLicenseGates = exports.adjustPolicyWindowSpend = exports.buildScopeKey = exports.evaluatePolicy = exports.knownModelCosts = exports.persistCostOverrides = exports.loadPersistedCostOverrides = exports.listCostOverrides = exports.inferProvider = exports.computeCallCents = exports.clearCostOverrides = exports.setCostOverride = exports.getModelCost = void 0;
11
- exports.PATENT_NOTICE = exports.AGENTGUARD_SPEND_VERSION = exports.formatBlockedTrace = exports.t = exports.resolveLocale = exports.TRANSLATIONS = exports.SUPPORTED_LOCALES = exports.DEFAULT_LOCALE = exports.withSpendGuardBedrock = exports.withSpendGuardAnthropic = exports.AgentGuardBlockedError = exports.withSpendGuard = exports.SpendGuard = void 0;
10
+ exports.AgentGuardWorkflowStateError = exports.AgentGuardDurationCapError = exports.AgentGuardChainCorruptError = exports.AgentGuardBudgetCapError = exports.validateReceiptChain = exports.computeChainHash = exports.WorkflowContext = exports.workflow = exports.modelCostFromOpenRouter = exports.persistOverrides = exports.syncPricingIntoCostTable = exports.getCachedCatalog = exports.fetchCatalog = exports.recordTelemetryEvent = exports.resetTelemetryInstallId = exports.disableTelemetry = exports.enableTelemetry = exports.telemetryStatus = exports.licenseKeyFingerprint = exports.clearConfiguredLicenseKey = exports.writeConfiguredLicenseKey = exports.readConfiguredLicenseKey = exports.validateAndRegisterLicense = exports.validateLicenseKey = exports.AgentGuardLicenseRequiredError = exports.InMemorySpendStore = exports.InMemoryDecisionLogStore = exports.GENESIS_PREVIOUS_HASH = exports.verifyChain = exports.verifyEntry = exports.signDecision = exports.computeSignerFingerprint = exports.computeEntryHash = exports.sha256Hex = exports.canonicalJson = exports.BUILT_IN_KEYWORD_WATCHLISTS = exports.findCustomKeywordWatchlists = exports.enforcePolicyLicenseGates = exports.adjustPolicyWindowSpend = exports.buildScopeKey = exports.evaluatePolicy = exports.knownModelCosts = exports.persistCostOverrides = exports.loadPersistedCostOverrides = exports.listCostOverrides = exports.inferProvider = exports.computeCallCents = exports.clearCostOverrides = exports.setCostOverride = exports.getModelCost = void 0;
11
+ exports.PATENT_NOTICE = exports.agentguard = exports.AGENTGUARD_SPEND_VERSION = exports.formatBlockedTrace = exports.t = exports.resolveLocale = exports.TRANSLATIONS = exports.SUPPORTED_LOCALES = exports.DEFAULT_LOCALE = exports.withSpendGuardBedrock = exports.withSpendGuardAnthropic = exports.AgentGuardBlockedError = exports.withSpendGuard = exports.SpendGuard = exports.writeAdvisorOutputs = exports.createAdvisorSessionLogger = exports.resolveAdvisorApiKey = exports.createAdvisorClient = exports.projectedSavings = exports.buildPolicyFromProfile = exports.buildBusinessProfile = exports.AdvisorConversation = void 0;
12
12
  const telemetry_1 = require("./telemetry");
13
+ const context_1 = require("./workflow/context");
13
14
  // Cost table
14
15
  var cost_table_1 = require("./cost-table");
15
16
  Object.defineProperty(exports, "getModelCost", { enumerable: true, get: function () { return cost_table_1.getModelCost; } });
@@ -66,6 +67,18 @@ Object.defineProperty(exports, "getCachedCatalog", { enumerable: true, get: func
66
67
  Object.defineProperty(exports, "syncPricingIntoCostTable", { enumerable: true, get: function () { return openrouter_catalog_1.syncPricingIntoCostTable; } });
67
68
  Object.defineProperty(exports, "persistOverrides", { enumerable: true, get: function () { return openrouter_catalog_1.persistOverrides; } });
68
69
  Object.defineProperty(exports, "modelCostFromOpenRouter", { enumerable: true, get: function () { return openrouter_catalog_1.modelCostFromOpenRouter; } });
70
+ // Workflow primitive
71
+ var context_2 = require("./workflow/context");
72
+ Object.defineProperty(exports, "workflow", { enumerable: true, get: function () { return context_2.workflow; } });
73
+ Object.defineProperty(exports, "WorkflowContext", { enumerable: true, get: function () { return context_2.WorkflowContext; } });
74
+ var chain_validator_1 = require("./workflow/chain-validator");
75
+ Object.defineProperty(exports, "computeChainHash", { enumerable: true, get: function () { return chain_validator_1.computeChainHash; } });
76
+ Object.defineProperty(exports, "validateReceiptChain", { enumerable: true, get: function () { return chain_validator_1.validateReceiptChain; } });
77
+ var errors_1 = require("./workflow/errors");
78
+ Object.defineProperty(exports, "AgentGuardBudgetCapError", { enumerable: true, get: function () { return errors_1.AgentGuardBudgetCapError; } });
79
+ Object.defineProperty(exports, "AgentGuardChainCorruptError", { enumerable: true, get: function () { return errors_1.AgentGuardChainCorruptError; } });
80
+ Object.defineProperty(exports, "AgentGuardDurationCapError", { enumerable: true, get: function () { return errors_1.AgentGuardDurationCapError; } });
81
+ Object.defineProperty(exports, "AgentGuardWorkflowStateError", { enumerable: true, get: function () { return errors_1.AgentGuardWorkflowStateError; } });
69
82
  // Advisor local setup
70
83
  var conversation_1 = require("./advisor/conversation");
71
84
  Object.defineProperty(exports, "AdvisorConversation", { enumerable: true, get: function () { return conversation_1.AdvisorConversation; } });
@@ -95,7 +108,10 @@ Object.defineProperty(exports, "TRANSLATIONS", { enumerable: true, get: function
95
108
  Object.defineProperty(exports, "resolveLocale", { enumerable: true, get: function () { return i18n_1.resolveLocale; } });
96
109
  Object.defineProperty(exports, "t", { enumerable: true, get: function () { return i18n_1.t; } });
97
110
  Object.defineProperty(exports, "formatBlockedTrace", { enumerable: true, get: function () { return i18n_1.formatBlockedTrace; } });
98
- exports.AGENTGUARD_SPEND_VERSION = '0.4.4';
111
+ exports.AGENTGUARD_SPEND_VERSION = '0.5.0';
112
+ exports.agentguard = {
113
+ workflow: context_1.workflow,
114
+ };
99
115
  /** Patent marking. 35 U.S.C. § 287 constructive notice. */
100
116
  exports.PATENT_NOTICE = 'Protected by U.S. patent-pending technology ' +
101
117
  '(App. Nos. 63/983,615; 63/983,621; 63/983,843; 63/984,626; ' +
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA;;;;;;GAMG;;;;AAEH,2CAA8E;AAmB9E,aAAa;AACb,2CAWsB;AAVpB,0GAAA,YAAY,OAAA;AACZ,6GAAA,eAAe,OAAA;AACf,gHAAA,kBAAkB,OAAA;AAClB,8GAAA,gBAAgB,OAAA;AAChB,2GAAA,aAAa,OAAA;AACb,+GAAA,iBAAiB,OAAA;AACjB,wHAAA,0BAA0B,OAAA;AAC1B,kHAAA,oBAAoB,OAAA;AACpB,6GAAA,eAAe,OAAA;AAIjB,gBAAgB;AAChB,mCAAuK;AAA9J,wGAAA,cAAc,OAAA;AAAE,uGAAA,aAAa,OAAA;AAAE,iHAAA,uBAAuB,OAAA;AAAE,mHAAA,yBAAyB,OAAA;AAAE,qHAAA,2BAA2B,OAAA;AAAE,qHAAA,2BAA2B,OAAA;AAEpJ,eAAe;AACf,+CAUwB;AATtB,6GAAA,aAAa,OAAA;AACb,yGAAA,SAAS,OAAA;AACT,gHAAA,gBAAgB,OAAA;AAChB,wHAAA,wBAAwB,OAAA;AACxB,4GAAA,YAAY,OAAA;AACZ,2GAAA,WAAW,OAAA;AACX,2GAAA,WAAW,OAAA;AACX,qHAAA,qBAAqB,OAAA;AACrB,wHAAA,wBAAwB,OAAA;AAG1B,wBAAwB;AACxB,+CAAoD;AAA3C,kHAAA,kBAAkB,OAAA;AAE3B,mBAAmB;AACnB,qCAWmB;AAVjB,yHAAA,8BAA8B,OAAA;AAC9B,6GAAA,kBAAkB,OAAA;AAClB,qHAAA,0BAA0B,OAAA;AAC1B,mHAAA,wBAAwB,OAAA;AACxB,oHAAA,yBAAyB,OAAA;AACzB,oHAAA,yBAAyB,OAAA;AACzB,gHAAA,qBAAqB,OAAA;AAMvB,qBAAqB;AACrB,yCAOqB;AANnB,4GAAA,eAAe,OAAA;AACf,4GAAA,eAAe,OAAA;AACf,6GAAA,gBAAgB,OAAA;AAChB,oHAAA,uBAAuB,OAAA;AACvB,iHAAA,oBAAoB,OAAA;AAItB,qBAAqB;AACrB,2DAS8B;AAR5B,kHAAA,YAAY,OAAA;AACZ,sHAAA,gBAAgB,OAAA;AAChB,8HAAA,wBAAwB,OAAA;AACxB,sHAAA,gBAAgB,OAAA;AAChB,6HAAA,uBAAuB,OAAA;AAOzB,sBAAsB;AACtB,uDAOgC;AAN9B,mHAAA,mBAAmB,OAAA;AACnB,oHAAA,oBAAoB,OAAA;AACpB,sHAAA,sBAAsB,OAAA;AACtB,gHAAA,gBAAgB,OAAA;AAIlB,mDAA2H;AAAlH,iHAAA,mBAAmB,OAAA;AAAE,kHAAA,oBAAoB,OAAA;AAClD,2CAAwG;AAA/F,oHAAA,0BAA0B,OAAA;AAAE,6GAAA,mBAAmB,OAAA;AAExD,eAAe;AACf,6CAQuB;AAPrB,yGAAA,UAAU,OAAA;AACV,6GAAA,cAAc,OAAA;AACd,qHAAA,sBAAsB,OAAA;AAOxB,kDAA6F;AAApF,oHAAA,uBAAuB,OAAA;AAChC,8CAAuF;AAA9E,gHAAA,qBAAqB,OAAA;AAE9B,sCAAsC;AACtC,+BASgB;AARd,sGAAA,cAAc,OAAA;AACd,yGAAA,iBAAiB,OAAA;AACjB,oGAAA,YAAY,OAAA;AAEZ,qGAAA,aAAa,OAAA;AACb,yFAAA,CAAC,OAAA;AACD,0GAAA,kBAAkB,OAAA;AAIP,QAAA,wBAAwB,GAAG,OAAO,CAAC;AAEhD,2DAA2D;AAC9C,QAAA,aAAa,GACxB,8CAA8C;IAC9C,6DAA6D;IAC7D,sDAAsD,CAAC;AACzD,IAAA,gCAAuB,EAAC,UAAU,CAAC,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import type { ChainValidationResult, ReceiptV2 } from './types';
2
+ export declare function validateReceiptChain(receipts: ReceiptV2[]): Promise<ChainValidationResult>;
3
+ export declare function computeChainHash(receipt: ReceiptV2): Promise<string>;
4
+ //# sourceMappingURL=chain-validator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chain-validator.d.ts","sourceRoot":"","sources":["../../src/workflow/chain-validator.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,qBAAqB,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAEhE,wBAAsB,oBAAoB,CAAC,QAAQ,EAAE,SAAS,EAAE,GAAG,OAAO,CAAC,qBAAqB,CAAC,CAoBhG;AAED,wBAAsB,gBAAgB,CAAC,OAAO,EAAE,SAAS,GAAG,OAAO,CAAC,MAAM,CAAC,CAS1E"}
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.validateReceiptChain = validateReceiptChain;
4
+ exports.computeChainHash = computeChainHash;
5
+ const receipt_1 = require("./receipt");
6
+ async function validateReceiptChain(receipts) {
7
+ if (receipts.length === 0)
8
+ return { ok: true };
9
+ for (let i = 0; i < receipts.length; i++) {
10
+ if (!(0, receipt_1.verifyReceipt)(receipts[i])) {
11
+ return { ok: false, broken_at: i, reason: 'signature_invalid' };
12
+ }
13
+ if (i === 0)
14
+ continue;
15
+ const prev = receipts[i - 1];
16
+ const curr = receipts[i];
17
+ const expectedHash = await computeChainHash(prev);
18
+ if (curr.chain_validation_hash !== expectedHash) {
19
+ return { ok: false, broken_at: i, reason: 'chain_hash_mismatch' };
20
+ }
21
+ if (curr.parent_receipt_id !== prev.receipt_id) {
22
+ return { ok: false, broken_at: i, reason: 'parent_reference_mismatch' };
23
+ }
24
+ }
25
+ return { ok: true };
26
+ }
27
+ async function computeChainHash(receipt) {
28
+ const canonical = (0, receipt_1.canonicalJSONStringify)({
29
+ receipt_id: receipt.receipt_id,
30
+ workflow_id: receipt.workflow_id,
31
+ cost_usd: receipt.cost_usd,
32
+ signed_at: receipt.signed_at,
33
+ signature: receipt.signature,
34
+ });
35
+ return (0, receipt_1.sha256)(canonical);
36
+ }
37
+ //# sourceMappingURL=chain-validator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chain-validator.js","sourceRoot":"","sources":["../../src/workflow/chain-validator.ts"],"names":[],"mappings":";;AAGA,oDAoBC;AAED,4CASC;AAlCD,uCAA0E;AAGnE,KAAK,UAAU,oBAAoB,CAAC,QAAqB;IAC9D,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC;IAE/C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACzC,IAAI,CAAC,IAAA,uBAAa,EAAC,QAAQ,CAAC,CAAC,CAAE,CAAC,EAAE,CAAC;YACjC,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,EAAE,MAAM,EAAE,mBAAmB,EAAE,CAAC;QAClE,CAAC;QACD,IAAI,CAAC,KAAK,CAAC;YAAE,SAAS;QACtB,MAAM,IAAI,GAAG,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAE,CAAC;QAC9B,MAAM,IAAI,GAAG,QAAQ,CAAC,CAAC,CAAE,CAAC;QAC1B,MAAM,YAAY,GAAG,MAAM,gBAAgB,CAAC,IAAI,CAAC,CAAC;QAClD,IAAI,IAAI,CAAC,qBAAqB,KAAK,YAAY,EAAE,CAAC;YAChD,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,EAAE,MAAM,EAAE,qBAAqB,EAAE,CAAC;QACpE,CAAC;QACD,IAAI,IAAI,CAAC,iBAAiB,KAAK,IAAI,CAAC,UAAU,EAAE,CAAC;YAC/C,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,EAAE,MAAM,EAAE,2BAA2B,EAAE,CAAC;QAC1E,CAAC;IACH,CAAC;IAED,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC;AACtB,CAAC;AAEM,KAAK,UAAU,gBAAgB,CAAC,OAAkB;IACvD,MAAM,SAAS,GAAG,IAAA,gCAAsB,EAAC;QACvC,UAAU,EAAE,OAAO,CAAC,UAAU;QAC9B,WAAW,EAAE,OAAO,CAAC,WAAW;QAChC,QAAQ,EAAE,OAAO,CAAC,QAAQ;QAC1B,SAAS,EAAE,OAAO,CAAC,SAAS;QAC5B,SAAS,EAAE,OAAO,CAAC,SAAS;KAC7B,CAAC,CAAC;IACH,OAAO,IAAA,gBAAM,EAAC,SAAS,CAAC,CAAC;AAC3B,CAAC"}
@@ -0,0 +1,46 @@
1
+ import type { CheckpointReceipt, ReceiptV2, WorkflowConfig, WorkflowState, WorkflowStatus } from './types';
2
+ interface WorkflowCreateResponse {
3
+ workflow_id: string;
4
+ created_at: string;
5
+ state?: WorkflowState;
6
+ total_spend_usd?: number;
7
+ outcome_count?: number;
8
+ last_receipt_id?: string | null;
9
+ last_checkpoint_id?: string | null;
10
+ last_chain_hash?: string | null;
11
+ receipts?: ReceiptV2[];
12
+ }
13
+ export declare class WorkflowContext {
14
+ readonly workflow_id: string;
15
+ readonly user_id: string;
16
+ readonly config: WorkflowConfig;
17
+ readonly created_at: Date;
18
+ private _total_spend_usd;
19
+ private _outcome_count;
20
+ private _last_receipt_id;
21
+ private _last_checkpoint_id;
22
+ private _last_chain_hash;
23
+ private _state;
24
+ private readonly _receipts;
25
+ private constructor();
26
+ static create(config: WorkflowConfig): Promise<WorkflowContext>;
27
+ static fromCheckpoint(config: WorkflowConfig, existing: WorkflowCreateResponse, userId?: string): WorkflowContext;
28
+ outcome<T>(name: string, fn: () => Promise<T>): Promise<T>;
29
+ checkpoint(label?: string): Promise<CheckpointReceipt>;
30
+ cancel(reason: string): Promise<void>;
31
+ finalize(): Promise<void>;
32
+ status(): WorkflowStatus;
33
+ receipts(): ReceiptV2[];
34
+ private writeCheckpoint;
35
+ private writeFinalReceipt;
36
+ private assertActive;
37
+ private assertOutcomeAllowed;
38
+ private assertBudgetRemaining;
39
+ private assertDurationRemaining;
40
+ private checkPostCallCaps;
41
+ private extractOutcomeCost;
42
+ private postReceipt;
43
+ }
44
+ export declare function workflow<T>(config: WorkflowConfig, fn: (ctx: WorkflowContext) => Promise<T>): Promise<T>;
45
+ export {};
46
+ //# sourceMappingURL=context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/workflow/context.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,iBAAiB,EAAE,SAAS,EAAE,cAAc,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAE3G,UAAU,sBAAsB;IAC9B,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,kBAAkB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,QAAQ,CAAC,EAAE,SAAS,EAAE,CAAC;CACxB;AAED,qBAAa,eAAe;IAC1B,SAAgB,WAAW,EAAE,MAAM,CAAC;IACpC,SAAgB,OAAO,EAAE,MAAM,CAAC;IAChC,SAAgB,MAAM,EAAE,cAAc,CAAC;IACvC,SAAgB,UAAU,EAAE,IAAI,CAAC;IAEjC,OAAO,CAAC,gBAAgB,CAAK;IAC7B,OAAO,CAAC,cAAc,CAAK;IAC3B,OAAO,CAAC,gBAAgB,CAAuB;IAC/C,OAAO,CAAC,mBAAmB,CAAuB;IAClD,OAAO,CAAC,gBAAgB,CAAuB;IAC/C,OAAO,CAAC,MAAM,CAA2B;IACzC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAmB;IAE7C,OAAO;WA0BM,MAAM,CAAC,MAAM,EAAE,cAAc,GAAG,OAAO,CAAC,eAAe,CAAC;IA2CrE,MAAM,CAAC,cAAc,CAAC,MAAM,EAAE,cAAc,EAAE,QAAQ,EAAE,sBAAsB,EAAE,MAAM,SAAe,GAAG,eAAe;IAgBjH,OAAO,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAqC1D,UAAU,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,CAAC;IAItD,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAKrC,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAO/B,MAAM,IAAI,cAAc;IAoBxB,QAAQ,IAAI,SAAS,EAAE;YAIT,eAAe;YAuBf,iBAAiB;IAoB/B,OAAO,CAAC,YAAY;IAqBpB,OAAO,CAAC,oBAAoB;IAS5B,OAAO,CAAC,qBAAqB;IAU7B,OAAO,CAAC,uBAAuB;YAYjB,iBAAiB;IAY/B,OAAO,CAAC,kBAAkB;YAUZ,WAAW;CAK1B;AAED,wBAAsB,QAAQ,CAAC,CAAC,EAAE,MAAM,EAAE,cAAc,EAAE,EAAE,EAAE,CAAC,GAAG,EAAE,eAAe,KAAK,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAO9G"}
@@ -0,0 +1,360 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.WorkflowContext = void 0;
4
+ exports.workflow = workflow;
5
+ const crypto_1 = require("crypto");
6
+ const chain_validator_1 = require("./chain-validator");
7
+ const errors_1 = require("./errors");
8
+ const receipt_1 = require("./receipt");
9
+ class WorkflowContext {
10
+ workflow_id;
11
+ user_id;
12
+ config;
13
+ created_at;
14
+ _total_spend_usd = 0;
15
+ _outcome_count = 0;
16
+ _last_receipt_id = null;
17
+ _last_checkpoint_id = null;
18
+ _last_chain_hash = null;
19
+ _state = 'active';
20
+ _receipts = [];
21
+ constructor(args) {
22
+ this.workflow_id = args.workflow_id;
23
+ this.user_id = args.user_id;
24
+ this.config = args.config;
25
+ this.created_at = args.created_at;
26
+ this._state = args.state ?? 'active';
27
+ this._total_spend_usd = args.total_spend_usd ?? 0;
28
+ this._outcome_count = args.outcome_count ?? 0;
29
+ this._last_receipt_id = args.last_receipt_id ?? null;
30
+ this._last_checkpoint_id = args.last_checkpoint_id ?? null;
31
+ this._last_chain_hash = args.last_chain_hash ?? null;
32
+ this._receipts.push(...(args.receipts ?? []));
33
+ }
34
+ static async create(config) {
35
+ validateConfig(config);
36
+ const userId = String(config.metadata?.user_id || config.user_id || 'local-user');
37
+ if (config.resume_if_exists) {
38
+ const existing = await tryResume(config, userId);
39
+ if (existing)
40
+ return existing;
41
+ }
42
+ const apiBase = resolveApiBase(config);
43
+ if (apiBase) {
44
+ const body = {
45
+ name: config.name,
46
+ budget_cap_usd: config.budget_cap_usd,
47
+ duration_cap_hours: config.duration_cap_hours,
48
+ checkpoint_every_outcomes: config.checkpoint_every_outcomes ?? 25,
49
+ parent_outcomes: config.parent_outcomes,
50
+ metadata: config.metadata,
51
+ };
52
+ const created = await postJson(config, `${apiBase}/api/workflows/create`, body);
53
+ return new WorkflowContext({
54
+ workflow_id: created.workflow_id,
55
+ user_id: userId,
56
+ config,
57
+ created_at: new Date(created.created_at),
58
+ state: created.state,
59
+ total_spend_usd: created.total_spend_usd,
60
+ outcome_count: created.outcome_count,
61
+ last_receipt_id: created.last_receipt_id,
62
+ last_checkpoint_id: created.last_checkpoint_id,
63
+ last_chain_hash: created.last_chain_hash,
64
+ receipts: created.receipts,
65
+ });
66
+ }
67
+ return new WorkflowContext({
68
+ workflow_id: `ag_w_${(0, crypto_1.randomUUID)().replace(/-/g, '').slice(0, 16)}`,
69
+ user_id: userId,
70
+ config,
71
+ created_at: new Date(),
72
+ });
73
+ }
74
+ static fromCheckpoint(config, existing, userId = 'local-user') {
75
+ return new WorkflowContext({
76
+ workflow_id: existing.workflow_id,
77
+ user_id: userId,
78
+ config,
79
+ created_at: new Date(existing.created_at),
80
+ state: existing.state ?? 'active',
81
+ total_spend_usd: existing.total_spend_usd,
82
+ outcome_count: existing.outcome_count,
83
+ last_receipt_id: existing.last_receipt_id,
84
+ last_checkpoint_id: existing.last_checkpoint_id,
85
+ last_chain_hash: existing.last_chain_hash,
86
+ receipts: existing.receipts,
87
+ });
88
+ }
89
+ async outcome(name, fn) {
90
+ this.assertActive();
91
+ this.assertOutcomeAllowed(name);
92
+ this.assertBudgetRemaining();
93
+ this.assertDurationRemaining();
94
+ const result = await fn();
95
+ const cost = this.extractOutcomeCost(result);
96
+ const parentReceiptId = this._last_receipt_id;
97
+ const chainHash = this._receipts.length ? await (0, chain_validator_1.computeChainHash)(this._receipts[this._receipts.length - 1]) : null;
98
+ const receipt = (0, receipt_1.buildReceipt)({
99
+ workflow_id: this.workflow_id,
100
+ outcome_name: name,
101
+ user_id: this.user_id,
102
+ cost_usd: cost,
103
+ parent_receipt_id: parentReceiptId,
104
+ chain_validation_hash: chainHash,
105
+ workflow_checkpoint_idx: null,
106
+ workflow_total_spend_usd_to_date: this._total_spend_usd + cost,
107
+ reviewer_cascade: extractReviewerCascade(result),
108
+ });
109
+ this._receipts.push(receipt);
110
+ this._total_spend_usd = (0, receipt_1.roundUsd)(this._total_spend_usd + cost);
111
+ this._outcome_count += 1;
112
+ this._last_receipt_id = receipt.receipt_id;
113
+ this._last_chain_hash = await (0, chain_validator_1.computeChainHash)(receipt);
114
+ await this.postReceipt(receipt);
115
+ if (this._outcome_count % (this.config.checkpoint_every_outcomes ?? 25) === 0) {
116
+ await this.writeCheckpoint();
117
+ }
118
+ await this.checkPostCallCaps();
119
+ return result;
120
+ }
121
+ async checkpoint(label) {
122
+ return this.writeCheckpoint(label);
123
+ }
124
+ async cancel(reason) {
125
+ this._state = 'cancelled';
126
+ await this.writeFinalReceipt('cancelled', reason);
127
+ }
128
+ async finalize() {
129
+ if (this._state === 'active') {
130
+ this._state = 'completed';
131
+ await this.writeFinalReceipt('completed', 'workflow completed');
132
+ }
133
+ }
134
+ status() {
135
+ const elapsed = Date.now() - this.created_at.getTime();
136
+ const capMs = this.config.duration_cap_hours * 3_600_000;
137
+ return {
138
+ workflow_id: this.workflow_id,
139
+ state: this._state,
140
+ total_spend_usd: this._total_spend_usd,
141
+ budget_cap_usd: this.config.budget_cap_usd,
142
+ budget_remaining_usd: (0, receipt_1.roundUsd)(Math.max(0, this.config.budget_cap_usd - this._total_spend_usd)),
143
+ budget_pct_used: this.config.budget_cap_usd === 0 ? 1 : this._total_spend_usd / this.config.budget_cap_usd,
144
+ outcome_count: this._outcome_count,
145
+ last_receipt_id: this._last_receipt_id,
146
+ last_checkpoint_id: this._last_checkpoint_id,
147
+ last_chain_hash: this._last_chain_hash,
148
+ duration_elapsed_ms: elapsed,
149
+ duration_cap_ms: capMs,
150
+ duration_remaining_ms: Math.max(0, capMs - elapsed),
151
+ };
152
+ }
153
+ receipts() {
154
+ return [...this._receipts];
155
+ }
156
+ async writeCheckpoint(label) {
157
+ const chainHash = this._receipts.length ? await (0, chain_validator_1.computeChainHash)(this._receipts[this._receipts.length - 1]) : null;
158
+ const checkpoint = (0, receipt_1.buildReceipt)({
159
+ workflow_id: this.workflow_id,
160
+ outcome_name: 'CHECKPOINT',
161
+ user_id: this.user_id,
162
+ cost_usd: 0,
163
+ parent_receipt_id: this._last_receipt_id,
164
+ chain_validation_hash: chainHash,
165
+ workflow_checkpoint_idx: this._outcome_count,
166
+ workflow_total_spend_usd_to_date: this._total_spend_usd,
167
+ is_checkpoint: true,
168
+ checkpoint_label: label ?? null,
169
+ receipt_type: 'checkpoint',
170
+ });
171
+ this._receipts.push(checkpoint);
172
+ this._last_checkpoint_id = checkpoint.receipt_id;
173
+ this._last_receipt_id = checkpoint.receipt_id;
174
+ this._last_chain_hash = await (0, chain_validator_1.computeChainHash)(checkpoint);
175
+ await this.postReceipt(checkpoint);
176
+ return checkpoint;
177
+ }
178
+ async writeFinalReceipt(type, reason) {
179
+ const chainHash = this._receipts.length ? await (0, chain_validator_1.computeChainHash)(this._receipts[this._receipts.length - 1]) : null;
180
+ const receipt = (0, receipt_1.buildReceipt)({
181
+ workflow_id: this.workflow_id,
182
+ outcome_name: type === 'completed' ? 'WORKFLOW_COMPLETED' : 'WORKFLOW_STOPPED',
183
+ user_id: this.user_id,
184
+ cost_usd: 0,
185
+ parent_receipt_id: this._last_receipt_id,
186
+ chain_validation_hash: chainHash,
187
+ workflow_checkpoint_idx: this._outcome_count,
188
+ workflow_total_spend_usd_to_date: this._total_spend_usd,
189
+ receipt_type: type === 'cancelled' ? 'cancel' : type,
190
+ cancelled_reason: reason,
191
+ });
192
+ this._receipts.push(receipt);
193
+ this._last_receipt_id = receipt.receipt_id;
194
+ this._last_chain_hash = await (0, chain_validator_1.computeChainHash)(receipt);
195
+ await this.postReceipt(receipt);
196
+ }
197
+ assertActive() {
198
+ if (this._state === 'budget_capped') {
199
+ throw new errors_1.AgentGuardBudgetCapError(`Workflow ${this.workflow_id} exceeded budget cap of $${this.config.budget_cap_usd}. Total spend to date: $${this._total_spend_usd}.`, { workflow_id: this.workflow_id, total_spend_usd: this._total_spend_usd });
200
+ }
201
+ if (this._state === 'duration_capped') {
202
+ throw new errors_1.AgentGuardDurationCapError(`Workflow ${this.workflow_id} exceeded duration cap.`, {
203
+ workflow_id: this.workflow_id,
204
+ elapsed_ms: Date.now() - this.created_at.getTime(),
205
+ });
206
+ }
207
+ if (this._state !== 'active') {
208
+ throw new errors_1.AgentGuardWorkflowStateError(`Workflow ${this.workflow_id} is ${this._state}.`, {
209
+ workflow_id: this.workflow_id,
210
+ state: this._state,
211
+ });
212
+ }
213
+ }
214
+ assertOutcomeAllowed(name) {
215
+ if (this.config.parent_outcomes && !this.config.parent_outcomes.includes(name)) {
216
+ throw new errors_1.AgentGuardWorkflowStateError(`Outcome ${name} is not allowed in workflow ${this.workflow_id}.`, {
217
+ workflow_id: this.workflow_id,
218
+ state: this._state,
219
+ });
220
+ }
221
+ }
222
+ assertBudgetRemaining() {
223
+ if (this._total_spend_usd >= this.config.budget_cap_usd) {
224
+ this._state = 'budget_capped';
225
+ throw new errors_1.AgentGuardBudgetCapError(`Workflow ${this.workflow_id} exceeded budget cap of $${this.config.budget_cap_usd}. Total spend to date: $${this._total_spend_usd}.`, { workflow_id: this.workflow_id, total_spend_usd: this._total_spend_usd });
226
+ }
227
+ }
228
+ assertDurationRemaining() {
229
+ const elapsed = Date.now() - this.created_at.getTime();
230
+ const cap = this.config.duration_cap_hours * 3_600_000;
231
+ if (elapsed >= cap) {
232
+ this._state = 'duration_capped';
233
+ throw new errors_1.AgentGuardDurationCapError(`Workflow ${this.workflow_id} exceeded duration cap.`, {
234
+ workflow_id: this.workflow_id,
235
+ elapsed_ms: elapsed,
236
+ });
237
+ }
238
+ }
239
+ async checkPostCallCaps() {
240
+ if (this._total_spend_usd >= this.config.budget_cap_usd) {
241
+ this._state = 'budget_capped';
242
+ await this.writeFinalReceipt('cap_hit', 'budget cap reached');
243
+ }
244
+ const elapsed = Date.now() - this.created_at.getTime();
245
+ if (elapsed >= this.config.duration_cap_hours * 3_600_000) {
246
+ this._state = 'duration_capped';
247
+ await this.writeFinalReceipt('cap_hit', 'duration cap reached');
248
+ }
249
+ }
250
+ extractOutcomeCost(result) {
251
+ if (isRecord(result)) {
252
+ if (typeof result.cost_usd === 'number')
253
+ return result.cost_usd;
254
+ const receipt = result.receipt;
255
+ if (isRecord(receipt) && typeof receipt.cost_usd === 'number')
256
+ return receipt.cost_usd;
257
+ }
258
+ const configured = this.config.metadata?.default_outcome_cost_usd;
259
+ return typeof configured === 'number' ? configured : 0;
260
+ }
261
+ async postReceipt(receipt) {
262
+ const apiBase = resolveApiBase(this.config);
263
+ if (!apiBase)
264
+ return;
265
+ await postJson(this.config, `${apiBase}/api/workflows/${this.workflow_id}/receipt`, { receipt });
266
+ }
267
+ }
268
+ exports.WorkflowContext = WorkflowContext;
269
+ async function workflow(config, fn) {
270
+ const ctx = await WorkflowContext.create(config);
271
+ try {
272
+ return await fn(ctx);
273
+ }
274
+ finally {
275
+ await ctx.finalize();
276
+ }
277
+ }
278
+ async function tryResume(config, userId) {
279
+ const apiBase = resolveApiBase(config);
280
+ if (!apiBase)
281
+ return null;
282
+ const headers = authHeaders(config);
283
+ const existing = await getJson(config, `${apiBase}/api/workflows/lookup?name=${encodeURIComponent(config.name)}`, headers);
284
+ if (!existing || ['cancelled', 'completed', 'budget_capped', 'duration_capped'].includes(existing.state ?? '')) {
285
+ return null;
286
+ }
287
+ const chain = await getJson(config, `${apiBase}/api/workflows/${existing.workflow_id}/chain`, headers);
288
+ const validation = await (0, chain_validator_1.validateReceiptChain)(chain.receipts);
289
+ if (!validation.ok) {
290
+ throw new errors_1.AgentGuardChainCorruptError(`Cannot resume workflow ${existing.workflow_id}: chain validation failed.`, {
291
+ workflow_id: existing.workflow_id,
292
+ broken_at: validation.broken_at,
293
+ reason: validation.reason,
294
+ });
295
+ }
296
+ return WorkflowContext.fromCheckpoint(config, { ...existing, receipts: chain.receipts }, userId);
297
+ }
298
+ function resolveApiBase(config) {
299
+ const value = config.api_base_url || process.env.AGENTGUARD_WORKFLOW_API_BASE || '';
300
+ return value ? value.replace(/\/$/, '') : null;
301
+ }
302
+ function authHeaders(config) {
303
+ const license = config.license_key || process.env.AGENTGUARD_LICENSE_KEY || '';
304
+ return {
305
+ 'content-type': 'application/json',
306
+ ...(license ? { authorization: `Bearer ${license}` } : {}),
307
+ };
308
+ }
309
+ async function postJson(config, url, body) {
310
+ const headers = authHeaders(config);
311
+ if (config.post_json)
312
+ return config.post_json(url, body, headers);
313
+ const response = await fetch(url, { method: 'POST', headers, body: JSON.stringify(body) });
314
+ if (!response.ok)
315
+ throw new Error(`Workflow API request failed: ${response.status}`);
316
+ return response.json();
317
+ }
318
+ async function getJson(config, url, headers) {
319
+ if (config.get_json)
320
+ return config.get_json(url, headers);
321
+ const response = await fetch(url, { headers });
322
+ if (response.status === 404)
323
+ return null;
324
+ if (!response.ok)
325
+ throw new Error(`Workflow API request failed: ${response.status}`);
326
+ return response.json();
327
+ }
328
+ function extractReviewerCascade(result) {
329
+ if (!isRecord(result))
330
+ return null;
331
+ const value = result.reviewer_cascade;
332
+ if (!isRecord(value))
333
+ return null;
334
+ return {
335
+ triggered: value.triggered === true,
336
+ drafter_model: typeof value.drafter_model === 'string' ? value.drafter_model : null,
337
+ reviewer_model: typeof value.reviewer_model === 'string' ? value.reviewer_model : null,
338
+ drafter_output_hash: typeof value.drafter_output_hash === 'string' ? value.drafter_output_hash : null,
339
+ reviewer_verdict: value.reviewer_verdict === 'approve' || value.reviewer_verdict === 'block' || value.reviewer_verdict === 'revise'
340
+ ? value.reviewer_verdict
341
+ : null,
342
+ reviewer_reasoning_hash: typeof value.reviewer_reasoning_hash === 'string' ? value.reviewer_reasoning_hash : null,
343
+ review_started_at: typeof value.review_started_at === 'string' ? value.review_started_at : null,
344
+ review_completed_at: typeof value.review_completed_at === 'string' ? value.review_completed_at : null,
345
+ };
346
+ }
347
+ function validateConfig(config) {
348
+ if (!config.name || !config.name.trim())
349
+ throw new Error('Workflow name is required');
350
+ if (!Number.isFinite(config.budget_cap_usd) || config.budget_cap_usd <= 0) {
351
+ throw new Error('Workflow budget_cap_usd must be greater than zero');
352
+ }
353
+ if (!Number.isFinite(config.duration_cap_hours) || config.duration_cap_hours <= 0) {
354
+ throw new Error('Workflow duration_cap_hours must be greater than zero');
355
+ }
356
+ }
357
+ function isRecord(value) {
358
+ return typeof value === 'object' && value !== null;
359
+ }
360
+ //# sourceMappingURL=context.js.map