ralph-research 0.1.2 → 0.1.3
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 +127 -101
- package/dist/adapters/fs/json-file-research-project-defaults-store.d.ts +8 -0
- package/dist/adapters/fs/json-file-research-project-defaults-store.js +30 -0
- package/dist/adapters/fs/json-file-research-project-defaults-store.js.map +1 -0
- package/dist/adapters/fs/json-file-research-session-repository.d.ts +24 -0
- package/dist/adapters/fs/json-file-research-session-repository.js +199 -0
- package/dist/adapters/fs/json-file-research-session-repository.js.map +1 -0
- package/dist/adapters/fs/manifest-loader.js +8 -1
- package/dist/adapters/fs/manifest-loader.js.map +1 -1
- package/dist/adapters/proposer/codex-cli-proposer.d.ts +16 -0
- package/dist/adapters/proposer/codex-cli-proposer.js +106 -0
- package/dist/adapters/proposer/codex-cli-proposer.js.map +1 -0
- package/dist/adapters/proposer/codex-cli-session-driver.d.ts +64 -0
- package/dist/adapters/proposer/codex-cli-session-driver.js +182 -0
- package/dist/adapters/proposer/codex-cli-session-driver.js.map +1 -0
- package/dist/adapters/proposer/codex-cli-session-manager.d.ts +79 -0
- package/dist/adapters/proposer/codex-cli-session-manager.js +248 -0
- package/dist/adapters/proposer/codex-cli-session-manager.js.map +1 -0
- package/dist/adapters/proposer/codex-cli-session-outcome-extractor.d.ts +3 -0
- package/dist/adapters/proposer/codex-cli-session-outcome-extractor.js +94 -0
- package/dist/adapters/proposer/codex-cli-session-outcome-extractor.js.map +1 -0
- package/dist/adapters/proposer/proposer-factory.d.ts +22 -0
- package/dist/adapters/proposer/proposer-factory.js +19 -0
- package/dist/adapters/proposer/proposer-factory.js.map +1 -0
- package/dist/app/services/codex-cli-session-lifecycle-service.d.ts +116 -0
- package/dist/app/services/codex-cli-session-lifecycle-service.js +186 -0
- package/dist/app/services/codex-cli-session-lifecycle-service.js.map +1 -0
- package/dist/app/services/research-project-defaults-service.d.ts +18 -0
- package/dist/app/services/research-project-defaults-service.js +175 -0
- package/dist/app/services/research-project-defaults-service.js.map +1 -0
- package/dist/app/services/research-session-draft-service.d.ts +121 -0
- package/dist/app/services/research-session-draft-service.js +846 -0
- package/dist/app/services/research-session-draft-service.js.map +1 -0
- package/dist/app/services/research-session-entry-flow-summary-mapper.d.ts +12 -0
- package/dist/app/services/research-session-entry-flow-summary-mapper.js +33 -0
- package/dist/app/services/research-session-entry-flow-summary-mapper.js.map +1 -0
- package/dist/app/services/research-session-interactive-service.d.ts +35 -0
- package/dist/app/services/research-session-interactive-service.js +295 -0
- package/dist/app/services/research-session-interactive-service.js.map +1 -0
- package/dist/app/services/research-session-launch-service.d.ts +46 -0
- package/dist/app/services/research-session-launch-service.js +389 -0
- package/dist/app/services/research-session-launch-service.js.map +1 -0
- package/dist/app/services/research-session-orchestrator-service.d.ts +140 -0
- package/dist/app/services/research-session-orchestrator-service.js +614 -0
- package/dist/app/services/research-session-orchestrator-service.js.map +1 -0
- package/dist/app/services/research-session-recovery-service.d.ts +30 -0
- package/dist/app/services/research-session-recovery-service.js +110 -0
- package/dist/app/services/research-session-recovery-service.js.map +1 -0
- package/dist/app/services/research-session-wizard-controller.d.ts +51 -0
- package/dist/app/services/research-session-wizard-controller.js +220 -0
- package/dist/app/services/research-session-wizard-controller.js.map +1 -0
- package/dist/app/services/run-cycle-service.d.ts +2 -0
- package/dist/app/services/run-cycle-service.js +2 -0
- package/dist/app/services/run-cycle-service.js.map +1 -1
- package/dist/cli/commands/inspect.js +2 -0
- package/dist/cli/commands/inspect.js.map +1 -1
- package/dist/cli/commands/launch.d.ts +16 -0
- package/dist/cli/commands/launch.js +68 -0
- package/dist/cli/commands/launch.js.map +1 -0
- package/dist/cli/commands/proposer-display.d.ts +2 -0
- package/dist/cli/commands/proposer-display.js +18 -0
- package/dist/cli/commands/proposer-display.js.map +1 -0
- package/dist/cli/commands/resume.d.ts +14 -0
- package/dist/cli/commands/resume.js +134 -0
- package/dist/cli/commands/resume.js.map +1 -0
- package/dist/cli/commands/run.d.ts +1 -1
- package/dist/cli/commands/run.js +2 -2
- package/dist/cli/commands/run.js.map +1 -1
- package/dist/cli/commands/status.js +4 -0
- package/dist/cli/commands/status.js.map +1 -1
- package/dist/cli/main.js +2 -29
- package/dist/cli/main.js.map +1 -1
- package/dist/cli/program.d.ts +15 -0
- package/dist/cli/program.js +54 -0
- package/dist/cli/program.js.map +1 -0
- package/dist/cli/tui/research-session-shell.d.ts +22 -0
- package/dist/cli/tui/research-session-shell.js +719 -0
- package/dist/cli/tui/research-session-shell.js.map +1 -0
- package/dist/core/engine/cycle-runner.d.ts +4 -0
- package/dist/core/engine/cycle-runner.js +15 -9
- package/dist/core/engine/cycle-runner.js.map +1 -1
- package/dist/core/manifest/admission.d.ts +1 -0
- package/dist/core/manifest/admission.js +50 -0
- package/dist/core/manifest/admission.js.map +1 -1
- package/dist/core/manifest/defaults.d.ts +21 -0
- package/dist/core/manifest/defaults.js +21 -0
- package/dist/core/manifest/defaults.js.map +1 -1
- package/dist/core/manifest/schema.d.ts +170 -0
- package/dist/core/manifest/schema.js +21 -1
- package/dist/core/manifest/schema.js.map +1 -1
- package/dist/core/model/codex-cli-cycle-session.d.ts +4 -0
- package/dist/core/model/codex-cli-cycle-session.js +2 -0
- package/dist/core/model/codex-cli-cycle-session.js.map +1 -0
- package/dist/core/model/codex-cli-session-lifecycle.d.ts +131 -0
- package/dist/core/model/codex-cli-session-lifecycle.js +237 -0
- package/dist/core/model/codex-cli-session-lifecycle.js.map +1 -0
- package/dist/core/model/codex-cli-session-outcome.d.ts +121 -0
- package/dist/core/model/codex-cli-session-outcome.js +70 -0
- package/dist/core/model/codex-cli-session-outcome.js.map +1 -0
- package/dist/core/model/research-project-defaults.d.ts +48 -0
- package/dist/core/model/research-project-defaults.js +46 -0
- package/dist/core/model/research-project-defaults.js.map +1 -0
- package/dist/core/model/research-session.d.ts +1143 -0
- package/dist/core/model/research-session.js +689 -0
- package/dist/core/model/research-session.js.map +1 -0
- package/dist/core/model/run-record.d.ts +56 -6
- package/dist/core/model/run-record.js +28 -0
- package/dist/core/model/run-record.js.map +1 -1
- package/dist/core/ports/research-project-defaults-store.d.ts +5 -0
- package/dist/core/ports/research-project-defaults-store.js +2 -0
- package/dist/core/ports/research-project-defaults-store.js.map +1 -0
- package/dist/core/ports/research-session-repository.d.ts +25 -0
- package/dist/core/ports/research-session-repository.js +2 -0
- package/dist/core/ports/research-session-repository.js.map +1 -0
- package/dist/core/state/research-session-recovery-classifier.d.ts +24 -0
- package/dist/core/state/research-session-recovery-classifier.js +236 -0
- package/dist/core/state/research-session-recovery-classifier.js.map +1 -0
- package/dist/core/state/research-session-resume-candidate.d.ts +8 -0
- package/dist/core/state/research-session-resume-candidate.js +62 -0
- package/dist/core/state/research-session-resume-candidate.js.map +1 -0
- package/dist/core/state/research-session-state-machine.d.ts +62 -0
- package/dist/core/state/research-session-state-machine.js +443 -0
- package/dist/core/state/research-session-state-machine.js.map +1 -0
- package/dist/mcp/server.d.ts +4 -0
- package/dist/mcp/server.js +192 -1
- package/dist/mcp/server.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
import { ResearchSessionRecoveryService, } from "./research-session-recovery-service.js";
|
|
2
|
+
export class CodexCliSessionLifecycleService {
|
|
3
|
+
recoveryService;
|
|
4
|
+
attachabilityValidator;
|
|
5
|
+
constructor(dependencies = {}) {
|
|
6
|
+
this.recoveryService =
|
|
7
|
+
dependencies.recoveryService ??
|
|
8
|
+
dependencies.createRecoveryService?.() ??
|
|
9
|
+
new ResearchSessionRecoveryService();
|
|
10
|
+
this.attachabilityValidator =
|
|
11
|
+
dependencies.attachabilityValidator ?? validateCodexCliSessionAttachability;
|
|
12
|
+
}
|
|
13
|
+
async inspectSession(input) {
|
|
14
|
+
const inspection = await this.recoveryService.inspectSession(input);
|
|
15
|
+
return materializeCodexCliSessionLifecycleInspection(inspection, this.attachabilityValidator(inspection));
|
|
16
|
+
}
|
|
17
|
+
async resolveCycleSession(input) {
|
|
18
|
+
const inspection = await this.recoveryService.inspectSession(input);
|
|
19
|
+
return resolveCodexCliSessionReuseOrReplaceDecision(inspection, this.attachabilityValidator(inspection));
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
export function classifyCodexCliSessionLifecycleInspection(inspection) {
|
|
23
|
+
return materializeCodexCliSessionLifecycleInspection(inspection, validateCodexCliSessionAttachability(inspection));
|
|
24
|
+
}
|
|
25
|
+
export function resolveCodexCliSessionReuseOrReplaceDecision(inspection, attachability = validateCodexCliSessionAttachability(inspection)) {
|
|
26
|
+
const result = materializeCodexCliSessionLifecycleInspection(inspection, attachability);
|
|
27
|
+
if (result.kind === "reusable_attachment_target") {
|
|
28
|
+
if (!inspection.codexSessionReference) {
|
|
29
|
+
throw new Error("Reusable Codex CLI attachments require a persisted Codex session reference");
|
|
30
|
+
}
|
|
31
|
+
return {
|
|
32
|
+
decision: "reuse",
|
|
33
|
+
session: result.session,
|
|
34
|
+
lifecycle: result.lifecycle,
|
|
35
|
+
recovery: result.recovery,
|
|
36
|
+
codexSessionReference: inspection.codexSessionReference,
|
|
37
|
+
reason: result.attachability.reason,
|
|
38
|
+
reuse: result.target,
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
return {
|
|
42
|
+
decision: "replace",
|
|
43
|
+
session: result.session,
|
|
44
|
+
lifecycle: result.lifecycle,
|
|
45
|
+
recovery: result.recovery,
|
|
46
|
+
codexSessionReference: inspection.codexSessionReference,
|
|
47
|
+
reason: result.attachability.reason,
|
|
48
|
+
replace: {
|
|
49
|
+
...result.outcome,
|
|
50
|
+
attachabilityMode: result.attachability.mode,
|
|
51
|
+
},
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
function materializeCodexCliSessionLifecycleInspection(inspection, attachability) {
|
|
55
|
+
const reusableAttachmentFailure = getReusableAttachmentFailure(inspection);
|
|
56
|
+
if (attachability.mode === "attach" && isReusableAttachmentLifecycle(inspection)) {
|
|
57
|
+
return buildReusableAttachmentTarget(inspection, attachability);
|
|
58
|
+
}
|
|
59
|
+
const safeAttachability = attachability.mode === "attach"
|
|
60
|
+
? deriveSafeStaleAttachability(inspection, reusableAttachmentFailure)
|
|
61
|
+
: attachability;
|
|
62
|
+
return buildStaleSessionOutcome(inspection, safeAttachability);
|
|
63
|
+
}
|
|
64
|
+
function buildReusableAttachmentTarget(inspection, attachability) {
|
|
65
|
+
return {
|
|
66
|
+
kind: "reusable_attachment_target",
|
|
67
|
+
session: inspection.session,
|
|
68
|
+
lifecycle: inspection.lifecycle,
|
|
69
|
+
recovery: inspection.recovery,
|
|
70
|
+
attachability,
|
|
71
|
+
target: {
|
|
72
|
+
researchSessionId: inspection.session.sessionId,
|
|
73
|
+
codexSessionId: inspection.lifecycle.identity.codexSessionId,
|
|
74
|
+
pid: inspection.lifecycle.pid,
|
|
75
|
+
phase: inspection.lifecycle.phase,
|
|
76
|
+
command: inspection.lifecycle.command,
|
|
77
|
+
args: [...inspection.lifecycle.args],
|
|
78
|
+
workingDirectory: inspection.lifecycle.workingDirectory,
|
|
79
|
+
attachmentStatus: "bound",
|
|
80
|
+
trackedGlobs: [...inspection.lifecycle.attachmentState.trackedGlobs],
|
|
81
|
+
extraWritableDirectories: [...inspection.lifecycle.attachmentState.extraWritableDirectories],
|
|
82
|
+
tty: { ...inspection.lifecycle.tty },
|
|
83
|
+
...(inspection.lifecycle.references.workspaceRef
|
|
84
|
+
? { workspaceRef: inspection.lifecycle.references.workspaceRef }
|
|
85
|
+
: {}),
|
|
86
|
+
...(inspection.lifecycle.references.workspacePath
|
|
87
|
+
? { workspacePath: inspection.lifecycle.references.workspacePath }
|
|
88
|
+
: {}),
|
|
89
|
+
...(inspection.lifecycle.references.checkpointRunId
|
|
90
|
+
? { checkpointRunId: inspection.lifecycle.references.checkpointRunId }
|
|
91
|
+
: {}),
|
|
92
|
+
...(inspection.lifecycle.references.checkpointDecisionId
|
|
93
|
+
? { checkpointDecisionId: inspection.lifecycle.references.checkpointDecisionId }
|
|
94
|
+
: {}),
|
|
95
|
+
},
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
function buildStaleSessionOutcome(inspection, attachability) {
|
|
99
|
+
return {
|
|
100
|
+
kind: "stale_session_outcome",
|
|
101
|
+
session: inspection.session,
|
|
102
|
+
lifecycle: inspection.lifecycle,
|
|
103
|
+
recovery: inspection.recovery,
|
|
104
|
+
attachability,
|
|
105
|
+
outcome: {
|
|
106
|
+
runtimeState: inspection.recovery.runtime.state,
|
|
107
|
+
completedCycles: inspection.session.progress.completedCycles,
|
|
108
|
+
resumeFromCycle: inspection.session.resume.resumeFromCycle,
|
|
109
|
+
resumable: inspection.recovery.resumeAllowed,
|
|
110
|
+
reason: inspection.recovery.reason,
|
|
111
|
+
...(inspection.lifecycle ? { phase: inspection.lifecycle.phase } : {}),
|
|
112
|
+
...(inspection.lifecycle ? { attachmentStatus: inspection.lifecycle.attachmentState.status } : {}),
|
|
113
|
+
},
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
function deriveSafeStaleAttachability(inspection, reusableAttachmentFailure) {
|
|
117
|
+
if (inspection.recovery.resumeAllowed) {
|
|
118
|
+
return {
|
|
119
|
+
mode: "resume",
|
|
120
|
+
attachable: false,
|
|
121
|
+
resumable: true,
|
|
122
|
+
reason: inspection.recovery.reason,
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
return {
|
|
126
|
+
mode: "inspect",
|
|
127
|
+
attachable: false,
|
|
128
|
+
resumable: false,
|
|
129
|
+
reason: reusableAttachmentFailure ??
|
|
130
|
+
"Codex CLI session looked attachable, but the persisted lifecycle evidence was incomplete",
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
export function validateCodexCliSessionAttachability(inspection) {
|
|
134
|
+
const reusableAttachmentFailure = getReusableAttachmentFailure(inspection);
|
|
135
|
+
if (!reusableAttachmentFailure) {
|
|
136
|
+
return {
|
|
137
|
+
mode: "attach",
|
|
138
|
+
attachable: true,
|
|
139
|
+
resumable: false,
|
|
140
|
+
reason: "Codex CLI session is still live and bound to the persisted working-directory attachment",
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
if (inspection.recovery.resumeAllowed) {
|
|
144
|
+
return {
|
|
145
|
+
mode: "resume",
|
|
146
|
+
attachable: false,
|
|
147
|
+
resumable: true,
|
|
148
|
+
reason: inspection.recovery.reason,
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
return {
|
|
152
|
+
mode: "inspect",
|
|
153
|
+
attachable: false,
|
|
154
|
+
resumable: false,
|
|
155
|
+
reason: reusableAttachmentFailure ?? inspection.recovery.reason,
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
function getReusableAttachmentFailure(inspection) {
|
|
159
|
+
const lifecycle = inspection.lifecycle;
|
|
160
|
+
if (!lifecycle) {
|
|
161
|
+
return inspection.recovery.reason;
|
|
162
|
+
}
|
|
163
|
+
if (!inspection.codexSessionReference) {
|
|
164
|
+
return "Persisted Codex session reference is missing";
|
|
165
|
+
}
|
|
166
|
+
if (inspection.codexSessionReference.codexSessionId !== lifecycle.identity.codexSessionId) {
|
|
167
|
+
return "Persisted Codex session reference does not match the lifecycle codex session id";
|
|
168
|
+
}
|
|
169
|
+
if (!inspection.recovery.runtime.processAlive || inspection.recovery.runtime.state !== "active") {
|
|
170
|
+
return inspection.recovery.reason;
|
|
171
|
+
}
|
|
172
|
+
if (lifecycle.phase !== "starting" && lifecycle.phase !== "running") {
|
|
173
|
+
return `Codex CLI process is live, but lifecycle phase ${lifecycle.phase} cannot accept attachment`;
|
|
174
|
+
}
|
|
175
|
+
if (lifecycle.pid === undefined) {
|
|
176
|
+
return "Codex CLI process is live, but the persisted lifecycle is missing the process id required for attachment";
|
|
177
|
+
}
|
|
178
|
+
if (lifecycle.attachmentState.status !== "bound") {
|
|
179
|
+
return `Codex CLI process is live, but attachmentState.status is ${lifecycle.attachmentState.status} instead of bound`;
|
|
180
|
+
}
|
|
181
|
+
return null;
|
|
182
|
+
}
|
|
183
|
+
function isReusableAttachmentLifecycle(inspection) {
|
|
184
|
+
return getReusableAttachmentFailure(inspection) === null;
|
|
185
|
+
}
|
|
186
|
+
//# sourceMappingURL=codex-cli-session-lifecycle-service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"codex-cli-session-lifecycle-service.js","sourceRoot":"","sources":["../../../src/app/services/codex-cli-session-lifecycle-service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { type ResearchProjectDefaultsRecord } from "../../core/model/research-project-defaults.js";
|
|
2
|
+
import type { ResearchSessionRecord } from "../../core/model/research-session.js";
|
|
3
|
+
import type { ResearchProjectDefaultsStore } from "../../core/ports/research-project-defaults-store.js";
|
|
4
|
+
export interface ResearchProjectDefaultsServiceDependencies {
|
|
5
|
+
now?: () => Date;
|
|
6
|
+
createStore?: (filePath: string) => ResearchProjectDefaultsStore;
|
|
7
|
+
}
|
|
8
|
+
export declare class ResearchProjectDefaultsService {
|
|
9
|
+
private readonly now;
|
|
10
|
+
private readonly createStore;
|
|
11
|
+
constructor(dependencies?: ResearchProjectDefaultsServiceDependencies);
|
|
12
|
+
loadForRepo(repoRoot: string): Promise<ResearchProjectDefaultsRecord | null>;
|
|
13
|
+
saveForSession(input: {
|
|
14
|
+
repoRoot: string;
|
|
15
|
+
session: ResearchSessionRecord;
|
|
16
|
+
}): Promise<ResearchProjectDefaultsRecord>;
|
|
17
|
+
private resolveStore;
|
|
18
|
+
}
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
import { realpath, stat } from "node:fs/promises";
|
|
2
|
+
import { join, resolve } from "node:path";
|
|
3
|
+
import { JsonFileResearchProjectDefaultsStore } from "../../adapters/fs/json-file-research-project-defaults-store.js";
|
|
4
|
+
import { DEFAULT_PROJECT_BASELINE_REF, DEFAULT_RESEARCH_PROJECT_DEFAULTS_FILE, DEFAULT_STORAGE_ROOT, } from "../../core/manifest/defaults.js";
|
|
5
|
+
import { researchProjectDefaultsRecordSchema, } from "../../core/model/research-project-defaults.js";
|
|
6
|
+
export class ResearchProjectDefaultsService {
|
|
7
|
+
now;
|
|
8
|
+
createStore;
|
|
9
|
+
constructor(dependencies = {}) {
|
|
10
|
+
this.now = dependencies.now ?? (() => new Date());
|
|
11
|
+
this.createStore =
|
|
12
|
+
dependencies.createStore ?? ((filePath) => new JsonFileResearchProjectDefaultsStore(filePath));
|
|
13
|
+
}
|
|
14
|
+
async loadForRepo(repoRoot) {
|
|
15
|
+
const { store } = await this.resolveStore(repoRoot);
|
|
16
|
+
return store.load();
|
|
17
|
+
}
|
|
18
|
+
async saveForSession(input) {
|
|
19
|
+
const { store } = await this.resolveStore(input.repoRoot);
|
|
20
|
+
const existing = await store.load();
|
|
21
|
+
const timestamp = this.now().toISOString();
|
|
22
|
+
const contract = deriveProjectDefaultsContract(input.session);
|
|
23
|
+
const record = researchProjectDefaultsRecordSchema.parse({
|
|
24
|
+
recordType: "research_project_defaults",
|
|
25
|
+
version: 1,
|
|
26
|
+
...contract,
|
|
27
|
+
createdAt: existing?.createdAt ?? timestamp,
|
|
28
|
+
updatedAt: timestamp,
|
|
29
|
+
});
|
|
30
|
+
await store.save(record);
|
|
31
|
+
return record;
|
|
32
|
+
}
|
|
33
|
+
async resolveStore(repoRoot) {
|
|
34
|
+
const resolvedRoot = resolve(repoRoot);
|
|
35
|
+
const repoStats = await stat(resolvedRoot).catch(() => null);
|
|
36
|
+
if (!repoStats?.isDirectory()) {
|
|
37
|
+
throw new Error(`Working directory is not a directory: ${resolvedRoot}`);
|
|
38
|
+
}
|
|
39
|
+
const canonicalRepoRoot = await realpath(resolvedRoot);
|
|
40
|
+
const defaultsPath = join(canonicalRepoRoot, DEFAULT_STORAGE_ROOT, DEFAULT_RESEARCH_PROJECT_DEFAULTS_FILE);
|
|
41
|
+
return {
|
|
42
|
+
canonicalRepoRoot,
|
|
43
|
+
store: this.createStore(defaultsPath),
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
function deriveProjectDefaultsContract(session) {
|
|
48
|
+
const permissions = session.draftState?.flowState?.permissions;
|
|
49
|
+
const stopRules = session.draftState?.flowState?.stopRules;
|
|
50
|
+
const outputs = session.draftState?.flowState?.outputs;
|
|
51
|
+
const contextStep = session.draftState?.contextStep;
|
|
52
|
+
const workspaceStep = session.draftState?.workspaceStep;
|
|
53
|
+
const goalStep = session.draftState?.goalStep;
|
|
54
|
+
const agentStep = session.draftState?.agentStep;
|
|
55
|
+
const resolvedModel = resolveOptionalString(outputs?.model ?? agentStep?.model ?? session.agent.model);
|
|
56
|
+
return {
|
|
57
|
+
workingDirectory: resolveRequiredString(permissions?.workingDirectory ?? workspaceStep?.workingDirectory, session.workingDirectory, "Working directory"),
|
|
58
|
+
context: {
|
|
59
|
+
trackableGlobs: resolveStringList(outputs?.trackableGlobs ?? contextStep?.trackableGlobs, session.context.trackableGlobs, "Trackable files"),
|
|
60
|
+
webSearch: resolveWebSearchChoice(permissions?.webSearch ?? contextStep?.webSearch, session.context.webSearch),
|
|
61
|
+
shellCommandAllowlistAdditions: resolveStringList(permissions?.shellCommandAllowlistAdditions ??
|
|
62
|
+
contextStep?.shellCommandAllowlistAdditions, session.context.shellCommandAllowlistAdditions, "Shell allowlist additions", { allowEmpty: true }),
|
|
63
|
+
shellCommandAllowlistRemovals: resolveStringList(permissions?.shellCommandAllowlistRemovals ??
|
|
64
|
+
contextStep?.shellCommandAllowlistRemovals, session.context.shellCommandAllowlistRemovals, "Shell allowlist removals", { allowEmpty: true }),
|
|
65
|
+
},
|
|
66
|
+
workspace: {
|
|
67
|
+
strategy: "git_worktree",
|
|
68
|
+
baseRef: resolveRequiredString(outputs?.baseRef ?? workspaceStep?.baseRef, session.workspace.baseRef ?? DEFAULT_PROJECT_BASELINE_REF, "Baseline ref"),
|
|
69
|
+
},
|
|
70
|
+
agent: {
|
|
71
|
+
type: session.agent.type,
|
|
72
|
+
command: resolveRequiredString(outputs?.agentCommand ?? goalStep?.agentCommand ?? agentStep?.command, session.agent.command, "Agent command"),
|
|
73
|
+
...(resolvedModel ? { model: resolvedModel } : {}),
|
|
74
|
+
approvalPolicy: resolveAgentApprovalPolicy(permissions?.approvalPolicy ?? agentStep?.approvalPolicy, session.agent.approvalPolicy),
|
|
75
|
+
sandboxMode: resolveAgentSandboxMode(permissions?.sandboxMode ?? agentStep?.sandboxMode, session.agent.sandboxMode),
|
|
76
|
+
ttySession: {
|
|
77
|
+
startupTimeoutSec: resolvePositiveInteger(outputs?.startupTimeoutSec ?? agentStep?.startupTimeoutSec, session.agent.ttySession.startupTimeoutSec, "Agent startup timeout"),
|
|
78
|
+
turnTimeoutSec: resolvePositiveInteger(outputs?.turnTimeoutSec ?? agentStep?.turnTimeoutSec, session.agent.ttySession.turnTimeoutSec, "Agent turn timeout"),
|
|
79
|
+
},
|
|
80
|
+
},
|
|
81
|
+
stopPolicy: {
|
|
82
|
+
repeatedFailures: resolvePositiveInteger(stopRules?.repeatedFailures ?? goalStep?.repeatedFailures, session.stopPolicy.repeatedFailures, "Repeated failures threshold"),
|
|
83
|
+
noMeaningfulProgress: resolvePositiveInteger(stopRules?.noMeaningfulProgress ?? goalStep?.noMeaningfulProgress, session.stopPolicy.noMeaningfulProgress, "No-progress threshold"),
|
|
84
|
+
insufficientEvidence: resolvePositiveInteger(stopRules?.insufficientEvidence ?? goalStep?.insufficientEvidence, session.stopPolicy.insufficientEvidence, "Insufficient-evidence threshold"),
|
|
85
|
+
},
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
function resolveRequiredString(draftValue, fallbackValue, label) {
|
|
89
|
+
const normalized = draftValue?.trim() ?? "";
|
|
90
|
+
if (normalized) {
|
|
91
|
+
return normalized;
|
|
92
|
+
}
|
|
93
|
+
const fallback = fallbackValue.trim();
|
|
94
|
+
if (!fallback) {
|
|
95
|
+
throw new Error(`${label} is required`);
|
|
96
|
+
}
|
|
97
|
+
return fallback;
|
|
98
|
+
}
|
|
99
|
+
function resolveOptionalString(value) {
|
|
100
|
+
const normalized = value?.trim() ?? "";
|
|
101
|
+
return normalized ? normalized : undefined;
|
|
102
|
+
}
|
|
103
|
+
function resolveStringList(draftValue, fallback, label, options = {}) {
|
|
104
|
+
if (draftValue === undefined) {
|
|
105
|
+
return [...fallback];
|
|
106
|
+
}
|
|
107
|
+
const values = draftValue
|
|
108
|
+
.split(",")
|
|
109
|
+
.map((entry) => entry.trim())
|
|
110
|
+
.filter((entry) => entry.length > 0);
|
|
111
|
+
if (values.length === 0) {
|
|
112
|
+
if (options.allowEmpty) {
|
|
113
|
+
return [];
|
|
114
|
+
}
|
|
115
|
+
return [...fallback];
|
|
116
|
+
}
|
|
117
|
+
return values;
|
|
118
|
+
}
|
|
119
|
+
function resolveWebSearchChoice(draftValue, fallback) {
|
|
120
|
+
if (draftValue === undefined) {
|
|
121
|
+
return fallback;
|
|
122
|
+
}
|
|
123
|
+
const normalized = draftValue.trim().toLowerCase();
|
|
124
|
+
if (normalized === "enabled") {
|
|
125
|
+
return true;
|
|
126
|
+
}
|
|
127
|
+
if (normalized === "disabled") {
|
|
128
|
+
return false;
|
|
129
|
+
}
|
|
130
|
+
return fallback;
|
|
131
|
+
}
|
|
132
|
+
function resolvePositiveInteger(draftValue, fallback, label) {
|
|
133
|
+
if (draftValue === undefined) {
|
|
134
|
+
return fallback;
|
|
135
|
+
}
|
|
136
|
+
const normalized = draftValue.trim();
|
|
137
|
+
if (!/^\d+$/.test(normalized)) {
|
|
138
|
+
return fallback;
|
|
139
|
+
}
|
|
140
|
+
const value = Number.parseInt(normalized, 10);
|
|
141
|
+
if (value < 1) {
|
|
142
|
+
return fallback;
|
|
143
|
+
}
|
|
144
|
+
return value;
|
|
145
|
+
}
|
|
146
|
+
function resolveAgentApprovalPolicy(draftValue, fallback) {
|
|
147
|
+
if (draftValue === undefined) {
|
|
148
|
+
return fallback;
|
|
149
|
+
}
|
|
150
|
+
const normalized = draftValue.trim();
|
|
151
|
+
switch (normalized) {
|
|
152
|
+
case "never":
|
|
153
|
+
case "on-failure":
|
|
154
|
+
case "on-request":
|
|
155
|
+
case "untrusted":
|
|
156
|
+
return normalized;
|
|
157
|
+
default:
|
|
158
|
+
return fallback;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
function resolveAgentSandboxMode(draftValue, fallback) {
|
|
162
|
+
if (draftValue === undefined) {
|
|
163
|
+
return fallback;
|
|
164
|
+
}
|
|
165
|
+
const normalized = draftValue.trim();
|
|
166
|
+
switch (normalized) {
|
|
167
|
+
case "read-only":
|
|
168
|
+
case "workspace-write":
|
|
169
|
+
case "danger-full-access":
|
|
170
|
+
return normalized;
|
|
171
|
+
default:
|
|
172
|
+
return fallback;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
//# sourceMappingURL=research-project-defaults-service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"research-project-defaults-service.js","sourceRoot":"","sources":["../../../src/app/services/research-project-defaults-service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import type { ResearchSessionRepository } from "../../core/ports/research-session-repository.js";
|
|
2
|
+
import { ResearchProjectDefaultsService } from "./research-project-defaults-service.js";
|
|
3
|
+
export type ResearchSessionDraftStep = "permissions" | "stopRules" | "outputs" | "review";
|
|
4
|
+
export interface ResearchSessionDraft {
|
|
5
|
+
sessionId: string;
|
|
6
|
+
currentStep: ResearchSessionDraftStep;
|
|
7
|
+
completedSteps: ResearchSessionDraftStep[];
|
|
8
|
+
returnToReview: boolean;
|
|
9
|
+
reviewConfirmed: boolean;
|
|
10
|
+
goal: string;
|
|
11
|
+
repoRoot: string;
|
|
12
|
+
workingDirectory: string;
|
|
13
|
+
contextSettings: {
|
|
14
|
+
trackableGlobs: string;
|
|
15
|
+
webSearch: string;
|
|
16
|
+
shellCommandAllowlistAdditions: string;
|
|
17
|
+
shellCommandAllowlistRemovals: string;
|
|
18
|
+
};
|
|
19
|
+
workspaceSettings: {
|
|
20
|
+
baseRef: string;
|
|
21
|
+
};
|
|
22
|
+
agentCommand: string;
|
|
23
|
+
stopPolicy: {
|
|
24
|
+
repeatedFailures: string;
|
|
25
|
+
noMeaningfulProgress: string;
|
|
26
|
+
insufficientEvidence: string;
|
|
27
|
+
};
|
|
28
|
+
agentSettings: {
|
|
29
|
+
model: string;
|
|
30
|
+
approvalPolicy: string;
|
|
31
|
+
sandboxMode: string;
|
|
32
|
+
startupTimeoutSec: string;
|
|
33
|
+
turnTimeoutSec: string;
|
|
34
|
+
};
|
|
35
|
+
reviewState: ResearchSessionReviewState;
|
|
36
|
+
}
|
|
37
|
+
export type ResearchSessionDraftValidationField = "goal" | "repeatedFailures" | "noMeaningfulProgress" | "insufficientEvidence" | "trackableGlobs" | "webSearch" | "shellCommandAllowlistAdditions" | "shellCommandAllowlistRemovals" | "workingDirectory" | "baseRef" | "agentCommand" | "approvalPolicy" | "sandboxMode" | "startupTimeoutSec" | "turnTimeoutSec";
|
|
38
|
+
export interface ResearchSessionDraftValidationResult {
|
|
39
|
+
isValid: boolean;
|
|
40
|
+
fieldErrors: Partial<Record<ResearchSessionDraftValidationField, string>>;
|
|
41
|
+
}
|
|
42
|
+
export interface ResearchSessionReviewSummaryField {
|
|
43
|
+
label: string;
|
|
44
|
+
value: string;
|
|
45
|
+
}
|
|
46
|
+
export interface ResearchSessionReviewStateSection {
|
|
47
|
+
index: string;
|
|
48
|
+
label: string;
|
|
49
|
+
step: Exclude<ResearchSessionDraftStep, "review">;
|
|
50
|
+
fields: ResearchSessionReviewSummaryField[];
|
|
51
|
+
}
|
|
52
|
+
export interface ResearchSessionReviewState {
|
|
53
|
+
sections: ResearchSessionReviewStateSection[];
|
|
54
|
+
}
|
|
55
|
+
export interface ResearchSessionReviewSummarySection extends ResearchSessionReviewStateSection {
|
|
56
|
+
validation: ResearchSessionDraftValidationResult;
|
|
57
|
+
}
|
|
58
|
+
export interface ResearchSessionDraftUpdate {
|
|
59
|
+
currentStep?: ResearchSessionDraftStep;
|
|
60
|
+
completedSteps?: ResearchSessionDraftStep[];
|
|
61
|
+
returnToReview?: boolean;
|
|
62
|
+
reviewConfirmed?: boolean;
|
|
63
|
+
goal?: string;
|
|
64
|
+
workingDirectory?: string;
|
|
65
|
+
agentCommand?: string;
|
|
66
|
+
contextSettings?: Partial<ResearchSessionDraft["contextSettings"]>;
|
|
67
|
+
workspaceSettings?: Partial<ResearchSessionDraft["workspaceSettings"]>;
|
|
68
|
+
stopPolicy?: Partial<ResearchSessionDraft["stopPolicy"]>;
|
|
69
|
+
agentSettings?: Partial<ResearchSessionDraft["agentSettings"]>;
|
|
70
|
+
}
|
|
71
|
+
export interface ResearchSessionDraftServiceDependencies {
|
|
72
|
+
now?: () => Date;
|
|
73
|
+
createRepository?: (sessionsRoot: string) => ResearchSessionRepository;
|
|
74
|
+
projectDefaultsService?: Pick<ResearchProjectDefaultsService, "saveForSession">;
|
|
75
|
+
createProjectDefaultsService?: () => Pick<ResearchProjectDefaultsService, "saveForSession">;
|
|
76
|
+
}
|
|
77
|
+
export interface ResearchSessionReviewStateInput {
|
|
78
|
+
workingDirectory: string;
|
|
79
|
+
webSearch: string;
|
|
80
|
+
shellCommandAllowlistAdditions: string;
|
|
81
|
+
shellCommandAllowlistRemovals: string;
|
|
82
|
+
approvalPolicy: string;
|
|
83
|
+
sandboxMode: string;
|
|
84
|
+
repeatedFailures: string;
|
|
85
|
+
noMeaningfulProgress: string;
|
|
86
|
+
insufficientEvidence: string;
|
|
87
|
+
goal: string;
|
|
88
|
+
trackableGlobs: string;
|
|
89
|
+
baseRef: string;
|
|
90
|
+
agentCommand: string;
|
|
91
|
+
model: string;
|
|
92
|
+
startupTimeoutSec: string;
|
|
93
|
+
turnTimeoutSec: string;
|
|
94
|
+
}
|
|
95
|
+
export declare class ResearchSessionDraftService {
|
|
96
|
+
private readonly now;
|
|
97
|
+
private readonly createRepository;
|
|
98
|
+
private readonly projectDefaultsService;
|
|
99
|
+
constructor(dependencies?: ResearchSessionDraftServiceDependencies);
|
|
100
|
+
loadDraft(input: {
|
|
101
|
+
repoRoot: string;
|
|
102
|
+
sessionId: string;
|
|
103
|
+
}): Promise<ResearchSessionDraft>;
|
|
104
|
+
updateDraft(input: {
|
|
105
|
+
repoRoot: string;
|
|
106
|
+
sessionId: string;
|
|
107
|
+
patch: ResearchSessionDraftUpdate;
|
|
108
|
+
}): Promise<ResearchSessionDraft>;
|
|
109
|
+
private resolveRepository;
|
|
110
|
+
}
|
|
111
|
+
export declare function validateGoalStepDraft(draft: ResearchSessionDraft): ResearchSessionDraftValidationResult;
|
|
112
|
+
export declare function validateContextStepDraft(draft: ResearchSessionDraft): ResearchSessionDraftValidationResult;
|
|
113
|
+
export declare function validateWorkspaceStepDraft(draft: ResearchSessionDraft): ResearchSessionDraftValidationResult;
|
|
114
|
+
export declare function validateAgentStepDraft(draft: ResearchSessionDraft): ResearchSessionDraftValidationResult;
|
|
115
|
+
export declare function validatePermissionsStepDraft(draft: ResearchSessionDraft): ResearchSessionDraftValidationResult;
|
|
116
|
+
export declare function validateStopRulesStepDraft(draft: ResearchSessionDraft): ResearchSessionDraftValidationResult;
|
|
117
|
+
export declare function validateOutputsStepDraft(draft: ResearchSessionDraft): ResearchSessionDraftValidationResult;
|
|
118
|
+
export declare function validateReviewStepDraft(draft: ResearchSessionDraft): ResearchSessionDraftValidationResult;
|
|
119
|
+
export declare function buildResearchSessionReviewSummary(draft: ResearchSessionDraft): ResearchSessionReviewSummarySection[];
|
|
120
|
+
export declare function buildResearchSessionReviewState(draft: Pick<ResearchSessionDraft, "workingDirectory" | "contextSettings" | "agentSettings" | "stopPolicy" | "goal" | "workspaceSettings" | "agentCommand">): ResearchSessionReviewState;
|
|
121
|
+
export declare function buildResearchSessionReviewStateFromValues(input: ResearchSessionReviewStateInput): ResearchSessionReviewState;
|