@aicalas/loopy 0.1.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 +101 -0
- package/dist/adapters.d.ts +111 -0
- package/dist/adapters.d.ts.map +1 -0
- package/dist/adapters.js +27 -0
- package/dist/adapters.js.map +1 -0
- package/dist/attention/github.d.ts +57 -0
- package/dist/attention/github.d.ts.map +1 -0
- package/dist/attention/github.js +162 -0
- package/dist/attention/github.js.map +1 -0
- package/dist/authoring/attention-config.d.ts +16 -0
- package/dist/authoring/attention-config.d.ts.map +1 -0
- package/dist/authoring/attention-config.js +19 -0
- package/dist/authoring/attention-config.js.map +1 -0
- package/dist/authoring/channel-config.d.ts +16 -0
- package/dist/authoring/channel-config.d.ts.map +1 -0
- package/dist/authoring/channel-config.js +16 -0
- package/dist/authoring/channel-config.js.map +1 -0
- package/dist/authoring/define.d.ts +13 -0
- package/dist/authoring/define.d.ts.map +1 -0
- package/dist/authoring/define.js +13 -0
- package/dist/authoring/define.js.map +1 -0
- package/dist/authoring/effect-config.d.ts +16 -0
- package/dist/authoring/effect-config.d.ts.map +1 -0
- package/dist/authoring/effect-config.js +17 -0
- package/dist/authoring/effect-config.js.map +1 -0
- package/dist/authoring/harness-config.d.ts +30 -0
- package/dist/authoring/harness-config.d.ts.map +1 -0
- package/dist/authoring/harness-config.js +36 -0
- package/dist/authoring/harness-config.js.map +1 -0
- package/dist/authoring/index.d.ts +10 -0
- package/dist/authoring/index.d.ts.map +1 -0
- package/dist/authoring/index.js +9 -0
- package/dist/authoring/index.js.map +1 -0
- package/dist/authoring/schema.d.ts +9 -0
- package/dist/authoring/schema.d.ts.map +1 -0
- package/dist/authoring/schema.js +28 -0
- package/dist/authoring/schema.js.map +1 -0
- package/dist/authoring/types.d.ts +115 -0
- package/dist/authoring/types.d.ts.map +1 -0
- package/dist/authoring/types.js +2 -0
- package/dist/authoring/types.js.map +1 -0
- package/dist/authoring/watcher-config.d.ts +33 -0
- package/dist/authoring/watcher-config.d.ts.map +1 -0
- package/dist/authoring/watcher-config.js +61 -0
- package/dist/authoring/watcher-config.js.map +1 -0
- package/dist/build/discover.d.ts +34 -0
- package/dist/build/discover.d.ts.map +1 -0
- package/dist/build/discover.js +165 -0
- package/dist/build/discover.js.map +1 -0
- package/dist/build/identity.d.ts +9 -0
- package/dist/build/identity.d.ts.map +1 -0
- package/dist/build/identity.js +0 -0
- package/dist/build/identity.js.map +1 -0
- package/dist/channels/github.d.ts +14 -0
- package/dist/channels/github.d.ts.map +1 -0
- package/dist/channels/github.js +118 -0
- package/dist/channels/github.js.map +1 -0
- package/dist/channels/index.d.ts +2 -0
- package/dist/channels/index.d.ts.map +1 -0
- package/dist/channels/index.js +2 -0
- package/dist/channels/index.js.map +1 -0
- package/dist/cli-help.d.ts +23 -0
- package/dist/cli-help.d.ts.map +1 -0
- package/dist/cli-help.js +186 -0
- package/dist/cli-help.js.map +1 -0
- package/dist/cli.d.ts +37 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +385 -0
- package/dist/cli.js.map +1 -0
- package/dist/config.d.ts +71 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +426 -0
- package/dist/config.js.map +1 -0
- package/dist/core/calls.d.ts +67 -0
- package/dist/core/calls.d.ts.map +1 -0
- package/dist/core/calls.js +109 -0
- package/dist/core/calls.js.map +1 -0
- package/dist/core/identifiers.d.ts +24 -0
- package/dist/core/identifiers.d.ts.map +1 -0
- package/dist/core/identifiers.js +129 -0
- package/dist/core/identifiers.js.map +1 -0
- package/dist/core/prompt.d.ts +5 -0
- package/dist/core/prompt.d.ts.map +1 -0
- package/dist/core/prompt.js +47 -0
- package/dist/core/prompt.js.map +1 -0
- package/dist/core/reconcile.d.ts +27 -0
- package/dist/core/reconcile.d.ts.map +1 -0
- package/dist/core/reconcile.js +36 -0
- package/dist/core/reconcile.js.map +1 -0
- package/dist/core/wire.d.ts +332 -0
- package/dist/core/wire.d.ts.map +1 -0
- package/dist/core/wire.js +543 -0
- package/dist/core/wire.js.map +1 -0
- package/dist/emitters/github.d.ts +15 -0
- package/dist/emitters/github.d.ts.map +1 -0
- package/dist/emitters/github.js +43 -0
- package/dist/emitters/github.js.map +1 -0
- package/dist/emitters/index.d.ts +2 -0
- package/dist/emitters/index.d.ts.map +1 -0
- package/dist/emitters/index.js +2 -0
- package/dist/emitters/index.js.map +1 -0
- package/dist/git.d.ts +17 -0
- package/dist/git.d.ts.map +1 -0
- package/dist/git.js +122 -0
- package/dist/git.js.map +1 -0
- package/dist/github/client.d.ts +53 -0
- package/dist/github/client.d.ts.map +1 -0
- package/dist/github/client.js +169 -0
- package/dist/github/client.js.map +1 -0
- package/dist/github/trigger.d.ts +12 -0
- package/dist/github/trigger.d.ts.map +1 -0
- package/dist/github/trigger.js +21 -0
- package/dist/github/trigger.js.map +1 -0
- package/dist/github/writes.d.ts +4 -0
- package/dist/github/writes.d.ts.map +1 -0
- package/dist/github/writes.js +21 -0
- package/dist/github/writes.js.map +1 -0
- package/dist/harnesses/base.d.ts +41 -0
- package/dist/harnesses/base.d.ts.map +1 -0
- package/dist/harnesses/base.js +182 -0
- package/dist/harnesses/base.js.map +1 -0
- package/dist/harnesses/claude-executable.d.ts +42 -0
- package/dist/harnesses/claude-executable.d.ts.map +1 -0
- package/dist/harnesses/claude-executable.js +138 -0
- package/dist/harnesses/claude-executable.js.map +1 -0
- package/dist/harnesses/claude.d.ts +35 -0
- package/dist/harnesses/claude.d.ts.map +1 -0
- package/dist/harnesses/claude.js +160 -0
- package/dist/harnesses/claude.js.map +1 -0
- package/dist/harnesses/codex.d.ts +40 -0
- package/dist/harnesses/codex.d.ts.map +1 -0
- package/dist/harnesses/codex.js +118 -0
- package/dist/harnesses/codex.js.map +1 -0
- package/dist/harnesses/index.d.ts +2 -0
- package/dist/harnesses/index.d.ts.map +1 -0
- package/dist/harnesses/index.js +2 -0
- package/dist/harnesses/index.js.map +1 -0
- package/dist/harnesses/opencode.d.ts +33 -0
- package/dist/harnesses/opencode.d.ts.map +1 -0
- package/dist/harnesses/opencode.js +203 -0
- package/dist/harnesses/opencode.js.map +1 -0
- package/dist/identifiers.d.ts +26 -0
- package/dist/identifiers.d.ts.map +1 -0
- package/dist/identifiers.js +62 -0
- package/dist/identifiers.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -0
- package/dist/log.d.ts +10 -0
- package/dist/log.d.ts.map +1 -0
- package/dist/log.js +44 -0
- package/dist/log.js.map +1 -0
- package/dist/settings.d.ts +43 -0
- package/dist/settings.d.ts.map +1 -0
- package/dist/settings.js +128 -0
- package/dist/settings.js.map +1 -0
- package/dist/temporal/activities.d.ts +57 -0
- package/dist/temporal/activities.d.ts.map +1 -0
- package/dist/temporal/activities.js +366 -0
- package/dist/temporal/activities.js.map +1 -0
- package/dist/temporal/answers.d.ts +48 -0
- package/dist/temporal/answers.d.ts.map +1 -0
- package/dist/temporal/answers.js +78 -0
- package/dist/temporal/answers.js.map +1 -0
- package/dist/temporal/client.d.ts +13 -0
- package/dist/temporal/client.d.ts.map +1 -0
- package/dist/temporal/client.js +20 -0
- package/dist/temporal/client.js.map +1 -0
- package/dist/temporal/contracts.d.ts +19 -0
- package/dist/temporal/contracts.d.ts.map +1 -0
- package/dist/temporal/contracts.js +22 -0
- package/dist/temporal/contracts.js.map +1 -0
- package/dist/temporal/drain.d.ts +19 -0
- package/dist/temporal/drain.d.ts.map +1 -0
- package/dist/temporal/drain.js +109 -0
- package/dist/temporal/drain.js.map +1 -0
- package/dist/temporal/executions.d.ts +18 -0
- package/dist/temporal/executions.d.ts.map +1 -0
- package/dist/temporal/executions.js +15 -0
- package/dist/temporal/executions.js.map +1 -0
- package/dist/temporal/handle.d.ts +39 -0
- package/dist/temporal/handle.d.ts.map +1 -0
- package/dist/temporal/handle.js +95 -0
- package/dist/temporal/handle.js.map +1 -0
- package/dist/temporal/history.d.ts +75 -0
- package/dist/temporal/history.d.ts.map +1 -0
- package/dist/temporal/history.js +310 -0
- package/dist/temporal/history.js.map +1 -0
- package/dist/temporal/observe.d.ts +85 -0
- package/dist/temporal/observe.d.ts.map +1 -0
- package/dist/temporal/observe.js +110 -0
- package/dist/temporal/observe.js.map +1 -0
- package/dist/temporal/schedules.d.ts +26 -0
- package/dist/temporal/schedules.d.ts.map +1 -0
- package/dist/temporal/schedules.js +200 -0
- package/dist/temporal/schedules.js.map +1 -0
- package/dist/temporal/status.d.ts +63 -0
- package/dist/temporal/status.d.ts.map +1 -0
- package/dist/temporal/status.js +153 -0
- package/dist/temporal/status.js.map +1 -0
- package/dist/temporal/stuck.d.ts +58 -0
- package/dist/temporal/stuck.d.ts.map +1 -0
- package/dist/temporal/stuck.js +53 -0
- package/dist/temporal/stuck.js.map +1 -0
- package/dist/temporal/supervisor.d.ts +11 -0
- package/dist/temporal/supervisor.d.ts.map +1 -0
- package/dist/temporal/supervisor.js +506 -0
- package/dist/temporal/supervisor.js.map +1 -0
- package/dist/temporal/worker.d.ts +21 -0
- package/dist/temporal/worker.d.ts.map +1 -0
- package/dist/temporal/worker.js +82 -0
- package/dist/temporal/worker.js.map +1 -0
- package/dist/temporal/workflow-bundle.js +12742 -0
- package/dist/temporal/workflows.d.ts +9 -0
- package/dist/temporal/workflows.d.ts.map +1 -0
- package/dist/temporal/workflows.js +144 -0
- package/dist/temporal/workflows.js.map +1 -0
- package/dist/version.d.ts +2 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +2 -0
- package/dist/version.js.map +1 -0
- package/dist/watchers/base.d.ts +4 -0
- package/dist/watchers/base.d.ts.map +1 -0
- package/dist/watchers/base.js +7 -0
- package/dist/watchers/base.js.map +1 -0
- package/dist/watchers/github/client.d.ts +52 -0
- package/dist/watchers/github/client.d.ts.map +1 -0
- package/dist/watchers/github/client.js +165 -0
- package/dist/watchers/github/client.js.map +1 -0
- package/dist/watchers/github/index.d.ts +19 -0
- package/dist/watchers/github/index.d.ts.map +1 -0
- package/dist/watchers/github/index.js +83 -0
- package/dist/watchers/github/index.js.map +1 -0
- package/dist/watchers/index.d.ts +2 -0
- package/dist/watchers/index.d.ts.map +1 -0
- package/dist/watchers/index.js +2 -0
- package/dist/watchers/index.js.map +1 -0
- package/dist/worker-lock.d.ts +11 -0
- package/dist/worker-lock.d.ts.map +1 -0
- package/dist/worker-lock.js +53 -0
- package/dist/worker-lock.js.map +1 -0
- package/package.json +92 -0
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
import { Ajv2020 } from "ajv/dist/2020.js";
|
|
2
|
+
import { sessionMismatchReason } from "../core/calls.js";
|
|
3
|
+
import { isJsonValue } from "../core/wire.js";
|
|
4
|
+
import { log } from "../log.js";
|
|
5
|
+
export const CLEANUP_TIMEOUT_MS = 10_000;
|
|
6
|
+
export class HarnessError extends Error {
|
|
7
|
+
diagnostic;
|
|
8
|
+
usage;
|
|
9
|
+
sessionId;
|
|
10
|
+
constructor(diagnostic, options = {}) {
|
|
11
|
+
super(diagnostic, options.cause === undefined ? undefined : { cause: options.cause });
|
|
12
|
+
this.name = new.target.name;
|
|
13
|
+
this.diagnostic = diagnostic;
|
|
14
|
+
this.usage = options.usage;
|
|
15
|
+
this.sessionId = options.sessionId;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
export class ProviderError extends HarnessError {
|
|
19
|
+
}
|
|
20
|
+
export class OutcomeError extends HarnessError {
|
|
21
|
+
}
|
|
22
|
+
export class ValidatingHarness {
|
|
23
|
+
async run(context, signal) {
|
|
24
|
+
const adapter = this.createAdapter(context);
|
|
25
|
+
let usage;
|
|
26
|
+
try {
|
|
27
|
+
throwIfAborted(signal);
|
|
28
|
+
const turn = await adapter.start(context.prompt, context.schema, signal);
|
|
29
|
+
usage = mergeUsage(usage, turn.usage);
|
|
30
|
+
assertSessionContinuity(context.resumeSessionId, adapter.sessionId);
|
|
31
|
+
let value;
|
|
32
|
+
try {
|
|
33
|
+
value = validateTurn(turn, context.schema);
|
|
34
|
+
}
|
|
35
|
+
catch (error) {
|
|
36
|
+
if (!(error instanceof OutcomeError) || turn.sessionId === undefined)
|
|
37
|
+
throw error;
|
|
38
|
+
const correction = "Return only one JSON value matching the required output schema. " +
|
|
39
|
+
`Correct these validation errors: ${error.diagnostic}`;
|
|
40
|
+
const corrected = await adapter.continue(correction, context.schema, signal);
|
|
41
|
+
usage = mergeUsage(usage, corrected.usage);
|
|
42
|
+
value = validateTurn(corrected, context.schema);
|
|
43
|
+
}
|
|
44
|
+
return {
|
|
45
|
+
value,
|
|
46
|
+
...(adapter.sessionId === undefined ? {} : { sessionId: adapter.sessionId }),
|
|
47
|
+
...(usage === undefined ? {} : { usage }),
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
catch (error) {
|
|
51
|
+
if (signal?.aborted || isAbortError(error)) {
|
|
52
|
+
await boundedCleanup(adapter.interrupt());
|
|
53
|
+
throw abortError(signal?.reason ?? error);
|
|
54
|
+
}
|
|
55
|
+
if (error instanceof HarnessError) {
|
|
56
|
+
error.usage = mergeUsage(usage, error.usage);
|
|
57
|
+
error.sessionId ??= adapter.sessionId;
|
|
58
|
+
}
|
|
59
|
+
throw error;
|
|
60
|
+
}
|
|
61
|
+
finally {
|
|
62
|
+
await boundedCleanup(adapter.close());
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
/** Guards the provider behaviour of silently starting a fresh session when a resume cannot bind. */
|
|
67
|
+
function assertSessionContinuity(expected, actual) {
|
|
68
|
+
if (expected === undefined)
|
|
69
|
+
return;
|
|
70
|
+
const reason = sessionMismatchReason(expected, actual);
|
|
71
|
+
if (reason !== undefined) {
|
|
72
|
+
throw new ProviderError(reason, actual === undefined ? {} : { sessionId: actual });
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
export function validateTurn(turn, schema) {
|
|
76
|
+
let payload = turn.payload;
|
|
77
|
+
if (payload === undefined) {
|
|
78
|
+
try {
|
|
79
|
+
payload = JSON.parse(turn.text ?? "");
|
|
80
|
+
}
|
|
81
|
+
catch (error) {
|
|
82
|
+
const message = error instanceof SyntaxError ? error.message : String(error);
|
|
83
|
+
throw new OutcomeError(`response is not JSON: ${message}`, { cause: error });
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
if (!isJsonValue(payload))
|
|
87
|
+
throw new OutcomeError("output must contain only JSON values");
|
|
88
|
+
const ajv = new Ajv2020({ allErrors: true, strict: true });
|
|
89
|
+
let validate;
|
|
90
|
+
try {
|
|
91
|
+
validate = ajv.compile(schema);
|
|
92
|
+
}
|
|
93
|
+
catch (error) {
|
|
94
|
+
throw new OutcomeError(`invalid output schema: ${errorMessage(error)}`, { cause: error });
|
|
95
|
+
}
|
|
96
|
+
if (!validate(payload)) {
|
|
97
|
+
const messages = [...(validate.errors ?? [])]
|
|
98
|
+
.sort(compareAjvErrors)
|
|
99
|
+
.map((error) => `${error.instancePath || "$"}: ${error.message ?? "invalid"}`);
|
|
100
|
+
throw new OutcomeError(messages.join("; ").slice(0, 2_000));
|
|
101
|
+
}
|
|
102
|
+
return payload;
|
|
103
|
+
}
|
|
104
|
+
export function mergeUsage(left, right) {
|
|
105
|
+
if (left === undefined)
|
|
106
|
+
return right === undefined ? undefined : structuredClone(right);
|
|
107
|
+
if (right === undefined)
|
|
108
|
+
return structuredClone(left);
|
|
109
|
+
const merged = structuredClone(left);
|
|
110
|
+
for (const [key, value] of Object.entries(right)) {
|
|
111
|
+
const current = merged[key];
|
|
112
|
+
if (isPlainJsonObject(current) && isPlainJsonObject(value)) {
|
|
113
|
+
merged[key] = mergeUsage(current, value) ?? {};
|
|
114
|
+
}
|
|
115
|
+
else if (typeof current === "number" && typeof value === "number") {
|
|
116
|
+
merged[key] = current + value;
|
|
117
|
+
}
|
|
118
|
+
else {
|
|
119
|
+
merged[key] = structuredClone(value);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
return merged;
|
|
123
|
+
}
|
|
124
|
+
export function jsonObject(value, label) {
|
|
125
|
+
if (value === undefined || value === null)
|
|
126
|
+
return undefined;
|
|
127
|
+
let normalized;
|
|
128
|
+
try {
|
|
129
|
+
normalized = JSON.parse(JSON.stringify(value));
|
|
130
|
+
}
|
|
131
|
+
catch (error) {
|
|
132
|
+
throw new ProviderError(`${label} is not JSON serializable`, { cause: error });
|
|
133
|
+
}
|
|
134
|
+
if (typeof normalized !== "object" || normalized === null || Array.isArray(normalized)) {
|
|
135
|
+
normalized = { value: normalized };
|
|
136
|
+
}
|
|
137
|
+
return normalized;
|
|
138
|
+
}
|
|
139
|
+
export function isAbortError(error) {
|
|
140
|
+
return error instanceof DOMException && error.name === "AbortError";
|
|
141
|
+
}
|
|
142
|
+
export function errorMessage(error) {
|
|
143
|
+
return error instanceof Error ? error.message : String(error);
|
|
144
|
+
}
|
|
145
|
+
async function boundedCleanup(operation) {
|
|
146
|
+
let timeout;
|
|
147
|
+
try {
|
|
148
|
+
await Promise.race([
|
|
149
|
+
operation,
|
|
150
|
+
new Promise((resolve) => {
|
|
151
|
+
timeout = setTimeout(() => {
|
|
152
|
+
log.warning(`agent provider cleanup exceeded ${CLEANUP_TIMEOUT_MS / 1_000}s`);
|
|
153
|
+
resolve();
|
|
154
|
+
}, CLEANUP_TIMEOUT_MS);
|
|
155
|
+
timeout.unref();
|
|
156
|
+
}),
|
|
157
|
+
]);
|
|
158
|
+
}
|
|
159
|
+
catch (error) {
|
|
160
|
+
log.warning("agent provider cleanup failed", error);
|
|
161
|
+
}
|
|
162
|
+
finally {
|
|
163
|
+
if (timeout !== undefined)
|
|
164
|
+
clearTimeout(timeout);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
function isPlainJsonObject(value) {
|
|
168
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
169
|
+
}
|
|
170
|
+
function compareAjvErrors(left, right) {
|
|
171
|
+
return (left.instancePath.localeCompare(right.instancePath) || left.keyword.localeCompare(right.keyword));
|
|
172
|
+
}
|
|
173
|
+
function throwIfAborted(signal) {
|
|
174
|
+
if (signal?.aborted)
|
|
175
|
+
throw abortError(signal.reason);
|
|
176
|
+
}
|
|
177
|
+
function abortError(reason) {
|
|
178
|
+
if (isAbortError(reason))
|
|
179
|
+
return reason;
|
|
180
|
+
return new DOMException(errorMessage(reason ?? "operation aborted"), "AbortError");
|
|
181
|
+
}
|
|
182
|
+
//# sourceMappingURL=base.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"base.js","sourceRoot":"","sources":["../../src/harnesses/base.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
export declare const CLAUDE_EXECUTABLE_ENV = "LOOPY_CLAUDE_EXECUTABLE";
|
|
2
|
+
export type LibcFamily = "glibc" | "musl";
|
|
3
|
+
interface ReportHeader {
|
|
4
|
+
glibcVersionRuntime?: string;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Host libc family, or undefined on platforms with no glibc/musl split we care
|
|
8
|
+
* about. Mirrors the SDK's own probe (`sdk.mjs` `preferMusl`): a Linux host is
|
|
9
|
+
* musl exactly when the Node process report carries no glibc runtime version.
|
|
10
|
+
*/
|
|
11
|
+
export declare function detectHostLibc(report?: () => ReportHeader | undefined, platform?: NodeJS.Platform): LibcFamily | undefined;
|
|
12
|
+
/**
|
|
13
|
+
* SDK platform-package binary specs for a host, most-preferred first. Mirrors
|
|
14
|
+
* the SDK's resolver: a musl host prefers the `-musl` package and falls back to
|
|
15
|
+
* the gnu one, and a glibc host the reverse, so a mismatched bundled binary is
|
|
16
|
+
* never chosen when a matching sibling package is installed.
|
|
17
|
+
*/
|
|
18
|
+
export declare function bundledExecutableSpecs(platform: NodeJS.Platform, arch: string, libc: LibcFamily | undefined): string[];
|
|
19
|
+
export interface ExecutableProbe {
|
|
20
|
+
readonly env: NodeJS.ProcessEnv;
|
|
21
|
+
/** The SDK's default bundled native binary, or undefined when no matching platform package is installed. */
|
|
22
|
+
resolveBundled(): string | undefined;
|
|
23
|
+
/** A `claude` executable found on PATH, or undefined. */
|
|
24
|
+
discoverOnPath(): string | undefined;
|
|
25
|
+
/** Whether the executable at `path` launches on this host (`--version` exits cleanly). */
|
|
26
|
+
launches(path: string): boolean;
|
|
27
|
+
}
|
|
28
|
+
export interface ClaudeExecutableOptions {
|
|
29
|
+
executable_path?: string | undefined;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* The `pathToClaudeCodeExecutable` to hand the SDK, or undefined to let the SDK
|
|
33
|
+
* resolve its own bundled binary. Priority: an explicit config override, then
|
|
34
|
+
* the `LOOPY_CLAUDE_EXECUTABLE` env override, then the SDK's bundled binary when
|
|
35
|
+
* it launches, then a `claude` discovered on PATH. An explicit or env override
|
|
36
|
+
* is trusted verbatim; auto-discovery only steps in when the bundled binary is
|
|
37
|
+
* missing or fails a launch probe.
|
|
38
|
+
*/
|
|
39
|
+
export declare function resolveClaudeExecutable(options: ClaudeExecutableOptions, probe?: ExecutableProbe): string | undefined;
|
|
40
|
+
export declare function createExecutableProbe(): ExecutableProbe;
|
|
41
|
+
export {};
|
|
42
|
+
//# sourceMappingURL=claude-executable.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claude-executable.d.ts","sourceRoot":"","sources":["../../src/harnesses/claude-executable.ts"],"names":[],"mappings":"AAeA,eAAO,MAAM,qBAAqB,4BAA4B,CAAC;AAI/D,MAAM,MAAM,UAAU,GAAG,OAAO,GAAG,MAAM,CAAC;AAE1C,UAAU,YAAY;IACpB,mBAAmB,CAAC,EAAE,MAAM,CAAC;CAC9B;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAC5B,MAAM,GAAE,MAAM,YAAY,GAAG,SAA+B,EAC5D,QAAQ,GAAE,MAAM,CAAC,QAA2B,GAC3C,UAAU,GAAG,SAAS,CAKxB;AAQD;;;;;GAKG;AACH,wBAAgB,sBAAsB,CACpC,QAAQ,EAAE,MAAM,CAAC,QAAQ,EACzB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,UAAU,GAAG,SAAS,GAC3B,MAAM,EAAE,CAWV;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC,UAAU,CAAC;IAChC,4GAA4G;IAC5G,cAAc,IAAI,MAAM,GAAG,SAAS,CAAC;IACrC,yDAAyD;IACzD,cAAc,IAAI,MAAM,GAAG,SAAS,CAAC;IACrC,0FAA0F;IAC1F,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;CACjC;AAED,MAAM,WAAW,uBAAuB;IACtC,eAAe,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACtC;AAED;;;;;;;GAOG;AACH,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,uBAAuB,EAChC,KAAK,GAAE,eAAyC,GAC/C,MAAM,GAAG,SAAS,CAoBpB;AAGD,wBAAgB,qBAAqB,IAAI,eAAe,CAOvD"}
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import { spawnSync } from "node:child_process";
|
|
2
|
+
import { accessSync, constants } from "node:fs";
|
|
3
|
+
import { createRequire } from "node:module";
|
|
4
|
+
import { delimiter, join } from "node:path";
|
|
5
|
+
import { log } from "../log.js";
|
|
6
|
+
// The Claude Agent SDK bundles a single native `claude` binary per platform
|
|
7
|
+
// package and only lets a caller override it via `pathToClaudeCodeExecutable`
|
|
8
|
+
// (there is no env override in the SDK). When that bundled binary's libc does
|
|
9
|
+
// not match the host - e.g. a musl-linked binary on a glibc host - it fails to
|
|
10
|
+
// launch and halts the whole instance at the first `claude` step. This module
|
|
11
|
+
// determines the host libc and picks a launchable executable so the harness is
|
|
12
|
+
// usable on any host. See issue #27.
|
|
13
|
+
export const CLAUDE_EXECUTABLE_ENV = "LOOPY_CLAUDE_EXECUTABLE";
|
|
14
|
+
const SDK_PACKAGE = "@anthropic-ai/claude-agent-sdk";
|
|
15
|
+
const LAUNCH_TIMEOUT_MS = 10_000;
|
|
16
|
+
/**
|
|
17
|
+
* Host libc family, or undefined on platforms with no glibc/musl split we care
|
|
18
|
+
* about. Mirrors the SDK's own probe (`sdk.mjs` `preferMusl`): a Linux host is
|
|
19
|
+
* musl exactly when the Node process report carries no glibc runtime version.
|
|
20
|
+
*/
|
|
21
|
+
export function detectHostLibc(report = defaultReportHeader, platform = process.platform) {
|
|
22
|
+
if (platform !== "linux")
|
|
23
|
+
return undefined;
|
|
24
|
+
const header = report();
|
|
25
|
+
if (header === undefined)
|
|
26
|
+
return undefined;
|
|
27
|
+
return header.glibcVersionRuntime === undefined ? "musl" : "glibc";
|
|
28
|
+
}
|
|
29
|
+
/* istanbul ignore next -- thin process.report boundary; detectHostLibc is tested with an injected report */
|
|
30
|
+
function defaultReportHeader() {
|
|
31
|
+
if (typeof process.report?.getReport !== "function")
|
|
32
|
+
return undefined;
|
|
33
|
+
return process.report.getReport().header;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* SDK platform-package binary specs for a host, most-preferred first. Mirrors
|
|
37
|
+
* the SDK's resolver: a musl host prefers the `-musl` package and falls back to
|
|
38
|
+
* the gnu one, and a glibc host the reverse, so a mismatched bundled binary is
|
|
39
|
+
* never chosen when a matching sibling package is installed.
|
|
40
|
+
*/
|
|
41
|
+
export function bundledExecutableSpecs(platform, arch, libc) {
|
|
42
|
+
const suffix = platform === "win32" ? ".exe" : "";
|
|
43
|
+
const packages = platform === "android"
|
|
44
|
+
? [`${SDK_PACKAGE}-linux-${arch}-android`]
|
|
45
|
+
: platform === "linux"
|
|
46
|
+
? libc === "musl"
|
|
47
|
+
? [`${SDK_PACKAGE}-linux-${arch}-musl`, `${SDK_PACKAGE}-linux-${arch}`]
|
|
48
|
+
: [`${SDK_PACKAGE}-linux-${arch}`, `${SDK_PACKAGE}-linux-${arch}-musl`]
|
|
49
|
+
: [`${SDK_PACKAGE}-${platform}-${arch}`];
|
|
50
|
+
return packages.map((pkg) => `${pkg}/claude${suffix}`);
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* The `pathToClaudeCodeExecutable` to hand the SDK, or undefined to let the SDK
|
|
54
|
+
* resolve its own bundled binary. Priority: an explicit config override, then
|
|
55
|
+
* the `LOOPY_CLAUDE_EXECUTABLE` env override, then the SDK's bundled binary when
|
|
56
|
+
* it launches, then a `claude` discovered on PATH. An explicit or env override
|
|
57
|
+
* is trusted verbatim; auto-discovery only steps in when the bundled binary is
|
|
58
|
+
* missing or fails a launch probe.
|
|
59
|
+
*/
|
|
60
|
+
export function resolveClaudeExecutable(options, probe = createExecutableProbe()) {
|
|
61
|
+
if (options.executable_path !== undefined)
|
|
62
|
+
return options.executable_path;
|
|
63
|
+
const override = probe.env[CLAUDE_EXECUTABLE_ENV]?.trim();
|
|
64
|
+
if (override !== undefined && override !== "")
|
|
65
|
+
return override;
|
|
66
|
+
const bundled = probe.resolveBundled();
|
|
67
|
+
if (bundled !== undefined && probe.launches(bundled))
|
|
68
|
+
return bundled;
|
|
69
|
+
const discovered = probe.discoverOnPath();
|
|
70
|
+
if (discovered !== undefined && probe.launches(discovered)) {
|
|
71
|
+
log.info(bundled === undefined
|
|
72
|
+
? `claude harness: no bundled SDK binary for this host; using ${discovered} from PATH`
|
|
73
|
+
: `claude harness: bundled SDK binary ${bundled} failed to launch; using ${discovered} from PATH`);
|
|
74
|
+
return discovered;
|
|
75
|
+
}
|
|
76
|
+
// Nothing better than the SDK default; let the SDK resolve and, if the
|
|
77
|
+
// bundled binary cannot launch, surface its own libc-mismatch diagnostic.
|
|
78
|
+
return undefined;
|
|
79
|
+
}
|
|
80
|
+
/* istanbul ignore next -- production process/filesystem wiring; resolveClaudeExecutable is tested with injected probes */
|
|
81
|
+
export function createExecutableProbe() {
|
|
82
|
+
return {
|
|
83
|
+
env: process.env,
|
|
84
|
+
resolveBundled: () => resolveBundledExecutable(),
|
|
85
|
+
discoverOnPath: () => discoverOnPath("claude"),
|
|
86
|
+
launches: (path) => launches(path),
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
/* istanbul ignore next -- resolves against installed SDK platform packages; exercised only in production installs */
|
|
90
|
+
function resolveBundledExecutable(platform = process.platform, arch = process.arch, libc = detectHostLibc()) {
|
|
91
|
+
let requireFromSdk;
|
|
92
|
+
try {
|
|
93
|
+
// Anchor at the SDK package so pnpm's nested platform packages resolve the
|
|
94
|
+
// same way the SDK's own resolver reaches them.
|
|
95
|
+
const requireFromHere = createRequire(import.meta.url);
|
|
96
|
+
requireFromSdk = createRequire(requireFromHere.resolve(SDK_PACKAGE));
|
|
97
|
+
}
|
|
98
|
+
catch {
|
|
99
|
+
return undefined;
|
|
100
|
+
}
|
|
101
|
+
for (const spec of bundledExecutableSpecs(platform, arch, libc)) {
|
|
102
|
+
try {
|
|
103
|
+
return requireFromSdk.resolve(spec);
|
|
104
|
+
}
|
|
105
|
+
catch {
|
|
106
|
+
// Try the next candidate package.
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
return undefined;
|
|
110
|
+
}
|
|
111
|
+
/* istanbul ignore next -- production PATH walk; discovery is exercised through injected probes */
|
|
112
|
+
function discoverOnPath(name, env = process.env, platform = process.platform) {
|
|
113
|
+
const directories = (env.PATH ?? "").split(delimiter).filter((entry) => entry !== "");
|
|
114
|
+
const candidates = platform === "win32" ? [`${name}.exe`, `${name}.cmd`, name] : [name];
|
|
115
|
+
for (const directory of directories) {
|
|
116
|
+
for (const candidate of candidates) {
|
|
117
|
+
const full = join(directory, candidate);
|
|
118
|
+
try {
|
|
119
|
+
accessSync(full, constants.X_OK);
|
|
120
|
+
return full;
|
|
121
|
+
}
|
|
122
|
+
catch {
|
|
123
|
+
// Not an executable here; keep looking.
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
return undefined;
|
|
128
|
+
}
|
|
129
|
+
/* istanbul ignore next -- spawns a real process; resolveClaudeExecutable is tested with an injected launch probe */
|
|
130
|
+
function launches(path, run = spawnSync) {
|
|
131
|
+
const result = run(path, ["--version"], {
|
|
132
|
+
timeout: LAUNCH_TIMEOUT_MS,
|
|
133
|
+
windowsHide: true,
|
|
134
|
+
stdio: "ignore",
|
|
135
|
+
});
|
|
136
|
+
return result.error === undefined && result.status === 0;
|
|
137
|
+
}
|
|
138
|
+
//# sourceMappingURL=claude-executable.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claude-executable.js","sourceRoot":"","sources":["../../src/harnesses/claude-executable.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { query as claudeQuery } from "@anthropic-ai/claude-agent-sdk";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
import type { HarnessContext, HarnessSpec } from "../adapters.js";
|
|
4
|
+
import { type Adapter, ValidatingHarness } from "./base.js";
|
|
5
|
+
export declare const claudeOptionsSchema: z.ZodObject<{
|
|
6
|
+
isolated: z.ZodDefault<z.ZodBoolean>;
|
|
7
|
+
permission_mode: z.ZodOptional<z.ZodEnum<{
|
|
8
|
+
acceptEdits: "acceptEdits";
|
|
9
|
+
auto: "auto";
|
|
10
|
+
bypassPermissions: "bypassPermissions";
|
|
11
|
+
default: "default";
|
|
12
|
+
dontAsk: "dontAsk";
|
|
13
|
+
plan: "plan";
|
|
14
|
+
}>>;
|
|
15
|
+
model: z.ZodString;
|
|
16
|
+
model_effort: z.ZodEnum<{
|
|
17
|
+
high: "high";
|
|
18
|
+
low: "low";
|
|
19
|
+
max: "max";
|
|
20
|
+
medium: "medium";
|
|
21
|
+
xhigh: "xhigh";
|
|
22
|
+
}>;
|
|
23
|
+
executable_path: z.ZodOptional<z.ZodString>;
|
|
24
|
+
}, z.core.$strict>;
|
|
25
|
+
export type ClaudeOptions = z.infer<typeof claudeOptionsSchema>;
|
|
26
|
+
export type ClaudeQueryFactory = typeof claudeQuery;
|
|
27
|
+
export declare class ClaudeHarness extends ValidatingHarness {
|
|
28
|
+
readonly options: ClaudeOptions;
|
|
29
|
+
private readonly queryFactory;
|
|
30
|
+
private readonly executable;
|
|
31
|
+
constructor(options: ClaudeOptions, queryFactory?: ClaudeQueryFactory, executable?: string);
|
|
32
|
+
protected createAdapter(context: HarnessContext): Adapter;
|
|
33
|
+
}
|
|
34
|
+
export declare const claudeHarnessSpec: HarnessSpec;
|
|
35
|
+
//# sourceMappingURL=claude.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claude.d.ts","sourceRoot":"","sources":["../../src/harnesses/claude.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,IAAI,WAAW,EAKrB,MAAM,gCAAgC,CAAC;AACxC,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAElE,OAAO,EACL,KAAK,OAAO,EAMZ,iBAAiB,EAClB,MAAM,WAAW,CAAC;AAGnB,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;kBAYrB,CAAC;AAEZ,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAChE,MAAM,MAAM,kBAAkB,GAAG,OAAO,WAAW,CAAC;AAEpD,qBAAa,aAAc,SAAQ,iBAAiB;IAClD,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAC;IAChC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAqB;IAClD,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAqB;IAEhD,YACE,OAAO,EAAE,aAAa,EAEtB,YAAY,GAAE,kBAAgC,EAC9C,UAAU,CAAC,EAAE,MAAM,EAMpB;IAED,SAAS,CAAC,aAAa,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAExD;CACF;AAsID,eAAO,MAAM,iBAAiB,EAAE,WAO/B,CAAC"}
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import { query as claudeQuery, } from "@anthropic-ai/claude-agent-sdk";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
import { errorMessage, isAbortError, jsonObject, ProviderError, ValidatingHarness, } from "./base.js";
|
|
4
|
+
import { resolveClaudeExecutable } from "./claude-executable.js";
|
|
5
|
+
export const claudeOptionsSchema = z
|
|
6
|
+
.object({
|
|
7
|
+
isolated: z.boolean().default(false),
|
|
8
|
+
permission_mode: z
|
|
9
|
+
.enum(["default", "acceptEdits", "plan", "bypassPermissions", "dontAsk", "auto"])
|
|
10
|
+
.optional(),
|
|
11
|
+
model: z.string().min(1),
|
|
12
|
+
model_effort: z.enum(["low", "medium", "high", "xhigh", "max"]),
|
|
13
|
+
// Override the SDK's bundled native binary when its libc does not match the
|
|
14
|
+
// host; auto-discovered from PATH when omitted. See claude-executable.ts.
|
|
15
|
+
executable_path: z.string().min(1).optional(),
|
|
16
|
+
})
|
|
17
|
+
.strict();
|
|
18
|
+
export class ClaudeHarness extends ValidatingHarness {
|
|
19
|
+
options;
|
|
20
|
+
queryFactory;
|
|
21
|
+
executable;
|
|
22
|
+
constructor(options,
|
|
23
|
+
/* istanbul ignore next -- production SDK wiring; tests inject a deterministic stream */
|
|
24
|
+
queryFactory = claudeQuery, executable) {
|
|
25
|
+
super();
|
|
26
|
+
this.options = options;
|
|
27
|
+
this.queryFactory = queryFactory;
|
|
28
|
+
this.executable = executable;
|
|
29
|
+
}
|
|
30
|
+
createAdapter(context) {
|
|
31
|
+
return new ClaudeAdapter(context, this.options, this.queryFactory, this.executable);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
class ClaudeAdapter {
|
|
35
|
+
sessionId;
|
|
36
|
+
currentQuery;
|
|
37
|
+
currentController;
|
|
38
|
+
context;
|
|
39
|
+
options;
|
|
40
|
+
queryFactory;
|
|
41
|
+
executable;
|
|
42
|
+
constructor(context, options, queryFactory, executable) {
|
|
43
|
+
this.context = context;
|
|
44
|
+
this.options = options;
|
|
45
|
+
this.queryFactory = queryFactory;
|
|
46
|
+
this.executable = executable;
|
|
47
|
+
}
|
|
48
|
+
start(prompt, schema, signal) {
|
|
49
|
+
return this.runQuery(prompt, schema, signal, this.context.resumeSessionId);
|
|
50
|
+
}
|
|
51
|
+
continue(prompt, schema, signal) {
|
|
52
|
+
/* istanbul ignore next -- ValidatingHarness only corrects turns carrying this session id */
|
|
53
|
+
if (this.sessionId === undefined) {
|
|
54
|
+
throw new ProviderError("Claude returned no session id for correction");
|
|
55
|
+
}
|
|
56
|
+
return this.runQuery(prompt, schema, signal, this.sessionId);
|
|
57
|
+
}
|
|
58
|
+
async interrupt() {
|
|
59
|
+
this.currentController?.abort();
|
|
60
|
+
this.currentQuery?.close();
|
|
61
|
+
}
|
|
62
|
+
async close() {
|
|
63
|
+
this.currentQuery?.close();
|
|
64
|
+
this.currentQuery = undefined;
|
|
65
|
+
this.currentController = undefined;
|
|
66
|
+
}
|
|
67
|
+
async runQuery(prompt, schema, signal, resume) {
|
|
68
|
+
const controller = new AbortController();
|
|
69
|
+
this.currentController = controller;
|
|
70
|
+
const onAbort = () => controller.abort(signal?.reason);
|
|
71
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
72
|
+
// Inherit on-disk config (~/.claude, project settings) unless the harness is isolated.
|
|
73
|
+
const settingSources = this.options.isolated
|
|
74
|
+
? []
|
|
75
|
+
: ["user", "project", "local"];
|
|
76
|
+
const options = {
|
|
77
|
+
abortController: controller,
|
|
78
|
+
cwd: this.context.workspace,
|
|
79
|
+
outputFormat: { type: "json_schema", schema: withoutSchemaDialect(schema) },
|
|
80
|
+
settingSources,
|
|
81
|
+
model: this.options.model,
|
|
82
|
+
effort: this.options.model_effort,
|
|
83
|
+
};
|
|
84
|
+
if (this.options.permission_mode !== undefined) {
|
|
85
|
+
options.permissionMode = this.options.permission_mode;
|
|
86
|
+
options.allowDangerouslySkipPermissions =
|
|
87
|
+
this.options.permission_mode === "bypassPermissions";
|
|
88
|
+
}
|
|
89
|
+
else if (this.options.isolated) {
|
|
90
|
+
// Sealed and unspecified: never block on prompts an operator cannot answer.
|
|
91
|
+
options.permissionMode = "bypassPermissions";
|
|
92
|
+
options.allowDangerouslySkipPermissions = true;
|
|
93
|
+
}
|
|
94
|
+
if (resume !== undefined)
|
|
95
|
+
options.resume = resume;
|
|
96
|
+
if (this.executable !== undefined)
|
|
97
|
+
options.pathToClaudeCodeExecutable = this.executable;
|
|
98
|
+
const stream = this.queryFactory({ prompt, options });
|
|
99
|
+
this.currentQuery = stream;
|
|
100
|
+
let result;
|
|
101
|
+
try {
|
|
102
|
+
for await (const message of stream) {
|
|
103
|
+
if (message.type === "result")
|
|
104
|
+
result = message;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
catch (error) {
|
|
108
|
+
if (controller.signal.aborted || signal?.aborted || isAbortError(error))
|
|
109
|
+
throw error;
|
|
110
|
+
throw new ProviderError(`Claude failed: ${errorMessage(error)}`.slice(0, 2_000), {
|
|
111
|
+
cause: error,
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
finally {
|
|
115
|
+
signal?.removeEventListener("abort", onAbort);
|
|
116
|
+
this.currentQuery = undefined;
|
|
117
|
+
this.currentController = undefined;
|
|
118
|
+
}
|
|
119
|
+
if (result === undefined)
|
|
120
|
+
throw new ProviderError("Claude returned no terminal result");
|
|
121
|
+
this.sessionId = result.session_id;
|
|
122
|
+
const usage = jsonObject({
|
|
123
|
+
tokens: result.usage,
|
|
124
|
+
models: result.modelUsage,
|
|
125
|
+
cost_usd: result.total_cost_usd,
|
|
126
|
+
}, "Claude usage");
|
|
127
|
+
if (result.subtype !== "success") {
|
|
128
|
+
const diagnostic = result.errors.join("; ") || result.stop_reason || "provider error";
|
|
129
|
+
throw new ProviderError(`Claude failed: ${diagnostic}`.slice(0, 2_000), usage === undefined ? {} : { usage });
|
|
130
|
+
}
|
|
131
|
+
const turn = {
|
|
132
|
+
text: result.result,
|
|
133
|
+
sessionId: result.session_id,
|
|
134
|
+
};
|
|
135
|
+
if (result.structured_output !== undefined)
|
|
136
|
+
turn.payload = result.structured_output;
|
|
137
|
+
if (usage !== undefined)
|
|
138
|
+
turn.usage = usage;
|
|
139
|
+
return turn;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
// Claude Code's `--json-schema` validator rejects a `$schema` dialect reference it cannot
|
|
143
|
+
// resolve (e.g. "https://json-schema.org/draft/2020-12/schema", which every loopy outcome
|
|
144
|
+
// schema declares), so drop the meta key before handing the schema to the SDK. The harness
|
|
145
|
+
// boundary still validates the returned outcome against the original schema with Ajv.
|
|
146
|
+
function withoutSchemaDialect(schema) {
|
|
147
|
+
if (!Object.hasOwn(schema, "$schema"))
|
|
148
|
+
return schema;
|
|
149
|
+
const { $schema: _dialect, ...rest } = schema;
|
|
150
|
+
return rest;
|
|
151
|
+
}
|
|
152
|
+
export const claudeHarnessSpec = {
|
|
153
|
+
name: "claude",
|
|
154
|
+
optionsSchema: claudeOptionsSchema,
|
|
155
|
+
create(options) {
|
|
156
|
+
const parsed = claudeOptionsSchema.parse(options);
|
|
157
|
+
return new ClaudeHarness(parsed, undefined, resolveClaudeExecutable(parsed));
|
|
158
|
+
},
|
|
159
|
+
};
|
|
160
|
+
//# sourceMappingURL=claude.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claude.js","sourceRoot":"","sources":["../../src/harnesses/claude.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { type Thread, type ThreadOptions } from "@openai/codex-sdk";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
import type { HarnessContext, HarnessSpec } from "../adapters.js";
|
|
4
|
+
import { type Adapter, ValidatingHarness } from "./base.js";
|
|
5
|
+
export declare const codexOptionsSchema: z.ZodObject<{
|
|
6
|
+
isolated: z.ZodDefault<z.ZodBoolean>;
|
|
7
|
+
sandbox: z.ZodOptional<z.ZodEnum<{
|
|
8
|
+
"full-access": "full-access";
|
|
9
|
+
"read-only": "read-only";
|
|
10
|
+
"workspace-write": "workspace-write";
|
|
11
|
+
}>>;
|
|
12
|
+
approval_mode: z.ZodOptional<z.ZodEnum<{
|
|
13
|
+
auto_review: "auto_review";
|
|
14
|
+
deny_all: "deny_all";
|
|
15
|
+
}>>;
|
|
16
|
+
model: z.ZodString;
|
|
17
|
+
model_effort: z.ZodEnum<{
|
|
18
|
+
high: "high";
|
|
19
|
+
low: "low";
|
|
20
|
+
medium: "medium";
|
|
21
|
+
minimal: "minimal";
|
|
22
|
+
none: "none";
|
|
23
|
+
xhigh: "xhigh";
|
|
24
|
+
}>;
|
|
25
|
+
}, z.core.$strict>;
|
|
26
|
+
export type CodexOptions = z.infer<typeof codexOptionsSchema>;
|
|
27
|
+
interface CodexClient {
|
|
28
|
+
startThread(options?: ThreadOptions): Thread;
|
|
29
|
+
resumeThread(id: string, options?: ThreadOptions): Thread;
|
|
30
|
+
}
|
|
31
|
+
export type CodexFactory = () => CodexClient;
|
|
32
|
+
export declare class CodexHarness extends ValidatingHarness {
|
|
33
|
+
readonly options: CodexOptions;
|
|
34
|
+
private readonly clientFactory;
|
|
35
|
+
constructor(options: CodexOptions, clientFactory?: CodexFactory);
|
|
36
|
+
protected createAdapter(context: HarnessContext): Adapter;
|
|
37
|
+
}
|
|
38
|
+
export declare const codexHarnessSpec: HarnessSpec;
|
|
39
|
+
export {};
|
|
40
|
+
//# sourceMappingURL=codex.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"codex.d.ts","sourceRoot":"","sources":["../../src/harnesses/codex.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,KAAK,MAAM,EACX,KAAK,aAAa,EACnB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAElE,OAAO,EACL,KAAK,OAAO,EAMZ,iBAAiB,EAClB,MAAM,WAAW,CAAC;AAEnB,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;kBAQpB,CAAC;AAEZ,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAE9D,UAAU,WAAW;IACnB,WAAW,CAAC,OAAO,CAAC,EAAE,aAAa,GAAG,MAAM,CAAC;IAC7C,YAAY,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,aAAa,GAAG,MAAM,CAAC;CAC3D;AAED,MAAM,MAAM,YAAY,GAAG,MAAM,WAAW,CAAC;AAE7C,qBAAa,YAAa,SAAQ,iBAAiB;IACjD,QAAQ,CAAC,OAAO,EAAE,YAAY,CAAC;IAC/B,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAe;IAE7C,YACE,OAAO,EAAE,YAAY,EAErB,aAAa,GAAE,YAAgC,EAKhD;IAED,SAAS,CAAC,aAAa,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAExD;CACF;AA2FD,eAAO,MAAM,gBAAgB,EAAE,WAM9B,CAAC"}
|