@cursor/july 0.1.112 → 0.1.113
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 +4 -0
- package/dist/bin/agent-serve.js +2 -3
- package/dist/channels/checks.d.ts +10 -0
- package/dist/channels/checks.d.ts.map +1 -1
- package/dist/channels/origin/checks.d.ts +1 -1
- package/dist/channels/origin/checks.d.ts.map +1 -1
- package/dist/channels/slack/dispatch.d.ts.map +1 -1
- package/dist/channels/slack/dispatch.js +6 -2
- package/dist/docs/404.html +2 -2
- package/dist/docs/assets/{app.DxTdhphC.js → app.CAeK13eM.js} +4 -4
- package/dist/docs/assets/chunks/@localSearchIndexroot.Ck9E52Ls.js +1 -0
- package/dist/docs/assets/chunks/{VPLocalSearchBox.CR3KTF0X.js → VPLocalSearchBox.C9LbPHod.js} +1 -1
- package/dist/docs/assets/chunks/{arc.CVVqBOdS.js → arc.CmMq2zmS.js} +1 -1
- package/dist/docs/assets/chunks/{architectureDiagram-Q4EWVU46.CJHGP4ki.js → architectureDiagram-Q4EWVU46.CCXB8Uj5.js} +1 -1
- package/dist/docs/assets/chunks/{baseUniq.r7UVVRBP.js → baseUniq.CyQo6eLe.js} +1 -1
- package/dist/docs/assets/chunks/{blockDiagram-DXYQGD6D.DKmMaTre.js → blockDiagram-DXYQGD6D.JYq6w91N.js} +1 -1
- package/dist/docs/assets/chunks/{c4Diagram-AHTNJAMY.DDJsntUO.js → c4Diagram-AHTNJAMY.BRV8GPJJ.js} +1 -1
- package/dist/docs/assets/chunks/channel.BHiYmnZ4.js +1 -0
- package/dist/docs/assets/chunks/{chunk-4BX2VUAB.BK2rKt6W.js → chunk-4BX2VUAB.Bv4ooYQR.js} +1 -1
- package/dist/docs/assets/chunks/{chunk-4TB4RGXK.DRLV8RnF.js → chunk-4TB4RGXK.t4JtKPcj.js} +1 -1
- package/dist/docs/assets/chunks/{chunk-55IACEB6.DaKjxtb7.js → chunk-55IACEB6.34lCHj9Y.js} +1 -1
- package/dist/docs/assets/chunks/{chunk-EDXVE4YY.C5sPCIT1.js → chunk-EDXVE4YY.BSwrPNrt.js} +1 -1
- package/dist/docs/assets/chunks/{chunk-FMBD7UC4.CSGWyNTB.js → chunk-FMBD7UC4.Beeun-R-.js} +1 -1
- package/dist/docs/assets/chunks/{chunk-OYMX7WX6.D5tK9XEr.js → chunk-OYMX7WX6.BUUFUcJc.js} +1 -1
- package/dist/docs/assets/chunks/{chunk-QZHKN3VN.BeZGd1UZ.js → chunk-QZHKN3VN.B2XjHzN_.js} +1 -1
- package/dist/docs/assets/chunks/{chunk-YZCP3GAM.U_tfWwQR.js → chunk-YZCP3GAM.CLYG8znk.js} +1 -1
- package/dist/docs/assets/chunks/classDiagram-6PBFFD2Q.Degh8l90.js +1 -0
- package/dist/docs/assets/chunks/classDiagram-v2-HSJHXN6E.Degh8l90.js +1 -0
- package/dist/docs/assets/chunks/clone.BIywbczV.js +1 -0
- package/dist/docs/assets/chunks/{cose-bilkent-S5V4N54A.DVeRXIb6.js → cose-bilkent-S5V4N54A.DVEa6fZp.js} +1 -1
- package/dist/docs/assets/chunks/{dagre-KV5264BT.BpKJAeRZ.js → dagre-KV5264BT.C9PZQK-S.js} +1 -1
- package/dist/docs/assets/chunks/{diagram-5BDNPKRD.BQOtrd1Z.js → diagram-5BDNPKRD.DoN0uv3Y.js} +1 -1
- package/dist/docs/assets/chunks/{diagram-G4DWMVQ6.CSDAhjPI.js → diagram-G4DWMVQ6.Czv3duqx.js} +1 -1
- package/dist/docs/assets/chunks/{diagram-MMDJMWI5.Dpztst2S.js → diagram-MMDJMWI5.BinJ5kWb.js} +1 -1
- package/dist/docs/assets/chunks/{diagram-TYMM5635.qJHRizHR.js → diagram-TYMM5635.DW326M4K.js} +1 -1
- package/dist/docs/assets/chunks/{erDiagram-SMLLAGMA.vbDotH3l.js → erDiagram-SMLLAGMA.U2pR_OA7.js} +1 -1
- package/dist/docs/assets/chunks/{flowDiagram-DWJPFMVM.CqS_ZQr4.js → flowDiagram-DWJPFMVM.ByWJXeYK.js} +1 -1
- package/dist/docs/assets/chunks/{ganttDiagram-T4ZO3ILL.DTLdR4pN.js → ganttDiagram-T4ZO3ILL.OquF0Rtg.js} +1 -1
- package/dist/docs/assets/chunks/{gitGraphDiagram-UUTBAWPF.D04lnbnr.js → gitGraphDiagram-UUTBAWPF.Bpn01P7X.js} +1 -1
- package/dist/docs/assets/chunks/{graph.BlfqLJsM.js → graph.CNRB6ETL.js} +1 -1
- package/dist/docs/assets/chunks/{infoDiagram-42DDH7IO.tAooImWA.js → infoDiagram-42DDH7IO.CqhknMWi.js} +1 -1
- package/dist/docs/assets/chunks/{ishikawaDiagram-UXIWVN3A.ClUsVqnJ.js → ishikawaDiagram-UXIWVN3A.C6xpR2af.js} +1 -1
- package/dist/docs/assets/chunks/{journeyDiagram-VCZTEJTY.C3tUgyCg.js → journeyDiagram-VCZTEJTY.Cg5f7oB3.js} +1 -1
- package/dist/docs/assets/chunks/{kanban-definition-6JOO6SKY.CtD9-QCe.js → kanban-definition-6JOO6SKY.Cx9YTwlU.js} +1 -1
- package/dist/docs/assets/chunks/{layout.D38U-LnT.js → layout.ljS-wFtK.js} +1 -1
- package/dist/docs/assets/chunks/{linear.BJmssyhN.js → linear.jSxNrsFC.js} +1 -1
- package/dist/docs/assets/chunks/{min.DNgXoouU.js → min.Cum8AlQw.js} +1 -1
- package/dist/docs/assets/chunks/{mindmap-definition-QFDTVHPH.Dcp6cxeu.js → mindmap-definition-QFDTVHPH.BLiysLpe.js} +1 -1
- package/dist/docs/assets/chunks/{pieDiagram-DEJITSTG.CLDw6zIs.js → pieDiagram-DEJITSTG.BoIDyuKF.js} +1 -1
- package/dist/docs/assets/chunks/{quadrantDiagram-34T5L4WZ.CYaeeY4c.js → quadrantDiagram-34T5L4WZ.DLkpDytR.js} +1 -1
- package/dist/docs/assets/chunks/{requirementDiagram-MS252O5E.gMYuRpq2.js → requirementDiagram-MS252O5E.DqTVqSu2.js} +1 -1
- package/dist/docs/assets/chunks/{sankeyDiagram-XADWPNL6.CZqyHFbc.js → sankeyDiagram-XADWPNL6.CG_6FF7j.js} +1 -1
- package/dist/docs/assets/chunks/{sequenceDiagram-FGHM5R23.BTsCjUDN.js → sequenceDiagram-FGHM5R23.BIp9602K.js} +1 -1
- package/dist/docs/assets/chunks/{stateDiagram-FHFEXIEX.CftT9mLJ.js → stateDiagram-FHFEXIEX.COSXsD9I.js} +1 -1
- package/dist/docs/assets/chunks/stateDiagram-v2-QKLJ7IA2.qrxrbFsX.js +1 -0
- package/dist/docs/assets/chunks/{theme.B_7J9ZsV.js → theme.CXJ7PNwy.js} +2 -2
- package/dist/docs/assets/chunks/{timeline-definition-GMOUNBTQ.DbU3WUNw.js → timeline-definition-GMOUNBTQ.CXdVqkLq.js} +1 -1
- package/dist/docs/assets/chunks/{vennDiagram-DHZGUBPP.ixsq-q2u.js → vennDiagram-DHZGUBPP.CZxGuc4r.js} +1 -1
- package/dist/docs/assets/chunks/wardley-RL74JXVD.3oVgfqQk.js +162 -0
- package/dist/docs/assets/chunks/{wardleyDiagram-NUSXRM2D.C0ewvgbp.js → wardleyDiagram-NUSXRM2D.6_irCgGJ.js} +1 -1
- package/dist/docs/assets/chunks/{xychartDiagram-5P7HB3ND.nAEhF4bO.js → xychartDiagram-5P7HB3ND.TRPe92m3.js} +1 -1
- package/dist/docs/assets/{evals.md.BYvfZ-PO.js → evals.md.D3Y3Aixt.js} +2 -2
- package/dist/docs/assets/{evals.md.BYvfZ-PO.lean.js → evals.md.D3Y3Aixt.lean.js} +1 -1
- package/dist/docs/assets/guides_agent-to-agent.md.CD4T5FIl.js +41 -0
- package/dist/docs/assets/guides_agent-to-agent.md.CD4T5FIl.lean.js +1 -0
- package/dist/docs/assets/guides_jev.md.F5fAkkfN.js +189 -0
- package/dist/docs/assets/guides_jev.md.F5fAkkfN.lean.js +1 -0
- package/dist/docs/assets/{reference_connections.md.CmyrlXfY.js → reference_connections.md.Je9dMsdd.js} +1 -1
- package/dist/docs/assets/{reference_extensions.md.Ceq-qT8d.js → reference_extensions.md.Cv5aLCz_.js} +1 -1
- package/dist/docs/assets/{reference_subagents.md.BHsSMMyO.js → reference_subagents.md.Dl16gcBj.js} +2 -2
- package/dist/docs/assets/{reference_subagents.md.BHsSMMyO.lean.js → reference_subagents.md.Dl16gcBj.lean.js} +1 -1
- package/dist/docs/assets/{reference_tools.md.BYzUTeVA.js → reference_tools.md.B1dH1lpa.js} +2 -2
- package/dist/docs/assets/{reference_tools.md.BYzUTeVA.lean.js → reference_tools.md.B1dH1lpa.lean.js} +1 -1
- package/dist/docs/building-with-agents.html +35 -35
- package/dist/docs/deployment.html +36 -36
- package/dist/docs/evals.html +36 -36
- package/dist/docs/evals.md +3 -0
- package/dist/docs/guides/agent-to-agent.html +65 -54
- package/dist/docs/guides/agent-to-agent.md +73 -68
- package/dist/docs/guides/bitbucket.html +35 -35
- package/dist/docs/guides/cloud-agents.html +35 -35
- package/dist/docs/guides/convert-automation.html +35 -35
- package/dist/docs/guides/github.html +35 -35
- package/dist/docs/guides/gitlab.html +35 -35
- package/dist/docs/guides/grokbot-agents.html +35 -35
- package/dist/docs/guides/improve.html +36 -36
- package/dist/docs/guides/jev.html +248 -0
- package/dist/docs/guides/jev.md +348 -0
- package/dist/docs/guides/mcp-oauth.html +36 -36
- package/dist/docs/guides/opentelemetry.html +35 -35
- package/dist/docs/guides/slack.html +35 -35
- package/dist/docs/guides/webhooks.html +35 -35
- package/dist/docs/hashmap.json +1 -1
- package/dist/docs/hillclimbing.html +35 -35
- package/dist/docs/index.html +35 -35
- package/dist/docs/llms-full.txt +434 -68
- package/dist/docs/llms.txt +2 -1
- package/dist/docs/quickstart.html +35 -35
- package/dist/docs/reference/agent-config.html +35 -35
- package/dist/docs/reference/artifacts.html +35 -35
- package/dist/docs/reference/channels.html +35 -35
- package/dist/docs/reference/cli.html +35 -35
- package/dist/docs/reference/connections.html +37 -37
- package/dist/docs/reference/connections.md +1 -1
- package/dist/docs/reference/evals.html +35 -35
- package/dist/docs/reference/extensions.html +37 -37
- package/dist/docs/reference/extensions.md +1 -0
- package/dist/docs/reference/hooks.html +35 -35
- package/dist/docs/reference/http-api.html +35 -35
- package/dist/docs/reference/instructions.html +35 -35
- package/dist/docs/reference/playground.html +35 -35
- package/dist/docs/reference/project-layout.html +35 -35
- package/dist/docs/reference/prompt.html +35 -35
- package/dist/docs/reference/schedules.html +35 -35
- package/dist/docs/reference/sessions.html +35 -35
- package/dist/docs/reference/skills.html +35 -35
- package/dist/docs/reference/subagents.html +37 -37
- package/dist/docs/reference/subagents.md +1 -1
- package/dist/docs/reference/tools.html +37 -37
- package/dist/docs/reference/tools.md +4 -0
- package/dist/docs/templates/agentic-owners.html +35 -35
- package/dist/docs/templates/pr-autofixer.html +35 -35
- package/dist/docs/templates/security-reviewer.html +35 -35
- package/dist/docs/templates/thermo-quality-review.html +35 -35
- package/dist/docs/templates/thermo-review.html +35 -35
- package/dist/docs/templates/triage.html +35 -35
- package/dist/docs/troubleshooting.html +35 -35
- package/dist/extensions/jev/extension.d.ts +43 -0
- package/dist/extensions/jev/extension.d.ts.map +1 -0
- package/dist/extensions/jev/extension.js +47 -0
- package/dist/extensions/jev/lib/evaluate.d.ts +101 -0
- package/dist/extensions/jev/lib/evaluate.d.ts.map +1 -0
- package/dist/extensions/jev/lib/evaluate.js +167 -0
- package/dist/extensions/jev/skills/gated-write.md +25 -0
- package/dist/extensions/jev/skills/questions.md +33 -0
- package/dist/extensions/jev/tools/evaluate.d.ts +4 -0
- package/dist/extensions/jev/tools/evaluate.d.ts.map +1 -0
- package/dist/extensions/jev/tools/evaluate.js +88 -0
- package/dist/extensions.d.ts +1 -1
- package/dist/extensions.d.ts.map +1 -1
- package/dist/extensions.js +2 -0
- package/dist/internal/advertise-tools.d.ts.map +1 -1
- package/dist/internal/advertise-tools.js +6 -0
- package/dist/internal/discovery/connections.d.ts.map +1 -1
- package/dist/internal/discovery/connections.js +18 -0
- package/dist/internal/discovery/extensions.d.ts.map +1 -1
- package/dist/internal/discovery/extensions.js +8 -4
- package/dist/internal/discovery/info.d.ts.map +1 -1
- package/dist/internal/discovery/info.js +1 -0
- package/dist/internal/hosted-delivery-protocol.d.ts +3 -0
- package/dist/internal/hosted-delivery-protocol.d.ts.map +1 -1
- package/dist/internal/hosted-delivery-protocol.js +1 -0
- package/dist/internal/hosted-delivery.d.ts.map +1 -1
- package/dist/internal/hosted-delivery.js +15 -25
- package/dist/internal/hosted-execution-diag.d.ts +12 -4
- package/dist/internal/hosted-execution-diag.d.ts.map +1 -1
- package/dist/internal/hosted-execution-diag.js +26 -4
- package/dist/internal/hosted-execution-flush.d.ts +1 -0
- package/dist/internal/hosted-execution-flush.d.ts.map +1 -1
- package/dist/internal/hosted-execution-flush.js +4 -2
- package/dist/internal/server.d.ts.map +1 -1
- package/dist/internal/server.js +17 -9
- package/dist/internal/session-engine.d.ts +4 -1
- package/dist/internal/session-engine.d.ts.map +1 -1
- package/dist/internal/session-engine.js +28 -4
- package/dist/playground/assets/index-DSMAewbx.css +1 -0
- package/dist/playground/assets/{index-B1c1LeIf.js → index-De_lpFxE.js} +43 -43
- package/dist/playground/index.html +2 -2
- package/dist/types.d.ts +23 -3
- package/dist/types.d.ts.map +1 -1
- package/docs/evals.md +3 -0
- package/docs/guides/agent-to-agent.md +74 -69
- package/docs/guides/jev.md +353 -0
- package/docs/reference/connections.md +1 -1
- package/docs/reference/extensions.md +1 -0
- package/docs/reference/subagents.md +1 -1
- package/docs/reference/tools.md +4 -0
- package/package.json +8 -1
- package/src/bin/agent-serve.ts +2 -3
- package/src/channels/checks.ts +8 -0
- package/src/channels/origin/checks.ts +3 -1
- package/src/channels/slack/dispatch.ts +7 -2
- package/src/extensions/jev/extension.ts +95 -0
- package/src/extensions/jev/lib/evaluate.ts +289 -0
- package/src/extensions/jev/skills/gated-write.md +25 -0
- package/src/extensions/jev/skills/questions.md +33 -0
- package/src/extensions/jev/tools/evaluate.ts +90 -0
- package/src/extensions.ts +2 -0
- package/src/internal/advertise-tools.ts +6 -0
- package/src/internal/discovery/connections.ts +21 -0
- package/src/internal/discovery/extensions.ts +12 -4
- package/src/internal/discovery/info.ts +1 -0
- package/src/internal/hosted-delivery-protocol.ts +4 -0
- package/src/internal/hosted-delivery.ts +15 -0
- package/src/internal/hosted-execution-diag.ts +33 -4
- package/src/internal/hosted-execution-flush.ts +4 -0
- package/src/internal/server.ts +26 -12
- package/src/internal/session-engine.ts +30 -4
- package/src/types.ts +24 -3
- package/dist/docs/assets/chunks/@localSearchIndexroot.QmjDU6Jh.js +0 -1
- package/dist/docs/assets/chunks/channel.BjpoSbz_.js +0 -1
- package/dist/docs/assets/chunks/classDiagram-6PBFFD2Q.BgxOlMHw.js +0 -1
- package/dist/docs/assets/chunks/classDiagram-v2-HSJHXN6E.BgxOlMHw.js +0 -1
- package/dist/docs/assets/chunks/clone.DRuGBKZC.js +0 -1
- package/dist/docs/assets/chunks/stateDiagram-v2-QKLJ7IA2.-43J68xB.js +0 -1
- package/dist/docs/assets/chunks/wardley-RL74JXVD.WRXz-Dux.js +0 -162
- package/dist/docs/assets/guides_agent-to-agent.md.8oDTfu-E.js +0 -30
- package/dist/docs/assets/guides_agent-to-agent.md.8oDTfu-E.lean.js +0 -1
- package/dist/playground/assets/index-CK2LX3iD.css +0 -1
- /package/dist/docs/assets/{reference_connections.md.CmyrlXfY.lean.js → reference_connections.md.Je9dMsdd.lean.js} +0 -0
- /package/dist/docs/assets/{reference_extensions.md.Ceq-qT8d.lean.js → reference_extensions.md.Cv5aLCz_.lean.js} +0 -0
|
@@ -0,0 +1,289 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* System One decisions for Agent SDK host code.
|
|
3
|
+
*
|
|
4
|
+
* Chat models write. {@link evaluate} asks Jev for typed choice / score /
|
|
5
|
+
* boolean answers over shared state. Call it from a project tool, a
|
|
6
|
+
* router, or other host code after mounting `@cursor/july/extensions/jev`.
|
|
7
|
+
* Do not set Jev as the `defineAgent` turn model.
|
|
8
|
+
*
|
|
9
|
+
* ```ts
|
|
10
|
+
* import { evaluate, decide, above, needsHuman } from "@cursor/july/extensions/jev";
|
|
11
|
+
*
|
|
12
|
+
* const { answers } = await evaluate({
|
|
13
|
+
* state: draft,
|
|
14
|
+
* questions: {
|
|
15
|
+
* route: {
|
|
16
|
+
* type: "choice",
|
|
17
|
+
* instructions: "Which queue should handle this?",
|
|
18
|
+
* criteria: {
|
|
19
|
+
* billing: "charges, invoices, refunds",
|
|
20
|
+
* shipping: "delivery",
|
|
21
|
+
* technical: "bugs and outages",
|
|
22
|
+
* },
|
|
23
|
+
* },
|
|
24
|
+
* post: {
|
|
25
|
+
* type: "boolean",
|
|
26
|
+
* instructions: "Is this safe to post publicly?",
|
|
27
|
+
* },
|
|
28
|
+
* },
|
|
29
|
+
* });
|
|
30
|
+
*
|
|
31
|
+
* if (needsHuman(answers.route) || !above(answers.post, 0.85)) {
|
|
32
|
+
* return { action: "review" };
|
|
33
|
+
* }
|
|
34
|
+
* ```
|
|
35
|
+
*
|
|
36
|
+
* Auth is `TYPESAFE_API_KEY`. `model` is a TypeSafe id (`jev-latest` by
|
|
37
|
+
* default).
|
|
38
|
+
*/
|
|
39
|
+
|
|
40
|
+
/** TypeSafe model used when {@link EvaluateArgs.model} is omitted. */
|
|
41
|
+
export const DEFAULT_EVALUATION_MODEL = "jev-latest";
|
|
42
|
+
|
|
43
|
+
/** Default bar for {@link needsHuman} when the caller does not pass one. */
|
|
44
|
+
export const DEFAULT_HUMAN_THRESHOLD = 0.7;
|
|
45
|
+
|
|
46
|
+
const DEFAULT_BASE_URL = "https://api.typesafe.ai/v1";
|
|
47
|
+
|
|
48
|
+
export type EvaluationState =
|
|
49
|
+
| string
|
|
50
|
+
| Record<string, unknown>
|
|
51
|
+
| readonly unknown[];
|
|
52
|
+
|
|
53
|
+
export type BooleanQuestion = {
|
|
54
|
+
type: "boolean";
|
|
55
|
+
instructions: string;
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
export type ChoiceCriterion =
|
|
59
|
+
| string
|
|
60
|
+
| readonly string[]
|
|
61
|
+
| { includes: readonly string[] }
|
|
62
|
+
| null;
|
|
63
|
+
|
|
64
|
+
export type ChoiceQuestion<
|
|
65
|
+
C extends Record<string, ChoiceCriterion> = Record<string, ChoiceCriterion>,
|
|
66
|
+
> = {
|
|
67
|
+
type: "choice";
|
|
68
|
+
instructions: string;
|
|
69
|
+
criteria: C;
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
export type ScoreQuestion = {
|
|
73
|
+
type: "score";
|
|
74
|
+
instructions: string;
|
|
75
|
+
criteria: readonly string[];
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
export type EvaluationQuestion =
|
|
79
|
+
| BooleanQuestion
|
|
80
|
+
| ChoiceQuestion
|
|
81
|
+
| ScoreQuestion;
|
|
82
|
+
|
|
83
|
+
export type QuestionMap = Record<string, EvaluationQuestion>;
|
|
84
|
+
|
|
85
|
+
export type BooleanAnswer = {
|
|
86
|
+
type: "boolean";
|
|
87
|
+
probability: number;
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
export type ChoiceAnswer<
|
|
91
|
+
C extends Record<string, unknown> = Record<string, unknown>,
|
|
92
|
+
> = {
|
|
93
|
+
type: "choice";
|
|
94
|
+
choice: keyof C & string;
|
|
95
|
+
probabilities: { [K in keyof C]: number };
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
export type ScoreAnswer = {
|
|
99
|
+
type: "score";
|
|
100
|
+
score: number;
|
|
101
|
+
probabilities: Record<string, number>;
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
export type EvaluationAnswer = BooleanAnswer | ChoiceAnswer | ScoreAnswer;
|
|
105
|
+
|
|
106
|
+
export type AnswerFor<Q> = Q extends BooleanQuestion
|
|
107
|
+
? BooleanAnswer
|
|
108
|
+
: Q extends ChoiceQuestion<infer C>
|
|
109
|
+
? ChoiceAnswer<C>
|
|
110
|
+
: Q extends ScoreQuestion
|
|
111
|
+
? ScoreAnswer
|
|
112
|
+
: never;
|
|
113
|
+
|
|
114
|
+
export type AnswersFor<Q extends QuestionMap> = {
|
|
115
|
+
[K in keyof Q]: AnswerFor<Q[K]>;
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
export type EvaluateResult<Q extends QuestionMap = QuestionMap> = {
|
|
119
|
+
answers: AnswersFor<Q>;
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
export type EvaluateArgs<Q extends QuestionMap = QuestionMap> = {
|
|
123
|
+
model?: string;
|
|
124
|
+
state: EvaluationState;
|
|
125
|
+
questions: Q;
|
|
126
|
+
apiKey?: string;
|
|
127
|
+
baseUrl?: string;
|
|
128
|
+
fetch?: typeof globalThis.fetch;
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
type WireQuestion =
|
|
132
|
+
| { type: "noul"; instructions: string }
|
|
133
|
+
| {
|
|
134
|
+
type: "choice";
|
|
135
|
+
instructions: string;
|
|
136
|
+
criteria: ChoiceQuestion["criteria"];
|
|
137
|
+
}
|
|
138
|
+
| { type: "score"; instructions: string; criteria: readonly string[] };
|
|
139
|
+
|
|
140
|
+
function resolveApiKey(explicit: string | undefined): string {
|
|
141
|
+
const key = (explicit ?? process.env.TYPESAFE_API_KEY)?.trim();
|
|
142
|
+
if (key === undefined || key === "") {
|
|
143
|
+
throw new Error("evaluate requires TYPESAFE_API_KEY");
|
|
144
|
+
}
|
|
145
|
+
return key;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
function toWireQuestion(question: EvaluationQuestion): WireQuestion {
|
|
149
|
+
if (question.type === "boolean") {
|
|
150
|
+
return { type: "noul", instructions: question.instructions };
|
|
151
|
+
}
|
|
152
|
+
return question;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
function asRecord(value: unknown, label: string): Record<string, unknown> {
|
|
156
|
+
if (value === null || typeof value !== "object") {
|
|
157
|
+
throw new Error(`evaluate ${label}`);
|
|
158
|
+
}
|
|
159
|
+
return value as Record<string, unknown>;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
function decodeAnswer(
|
|
163
|
+
question: EvaluationQuestion,
|
|
164
|
+
raw: unknown
|
|
165
|
+
): EvaluationAnswer {
|
|
166
|
+
const value = asRecord(raw, "answer is missing");
|
|
167
|
+
if (question.type === "boolean") {
|
|
168
|
+
if (typeof value.noul !== "number") {
|
|
169
|
+
throw new Error("evaluate noul is not a number");
|
|
170
|
+
}
|
|
171
|
+
return { type: "boolean", probability: value.noul };
|
|
172
|
+
}
|
|
173
|
+
if (question.type === "choice") {
|
|
174
|
+
if (typeof value.choice !== "string") {
|
|
175
|
+
throw new Error("evaluate choice is not a string");
|
|
176
|
+
}
|
|
177
|
+
return {
|
|
178
|
+
type: "choice",
|
|
179
|
+
choice: value.choice,
|
|
180
|
+
probabilities: asRecord(
|
|
181
|
+
value.probabilities,
|
|
182
|
+
"choice probabilities are missing"
|
|
183
|
+
) as ChoiceAnswer["probabilities"],
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
if (typeof value.score !== "number") {
|
|
187
|
+
throw new Error("evaluate score is not a number");
|
|
188
|
+
}
|
|
189
|
+
return {
|
|
190
|
+
type: "score",
|
|
191
|
+
score: value.score,
|
|
192
|
+
probabilities: asRecord(
|
|
193
|
+
value.probabilities,
|
|
194
|
+
"score probabilities are missing"
|
|
195
|
+
) as ScoreAnswer["probabilities"],
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
async function postSystemOne(args: {
|
|
200
|
+
url: string;
|
|
201
|
+
apiKey: string;
|
|
202
|
+
body: {
|
|
203
|
+
model: string;
|
|
204
|
+
state: EvaluationState;
|
|
205
|
+
questions: Record<string, WireQuestion>;
|
|
206
|
+
};
|
|
207
|
+
fetch: typeof globalThis.fetch;
|
|
208
|
+
}): Promise<Record<string, unknown>> {
|
|
209
|
+
const response = await args.fetch(args.url, {
|
|
210
|
+
method: "POST",
|
|
211
|
+
headers: {
|
|
212
|
+
Authorization: `Bearer ${args.apiKey}`,
|
|
213
|
+
"Content-Type": "application/json",
|
|
214
|
+
},
|
|
215
|
+
body: JSON.stringify(args.body),
|
|
216
|
+
});
|
|
217
|
+
const text = await response.text();
|
|
218
|
+
let parsed: unknown;
|
|
219
|
+
try {
|
|
220
|
+
parsed = text.length === 0 ? {} : JSON.parse(text);
|
|
221
|
+
} catch {
|
|
222
|
+
throw new Error(`evaluate returned non-JSON (${response.status})`);
|
|
223
|
+
}
|
|
224
|
+
if (!response.ok) {
|
|
225
|
+
throw new Error(
|
|
226
|
+
`evaluate failed (${response.status}): ${text.slice(0, 240)}`
|
|
227
|
+
);
|
|
228
|
+
}
|
|
229
|
+
return asRecord(
|
|
230
|
+
asRecord(parsed, "response is not an object").answers,
|
|
231
|
+
"response is missing answers"
|
|
232
|
+
);
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
/** Ask Jev for typed answers over one state. */
|
|
236
|
+
export async function evaluate<const Q extends QuestionMap>(
|
|
237
|
+
args: EvaluateArgs<Q>
|
|
238
|
+
): Promise<EvaluateResult<Q>> {
|
|
239
|
+
const questions: Record<string, WireQuestion> = {};
|
|
240
|
+
for (const [id, question] of Object.entries(args.questions)) {
|
|
241
|
+
questions[id] = toWireQuestion(question);
|
|
242
|
+
}
|
|
243
|
+
const raw = await postSystemOne({
|
|
244
|
+
url: `${(args.baseUrl ?? DEFAULT_BASE_URL).replace(/\/$/u, "")}/systemone`,
|
|
245
|
+
apiKey: resolveApiKey(args.apiKey),
|
|
246
|
+
fetch: args.fetch ?? globalThis.fetch,
|
|
247
|
+
body: {
|
|
248
|
+
model: args.model ?? DEFAULT_EVALUATION_MODEL,
|
|
249
|
+
state: args.state,
|
|
250
|
+
questions,
|
|
251
|
+
},
|
|
252
|
+
});
|
|
253
|
+
const answers = {} as AnswersFor<Q>;
|
|
254
|
+
for (const id of Object.keys(args.questions) as (keyof Q & string)[]) {
|
|
255
|
+
answers[id] = decodeAnswer(
|
|
256
|
+
args.questions[id],
|
|
257
|
+
raw[id]
|
|
258
|
+
) as AnswersFor<Q>[typeof id];
|
|
259
|
+
}
|
|
260
|
+
return { answers };
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
/** Same as {@link evaluate}, returning only `answers`. */
|
|
264
|
+
export async function decide<const Q extends QuestionMap>(
|
|
265
|
+
args: EvaluateArgs<Q>
|
|
266
|
+
): Promise<AnswersFor<Q>> {
|
|
267
|
+
const result = await evaluate(args);
|
|
268
|
+
return result.answers;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
export function above(
|
|
272
|
+
answer: BooleanAnswer | ScoreAnswer,
|
|
273
|
+
threshold: number
|
|
274
|
+
): boolean {
|
|
275
|
+
if (answer.type === "boolean") {
|
|
276
|
+
return answer.probability >= threshold;
|
|
277
|
+
}
|
|
278
|
+
return answer.score >= threshold;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
export function needsHuman(
|
|
282
|
+
answer: BooleanAnswer | ChoiceAnswer,
|
|
283
|
+
threshold: number = DEFAULT_HUMAN_THRESHOLD
|
|
284
|
+
): boolean {
|
|
285
|
+
if (answer.type === "boolean") {
|
|
286
|
+
return answer.probability < threshold;
|
|
287
|
+
}
|
|
288
|
+
return answer.probabilities[answer.choice] < threshold;
|
|
289
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "Gate a channel wake, approval, or review comment on Jev by calling decide, then continuing or holding."
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# Gating a GitHub write on Jev
|
|
6
|
+
|
|
7
|
+
Channel hooks can call `decide` before they start a model turn. Return
|
|
8
|
+
`null` when the answer misses the bar; return `{ auth }` or `{ task }`
|
|
9
|
+
when the agent should run.
|
|
10
|
+
|
|
11
|
+
This extension's `evaluate` tool does not write to GitHub. When an
|
|
12
|
+
approval or a review comment must follow the judgment, add a server tool
|
|
13
|
+
in this project that calls `decide`, then writes or holds in the same
|
|
14
|
+
`execute`.
|
|
15
|
+
|
|
16
|
+
```ts
|
|
17
|
+
import { above, decide, needsHuman } from "@cursor/july/extensions/jev";
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
Hold when `needsHuman` is true or `above` misses the bar. Very low and
|
|
21
|
+
low risk can approve; medium and above hold. A finding comment posts
|
|
22
|
+
only when the draft is a real bug. Calibrate those numbers on labeled
|
|
23
|
+
pull requests from this workflow. Pass the pull request title, summary,
|
|
24
|
+
and draft, not the checkout. Return without writing when
|
|
25
|
+
`ctx.session.purpose === "eval"`.
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "Ask Jev for a risk tier, a finding judgment, or a score when you are not about to approve or comment."
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# Asking Jev
|
|
6
|
+
|
|
7
|
+
Call this extension's `evaluate` tool when you need a typed judgment over
|
|
8
|
+
a pull request and you are not about to approve or comment. It returns
|
|
9
|
+
answers only. The tool appears as `<namespace>__evaluate`.
|
|
10
|
+
|
|
11
|
+
## Questions
|
|
12
|
+
|
|
13
|
+
Pass `state` (the pull request title, a short summary of the diff, and
|
|
14
|
+
any draft finding) and one or more questions. Each question has an `id`,
|
|
15
|
+
a `type`, and `instructions`.
|
|
16
|
+
|
|
17
|
+
- `boolean`: probability of true between 0 and 1
|
|
18
|
+
- `choice`: `criteria` maps each option name to a short description; the
|
|
19
|
+
answer names one option
|
|
20
|
+
- `score`: `criteria` from lowest to highest; the answer is a number
|
|
21
|
+
along that rubric
|
|
22
|
+
|
|
23
|
+
`instructions` can set the decision, who the review is for, and which
|
|
24
|
+
evidence to weigh. Pass the pull request summary, not the checkout.
|
|
25
|
+
|
|
26
|
+
## Reading answers
|
|
27
|
+
|
|
28
|
+
A boolean answer has `probability`. A choice has `choice` and
|
|
29
|
+
`probabilities`. A score has `score` and `probabilities`.
|
|
30
|
+
|
|
31
|
+
When an approval or a review comment must follow the judgment, use a
|
|
32
|
+
project tool that calls `decide` itself. Do not treat these answers as
|
|
33
|
+
a GitHub write.
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { defineTool } from "../../../tools.js";
|
|
3
|
+
import type { ToolDefinition } from "../../../types.js";
|
|
4
|
+
import extension from "../extension.js";
|
|
5
|
+
import { evaluate, type QuestionMap } from "../lib/evaluate.js";
|
|
6
|
+
|
|
7
|
+
const booleanQuestion = z.object({
|
|
8
|
+
id: z.string().min(1),
|
|
9
|
+
type: z.literal("boolean"),
|
|
10
|
+
instructions: z.string().min(1),
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
const choiceQuestion = z.object({
|
|
14
|
+
id: z.string().min(1),
|
|
15
|
+
type: z.literal("choice"),
|
|
16
|
+
instructions: z.string().min(1),
|
|
17
|
+
criteria: z.record(z.string()),
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
const scoreQuestion = z.object({
|
|
21
|
+
id: z.string().min(1),
|
|
22
|
+
type: z.literal("score"),
|
|
23
|
+
instructions: z.string().min(1),
|
|
24
|
+
criteria: z.array(z.string()).min(2),
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
const question = z.discriminatedUnion("type", [
|
|
28
|
+
booleanQuestion,
|
|
29
|
+
choiceQuestion,
|
|
30
|
+
scoreQuestion,
|
|
31
|
+
]);
|
|
32
|
+
|
|
33
|
+
function toQuestionMap(questions: z.infer<typeof question>[]): QuestionMap {
|
|
34
|
+
const map: QuestionMap = {};
|
|
35
|
+
for (const item of questions) {
|
|
36
|
+
if (item.type === "boolean") {
|
|
37
|
+
map[item.id] = {
|
|
38
|
+
type: "boolean",
|
|
39
|
+
instructions: item.instructions,
|
|
40
|
+
};
|
|
41
|
+
} else if (item.type === "choice") {
|
|
42
|
+
map[item.id] = {
|
|
43
|
+
type: "choice",
|
|
44
|
+
instructions: item.instructions,
|
|
45
|
+
criteria: item.criteria,
|
|
46
|
+
};
|
|
47
|
+
} else {
|
|
48
|
+
map[item.id] = {
|
|
49
|
+
type: "score",
|
|
50
|
+
instructions: item.instructions,
|
|
51
|
+
criteria: item.criteria,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
return map;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const evaluateTool: ToolDefinition = defineTool({
|
|
59
|
+
description:
|
|
60
|
+
"Ask Jev for typed boolean, choice, or score answers over one state. Returns answers only; it does not post, assign, or merge.",
|
|
61
|
+
effect: "read",
|
|
62
|
+
inputSchema: z
|
|
63
|
+
.object({
|
|
64
|
+
state: z
|
|
65
|
+
.union([z.string(), z.array(z.unknown()), z.record(z.unknown())])
|
|
66
|
+
.describe(
|
|
67
|
+
"Ticket, pull request, or other state Jev should judge. Not repo source."
|
|
68
|
+
),
|
|
69
|
+
questions: z
|
|
70
|
+
.array(question)
|
|
71
|
+
.min(1)
|
|
72
|
+
.describe("One or more typed questions over the same state."),
|
|
73
|
+
})
|
|
74
|
+
.refine(
|
|
75
|
+
input =>
|
|
76
|
+
new Set(input.questions.map(item => item.id)).size ===
|
|
77
|
+
input.questions.length,
|
|
78
|
+
"questions must not repeat an id"
|
|
79
|
+
),
|
|
80
|
+
async execute(input) {
|
|
81
|
+
return evaluate({
|
|
82
|
+
state: input.state,
|
|
83
|
+
questions: toQuestionMap(input.questions),
|
|
84
|
+
apiKey: extension.config.apiKey,
|
|
85
|
+
model: extension.config.model,
|
|
86
|
+
});
|
|
87
|
+
},
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
export default evaluateTool;
|
package/src/extensions.ts
CHANGED
|
@@ -87,6 +87,7 @@ export type {
|
|
|
87
87
|
DisabledToolDefinition,
|
|
88
88
|
DiscoveredExtension,
|
|
89
89
|
Extension,
|
|
90
|
+
ExtensionContributionSelection,
|
|
90
91
|
ExtensionDeclaration,
|
|
91
92
|
ExtensionMount,
|
|
92
93
|
ExtensionOptions,
|
|
@@ -105,6 +106,7 @@ export function defineExtension<TConfig = undefined, TInput = TConfig>(
|
|
|
105
106
|
return brandDefinition("extension", {
|
|
106
107
|
extension: handle,
|
|
107
108
|
config: parsed,
|
|
109
|
+
contributions: options.contributions?.(parsed),
|
|
108
110
|
});
|
|
109
111
|
};
|
|
110
112
|
const handle = Object.defineProperties(mount, {
|
|
@@ -163,6 +163,9 @@ export async function resolveAdvertisedTools(args: {
|
|
|
163
163
|
args.onConnectionError(connection.name, listing.error);
|
|
164
164
|
continue;
|
|
165
165
|
}
|
|
166
|
+
if (connection.optional === true) {
|
|
167
|
+
continue;
|
|
168
|
+
}
|
|
166
169
|
throw new Error(
|
|
167
170
|
`Failed to list tools on advertised connection "${connection.name}": ${describeError(listing.error)}`,
|
|
168
171
|
{ cause: listing.error }
|
|
@@ -181,6 +184,9 @@ export async function resolveAdvertisedTools(args: {
|
|
|
181
184
|
args.onConnectionError(connection.name, error);
|
|
182
185
|
continue;
|
|
183
186
|
}
|
|
187
|
+
if (connection.optional === true) {
|
|
188
|
+
continue;
|
|
189
|
+
}
|
|
184
190
|
throw error;
|
|
185
191
|
}
|
|
186
192
|
const intended = listed.filter(
|
|
@@ -311,6 +311,26 @@ export async function compileConnection(
|
|
|
311
311
|
});
|
|
312
312
|
return undefined;
|
|
313
313
|
}
|
|
314
|
+
if (
|
|
315
|
+
connection.optional !== undefined &&
|
|
316
|
+
typeof connection.optional !== "boolean"
|
|
317
|
+
) {
|
|
318
|
+
ctx.diagnostics.push({
|
|
319
|
+
severity: "error",
|
|
320
|
+
path: displayPath(ctx, entryPath),
|
|
321
|
+
message: "MCP connection `optional` must be a boolean.",
|
|
322
|
+
});
|
|
323
|
+
return undefined;
|
|
324
|
+
}
|
|
325
|
+
if (connection.optional === true && connection.advertiseTools !== true) {
|
|
326
|
+
ctx.diagnostics.push({
|
|
327
|
+
severity: "error",
|
|
328
|
+
path: displayPath(ctx, entryPath),
|
|
329
|
+
message:
|
|
330
|
+
"MCP connection `optional` skips advertised listing failures; set `advertiseTools: true` or drop `optional`.",
|
|
331
|
+
});
|
|
332
|
+
return undefined;
|
|
333
|
+
}
|
|
314
334
|
const parsedEffects = parseConnectionEffects(connection.effects);
|
|
315
335
|
if (!parsedEffects.ok) {
|
|
316
336
|
ctx.diagnostics.push({
|
|
@@ -471,6 +491,7 @@ export async function compileConnection(
|
|
|
471
491
|
description: connection.description,
|
|
472
492
|
auth: connection.auth,
|
|
473
493
|
advertiseTools: connection.advertiseTools,
|
|
494
|
+
optional: connection.optional,
|
|
474
495
|
effects: parsedEffects.value,
|
|
475
496
|
tools: parsedTools.value,
|
|
476
497
|
disallowedTools: parsedDisallowed.value,
|
|
@@ -15,6 +15,7 @@ import type {
|
|
|
15
15
|
DiscoveredSchedule,
|
|
16
16
|
DiscoveredSkill,
|
|
17
17
|
DiscoveredTool,
|
|
18
|
+
ExtensionContributionSelection,
|
|
18
19
|
ExtensionMount,
|
|
19
20
|
ResolvedAgent,
|
|
20
21
|
SeedFile,
|
|
@@ -450,18 +451,25 @@ async function readExtensionTree(
|
|
|
450
451
|
seedFiles: [],
|
|
451
452
|
};
|
|
452
453
|
}
|
|
453
|
-
return readNativeTree(ctx, root);
|
|
454
|
+
return readNativeTree(ctx, root, mount.contributions);
|
|
454
455
|
}
|
|
455
456
|
|
|
456
457
|
async function readNativeTree(
|
|
457
458
|
ctx: DiscoveryContext,
|
|
458
|
-
root: string
|
|
459
|
+
root: string,
|
|
460
|
+
contributions?: ExtensionContributionSelection
|
|
459
461
|
): Promise<ExtensionTree> {
|
|
460
462
|
await warnAgentRootOnlySlots(ctx, root);
|
|
461
463
|
const connections = await loadConnections(ctx, join(root, "mcp-connections"));
|
|
462
464
|
return {
|
|
463
|
-
tools:
|
|
464
|
-
|
|
465
|
+
tools:
|
|
466
|
+
contributions?.tools === false
|
|
467
|
+
? []
|
|
468
|
+
: await loadTools(ctx, join(root, "tools")),
|
|
469
|
+
skills:
|
|
470
|
+
contributions?.skills === false
|
|
471
|
+
? []
|
|
472
|
+
: await loadSkills(ctx, join(root, "skills")),
|
|
465
473
|
connections,
|
|
466
474
|
hostConnections: await loadHostConnections(ctx, root, connections),
|
|
467
475
|
overlaidServers: [],
|
|
@@ -80,6 +80,7 @@ export function projectInfo(project: AgentProject): AgentProjectInfo {
|
|
|
80
80
|
name: connection.name,
|
|
81
81
|
transport: connectionTransportLabel(connection.transport),
|
|
82
82
|
advertiseTools: connection.advertiseTools,
|
|
83
|
+
optional: connection.optional,
|
|
83
84
|
effects: connection.effects,
|
|
84
85
|
tools: connection.tools,
|
|
85
86
|
disallowedTools: connection.disallowedTools,
|
|
@@ -149,6 +149,8 @@ export type HostedGuestError = {
|
|
|
149
149
|
classification: HostedFailureClassification;
|
|
150
150
|
message?: string;
|
|
151
151
|
turnStatus?: string;
|
|
152
|
+
/** Runner/SDK code (`unknown`, `canceled`, …). Not the human message. */
|
|
153
|
+
errorCode?: string;
|
|
152
154
|
};
|
|
153
155
|
|
|
154
156
|
/**
|
|
@@ -162,6 +164,7 @@ export function hostedGuestErrorResponse(input: {
|
|
|
162
164
|
retry: HostedGuestRetryDisposition;
|
|
163
165
|
message?: string;
|
|
164
166
|
turnStatus?: string;
|
|
167
|
+
errorCode?: string;
|
|
165
168
|
}): Response {
|
|
166
169
|
const body: HostedGuestError = {
|
|
167
170
|
ok: false,
|
|
@@ -170,6 +173,7 @@ export function hostedGuestErrorResponse(input: {
|
|
|
170
173
|
classification: hostedFailureClassification(input.error),
|
|
171
174
|
message: input.message,
|
|
172
175
|
turnStatus: input.turnStatus,
|
|
176
|
+
errorCode: input.errorCode,
|
|
173
177
|
};
|
|
174
178
|
return Response.json(body, { status: input.status });
|
|
175
179
|
}
|
|
@@ -14,6 +14,7 @@ import {
|
|
|
14
14
|
createDeferredChannelSession,
|
|
15
15
|
DeferredChannelSessionError,
|
|
16
16
|
} from "./deferred-channel-session.js";
|
|
17
|
+
import { describeErrorCode } from "./describe-error.js";
|
|
17
18
|
import {
|
|
18
19
|
formatGuestNetworkServerTiming,
|
|
19
20
|
GUEST_CONNECT_STALLED,
|
|
@@ -889,6 +890,7 @@ export function registerHostedDeliveryRoute(input: {
|
|
|
889
890
|
| ReturnType<typeof abortReasonFromTurnStatus>
|
|
890
891
|
| "execute_throw";
|
|
891
892
|
failureCode?: string;
|
|
893
|
+
errorCode?: string;
|
|
892
894
|
error?: unknown;
|
|
893
895
|
}): Promise<void> => {
|
|
894
896
|
const classification =
|
|
@@ -911,6 +913,9 @@ export function registerHostedDeliveryRoute(input: {
|
|
|
911
913
|
? {}
|
|
912
914
|
: { abortReason: fields.abortReason }),
|
|
913
915
|
failureCode: fields.failureCode,
|
|
916
|
+
...(fields.errorCode === undefined
|
|
917
|
+
? {}
|
|
918
|
+
: { errorCode: fields.errorCode }),
|
|
914
919
|
classification,
|
|
915
920
|
...(fields.error === undefined ? {} : { error: fields.error }),
|
|
916
921
|
});
|
|
@@ -1004,6 +1009,9 @@ export function registerHostedDeliveryRoute(input: {
|
|
|
1004
1009
|
outcome.cancellationReason
|
|
1005
1010
|
),
|
|
1006
1011
|
failureCode: hostedFailure?.error,
|
|
1012
|
+
...(outcome.errorCode === undefined
|
|
1013
|
+
? {}
|
|
1014
|
+
: { errorCode: outcome.errorCode }),
|
|
1007
1015
|
});
|
|
1008
1016
|
const reply =
|
|
1009
1017
|
hostedFailure !== undefined
|
|
@@ -1018,6 +1026,9 @@ export function registerHostedDeliveryRoute(input: {
|
|
|
1018
1026
|
),
|
|
1019
1027
|
turnStatus: outcome.status,
|
|
1020
1028
|
message: outcome.errorMessage,
|
|
1029
|
+
...(outcome.errorCode === undefined
|
|
1030
|
+
? {}
|
|
1031
|
+
: { errorCode: outcome.errorCode }),
|
|
1021
1032
|
},
|
|
1022
1033
|
}
|
|
1023
1034
|
: {
|
|
@@ -1047,6 +1058,7 @@ export function registerHostedDeliveryRoute(input: {
|
|
|
1047
1058
|
sessionId,
|
|
1048
1059
|
execution.sessionPublicId
|
|
1049
1060
|
);
|
|
1061
|
+
const thrownErrorCode = describeErrorCode(error);
|
|
1050
1062
|
await writeDiag({
|
|
1051
1063
|
sessionId: "",
|
|
1052
1064
|
turnStatus: "error",
|
|
@@ -1055,6 +1067,9 @@ export function registerHostedDeliveryRoute(input: {
|
|
|
1055
1067
|
abortReason: "execute_throw",
|
|
1056
1068
|
failureCode: "internal_error",
|
|
1057
1069
|
error,
|
|
1070
|
+
...(thrownErrorCode === undefined
|
|
1071
|
+
? {}
|
|
1072
|
+
: { errorCode: thrownErrorCode }),
|
|
1058
1073
|
});
|
|
1059
1074
|
const endedAt = hostedExecutionNow();
|
|
1060
1075
|
// Preserve completion/drain marks when the failure happened
|