@exaudeus/workrail 3.9.2 → 3.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/application/services/validation-engine.js +134 -0
- package/dist/application/services/workflow-compiler.js +54 -0
- package/dist/manifest.json +150 -78
- package/dist/mcp/handlers/v2-advance-core/assessment-consequences.d.ts +14 -0
- package/dist/mcp/handlers/v2-advance-core/assessment-consequences.js +27 -0
- package/dist/mcp/handlers/v2-advance-core/assessment-validation.d.ts +16 -0
- package/dist/mcp/handlers/v2-advance-core/assessment-validation.js +213 -0
- package/dist/mcp/handlers/v2-advance-core/event-builders.d.ts +1 -0
- package/dist/mcp/handlers/v2-advance-core/event-builders.js +3 -2
- package/dist/mcp/handlers/v2-advance-core/index.js +23 -8
- package/dist/mcp/handlers/v2-advance-core/input-validation.d.ts +9 -1
- package/dist/mcp/handlers/v2-advance-core/input-validation.js +22 -2
- package/dist/mcp/handlers/v2-advance-core/outcome-blocked.d.ts +2 -0
- package/dist/mcp/handlers/v2-advance-core/outcome-blocked.js +69 -19
- package/dist/mcp/handlers/v2-advance-core/outcome-success.js +22 -0
- package/dist/mcp/handlers/v2-execution/replay.js +7 -0
- package/dist/mcp/output-schemas.d.ts +156 -42
- package/dist/mcp/output-schemas.js +17 -1
- package/dist/mcp/v2-response-formatter.js +7 -1
- package/dist/types/workflow-definition.d.ts +26 -0
- package/dist/types/workflow-definition.js +16 -1
- package/dist/v2/durable-core/constants.d.ts +4 -1
- package/dist/v2/durable-core/constants.js +5 -2
- package/dist/v2/durable-core/domain/assessment-consequence-event-builder.d.ts +23 -0
- package/dist/v2/durable-core/domain/assessment-consequence-event-builder.js +36 -0
- package/dist/v2/durable-core/domain/assessment-record.d.ts +12 -0
- package/dist/v2/durable-core/domain/assessment-record.js +2 -0
- package/dist/v2/durable-core/domain/assessment-recorded-event-builder.d.ts +22 -0
- package/dist/v2/durable-core/domain/assessment-recorded-event-builder.js +38 -0
- package/dist/v2/durable-core/domain/blocked-node-builder.d.ts +1 -1
- package/dist/v2/durable-core/domain/blocked-node-builder.js +8 -0
- package/dist/v2/durable-core/domain/blocking-decision.d.ts +6 -0
- package/dist/v2/durable-core/domain/blocking-decision.js +15 -0
- package/dist/v2/durable-core/domain/prompt-renderer.js +53 -67
- package/dist/v2/durable-core/domain/reason-model.d.ts +12 -2
- package/dist/v2/durable-core/domain/reason-model.js +27 -2
- package/dist/v2/durable-core/domain/retrieval-contract.d.ts +105 -0
- package/dist/v2/durable-core/domain/retrieval-contract.js +310 -0
- package/dist/v2/durable-core/domain/risk-policy-guardrails.js +1 -0
- package/dist/v2/durable-core/domain/validation-criteria-validator.d.ts +1 -0
- package/dist/v2/durable-core/domain/validation-criteria-validator.js +11 -0
- package/dist/v2/durable-core/schemas/artifacts/assessment.d.ts +55 -0
- package/dist/v2/durable-core/schemas/artifacts/assessment.js +29 -0
- package/dist/v2/durable-core/schemas/artifacts/index.d.ts +2 -1
- package/dist/v2/durable-core/schemas/artifacts/index.js +8 -1
- package/dist/v2/durable-core/schemas/compiled-workflow/index.d.ts +24 -24
- package/dist/v2/durable-core/schemas/execution-snapshot/blocked-snapshot.d.ts +141 -21
- package/dist/v2/durable-core/schemas/execution-snapshot/blocked-snapshot.js +10 -1
- package/dist/v2/durable-core/schemas/execution-snapshot/execution-snapshot.v1.d.ts +729 -171
- package/dist/v2/durable-core/schemas/export-bundle/index.d.ts +1442 -202
- package/dist/v2/durable-core/schemas/session/events.d.ts +231 -8
- package/dist/v2/durable-core/schemas/session/events.js +36 -0
- package/dist/v2/durable-core/schemas/session/gaps.d.ts +2 -2
- package/dist/v2/projections/assessment-consequences.d.ts +19 -0
- package/dist/v2/projections/assessment-consequences.js +33 -0
- package/dist/v2/projections/assessments.d.ts +21 -0
- package/dist/v2/projections/assessments.js +35 -0
- package/dist/v2/projections/resume-ranking.d.ts +1 -0
- package/dist/v2/projections/resume-ranking.js +12 -24
- package/package.json +1 -1
- package/spec/workflow.schema.json +110 -0
- package/workflows/bug-investigation.agentic.v2.json +28 -2
- package/workflows/mr-review-workflow.agentic.v2.json +10 -5
- package/workflows/test-artifact-loop-control.json +28 -2
|
@@ -5,6 +5,7 @@ exports.toPendingStep = toPendingStep;
|
|
|
5
5
|
const zod_1 = require("zod");
|
|
6
6
|
const state_js_1 = require("../domain/execution/state.js");
|
|
7
7
|
const token_patterns_js_1 = require("../v2/durable-core/tokens/token-patterns.js");
|
|
8
|
+
const constants_js_1 = require("../v2/durable-core/constants.js");
|
|
8
9
|
const JsonPrimitiveSchema = zod_1.z.union([zod_1.z.string(), zod_1.z.number(), zod_1.z.boolean(), zod_1.z.null()]);
|
|
9
10
|
exports.JsonValueSchema = zod_1.z.lazy(() => zod_1.z.union([JsonPrimitiveSchema, zod_1.z.array(exports.JsonValueSchema), zod_1.z.record(exports.JsonValueSchema)]));
|
|
10
11
|
exports.WorkflowSummarySchema = zod_1.z.object({
|
|
@@ -143,6 +144,11 @@ const V2BlockerPointerSchema = zod_1.z.discriminatedUnion('kind', [
|
|
|
143
144
|
zod_1.z.object({ kind: zod_1.z.literal('context_budget') }),
|
|
144
145
|
zod_1.z.object({ kind: zod_1.z.literal('output_contract'), contractRef: zod_1.z.string().min(1) }),
|
|
145
146
|
zod_1.z.object({ kind: zod_1.z.literal('capability'), capability: zod_1.z.enum(['delegation', 'web_browsing']) }),
|
|
147
|
+
zod_1.z.object({
|
|
148
|
+
kind: zod_1.z.literal('assessment_dimension'),
|
|
149
|
+
assessmentId: zod_1.z.string().min(1),
|
|
150
|
+
dimensionId: zod_1.z.string().min(1).regex(DELIMITER_SAFE_ID_PATTERN, 'dimensionId must be delimiter-safe: [a-z0-9_-]+'),
|
|
151
|
+
}),
|
|
146
152
|
zod_1.z.object({
|
|
147
153
|
kind: zod_1.z.literal('workflow_step'),
|
|
148
154
|
stepId: zod_1.z.string().min(1).regex(DELIMITER_SAFE_ID_PATTERN, 'stepId must be delimiter-safe: [a-z0-9_-]+'),
|
|
@@ -153,6 +159,7 @@ const V2BlockerSchema = zod_1.z.object({
|
|
|
153
159
|
'USER_ONLY_DEPENDENCY',
|
|
154
160
|
'MISSING_REQUIRED_OUTPUT',
|
|
155
161
|
'INVALID_REQUIRED_OUTPUT',
|
|
162
|
+
'ASSESSMENT_FOLLOWUP_REQUIRED',
|
|
156
163
|
'MISSING_REQUIRED_NOTES',
|
|
157
164
|
'MISSING_CONTEXT_KEY',
|
|
158
165
|
'CONTEXT_BUDGET_EXCEEDED',
|
|
@@ -194,6 +201,9 @@ exports.V2BlockerReportSchema = zod_1.z
|
|
|
194
201
|
case 'capability':
|
|
195
202
|
ptrStable = p.capability;
|
|
196
203
|
break;
|
|
204
|
+
case 'assessment_dimension':
|
|
205
|
+
ptrStable = `${p.assessmentId}|${p.dimensionId}`;
|
|
206
|
+
break;
|
|
197
207
|
case 'workflow_step':
|
|
198
208
|
ptrStable = p.stepId;
|
|
199
209
|
break;
|
|
@@ -251,6 +261,12 @@ const V2ContinueWorkflowBlockedSchema = zod_1.z.object({
|
|
|
251
261
|
suggestions: zod_1.z.array(zod_1.z.string()),
|
|
252
262
|
})
|
|
253
263
|
.optional(),
|
|
264
|
+
assessmentFollowup: zod_1.z
|
|
265
|
+
.object({
|
|
266
|
+
title: zod_1.z.string().min(1),
|
|
267
|
+
guidance: zod_1.z.string().min(1),
|
|
268
|
+
})
|
|
269
|
+
.optional(),
|
|
254
270
|
});
|
|
255
271
|
exports.V2ContinueWorkflowOutputSchema = zod_1.z.discriminatedUnion('kind', [
|
|
256
272
|
V2ContinueWorkflowOkSchema,
|
|
@@ -264,7 +280,7 @@ exports.V2ResumeSessionOutputSchema = zod_1.z.object({
|
|
|
264
280
|
sessionTitle: zod_1.z.string().nullable().describe('Human-readable task/session title derived from persisted workflow context or early recap text.'),
|
|
265
281
|
gitBranch: zod_1.z.string().nullable().describe('Git branch associated with the session, if available.'),
|
|
266
282
|
resumeToken: zod_1.z.string().regex(token_patterns_js_1.STATE_TOKEN_PATTERN, 'Invalid resumeToken format'),
|
|
267
|
-
snippet: zod_1.z.string().max(
|
|
283
|
+
snippet: zod_1.z.string().max(constants_js_1.MAX_RESUME_PREVIEW_BYTES),
|
|
268
284
|
confidence: zod_1.z.enum(['strong', 'medium', 'weak']).describe('Coarse confidence band for how likely this candidate is the intended session.'),
|
|
269
285
|
matchExplanation: zod_1.z.string().min(1).describe('Short natural-language explanation of why this candidate ranked here.'),
|
|
270
286
|
pendingStepId: zod_1.z.string().nullable().describe('The current pending step ID (e.g. "phase-3-implement") if the workflow is in progress. ' +
|
|
@@ -126,7 +126,13 @@ function formatBlockedRetryable(data) {
|
|
|
126
126
|
lines.push('');
|
|
127
127
|
}
|
|
128
128
|
}
|
|
129
|
-
|
|
129
|
+
if (data.assessmentFollowup) {
|
|
130
|
+
lines.push('**Follow-up required before retrying this step:**');
|
|
131
|
+
lines.push(`- ${data.assessmentFollowup.title}`);
|
|
132
|
+
lines.push(`- ${data.assessmentFollowup.guidance}`);
|
|
133
|
+
lines.push('');
|
|
134
|
+
}
|
|
135
|
+
lines.push('Retry the same step with improved output:');
|
|
130
136
|
lines.push('');
|
|
131
137
|
lines.push(formatTokenBlock(data));
|
|
132
138
|
return lines.join('\n');
|
|
@@ -11,6 +11,29 @@ export interface PromptFragment {
|
|
|
11
11
|
readonly when?: Condition;
|
|
12
12
|
readonly text: string;
|
|
13
13
|
}
|
|
14
|
+
export interface AssessmentDimensionDefinition {
|
|
15
|
+
readonly id: string;
|
|
16
|
+
readonly purpose: string;
|
|
17
|
+
readonly levels: readonly string[];
|
|
18
|
+
readonly required?: boolean;
|
|
19
|
+
}
|
|
20
|
+
export interface AssessmentDefinition {
|
|
21
|
+
readonly id: string;
|
|
22
|
+
readonly purpose: string;
|
|
23
|
+
readonly dimensions: readonly AssessmentDimensionDefinition[];
|
|
24
|
+
}
|
|
25
|
+
export interface AssessmentConsequenceTriggerDefinition {
|
|
26
|
+
readonly dimensionId: string;
|
|
27
|
+
readonly equalsLevel: string;
|
|
28
|
+
}
|
|
29
|
+
export interface AssessmentFollowupRequiredEffectDefinition {
|
|
30
|
+
readonly kind: 'require_followup';
|
|
31
|
+
readonly guidance: string;
|
|
32
|
+
}
|
|
33
|
+
export interface AssessmentConsequenceDefinition {
|
|
34
|
+
readonly when: AssessmentConsequenceTriggerDefinition;
|
|
35
|
+
readonly effect: AssessmentFollowupRequiredEffectDefinition;
|
|
36
|
+
}
|
|
14
37
|
export interface WorkflowStepDefinition {
|
|
15
38
|
readonly id: string;
|
|
16
39
|
readonly title: string;
|
|
@@ -23,6 +46,8 @@ export interface WorkflowStepDefinition {
|
|
|
23
46
|
readonly runCondition?: Readonly<Record<string, unknown>>;
|
|
24
47
|
readonly validationCriteria?: ValidationCriteria;
|
|
25
48
|
readonly outputContract?: OutputContract;
|
|
49
|
+
readonly assessmentRefs?: readonly string[];
|
|
50
|
+
readonly assessmentConsequences?: readonly AssessmentConsequenceDefinition[];
|
|
26
51
|
readonly notesOptional?: boolean;
|
|
27
52
|
readonly templateCall?: TemplateCall;
|
|
28
53
|
readonly promptFragments?: readonly PromptFragment[];
|
|
@@ -106,6 +131,7 @@ export interface WorkflowDefinition {
|
|
|
106
131
|
readonly functionDefinitions?: readonly FunctionDefinition[];
|
|
107
132
|
readonly recommendedPreferences?: WorkflowRecommendedPreferences;
|
|
108
133
|
readonly features?: readonly string[];
|
|
134
|
+
readonly assessments?: readonly AssessmentDefinition[];
|
|
109
135
|
readonly extensionPoints?: readonly ExtensionPoint[];
|
|
110
136
|
readonly references?: readonly WorkflowReference[];
|
|
111
137
|
}
|
|
@@ -28,11 +28,26 @@ function hasWorkflowDefinitionShape(obj) {
|
|
|
28
28
|
function createWorkflowDefinition(definition) {
|
|
29
29
|
return Object.freeze({
|
|
30
30
|
...definition,
|
|
31
|
-
steps: Object.freeze(definition.steps.map(step => Object.freeze({
|
|
31
|
+
steps: Object.freeze(definition.steps.map(step => Object.freeze({
|
|
32
|
+
...step,
|
|
33
|
+
assessmentConsequences: 'assessmentConsequences' in step && step.assessmentConsequences
|
|
34
|
+
? Object.freeze(step.assessmentConsequences.map(consequence => Object.freeze({
|
|
35
|
+
...consequence,
|
|
36
|
+
when: Object.freeze({ ...consequence.when }),
|
|
37
|
+
effect: Object.freeze({ ...consequence.effect }),
|
|
38
|
+
})))
|
|
39
|
+
: undefined,
|
|
40
|
+
}))),
|
|
32
41
|
preconditions: definition.preconditions ? Object.freeze([...definition.preconditions]) : undefined,
|
|
33
42
|
clarificationPrompts: definition.clarificationPrompts ? Object.freeze([...definition.clarificationPrompts]) : undefined,
|
|
34
43
|
metaGuidance: definition.metaGuidance ? Object.freeze([...definition.metaGuidance]) : undefined,
|
|
35
44
|
functionDefinitions: definition.functionDefinitions ? Object.freeze([...definition.functionDefinitions]) : undefined,
|
|
45
|
+
assessments: definition.assessments
|
|
46
|
+
? Object.freeze(definition.assessments.map(assessment => Object.freeze({
|
|
47
|
+
...assessment,
|
|
48
|
+
dimensions: Object.freeze(assessment.dimensions.map(dimension => Object.freeze({ ...dimension }))),
|
|
49
|
+
})))
|
|
50
|
+
: undefined,
|
|
36
51
|
extensionPoints: definition.extensionPoints ? Object.freeze([...definition.extensionPoints]) : undefined,
|
|
37
52
|
references: definition.references ? Object.freeze(definition.references.map(ref => Object.freeze({ ...ref }))) : undefined,
|
|
38
53
|
});
|
|
@@ -15,7 +15,8 @@ export declare const MAX_OBSERVATION_SHORT_STRING_LENGTH = 80;
|
|
|
15
15
|
export declare const SESSION_LOCK_RETRY_AFTER_MS = 1000;
|
|
16
16
|
export declare const DEFAULT_RETRY_AFTER_MS = 1000;
|
|
17
17
|
export declare const TRUNCATION_MARKER = "\n\n[TRUNCATED]";
|
|
18
|
-
export declare const RECOVERY_BUDGET_BYTES
|
|
18
|
+
export declare const RECOVERY_BUDGET_BYTES: number;
|
|
19
|
+
export declare const MAX_RESUME_PREVIEW_BYTES: number;
|
|
19
20
|
export declare const SHA256_DIGEST_PATTERN: RegExp;
|
|
20
21
|
export declare const DELIMITER_SAFE_ID_PATTERN: RegExp;
|
|
21
22
|
export declare const EVENT_KIND: {
|
|
@@ -27,6 +28,8 @@ export declare const EVENT_KIND: {
|
|
|
27
28
|
readonly ADVANCE_RECORDED: "advance_recorded";
|
|
28
29
|
readonly VALIDATION_PERFORMED: "validation_performed";
|
|
29
30
|
readonly NODE_OUTPUT_APPENDED: "node_output_appended";
|
|
31
|
+
readonly ASSESSMENT_RECORDED: "assessment_recorded";
|
|
32
|
+
readonly ASSESSMENT_CONSEQUENCE_APPLIED: "assessment_consequence_applied";
|
|
30
33
|
readonly PREFERENCES_CHANGED: "preferences_changed";
|
|
31
34
|
readonly CAPABILITY_OBSERVED: "capability_observed";
|
|
32
35
|
readonly GAP_RECORDED: "gap_recorded";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.AUTONOMY_MODE = exports.ADVANCE_INTENT = exports.MANIFEST_KIND = exports.EDGE_CAUSE = exports.ADVANCE_OUTCOME = exports.ENGINE_STATE = exports.EDGE_KIND = exports.PAYLOAD_KIND = exports.OUTPUT_CHANNEL = exports.EVENT_KIND = exports.DELIMITER_SAFE_ID_PATTERN = exports.SHA256_DIGEST_PATTERN = exports.RECOVERY_BUDGET_BYTES = exports.TRUNCATION_MARKER = exports.DEFAULT_RETRY_AFTER_MS = exports.SESSION_LOCK_RETRY_AFTER_MS = exports.MAX_OBSERVATION_SHORT_STRING_LENGTH = exports.MAX_CONTEXT_DEPTH = exports.MAX_CONTEXT_BYTES = exports.MAX_VALIDATION_SUGGESTIONS_BYTES = exports.MAX_VALIDATION_ISSUES_BYTES = exports.MAX_VALIDATION_SUGGESTION_ITEM_BYTES = exports.MAX_VALIDATION_ISSUE_ITEM_BYTES = exports.MAX_OUTPUT_NOTES_MARKDOWN_BYTES = exports.MAX_DECISION_TRACE_TOTAL_BYTES = exports.MAX_DECISION_TRACE_ENTRY_SUMMARY_BYTES = exports.MAX_DECISION_TRACE_ENTRIES = exports.MAX_BLOCKER_SUGGESTED_FIX_BYTES = exports.MAX_BLOCKER_MESSAGE_BYTES = exports.MAX_BLOCKERS = void 0;
|
|
3
|
+
exports.AUTONOMY_MODE = exports.ADVANCE_INTENT = exports.MANIFEST_KIND = exports.EDGE_CAUSE = exports.ADVANCE_OUTCOME = exports.ENGINE_STATE = exports.EDGE_KIND = exports.PAYLOAD_KIND = exports.OUTPUT_CHANNEL = exports.EVENT_KIND = exports.DELIMITER_SAFE_ID_PATTERN = exports.SHA256_DIGEST_PATTERN = exports.MAX_RESUME_PREVIEW_BYTES = exports.RECOVERY_BUDGET_BYTES = exports.TRUNCATION_MARKER = exports.DEFAULT_RETRY_AFTER_MS = exports.SESSION_LOCK_RETRY_AFTER_MS = exports.MAX_OBSERVATION_SHORT_STRING_LENGTH = exports.MAX_CONTEXT_DEPTH = exports.MAX_CONTEXT_BYTES = exports.MAX_VALIDATION_SUGGESTIONS_BYTES = exports.MAX_VALIDATION_ISSUES_BYTES = exports.MAX_VALIDATION_SUGGESTION_ITEM_BYTES = exports.MAX_VALIDATION_ISSUE_ITEM_BYTES = exports.MAX_OUTPUT_NOTES_MARKDOWN_BYTES = exports.MAX_DECISION_TRACE_TOTAL_BYTES = exports.MAX_DECISION_TRACE_ENTRY_SUMMARY_BYTES = exports.MAX_DECISION_TRACE_ENTRIES = exports.MAX_BLOCKER_SUGGESTED_FIX_BYTES = exports.MAX_BLOCKER_MESSAGE_BYTES = exports.MAX_BLOCKERS = void 0;
|
|
4
4
|
exports.MAX_BLOCKERS = 10;
|
|
5
5
|
exports.MAX_BLOCKER_MESSAGE_BYTES = 512;
|
|
6
6
|
exports.MAX_BLOCKER_SUGGESTED_FIX_BYTES = 1024;
|
|
@@ -18,7 +18,8 @@ exports.MAX_OBSERVATION_SHORT_STRING_LENGTH = 80;
|
|
|
18
18
|
exports.SESSION_LOCK_RETRY_AFTER_MS = 1000;
|
|
19
19
|
exports.DEFAULT_RETRY_AFTER_MS = 1000;
|
|
20
20
|
exports.TRUNCATION_MARKER = '\n\n[TRUNCATED]';
|
|
21
|
-
exports.RECOVERY_BUDGET_BYTES =
|
|
21
|
+
exports.RECOVERY_BUDGET_BYTES = 24 * 1024;
|
|
22
|
+
exports.MAX_RESUME_PREVIEW_BYTES = 2 * 1024;
|
|
22
23
|
exports.SHA256_DIGEST_PATTERN = /^sha256:[0-9a-f]{64}$/;
|
|
23
24
|
exports.DELIMITER_SAFE_ID_PATTERN = /^[a-z0-9_-]+$/;
|
|
24
25
|
exports.EVENT_KIND = {
|
|
@@ -30,6 +31,8 @@ exports.EVENT_KIND = {
|
|
|
30
31
|
ADVANCE_RECORDED: 'advance_recorded',
|
|
31
32
|
VALIDATION_PERFORMED: 'validation_performed',
|
|
32
33
|
NODE_OUTPUT_APPENDED: 'node_output_appended',
|
|
34
|
+
ASSESSMENT_RECORDED: 'assessment_recorded',
|
|
35
|
+
ASSESSMENT_CONSEQUENCE_APPLIED: 'assessment_consequence_applied',
|
|
33
36
|
PREFERENCES_CHANGED: 'preferences_changed',
|
|
34
37
|
CAPABILITY_OBSERVED: 'capability_observed',
|
|
35
38
|
GAP_RECORDED: 'gap_recorded',
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { type Result } from 'neverthrow';
|
|
2
|
+
import type { DomainEventV1 } from '../schemas/session/index.js';
|
|
3
|
+
type EventToAppendV1 = Omit<DomainEventV1, 'eventIndex' | 'sessionId'>;
|
|
4
|
+
export type AssessmentConsequenceEventError = {
|
|
5
|
+
readonly code: 'ASSESSMENT_CONSEQUENCE_EVENT_INVARIANT_VIOLATION';
|
|
6
|
+
readonly message: string;
|
|
7
|
+
};
|
|
8
|
+
export declare function buildAssessmentConsequenceAppliedEvent(args: {
|
|
9
|
+
readonly sessionId: string;
|
|
10
|
+
readonly attemptId: string;
|
|
11
|
+
readonly scope: {
|
|
12
|
+
readonly runId: string;
|
|
13
|
+
readonly nodeId: string;
|
|
14
|
+
};
|
|
15
|
+
readonly assessmentId: string;
|
|
16
|
+
readonly dimensionId: string;
|
|
17
|
+
readonly level: string;
|
|
18
|
+
readonly guidance: string;
|
|
19
|
+
readonly minted: {
|
|
20
|
+
readonly eventId: string;
|
|
21
|
+
};
|
|
22
|
+
}): Result<EventToAppendV1, AssessmentConsequenceEventError>;
|
|
23
|
+
export {};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.buildAssessmentConsequenceAppliedEvent = buildAssessmentConsequenceAppliedEvent;
|
|
4
|
+
const neverthrow_1 = require("neverthrow");
|
|
5
|
+
const constants_js_1 = require("../constants.js");
|
|
6
|
+
function buildAssessmentConsequenceAppliedEvent(args) {
|
|
7
|
+
if (!args.sessionId)
|
|
8
|
+
return (0, neverthrow_1.err)({ code: 'ASSESSMENT_CONSEQUENCE_EVENT_INVARIANT_VIOLATION', message: 'sessionId is required' });
|
|
9
|
+
if (!args.attemptId)
|
|
10
|
+
return (0, neverthrow_1.err)({ code: 'ASSESSMENT_CONSEQUENCE_EVENT_INVARIANT_VIOLATION', message: 'attemptId is required' });
|
|
11
|
+
if (!args.scope.runId || !args.scope.nodeId) {
|
|
12
|
+
return (0, neverthrow_1.err)({ code: 'ASSESSMENT_CONSEQUENCE_EVENT_INVARIANT_VIOLATION', message: 'scope.runId and scope.nodeId are required' });
|
|
13
|
+
}
|
|
14
|
+
if (!args.assessmentId || !args.dimensionId || !args.level || !args.guidance) {
|
|
15
|
+
return (0, neverthrow_1.err)({ code: 'ASSESSMENT_CONSEQUENCE_EVENT_INVARIANT_VIOLATION', message: 'assessment consequence fields are required' });
|
|
16
|
+
}
|
|
17
|
+
return (0, neverthrow_1.ok)({
|
|
18
|
+
v: 1,
|
|
19
|
+
eventId: args.minted.eventId,
|
|
20
|
+
kind: constants_js_1.EVENT_KIND.ASSESSMENT_CONSEQUENCE_APPLIED,
|
|
21
|
+
dedupeKey: `assessment_consequence_applied:${args.sessionId}:${args.scope.nodeId}:${args.attemptId}`,
|
|
22
|
+
scope: { runId: args.scope.runId, nodeId: args.scope.nodeId },
|
|
23
|
+
data: {
|
|
24
|
+
attemptId: args.attemptId,
|
|
25
|
+
assessmentId: args.assessmentId,
|
|
26
|
+
trigger: {
|
|
27
|
+
dimensionId: args.dimensionId,
|
|
28
|
+
level: args.level,
|
|
29
|
+
},
|
|
30
|
+
effect: {
|
|
31
|
+
kind: 'require_followup',
|
|
32
|
+
guidance: args.guidance,
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
});
|
|
36
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export interface RecordedAssessmentDimensionV1 {
|
|
2
|
+
readonly dimensionId: string;
|
|
3
|
+
readonly level: string;
|
|
4
|
+
readonly rationale?: string;
|
|
5
|
+
readonly normalization: 'exact' | 'normalized';
|
|
6
|
+
}
|
|
7
|
+
export interface RecordedAssessmentV1 {
|
|
8
|
+
readonly assessmentId: string;
|
|
9
|
+
readonly summary?: string;
|
|
10
|
+
readonly dimensions: readonly RecordedAssessmentDimensionV1[];
|
|
11
|
+
readonly normalizationNotes: readonly string[];
|
|
12
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { type Result } from 'neverthrow';
|
|
2
|
+
import type { DomainEventV1 } from '../schemas/session/index.js';
|
|
3
|
+
import type { RecordedAssessmentV1 } from './assessment-record.js';
|
|
4
|
+
type EventToAppendV1 = Omit<DomainEventV1, 'eventIndex' | 'sessionId'>;
|
|
5
|
+
export type AssessmentRecordedEventError = {
|
|
6
|
+
readonly code: 'ASSESSMENT_EVENT_INVARIANT_VIOLATION';
|
|
7
|
+
readonly message: string;
|
|
8
|
+
};
|
|
9
|
+
export declare function buildAssessmentRecordedEvent(args: {
|
|
10
|
+
readonly sessionId: string;
|
|
11
|
+
readonly attemptId: string;
|
|
12
|
+
readonly artifactOutputId: string;
|
|
13
|
+
readonly scope: {
|
|
14
|
+
readonly runId: string;
|
|
15
|
+
readonly nodeId: string;
|
|
16
|
+
};
|
|
17
|
+
readonly assessment: RecordedAssessmentV1;
|
|
18
|
+
readonly minted: {
|
|
19
|
+
readonly eventId: string;
|
|
20
|
+
};
|
|
21
|
+
}): Result<EventToAppendV1, AssessmentRecordedEventError>;
|
|
22
|
+
export {};
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.buildAssessmentRecordedEvent = buildAssessmentRecordedEvent;
|
|
4
|
+
const neverthrow_1 = require("neverthrow");
|
|
5
|
+
const constants_js_1 = require("../constants.js");
|
|
6
|
+
function buildAssessmentRecordedEvent(args) {
|
|
7
|
+
if (!args.sessionId)
|
|
8
|
+
return (0, neverthrow_1.err)({ code: 'ASSESSMENT_EVENT_INVARIANT_VIOLATION', message: 'sessionId is required' });
|
|
9
|
+
if (!args.attemptId)
|
|
10
|
+
return (0, neverthrow_1.err)({ code: 'ASSESSMENT_EVENT_INVARIANT_VIOLATION', message: 'attemptId is required' });
|
|
11
|
+
if (!args.artifactOutputId)
|
|
12
|
+
return (0, neverthrow_1.err)({ code: 'ASSESSMENT_EVENT_INVARIANT_VIOLATION', message: 'artifactOutputId is required' });
|
|
13
|
+
if (!args.scope.runId || !args.scope.nodeId) {
|
|
14
|
+
return (0, neverthrow_1.err)({ code: 'ASSESSMENT_EVENT_INVARIANT_VIOLATION', message: 'scope.runId and scope.nodeId are required' });
|
|
15
|
+
}
|
|
16
|
+
if (!args.minted.eventId)
|
|
17
|
+
return (0, neverthrow_1.err)({ code: 'ASSESSMENT_EVENT_INVARIANT_VIOLATION', message: 'minted.eventId is required' });
|
|
18
|
+
return (0, neverthrow_1.ok)({
|
|
19
|
+
v: 1,
|
|
20
|
+
eventId: args.minted.eventId,
|
|
21
|
+
kind: constants_js_1.EVENT_KIND.ASSESSMENT_RECORDED,
|
|
22
|
+
dedupeKey: `assessment_recorded:${args.sessionId}:${args.scope.nodeId}:${args.attemptId}`,
|
|
23
|
+
scope: { runId: args.scope.runId, nodeId: args.scope.nodeId },
|
|
24
|
+
data: {
|
|
25
|
+
assessmentId: args.assessment.assessmentId,
|
|
26
|
+
attemptId: args.attemptId,
|
|
27
|
+
artifactOutputId: args.artifactOutputId,
|
|
28
|
+
summary: args.assessment.summary,
|
|
29
|
+
normalizationNotes: [...args.assessment.normalizationNotes],
|
|
30
|
+
dimensions: args.assessment.dimensions.map((dimension) => ({
|
|
31
|
+
dimensionId: dimension.dimensionId,
|
|
32
|
+
level: dimension.level,
|
|
33
|
+
normalization: dimension.normalization,
|
|
34
|
+
...(dimension.rationale ? { rationale: dimension.rationale } : {}),
|
|
35
|
+
})),
|
|
36
|
+
},
|
|
37
|
+
});
|
|
38
|
+
}
|
|
@@ -14,7 +14,7 @@ export declare function buildBlockedNodeSnapshot(args: {
|
|
|
14
14
|
readonly priorSnapshot: ExecutionSnapshotFileV1;
|
|
15
15
|
readonly primaryReason: ReasonV1;
|
|
16
16
|
readonly attemptId: AttemptId;
|
|
17
|
-
readonly validationRef
|
|
17
|
+
readonly validationRef?: string;
|
|
18
18
|
readonly blockers: BlockerReportV1;
|
|
19
19
|
readonly sha256: Sha256PortV2;
|
|
20
20
|
}): Result<ExecutionSnapshotFileV1, BlockedNodeBuildError>;
|
|
@@ -9,6 +9,14 @@ function toContractViolationReason(reason) {
|
|
|
9
9
|
return { kind: 'invalid_required_output', contractRef: reason.contractRef };
|
|
10
10
|
case 'missing_required_output':
|
|
11
11
|
return { kind: 'missing_required_output', contractRef: reason.contractRef };
|
|
12
|
+
case 'assessment_followup_required':
|
|
13
|
+
return {
|
|
14
|
+
kind: 'assessment_followup_required',
|
|
15
|
+
assessmentId: reason.assessmentId,
|
|
16
|
+
dimensionId: reason.dimensionId,
|
|
17
|
+
level: reason.level,
|
|
18
|
+
guidance: reason.guidance,
|
|
19
|
+
};
|
|
12
20
|
case 'missing_context_key':
|
|
13
21
|
return { kind: 'missing_context_key', key: reason.key };
|
|
14
22
|
case 'context_budget_exceeded':
|
|
@@ -34,4 +34,10 @@ export declare function detectBlockingReasonsV1(args: {
|
|
|
34
34
|
readonly missingNotes?: {
|
|
35
35
|
readonly stepId: string;
|
|
36
36
|
};
|
|
37
|
+
readonly assessmentFollowupRequired?: {
|
|
38
|
+
readonly assessmentId: string;
|
|
39
|
+
readonly dimensionId: string;
|
|
40
|
+
readonly level: string;
|
|
41
|
+
readonly guidance: string;
|
|
42
|
+
};
|
|
37
43
|
}): Result<readonly ReasonV1[], BlockingDecisionError>;
|
|
@@ -63,5 +63,20 @@ function detectBlockingReasonsV1(args) {
|
|
|
63
63
|
}
|
|
64
64
|
reasons.push({ kind: 'missing_notes', stepId: args.missingNotes.stepId });
|
|
65
65
|
}
|
|
66
|
+
if (args.assessmentFollowupRequired) {
|
|
67
|
+
if (!constants_js_1.DELIMITER_SAFE_ID_PATTERN.test(args.assessmentFollowupRequired.dimensionId)) {
|
|
68
|
+
return (0, neverthrow_1.err)({
|
|
69
|
+
code: 'INVALID_DELIMITER_SAFE_ID',
|
|
70
|
+
message: `assessment dimension ID must be delimiter-safe: [a-z0-9_-]+ (got: ${args.assessmentFollowupRequired.dimensionId})`,
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
reasons.push({
|
|
74
|
+
kind: 'assessment_followup_required',
|
|
75
|
+
assessmentId: args.assessmentFollowupRequired.assessmentId,
|
|
76
|
+
dimensionId: args.assessmentFollowupRequired.dimensionId,
|
|
77
|
+
level: args.assessmentFollowupRequired.level,
|
|
78
|
+
guidance: args.assessmentFollowupRequired.guidance,
|
|
79
|
+
});
|
|
80
|
+
}
|
|
66
81
|
return (0, neverthrow_1.ok)(reasons);
|
|
67
82
|
}
|
|
@@ -15,11 +15,13 @@ const index_js_2 = require("../schemas/artifacts/index.js");
|
|
|
15
15
|
const run_context_js_1 = require("../../projections/run-context.js");
|
|
16
16
|
const condition_evaluator_js_1 = require("../../../utils/condition-evaluator.js");
|
|
17
17
|
const context_template_resolver_js_1 = require("./context-template-resolver.js");
|
|
18
|
-
|
|
19
|
-
|
|
18
|
+
const retrieval_contract_js_1 = require("./retrieval-contract.js");
|
|
19
|
+
function buildNonTipSegments(args) {
|
|
20
|
+
const segments = [];
|
|
20
21
|
const childSummary = (0, recap_recovery_js_1.buildChildSummary)({ nodeId: args.nodeId, dag: args.run });
|
|
21
|
-
|
|
22
|
-
|
|
22
|
+
const childSummarySegment = (0, retrieval_contract_js_1.createBranchSummarySegment)(childSummary);
|
|
23
|
+
if (childSummarySegment) {
|
|
24
|
+
segments.push(childSummarySegment);
|
|
23
25
|
}
|
|
24
26
|
if (args.run.preferredTipNodeId && args.run.preferredTipNodeId !== String(args.nodeId)) {
|
|
25
27
|
const downstreamRes = (0, recap_recovery_js_1.collectDownstreamRecap)({
|
|
@@ -29,12 +31,15 @@ function buildNonTipSections(args) {
|
|
|
29
31
|
outputs: args.outputs,
|
|
30
32
|
});
|
|
31
33
|
if (downstreamRes.isOk() && downstreamRes.value.length > 0) {
|
|
32
|
-
|
|
34
|
+
const downstreamSegment = (0, retrieval_contract_js_1.createDownstreamRecapSegment)(downstreamRes.value.join('\n\n'));
|
|
35
|
+
if (downstreamSegment) {
|
|
36
|
+
segments.push(downstreamSegment);
|
|
37
|
+
}
|
|
33
38
|
}
|
|
34
39
|
}
|
|
35
|
-
return
|
|
40
|
+
return segments;
|
|
36
41
|
}
|
|
37
|
-
function
|
|
42
|
+
function buildAncestrySegments(args) {
|
|
38
43
|
const ancestryRes = (0, recap_recovery_js_1.collectAncestryRecap)({
|
|
39
44
|
nodeId: args.nodeId,
|
|
40
45
|
dag: args.run,
|
|
@@ -42,11 +47,12 @@ function buildAncestrySections(args) {
|
|
|
42
47
|
includeCurrentNode: false,
|
|
43
48
|
});
|
|
44
49
|
if (ancestryRes.isOk() && ancestryRes.value.length > 0) {
|
|
45
|
-
|
|
50
|
+
const ancestrySegment = (0, retrieval_contract_js_1.createAncestryRecapSegment)(ancestryRes.value.join('\n\n'));
|
|
51
|
+
return ancestrySegment ? [ancestrySegment] : [];
|
|
46
52
|
}
|
|
47
53
|
return [];
|
|
48
54
|
}
|
|
49
|
-
function
|
|
55
|
+
function buildFunctionDefsSegments(args) {
|
|
50
56
|
const funcsRes = (0, function_definition_expander_js_1.expandFunctionDefinitions)({
|
|
51
57
|
workflow: args.workflow,
|
|
52
58
|
stepId: args.stepId,
|
|
@@ -55,7 +61,8 @@ function buildFunctionDefsSections(args) {
|
|
|
55
61
|
});
|
|
56
62
|
if (funcsRes.isOk() && funcsRes.value.length > 0) {
|
|
57
63
|
const formatted = funcsRes.value.map(function_definition_expander_js_1.formatFunctionDef).join('\n\n');
|
|
58
|
-
|
|
64
|
+
const functionDefinitionsSegment = (0, retrieval_contract_js_1.createFunctionDefinitionsSegment)(`\`\`\`\n${formatted}\n\`\`\``);
|
|
65
|
+
return functionDefinitionsSegment ? [functionDefinitionsSegment] : [];
|
|
59
66
|
}
|
|
60
67
|
return [];
|
|
61
68
|
}
|
|
@@ -65,12 +72,12 @@ function hasPriorNotesInRun(args) {
|
|
|
65
72
|
e.data.outputChannel === constants_js_1.OUTPUT_CHANNEL.RECAP &&
|
|
66
73
|
e.data.payload.payloadKind === constants_js_1.PAYLOAD_KIND.NOTES);
|
|
67
74
|
}
|
|
68
|
-
function
|
|
75
|
+
function buildRecoverySegments(args) {
|
|
69
76
|
const isTip = args.run.tipNodeIds.includes(String(args.nodeId));
|
|
70
77
|
return [
|
|
71
|
-
...(isTip ? [] :
|
|
72
|
-
...
|
|
73
|
-
...
|
|
78
|
+
...(isTip ? [] : buildNonTipSegments({ nodeId: args.nodeId, run: args.run, outputs: args.outputs })),
|
|
79
|
+
...buildAncestrySegments({ nodeId: args.nodeId, run: args.run, outputs: args.outputs }),
|
|
80
|
+
...buildFunctionDefsSegments({
|
|
74
81
|
workflow: args.workflow,
|
|
75
82
|
stepId: args.stepId,
|
|
76
83
|
loopPath: args.loopPath,
|
|
@@ -78,52 +85,6 @@ function buildRecoverySections(args) {
|
|
|
78
85
|
}),
|
|
79
86
|
];
|
|
80
87
|
}
|
|
81
|
-
function trimToUtf8Boundary(bytes) {
|
|
82
|
-
const n = bytes.length;
|
|
83
|
-
if (n === 0)
|
|
84
|
-
return bytes;
|
|
85
|
-
let cont = 0;
|
|
86
|
-
for (let i = n - 1; i >= 0 && i >= n - 4; i--) {
|
|
87
|
-
const b = bytes[i];
|
|
88
|
-
if ((b & 192) === 128) {
|
|
89
|
-
cont++;
|
|
90
|
-
}
|
|
91
|
-
else {
|
|
92
|
-
break;
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
if (cont === 0)
|
|
96
|
-
return bytes;
|
|
97
|
-
const leadByteIndex = n - cont - 1;
|
|
98
|
-
if (leadByteIndex < 0) {
|
|
99
|
-
return new Uint8Array(0);
|
|
100
|
-
}
|
|
101
|
-
const leadByte = bytes[leadByteIndex];
|
|
102
|
-
const expectedLen = (leadByte & 128) === 0 ? 1 :
|
|
103
|
-
(leadByte & 224) === 192 ? 2 :
|
|
104
|
-
(leadByte & 240) === 224 ? 3 :
|
|
105
|
-
(leadByte & 248) === 240 ? 4 :
|
|
106
|
-
0;
|
|
107
|
-
const actualLen = cont + 1;
|
|
108
|
-
if (expectedLen === 0 || expectedLen !== actualLen) {
|
|
109
|
-
return bytes.subarray(0, leadByteIndex);
|
|
110
|
-
}
|
|
111
|
-
return bytes;
|
|
112
|
-
}
|
|
113
|
-
function applyPromptBudget(combinedPrompt) {
|
|
114
|
-
const encoder = new TextEncoder();
|
|
115
|
-
const promptBytes = encoder.encode(combinedPrompt);
|
|
116
|
-
if (promptBytes.length <= constants_js_1.RECOVERY_BUDGET_BYTES) {
|
|
117
|
-
return combinedPrompt;
|
|
118
|
-
}
|
|
119
|
-
const markerText = constants_js_1.TRUNCATION_MARKER;
|
|
120
|
-
const omissionNote = `\nOmitted recovery content due to budget constraints.`;
|
|
121
|
-
const suffixBytes = encoder.encode(markerText + omissionNote);
|
|
122
|
-
const maxContentBytes = constants_js_1.RECOVERY_BUDGET_BYTES - suffixBytes.length;
|
|
123
|
-
const truncatedBytes = trimToUtf8Boundary(promptBytes.subarray(0, maxContentBytes));
|
|
124
|
-
const decoder = new TextDecoder('utf-8');
|
|
125
|
-
return decoder.decode(truncatedBytes) + markerText + omissionNote;
|
|
126
|
-
}
|
|
127
88
|
function resolveParentLoopStep(workflow, stepId) {
|
|
128
89
|
for (const step of workflow.definition.steps) {
|
|
129
90
|
if ((0, workflow_js_1.isLoopStepDefinition)(step) && Array.isArray(step.body)) {
|
|
@@ -220,6 +181,18 @@ function formatOutputContractRequirements(outputContract) {
|
|
|
220
181
|
];
|
|
221
182
|
}
|
|
222
183
|
}
|
|
184
|
+
function formatAssessmentRequirements(assessments) {
|
|
185
|
+
if (assessments.length === 0)
|
|
186
|
+
return [];
|
|
187
|
+
const requirements = [];
|
|
188
|
+
for (const assessment of assessments) {
|
|
189
|
+
requirements.push('Provide an artifact with kind: "wr.assessment"');
|
|
190
|
+
requirements.push(`Assessment target: "${assessment.id}"`);
|
|
191
|
+
requirements.push(`Dimensions: ${assessment.dimensions.map((dimension) => `${dimension.id} (${dimension.levels.join(' | ')})`).join(', ')}`);
|
|
192
|
+
requirements.push('Use only canonical dimension levels. If the engine rejects the artifact, correct the submitted levels instead of inventing new ones.');
|
|
193
|
+
}
|
|
194
|
+
return requirements;
|
|
195
|
+
}
|
|
223
196
|
function assembleFragmentedPrompt(fragments, context) {
|
|
224
197
|
return fragments
|
|
225
198
|
.filter(f => (0, condition_evaluator_js_1.evaluateCondition)(f.when, context))
|
|
@@ -256,6 +229,12 @@ function renderPendingPrompt(args) {
|
|
|
256
229
|
const outputContract = 'outputContract' in step
|
|
257
230
|
? step.outputContract
|
|
258
231
|
: undefined;
|
|
232
|
+
const stepAssessmentRefs = 'assessmentRefs' in step
|
|
233
|
+
? step.assessmentRefs
|
|
234
|
+
: undefined;
|
|
235
|
+
const stepAssessments = stepAssessmentRefs && stepAssessmentRefs.length > 0
|
|
236
|
+
? (args.workflow.definition.assessments ?? []).filter((assessment) => stepAssessmentRefs.includes(assessment.id))
|
|
237
|
+
: [];
|
|
259
238
|
const isExitStep = outputContract?.contractRef === index_js_2.LOOP_CONTROL_CONTRACT_REF;
|
|
260
239
|
const loopStep = resolveParentLoopStep(args.workflow, args.stepId);
|
|
261
240
|
const maxIterations = loopStep?.loop.maxIterations;
|
|
@@ -286,6 +265,12 @@ function renderPendingPrompt(args) {
|
|
|
286
265
|
? `\n\n${contractRequirements.map(r => `- ${r}`).join('\n')}`
|
|
287
266
|
: `\n\n**OUTPUT REQUIREMENTS (System):**\n${contractRequirements.map(r => `- ${r}`).join('\n')}`
|
|
288
267
|
: '';
|
|
268
|
+
const assessmentRequirements = formatAssessmentRequirements(stepAssessments);
|
|
269
|
+
const assessmentSection = assessmentRequirements.length > 0
|
|
270
|
+
? cleanResponseFormat
|
|
271
|
+
? `\n\n${assessmentRequirements.map(r => `- ${r}`).join('\n')}`
|
|
272
|
+
: `\n\n**ASSESSMENT REQUIREMENTS (System):**\n${assessmentRequirements.map(r => `- ${r}`).join('\n')}`
|
|
273
|
+
: '';
|
|
289
274
|
const isNotesOptional = outputContract !== undefined ||
|
|
290
275
|
('notesOptional' in step && step.notesOptional === true);
|
|
291
276
|
const notesSection = (() => {
|
|
@@ -336,7 +321,7 @@ function renderPendingPrompt(args) {
|
|
|
336
321
|
const fragmentSuffix = promptFragments && promptFragments.length > 0
|
|
337
322
|
? assembleFragmentedPrompt(promptFragments, renderContext)
|
|
338
323
|
: '';
|
|
339
|
-
const enhancedPrompt = loopBanner + basePrompt + requirementsSection + contractSection + notesSection
|
|
324
|
+
const enhancedPrompt = loopBanner + basePrompt + requirementsSection + contractSection + assessmentSection + notesSection
|
|
340
325
|
+ (fragmentSuffix ? '\n\n' + fragmentSuffix : '');
|
|
341
326
|
if (!args.rehydrateOnly) {
|
|
342
327
|
return (0, neverthrow_1.ok)({ stepId: args.stepId, title: baseTitle, prompt: enhancedPrompt, agentRole, requireConfirmation });
|
|
@@ -352,9 +337,8 @@ function renderPendingPrompt(args) {
|
|
|
352
337
|
});
|
|
353
338
|
}
|
|
354
339
|
const { run, outputs } = projectionsRes.value;
|
|
355
|
-
const
|
|
340
|
+
const segments = buildRecoverySegments({
|
|
356
341
|
nodeId: args.nodeId,
|
|
357
|
-
dag: run,
|
|
358
342
|
run,
|
|
359
343
|
outputs,
|
|
360
344
|
workflow: args.workflow,
|
|
@@ -362,12 +346,14 @@ function renderPendingPrompt(args) {
|
|
|
362
346
|
loopPath: args.loopPath,
|
|
363
347
|
functionReferences,
|
|
364
348
|
});
|
|
365
|
-
if (
|
|
349
|
+
if (segments.length === 0) {
|
|
366
350
|
return (0, neverthrow_1.ok)({ stepId: args.stepId, title: baseTitle, prompt: enhancedPrompt, agentRole, requireConfirmation });
|
|
367
351
|
}
|
|
368
352
|
const recoveryHeader = cleanResponseFormat ? 'Your previous work:' : '## Recovery Context';
|
|
369
|
-
const recoveryText =
|
|
370
|
-
|
|
371
|
-
|
|
353
|
+
const recoveryText = (0, retrieval_contract_js_1.renderBudgetedRehydrateRecovery)({
|
|
354
|
+
header: recoveryHeader,
|
|
355
|
+
segments,
|
|
356
|
+
}).text;
|
|
357
|
+
const finalPrompt = `${enhancedPrompt}\n\n${recoveryText}`;
|
|
372
358
|
return (0, neverthrow_1.ok)({ stepId: args.stepId, title: baseTitle, prompt: finalPrompt, agentRole, requireConfirmation });
|
|
373
359
|
}
|