@odla-ai/harness 0.2.0 → 0.4.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/dist/{chunk-5FFR7U4L.js → chunk-ANNX7VGK.js} +87 -1
- package/dist/chunk-ANNX7VGK.js.map +1 -0
- package/dist/code-runtime-cli.cjs +58 -0
- package/dist/code-runtime-cli.cjs.map +1 -1
- package/dist/code-runtime-cli.js +1 -1
- package/dist/node.cjs +151 -2
- package/dist/node.cjs.map +1 -1
- package/dist/node.d.cts +195 -2
- package/dist/node.d.ts +195 -2
- package/dist/node.js +65 -1
- package/dist/node.js.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-5FFR7U4L.js.map +0 -1
package/dist/code-runtime-cli.js
CHANGED
package/dist/node.cjs
CHANGED
|
@@ -26,6 +26,7 @@ __export(node_exports, {
|
|
|
26
26
|
CodeRuntimeControlError: () => CodeRuntimeControlError,
|
|
27
27
|
CodeRuntimeReconciler: () => CodeRuntimeReconciler,
|
|
28
28
|
DecompositionError: () => DecompositionError,
|
|
29
|
+
MAX_MEMORY_BODY: () => MAX_MEMORY_BODY,
|
|
29
30
|
MEASURED_PREMIUM: () => MEASURED_PREMIUM,
|
|
30
31
|
SYSTEM_PROMPT_FOR: () => SYSTEM_PROMPT_FOR,
|
|
31
32
|
V1_SYSTEM_PROMPT: () => V1_SYSTEM_PROMPT,
|
|
@@ -48,17 +49,23 @@ __export(node_exports, {
|
|
|
48
49
|
describePatchFailure: () => describePatchFailure,
|
|
49
50
|
digestStagedWorkspace: () => digestStagedWorkspace,
|
|
50
51
|
feedbackIsActionable: () => feedbackIsActionable,
|
|
52
|
+
hazardFromAttempt: () => hazardFromAttempt,
|
|
51
53
|
installedDependencies: () => installedDependencies,
|
|
52
54
|
integrateSubGoals: () => integrateSubGoals,
|
|
53
55
|
isCheckpointEffectCompleted: () => isCheckpointEffectCompleted,
|
|
54
56
|
materializeCodeRuntimeSource: () => materializeCodeRuntimeSource,
|
|
55
57
|
materializeCommandWorkspace: () => materializeCommandWorkspace,
|
|
56
58
|
materializeGitTree: () => materializeGitTree,
|
|
59
|
+
outcomeCloses: () => outcomeCloses,
|
|
60
|
+
outcomeMemory: () => outcomeMemory,
|
|
57
61
|
patchPaths: () => patchPaths,
|
|
58
62
|
planReachCollisions: () => planReachCollisions,
|
|
59
63
|
prepareRuntimeCheckpoint: () => prepareRuntimeCheckpoint,
|
|
60
64
|
racedAttempt: () => racedAttempt,
|
|
65
|
+
recallAbout: () => recallAbout,
|
|
61
66
|
registeredFiles: () => registeredFiles,
|
|
67
|
+
renderMemories: () => renderMemories,
|
|
68
|
+
renderOutcome: () => renderOutcome,
|
|
62
69
|
resolveCodePath: () => resolveCodePath,
|
|
63
70
|
restoreCodeWorkspaceCheckpoint: () => restoreCodeWorkspaceCheckpoint,
|
|
64
71
|
runCodeAgent: () => runCodeAgent,
|
|
@@ -68,6 +75,7 @@ __export(node_exports, {
|
|
|
68
75
|
runGoal: () => runGoal,
|
|
69
76
|
runHarnessRunner: () => runHarnessRunner,
|
|
70
77
|
runLeasedAttempt: () => runLeasedAttempt,
|
|
78
|
+
runtimeMemoryStore: () => runtimeMemoryStore,
|
|
71
79
|
safeWorkspaceLabel: () => safeWorkspaceLabel,
|
|
72
80
|
selectContainerEngine: () => selectContainerEngine,
|
|
73
81
|
selectWinner: () => selectWinner,
|
|
@@ -76,6 +84,7 @@ __export(node_exports, {
|
|
|
76
84
|
straySubGoalFiles: () => straySubGoalFiles,
|
|
77
85
|
stripPatchEnvelope: () => stripPatchEnvelope,
|
|
78
86
|
validateCodePatch: () => validateCodePatch,
|
|
87
|
+
validateMemory: () => validateMemory,
|
|
79
88
|
validateRelativePath: () => validateRelativePath,
|
|
80
89
|
verifyCodeCandidate: () => verifyCodeCandidate,
|
|
81
90
|
verifyContainerEngineBoundary: () => verifyContainerEngineBoundary,
|
|
@@ -974,6 +983,16 @@ function createCodeRuntimeControlClient(options) {
|
|
|
974
983
|
}
|
|
975
984
|
await call(`/registry/code/runtime/sessions/${validSessionId(sessionId)}/chat/events`, { eventId, event });
|
|
976
985
|
},
|
|
986
|
+
recallMemories: async (sessionId, subjects, limit) => {
|
|
987
|
+
const response2 = await call(
|
|
988
|
+
`/registry/code/runtime/sessions/${validSessionId(sessionId)}/recall`,
|
|
989
|
+
{ subjects: [...subjects], limit }
|
|
990
|
+
);
|
|
991
|
+
return Array.isArray(response2.memories) ? response2.memories : [];
|
|
992
|
+
},
|
|
993
|
+
rememberMemory: async (sessionId, memory) => {
|
|
994
|
+
await call(`/registry/code/runtime/sessions/${validSessionId(sessionId)}/remember`, memory);
|
|
995
|
+
},
|
|
977
996
|
reportSessionFailure: async (sessionId, message2) => {
|
|
978
997
|
if (!message2.trim() || message2.length > 2e3) throw new TypeError("invalid Code session failure");
|
|
979
998
|
await call(`/registry/code/runtime/sessions/${validSessionId(sessionId)}/failure`, { message: message2 });
|
|
@@ -2832,6 +2851,55 @@ function createCodeRuntimeToolBroker(input, lease, role) {
|
|
|
2832
2851
|
return role === "coding" ? broker : { execute: (context, request) => request.tool === "sandbox.read" ? broker.execute(context, request) : Promise.resolve({ requestId: request.requestId, ok: false, content: "review sessions are read-only" }) };
|
|
2833
2852
|
}
|
|
2834
2853
|
|
|
2854
|
+
// src/code-memory.ts
|
|
2855
|
+
var import_graph2 = require("@odla-ai/graph");
|
|
2856
|
+
var MAX_MEMORY_BODY = 4e3;
|
|
2857
|
+
function validateMemory(memory) {
|
|
2858
|
+
if (!memory.subject.includes(":")) {
|
|
2859
|
+
throw new TypeError(`memory subject must be a graph node id, got "${memory.subject}"`);
|
|
2860
|
+
}
|
|
2861
|
+
const body = memory.body.trim();
|
|
2862
|
+
if (!body) throw new TypeError("a memory needs a body");
|
|
2863
|
+
if (body.length > MAX_MEMORY_BODY) throw new TypeError("memory body exceeds its bound");
|
|
2864
|
+
if (!memory.authorId.trim()) throw new TypeError("a memory needs an author");
|
|
2865
|
+
}
|
|
2866
|
+
async function recallAbout(store, subjects, options = {}) {
|
|
2867
|
+
const limit = options.limit ?? 20;
|
|
2868
|
+
const wanted = options.graph ? [...(0, import_graph2.closure)(options.graph, subjects, {
|
|
2869
|
+
direction: "out",
|
|
2870
|
+
maxDepth: options.depth ?? 1,
|
|
2871
|
+
...options.kinds ? { kinds: options.kinds } : {}
|
|
2872
|
+
})] : [...subjects];
|
|
2873
|
+
const found = await store.recall(wanted, limit * 2);
|
|
2874
|
+
return found.filter((memory) => !memory.supersededBy).slice(0, limit);
|
|
2875
|
+
}
|
|
2876
|
+
function renderMemories(memories) {
|
|
2877
|
+
if (memories.length === 0) return "";
|
|
2878
|
+
const lines = memories.map((memory) => {
|
|
2879
|
+
const source = memory.evidence ? ` [${memory.evidence.kind}:${memory.evidence.ref}]` : " [unverified]";
|
|
2880
|
+
return `- (${memory.kind}) ${memory.subject}${source}
|
|
2881
|
+
${memory.body.replace(/\s+/g, " ").slice(0, 400)}`;
|
|
2882
|
+
});
|
|
2883
|
+
return [
|
|
2884
|
+
"What previous runs learned about this code. A hazard cost an attempt to find;",
|
|
2885
|
+
"an unverified note is one agent's opinion. Treat them accordingly.",
|
|
2886
|
+
...lines
|
|
2887
|
+
].join("\n");
|
|
2888
|
+
}
|
|
2889
|
+
function hazardFromAttempt(input) {
|
|
2890
|
+
const body = [
|
|
2891
|
+
`Attempt ${input.attempt} at "${input.goal.slice(0, 200)}" failed its proof.`,
|
|
2892
|
+
input.feedback.replace(/\s+/g, " ").slice(0, MAX_MEMORY_BODY - 300)
|
|
2893
|
+
].join(" ");
|
|
2894
|
+
return input.touched.slice(0, 10).map((path) => ({
|
|
2895
|
+
subject: path.includes(":") ? path : `file:${path}`,
|
|
2896
|
+
kind: "hazard",
|
|
2897
|
+
body,
|
|
2898
|
+
evidence: { kind: "gate", ref: input.verificationId },
|
|
2899
|
+
authorId: input.authorId
|
|
2900
|
+
}));
|
|
2901
|
+
}
|
|
2902
|
+
|
|
2835
2903
|
// src/code-goal-runner.ts
|
|
2836
2904
|
async function runGoal(spec, attempt) {
|
|
2837
2905
|
assertBudget(spec.budget);
|
|
@@ -3016,6 +3084,9 @@ function pursueRuntimeGoal(input) {
|
|
|
3016
3084
|
return { gatePassed: false, feedback: "", tokens: outcome.tokens, error: outcome.error };
|
|
3017
3085
|
}
|
|
3018
3086
|
const verdict = await input.gate(attempt);
|
|
3087
|
+
if (!verdict.passed && input.memory) {
|
|
3088
|
+
await rememberFailure(input, attempt, verdict.feedback);
|
|
3089
|
+
}
|
|
3019
3090
|
return {
|
|
3020
3091
|
gatePassed: verdict.passed,
|
|
3021
3092
|
feedback: verdict.feedback,
|
|
@@ -3026,6 +3097,25 @@ function pursueRuntimeGoal(input) {
|
|
|
3026
3097
|
}
|
|
3027
3098
|
);
|
|
3028
3099
|
}
|
|
3100
|
+
async function rememberFailure(input, attempt, feedback) {
|
|
3101
|
+
if (!input.memory || !feedback.trim()) return;
|
|
3102
|
+
try {
|
|
3103
|
+
const touched = await input.touched?.(attempt) ?? [];
|
|
3104
|
+
if (touched.length === 0) return;
|
|
3105
|
+
for (const memory of hazardFromAttempt({
|
|
3106
|
+
goal: input.spec.goal,
|
|
3107
|
+
attempt,
|
|
3108
|
+
feedback,
|
|
3109
|
+
touched,
|
|
3110
|
+
verificationId: `goal-${attempt}`,
|
|
3111
|
+
authorId: input.memory.authorId
|
|
3112
|
+
})) {
|
|
3113
|
+
validateMemory(memory);
|
|
3114
|
+
await input.memory.store.remember(memory);
|
|
3115
|
+
}
|
|
3116
|
+
} catch {
|
|
3117
|
+
}
|
|
3118
|
+
}
|
|
3029
3119
|
function goalEventLine(event) {
|
|
3030
3120
|
if (event.type === "attempt_started") return `Goal attempt ${event.attempt} starting.`;
|
|
3031
3121
|
if (event.type === "attempt_failed") return `Attempt ${event.attempt} did not satisfy the proof.`;
|
|
@@ -3351,6 +3441,56 @@ var CodePiRuntimeEngine = class {
|
|
|
3351
3441
|
}
|
|
3352
3442
|
};
|
|
3353
3443
|
|
|
3444
|
+
// src/code-runtime-memory.ts
|
|
3445
|
+
async function mutationId(memory) {
|
|
3446
|
+
const source = `${memory.subject} ${memory.kind} ${memory.body}`;
|
|
3447
|
+
const bytes = await crypto.subtle.digest("SHA-256", new TextEncoder().encode(source));
|
|
3448
|
+
return Array.from(new Uint8Array(bytes), (byte) => byte.toString(16).padStart(2, "0")).join("").slice(0, 40);
|
|
3449
|
+
}
|
|
3450
|
+
function runtimeMemoryStore(control, sessionId) {
|
|
3451
|
+
const recall = control.recallMemories;
|
|
3452
|
+
const remember = control.rememberMemory;
|
|
3453
|
+
if (!recall || !remember) return null;
|
|
3454
|
+
return {
|
|
3455
|
+
recall: async (subjects, limit) => await recall.call(control, sessionId, subjects, limit),
|
|
3456
|
+
remember: async (memory) => {
|
|
3457
|
+
await remember.call(control, sessionId, {
|
|
3458
|
+
subject: memory.subject,
|
|
3459
|
+
kind: memory.kind,
|
|
3460
|
+
body: memory.body,
|
|
3461
|
+
...memory.evidence ? { evidence: memory.evidence } : {},
|
|
3462
|
+
mutationId: await mutationId(memory)
|
|
3463
|
+
});
|
|
3464
|
+
return { ...memory, id: "", createdAt: Date.now() };
|
|
3465
|
+
}
|
|
3466
|
+
};
|
|
3467
|
+
}
|
|
3468
|
+
|
|
3469
|
+
// src/code-goal-outcome.ts
|
|
3470
|
+
function outcomeCloses(outcome) {
|
|
3471
|
+
return outcome.met && outcome.evidence !== void 0;
|
|
3472
|
+
}
|
|
3473
|
+
function renderOutcome(outcome) {
|
|
3474
|
+
const spend = outcome.costUsd === void 0 ? "cost unknown" : `$${outcome.costUsd.toFixed(4)}`;
|
|
3475
|
+
const scale = `${outcome.attempts} attempt(s), ${outcome.tokens.toLocaleString()} tokens, ${spend}`;
|
|
3476
|
+
if (!outcome.met) {
|
|
3477
|
+
return `Goal not met (${outcome.stoppedReason}) after ${scale}. Proof: ${outcome.proof}`;
|
|
3478
|
+
}
|
|
3479
|
+
if (!outcome.evidence) {
|
|
3480
|
+
return `Goal reported met after ${scale}, but no verification receipt was produced. Treat as unverified. Proof: ${outcome.proof}`;
|
|
3481
|
+
}
|
|
3482
|
+
return `Goal met after ${scale}. Verified by ${outcome.evidence.kind}:${outcome.evidence.ref}. Proof: ${outcome.proof}`;
|
|
3483
|
+
}
|
|
3484
|
+
function outcomeMemory(outcome, subject, authorId) {
|
|
3485
|
+
return {
|
|
3486
|
+
subject,
|
|
3487
|
+
kind: "outcome",
|
|
3488
|
+
body: renderOutcome(outcome),
|
|
3489
|
+
...outcome.evidence ? { evidence: outcome.evidence } : {},
|
|
3490
|
+
authorId
|
|
3491
|
+
};
|
|
3492
|
+
}
|
|
3493
|
+
|
|
3354
3494
|
// src/code-goal-race.ts
|
|
3355
3495
|
function selectWinner(outcomes) {
|
|
3356
3496
|
const ranked = [...outcomes].sort((left, right) => {
|
|
@@ -3411,7 +3551,7 @@ function racedAttempt(options) {
|
|
|
3411
3551
|
}
|
|
3412
3552
|
|
|
3413
3553
|
// src/code-goal-decompose.ts
|
|
3414
|
-
var
|
|
3554
|
+
var import_graph3 = require("@odla-ai/graph");
|
|
3415
3555
|
var import_code5 = require("@odla-ai/graph/code");
|
|
3416
3556
|
var DecompositionError = class extends Error {
|
|
3417
3557
|
constructor(message2) {
|
|
@@ -3499,7 +3639,7 @@ async function integrateSubGoals(options) {
|
|
|
3499
3639
|
}
|
|
3500
3640
|
async function planReachCollisions(plan, workspace) {
|
|
3501
3641
|
const graph = await (0, import_code5.buildCodeGraph)({ paths: workspace.paths, read: workspace.read });
|
|
3502
|
-
return (0,
|
|
3642
|
+
return (0, import_graph3.partition)(graph, plan.map((sub) => sub.files.map((file) => `${import_code5.FILE}:${file}`)), {
|
|
3503
3643
|
kinds: [import_code5.IMPORTS, import_code5.READS, import_code5.WRITES],
|
|
3504
3644
|
direction: "out"
|
|
3505
3645
|
});
|
|
@@ -3609,6 +3749,7 @@ async function installedDependencies(repoRoot) {
|
|
|
3609
3749
|
CodeRuntimeControlError,
|
|
3610
3750
|
CodeRuntimeReconciler,
|
|
3611
3751
|
DecompositionError,
|
|
3752
|
+
MAX_MEMORY_BODY,
|
|
3612
3753
|
MEASURED_PREMIUM,
|
|
3613
3754
|
SYSTEM_PROMPT_FOR,
|
|
3614
3755
|
V1_SYSTEM_PROMPT,
|
|
@@ -3631,17 +3772,23 @@ async function installedDependencies(repoRoot) {
|
|
|
3631
3772
|
describePatchFailure,
|
|
3632
3773
|
digestStagedWorkspace,
|
|
3633
3774
|
feedbackIsActionable,
|
|
3775
|
+
hazardFromAttempt,
|
|
3634
3776
|
installedDependencies,
|
|
3635
3777
|
integrateSubGoals,
|
|
3636
3778
|
isCheckpointEffectCompleted,
|
|
3637
3779
|
materializeCodeRuntimeSource,
|
|
3638
3780
|
materializeCommandWorkspace,
|
|
3639
3781
|
materializeGitTree,
|
|
3782
|
+
outcomeCloses,
|
|
3783
|
+
outcomeMemory,
|
|
3640
3784
|
patchPaths,
|
|
3641
3785
|
planReachCollisions,
|
|
3642
3786
|
prepareRuntimeCheckpoint,
|
|
3643
3787
|
racedAttempt,
|
|
3788
|
+
recallAbout,
|
|
3644
3789
|
registeredFiles,
|
|
3790
|
+
renderMemories,
|
|
3791
|
+
renderOutcome,
|
|
3645
3792
|
resolveCodePath,
|
|
3646
3793
|
restoreCodeWorkspaceCheckpoint,
|
|
3647
3794
|
runCodeAgent,
|
|
@@ -3651,6 +3798,7 @@ async function installedDependencies(repoRoot) {
|
|
|
3651
3798
|
runGoal,
|
|
3652
3799
|
runHarnessRunner,
|
|
3653
3800
|
runLeasedAttempt,
|
|
3801
|
+
runtimeMemoryStore,
|
|
3654
3802
|
safeWorkspaceLabel,
|
|
3655
3803
|
selectContainerEngine,
|
|
3656
3804
|
selectWinner,
|
|
@@ -3659,6 +3807,7 @@ async function installedDependencies(repoRoot) {
|
|
|
3659
3807
|
straySubGoalFiles,
|
|
3660
3808
|
stripPatchEnvelope,
|
|
3661
3809
|
validateCodePatch,
|
|
3810
|
+
validateMemory,
|
|
3662
3811
|
validateRelativePath,
|
|
3663
3812
|
verifyCodeCandidate,
|
|
3664
3813
|
verifyContainerEngineBoundary,
|