@workbench-ai/agent-driver 0.0.44

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.
Files changed (52) hide show
  1. package/dist/access-contracts.d.ts +10 -0
  2. package/dist/access-contracts.d.ts.map +1 -0
  3. package/dist/access-contracts.js +45 -0
  4. package/dist/behavior-contract.d.ts +26 -0
  5. package/dist/behavior-contract.d.ts.map +1 -0
  6. package/dist/behavior-contract.js +200 -0
  7. package/dist/conformance.d.ts +3 -0
  8. package/dist/conformance.d.ts.map +1 -0
  9. package/dist/conformance.js +37 -0
  10. package/dist/global-skills.d.ts +22 -0
  11. package/dist/global-skills.d.ts.map +1 -0
  12. package/dist/global-skills.js +168 -0
  13. package/dist/index.d.ts +138 -0
  14. package/dist/index.d.ts.map +1 -0
  15. package/dist/index.js +44 -0
  16. package/dist/internal-utils.d.ts +8 -0
  17. package/dist/internal-utils.d.ts.map +1 -0
  18. package/dist/internal-utils.js +46 -0
  19. package/dist/json-rpc.d.ts +22 -0
  20. package/dist/json-rpc.d.ts.map +1 -0
  21. package/dist/json-rpc.js +1 -0
  22. package/dist/managed-runtime.d.ts +21 -0
  23. package/dist/managed-runtime.d.ts.map +1 -0
  24. package/dist/managed-runtime.js +119 -0
  25. package/dist/model-config.d.ts +17 -0
  26. package/dist/model-config.d.ts.map +1 -0
  27. package/dist/model-config.js +43 -0
  28. package/dist/normalized-activity.d.ts +75 -0
  29. package/dist/normalized-activity.d.ts.map +1 -0
  30. package/dist/normalized-activity.js +89 -0
  31. package/dist/prepare.d.ts +9 -0
  32. package/dist/prepare.d.ts.map +1 -0
  33. package/dist/prepare.js +119 -0
  34. package/dist/process-env.d.ts +20 -0
  35. package/dist/process-env.d.ts.map +1 -0
  36. package/dist/process-env.js +75 -0
  37. package/dist/session-runtime.d.ts +60 -0
  38. package/dist/session-runtime.d.ts.map +1 -0
  39. package/dist/session-runtime.js +240 -0
  40. package/dist/tool-semantics.d.ts +22 -0
  41. package/dist/tool-semantics.d.ts.map +1 -0
  42. package/dist/tool-semantics.js +241 -0
  43. package/dist/trace-builder.d.ts +88 -0
  44. package/dist/trace-builder.d.ts.map +1 -0
  45. package/dist/trace-builder.js +493 -0
  46. package/dist/trace-replay.d.ts +33 -0
  47. package/dist/trace-replay.d.ts.map +1 -0
  48. package/dist/trace-replay.js +4 -0
  49. package/dist/types.d.ts +156 -0
  50. package/dist/types.d.ts.map +1 -0
  51. package/dist/types.js +10 -0
  52. package/package.json +39 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js ADDED
@@ -0,0 +1,44 @@
1
+ import { z } from "zod";
2
+ export * from "./behavior-contract.js";
3
+ export * from "./access-contracts.js";
4
+ export * from "./conformance.js";
5
+ export * from "./global-skills.js";
6
+ export * from "./internal-utils.js";
7
+ export * from "./json-rpc.js";
8
+ export * from "./managed-runtime.js";
9
+ export * from "./model-config.js";
10
+ export * from "./normalized-activity.js";
11
+ export * from "./prepare.js";
12
+ export * from "./process-env.js";
13
+ export * from "./session-runtime.js";
14
+ export * from "./trace-builder.js";
15
+ export * from "./trace-replay.js";
16
+ export * from "./tool-semantics.js";
17
+ export * from "./types.js";
18
+ export function defineHarnessProvider(factory) {
19
+ return factory;
20
+ }
21
+ export function createCliHarnessManifest(args) {
22
+ return {
23
+ id: args.id,
24
+ display_name: args.displayName ?? args.id,
25
+ auth_schema: zodSchemaToManifestJsonSchema(args.auth),
26
+ config_schema: zodSchemaToManifestJsonSchema(args.config),
27
+ defaults: {
28
+ ...(args.defaults ?? {}),
29
+ config: { ...(args.defaults?.config ?? {}) },
30
+ },
31
+ capabilities: args.capabilities,
32
+ supported_workspace_modes: [...args.supportedWorkspaceModes],
33
+ };
34
+ }
35
+ function zodSchemaToManifestJsonSchema(schema) {
36
+ const jsonSchema = z.toJSONSchema(schema);
37
+ if (jsonSchema &&
38
+ typeof jsonSchema === "object" &&
39
+ !Array.isArray(jsonSchema)) {
40
+ const { $schema: _schema, ...rest } = jsonSchema;
41
+ return rest;
42
+ }
43
+ return jsonSchema;
44
+ }
@@ -0,0 +1,8 @@
1
+ export declare function nowIso(): string;
2
+ export declare function createId(prefix: string): string;
3
+ export declare function ensureDir(dirPath: string): Promise<void>;
4
+ export declare function appendNdjson(filePath: string, value: unknown): Promise<void>;
5
+ export declare function expandHome(inputPath: string): string;
6
+ export declare function resolveRuntimeHome(runtimeHome?: string): string;
7
+ export declare function resolveCanonicalProjectRoot(repoRoot: string): string;
8
+ //# sourceMappingURL=internal-utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"internal-utils.d.ts","sourceRoot":"","sources":["../src/internal-utils.ts"],"names":[],"mappings":"AAMA,wBAAgB,MAAM,IAAI,MAAM,CAE/B;AAED,wBAAgB,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAE/C;AAED,wBAAsB,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAE9D;AAED,wBAAsB,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAGlF;AAOD,wBAAgB,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAUpD;AAED,wBAAgB,kBAAkB,CAChC,WAAW,SAA8E,GACxF,MAAM,CAER;AAED,wBAAgB,2BAA2B,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAUpE"}
@@ -0,0 +1,46 @@
1
+ import { randomUUID } from "node:crypto";
2
+ import { promises as fs } from "node:fs";
3
+ import { realpathSync } from "node:fs";
4
+ import os from "node:os";
5
+ import path from "node:path";
6
+ export function nowIso() {
7
+ return new Date().toISOString();
8
+ }
9
+ export function createId(prefix) {
10
+ return `${prefix}_${randomUUID()}`;
11
+ }
12
+ export async function ensureDir(dirPath) {
13
+ await fs.mkdir(dirPath, { recursive: true });
14
+ }
15
+ export async function appendNdjson(filePath, value) {
16
+ await ensureDir(path.dirname(filePath));
17
+ await fs.appendFile(filePath, `${JSON.stringify(value)}\n`, "utf8");
18
+ }
19
+ function isMissingPathError(error) {
20
+ const code = error?.code;
21
+ return code === "ENOENT" || code === "ENOTDIR";
22
+ }
23
+ export function expandHome(inputPath) {
24
+ if (inputPath === "~") {
25
+ return process.env.HOME ?? inputPath;
26
+ }
27
+ if (inputPath.startsWith("~/")) {
28
+ return path.join(process.env.HOME ?? "", inputPath.slice(2));
29
+ }
30
+ return inputPath;
31
+ }
32
+ export function resolveRuntimeHome(runtimeHome = process.env.AGENT_RUNTIME_HOME ?? path.join(os.homedir(), ".agent-runtime")) {
33
+ return path.resolve(expandHome(runtimeHome));
34
+ }
35
+ export function resolveCanonicalProjectRoot(repoRoot) {
36
+ const absoluteRoot = path.resolve(repoRoot);
37
+ try {
38
+ return realpathSync.native(absoluteRoot);
39
+ }
40
+ catch (error) {
41
+ if (isMissingPathError(error)) {
42
+ return absoluteRoot;
43
+ }
44
+ throw error;
45
+ }
46
+ }
@@ -0,0 +1,22 @@
1
+ export interface JsonRpcResponse<T = unknown> {
2
+ jsonrpc: "2.0";
3
+ id: number | string;
4
+ result?: T;
5
+ error?: {
6
+ code: number;
7
+ message: string;
8
+ data?: unknown;
9
+ };
10
+ }
11
+ export interface JsonRpcNotification<T = unknown> {
12
+ jsonrpc?: "2.0";
13
+ method: string;
14
+ params: T;
15
+ }
16
+ export interface JsonRpcRequest<T = unknown> {
17
+ jsonrpc: "2.0";
18
+ id: number | string;
19
+ method: string;
20
+ params?: T;
21
+ }
22
+ //# sourceMappingURL=json-rpc.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"json-rpc.d.ts","sourceRoot":"","sources":["../src/json-rpc.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,eAAe,CAAC,CAAC,GAAG,OAAO;IAC1C,OAAO,EAAE,KAAK,CAAC;IACf,EAAE,EAAE,MAAM,GAAG,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,CAAC,CAAC;IACX,KAAK,CAAC,EAAE;QACN,IAAI,EAAE,MAAM,CAAC;QACb,OAAO,EAAE,MAAM,CAAC;QAChB,IAAI,CAAC,EAAE,OAAO,CAAC;KAChB,CAAC;CACH;AAED,MAAM,WAAW,mBAAmB,CAAC,CAAC,GAAG,OAAO;IAC9C,OAAO,CAAC,EAAE,KAAK,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,CAAC,CAAC;CACX;AAED,MAAM,WAAW,cAAc,CAAC,CAAC,GAAG,OAAO;IACzC,OAAO,EAAE,KAAK,CAAC;IACf,EAAE,EAAE,MAAM,GAAG,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,CAAC,CAAC;CACZ"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,21 @@
1
+ import type { WorkspaceMode } from "./types.js";
2
+ export declare function mirrorManagedWorkspace(sourcePath: string, destinationPath: string, excludedTopLevelEntries?: readonly string[]): Promise<void>;
3
+ export interface PreparedStageSessionWorkspace {
4
+ workspacePath: string;
5
+ attemptWorkspacePath: string;
6
+ sessionWorkspacePath: string | null;
7
+ }
8
+ export declare function prepareStageSessionWorkspace(args: {
9
+ workspaceMode: WorkspaceMode;
10
+ workspacePath: string;
11
+ stageSessionPath: string;
12
+ excludedTopLevelEntries?: readonly string[];
13
+ }): Promise<PreparedStageSessionWorkspace>;
14
+ export declare function persistStageSessionWorkspace(args: {
15
+ attemptWorkspacePath: string;
16
+ sessionWorkspacePath: string | null;
17
+ excludedTopLevelEntries?: readonly string[];
18
+ }): Promise<void>;
19
+ export declare function buildManagedHarnessEnv(parentEnv: NodeJS.ProcessEnv, injectedEnv?: NodeJS.ProcessEnv): NodeJS.ProcessEnv;
20
+ export declare function getManagedHarnessHomePath(stageSessionPath: string): string;
21
+ //# sourceMappingURL=managed-runtime.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"managed-runtime.d.ts","sourceRoot":"","sources":["../src/managed-runtime.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAwBhD,wBAAsB,sBAAsB,CAC1C,UAAU,EAAE,MAAM,EAClB,eAAe,EAAE,MAAM,EACvB,uBAAuB,GAAE,SAAS,MAAM,EAAO,GAC9C,OAAO,CAAC,IAAI,CAAC,CA4Cf;AAED,MAAM,WAAW,6BAA6B;IAC5C,aAAa,EAAE,MAAM,CAAC;IACtB,oBAAoB,EAAE,MAAM,CAAC;IAC7B,oBAAoB,EAAE,MAAM,GAAG,IAAI,CAAC;CACrC;AAED,wBAAsB,4BAA4B,CAAC,IAAI,EAAE;IACvD,aAAa,EAAE,aAAa,CAAC;IAC7B,aAAa,EAAE,MAAM,CAAC;IACtB,gBAAgB,EAAE,MAAM,CAAC;IACzB,uBAAuB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAC7C,GAAG,OAAO,CAAC,6BAA6B,CAAC,CAoBzC;AAED,wBAAsB,4BAA4B,CAAC,IAAI,EAAE;IACvD,oBAAoB,EAAE,MAAM,CAAC;IAC7B,oBAAoB,EAAE,MAAM,GAAG,IAAI,CAAC;IACpC,uBAAuB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAC7C,GAAG,OAAO,CAAC,IAAI,CAAC,CAShB;AAED,wBAAgB,sBAAsB,CACpC,SAAS,EAAE,MAAM,CAAC,UAAU,EAC5B,WAAW,GAAE,MAAM,CAAC,UAAe,GAClC,MAAM,CAAC,UAAU,CAoBnB;AAED,wBAAgB,yBAAyB,CAAC,gBAAgB,EAAE,MAAM,GAAG,MAAM,CAE1E"}
@@ -0,0 +1,119 @@
1
+ import { randomUUID } from "node:crypto";
2
+ import { promises as fs } from "node:fs";
3
+ import path from "node:path";
4
+ const managedHarnessEnvAllowlist = new Set([
5
+ "PATH",
6
+ "LANG",
7
+ "LC_ALL",
8
+ "LC_CTYPE",
9
+ "LC_MESSAGES",
10
+ "TERM",
11
+ "COLORTERM",
12
+ "NO_COLOR",
13
+ "TMPDIR",
14
+ "TMP",
15
+ "TEMP",
16
+ "SSL_CERT_FILE",
17
+ "SSL_CERT_DIR",
18
+ "HTTP_PROXY",
19
+ "HTTPS_PROXY",
20
+ "NO_PROXY",
21
+ "http_proxy",
22
+ "https_proxy",
23
+ "no_proxy",
24
+ ]);
25
+ export async function mirrorManagedWorkspace(sourcePath, destinationPath, excludedTopLevelEntries = []) {
26
+ const destinationRelativeToSource = path.relative(sourcePath, destinationPath);
27
+ if (destinationRelativeToSource &&
28
+ destinationRelativeToSource !== "." &&
29
+ !destinationRelativeToSource.startsWith(`..${path.sep}`) &&
30
+ destinationRelativeToSource !== ".." &&
31
+ !path.isAbsolute(destinationRelativeToSource)) {
32
+ throw new Error(`Cannot mirror ${sourcePath} into nested destination ${destinationPath}.`);
33
+ }
34
+ const exclusions = new Set(excludedTopLevelEntries.map((value) => value.replace(/\/+$/u, "")));
35
+ const destinationParent = path.dirname(destinationPath);
36
+ const stagingPath = path.join(destinationParent, `.flow-mirror-${path.basename(destinationPath)}-${randomUUID()}`);
37
+ await fs.rm(stagingPath, { recursive: true, force: true });
38
+ await fs.mkdir(destinationParent, { recursive: true });
39
+ try {
40
+ await fs.cp(sourcePath, stagingPath, {
41
+ recursive: true,
42
+ force: true,
43
+ filter: (entry) => {
44
+ const relative = path.relative(sourcePath, entry);
45
+ if (!relative || relative === ".") {
46
+ return true;
47
+ }
48
+ const topLevel = relative.split(path.sep, 1)[0] ?? relative;
49
+ return !exclusions.has(topLevel);
50
+ },
51
+ });
52
+ await replaceMirroredWorkspace(stagingPath, destinationPath);
53
+ }
54
+ catch (error) {
55
+ await fs.rm(stagingPath, { recursive: true, force: true }).catch(() => undefined);
56
+ throw error;
57
+ }
58
+ }
59
+ export async function prepareStageSessionWorkspace(args) {
60
+ if (args.workspaceMode === "project") {
61
+ return {
62
+ workspacePath: args.workspacePath,
63
+ attemptWorkspacePath: args.workspacePath,
64
+ sessionWorkspacePath: null,
65
+ };
66
+ }
67
+ const sessionWorkspacePath = path.join(args.stageSessionPath, "workspace");
68
+ await mirrorManagedWorkspace(args.workspacePath, sessionWorkspacePath, args.excludedTopLevelEntries);
69
+ return {
70
+ workspacePath: sessionWorkspacePath,
71
+ attemptWorkspacePath: args.workspacePath,
72
+ sessionWorkspacePath,
73
+ };
74
+ }
75
+ export async function persistStageSessionWorkspace(args) {
76
+ if (!args.sessionWorkspacePath) {
77
+ return;
78
+ }
79
+ await mirrorManagedWorkspace(args.sessionWorkspacePath, args.attemptWorkspacePath, args.excludedTopLevelEntries);
80
+ }
81
+ export function buildManagedHarnessEnv(parentEnv, injectedEnv = {}) {
82
+ const env = {};
83
+ for (const [key, value] of Object.entries(parentEnv)) {
84
+ if (typeof value === "string" &&
85
+ (managedHarnessEnvAllowlist.has(key)
86
+ || key.startsWith("FLOW_FAKE_")
87
+ || key.startsWith("WORKBENCH_"))) {
88
+ env[key] = value;
89
+ }
90
+ }
91
+ for (const [key, value] of Object.entries(injectedEnv)) {
92
+ if (value !== undefined) {
93
+ env[key] = value;
94
+ }
95
+ }
96
+ return env;
97
+ }
98
+ export function getManagedHarnessHomePath(stageSessionPath) {
99
+ return path.join(stageSessionPath, "home");
100
+ }
101
+ async function replaceMirroredWorkspace(stagingPath, destinationPath) {
102
+ await fs.rm(destinationPath, { recursive: true, force: true });
103
+ try {
104
+ await fs.rename(stagingPath, destinationPath);
105
+ }
106
+ catch (error) {
107
+ if (!isMirrorDestinationConflict(error)) {
108
+ throw error;
109
+ }
110
+ await fs.rm(destinationPath, { recursive: true, force: true });
111
+ await fs.rename(stagingPath, destinationPath);
112
+ }
113
+ }
114
+ function isMirrorDestinationConflict(error) {
115
+ return (error instanceof Error &&
116
+ "code" in error &&
117
+ (error.code === "EEXIST" ||
118
+ error.code === "ENOTEMPTY"));
119
+ }
@@ -0,0 +1,17 @@
1
+ import { z } from "zod";
2
+ import type { JsonValue } from "./types.js";
3
+ export declare const harnessModelConfigJsonSchemaProperty: JsonValue;
4
+ export declare const harnessModelConfigZodShape: {
5
+ readonly model: z.ZodOptional<z.ZodString>;
6
+ };
7
+ export declare const sharedHarnessEffortValues: readonly ["low", "medium", "high"];
8
+ export declare const codexHarnessEffortValues: readonly ["none", "minimal", "low", "medium", "high", "xhigh"];
9
+ export declare function createHarnessEffortJsonSchemaProperty(values: readonly string[]): JsonValue;
10
+ export declare function createHarnessEffortZodSchema<T extends readonly [string, ...string[]]>(values: T): z.ZodOptional<z.ZodType<T[number]>>;
11
+ export declare function resolveHarnessConfiguredModel(config: {
12
+ model?: string | null;
13
+ }): string | null;
14
+ export declare function resolveHarnessConfiguredEffort<T extends readonly string[]>(config: {
15
+ effort?: string | null;
16
+ }, values: T): T[number] | null;
17
+ //# sourceMappingURL=model-config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"model-config.d.ts","sourceRoot":"","sources":["../src/model-config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAE5C,eAAO,MAAM,oCAAoC,EAAE,SAGlD,CAAC;AAEF,eAAO,MAAM,0BAA0B;;CAE7B,CAAC;AAEX,eAAO,MAAM,yBAAyB,oCAAqC,CAAC;AAE5E,eAAO,MAAM,wBAAwB,gEAK3B,CAAC;AAEX,wBAAgB,qCAAqC,CACnD,MAAM,EAAE,SAAS,MAAM,EAAE,GACxB,SAAS,CAIX;AAED,wBAAgB,4BAA4B,CAC1C,CAAC,SAAS,SAAS,CAAC,MAAM,EAAE,GAAG,MAAM,EAAE,CAAC,EACxC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAQhD;AAED,wBAAgB,6BAA6B,CAAC,MAAM,EAAE;IAAE,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,GAAG,MAAM,GAAG,IAAI,CAO9F;AAED,wBAAgB,8BAA8B,CAC5C,CAAC,SAAS,SAAS,MAAM,EAAE,EAE3B,MAAM,EAAE;IAAE,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,EAClC,MAAM,EAAE,CAAC,GACR,CAAC,CAAC,MAAM,CAAC,GAAG,IAAI,CAWlB"}
@@ -0,0 +1,43 @@
1
+ import { z } from "zod";
2
+ export const harnessModelConfigJsonSchemaProperty = {
3
+ type: "string",
4
+ minLength: 1,
5
+ };
6
+ export const harnessModelConfigZodShape = {
7
+ model: z.string().trim().min(1).optional(),
8
+ };
9
+ export const sharedHarnessEffortValues = ["low", "medium", "high"];
10
+ export const codexHarnessEffortValues = [
11
+ "none",
12
+ "minimal",
13
+ ...sharedHarnessEffortValues,
14
+ "xhigh",
15
+ ];
16
+ export function createHarnessEffortJsonSchemaProperty(values) {
17
+ return {
18
+ enum: [...values],
19
+ };
20
+ }
21
+ export function createHarnessEffortZodSchema(values) {
22
+ const enumSchema = z.enum(values);
23
+ return z
24
+ .preprocess((value) => (typeof value === "string" ? value.trim() : value), enumSchema)
25
+ .optional();
26
+ }
27
+ export function resolveHarnessConfiguredModel(config) {
28
+ if (typeof config.model !== "string") {
29
+ return null;
30
+ }
31
+ const model = config.model.trim();
32
+ return model.length > 0 ? model : null;
33
+ }
34
+ export function resolveHarnessConfiguredEffort(config, values) {
35
+ if (typeof config.effort !== "string") {
36
+ return null;
37
+ }
38
+ const effort = config.effort.trim();
39
+ if (effort.length === 0 || !values.includes(effort)) {
40
+ return null;
41
+ }
42
+ return effort;
43
+ }
@@ -0,0 +1,75 @@
1
+ import type { JsonValue } from "./types.js";
2
+ import { HarnessTraceBuilder } from "./trace-builder.js";
3
+ export type NormalizedHarnessActivity = {
4
+ type: "session.started";
5
+ at?: string;
6
+ provider: string;
7
+ model?: string | null;
8
+ sessionId?: string | null;
9
+ attributes?: Record<string, JsonValue>;
10
+ } | {
11
+ type: "turn.started";
12
+ at?: string;
13
+ provider: string;
14
+ model?: string | null;
15
+ sessionId?: string | null;
16
+ operationId?: string | null;
17
+ attributes?: Record<string, JsonValue>;
18
+ } | {
19
+ type: "turn.completed";
20
+ at?: string;
21
+ provider?: string | null;
22
+ model?: string | null;
23
+ sessionId?: string | null;
24
+ operationId?: string | null;
25
+ status?: string | null;
26
+ errorMessage?: string | null;
27
+ attributes?: Record<string, JsonValue>;
28
+ } | {
29
+ type: "assistant_output.started";
30
+ at?: string;
31
+ phase?: string | null;
32
+ itemId?: string | null;
33
+ } | {
34
+ type: "assistant_output.delta";
35
+ at?: string;
36
+ phase?: string | null;
37
+ itemId?: string | null;
38
+ delta: string;
39
+ } | {
40
+ type: "assistant_output.completed";
41
+ at?: string;
42
+ phase?: string | null;
43
+ itemId?: string | null;
44
+ text: string;
45
+ } | {
46
+ type: "tool.started";
47
+ at?: string;
48
+ toolId?: string | null;
49
+ toolName?: string | null;
50
+ attributes?: Record<string, JsonValue>;
51
+ } | {
52
+ type: "tool.completed";
53
+ at?: string;
54
+ toolId?: string | null;
55
+ toolName?: string | null;
56
+ attributes?: Record<string, JsonValue>;
57
+ } | {
58
+ type: "usage.updated";
59
+ at?: string;
60
+ inputTokens?: number | null;
61
+ outputTokens?: number | null;
62
+ attributes?: Record<string, JsonValue>;
63
+ } | {
64
+ type: "note";
65
+ at?: string;
66
+ message: string;
67
+ attributes?: Record<string, JsonValue>;
68
+ } | {
69
+ type: "error";
70
+ at?: string;
71
+ message: string;
72
+ attributes?: Record<string, JsonValue>;
73
+ };
74
+ export declare function applyNormalizedHarnessActivity(trace: HarnessTraceBuilder, activity: NormalizedHarnessActivity): void;
75
+ //# sourceMappingURL=normalized-activity.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"normalized-activity.d.ts","sourceRoot":"","sources":["../src/normalized-activity.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,89 @@
1
+ import { nowIso } from "./internal-utils.js";
2
+ export function applyNormalizedHarnessActivity(trace, activity) {
3
+ const at = activity.at ?? nowIso();
4
+ switch (activity.type) {
5
+ case "session.started":
6
+ trace.recordNote("Model session started", at, {
7
+ provider: activity.provider,
8
+ model: activity.model ?? null,
9
+ session_id: activity.sessionId ?? null,
10
+ ...(activity.attributes ?? {}),
11
+ });
12
+ return;
13
+ case "turn.started":
14
+ trace.startTurn({
15
+ at,
16
+ provider: activity.provider,
17
+ model: activity.model ?? null,
18
+ sessionId: activity.sessionId ?? null,
19
+ operationId: activity.operationId ?? null,
20
+ attributes: activity.attributes,
21
+ });
22
+ return;
23
+ case "turn.completed":
24
+ trace.completeTurn({
25
+ at,
26
+ provider: activity.provider ?? null,
27
+ model: activity.model ?? null,
28
+ sessionId: activity.sessionId ?? null,
29
+ operationId: activity.operationId ?? null,
30
+ status: activity.status ?? null,
31
+ errorMessage: activity.errorMessage ?? null,
32
+ attributes: activity.attributes,
33
+ });
34
+ return;
35
+ case "assistant_output.started":
36
+ trace.startAssistantOutput({
37
+ at,
38
+ phase: activity.phase ?? null,
39
+ itemId: activity.itemId ?? null,
40
+ });
41
+ return;
42
+ case "assistant_output.delta":
43
+ trace.appendOutputDelta({
44
+ at,
45
+ delta: activity.delta,
46
+ phase: activity.phase ?? null,
47
+ itemId: activity.itemId ?? null,
48
+ });
49
+ return;
50
+ case "assistant_output.completed":
51
+ trace.completeAssistantOutput({
52
+ at,
53
+ text: activity.text,
54
+ phase: activity.phase ?? null,
55
+ itemId: activity.itemId ?? null,
56
+ });
57
+ return;
58
+ case "tool.started":
59
+ trace.startToolCall({
60
+ at,
61
+ toolId: activity.toolId ?? null,
62
+ toolName: activity.toolName ?? null,
63
+ attributes: activity.attributes,
64
+ });
65
+ return;
66
+ case "tool.completed":
67
+ trace.completeToolCall({
68
+ at,
69
+ toolId: activity.toolId ?? null,
70
+ toolName: activity.toolName ?? null,
71
+ attributes: activity.attributes,
72
+ });
73
+ return;
74
+ case "usage.updated":
75
+ trace.recordUsage({
76
+ at,
77
+ inputTokens: activity.inputTokens ?? null,
78
+ outputTokens: activity.outputTokens ?? null,
79
+ attributes: activity.attributes,
80
+ });
81
+ return;
82
+ case "note":
83
+ trace.recordNote(activity.message, at, activity.attributes);
84
+ return;
85
+ case "error":
86
+ trace.recordError(activity.message, at, activity.attributes);
87
+ return;
88
+ }
89
+ }
@@ -0,0 +1,9 @@
1
+ import type { HarnessExecutionPlan } from "./index.js";
2
+ export interface HarnessPrepareCommandArgs {
3
+ plan: HarnessExecutionPlan;
4
+ workspacePath: string;
5
+ stageSessionPath: string;
6
+ childEnv: NodeJS.ProcessEnv;
7
+ }
8
+ export declare function runHarnessPrepareCommand(args: HarnessPrepareCommandArgs): Promise<void>;
9
+ //# sourceMappingURL=prepare.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prepare.d.ts","sourceRoot":"","sources":["../src/prepare.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAUvD,MAAM,WAAW,yBAAyB;IACxC,IAAI,EAAE,oBAAoB,CAAC;IAC3B,aAAa,EAAE,MAAM,CAAC;IACtB,gBAAgB,EAAE,MAAM,CAAC;IACzB,QAAQ,EAAE,MAAM,CAAC,UAAU,CAAC;CAC7B;AAcD,wBAAsB,wBAAwB,CAC5C,IAAI,EAAE,yBAAyB,GAC9B,OAAO,CAAC,IAAI,CAAC,CA8Ff"}
@@ -0,0 +1,119 @@
1
+ import { spawn } from "node:child_process";
2
+ import { DEFAULT_HARNESS_PREPARE_TIMEOUT_MS } from "./types.js";
3
+ const harnessPrepareContextEnvNames = Object.freeze([
4
+ "AGENT_HARNESS_PROVIDER",
5
+ "AGENT_HARNESS_WORKSPACE_ROOT",
6
+ "AGENT_HARNESS_STAGE_ROOT",
7
+ "AGENT_HARNESS_WORKSPACE_MODE",
8
+ ]);
9
+ function buildHarnessPrepareEnv(args) {
10
+ const prepare = args.plan.harness.prepare;
11
+ return {
12
+ ...args.childEnv,
13
+ ...(prepare?.env ?? {}),
14
+ AGENT_HARNESS_PROVIDER: args.plan.harness.id,
15
+ AGENT_HARNESS_WORKSPACE_ROOT: args.workspacePath,
16
+ AGENT_HARNESS_STAGE_ROOT: args.stageSessionPath,
17
+ AGENT_HARNESS_WORKSPACE_MODE: args.plan.workspace.mode,
18
+ };
19
+ }
20
+ export async function runHarnessPrepareCommand(args) {
21
+ const prepare = args.plan.harness.prepare;
22
+ if (!prepare) {
23
+ return;
24
+ }
25
+ const timeoutMs = prepare.timeout_ms ?? DEFAULT_HARNESS_PREPARE_TIMEOUT_MS;
26
+ const env = buildHarnessPrepareEnv(args);
27
+ await new Promise((resolve, reject) => {
28
+ const child = spawn("sh", ["-lc", prepare.run], {
29
+ cwd: args.workspacePath,
30
+ env,
31
+ stdio: "pipe",
32
+ });
33
+ let stdout = "";
34
+ let stderr = "";
35
+ let settled = false;
36
+ let timedOut = false;
37
+ const finish = (callback) => {
38
+ if (settled) {
39
+ return;
40
+ }
41
+ settled = true;
42
+ clearTimeout(timeout);
43
+ callback();
44
+ };
45
+ const timeout = setTimeout(() => {
46
+ timedOut = true;
47
+ child.kill("SIGKILL");
48
+ }, timeoutMs);
49
+ child.stdout.setEncoding("utf8");
50
+ child.stderr.setEncoding("utf8");
51
+ child.stdout.on("data", (chunk) => {
52
+ stdout += chunk;
53
+ });
54
+ child.stderr.on("data", (chunk) => {
55
+ stderr += chunk;
56
+ });
57
+ child.on("error", (error) => {
58
+ finish(() => {
59
+ reject(new Error(formatHarnessPrepareFailure({
60
+ command: prepare.run,
61
+ error,
62
+ stdout,
63
+ stderr,
64
+ })));
65
+ });
66
+ });
67
+ child.on("exit", (code, signal) => {
68
+ finish(() => {
69
+ if (timedOut) {
70
+ reject(new Error(formatHarnessPrepareTimeout({
71
+ command: prepare.run,
72
+ timeoutMs,
73
+ stdout,
74
+ stderr,
75
+ })));
76
+ return;
77
+ }
78
+ if (code === 0) {
79
+ resolve();
80
+ return;
81
+ }
82
+ reject(new Error(formatHarnessPrepareFailure({
83
+ command: prepare.run,
84
+ code,
85
+ signal,
86
+ stdout,
87
+ stderr,
88
+ })));
89
+ });
90
+ });
91
+ });
92
+ }
93
+ function formatHarnessPrepareFailure(args) {
94
+ const reason = args.error instanceof Error
95
+ ? args.error.message
96
+ : `code ${args.code ?? "null"} signal ${args.signal ?? "null"}`;
97
+ return [
98
+ `Harness prepare command failed (${reason}): ${args.command}`,
99
+ ...formatHarnessPrepareOutput(args.stdout, args.stderr),
100
+ ].join("\n");
101
+ }
102
+ function formatHarnessPrepareTimeout(args) {
103
+ return [
104
+ `Harness prepare command timed out after ${args.timeoutMs}ms: ${args.command}`,
105
+ ...formatHarnessPrepareOutput(args.stdout, args.stderr),
106
+ ].join("\n");
107
+ }
108
+ function formatHarnessPrepareOutput(stdout, stderr) {
109
+ const lines = [];
110
+ const normalizedStdout = stdout.trim();
111
+ const normalizedStderr = stderr.trim();
112
+ if (normalizedStdout) {
113
+ lines.push(`stdout: ${normalizedStdout}`);
114
+ }
115
+ if (normalizedStderr) {
116
+ lines.push(`stderr: ${normalizedStderr}`);
117
+ }
118
+ return lines;
119
+ }