@sweny-ai/core 0.1.156 → 0.1.158
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/budget.d.ts +115 -0
- package/dist/budget.js +191 -0
- package/dist/cli/main.d.ts +2 -0
- package/dist/cli/main.js +5 -1
- package/dist/cli/run-output.d.ts +10 -0
- package/dist/cli/run-output.js +20 -1
- package/dist/cli/workflow-input.d.ts +9 -0
- package/dist/cli/workflow-input.js +21 -0
- package/dist/eval/index.js +32 -32
- package/dist/executor.d.ts +12 -0
- package/dist/executor.js +177 -33
- package/dist/harness/acp.js +4 -1
- package/dist/harness/capabilities.d.ts +10 -4
- package/dist/harness/capabilities.js +12 -6
- package/dist/harness/claude-code.js +25 -1
- package/dist/harness/index.d.ts +1 -1
- package/dist/harness/index.js +1 -1
- package/dist/harness/policy.d.ts +13 -0
- package/dist/harness/policy.js +37 -0
- package/dist/harness/types.d.ts +7 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +1 -0
- package/dist/schema.d.ts +144 -1
- package/dist/schema.js +61 -1
- package/dist/types.d.ts +35 -0
- package/dist/types.js +2 -0
- package/package.json +1 -1
package/dist/schema.d.ts
CHANGED
|
@@ -848,6 +848,26 @@ export declare const nodePermissionsZ: z.ZodUnion<[z.ZodEnum<["read", "write"]>,
|
|
|
848
848
|
deny?: ("shell" | "write" | "edit" | "net" | "subagent")[] | undefined;
|
|
849
849
|
access?: "write" | "read" | undefined;
|
|
850
850
|
}>]>;
|
|
851
|
+
/**
|
|
852
|
+
* Spend ceiling (#449): input + output tokens and/or reported USD. The object
|
|
853
|
+
* must declare at least one of the two.
|
|
854
|
+
*/
|
|
855
|
+
export declare const budgetZ: z.ZodEffects<z.ZodObject<{
|
|
856
|
+
tokens: z.ZodOptional<z.ZodNumber>;
|
|
857
|
+
cost_usd: z.ZodOptional<z.ZodNumber>;
|
|
858
|
+
}, "strict", z.ZodTypeAny, {
|
|
859
|
+
tokens?: number | undefined;
|
|
860
|
+
cost_usd?: number | undefined;
|
|
861
|
+
}, {
|
|
862
|
+
tokens?: number | undefined;
|
|
863
|
+
cost_usd?: number | undefined;
|
|
864
|
+
}>, {
|
|
865
|
+
tokens?: number | undefined;
|
|
866
|
+
cost_usd?: number | undefined;
|
|
867
|
+
}, {
|
|
868
|
+
tokens?: number | undefined;
|
|
869
|
+
cost_usd?: number | undefined;
|
|
870
|
+
}>;
|
|
851
871
|
/** One typed write intent a node may emit (#365). */
|
|
852
872
|
export declare const safeOutputDeclarationZ: z.ZodObject<{
|
|
853
873
|
type: z.ZodEnum<["comment", "issue", "pr", "label", "issue_state"]>;
|
|
@@ -940,6 +960,22 @@ export declare const nodeZ: z.ZodObject<{
|
|
|
940
960
|
skills: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
|
|
941
961
|
output: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
942
962
|
max_turns: z.ZodOptional<z.ZodNumber>;
|
|
963
|
+
budget: z.ZodOptional<z.ZodEffects<z.ZodObject<{
|
|
964
|
+
tokens: z.ZodOptional<z.ZodNumber>;
|
|
965
|
+
cost_usd: z.ZodOptional<z.ZodNumber>;
|
|
966
|
+
}, "strict", z.ZodTypeAny, {
|
|
967
|
+
tokens?: number | undefined;
|
|
968
|
+
cost_usd?: number | undefined;
|
|
969
|
+
}, {
|
|
970
|
+
tokens?: number | undefined;
|
|
971
|
+
cost_usd?: number | undefined;
|
|
972
|
+
}>, {
|
|
973
|
+
tokens?: number | undefined;
|
|
974
|
+
cost_usd?: number | undefined;
|
|
975
|
+
}, {
|
|
976
|
+
tokens?: number | undefined;
|
|
977
|
+
cost_usd?: number | undefined;
|
|
978
|
+
}>>;
|
|
943
979
|
disallowed_tools: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
944
980
|
tools: z.ZodOptional<z.ZodEffects<z.ZodObject<{
|
|
945
981
|
allow: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
@@ -1426,6 +1462,10 @@ export declare const nodeZ: z.ZodObject<{
|
|
|
1426
1462
|
model?: string | undefined;
|
|
1427
1463
|
on_fail?: "halt" | "continue" | undefined;
|
|
1428
1464
|
max_turns?: number | undefined;
|
|
1465
|
+
budget?: {
|
|
1466
|
+
tokens?: number | undefined;
|
|
1467
|
+
cost_usd?: number | undefined;
|
|
1468
|
+
} | undefined;
|
|
1429
1469
|
disallowed_tools?: string[] | undefined;
|
|
1430
1470
|
fail_soft?: boolean | undefined;
|
|
1431
1471
|
permissions?: "write" | "read" | {
|
|
@@ -1540,6 +1580,10 @@ export declare const nodeZ: z.ZodObject<{
|
|
|
1540
1580
|
on_fail?: "halt" | "continue" | undefined;
|
|
1541
1581
|
skills?: string[] | undefined;
|
|
1542
1582
|
max_turns?: number | undefined;
|
|
1583
|
+
budget?: {
|
|
1584
|
+
tokens?: number | undefined;
|
|
1585
|
+
cost_usd?: number | undefined;
|
|
1586
|
+
} | undefined;
|
|
1543
1587
|
disallowed_tools?: string[] | undefined;
|
|
1544
1588
|
fail_soft?: boolean | undefined;
|
|
1545
1589
|
permissions?: "write" | "read" | {
|
|
@@ -1698,6 +1742,22 @@ export declare const workflowZ: z.ZodObject<{
|
|
|
1698
1742
|
skills: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
|
|
1699
1743
|
output: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
1700
1744
|
max_turns: z.ZodOptional<z.ZodNumber>;
|
|
1745
|
+
budget: z.ZodOptional<z.ZodEffects<z.ZodObject<{
|
|
1746
|
+
tokens: z.ZodOptional<z.ZodNumber>;
|
|
1747
|
+
cost_usd: z.ZodOptional<z.ZodNumber>;
|
|
1748
|
+
}, "strict", z.ZodTypeAny, {
|
|
1749
|
+
tokens?: number | undefined;
|
|
1750
|
+
cost_usd?: number | undefined;
|
|
1751
|
+
}, {
|
|
1752
|
+
tokens?: number | undefined;
|
|
1753
|
+
cost_usd?: number | undefined;
|
|
1754
|
+
}>, {
|
|
1755
|
+
tokens?: number | undefined;
|
|
1756
|
+
cost_usd?: number | undefined;
|
|
1757
|
+
}, {
|
|
1758
|
+
tokens?: number | undefined;
|
|
1759
|
+
cost_usd?: number | undefined;
|
|
1760
|
+
}>>;
|
|
1701
1761
|
disallowed_tools: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
1702
1762
|
tools: z.ZodOptional<z.ZodEffects<z.ZodObject<{
|
|
1703
1763
|
allow: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
@@ -2184,6 +2244,10 @@ export declare const workflowZ: z.ZodObject<{
|
|
|
2184
2244
|
model?: string | undefined;
|
|
2185
2245
|
on_fail?: "halt" | "continue" | undefined;
|
|
2186
2246
|
max_turns?: number | undefined;
|
|
2247
|
+
budget?: {
|
|
2248
|
+
tokens?: number | undefined;
|
|
2249
|
+
cost_usd?: number | undefined;
|
|
2250
|
+
} | undefined;
|
|
2187
2251
|
disallowed_tools?: string[] | undefined;
|
|
2188
2252
|
fail_soft?: boolean | undefined;
|
|
2189
2253
|
permissions?: "write" | "read" | {
|
|
@@ -2298,6 +2362,10 @@ export declare const workflowZ: z.ZodObject<{
|
|
|
2298
2362
|
on_fail?: "halt" | "continue" | undefined;
|
|
2299
2363
|
skills?: string[] | undefined;
|
|
2300
2364
|
max_turns?: number | undefined;
|
|
2365
|
+
budget?: {
|
|
2366
|
+
tokens?: number | undefined;
|
|
2367
|
+
cost_usd?: number | undefined;
|
|
2368
|
+
} | undefined;
|
|
2301
2369
|
disallowed_tools?: string[] | undefined;
|
|
2302
2370
|
fail_soft?: boolean | undefined;
|
|
2303
2371
|
permissions?: "write" | "read" | {
|
|
@@ -2547,6 +2615,23 @@ export declare const workflowZ: z.ZodObject<{
|
|
|
2547
2615
|
judge_model: z.ZodOptional<z.ZodString>;
|
|
2548
2616
|
model: z.ZodOptional<z.ZodString>;
|
|
2549
2617
|
judge_budget: z.ZodOptional<z.ZodNumber>;
|
|
2618
|
+
budget: z.ZodOptional<z.ZodEffects<z.ZodObject<{
|
|
2619
|
+
tokens: z.ZodOptional<z.ZodNumber>;
|
|
2620
|
+
cost_usd: z.ZodOptional<z.ZodNumber>;
|
|
2621
|
+
}, "strict", z.ZodTypeAny, {
|
|
2622
|
+
tokens?: number | undefined;
|
|
2623
|
+
cost_usd?: number | undefined;
|
|
2624
|
+
}, {
|
|
2625
|
+
tokens?: number | undefined;
|
|
2626
|
+
cost_usd?: number | undefined;
|
|
2627
|
+
}>, {
|
|
2628
|
+
tokens?: number | undefined;
|
|
2629
|
+
cost_usd?: number | undefined;
|
|
2630
|
+
}, {
|
|
2631
|
+
tokens?: number | undefined;
|
|
2632
|
+
cost_usd?: number | undefined;
|
|
2633
|
+
}>>;
|
|
2634
|
+
context_mode: z.ZodOptional<z.ZodEnum<["bounded", "full"]>>;
|
|
2550
2635
|
inputs: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodEffects<z.ZodObject<{
|
|
2551
2636
|
type: z.ZodEnum<["string", "number", "boolean", "string[]"]>;
|
|
2552
2637
|
description: z.ZodOptional<z.ZodString>;
|
|
@@ -2657,6 +2742,10 @@ export declare const workflowZ: z.ZodObject<{
|
|
|
2657
2742
|
model?: string | undefined;
|
|
2658
2743
|
on_fail?: "halt" | "continue" | undefined;
|
|
2659
2744
|
max_turns?: number | undefined;
|
|
2745
|
+
budget?: {
|
|
2746
|
+
tokens?: number | undefined;
|
|
2747
|
+
cost_usd?: number | undefined;
|
|
2748
|
+
} | undefined;
|
|
2660
2749
|
disallowed_tools?: string[] | undefined;
|
|
2661
2750
|
fail_soft?: boolean | undefined;
|
|
2662
2751
|
permissions?: "write" | "read" | {
|
|
@@ -2761,6 +2850,10 @@ export declare const workflowZ: z.ZodObject<{
|
|
|
2761
2850
|
}[];
|
|
2762
2851
|
entry: string;
|
|
2763
2852
|
model?: string | undefined;
|
|
2853
|
+
budget?: {
|
|
2854
|
+
tokens?: number | undefined;
|
|
2855
|
+
cost_usd?: number | undefined;
|
|
2856
|
+
} | undefined;
|
|
2764
2857
|
permissions?: "write" | "read" | {
|
|
2765
2858
|
strict?: boolean | undefined;
|
|
2766
2859
|
deny?: ("shell" | "write" | "edit" | "net" | "subagent")[] | undefined;
|
|
@@ -2785,6 +2878,7 @@ export declare const workflowZ: z.ZodObject<{
|
|
|
2785
2878
|
judge_model?: string | undefined;
|
|
2786
2879
|
workflow_type?: "pr_review" | "e2e_test" | "content_generation" | "monitor" | "data_sync" | "generic" | undefined;
|
|
2787
2880
|
judge_budget?: number | undefined;
|
|
2881
|
+
context_mode?: "full" | "bounded" | undefined;
|
|
2788
2882
|
inputs?: Record<string, {
|
|
2789
2883
|
type: "string" | "number" | "boolean" | "string[]";
|
|
2790
2884
|
description?: string | undefined;
|
|
@@ -2822,6 +2916,10 @@ export declare const workflowZ: z.ZodObject<{
|
|
|
2822
2916
|
on_fail?: "halt" | "continue" | undefined;
|
|
2823
2917
|
skills?: string[] | undefined;
|
|
2824
2918
|
max_turns?: number | undefined;
|
|
2919
|
+
budget?: {
|
|
2920
|
+
tokens?: number | undefined;
|
|
2921
|
+
cost_usd?: number | undefined;
|
|
2922
|
+
} | undefined;
|
|
2825
2923
|
disallowed_tools?: string[] | undefined;
|
|
2826
2924
|
fail_soft?: boolean | undefined;
|
|
2827
2925
|
permissions?: "write" | "read" | {
|
|
@@ -2940,6 +3038,10 @@ export declare const workflowZ: z.ZodObject<{
|
|
|
2940
3038
|
env?: Record<string, string> | undefined;
|
|
2941
3039
|
} | undefined;
|
|
2942
3040
|
}> | undefined;
|
|
3041
|
+
budget?: {
|
|
3042
|
+
tokens?: number | undefined;
|
|
3043
|
+
cost_usd?: number | undefined;
|
|
3044
|
+
} | undefined;
|
|
2943
3045
|
permissions?: "write" | "read" | {
|
|
2944
3046
|
strict?: boolean | undefined;
|
|
2945
3047
|
deny?: ("shell" | "write" | "edit" | "net" | "subagent")[] | undefined;
|
|
@@ -2964,6 +3066,7 @@ export declare const workflowZ: z.ZodObject<{
|
|
|
2964
3066
|
judge_model?: string | undefined;
|
|
2965
3067
|
workflow_type?: "pr_review" | "e2e_test" | "content_generation" | "monitor" | "data_sync" | "generic" | undefined;
|
|
2966
3068
|
judge_budget?: number | undefined;
|
|
3069
|
+
context_mode?: "full" | "bounded" | undefined;
|
|
2967
3070
|
inputs?: Record<string, {
|
|
2968
3071
|
type: "string" | "number" | "boolean" | "string[]";
|
|
2969
3072
|
description?: string | undefined;
|
|
@@ -3029,6 +3132,10 @@ export declare function parseWorkflow(raw: unknown): {
|
|
|
3029
3132
|
model?: string | undefined;
|
|
3030
3133
|
on_fail?: "halt" | "continue" | undefined;
|
|
3031
3134
|
max_turns?: number | undefined;
|
|
3135
|
+
budget?: {
|
|
3136
|
+
tokens?: number | undefined;
|
|
3137
|
+
cost_usd?: number | undefined;
|
|
3138
|
+
} | undefined;
|
|
3032
3139
|
disallowed_tools?: string[] | undefined;
|
|
3033
3140
|
fail_soft?: boolean | undefined;
|
|
3034
3141
|
permissions?: "write" | "read" | {
|
|
@@ -3133,6 +3240,10 @@ export declare function parseWorkflow(raw: unknown): {
|
|
|
3133
3240
|
}[];
|
|
3134
3241
|
entry: string;
|
|
3135
3242
|
model?: string | undefined;
|
|
3243
|
+
budget?: {
|
|
3244
|
+
tokens?: number | undefined;
|
|
3245
|
+
cost_usd?: number | undefined;
|
|
3246
|
+
} | undefined;
|
|
3136
3247
|
permissions?: "write" | "read" | {
|
|
3137
3248
|
strict?: boolean | undefined;
|
|
3138
3249
|
deny?: ("shell" | "write" | "edit" | "net" | "subagent")[] | undefined;
|
|
@@ -3157,6 +3268,7 @@ export declare function parseWorkflow(raw: unknown): {
|
|
|
3157
3268
|
judge_model?: string | undefined;
|
|
3158
3269
|
workflow_type?: "pr_review" | "e2e_test" | "content_generation" | "monitor" | "data_sync" | "generic" | undefined;
|
|
3159
3270
|
judge_budget?: number | undefined;
|
|
3271
|
+
context_mode?: "full" | "bounded" | undefined;
|
|
3160
3272
|
inputs?: Record<string, {
|
|
3161
3273
|
type: "string" | "number" | "boolean" | "string[]";
|
|
3162
3274
|
description?: string | undefined;
|
|
@@ -3174,7 +3286,7 @@ export declare function parseWorkflow(raw: unknown): {
|
|
|
3174
3286
|
} | undefined;
|
|
3175
3287
|
};
|
|
3176
3288
|
export interface WorkflowError {
|
|
3177
|
-
code: "MISSING_ENTRY" | "UNKNOWN_EDGE_SOURCE" | "UNKNOWN_EDGE_TARGET" | "UNREACHABLE_NODE" | "UNKNOWN_SKILL" | "SELF_LOOP" | "UNBOUNDED_CYCLE" | "AMBIGUOUS_EDGES" | "UNSUPPORTED_EVAL_POLICY" | "INVALID_INLINE_SKILL" | "EDGE_ITERATIONS_EXCEEDED" | "RETRY_MAX_EXCEEDED" | "PERMISSION_CEILING" | "OUTPUT_NOT_ALLOWED" | "DUPLICATE_OUTPUT" | "UNSUPPORTED_OUTPUT";
|
|
3289
|
+
code: "MISSING_ENTRY" | "UNKNOWN_EDGE_SOURCE" | "UNKNOWN_EDGE_TARGET" | "UNREACHABLE_NODE" | "UNKNOWN_SKILL" | "SELF_LOOP" | "UNBOUNDED_CYCLE" | "AMBIGUOUS_EDGES" | "UNSUPPORTED_EVAL_POLICY" | "INVALID_INLINE_SKILL" | "EDGE_ITERATIONS_EXCEEDED" | "RETRY_MAX_EXCEEDED" | "PERMISSION_CEILING" | "BUDGET_CEILING" | "OUTPUT_NOT_ALLOWED" | "DUPLICATE_OUTPUT" | "UNSUPPORTED_OUTPUT";
|
|
3178
3290
|
message: string;
|
|
3179
3291
|
nodeId?: string;
|
|
3180
3292
|
}
|
|
@@ -3434,6 +3546,24 @@ export declare const workflowJsonSchema: {
|
|
|
3434
3546
|
};
|
|
3435
3547
|
}];
|
|
3436
3548
|
};
|
|
3549
|
+
readonly Budget: {
|
|
3550
|
+
readonly type: "object";
|
|
3551
|
+
readonly additionalProperties: false;
|
|
3552
|
+
readonly minProperties: 1;
|
|
3553
|
+
readonly description: "A spend ceiling. 'tokens' counts input plus output tokens as the harness reports them; 'cost_usd' is the harness-reported cost (never estimated). A crossing stops the agent and fails the node; the run halts.";
|
|
3554
|
+
readonly properties: {
|
|
3555
|
+
readonly tokens: {
|
|
3556
|
+
readonly type: "integer";
|
|
3557
|
+
readonly minimum: 1;
|
|
3558
|
+
readonly description: "Max input plus output tokens.";
|
|
3559
|
+
};
|
|
3560
|
+
readonly cost_usd: {
|
|
3561
|
+
readonly type: "number";
|
|
3562
|
+
readonly exclusiveMinimum: 0;
|
|
3563
|
+
readonly description: "Max reported cost in USD.";
|
|
3564
|
+
};
|
|
3565
|
+
};
|
|
3566
|
+
};
|
|
3437
3567
|
readonly SafeOutput: {
|
|
3438
3568
|
readonly type: "object";
|
|
3439
3569
|
readonly required: readonly ["type"];
|
|
@@ -3610,6 +3740,15 @@ export declare const workflowJsonSchema: {
|
|
|
3610
3740
|
readonly minimum: 0;
|
|
3611
3741
|
readonly description: "Soft cap on expected judge calls per workflow run. Executor warns at load time if exceeded; not a hard runtime cap in v1.";
|
|
3612
3742
|
};
|
|
3743
|
+
readonly budget: {
|
|
3744
|
+
readonly $ref: "#/$defs/Budget";
|
|
3745
|
+
readonly description: "Spend ceiling for the whole run and for every node. A node's own budget may only narrow it. The CLI's --max-tokens and --max-cost tighten it further.";
|
|
3746
|
+
};
|
|
3747
|
+
readonly context_mode: {
|
|
3748
|
+
readonly type: "string";
|
|
3749
|
+
readonly enum: readonly ["bounded", "full"];
|
|
3750
|
+
readonly description: "What prior results a node's prompt receives. bounded (default): only nodes it can depend on, and a schema'd node's declared fields instead of its free-text summary. full: every prior node's complete data.";
|
|
3751
|
+
};
|
|
3613
3752
|
readonly inputs: {
|
|
3614
3753
|
readonly type: "object";
|
|
3615
3754
|
readonly description: "Declared per-run input contract. Each entry names a parameter the caller may supply via --input. The CLI validates against this declaration, applies defaults for omitted optional fields, and rejects unknown types before the executor runs. Optional; workflows without an inputs block accept any JSON object (back-compat).";
|
|
@@ -3770,6 +3909,10 @@ export declare const workflowJsonSchema: {
|
|
|
3770
3909
|
readonly minimum: 1;
|
|
3771
3910
|
readonly description: "Max AI model turns for this node. When absent, the executor's default applies.";
|
|
3772
3911
|
};
|
|
3912
|
+
readonly budget: {
|
|
3913
|
+
readonly $ref: "#/$defs/Budget";
|
|
3914
|
+
readonly description: "Spend ceiling for one visit to this node, retry attempts included. Never above the workflow's budget. Crossing it stops the agent and fails the node (fail_soft and on_fail: continue do not apply) and the run halts.";
|
|
3915
|
+
};
|
|
3773
3916
|
readonly disallowed_tools: {
|
|
3774
3917
|
readonly type: "array";
|
|
3775
3918
|
readonly items: {
|
package/dist/schema.js
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* parsing untrusted input (JSON/YAML import, Studio editor).
|
|
8
8
|
*/
|
|
9
9
|
import { z } from "zod";
|
|
10
|
-
import { AUTHOR_ASSOCIATIONS, EVALUATOR_KINDS, EVAL_POLICIES, MCP_TRANSPORTS, NODE_ACCESS, NODE_ON_FAIL, REQUIRES_ON_FAIL, SAFE_OUTPUT_APPLIERS, SAFE_OUTPUT_EXPIRES_PATTERN, SAFE_OUTPUT_MAX_CEILING, SAFE_OUTPUT_STATES, SAFE_OUTPUT_TYPES, SKILL_CATEGORIES, SKILL_ID_MAX_LENGTH, SKILL_ID_PATTERN, TOOL_ACCESS, TOOL_CLASSES, WORKFLOW_TYPES, } from "./types.js";
|
|
10
|
+
import { AUTHOR_ASSOCIATIONS, CONTEXT_MODES, EVALUATOR_KINDS, EVAL_POLICIES, MCP_TRANSPORTS, NODE_ACCESS, NODE_ON_FAIL, REQUIRES_ON_FAIL, SAFE_OUTPUT_APPLIERS, SAFE_OUTPUT_EXPIRES_PATTERN, SAFE_OUTPUT_MAX_CEILING, SAFE_OUTPUT_STATES, SAFE_OUTPUT_TYPES, SKILL_CATEGORIES, SKILL_ID_MAX_LENGTH, SKILL_ID_PATTERN, TOOL_ACCESS, TOOL_CLASSES, WORKFLOW_TYPES, } from "./types.js";
|
|
11
11
|
import { sourceZ } from "./sources.js";
|
|
12
12
|
import { workflowInputsZ, WORKFLOW_INPUT_TYPES } from "./inputs.js";
|
|
13
13
|
export { sourceZ };
|
|
@@ -262,6 +262,19 @@ export const nodePermissionsZ = z.union([
|
|
|
262
262
|
message: "permissions must declare at least one of access, deny, strict",
|
|
263
263
|
}),
|
|
264
264
|
]);
|
|
265
|
+
/**
|
|
266
|
+
* Spend ceiling (#449): input + output tokens and/or reported USD. The object
|
|
267
|
+
* must declare at least one of the two.
|
|
268
|
+
*/
|
|
269
|
+
export const budgetZ = z
|
|
270
|
+
.object({
|
|
271
|
+
tokens: z.number().int().min(1).optional(),
|
|
272
|
+
cost_usd: z.number().positive().optional(),
|
|
273
|
+
})
|
|
274
|
+
.strict()
|
|
275
|
+
.refine((b) => b.tokens !== undefined || b.cost_usd !== undefined, {
|
|
276
|
+
message: "budget must declare at least one of tokens, cost_usd",
|
|
277
|
+
});
|
|
265
278
|
/** One typed write intent a node may emit (#365). */
|
|
266
279
|
export const safeOutputDeclarationZ = z
|
|
267
280
|
.object({
|
|
@@ -296,6 +309,7 @@ export const nodeZ = z
|
|
|
296
309
|
skills: z.array(z.string()).default([]),
|
|
297
310
|
output: jsonSchemaZ.optional(),
|
|
298
311
|
max_turns: z.number().int().min(1).optional(),
|
|
312
|
+
budget: budgetZ.optional(),
|
|
299
313
|
disallowed_tools: z.array(z.string().min(1)).optional(),
|
|
300
314
|
tools: nodeToolsZ.optional(),
|
|
301
315
|
fail_soft: z.boolean().optional(),
|
|
@@ -353,6 +367,8 @@ export const workflowZ = z.object({
|
|
|
353
367
|
judge_model: z.string().min(1).optional(),
|
|
354
368
|
model: z.string().min(1).optional(),
|
|
355
369
|
judge_budget: z.number().int().min(0).optional(),
|
|
370
|
+
budget: budgetZ.optional(),
|
|
371
|
+
context_mode: z.enum(CONTEXT_MODES).optional(),
|
|
356
372
|
inputs: workflowInputsZ.optional(),
|
|
357
373
|
permissions: nodePermissionsZ.optional(),
|
|
358
374
|
safe_outputs: safeOutputsPolicyZ.optional(),
|
|
@@ -610,6 +626,27 @@ export function validateWorkflow(workflow, knownSkills) {
|
|
|
610
626
|
nodeId,
|
|
611
627
|
});
|
|
612
628
|
}
|
|
629
|
+
// Budgets (#449): the workflow's `budget` is the ceiling for every node.
|
|
630
|
+
const wfBudget = workflow.budget;
|
|
631
|
+
const nodeBudget = node.budget;
|
|
632
|
+
if (wfBudget && nodeBudget) {
|
|
633
|
+
if (wfBudget.tokens !== undefined && nodeBudget.tokens !== undefined && nodeBudget.tokens > wfBudget.tokens) {
|
|
634
|
+
errors.push({
|
|
635
|
+
code: "BUDGET_CEILING",
|
|
636
|
+
message: `Node "${nodeId}" declares budget.tokens ${nodeBudget.tokens}, above the workflow's budget.tokens ${wfBudget.tokens}`,
|
|
637
|
+
nodeId,
|
|
638
|
+
});
|
|
639
|
+
}
|
|
640
|
+
if (wfBudget.cost_usd !== undefined &&
|
|
641
|
+
nodeBudget.cost_usd !== undefined &&
|
|
642
|
+
nodeBudget.cost_usd > wfBudget.cost_usd) {
|
|
643
|
+
errors.push({
|
|
644
|
+
code: "BUDGET_CEILING",
|
|
645
|
+
message: `Node "${nodeId}" declares budget.cost_usd ${nodeBudget.cost_usd}, above the workflow's budget.cost_usd ${wfBudget.cost_usd}`,
|
|
646
|
+
nodeId,
|
|
647
|
+
});
|
|
648
|
+
}
|
|
649
|
+
}
|
|
613
650
|
const seenTypes = new Set();
|
|
614
651
|
for (const out of node.outputs ?? []) {
|
|
615
652
|
if (seenTypes.has(out.type)) {
|
|
@@ -843,6 +880,16 @@ export const workflowJsonSchema = {
|
|
|
843
880
|
},
|
|
844
881
|
],
|
|
845
882
|
},
|
|
883
|
+
Budget: {
|
|
884
|
+
type: "object",
|
|
885
|
+
additionalProperties: false,
|
|
886
|
+
minProperties: 1,
|
|
887
|
+
description: "A spend ceiling. 'tokens' counts input plus output tokens as the harness reports them; 'cost_usd' is the harness-reported cost (never estimated). A crossing stops the agent and fails the node; the run halts.",
|
|
888
|
+
properties: {
|
|
889
|
+
tokens: { type: "integer", minimum: 1, description: "Max input plus output tokens." },
|
|
890
|
+
cost_usd: { type: "number", exclusiveMinimum: 0, description: "Max reported cost in USD." },
|
|
891
|
+
},
|
|
892
|
+
},
|
|
846
893
|
SafeOutput: {
|
|
847
894
|
type: "object",
|
|
848
895
|
required: ["type"],
|
|
@@ -983,6 +1030,15 @@ export const workflowJsonSchema = {
|
|
|
983
1030
|
// applies the soft-cap default at use-time. See judge_model above.
|
|
984
1031
|
description: "Soft cap on expected judge calls per workflow run. Executor warns at load time if exceeded; not a hard runtime cap in v1.",
|
|
985
1032
|
},
|
|
1033
|
+
budget: {
|
|
1034
|
+
$ref: "#/$defs/Budget",
|
|
1035
|
+
description: "Spend ceiling for the whole run and for every node. A node's own budget may only narrow it. The CLI's --max-tokens and --max-cost tighten it further.",
|
|
1036
|
+
},
|
|
1037
|
+
context_mode: {
|
|
1038
|
+
type: "string",
|
|
1039
|
+
enum: [...CONTEXT_MODES],
|
|
1040
|
+
description: "What prior results a node's prompt receives. bounded (default): only nodes it can depend on, and a schema'd node's declared fields instead of its free-text summary. full: every prior node's complete data.",
|
|
1041
|
+
},
|
|
986
1042
|
inputs: {
|
|
987
1043
|
type: "object",
|
|
988
1044
|
description: "Declared per-run input contract. Each entry names a parameter the caller may supply via --input. The CLI validates against this declaration, applies defaults for omitted optional fields, and rejects unknown types before the executor runs. Optional; workflows without an inputs block accept any JSON object (back-compat).",
|
|
@@ -1094,6 +1150,10 @@ export const workflowJsonSchema = {
|
|
|
1094
1150
|
minimum: 1,
|
|
1095
1151
|
description: "Max AI model turns for this node. When absent, the executor's default applies.",
|
|
1096
1152
|
},
|
|
1153
|
+
budget: {
|
|
1154
|
+
$ref: "#/$defs/Budget",
|
|
1155
|
+
description: "Spend ceiling for one visit to this node, retry attempts included. Never above the workflow's budget. Crossing it stops the agent and fails the node (fail_soft and on_fail: continue do not apply) and the run halts.",
|
|
1156
|
+
},
|
|
1097
1157
|
disallowed_tools: {
|
|
1098
1158
|
type: "array",
|
|
1099
1159
|
items: { type: "string", minLength: 1 },
|
package/dist/types.d.ts
CHANGED
|
@@ -3,6 +3,7 @@ export type { WorkflowInputs, WorkflowInputField, WorkflowInputType, InputValida
|
|
|
3
3
|
export { WORKFLOW_INPUT_TYPES } from "./inputs.js";
|
|
4
4
|
import type { Source as _Source, ResolvedSource as _ResolvedSource } from "./sources.js";
|
|
5
5
|
import type { ToolClass } from "./harness/types.js";
|
|
6
|
+
import type { Budget, BudgetOverrun } from "./budget.js";
|
|
6
7
|
export type JSONSchema = Record<string, unknown>;
|
|
7
8
|
/** Context passed to tool handlers at execution time */
|
|
8
9
|
export interface ToolContext {
|
|
@@ -137,6 +138,9 @@ export type EvaluatorKind = (typeof EVALUATOR_KINDS)[number];
|
|
|
137
138
|
/** Aggregation policy for a node's evaluator results. v1 implements `all_pass`. */
|
|
138
139
|
export declare const EVAL_POLICIES: readonly ["all_pass", "any_pass", "weighted"];
|
|
139
140
|
export type EvalPolicy = (typeof EVAL_POLICIES)[number];
|
|
141
|
+
/** What prior results a node's prompt receives (#337). See {@link Workflow.context_mode}. */
|
|
142
|
+
export declare const CONTEXT_MODES: readonly ["bounded", "full"];
|
|
143
|
+
export type ContextMode = (typeof CONTEXT_MODES)[number];
|
|
140
144
|
/** Action when a `requires` precondition fails. */
|
|
141
145
|
export declare const REQUIRES_ON_FAIL: readonly ["fail", "skip"];
|
|
142
146
|
export type RequiresOnFail = (typeof REQUIRES_ON_FAIL)[number];
|
|
@@ -291,6 +295,12 @@ export interface Node {
|
|
|
291
295
|
output?: JSONSchema;
|
|
292
296
|
/** Max AI model turns for this node. When absent, the executor's default applies. */
|
|
293
297
|
max_turns?: number;
|
|
298
|
+
/**
|
|
299
|
+
* Spend ceiling for one visit to this node (all retry attempts included),
|
|
300
|
+
* in input + output tokens and/or reported USD. Never above the workflow's
|
|
301
|
+
* `budget`. A crossing stops the agent and fails the node (see `budget.ts`).
|
|
302
|
+
*/
|
|
303
|
+
budget?: Budget;
|
|
294
304
|
/** Per-node directives. Additive by default; set `{ only: true, sources: [...] }` to block cascade. */
|
|
295
305
|
rules?: NodeSources;
|
|
296
306
|
/** Per-node background knowledge. Additive by default; set `{ only: true, sources: [...] }` to block cascade. */
|
|
@@ -520,6 +530,18 @@ export interface Workflow {
|
|
|
520
530
|
model?: string;
|
|
521
531
|
/** Soft cap on expected judge calls per workflow run. Warning at load time when exceeded. */
|
|
522
532
|
judge_budget?: number;
|
|
533
|
+
/**
|
|
534
|
+
* Spend ceiling for the whole run and for every node (#449). A node's own
|
|
535
|
+
* `budget` may only narrow it. The CLI's `--max-tokens` / `--max-cost` tighten it.
|
|
536
|
+
*/
|
|
537
|
+
budget?: Budget;
|
|
538
|
+
/**
|
|
539
|
+
* What prior results a node's prompt receives (#337). `bounded` (default):
|
|
540
|
+
* only nodes it can depend on (graph ancestors, nodes named by `requires`
|
|
541
|
+
* or its instruction), and a schema'd node's declared fields instead of its
|
|
542
|
+
* free-text `summary`. `full`: every prior node's complete data.
|
|
543
|
+
*/
|
|
544
|
+
context_mode?: ContextMode;
|
|
523
545
|
/**
|
|
524
546
|
* Declared per-run input contract. When present, the CLI validates the
|
|
525
547
|
* caller-provided `--input` JSON against this declaration, applies defaults
|
|
@@ -602,6 +624,12 @@ export interface NodeResult {
|
|
|
602
624
|
degraded?: string[];
|
|
603
625
|
/** Safe outputs (#365): what the write stage did with each intent. Absent when the node declares none. */
|
|
604
626
|
outputs?: SafeOutputReceipt[];
|
|
627
|
+
/**
|
|
628
|
+
* Set when this node's spend crossed a token or cost budget (#449), or when
|
|
629
|
+
* the run's budget was already spent before it could start. The node is
|
|
630
|
+
* `failed`, `fail_soft` and `on_fail: continue` do not apply, and the run halts.
|
|
631
|
+
*/
|
|
632
|
+
budget?: BudgetOverrun;
|
|
605
633
|
}
|
|
606
634
|
export interface ToolCall {
|
|
607
635
|
tool: string;
|
|
@@ -770,6 +798,13 @@ export interface Claude {
|
|
|
770
798
|
* carry the same read-only and native-deny intent.
|
|
771
799
|
*/
|
|
772
800
|
policy?: import("./harness/types.js").NodePolicy;
|
|
801
|
+
/**
|
|
802
|
+
* Live spend (#449): a harness that declares `capabilities.usage.live`
|
|
803
|
+
* calls this with the run's cumulative usage as it grows. The executor
|
|
804
|
+
* aborts `signal` when a budget is crossed. Harnesses that report usage
|
|
805
|
+
* only at the end never call it.
|
|
806
|
+
*/
|
|
807
|
+
onUsage?: (usage: NodeUsage) => void;
|
|
773
808
|
}): Promise<NodeResult>;
|
|
774
809
|
/**
|
|
775
810
|
* Evaluate a routing condition — pick one of N choices.
|
package/dist/types.js
CHANGED
|
@@ -51,6 +51,8 @@ export function isValidSkillId(id) {
|
|
|
51
51
|
export const EVALUATOR_KINDS = ["value", "function", "judge"];
|
|
52
52
|
/** Aggregation policy for a node's evaluator results. v1 implements `all_pass`. */
|
|
53
53
|
export const EVAL_POLICIES = ["all_pass", "any_pass", "weighted"];
|
|
54
|
+
/** What prior results a node's prompt receives (#337). See {@link Workflow.context_mode}. */
|
|
55
|
+
export const CONTEXT_MODES = ["bounded", "full"];
|
|
54
56
|
/** Action when a `requires` precondition fails. */
|
|
55
57
|
export const REQUIRES_ON_FAIL = ["fail", "skip"];
|
|
56
58
|
/**
|