voratiq 0.1.0-beta.20 → 0.1.0-beta.21
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/agents/runtime/policy.d.ts +1 -1
- package/dist/bin.js +50 -19
- package/dist/cli/contract.d.ts +35 -5
- package/dist/cli/contract.js +42 -5
- package/dist/cli/list.js +4 -1
- package/dist/cli/message.d.ts +28 -0
- package/dist/cli/message.js +147 -0
- package/dist/cli/operator-envelope.d.ts +22 -1
- package/dist/cli/operator-envelope.js +48 -3
- package/dist/cli/reduce.js +5 -2
- package/dist/cli/verify.js +6 -2
- package/dist/commands/list/command.d.ts +1 -0
- package/dist/commands/list/command.js +117 -7
- package/dist/commands/message/command.d.ts +23 -0
- package/dist/commands/message/command.js +215 -0
- package/dist/commands/message/errors.d.ts +9 -0
- package/dist/commands/message/errors.js +20 -0
- package/dist/commands/message/lifecycle.d.ts +14 -0
- package/dist/commands/message/lifecycle.js +128 -0
- package/dist/commands/reduce/command.d.ts +1 -0
- package/dist/commands/reduce/command.js +3 -1
- package/dist/commands/reduce/targets.d.ts +1 -0
- package/dist/commands/reduce/targets.js +48 -2
- package/dist/commands/shared/resolve-stage-competitors.js +4 -1
- package/dist/commands/verify/command.d.ts +1 -0
- package/dist/commands/verify/command.js +2 -1
- package/dist/commands/verify/max-parallel.d.ts +1 -1
- package/dist/commands/verify/max-parallel.js +3 -1
- package/dist/commands/verify/targets.d.ts +2 -1
- package/dist/commands/verify/targets.js +154 -22
- package/dist/configs/agents/defaults.js +25 -25
- package/dist/configs/orchestration/bootstrap.d.ts +6 -1
- package/dist/configs/orchestration/bootstrap.js +27 -6
- package/dist/configs/orchestration/types.d.ts +25 -10
- package/dist/configs/orchestration/types.js +10 -6
- package/dist/configs/verification/types.d.ts +5 -0
- package/dist/configs/verification/types.js +3 -0
- package/dist/contracts/list.d.ts +38 -4
- package/dist/contracts/list.js +30 -1
- package/dist/domain/message/competition/adapter.d.ts +36 -0
- package/dist/domain/message/competition/adapter.js +197 -0
- package/dist/domain/message/competition/prompt.d.ts +8 -0
- package/dist/domain/message/competition/prompt.js +29 -0
- package/dist/domain/message/model/mutators.d.ts +17 -0
- package/dist/domain/message/model/mutators.js +107 -0
- package/dist/domain/message/model/types.d.ts +100 -0
- package/dist/domain/message/model/types.js +87 -0
- package/dist/domain/message/persistence/adapter.d.ts +43 -0
- package/dist/domain/message/persistence/adapter.js +124 -0
- package/dist/domain/reduce/competition/adapter.d.ts +1 -0
- package/dist/domain/reduce/competition/adapter.js +57 -4
- package/dist/domain/reduce/competition/prompt.d.ts +1 -1
- package/dist/domain/reduce/model/types.d.ts +3 -0
- package/dist/domain/reduce/model/types.js +2 -1
- package/dist/domain/verify/competition/adapter.js +8 -5
- package/dist/domain/verify/competition/programmatic.js +3 -0
- package/dist/domain/verify/competition/prompt.js +6 -0
- package/dist/domain/verify/competition/rubric.js +7 -1
- package/dist/domain/verify/competition/shared-layout.d.ts +42 -2
- package/dist/domain/verify/competition/shared-layout.js +92 -21
- package/dist/domain/verify/competition/target.d.ts +17 -0
- package/dist/domain/verify/model/types.d.ts +20 -2
- package/dist/domain/verify/model/types.js +15 -2
- package/dist/mcp/server.d.ts +2 -2
- package/dist/mcp/server.js +30 -13
- package/dist/policy/verification.js +2 -0
- package/dist/preflight/index.d.ts +2 -0
- package/dist/preflight/index.js +3 -1
- package/dist/render/transcripts/list.d.ts +2 -0
- package/dist/render/transcripts/list.js +24 -0
- package/dist/render/transcripts/message.d.ts +72 -0
- package/dist/render/transcripts/message.js +362 -0
- package/dist/render/transcripts/stage-progress.d.ts +1 -1
- package/dist/render/transcripts/verify.d.ts +4 -0
- package/dist/render/transcripts/verify.js +7 -1
- package/dist/render/utils/transcript-shell.d.ts +1 -1
- package/dist/render/utils/transcript-shell.js +6 -0
- package/dist/status/index.d.ts +21 -0
- package/dist/status/index.js +30 -0
- package/dist/workspace/setup.js +13 -7
- package/dist/workspace/structure.d.ts +14 -6
- package/dist/workspace/structure.js +25 -9
- package/dist/workspace/verification-defaults.d.ts +1 -1
- package/dist/workspace/verification-defaults.js +255 -0
- package/package.json +15 -16
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { type MessageRecipientStatus, messageRecipientStatusSchema, type MessageStatus, messageStatusSchema, TERMINAL_MESSAGE_RECIPIENT_STATUSES, TERMINAL_MESSAGE_STATUSES } from "../../../status/index.js";
|
|
3
|
+
export type { MessageRecipientStatus, MessageStatus };
|
|
4
|
+
export { messageRecipientStatusSchema, messageStatusSchema, TERMINAL_MESSAGE_RECIPIENT_STATUSES, TERMINAL_MESSAGE_STATUSES, };
|
|
5
|
+
export declare const messageRecipientEntrySchema: z.ZodObject<{
|
|
6
|
+
agentId: z.ZodString;
|
|
7
|
+
status: z.ZodEnum<{
|
|
8
|
+
queued: "queued";
|
|
9
|
+
running: "running";
|
|
10
|
+
succeeded: "succeeded";
|
|
11
|
+
failed: "failed";
|
|
12
|
+
aborted: "aborted";
|
|
13
|
+
}>;
|
|
14
|
+
startedAt: z.ZodOptional<z.ZodString>;
|
|
15
|
+
completedAt: z.ZodOptional<z.ZodString>;
|
|
16
|
+
outputPath: z.ZodOptional<z.ZodString>;
|
|
17
|
+
stdoutPath: z.ZodOptional<z.ZodString>;
|
|
18
|
+
stderrPath: z.ZodOptional<z.ZodString>;
|
|
19
|
+
tokenUsage: z.ZodOptional<z.ZodUnion<readonly [z.ZodObject<{
|
|
20
|
+
input_tokens: z.ZodOptional<z.ZodNumber>;
|
|
21
|
+
output_tokens: z.ZodOptional<z.ZodNumber>;
|
|
22
|
+
cache_read_input_tokens: z.ZodOptional<z.ZodNumber>;
|
|
23
|
+
cache_creation_input_tokens: z.ZodOptional<z.ZodNumber>;
|
|
24
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
25
|
+
input_tokens: z.ZodOptional<z.ZodNumber>;
|
|
26
|
+
cached_input_tokens: z.ZodOptional<z.ZodNumber>;
|
|
27
|
+
output_tokens: z.ZodOptional<z.ZodNumber>;
|
|
28
|
+
reasoning_output_tokens: z.ZodOptional<z.ZodNumber>;
|
|
29
|
+
total_tokens: z.ZodOptional<z.ZodNumber>;
|
|
30
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
31
|
+
input: z.ZodOptional<z.ZodNumber>;
|
|
32
|
+
output: z.ZodOptional<z.ZodNumber>;
|
|
33
|
+
cached: z.ZodOptional<z.ZodNumber>;
|
|
34
|
+
thoughts: z.ZodOptional<z.ZodNumber>;
|
|
35
|
+
tool: z.ZodOptional<z.ZodNumber>;
|
|
36
|
+
total: z.ZodOptional<z.ZodNumber>;
|
|
37
|
+
}, z.core.$strict>]>>;
|
|
38
|
+
error: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
39
|
+
}, z.core.$strip>;
|
|
40
|
+
export type MessageRecipientEntry = z.infer<typeof messageRecipientEntrySchema>;
|
|
41
|
+
export declare const messageRecordSchema: z.ZodObject<{
|
|
42
|
+
sessionId: z.ZodString;
|
|
43
|
+
createdAt: z.ZodString;
|
|
44
|
+
startedAt: z.ZodString;
|
|
45
|
+
completedAt: z.ZodOptional<z.ZodString>;
|
|
46
|
+
status: z.ZodEnum<{
|
|
47
|
+
queued: "queued";
|
|
48
|
+
running: "running";
|
|
49
|
+
succeeded: "succeeded";
|
|
50
|
+
failed: "failed";
|
|
51
|
+
aborted: "aborted";
|
|
52
|
+
}>;
|
|
53
|
+
baseRevisionSha: z.ZodOptional<z.ZodString>;
|
|
54
|
+
prompt: z.ZodString;
|
|
55
|
+
sourceInteractiveSessionId: z.ZodOptional<z.ZodString>;
|
|
56
|
+
extraContext: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
57
|
+
extraContextMetadata: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
58
|
+
stagedPath: z.ZodString;
|
|
59
|
+
sourcePath: z.ZodString;
|
|
60
|
+
}, z.core.$strip>>>;
|
|
61
|
+
recipients: z.ZodArray<z.ZodObject<{
|
|
62
|
+
agentId: z.ZodString;
|
|
63
|
+
status: z.ZodEnum<{
|
|
64
|
+
queued: "queued";
|
|
65
|
+
running: "running";
|
|
66
|
+
succeeded: "succeeded";
|
|
67
|
+
failed: "failed";
|
|
68
|
+
aborted: "aborted";
|
|
69
|
+
}>;
|
|
70
|
+
startedAt: z.ZodOptional<z.ZodString>;
|
|
71
|
+
completedAt: z.ZodOptional<z.ZodString>;
|
|
72
|
+
outputPath: z.ZodOptional<z.ZodString>;
|
|
73
|
+
stdoutPath: z.ZodOptional<z.ZodString>;
|
|
74
|
+
stderrPath: z.ZodOptional<z.ZodString>;
|
|
75
|
+
tokenUsage: z.ZodOptional<z.ZodUnion<readonly [z.ZodObject<{
|
|
76
|
+
input_tokens: z.ZodOptional<z.ZodNumber>;
|
|
77
|
+
output_tokens: z.ZodOptional<z.ZodNumber>;
|
|
78
|
+
cache_read_input_tokens: z.ZodOptional<z.ZodNumber>;
|
|
79
|
+
cache_creation_input_tokens: z.ZodOptional<z.ZodNumber>;
|
|
80
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
81
|
+
input_tokens: z.ZodOptional<z.ZodNumber>;
|
|
82
|
+
cached_input_tokens: z.ZodOptional<z.ZodNumber>;
|
|
83
|
+
output_tokens: z.ZodOptional<z.ZodNumber>;
|
|
84
|
+
reasoning_output_tokens: z.ZodOptional<z.ZodNumber>;
|
|
85
|
+
total_tokens: z.ZodOptional<z.ZodNumber>;
|
|
86
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
87
|
+
input: z.ZodOptional<z.ZodNumber>;
|
|
88
|
+
output: z.ZodOptional<z.ZodNumber>;
|
|
89
|
+
cached: z.ZodOptional<z.ZodNumber>;
|
|
90
|
+
thoughts: z.ZodOptional<z.ZodNumber>;
|
|
91
|
+
tool: z.ZodOptional<z.ZodNumber>;
|
|
92
|
+
total: z.ZodOptional<z.ZodNumber>;
|
|
93
|
+
}, z.core.$strict>]>>;
|
|
94
|
+
error: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
95
|
+
}, z.core.$strip>>;
|
|
96
|
+
error: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
97
|
+
}, z.core.$strip>;
|
|
98
|
+
export type MessageRecord = z.infer<typeof messageRecordSchema>;
|
|
99
|
+
export type MessageIndexEntry = Pick<MessageRecord, "sessionId" | "createdAt" | "status">;
|
|
100
|
+
export declare function deriveMessageStatusFromRecipients(recipientStatuses: readonly MessageRecipientStatus[]): MessageStatus;
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { agentIdSchema } from "../../../configs/agents/types.js";
|
|
3
|
+
import { extractedTokenUsageSchema } from "../../../domain/run/model/types.js";
|
|
4
|
+
import { extraContextMetadataEntrySchema, persistedExtraContextPathSchema, } from "../../../persistence/extra-context.js";
|
|
5
|
+
import { repoRelativeRecordPathSchema } from "../../../persistence/record-path-schema.js";
|
|
6
|
+
import { messageRecipientStatusSchema, messageStatusSchema, TERMINAL_MESSAGE_RECIPIENT_STATUSES, TERMINAL_MESSAGE_STATUSES, } from "../../../status/index.js";
|
|
7
|
+
import { validateOperationLifecycleTimestamps, validateRecordLifecycleTimestamps, } from "../../shared/lifecycle.js";
|
|
8
|
+
export { messageRecipientStatusSchema, messageStatusSchema, TERMINAL_MESSAGE_RECIPIENT_STATUSES, TERMINAL_MESSAGE_STATUSES, };
|
|
9
|
+
const RUNNING_MESSAGE_RECORD_STATUSES = [
|
|
10
|
+
"running",
|
|
11
|
+
];
|
|
12
|
+
export const messageRecipientEntrySchema = z
|
|
13
|
+
.object({
|
|
14
|
+
agentId: agentIdSchema,
|
|
15
|
+
status: messageRecipientStatusSchema,
|
|
16
|
+
startedAt: z.string().optional(),
|
|
17
|
+
completedAt: z.string().optional(),
|
|
18
|
+
outputPath: repoRelativeRecordPathSchema.optional(),
|
|
19
|
+
stdoutPath: repoRelativeRecordPathSchema.optional(),
|
|
20
|
+
stderrPath: repoRelativeRecordPathSchema.optional(),
|
|
21
|
+
tokenUsage: extractedTokenUsageSchema.optional(),
|
|
22
|
+
error: z.string().nullable().optional(),
|
|
23
|
+
})
|
|
24
|
+
.superRefine((recipient, ctx) => {
|
|
25
|
+
if (recipient.status === "succeeded" && !recipient.outputPath) {
|
|
26
|
+
ctx.addIssue({
|
|
27
|
+
code: z.ZodIssueCode.custom,
|
|
28
|
+
path: ["outputPath"],
|
|
29
|
+
message: "succeeded message recipients must persist `outputPath`",
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
validateOperationLifecycleTimestamps({
|
|
33
|
+
status: recipient.status,
|
|
34
|
+
startedAt: recipient.startedAt,
|
|
35
|
+
completedAt: recipient.completedAt,
|
|
36
|
+
}, ctx, {
|
|
37
|
+
queued: ["queued"],
|
|
38
|
+
running: ["running"],
|
|
39
|
+
terminal: TERMINAL_MESSAGE_RECIPIENT_STATUSES,
|
|
40
|
+
});
|
|
41
|
+
});
|
|
42
|
+
export const messageRecordSchema = z
|
|
43
|
+
.object({
|
|
44
|
+
sessionId: z.string(),
|
|
45
|
+
createdAt: z.string(),
|
|
46
|
+
startedAt: z.string(),
|
|
47
|
+
completedAt: z.string().optional(),
|
|
48
|
+
status: messageStatusSchema,
|
|
49
|
+
baseRevisionSha: z.string().optional(),
|
|
50
|
+
prompt: z.string(),
|
|
51
|
+
sourceInteractiveSessionId: z.string().optional(),
|
|
52
|
+
extraContext: z.array(persistedExtraContextPathSchema).optional(),
|
|
53
|
+
extraContextMetadata: z.array(extraContextMetadataEntrySchema).optional(),
|
|
54
|
+
recipients: z
|
|
55
|
+
.array(messageRecipientEntrySchema)
|
|
56
|
+
.min(1)
|
|
57
|
+
.superRefine((recipients, ctx) => {
|
|
58
|
+
const seen = new Set();
|
|
59
|
+
for (const recipient of recipients) {
|
|
60
|
+
if (seen.has(recipient.agentId)) {
|
|
61
|
+
ctx.addIssue({
|
|
62
|
+
code: z.ZodIssueCode.custom,
|
|
63
|
+
message: `Duplicate message recipient agent id: ${recipient.agentId}`,
|
|
64
|
+
});
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
seen.add(recipient.agentId);
|
|
68
|
+
}
|
|
69
|
+
}),
|
|
70
|
+
error: z.string().nullable().optional(),
|
|
71
|
+
})
|
|
72
|
+
.superRefine((record, ctx) => {
|
|
73
|
+
validateRecordLifecycleTimestamps({
|
|
74
|
+
status: record.status,
|
|
75
|
+
createdAt: record.createdAt,
|
|
76
|
+
startedAt: record.startedAt,
|
|
77
|
+
completedAt: record.completedAt,
|
|
78
|
+
}, ctx, {
|
|
79
|
+
queued: [],
|
|
80
|
+
running: RUNNING_MESSAGE_RECORD_STATUSES,
|
|
81
|
+
terminal: TERMINAL_MESSAGE_STATUSES,
|
|
82
|
+
});
|
|
83
|
+
});
|
|
84
|
+
export function deriveMessageStatusFromRecipients(recipientStatuses) {
|
|
85
|
+
const hasSuccess = recipientStatuses.some((status) => status === "succeeded");
|
|
86
|
+
return hasSuccess ? "succeeded" : "failed";
|
|
87
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type { MessageRecord } from "../model/types.js";
|
|
2
|
+
export type MessageRecordPredicate = (record: MessageRecord) => boolean;
|
|
3
|
+
export interface MessageRecordWarningMissing {
|
|
4
|
+
kind: "missing-record";
|
|
5
|
+
sessionId: string;
|
|
6
|
+
recordPath: string;
|
|
7
|
+
displayPath: string;
|
|
8
|
+
}
|
|
9
|
+
export interface MessageRecordWarningParse {
|
|
10
|
+
kind: "parse-error";
|
|
11
|
+
sessionId: string;
|
|
12
|
+
recordPath: string;
|
|
13
|
+
displayPath: string;
|
|
14
|
+
details: string;
|
|
15
|
+
}
|
|
16
|
+
export type MessageRecordWarning = MessageRecordWarningMissing | MessageRecordWarningParse;
|
|
17
|
+
export interface ReadMessageRecordsOptions {
|
|
18
|
+
root: string;
|
|
19
|
+
messagesFilePath: string;
|
|
20
|
+
limit?: number;
|
|
21
|
+
predicate?: MessageRecordPredicate;
|
|
22
|
+
onWarning?: (warning: MessageRecordWarning) => void;
|
|
23
|
+
}
|
|
24
|
+
export interface RewriteMessageRecordOptions {
|
|
25
|
+
root: string;
|
|
26
|
+
messagesFilePath: string;
|
|
27
|
+
sessionId: string;
|
|
28
|
+
mutate: (record: MessageRecord) => MessageRecord;
|
|
29
|
+
forceFlush?: boolean;
|
|
30
|
+
}
|
|
31
|
+
export interface AppendMessageRecordOptions {
|
|
32
|
+
root: string;
|
|
33
|
+
messagesFilePath: string;
|
|
34
|
+
record: MessageRecord;
|
|
35
|
+
}
|
|
36
|
+
export declare function readMessageRecords(options: ReadMessageRecordsOptions): Promise<MessageRecord[]>;
|
|
37
|
+
export declare function appendMessageRecord(options: AppendMessageRecordOptions): Promise<void>;
|
|
38
|
+
export declare function rewriteMessageRecord(options: RewriteMessageRecordOptions): Promise<MessageRecord>;
|
|
39
|
+
export declare function flushMessageRecordBuffer(options: {
|
|
40
|
+
messagesFilePath: string;
|
|
41
|
+
sessionId: string;
|
|
42
|
+
}): Promise<void>;
|
|
43
|
+
export declare function flushAllMessageRecordBuffers(): Promise<void>;
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import { dirname, join } from "node:path";
|
|
2
|
+
import { mapSessionStoreError, sessionStoreErrorMapper, } from "../../../persistence/error-mapping.js";
|
|
3
|
+
import { SessionRecordParseError } from "../../../persistence/errors.js";
|
|
4
|
+
import { acquireHistoryLock } from "../../../persistence/history-lock.js";
|
|
5
|
+
import { createSessionStore, } from "../../../persistence/session-store.js";
|
|
6
|
+
import { messageRecordSchema, TERMINAL_MESSAGE_STATUSES, } from "../model/types.js";
|
|
7
|
+
const MESSAGE_INDEX_VERSION = 1;
|
|
8
|
+
const MESSAGE_RECORD_FILENAME = "record.json";
|
|
9
|
+
const MESSAGE_HISTORY_LOCK_FILENAME = "history.lock";
|
|
10
|
+
const messagePersistence = createSessionStore({
|
|
11
|
+
recordFilename: MESSAGE_RECORD_FILENAME,
|
|
12
|
+
indexVersion: MESSAGE_INDEX_VERSION,
|
|
13
|
+
acquireLock: acquireHistoryLock,
|
|
14
|
+
parseRecord: ({ path, raw }) => {
|
|
15
|
+
const parsed = JSON.parse(raw);
|
|
16
|
+
const result = messageRecordSchema.safeParse(parsed);
|
|
17
|
+
if (!result.success) {
|
|
18
|
+
const issues = result.error.issues
|
|
19
|
+
.map((issue) => issue.message)
|
|
20
|
+
.join(", ");
|
|
21
|
+
throw new SessionRecordParseError(path, issues);
|
|
22
|
+
}
|
|
23
|
+
return result.data;
|
|
24
|
+
},
|
|
25
|
+
buildIndexEntry: (record) => ({
|
|
26
|
+
sessionId: record.sessionId,
|
|
27
|
+
createdAt: record.createdAt,
|
|
28
|
+
status: record.status,
|
|
29
|
+
}),
|
|
30
|
+
getIndexEntryId: (entry) => entry.sessionId,
|
|
31
|
+
shouldForceFlush: (record) => TERMINAL_MESSAGE_STATUSES.includes(record.status),
|
|
32
|
+
getRecordId: (record) => record.sessionId,
|
|
33
|
+
getRecordStatus: (record) => record.status,
|
|
34
|
+
readIndexEntries: (parsed) => {
|
|
35
|
+
const payload = parsed;
|
|
36
|
+
return Array.isArray(payload.sessions) ? payload.sessions : [];
|
|
37
|
+
},
|
|
38
|
+
});
|
|
39
|
+
export async function readMessageRecords(options) {
|
|
40
|
+
const { root, messagesFilePath, limit, predicate, onWarning } = options;
|
|
41
|
+
const paths = buildMessagePaths(root, messagesFilePath);
|
|
42
|
+
try {
|
|
43
|
+
return await messagePersistence.readRecords({
|
|
44
|
+
paths,
|
|
45
|
+
limit,
|
|
46
|
+
predicate,
|
|
47
|
+
onWarning: onWarning
|
|
48
|
+
? (warning) => onWarning(mapWarning(warning))
|
|
49
|
+
: undefined,
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
catch (error) {
|
|
53
|
+
throw mapSessionStoreError(error, sessionStoreErrorMapper);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
export async function appendMessageRecord(options) {
|
|
57
|
+
const { root, messagesFilePath, record } = options;
|
|
58
|
+
const paths = buildMessagePaths(root, messagesFilePath);
|
|
59
|
+
try {
|
|
60
|
+
await messagePersistence.appendRecord({ paths, record });
|
|
61
|
+
}
|
|
62
|
+
catch (error) {
|
|
63
|
+
throw mapSessionStoreError(error, sessionStoreErrorMapper);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
export async function rewriteMessageRecord(options) {
|
|
67
|
+
const { root, messagesFilePath, sessionId, mutate, forceFlush = false, } = options;
|
|
68
|
+
const paths = buildMessagePaths(root, messagesFilePath);
|
|
69
|
+
try {
|
|
70
|
+
return await messagePersistence.rewriteRecord({
|
|
71
|
+
paths,
|
|
72
|
+
sessionId,
|
|
73
|
+
mutate,
|
|
74
|
+
forceFlush,
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
catch (error) {
|
|
78
|
+
throw mapSessionStoreError(error, sessionStoreErrorMapper);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
export async function flushMessageRecordBuffer(options) {
|
|
82
|
+
const { messagesFilePath, sessionId } = options;
|
|
83
|
+
const paths = buildMessagePaths("", messagesFilePath);
|
|
84
|
+
try {
|
|
85
|
+
await messagePersistence.flushRecordBuffer({ paths, sessionId });
|
|
86
|
+
}
|
|
87
|
+
catch (error) {
|
|
88
|
+
throw mapSessionStoreError(error, sessionStoreErrorMapper);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
export async function flushAllMessageRecordBuffers() {
|
|
92
|
+
try {
|
|
93
|
+
await messagePersistence.flushAllRecordBuffers();
|
|
94
|
+
}
|
|
95
|
+
catch (error) {
|
|
96
|
+
throw mapSessionStoreError(error, sessionStoreErrorMapper);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
function buildMessagePaths(root, messagesFilePath) {
|
|
100
|
+
const messagesRoot = dirname(messagesFilePath);
|
|
101
|
+
return {
|
|
102
|
+
root,
|
|
103
|
+
indexPath: messagesFilePath,
|
|
104
|
+
sessionsDir: join(messagesRoot, "sessions"),
|
|
105
|
+
lockPath: join(messagesRoot, MESSAGE_HISTORY_LOCK_FILENAME),
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
function mapWarning(warning) {
|
|
109
|
+
if (warning.kind === "parse-error") {
|
|
110
|
+
return {
|
|
111
|
+
kind: "parse-error",
|
|
112
|
+
sessionId: warning.sessionId,
|
|
113
|
+
recordPath: warning.recordPath,
|
|
114
|
+
displayPath: warning.displayPath,
|
|
115
|
+
details: warning.details,
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
return {
|
|
119
|
+
kind: "missing-record",
|
|
120
|
+
sessionId: warning.sessionId,
|
|
121
|
+
recordPath: warning.recordPath,
|
|
122
|
+
displayPath: warning.displayPath,
|
|
123
|
+
};
|
|
124
|
+
}
|
|
@@ -31,6 +31,7 @@ export interface CreateReduceCompetitionAdapterInput {
|
|
|
31
31
|
readonly reductionsFilePath: string;
|
|
32
32
|
readonly specsFilePath: string;
|
|
33
33
|
readonly runsFilePath: string;
|
|
34
|
+
readonly messagesFilePath: string;
|
|
34
35
|
readonly verificationsFilePath: string;
|
|
35
36
|
readonly target: ReductionTarget;
|
|
36
37
|
readonly environment: EnvironmentConfig;
|
|
@@ -7,6 +7,7 @@ import { RunNotFoundCliError } from "../../../cli/errors.js";
|
|
|
7
7
|
import { stageExtraContextFiles, } from "../../../competition/shared/extra-context.js";
|
|
8
8
|
import { composeStageSandboxPolicy } from "../../../competition/shared/sandbox-policy.js";
|
|
9
9
|
import { createTeardownController, runTeardown, } from "../../../competition/shared/teardown.js";
|
|
10
|
+
import { readMessageRecords } from "../../../domain/message/persistence/adapter.js";
|
|
10
11
|
import { validateReductionOutputContract } from "../../../domain/reduce/competition/output-validation.js";
|
|
11
12
|
import { buildReducePrompt } from "../../../domain/reduce/competition/prompt.js";
|
|
12
13
|
import { parseReductionArtifact } from "../../../domain/reduce/competition/reduction.js";
|
|
@@ -25,9 +26,9 @@ import { normalizePathForDisplay, relativeToRoot, resolvePath, } from "../../../
|
|
|
25
26
|
import { extractProviderNativeTokenUsageForSession } from "../../../workspace/chat/native-usage.js";
|
|
26
27
|
import { scaffoldAgentSessionWorkspace, } from "../../../workspace/layout.js";
|
|
27
28
|
import { promoteWorkspaceFile } from "../../../workspace/promotion.js";
|
|
28
|
-
import { REDUCTION_ARTIFACT_INFO_FILENAME, REDUCTION_DATA_FILENAME, REDUCTION_FILENAME, VORATIQ_REDUCTION_DIR, } from "../../../workspace/structure.js";
|
|
29
|
+
import { MESSAGE_RESPONSE_FILENAME, REDUCTION_ARTIFACT_INFO_FILENAME, REDUCTION_DATA_FILENAME, REDUCTION_FILENAME, VORATIQ_REDUCTION_DIR, } from "../../../workspace/structure.js";
|
|
29
30
|
export function createReduceCompetitionAdapter(input) {
|
|
30
|
-
const { root, reductionId, createdAt, reductionsFilePath, specsFilePath, runsFilePath, verificationsFilePath, target, environment, extraContextFiles = [], renderer, } = input;
|
|
31
|
+
const { root, reductionId, createdAt, reductionsFilePath, specsFilePath, runsFilePath, messagesFilePath, verificationsFilePath, target, environment, extraContextFiles = [], renderer, } = input;
|
|
31
32
|
let failure;
|
|
32
33
|
const teardown = createTeardownController(`reduce \`${reductionId}\``);
|
|
33
34
|
teardown.addAction({
|
|
@@ -55,6 +56,7 @@ export function createReduceCompetitionAdapter(input) {
|
|
|
55
56
|
root,
|
|
56
57
|
specsFilePath,
|
|
57
58
|
runsFilePath,
|
|
59
|
+
messagesFilePath,
|
|
58
60
|
verificationsFilePath,
|
|
59
61
|
reductionsFilePath,
|
|
60
62
|
target,
|
|
@@ -443,10 +445,12 @@ async function prepareReductionTargetContext(options) {
|
|
|
443
445
|
return await prepareSpecTargetContext(options);
|
|
444
446
|
case "run":
|
|
445
447
|
return await prepareRunTargetContext(options);
|
|
446
|
-
case "verify":
|
|
447
|
-
return await prepareVerificationTargetContext(options);
|
|
448
448
|
case "reduce":
|
|
449
449
|
return await prepareReductionTargetContextInternal(options);
|
|
450
|
+
case "verify":
|
|
451
|
+
return await prepareVerificationTargetContext(options);
|
|
452
|
+
case "message":
|
|
453
|
+
return await prepareMessageTargetContext(options);
|
|
450
454
|
}
|
|
451
455
|
}
|
|
452
456
|
async function prepareSpecTargetContext(options) {
|
|
@@ -682,6 +686,55 @@ async function prepareReductionTargetContextInternal(options) {
|
|
|
682
686
|
},
|
|
683
687
|
};
|
|
684
688
|
}
|
|
689
|
+
async function prepareMessageTargetContext(options) {
|
|
690
|
+
const { root, messagesFilePath, target } = options;
|
|
691
|
+
const [record] = await readMessageRecords({
|
|
692
|
+
root,
|
|
693
|
+
messagesFilePath,
|
|
694
|
+
limit: 1,
|
|
695
|
+
predicate: (entry) => entry.sessionId === target.id,
|
|
696
|
+
});
|
|
697
|
+
if (!record) {
|
|
698
|
+
throw new Error(`Message session \`${target.id}\` not found.`);
|
|
699
|
+
}
|
|
700
|
+
const succeededRecipients = record.recipients.filter((recipient) => recipient.status === "succeeded" &&
|
|
701
|
+
typeof recipient.outputPath === "string");
|
|
702
|
+
if (succeededRecipients.length === 0) {
|
|
703
|
+
throw new Error(`Message session \`${target.id}\` has no generated artifacts.`);
|
|
704
|
+
}
|
|
705
|
+
const stagedFiles = [];
|
|
706
|
+
const artifacts = [];
|
|
707
|
+
for (const recipient of succeededRecipients) {
|
|
708
|
+
const outputRelative = `inputs/recipients/${recipient.agentId}/${MESSAGE_RESPONSE_FILENAME}`;
|
|
709
|
+
stagedFiles.push({
|
|
710
|
+
sourceAbsolutePath: resolvePath(root, recipient.outputPath),
|
|
711
|
+
stagedRelativePath: outputRelative,
|
|
712
|
+
});
|
|
713
|
+
artifacts.push({
|
|
714
|
+
artifactId: `message:${recipient.agentId}`,
|
|
715
|
+
kind: "message-output",
|
|
716
|
+
agentId: recipient.agentId,
|
|
717
|
+
status: recipient.status,
|
|
718
|
+
outputPath: outputRelative,
|
|
719
|
+
...(recipient.tokenUsage ? { tokenUsage: recipient.tokenUsage } : {}),
|
|
720
|
+
});
|
|
721
|
+
}
|
|
722
|
+
return {
|
|
723
|
+
target,
|
|
724
|
+
displayPath: `.voratiq/message/sessions/${record.sessionId}`,
|
|
725
|
+
stagedFiles,
|
|
726
|
+
manifest: {
|
|
727
|
+
target: {
|
|
728
|
+
operator: "message",
|
|
729
|
+
id: record.sessionId,
|
|
730
|
+
path: `.voratiq/message/sessions/${record.sessionId}`,
|
|
731
|
+
status: record.status,
|
|
732
|
+
prompt: record.prompt,
|
|
733
|
+
},
|
|
734
|
+
artifacts,
|
|
735
|
+
},
|
|
736
|
+
};
|
|
737
|
+
}
|
|
685
738
|
async function stageReductionTargetContext(options) {
|
|
686
739
|
const { workspacePath, targetContext } = options;
|
|
687
740
|
for (const stagedFile of targetContext.stagedFiles) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type ResolvedExtraContextFile } from "../../../competition/shared/extra-context.js";
|
|
2
2
|
export interface BuildReducePromptOptions {
|
|
3
|
-
targetOperator: "spec" | "run" | "verify" | "
|
|
3
|
+
targetOperator: "spec" | "run" | "reduce" | "verify" | "message";
|
|
4
4
|
targetId: string;
|
|
5
5
|
artifactInfoPath: string;
|
|
6
6
|
repoRootPath: string;
|
|
@@ -3,6 +3,7 @@ import { type ReductionStatus, reductionStatusSchema, TERMINAL_REDUCTION_STATUSE
|
|
|
3
3
|
export type { ReductionStatus };
|
|
4
4
|
export { reductionStatusSchema, TERMINAL_REDUCTION_STATUSES };
|
|
5
5
|
export declare const reductionTargetTypeSchema: z.ZodEnum<{
|
|
6
|
+
message: "message";
|
|
6
7
|
reduce: "reduce";
|
|
7
8
|
spec: "spec";
|
|
8
9
|
run: "run";
|
|
@@ -11,6 +12,7 @@ export declare const reductionTargetTypeSchema: z.ZodEnum<{
|
|
|
11
12
|
export type ReductionTargetType = z.infer<typeof reductionTargetTypeSchema>;
|
|
12
13
|
export declare const reductionTargetSchema: z.ZodObject<{
|
|
13
14
|
type: z.ZodEnum<{
|
|
15
|
+
message: "message";
|
|
14
16
|
reduce: "reduce";
|
|
15
17
|
spec: "spec";
|
|
16
18
|
run: "run";
|
|
@@ -57,6 +59,7 @@ export declare const reductionRecordSchema: z.ZodObject<{
|
|
|
57
59
|
sessionId: z.ZodString;
|
|
58
60
|
target: z.ZodObject<{
|
|
59
61
|
type: z.ZodEnum<{
|
|
62
|
+
message: "message";
|
|
60
63
|
reduce: "reduce";
|
|
61
64
|
spec: "spec";
|
|
62
65
|
run: "run";
|
|
@@ -17,7 +17,7 @@ import { verificationResultArtifactSchema, } from "../model/types.js";
|
|
|
17
17
|
import { writeVerificationArtifact } from "./artifacts.js";
|
|
18
18
|
import { assertNoVerificationIdentityLeak, assertRubricResultSelectorsMatchAliasMap, buildForbiddenVerificationIdentityTokens, parseRubricResultPayload, } from "./blinding.js";
|
|
19
19
|
import { buildRubricPrompt } from "./prompt.js";
|
|
20
|
-
import { attachVerifierWorkspaceMounts, buildStagedVerificationInputs, } from "./shared-layout.js";
|
|
20
|
+
import { attachVerifierWorkspaceMounts, buildStagedVerificationInputs, sharedInputsUseReferenceRepo, } from "./shared-layout.js";
|
|
21
21
|
export function createVerifyCompetitionAdapter(input) {
|
|
22
22
|
const { root, verificationId, resolvedTarget, aliasMap, environment, extraContextFiles, sharedInputs, teardown, mutators, renderer, } = input;
|
|
23
23
|
const startedAtByExecutionKey = new Map();
|
|
@@ -94,8 +94,7 @@ export function createVerifyCompetitionAdapter(input) {
|
|
|
94
94
|
await attachVerifierWorkspaceMounts({
|
|
95
95
|
workspacePath: workspacePaths.workspacePath,
|
|
96
96
|
contextPath: workspacePaths.contextPath,
|
|
97
|
-
|
|
98
|
-
referenceRepoAbsolute: sharedInputs.referenceRepoAbsolute,
|
|
97
|
+
sharedInputs,
|
|
99
98
|
});
|
|
100
99
|
await ensureWorkspaceDependencies({
|
|
101
100
|
root,
|
|
@@ -131,9 +130,13 @@ export function createVerifyCompetitionAdapter(input) {
|
|
|
131
130
|
workspacePaths.contextPath,
|
|
132
131
|
join(workspacePaths.workspacePath, "context"),
|
|
133
132
|
join(workspacePaths.workspacePath, "inputs"),
|
|
134
|
-
join(workspacePaths.workspacePath, "reference_repo"),
|
|
135
133
|
sharedInputs.sharedInputsAbsolute,
|
|
136
|
-
sharedInputs
|
|
134
|
+
...(sharedInputsUseReferenceRepo(sharedInputs)
|
|
135
|
+
? [
|
|
136
|
+
join(workspacePaths.workspacePath, "reference_repo"),
|
|
137
|
+
sharedInputs.referenceRepoAbsolute,
|
|
138
|
+
]
|
|
139
|
+
: []),
|
|
137
140
|
],
|
|
138
141
|
});
|
|
139
142
|
const result = await runSandboxedAgent({
|
|
@@ -277,6 +277,9 @@ function resolveProgrammaticMethodPlan(options) {
|
|
|
277
277
|
checks,
|
|
278
278
|
};
|
|
279
279
|
}
|
|
280
|
+
if (resolvedTarget.target.kind === "message") {
|
|
281
|
+
return { kind: "none" };
|
|
282
|
+
}
|
|
280
283
|
const configuredChecks = extractUnsupportedProgrammaticChecks(resolvedTarget.target.kind === "spec"
|
|
281
284
|
? verificationConfig.spec
|
|
282
285
|
: verificationConfig.reduce);
|
|
@@ -38,6 +38,12 @@ export function buildRubricPrompt(options) {
|
|
|
38
38
|
return ` - ${candidate.alias}${suffix}`;
|
|
39
39
|
}));
|
|
40
40
|
}
|
|
41
|
+
else if (staged.kind === "message") {
|
|
42
|
+
lines.push(`- Original message prompt: \`${staged.promptPath}\``, "- Candidate responses:", ...staged.candidates.map((candidate) => ` - ${candidate.alias}: \`${candidate.responsePath}\``));
|
|
43
|
+
}
|
|
44
|
+
else if (staged.kind === "reduce-no-reference") {
|
|
45
|
+
lines.push(`- No repository snapshot is available for this reduction target because its lineage reaches message session \`${staged.referenceRepoUnavailable.messageSessionId}\` without a durable base revision.`, "- Reduction candidates:", ...staged.candidates.map((candidate) => ` - ${candidate.alias}: \`${candidate.reductionPath}\``));
|
|
46
|
+
}
|
|
41
47
|
else {
|
|
42
48
|
lines.push(`- Base repository snapshot (read-only): \`${staged.referenceRepoPath}/\``, "- Reduction candidates:", ...staged.candidates.map((candidate) => ` - ${candidate.alias}: \`${candidate.reductionPath}\``));
|
|
43
49
|
}
|
|
@@ -8,7 +8,13 @@ export async function executeAndPersistRubricMethods(options) {
|
|
|
8
8
|
? verificationConfig.spec.rubric
|
|
9
9
|
: resolvedTarget.target.kind === "run"
|
|
10
10
|
? verificationConfig.run.rubric
|
|
11
|
-
:
|
|
11
|
+
: resolvedTarget.target.kind === "reduce"
|
|
12
|
+
? verificationConfig.reduce.rubric
|
|
13
|
+
: verificationConfig.message.rubric;
|
|
14
|
+
if (resolvedTarget.target.kind === "message" &&
|
|
15
|
+
rubricTemplates.length === 0) {
|
|
16
|
+
throw new Error("Message verification requires at least one configured rubric template under `message.rubric` in `.voratiq/verification.yaml`.");
|
|
17
|
+
}
|
|
12
18
|
if (rubricTemplates.length === 0 || verifierAgents.length === 0) {
|
|
13
19
|
return [];
|
|
14
20
|
}
|
|
@@ -31,6 +31,27 @@ export type SharedVerificationInputs = {
|
|
|
31
31
|
candidates: readonly {
|
|
32
32
|
alias: string;
|
|
33
33
|
}[];
|
|
34
|
+
} | {
|
|
35
|
+
kind: "reduce-no-reference";
|
|
36
|
+
sharedRootAbsolute: string;
|
|
37
|
+
sharedInputsAbsolute: string;
|
|
38
|
+
worktreesToRemove: readonly string[];
|
|
39
|
+
referenceRepoUnavailable: {
|
|
40
|
+
reason: "message-lineage";
|
|
41
|
+
messageSessionId: string;
|
|
42
|
+
};
|
|
43
|
+
candidates: readonly {
|
|
44
|
+
alias: string;
|
|
45
|
+
}[];
|
|
46
|
+
} | {
|
|
47
|
+
kind: "message";
|
|
48
|
+
sharedRootAbsolute: string;
|
|
49
|
+
sharedInputsAbsolute: string;
|
|
50
|
+
worktreesToRemove: readonly string[];
|
|
51
|
+
promptAbsolute: string;
|
|
52
|
+
candidates: readonly {
|
|
53
|
+
alias: string;
|
|
54
|
+
}[];
|
|
34
55
|
};
|
|
35
56
|
export type StagedVerificationInputs = {
|
|
36
57
|
kind: "spec";
|
|
@@ -57,6 +78,23 @@ export type StagedVerificationInputs = {
|
|
|
57
78
|
alias: string;
|
|
58
79
|
reductionPath: string;
|
|
59
80
|
}[];
|
|
81
|
+
} | {
|
|
82
|
+
kind: "reduce-no-reference";
|
|
83
|
+
referenceRepoUnavailable: {
|
|
84
|
+
reason: "message-lineage";
|
|
85
|
+
messageSessionId: string;
|
|
86
|
+
};
|
|
87
|
+
candidates: readonly {
|
|
88
|
+
alias: string;
|
|
89
|
+
reductionPath: string;
|
|
90
|
+
}[];
|
|
91
|
+
} | {
|
|
92
|
+
kind: "message";
|
|
93
|
+
promptPath: string;
|
|
94
|
+
candidates: readonly {
|
|
95
|
+
alias: string;
|
|
96
|
+
responsePath: string;
|
|
97
|
+
}[];
|
|
60
98
|
};
|
|
61
99
|
export declare function prepareSharedVerificationInputs(options: {
|
|
62
100
|
root: string;
|
|
@@ -73,9 +111,11 @@ export declare function buildStagedVerificationInputs(options: {
|
|
|
73
111
|
workspacePaths: AgentWorkspacePaths;
|
|
74
112
|
sharedInputs: SharedVerificationInputs;
|
|
75
113
|
}): StagedVerificationInputs;
|
|
114
|
+
export declare function sharedInputsUseReferenceRepo(sharedInputs: SharedVerificationInputs): sharedInputs is Extract<SharedVerificationInputs, {
|
|
115
|
+
kind: "spec" | "run" | "reduce";
|
|
116
|
+
}>;
|
|
76
117
|
export declare function attachVerifierWorkspaceMounts(options: {
|
|
77
118
|
workspacePath: string;
|
|
78
119
|
contextPath: string;
|
|
79
|
-
|
|
80
|
-
referenceRepoAbsolute: string;
|
|
120
|
+
sharedInputs: SharedVerificationInputs;
|
|
81
121
|
}): Promise<void>;
|