voratiq 0.1.0-beta.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/LICENSE +21 -0
- package/README.md +59 -0
- package/dist/auth/providers/claude/constants.d.ts +7 -0
- package/dist/auth/providers/claude/constants.js +9 -0
- package/dist/auth/providers/claude/credentials.d.ts +5 -0
- package/dist/auth/providers/claude/credentials.js +112 -0
- package/dist/auth/providers/claude/error.d.ts +5 -0
- package/dist/auth/providers/claude/error.js +6 -0
- package/dist/auth/providers/claude/keychain.d.ts +4 -0
- package/dist/auth/providers/claude/keychain.js +158 -0
- package/dist/auth/providers/claude.d.ts +2 -0
- package/dist/auth/providers/claude.js +124 -0
- package/dist/auth/providers/codex.d.ts +2 -0
- package/dist/auth/providers/codex.js +93 -0
- package/dist/auth/providers/gemini.d.ts +2 -0
- package/dist/auth/providers/gemini.js +159 -0
- package/dist/auth/providers/index.d.ts +2 -0
- package/dist/auth/providers/index.js +16 -0
- package/dist/auth/providers/messages.d.ts +1 -0
- package/dist/auth/providers/messages.js +3 -0
- package/dist/auth/providers/secret-staging.d.ts +14 -0
- package/dist/auth/providers/secret-staging.js +72 -0
- package/dist/auth/providers/teardown.d.ts +2 -0
- package/dist/auth/providers/teardown.js +6 -0
- package/dist/auth/providers/types.d.ts +31 -0
- package/dist/auth/providers/types.js +1 -0
- package/dist/auth/providers/utils.d.ts +20 -0
- package/dist/auth/providers/utils.js +148 -0
- package/dist/auth/runtime.d.ts +2 -0
- package/dist/auth/runtime.js +17 -0
- package/dist/auth/staging.d.ts +8 -0
- package/dist/auth/staging.js +7 -0
- package/dist/bin.d.ts +2 -0
- package/dist/bin.js +142 -0
- package/dist/cli/apply.d.ts +14 -0
- package/dist/cli/apply.js +38 -0
- package/dist/cli/commander-utils.d.ts +3 -0
- package/dist/cli/commander-utils.js +27 -0
- package/dist/cli/confirmation.d.ts +14 -0
- package/dist/cli/confirmation.js +16 -0
- package/dist/cli/errors.d.ts +5 -0
- package/dist/cli/errors.js +16 -0
- package/dist/cli/init.d.ts +10 -0
- package/dist/cli/init.js +41 -0
- package/dist/cli/list.d.ts +14 -0
- package/dist/cli/list.js +48 -0
- package/dist/cli/output.d.ts +14 -0
- package/dist/cli/output.js +62 -0
- package/dist/cli/prune.d.ts +14 -0
- package/dist/cli/prune.js +54 -0
- package/dist/cli/review.d.ts +12 -0
- package/dist/cli/review.js +33 -0
- package/dist/cli/run.d.ts +13 -0
- package/dist/cli/run.js +51 -0
- package/dist/commands/apply/command.d.ts +9 -0
- package/dist/commands/apply/command.js +135 -0
- package/dist/commands/apply/errors.d.ts +35 -0
- package/dist/commands/apply/errors.js +73 -0
- package/dist/commands/apply/types.d.ts +13 -0
- package/dist/commands/apply/types.js +1 -0
- package/dist/commands/errors.d.ts +4 -0
- package/dist/commands/errors.js +7 -0
- package/dist/commands/fetch.d.ts +8 -0
- package/dist/commands/fetch.js +25 -0
- package/dist/commands/init/agents.d.ts +3 -0
- package/dist/commands/init/agents.js +159 -0
- package/dist/commands/init/command.d.ts +2 -0
- package/dist/commands/init/command.js +40 -0
- package/dist/commands/init/environment.d.ts +2 -0
- package/dist/commands/init/environment.js +76 -0
- package/dist/commands/init/evals.d.ts +4 -0
- package/dist/commands/init/evals.js +219 -0
- package/dist/commands/init/types.d.ts +48 -0
- package/dist/commands/init/types.js +1 -0
- package/dist/commands/list/command.d.ts +13 -0
- package/dist/commands/list/command.js +60 -0
- package/dist/commands/prune/command.d.ts +2 -0
- package/dist/commands/prune/command.js +336 -0
- package/dist/commands/prune/errors.d.ts +20 -0
- package/dist/commands/prune/errors.js +39 -0
- package/dist/commands/prune/types.d.ts +42 -0
- package/dist/commands/prune/types.js +1 -0
- package/dist/commands/review/command.d.ts +10 -0
- package/dist/commands/review/command.js +26 -0
- package/dist/commands/run/agent-execution.d.ts +19 -0
- package/dist/commands/run/agent-execution.js +63 -0
- package/dist/commands/run/agents/auth-stage.d.ts +23 -0
- package/dist/commands/run/agents/auth-stage.js +108 -0
- package/dist/commands/run/agents/chat-preserver.d.ts +9 -0
- package/dist/commands/run/agents/chat-preserver.js +35 -0
- package/dist/commands/run/agents/eval-runner.d.ts +19 -0
- package/dist/commands/run/agents/eval-runner.js +27 -0
- package/dist/commands/run/agents/failures.d.ts +7 -0
- package/dist/commands/run/agents/failures.js +32 -0
- package/dist/commands/run/agents/lifecycle.d.ts +9 -0
- package/dist/commands/run/agents/lifecycle.js +157 -0
- package/dist/commands/run/agents/preparation.d.ts +2 -0
- package/dist/commands/run/agents/preparation.js +123 -0
- package/dist/commands/run/agents/run-context.d.ts +46 -0
- package/dist/commands/run/agents/run-context.js +193 -0
- package/dist/commands/run/agents/sandbox-launcher.d.ts +44 -0
- package/dist/commands/run/agents/sandbox-launcher.js +211 -0
- package/dist/commands/run/agents/types.d.ts +47 -0
- package/dist/commands/run/agents/types.js +1 -0
- package/dist/commands/run/agents/watchdog.d.ts +39 -0
- package/dist/commands/run/agents/watchdog.js +172 -0
- package/dist/commands/run/agents/workspace-prep.d.ts +17 -0
- package/dist/commands/run/agents/workspace-prep.js +78 -0
- package/dist/commands/run/agents.d.ts +14 -0
- package/dist/commands/run/agents.js +47 -0
- package/dist/commands/run/argv.d.ts +1 -0
- package/dist/commands/run/argv.js +19 -0
- package/dist/commands/run/command.d.ts +14 -0
- package/dist/commands/run/command.js +170 -0
- package/dist/commands/run/errors.d.ts +61 -0
- package/dist/commands/run/errors.js +86 -0
- package/dist/commands/run/id.d.ts +1 -0
- package/dist/commands/run/id.js +22 -0
- package/dist/commands/run/lifecycle.d.ts +19 -0
- package/dist/commands/run/lifecycle.js +186 -0
- package/dist/commands/run/phases.d.ts +11 -0
- package/dist/commands/run/phases.js +1 -0
- package/dist/commands/run/prompts.d.ts +4 -0
- package/dist/commands/run/prompts.js +16 -0
- package/dist/commands/run/record-init.d.ts +15 -0
- package/dist/commands/run/record-init.js +29 -0
- package/dist/commands/run/reports.d.ts +14 -0
- package/dist/commands/run/reports.js +63 -0
- package/dist/commands/run/sandbox-registry.d.ts +4 -0
- package/dist/commands/run/sandbox-registry.js +54 -0
- package/dist/commands/run/sandbox.d.ts +16 -0
- package/dist/commands/run/sandbox.js +96 -0
- package/dist/commands/run/shim/agent-manifest.d.ts +7 -0
- package/dist/commands/run/shim/agent-manifest.js +1 -0
- package/dist/commands/run/shim/run-agent-shim.d.ts +1 -0
- package/dist/commands/run/shim/run-agent-shim.js +232 -0
- package/dist/commands/run/shim/run-agent-shim.mjs +10 -0
- package/dist/commands/run/validation.d.ts +20 -0
- package/dist/commands/run/validation.js +60 -0
- package/dist/configs/agents/defaults.d.ts +9 -0
- package/dist/configs/agents/defaults.js +55 -0
- package/dist/configs/agents/errors.d.ts +40 -0
- package/dist/configs/agents/errors.js +78 -0
- package/dist/configs/agents/loader.d.ts +8 -0
- package/dist/configs/agents/loader.js +137 -0
- package/dist/configs/agents/types.d.ts +39 -0
- package/dist/configs/agents/types.js +31 -0
- package/dist/configs/environment/detect.d.ts +17 -0
- package/dist/configs/environment/detect.js +79 -0
- package/dist/configs/environment/errors.d.ts +12 -0
- package/dist/configs/environment/errors.js +26 -0
- package/dist/configs/environment/loader.d.ts +10 -0
- package/dist/configs/environment/loader.js +80 -0
- package/dist/configs/environment/types.d.ts +21 -0
- package/dist/configs/environment/types.js +98 -0
- package/dist/configs/evals/defaults.d.ts +8 -0
- package/dist/configs/evals/defaults.js +28 -0
- package/dist/configs/evals/detect.d.ts +10 -0
- package/dist/configs/evals/detect.js +224 -0
- package/dist/configs/evals/errors.d.ts +16 -0
- package/dist/configs/evals/errors.js +29 -0
- package/dist/configs/evals/loader.d.ts +9 -0
- package/dist/configs/evals/loader.js +46 -0
- package/dist/configs/evals/types.d.ts +42 -0
- package/dist/configs/evals/types.js +74 -0
- package/dist/configs/sandbox/defaults.d.ts +14 -0
- package/dist/configs/sandbox/defaults.js +54 -0
- package/dist/configs/sandbox/errors.d.ts +5 -0
- package/dist/configs/sandbox/errors.js +8 -0
- package/dist/configs/sandbox/loader.d.ts +6 -0
- package/dist/configs/sandbox/loader.js +192 -0
- package/dist/configs/sandbox/merge.d.ts +9 -0
- package/dist/configs/sandbox/merge.js +94 -0
- package/dist/configs/sandbox/schemas.d.ts +58 -0
- package/dist/configs/sandbox/schemas.js +72 -0
- package/dist/configs/sandbox/types.d.ts +34 -0
- package/dist/configs/sandbox/types.js +1 -0
- package/dist/configs/shared/loader-factory.d.ts +19 -0
- package/dist/configs/shared/loader-factory.js +33 -0
- package/dist/configs/shared/yaml-error-formatter.d.ts +40 -0
- package/dist/configs/shared/yaml-error-formatter.js +41 -0
- package/dist/evals/runner.d.ts +16 -0
- package/dist/evals/runner.js +132 -0
- package/dist/preflight/errors.d.ts +10 -0
- package/dist/preflight/errors.js +21 -0
- package/dist/preflight/index.d.ts +30 -0
- package/dist/preflight/index.js +157 -0
- package/dist/records/enhanced.d.ts +38 -0
- package/dist/records/enhanced.js +139 -0
- package/dist/records/errors.d.ts +23 -0
- package/dist/records/errors.js +43 -0
- package/dist/records/history-lock.d.ts +27 -0
- package/dist/records/history-lock.js +184 -0
- package/dist/records/mutators.d.ts +17 -0
- package/dist/records/mutators.js +144 -0
- package/dist/records/persistence.d.ts +95 -0
- package/dist/records/persistence.js +459 -0
- package/dist/records/types.d.ts +238 -0
- package/dist/records/types.js +131 -0
- package/dist/render/interactions/confirmation.d.ts +19 -0
- package/dist/render/interactions/confirmation.js +63 -0
- package/dist/render/transcripts/apply.d.ts +2 -0
- package/dist/render/transcripts/apply.js +52 -0
- package/dist/render/transcripts/init.d.ts +18 -0
- package/dist/render/transcripts/init.js +84 -0
- package/dist/render/transcripts/list.d.ts +3 -0
- package/dist/render/transcripts/list.js +44 -0
- package/dist/render/transcripts/prune.d.ts +16 -0
- package/dist/render/transcripts/prune.js +50 -0
- package/dist/render/transcripts/review.d.ts +2 -0
- package/dist/render/transcripts/review.js +36 -0
- package/dist/render/transcripts/run.d.ts +25 -0
- package/dist/render/transcripts/run.js +295 -0
- package/dist/render/transcripts/shared.d.ts +12 -0
- package/dist/render/transcripts/shared.js +41 -0
- package/dist/render/utils/agents.d.ts +28 -0
- package/dist/render/utils/agents.js +261 -0
- package/dist/render/utils/badges.d.ts +20 -0
- package/dist/render/utils/badges.js +37 -0
- package/dist/render/utils/errors.d.ts +2 -0
- package/dist/render/utils/errors.js +14 -0
- package/dist/render/utils/records.d.ts +1 -0
- package/dist/render/utils/records.js +32 -0
- package/dist/render/utils/runs.d.ts +16 -0
- package/dist/render/utils/runs.js +50 -0
- package/dist/render/utils/table.d.ts +12 -0
- package/dist/render/utils/table.js +32 -0
- package/dist/render/utils/transcript.d.ts +14 -0
- package/dist/render/utils/transcript.js +44 -0
- package/dist/status/colors.d.ts +10 -0
- package/dist/status/colors.js +33 -0
- package/dist/status/index.d.ts +37 -0
- package/dist/status/index.js +30 -0
- package/dist/testing/test-hooks.d.ts +7 -0
- package/dist/testing/test-hooks.js +16 -0
- package/dist/utils/binaries.d.ts +1 -0
- package/dist/utils/binaries.js +13 -0
- package/dist/utils/cli-root.d.ts +2 -0
- package/dist/utils/cli-root.js +42 -0
- package/dist/utils/colors.d.ts +2 -0
- package/dist/utils/colors.js +23 -0
- package/dist/utils/diff.d.ts +9 -0
- package/dist/utils/diff.js +61 -0
- package/dist/utils/env.d.ts +10 -0
- package/dist/utils/env.js +56 -0
- package/dist/utils/errors.d.ts +31 -0
- package/dist/utils/errors.js +53 -0
- package/dist/utils/fs.d.ts +13 -0
- package/dist/utils/fs.js +70 -0
- package/dist/utils/git.d.ts +40 -0
- package/dist/utils/git.js +126 -0
- package/dist/utils/output.d.ts +4 -0
- package/dist/utils/output.js +12 -0
- package/dist/utils/path.d.ts +11 -0
- package/dist/utils/path.js +84 -0
- package/dist/utils/process.d.ts +37 -0
- package/dist/utils/process.js +152 -0
- package/dist/utils/terminal.d.ts +5 -0
- package/dist/utils/terminal.js +5 -0
- package/dist/utils/validators.d.ts +1 -0
- package/dist/utils/validators.js +15 -0
- package/dist/utils/version.d.ts +1 -0
- package/dist/utils/version.js +25 -0
- package/dist/utils/yaml-reader.d.ts +14 -0
- package/dist/utils/yaml-reader.js +41 -0
- package/dist/utils/yaml.d.ts +33 -0
- package/dist/utils/yaml.js +75 -0
- package/dist/workspace/agents.d.ts +33 -0
- package/dist/workspace/agents.js +189 -0
- package/dist/workspace/chat/artifacts.d.ts +14 -0
- package/dist/workspace/chat/artifacts.js +157 -0
- package/dist/workspace/chat/sources.d.ts +5 -0
- package/dist/workspace/chat/sources.js +80 -0
- package/dist/workspace/chat/types.d.ts +1 -0
- package/dist/workspace/chat/types.js +1 -0
- package/dist/workspace/cleanup.d.ts +4 -0
- package/dist/workspace/cleanup.js +12 -0
- package/dist/workspace/credential-guard.d.ts +4 -0
- package/dist/workspace/credential-guard.js +71 -0
- package/dist/workspace/dependencies.d.ts +23 -0
- package/dist/workspace/dependencies.js +190 -0
- package/dist/workspace/errors.d.ts +16 -0
- package/dist/workspace/errors.js +43 -0
- package/dist/workspace/layout.d.ts +30 -0
- package/dist/workspace/layout.js +124 -0
- package/dist/workspace/prune.d.ts +8 -0
- package/dist/workspace/prune.js +29 -0
- package/dist/workspace/run.d.ts +14 -0
- package/dist/workspace/run.js +28 -0
- package/dist/workspace/sandbox-requirements.d.ts +17 -0
- package/dist/workspace/sandbox-requirements.js +69 -0
- package/dist/workspace/setup.d.ts +3 -0
- package/dist/workspace/setup.js +81 -0
- package/dist/workspace/shim.d.ts +4 -0
- package/dist/workspace/shim.js +65 -0
- package/dist/workspace/structure.d.ts +77 -0
- package/dist/workspace/structure.js +134 -0
- package/dist/workspace/templates.d.ts +9 -0
- package/dist/workspace/templates.js +66 -0
- package/dist/workspace/types.d.ts +4 -0
- package/dist/workspace/types.js +1 -0
- package/package.json +82 -0
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export interface YamlParseErrorDetail {
|
|
2
|
+
reason?: string;
|
|
3
|
+
message?: string;
|
|
4
|
+
line?: number;
|
|
5
|
+
column?: number;
|
|
6
|
+
error: unknown;
|
|
7
|
+
isYamlError: boolean;
|
|
8
|
+
}
|
|
9
|
+
export interface ParseYamlDocumentOptions<TError extends Error> {
|
|
10
|
+
emptyValue?: unknown;
|
|
11
|
+
onEmpty?: () => void;
|
|
12
|
+
formatError: (detail: YamlParseErrorDetail) => TError;
|
|
13
|
+
}
|
|
14
|
+
export declare function parseYamlDocument<TError extends Error>(content: string, options: ParseYamlDocumentOptions<TError>): unknown;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { load } from "js-yaml";
|
|
2
|
+
import { toErrorMessage } from "./errors.js";
|
|
3
|
+
import { isYamlException } from "./yaml.js";
|
|
4
|
+
const DEFAULT_EMPTY_VALUE = {};
|
|
5
|
+
export function parseYamlDocument(content, options) {
|
|
6
|
+
const { emptyValue = DEFAULT_EMPTY_VALUE, onEmpty, formatError } = options;
|
|
7
|
+
const source = content.trim();
|
|
8
|
+
if (source.length === 0) {
|
|
9
|
+
onEmpty?.();
|
|
10
|
+
return emptyValue;
|
|
11
|
+
}
|
|
12
|
+
try {
|
|
13
|
+
const document = load(source, { json: false });
|
|
14
|
+
return document ?? emptyValue;
|
|
15
|
+
}
|
|
16
|
+
catch (error) {
|
|
17
|
+
throw formatError(buildYamlParseErrorDetail(error));
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
function buildYamlParseErrorDetail(error) {
|
|
21
|
+
if (isYamlException(error)) {
|
|
22
|
+
const { reason, message, mark } = error;
|
|
23
|
+
return {
|
|
24
|
+
reason: reason ?? undefined,
|
|
25
|
+
message: message ?? undefined,
|
|
26
|
+
line: typeof mark?.line === "number" && Number.isFinite(mark.line)
|
|
27
|
+
? mark.line + 1
|
|
28
|
+
: undefined,
|
|
29
|
+
column: typeof mark?.column === "number" && Number.isFinite(mark.column)
|
|
30
|
+
? mark.column + 1
|
|
31
|
+
: undefined,
|
|
32
|
+
error,
|
|
33
|
+
isYamlError: true,
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
return {
|
|
37
|
+
message: toErrorMessage(error),
|
|
38
|
+
error,
|
|
39
|
+
isYamlError: false,
|
|
40
|
+
};
|
|
41
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { YAMLException } from "js-yaml";
|
|
2
|
+
export interface ConfigSnapshot {
|
|
3
|
+
content: string;
|
|
4
|
+
normalized: string;
|
|
5
|
+
exists: boolean;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Reads a YAML (or general text) config file and returns its snapshot.
|
|
9
|
+
*/
|
|
10
|
+
export declare function readConfigSnapshot(filePath: string): Promise<ConfigSnapshot>;
|
|
11
|
+
/**
|
|
12
|
+
* Normalizes YAML text for comparisons by trimming whitespace and normalizing line endings.
|
|
13
|
+
*/
|
|
14
|
+
export declare function normalizeConfigText(value: string): string;
|
|
15
|
+
/**
|
|
16
|
+
* Writes config content to disk if the normalized version differs from the previous snapshot.
|
|
17
|
+
*/
|
|
18
|
+
export declare function writeConfigIfChanged(filePath: string, nextContent: string, previousNormalized: string): Promise<boolean>;
|
|
19
|
+
export interface YamlConfigLoadResult<T> {
|
|
20
|
+
snapshot: ConfigSnapshot;
|
|
21
|
+
config: T;
|
|
22
|
+
}
|
|
23
|
+
export declare function loadYamlConfig<T>(filePath: string, parse: (content: string) => T): Promise<YamlConfigLoadResult<T>>;
|
|
24
|
+
export declare function isDefaultYamlTemplate(snapshot: ConfigSnapshot, defaultTemplate: string): boolean;
|
|
25
|
+
export interface PersistYamlConfigOptions {
|
|
26
|
+
filePath: string;
|
|
27
|
+
serialized: string;
|
|
28
|
+
original: ConfigSnapshot;
|
|
29
|
+
defaultTemplate: string;
|
|
30
|
+
isDefaultTemplate?: boolean;
|
|
31
|
+
}
|
|
32
|
+
export declare function persistYamlConfig(options: PersistYamlConfigOptions): Promise<boolean>;
|
|
33
|
+
export declare function isYamlException(error: unknown): error is YAMLException;
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { readFile, writeFile } from "node:fs/promises";
|
|
2
|
+
import { isFileSystemError } from "./fs.js";
|
|
3
|
+
/**
|
|
4
|
+
* Reads a YAML (or general text) config file and returns its snapshot.
|
|
5
|
+
*/
|
|
6
|
+
export async function readConfigSnapshot(filePath) {
|
|
7
|
+
try {
|
|
8
|
+
const content = await readFile(filePath, "utf8");
|
|
9
|
+
return {
|
|
10
|
+
content,
|
|
11
|
+
normalized: normalizeConfigText(content),
|
|
12
|
+
exists: true,
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
catch (error) {
|
|
16
|
+
if (isFileSystemError(error) && error.code === "ENOENT") {
|
|
17
|
+
return { content: "", normalized: "", exists: false };
|
|
18
|
+
}
|
|
19
|
+
throw error;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Normalizes YAML text for comparisons by trimming whitespace and normalizing line endings.
|
|
24
|
+
*/
|
|
25
|
+
export function normalizeConfigText(value) {
|
|
26
|
+
if (value.length === 0) {
|
|
27
|
+
return "";
|
|
28
|
+
}
|
|
29
|
+
return value.replace(/\r\n/g, "\n").trim();
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Writes config content to disk if the normalized version differs from the previous snapshot.
|
|
33
|
+
*/
|
|
34
|
+
export async function writeConfigIfChanged(filePath, nextContent, previousNormalized) {
|
|
35
|
+
const nextNormalized = normalizeConfigText(nextContent);
|
|
36
|
+
if (nextNormalized === previousNormalized) {
|
|
37
|
+
return false;
|
|
38
|
+
}
|
|
39
|
+
await writeFile(filePath, ensureTrailingNewline(nextContent), "utf8");
|
|
40
|
+
return true;
|
|
41
|
+
}
|
|
42
|
+
export async function loadYamlConfig(filePath, parse) {
|
|
43
|
+
const snapshot = await readConfigSnapshot(filePath);
|
|
44
|
+
return {
|
|
45
|
+
snapshot,
|
|
46
|
+
config: parse(snapshot.content),
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
export function isDefaultYamlTemplate(snapshot, defaultTemplate) {
|
|
50
|
+
if (!snapshot.exists) {
|
|
51
|
+
return true;
|
|
52
|
+
}
|
|
53
|
+
const defaults = normalizeConfigText(defaultTemplate);
|
|
54
|
+
return snapshot.normalized === defaults;
|
|
55
|
+
}
|
|
56
|
+
export async function persistYamlConfig(options) {
|
|
57
|
+
const { filePath, serialized, original, defaultTemplate, isDefaultTemplate } = options;
|
|
58
|
+
if (!original.exists) {
|
|
59
|
+
return writeConfigIfChanged(filePath, serialized, "__missing__");
|
|
60
|
+
}
|
|
61
|
+
const wasDefaultTemplate = isDefaultTemplate ?? isDefaultYamlTemplate(original, defaultTemplate);
|
|
62
|
+
const previousNormalized = wasDefaultTemplate
|
|
63
|
+
? normalizeConfigText(defaultTemplate)
|
|
64
|
+
: original.normalized;
|
|
65
|
+
return writeConfigIfChanged(filePath, serialized, previousNormalized);
|
|
66
|
+
}
|
|
67
|
+
function ensureTrailingNewline(content) {
|
|
68
|
+
return content.endsWith("\n") ? content : `${content}\n`;
|
|
69
|
+
}
|
|
70
|
+
export function isYamlException(error) {
|
|
71
|
+
return (Boolean(error) &&
|
|
72
|
+
typeof error === "object" &&
|
|
73
|
+
"name" in error &&
|
|
74
|
+
error.name === "YAMLException");
|
|
75
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { WorkspaceSetupRunError } from "../commands/run/errors.js";
|
|
2
|
+
import type { AgentId } from "../configs/agents/types.js";
|
|
3
|
+
import type { EnvironmentConfig } from "../configs/environment/types.js";
|
|
4
|
+
import { type AgentWorkspacePaths } from "./layout.js";
|
|
5
|
+
export interface ArtifactCollectionResult {
|
|
6
|
+
summaryCaptured: boolean;
|
|
7
|
+
diffStatistics?: string;
|
|
8
|
+
commitSha?: string;
|
|
9
|
+
diffAttempted: boolean;
|
|
10
|
+
diffCaptured: boolean;
|
|
11
|
+
}
|
|
12
|
+
export interface SandboxPersona {
|
|
13
|
+
authorName: string;
|
|
14
|
+
authorEmail: string;
|
|
15
|
+
}
|
|
16
|
+
export declare function prepareAgentWorkspace(options: {
|
|
17
|
+
paths: AgentWorkspacePaths;
|
|
18
|
+
baseRevisionSha: string;
|
|
19
|
+
root: string;
|
|
20
|
+
agentId: AgentId;
|
|
21
|
+
runId: string;
|
|
22
|
+
environment: EnvironmentConfig;
|
|
23
|
+
}): Promise<void>;
|
|
24
|
+
export declare function collectAgentArtifacts(options: {
|
|
25
|
+
baseRevisionSha: string;
|
|
26
|
+
workspacePath: string;
|
|
27
|
+
summaryPath: string;
|
|
28
|
+
diffPath: string;
|
|
29
|
+
root: string;
|
|
30
|
+
environment: EnvironmentConfig;
|
|
31
|
+
persona: SandboxPersona;
|
|
32
|
+
}): Promise<ArtifactCollectionResult>;
|
|
33
|
+
export declare function ensureWorkspaceError(error: unknown): WorkspaceSetupRunError;
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
import { readFile, rm, writeFile } from "node:fs/promises";
|
|
2
|
+
import { AgentProcessError, GitOperationError, WorkspaceSetupRunError, } from "../commands/run/errors.js";
|
|
3
|
+
import { toErrorMessage } from "../utils/errors.js";
|
|
4
|
+
import { createWorktree, gitAddAll, gitCommitAll, gitDiff, gitDiffShortStat, gitHasStagedChanges, runGitCommand, } from "../utils/git.js";
|
|
5
|
+
import { resolvePath } from "../utils/path.js";
|
|
6
|
+
import { enforceCredentialExclusion } from "./credential-guard.js";
|
|
7
|
+
import { cleanupWorkspaceDependencies, ensureWorkspaceDependencies, WorkspaceDependencyCleanupError, } from "./dependencies.js";
|
|
8
|
+
import { WorkspaceSetupError } from "./errors.js";
|
|
9
|
+
import { scaffoldAgentWorkspace, WORKSPACE_SUMMARY_FILENAME, } from "./layout.js";
|
|
10
|
+
import { ensureWorkspaceShim } from "./shim.js";
|
|
11
|
+
export async function prepareAgentWorkspace(options) {
|
|
12
|
+
const { paths, baseRevisionSha, root, agentId, runId, environment } = options;
|
|
13
|
+
try {
|
|
14
|
+
await scaffoldAgentWorkspace(paths);
|
|
15
|
+
await rm(resolvePath(paths.agentRoot, "tmp"), {
|
|
16
|
+
recursive: true,
|
|
17
|
+
force: true,
|
|
18
|
+
}).catch(() => { });
|
|
19
|
+
}
|
|
20
|
+
catch (error) {
|
|
21
|
+
throw ensureWorkspaceError(error);
|
|
22
|
+
}
|
|
23
|
+
try {
|
|
24
|
+
await createWorktree({
|
|
25
|
+
root,
|
|
26
|
+
worktreePath: paths.workspacePath,
|
|
27
|
+
branch: `voratiq/run/${runId}/${agentId}`,
|
|
28
|
+
baseRevision: baseRevisionSha,
|
|
29
|
+
});
|
|
30
|
+
await ensureWorkspaceDependencies({
|
|
31
|
+
root,
|
|
32
|
+
workspacePath: paths.workspacePath,
|
|
33
|
+
environment,
|
|
34
|
+
});
|
|
35
|
+
await ensureWorkspaceShim({
|
|
36
|
+
workspacePath: paths.workspacePath,
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
catch (error) {
|
|
40
|
+
throw ensureWorkspaceError(error);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
export async function collectAgentArtifacts(options) {
|
|
44
|
+
const { baseRevisionSha, workspacePath, summaryPath, diffPath, root, environment, persona, } = options;
|
|
45
|
+
let dependenciesCleanup = {
|
|
46
|
+
nodeRemoved: false,
|
|
47
|
+
pythonRemoved: false,
|
|
48
|
+
};
|
|
49
|
+
let cleanupFailed = false;
|
|
50
|
+
try {
|
|
51
|
+
dependenciesCleanup = await cleanupWorkspaceDependencies({
|
|
52
|
+
root,
|
|
53
|
+
workspacePath,
|
|
54
|
+
environment,
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
catch (error) {
|
|
58
|
+
cleanupFailed = true;
|
|
59
|
+
if (error instanceof WorkspaceDependencyCleanupError) {
|
|
60
|
+
dependenciesCleanup = error.cleanup;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
let runFailed = true;
|
|
64
|
+
let artifactResult;
|
|
65
|
+
let dependencyRestoreError;
|
|
66
|
+
try {
|
|
67
|
+
await runGitStep("Git add failed", async () => gitAddAll(workspacePath));
|
|
68
|
+
const hasChangesBeforeSummary = await gitHasStagedChanges(workspacePath);
|
|
69
|
+
if (!hasChangesBeforeSummary) {
|
|
70
|
+
throw new AgentProcessError({
|
|
71
|
+
detail: "Agent process failed. No workspace changes detected.",
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
const { summary } = await harvestSummary({
|
|
75
|
+
workspacePath,
|
|
76
|
+
summaryPath,
|
|
77
|
+
});
|
|
78
|
+
await runGitStep("Git add failed", async () => gitAddAll(workspacePath));
|
|
79
|
+
const hasChanges = await gitHasStagedChanges(workspacePath);
|
|
80
|
+
if (!hasChanges) {
|
|
81
|
+
throw new AgentProcessError({
|
|
82
|
+
detail: "Agent process failed. No workspace changes detected.",
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
let diffStatistics;
|
|
86
|
+
let commitSha;
|
|
87
|
+
await runGitStep("Git commit failed", async () => gitCommitAll({
|
|
88
|
+
cwd: workspacePath,
|
|
89
|
+
message: summary,
|
|
90
|
+
authorName: persona.authorName,
|
|
91
|
+
authorEmail: persona.authorEmail,
|
|
92
|
+
}));
|
|
93
|
+
commitSha = await runGitStep("Git rev-parse failed", async () => runGitCommand(["rev-parse", "HEAD"], { cwd: workspacePath }));
|
|
94
|
+
const diffContent = await runGitStep("Git diff failed", async () => gitDiff({
|
|
95
|
+
cwd: workspacePath,
|
|
96
|
+
baseRevision: baseRevisionSha,
|
|
97
|
+
targetRevision: "HEAD",
|
|
98
|
+
}));
|
|
99
|
+
await enforceCredentialExclusion({
|
|
100
|
+
workspacePath,
|
|
101
|
+
diffContent,
|
|
102
|
+
});
|
|
103
|
+
await writeFile(diffPath, diffContent, { encoding: "utf8" });
|
|
104
|
+
diffStatistics = await runGitStep("Git diff --shortstat failed", async () => gitDiffShortStat({
|
|
105
|
+
cwd: workspacePath,
|
|
106
|
+
baseRevision: baseRevisionSha,
|
|
107
|
+
targetRevision: "HEAD",
|
|
108
|
+
}));
|
|
109
|
+
runFailed = false;
|
|
110
|
+
artifactResult = {
|
|
111
|
+
summaryCaptured: true,
|
|
112
|
+
diffStatistics,
|
|
113
|
+
commitSha,
|
|
114
|
+
diffAttempted: true,
|
|
115
|
+
diffCaptured: true,
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
finally {
|
|
119
|
+
const cleanupTouched = dependenciesCleanup.nodeRemoved || dependenciesCleanup.pythonRemoved;
|
|
120
|
+
const shouldRestoreDependencies = cleanupTouched || cleanupFailed;
|
|
121
|
+
if (shouldRestoreDependencies) {
|
|
122
|
+
try {
|
|
123
|
+
await ensureWorkspaceDependencies({
|
|
124
|
+
root,
|
|
125
|
+
workspacePath,
|
|
126
|
+
environment,
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
catch (error) {
|
|
130
|
+
if (!runFailed) {
|
|
131
|
+
dependencyRestoreError = new AgentProcessError({
|
|
132
|
+
detail: `[voratiq] Failed to restore workspace dependencies after export: ${toErrorMessage(error)}`,
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
if (dependencyRestoreError) {
|
|
139
|
+
throw dependencyRestoreError;
|
|
140
|
+
}
|
|
141
|
+
if (!artifactResult) {
|
|
142
|
+
throw new AgentProcessError({
|
|
143
|
+
detail: "Agent process failed before artifacts were collected.",
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
return artifactResult;
|
|
147
|
+
}
|
|
148
|
+
export function ensureWorkspaceError(error) {
|
|
149
|
+
if (error instanceof WorkspaceSetupError) {
|
|
150
|
+
return new WorkspaceSetupRunError(error.detail, {
|
|
151
|
+
detailLines: error.detailLines,
|
|
152
|
+
hintLines: error.hintLines,
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
return new WorkspaceSetupRunError(toErrorMessage(error));
|
|
156
|
+
}
|
|
157
|
+
async function harvestSummary(options) {
|
|
158
|
+
const { workspacePath, summaryPath } = options;
|
|
159
|
+
const workspaceSummaryPath = resolvePath(workspacePath, WORKSPACE_SUMMARY_FILENAME);
|
|
160
|
+
let raw;
|
|
161
|
+
try {
|
|
162
|
+
raw = await readFile(workspaceSummaryPath, "utf8");
|
|
163
|
+
}
|
|
164
|
+
catch (error) {
|
|
165
|
+
throw new AgentProcessError({ detail: toErrorMessage(error) });
|
|
166
|
+
}
|
|
167
|
+
const trimmed = raw.trim();
|
|
168
|
+
if (!trimmed) {
|
|
169
|
+
throw new AgentProcessError({
|
|
170
|
+
detail: "Agent process failed. Summary is empty.",
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
await writeFile(summaryPath, `${trimmed}\n`, { encoding: "utf8" });
|
|
174
|
+
await rm(workspaceSummaryPath, { force: true });
|
|
175
|
+
return {
|
|
176
|
+
summary: trimmed,
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
async function runGitStep(operationMessage, step) {
|
|
180
|
+
try {
|
|
181
|
+
return await step();
|
|
182
|
+
}
|
|
183
|
+
catch (error) {
|
|
184
|
+
throw new GitOperationError({
|
|
185
|
+
operation: operationMessage,
|
|
186
|
+
detail: toErrorMessage(error),
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { ChatArtifactFormat } from "./types.js";
|
|
2
|
+
export type ChatArtifactStatus = "captured" | "already-exists" | "not-found" | "error";
|
|
3
|
+
export interface ChatArtifactCaptureResult {
|
|
4
|
+
status: ChatArtifactStatus;
|
|
5
|
+
artifactPath?: string;
|
|
6
|
+
format?: ChatArtifactFormat;
|
|
7
|
+
sourceCount?: number;
|
|
8
|
+
error?: unknown;
|
|
9
|
+
}
|
|
10
|
+
export interface PreserveChatArtifactsOptions {
|
|
11
|
+
providerId: string;
|
|
12
|
+
agentRoot: string;
|
|
13
|
+
}
|
|
14
|
+
export declare function preserveProviderChatTranscripts(options: PreserveChatArtifactsOptions): Promise<ChatArtifactCaptureResult>;
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import { once } from "node:events";
|
|
2
|
+
import { createReadStream, createWriteStream } from "node:fs";
|
|
3
|
+
import { mkdir, readFile, rm, writeFile } from "node:fs/promises";
|
|
4
|
+
import { dirname, relative, resolve } from "node:path";
|
|
5
|
+
import { finished } from "node:stream/promises";
|
|
6
|
+
import { pathExists } from "../../utils/fs.js";
|
|
7
|
+
import { ARTIFACTS_DIRNAME, CHAT_JSON_FILENAME, CHAT_JSONL_FILENAME, } from "../structure.js";
|
|
8
|
+
import { findProviderTranscripts } from "./sources.js";
|
|
9
|
+
export async function preserveProviderChatTranscripts(options) {
|
|
10
|
+
const { providerId, agentRoot } = options;
|
|
11
|
+
if (!providerId) {
|
|
12
|
+
return { status: "not-found" };
|
|
13
|
+
}
|
|
14
|
+
const existing = await locateExistingChatArtifact(agentRoot);
|
|
15
|
+
if (existing !== undefined) {
|
|
16
|
+
const { path, format } = existing;
|
|
17
|
+
return {
|
|
18
|
+
status: "already-exists",
|
|
19
|
+
artifactPath: path,
|
|
20
|
+
format,
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
let transcriptPaths;
|
|
24
|
+
try {
|
|
25
|
+
transcriptPaths = await findProviderTranscripts(providerId, agentRoot);
|
|
26
|
+
}
|
|
27
|
+
catch (error) {
|
|
28
|
+
return {
|
|
29
|
+
status: "error",
|
|
30
|
+
error: error instanceof Error ? error : new Error(String(error)),
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
const selection = selectTranscriptFiles(transcriptPaths);
|
|
34
|
+
if (!selection) {
|
|
35
|
+
return { status: "not-found" };
|
|
36
|
+
}
|
|
37
|
+
const { format: selectionFormat, files } = selection;
|
|
38
|
+
const artifactPath = resolve(agentRoot, ARTIFACTS_DIRNAME, selectionFormat === "json" ? CHAT_JSON_FILENAME : CHAT_JSONL_FILENAME);
|
|
39
|
+
try {
|
|
40
|
+
await mkdir(dirname(artifactPath), { recursive: true });
|
|
41
|
+
if (selectionFormat === "json") {
|
|
42
|
+
await bundleJsonTranscripts({
|
|
43
|
+
files,
|
|
44
|
+
artifactPath,
|
|
45
|
+
agentRoot,
|
|
46
|
+
providerId,
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
else {
|
|
50
|
+
await concatenateJsonlTranscripts(files, artifactPath);
|
|
51
|
+
}
|
|
52
|
+
return {
|
|
53
|
+
status: "captured",
|
|
54
|
+
artifactPath,
|
|
55
|
+
format: selectionFormat,
|
|
56
|
+
sourceCount: files.length,
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
catch (error) {
|
|
60
|
+
await rm(artifactPath, { force: true }).catch(() => { });
|
|
61
|
+
return {
|
|
62
|
+
status: "error",
|
|
63
|
+
error: error instanceof Error ? error : new Error(String(error)),
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
async function locateExistingChatArtifact(agentRoot) {
|
|
68
|
+
const candidates = [
|
|
69
|
+
{
|
|
70
|
+
path: resolve(agentRoot, ARTIFACTS_DIRNAME, CHAT_JSONL_FILENAME),
|
|
71
|
+
format: "jsonl",
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
path: resolve(agentRoot, ARTIFACTS_DIRNAME, CHAT_JSON_FILENAME),
|
|
75
|
+
format: "json",
|
|
76
|
+
},
|
|
77
|
+
];
|
|
78
|
+
for (const candidate of candidates) {
|
|
79
|
+
if (await pathExists(candidate.path)) {
|
|
80
|
+
return candidate;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
return undefined;
|
|
84
|
+
}
|
|
85
|
+
function selectTranscriptFiles(transcriptPaths) {
|
|
86
|
+
const jsonlFiles = transcriptPaths.filter((path) => path.toLowerCase().endsWith(".jsonl"));
|
|
87
|
+
if (jsonlFiles.length > 0) {
|
|
88
|
+
return { format: "jsonl", files: [...jsonlFiles].sort() };
|
|
89
|
+
}
|
|
90
|
+
const jsonFiles = transcriptPaths
|
|
91
|
+
.filter((path) => path.toLowerCase().endsWith(".json"))
|
|
92
|
+
.sort();
|
|
93
|
+
if (jsonFiles.length > 0) {
|
|
94
|
+
return { format: "json", files: jsonFiles };
|
|
95
|
+
}
|
|
96
|
+
return undefined;
|
|
97
|
+
}
|
|
98
|
+
async function bundleJsonTranscripts(options) {
|
|
99
|
+
const { files, artifactPath, agentRoot, providerId } = options;
|
|
100
|
+
if (files.length === 0) {
|
|
101
|
+
throw new Error("No JSON transcripts available to bundle");
|
|
102
|
+
}
|
|
103
|
+
const transcripts = [];
|
|
104
|
+
for (const file of files) {
|
|
105
|
+
const raw = await readFile(file, "utf8");
|
|
106
|
+
transcripts.push({
|
|
107
|
+
source: relative(agentRoot, file),
|
|
108
|
+
payload: parseJsonOrString(raw),
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
const payload = {
|
|
112
|
+
provider: providerId,
|
|
113
|
+
collectedAt: new Date().toISOString(),
|
|
114
|
+
transcripts,
|
|
115
|
+
};
|
|
116
|
+
await writeFile(artifactPath, `${JSON.stringify(payload, null, 2)}\n`, "utf8");
|
|
117
|
+
}
|
|
118
|
+
async function concatenateJsonlTranscripts(files, artifactPath) {
|
|
119
|
+
const writer = createWriteStream(artifactPath, {
|
|
120
|
+
flags: "w",
|
|
121
|
+
encoding: "utf8",
|
|
122
|
+
});
|
|
123
|
+
try {
|
|
124
|
+
for (const file of files) {
|
|
125
|
+
await appendFileContents(file, writer);
|
|
126
|
+
}
|
|
127
|
+
writer.end();
|
|
128
|
+
await finished(writer);
|
|
129
|
+
}
|
|
130
|
+
catch (error) {
|
|
131
|
+
writer.destroy();
|
|
132
|
+
throw error;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
async function appendFileContents(sourcePath, writer) {
|
|
136
|
+
const reader = createReadStream(sourcePath, { encoding: "utf8" });
|
|
137
|
+
let endsWithNewline = false;
|
|
138
|
+
for await (const chunk of reader) {
|
|
139
|
+
endsWithNewline = chunk.endsWith("\n");
|
|
140
|
+
if (!writer.write(chunk)) {
|
|
141
|
+
await once(writer, "drain");
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
if (!endsWithNewline) {
|
|
145
|
+
if (!writer.write("\n")) {
|
|
146
|
+
await once(writer, "drain");
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
function parseJsonOrString(content) {
|
|
151
|
+
try {
|
|
152
|
+
return JSON.parse(content);
|
|
153
|
+
}
|
|
154
|
+
catch {
|
|
155
|
+
return content;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export type TranscriptLocator = (agentRoot: string) => Promise<readonly string[]>;
|
|
2
|
+
export declare function findProviderTranscripts(providerId: string, agentRoot: string): Promise<readonly string[]>;
|
|
3
|
+
export declare function findClaudeTranscripts(agentRoot: string): Promise<readonly string[]>;
|
|
4
|
+
export declare function findCodexTranscripts(agentRoot: string): Promise<readonly string[]>;
|
|
5
|
+
export declare function findGeminiTranscripts(agentRoot: string): Promise<readonly string[]>;
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { readdir } from "node:fs/promises";
|
|
2
|
+
import { resolve as resolvePath } from "node:path";
|
|
3
|
+
import { isMissing } from "../../utils/fs.js";
|
|
4
|
+
import { SANDBOX_DIRNAME } from "../structure.js";
|
|
5
|
+
const locatorMap = {
|
|
6
|
+
claude: findClaudeTranscripts,
|
|
7
|
+
codex: findCodexTranscripts,
|
|
8
|
+
gemini: findGeminiTranscripts,
|
|
9
|
+
};
|
|
10
|
+
export async function findProviderTranscripts(providerId, agentRoot) {
|
|
11
|
+
const locator = locatorMap[providerId];
|
|
12
|
+
if (!locator) {
|
|
13
|
+
return [];
|
|
14
|
+
}
|
|
15
|
+
return locator(agentRoot);
|
|
16
|
+
}
|
|
17
|
+
export async function findClaudeTranscripts(agentRoot) {
|
|
18
|
+
const projectsRoot = resolveSandboxPath(agentRoot, ".claude", "projects");
|
|
19
|
+
return collectFiles(projectsRoot, {
|
|
20
|
+
extensions: [".jsonl"],
|
|
21
|
+
maxDepth: 2,
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
export async function findCodexTranscripts(agentRoot) {
|
|
25
|
+
const sessionsRoot = resolveSandboxPath(agentRoot, ".codex", "sessions");
|
|
26
|
+
return collectFiles(sessionsRoot, { extensions: [".jsonl"], maxDepth: 6 });
|
|
27
|
+
}
|
|
28
|
+
export async function findGeminiTranscripts(agentRoot) {
|
|
29
|
+
const tmpRoot = resolveSandboxPath(agentRoot, ".gemini", "tmp");
|
|
30
|
+
const entries = await safeReadDir(tmpRoot);
|
|
31
|
+
const transcripts = [];
|
|
32
|
+
for (const entry of entries) {
|
|
33
|
+
if (!entry.isDirectory()) {
|
|
34
|
+
continue;
|
|
35
|
+
}
|
|
36
|
+
const chatsDir = resolvePath(tmpRoot, entry.name, "chats");
|
|
37
|
+
const chatFiles = await collectFiles(chatsDir, {
|
|
38
|
+
extensions: [".json", ".jsonl"],
|
|
39
|
+
maxDepth: 1,
|
|
40
|
+
});
|
|
41
|
+
transcripts.push(...chatFiles);
|
|
42
|
+
}
|
|
43
|
+
return transcripts.sort();
|
|
44
|
+
}
|
|
45
|
+
function resolveSandboxPath(agentRoot, ...segments) {
|
|
46
|
+
return resolvePath(agentRoot, SANDBOX_DIRNAME, ...segments);
|
|
47
|
+
}
|
|
48
|
+
async function collectFiles(root, { extensions, maxDepth = Number.POSITIVE_INFINITY }) {
|
|
49
|
+
const results = [];
|
|
50
|
+
await traverse(root, 0);
|
|
51
|
+
results.sort();
|
|
52
|
+
return results;
|
|
53
|
+
async function traverse(current, depth) {
|
|
54
|
+
if (depth > maxDepth) {
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
const entries = await safeReadDir(current);
|
|
58
|
+
for (const entry of entries) {
|
|
59
|
+
const entryPath = resolvePath(current, entry.name);
|
|
60
|
+
if (entry.isDirectory()) {
|
|
61
|
+
await traverse(entryPath, depth + 1);
|
|
62
|
+
continue;
|
|
63
|
+
}
|
|
64
|
+
if (extensions.some((extension) => entry.name.endsWith(extension))) {
|
|
65
|
+
results.push(entryPath);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
async function safeReadDir(directory) {
|
|
71
|
+
try {
|
|
72
|
+
return await readdir(directory, { withFileTypes: true });
|
|
73
|
+
}
|
|
74
|
+
catch (error) {
|
|
75
|
+
if (isMissing(error)) {
|
|
76
|
+
return [];
|
|
77
|
+
}
|
|
78
|
+
throw error;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export type ChatArtifactFormat = "json" | "jsonl";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { rm } from "node:fs/promises";
|
|
2
|
+
/**
|
|
3
|
+
* Remove a run workspace directory, ignoring cleanup errors to preserve the original failure context.
|
|
4
|
+
*/
|
|
5
|
+
export async function cleanupRunWorkspace(runRoot) {
|
|
6
|
+
try {
|
|
7
|
+
await rm(runRoot, { recursive: true, force: true });
|
|
8
|
+
}
|
|
9
|
+
catch {
|
|
10
|
+
// Intentionally ignore cleanup failures.
|
|
11
|
+
}
|
|
12
|
+
}
|