@sweny-ai/core 0.1.199 → 0.1.200
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 +77 -11
- package/dist/budget.js +132 -16
- package/dist/cli/renderer.js +5 -0
- package/dist/cli/run-history.d.ts +12 -0
- package/dist/cli/run-history.js +16 -0
- package/dist/cli/run-output.d.ts +16 -1
- package/dist/cli/run-output.js +46 -4
- package/dist/cli/runs.js +38 -1
- package/dist/cli/ticket.js +7 -2
- package/dist/eval/index.d.ts +10 -0
- package/dist/eval/index.js +27 -6
- package/dist/eval/judge.d.ts +3 -0
- package/dist/eval/judge.js +12 -2
- package/dist/executor.js +276 -31
- package/dist/harness/acp.js +4 -1
- package/dist/harness/claude-code.d.ts +3 -1
- package/dist/harness/claude-code.js +4 -1
- package/dist/harness/codex.js +3 -1
- package/dist/harness/compat.js +1 -0
- package/dist/harness/index.d.ts +1 -1
- package/dist/harness/index.js +1 -1
- package/dist/harness/pi.js +3 -1
- package/dist/harness/prompts.d.ts +11 -1
- package/dist/harness/prompts.js +21 -2
- package/dist/harness/types.d.ts +9 -1
- package/dist/index.d.ts +4 -4
- package/dist/index.js +2 -2
- package/dist/journal.d.ts +48 -10
- package/dist/journal.js +164 -16
- package/dist/safe-outputs.d.ts +9 -0
- package/dist/safe-outputs.js +41 -26
- package/dist/skills/linear.js +3 -1
- package/dist/studio.js +2 -1
- package/dist/types.d.ts +34 -1
- package/package.json +1 -1
package/dist/safe-outputs.d.ts
CHANGED
|
@@ -114,6 +114,15 @@ export interface ApplySafeOutputsOptions {
|
|
|
114
114
|
* passed every deterministic check). Anything but `ALLOW` is a veto.
|
|
115
115
|
*/
|
|
116
116
|
screen?: (writes: Record<string, unknown>[]) => Promise<string | null>;
|
|
117
|
+
/**
|
|
118
|
+
* Resume: reconcile one write (its skill, tool and arguments) with the
|
|
119
|
+
* journal and, for an outstanding intent, the provider's read-only probes,
|
|
120
|
+
* before the screen. `applied`: recorded or found on the provider; it is not
|
|
121
|
+
* screened and keeps its receipt even when the screen vetoes the rest.
|
|
122
|
+
* `unknown`: the probe could not tell; it is not screened or vetoed, and the
|
|
123
|
+
* write handler reports the uncertainty. `absent`: screened as usual.
|
|
124
|
+
*/
|
|
125
|
+
reconcile?: (skill: Skill, tool: string, args: unknown, ctx: ToolContext) => Promise<"applied" | "unknown" | "absent">;
|
|
117
126
|
now?: () => number;
|
|
118
127
|
}
|
|
119
128
|
export interface ApplySafeOutputsResult {
|
package/dist/safe-outputs.js
CHANGED
|
@@ -545,26 +545,49 @@ export async function applySafeOutputs(o) {
|
|
|
545
545
|
printPreview(write, o.logger);
|
|
546
546
|
return { receipts };
|
|
547
547
|
}
|
|
548
|
-
|
|
548
|
+
const toolCtx = {
|
|
549
|
+
config: o.config,
|
|
550
|
+
logger: o.logger,
|
|
551
|
+
...(o.cwd ? { cwd: o.cwd } : {}),
|
|
552
|
+
...(o.pushBranch ? { pushBranch: o.pushBranch } : {}),
|
|
553
|
+
...(o.githubApiUrl ? { githubApiUrl: o.githubApiUrl } : {}),
|
|
554
|
+
...(o.run ? { run: o.run } : {}),
|
|
555
|
+
...(o.summary ? { summary: o.summary } : {}),
|
|
556
|
+
};
|
|
557
|
+
// Model screen: veto only. It sees only what passed every deterministic
|
|
558
|
+
// check and is not already applied: on a resume, outstanding writes are
|
|
559
|
+
// reconciled with the journal and the provider first, so a write that
|
|
560
|
+
// landed before the crash keeps its receipt, and one whose probe could not
|
|
561
|
+
// tell is reported as uncertain by its handler, never as vetoed.
|
|
562
|
+
let toApply = accepted;
|
|
549
563
|
if (o.policy?.screen) {
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
verdict = null;
|
|
564
|
+
const state = new Map();
|
|
565
|
+
for (const a of accepted) {
|
|
566
|
+
const applier = APPLIERS[a.write.via][a.write.type];
|
|
567
|
+
const skill = o.skills.get(a.write.via);
|
|
568
|
+
state.set(a.index, o.reconcile && skill ? await o.reconcile(skill, applier.tool, applier.build(a.write), toolCtx) : "absent");
|
|
556
569
|
}
|
|
557
|
-
const
|
|
558
|
-
if (
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
570
|
+
const pending = accepted.filter((a) => state.get(a.index) === "absent");
|
|
571
|
+
if (pending.length > 0) {
|
|
572
|
+
let verdict = null;
|
|
573
|
+
try {
|
|
574
|
+
verdict = o.screen ? await o.screen(pending.map(({ write }) => ({ ...write }))) : null;
|
|
575
|
+
}
|
|
576
|
+
catch {
|
|
577
|
+
verdict = null;
|
|
578
|
+
}
|
|
579
|
+
const allow = (verdict ?? "").trim().replace(/\.$/, "").toUpperCase() === "ALLOW";
|
|
580
|
+
if (!allow) {
|
|
581
|
+
o.logger.warn(` safe outputs: screen vetoed ${pending.length} write(s)`, { node: o.nodeId });
|
|
582
|
+
for (const { index } of pending) {
|
|
583
|
+
receipts[index] = { ...receipts[index], status: "vetoed", reason: "screen vetoed" };
|
|
584
|
+
}
|
|
585
|
+
toApply = accepted.filter((a) => state.get(a.index) !== "absent");
|
|
562
586
|
}
|
|
563
|
-
return { receipts };
|
|
564
587
|
}
|
|
565
588
|
}
|
|
566
|
-
for (let n = 0; n <
|
|
567
|
-
const { index, write } =
|
|
589
|
+
for (let n = 0; n < toApply.length; n++) {
|
|
590
|
+
const { index, write } = toApply[n];
|
|
568
591
|
const applier = APPLIERS[write.via][write.type];
|
|
569
592
|
const skill = o.skills.get(write.via);
|
|
570
593
|
const tool = skill?.tools.find((t) => t.name === applier.tool);
|
|
@@ -573,15 +596,7 @@ export async function applySafeOutputs(o) {
|
|
|
573
596
|
continue;
|
|
574
597
|
}
|
|
575
598
|
try {
|
|
576
|
-
const output = await tool.handler(applier.build(write),
|
|
577
|
-
config: o.config,
|
|
578
|
-
logger: o.logger,
|
|
579
|
-
...(o.cwd ? { cwd: o.cwd } : {}),
|
|
580
|
-
...(o.pushBranch ? { pushBranch: o.pushBranch } : {}),
|
|
581
|
-
...(o.githubApiUrl ? { githubApiUrl: o.githubApiUrl } : {}),
|
|
582
|
-
...(o.run ? { run: o.run } : {}),
|
|
583
|
-
...(o.summary ? { summary: o.summary } : {}),
|
|
584
|
-
});
|
|
599
|
+
const output = await tool.handler(applier.build(write), toolCtx);
|
|
585
600
|
const ref = refOf(output);
|
|
586
601
|
const url = urlOf(output);
|
|
587
602
|
const produced = { ...(ref !== undefined ? { ref } : {}), ...(url ? { url } : {}) };
|
|
@@ -593,7 +608,7 @@ export async function applySafeOutputs(o) {
|
|
|
593
608
|
// reason still counts as one.
|
|
594
609
|
const reason = refusalReason(output);
|
|
595
610
|
receipts[index] = { ...receipts[index], ...produced, status: "refused", reason };
|
|
596
|
-
for (const rest of
|
|
611
|
+
for (const rest of toApply.slice(n + 1)) {
|
|
597
612
|
receipts[rest.index] = { ...receipts[rest.index], status: "skipped", reason: "an earlier write was refused" };
|
|
598
613
|
}
|
|
599
614
|
return { receipts, error: `safe output ${write.type} via ${write.via} was refused: ${reason}` };
|
|
@@ -613,7 +628,7 @@ export async function applySafeOutputs(o) {
|
|
|
613
628
|
catch (err) {
|
|
614
629
|
const msg = err instanceof Error ? err.message : String(err);
|
|
615
630
|
receipts[index] = { ...receipts[index], status: "failed", reason: "apply failed" };
|
|
616
|
-
for (const rest of
|
|
631
|
+
for (const rest of toApply.slice(n + 1)) {
|
|
617
632
|
receipts[rest.index] = { ...receipts[rest.index], status: "skipped", reason: "an earlier write failed" };
|
|
618
633
|
}
|
|
619
634
|
return { receipts, error: `safe output ${write.type} via ${write.via} failed: ${msg}` };
|
package/dist/skills/linear.js
CHANGED
|
@@ -68,9 +68,11 @@ export const linear = {
|
|
|
68
68
|
},
|
|
69
69
|
required: ["query"],
|
|
70
70
|
},
|
|
71
|
+
// `withDescription` is not in the schema: only the run journal's resume
|
|
72
|
+
// probe sets it, to match a write's marker. Agent results stay as they were.
|
|
71
73
|
handler: async (input, ctx) => linearGql(`query($query: String!, $first: Int) {
|
|
72
74
|
searchIssues(term: $query, first: $first) {
|
|
73
|
-
nodes { id identifier title state { name } priority url }
|
|
75
|
+
nodes { id identifier title ${input.withDescription === true ? "description " : ""}state { name } priority url }
|
|
74
76
|
}
|
|
75
77
|
}`, { query: input.query, first: input.limit ?? 10 }, ctx),
|
|
76
78
|
},
|
package/dist/studio.js
CHANGED
|
@@ -120,7 +120,8 @@ export function applyExecutionEvent(event, nodeDataMap) {
|
|
|
120
120
|
data.exec.currentTool = undefined;
|
|
121
121
|
break;
|
|
122
122
|
}
|
|
123
|
-
case "node:exit":
|
|
123
|
+
case "node:exit":
|
|
124
|
+
case "node:amended": {
|
|
124
125
|
const data = nodeDataMap.get(event.node);
|
|
125
126
|
if (data) {
|
|
126
127
|
// NodeResult.status is already one of "success" | "failed" | "skipped";
|
package/dist/types.d.ts
CHANGED
|
@@ -3,7 +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
|
+
import type { Budget, BudgetOverrun, SpendBreakdown } from "./budget.js";
|
|
7
7
|
import type { DeciderConfig, DeciderRecord } from "./decider.js";
|
|
8
8
|
export type JSONSchema = Record<string, unknown>;
|
|
9
9
|
/** Context passed to tool handlers at execution time */
|
|
@@ -873,6 +873,16 @@ export type ExecutionEvent = {
|
|
|
873
873
|
type: "node:exit";
|
|
874
874
|
node: string;
|
|
875
875
|
result: NodeResult;
|
|
876
|
+
}
|
|
877
|
+
/**
|
|
878
|
+
* A finished node's result changed after its `node:exit` (a budget stop at
|
|
879
|
+
* the route that followed it). Not a second exit: consumers that keep each
|
|
880
|
+
* node's final result replace it; timers and step printers ignore it.
|
|
881
|
+
*/
|
|
882
|
+
| {
|
|
883
|
+
type: "node:amended";
|
|
884
|
+
node: string;
|
|
885
|
+
result: NodeResult;
|
|
876
886
|
} | {
|
|
877
887
|
type: "node:progress";
|
|
878
888
|
node: string;
|
|
@@ -951,6 +961,13 @@ export interface ExecutionTrace {
|
|
|
951
961
|
* URL, an open breaker or a spent call cap. Absent when nothing turned it off.
|
|
952
962
|
*/
|
|
953
963
|
deciderOff?: string;
|
|
964
|
+
/**
|
|
965
|
+
* Model spend by kind: agent `node` runs and the executor's own `judge`,
|
|
966
|
+
* `route`, `reflect` (retry reflection) and `screen` completions. Absent
|
|
967
|
+
* unless one of those own completions reported usage. The run budget is
|
|
968
|
+
* over the sum. `node` covers every attempt of every visit.
|
|
969
|
+
*/
|
|
970
|
+
spend?: SpendBreakdown;
|
|
954
971
|
}
|
|
955
972
|
/** Result of execute() — final node results + full execution trace */
|
|
956
973
|
export interface ExecutionResult {
|
|
@@ -1047,6 +1064,14 @@ export interface Claude {
|
|
|
1047
1064
|
timeoutMs?: number;
|
|
1048
1065
|
/** Caller-supplied abort signal. Aborting it interrupts the query. */
|
|
1049
1066
|
signal?: AbortSignal;
|
|
1067
|
+
/**
|
|
1068
|
+
* Called once with the completion's total usage, when the harness reports
|
|
1069
|
+
* it, before the outcome is known (a failed completion was still billed).
|
|
1070
|
+
* Unlike `run`'s `onUsage`, which streams cumulative reports while a node
|
|
1071
|
+
* runs, this is one report per completion. The executor counts it against
|
|
1072
|
+
* the run budget. A hook that throws never changes the result.
|
|
1073
|
+
*/
|
|
1074
|
+
onUsage?: (usage: NodeUsage) => void;
|
|
1050
1075
|
}): Promise<string | null>;
|
|
1051
1076
|
/**
|
|
1052
1077
|
* Single-completion free-text query. No tools, no output schema.
|
|
@@ -1064,6 +1089,14 @@ export interface Claude {
|
|
|
1064
1089
|
timeoutMs?: number;
|
|
1065
1090
|
/** Caller-supplied abort signal. Aborting it interrupts the query. */
|
|
1066
1091
|
signal?: AbortSignal;
|
|
1092
|
+
/**
|
|
1093
|
+
* Called once with the completion's total usage, when the harness reports
|
|
1094
|
+
* it, before the outcome is known (a failed completion was still billed).
|
|
1095
|
+
* Unlike `run`'s `onUsage`, which streams cumulative reports while a node
|
|
1096
|
+
* runs, this is one report per completion. The executor counts it against
|
|
1097
|
+
* the run budget. A hook that throws never changes the result.
|
|
1098
|
+
*/
|
|
1099
|
+
onUsage?: (usage: NodeUsage) => void;
|
|
1067
1100
|
}): Promise<string>;
|
|
1068
1101
|
}
|
|
1069
1102
|
export interface McpServerConfig {
|