pi-harness-runtime 0.9.25 → 0.10.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/CHANGELOG.md +27 -7
- package/README.md +51 -51
- package/harness/auto-compact.ts +1 -1
- package/harness/autonomous-review.ts +88 -0
- package/harness/context-compact-orchestrator.ts +23 -23
- package/harness/context-window-manager.ts +5 -5
- package/harness/continue-prompt.ts +3 -3
- package/harness/e2e/minimax-quota-scraper.ts +1 -1
- package/harness/forked-summarizer.ts +4 -4
- package/harness/herdr-agents.ts +91 -0
- package/harness/index.ts +5 -5
- package/harness/loop-code-agent.ts +284 -0
- package/harness/loop-controller.ts +201 -0
- package/harness/loop-review-agent.ts +295 -0
- package/harness/loop-runtime.ts +10 -10
- package/harness/loop-types.ts +118 -0
- package/harness/notification-events.ts +3 -3
- package/harness/output-limit-handler.ts +1 -1
- package/harness/partial-recovery.ts +3 -3
- package/harness/session-memory.ts +5 -5
- package/index.ts +46 -32
- package/package.json +1 -1
- package/packages/a2a-adapter/package.json +1 -1
- package/packages/a2a-adapter/src/types.ts +5 -5
- package/packages/auth/package.json +1 -1
- package/packages/autonomous-refactor/package.json +1 -1
- package/packages/autonomous-runtime/dist/inbox.d.ts +3 -3
- package/packages/autonomous-runtime/dist/inbox.js +12 -12
- package/packages/autonomous-runtime/dist/lease.js +14 -14
- package/packages/autonomous-runtime/dist/types.js +1 -1
- package/packages/autonomous-runtime/package.json +1 -1
- package/packages/autonomous-runtime/src/inbox.ts +12 -12
- package/packages/autonomous-runtime/src/lease.ts +15 -15
- package/packages/autonomous-runtime/src/types.ts +13 -13
- package/packages/autonomous-runtime/tsconfig.tsbuildinfo +1 -1
- package/packages/cache-strategy/package.json +1 -1
- package/packages/capability-registry/dist/types.js +1 -1
- package/packages/capability-registry/package.json +1 -1
- package/packages/capability-registry/src/types.ts +5 -5
- package/packages/checkpoint/README.md +6 -6
- package/packages/checkpoint/dist/differ.js +2 -2
- package/packages/checkpoint/dist/engine.js +3 -3
- package/packages/checkpoint/dist/index.js +5 -5
- package/packages/checkpoint/dist/storage.js +3 -3
- package/packages/checkpoint/dist/types.js +1 -1
- package/packages/checkpoint/package.json +1 -1
- package/packages/checkpoint/src/differ.ts +2 -2
- package/packages/checkpoint/src/engine.ts +3 -3
- package/packages/checkpoint/src/index.ts +5 -5
- package/packages/checkpoint/src/storage.ts +3 -3
- package/packages/checkpoint/src/types.ts +10 -10
- package/packages/checkpoint/tsconfig.tsbuildinfo +1 -1
- package/packages/cli-plugin-sdk/package.json +1 -1
- package/packages/clipboard/dist/src/clipboard.d.ts.map +1 -1
- package/packages/clipboard/dist/src/clipboard.js +15 -7
- package/packages/clipboard/dist/src/clipboard.js.map +1 -1
- package/packages/clipboard/package.json +1 -1
- package/packages/clipboard/src/clipboard.ts +16 -9
- package/packages/code-generation/README.md +13 -13
- package/packages/code-generation/dist/faker.js +4 -4
- package/packages/code-generation/dist/generator.js +3 -3
- package/packages/code-generation/dist/index.js +3 -3
- package/packages/code-generation/dist/templates/registry.js +1 -1
- package/packages/code-generation/dist/types.js +1 -1
- package/packages/code-generation/package.json +1 -1
- package/packages/code-generation/src/faker.ts +5 -5
- package/packages/code-generation/src/generator.ts +4 -4
- package/packages/code-generation/src/index.ts +3 -3
- package/packages/code-generation/src/templates/registry.ts +1 -1
- package/packages/code-generation/src/types.ts +10 -10
- package/packages/code-generation/tsconfig.tsbuildinfo +1 -1
- package/packages/code-review/README.md +13 -13
- package/packages/code-review/dist/engine.js +3 -3
- package/packages/code-review/dist/index.js +3 -3
- package/packages/code-review/dist/types.js +1 -1
- package/packages/code-review/package.json +1 -1
- package/packages/code-review/src/engine.ts +3 -3
- package/packages/code-review/src/index.ts +3 -3
- package/packages/code-review/src/types.ts +10 -10
- package/packages/code-review/tsconfig.tsbuildinfo +1 -1
- package/packages/codex-adapter/package.json +1 -1
- package/packages/context-compiler/dist/compiler.js +1 -1
- package/packages/context-compiler/package.json +1 -1
- package/packages/context-compiler/src/compiler.ts +1 -1
- package/packages/context-compiler/src/types.ts +11 -11
- package/packages/context-compiler/test/context-compiler.test.ts +11 -11
- package/packages/context-discovery/package.json +1 -1
- package/packages/context-manager/package.json +1 -1
- package/packages/cookie-sanitizer/README.md +27 -27
- package/packages/cookie-sanitizer/package.json +1 -1
- package/packages/cost-optimizer/package.json +1 -1
- package/packages/cost-optimizer/src/types.ts +5 -5
- package/packages/dependency-analyzer/package.json +1 -1
- package/packages/django-plugin/dist/analyzer.js +7 -7
- package/packages/django-plugin/package.json +1 -1
- package/packages/django-plugin/src/analyzer.ts +7 -7
- package/packages/doc-generator/package.json +1 -1
- package/packages/evaluation-engine/dist/engine.js +9 -9
- package/packages/evaluation-engine/package.json +1 -1
- package/packages/evaluation-engine/src/engine.ts +9 -9
- package/packages/evaluation-engine/src/types.ts +3 -3
- package/packages/evaluation-runner/package.json +1 -1
- package/packages/event-bus/dist/src/herdr-bus.d.ts +121 -0
- package/packages/event-bus/dist/src/herdr-bus.d.ts.map +1 -0
- package/packages/event-bus/dist/src/herdr-bus.js +322 -0
- package/packages/event-bus/dist/src/herdr-bus.js.map +1 -0
- package/packages/event-bus/dist/src/index.d.ts +2 -0
- package/packages/event-bus/dist/src/index.d.ts.map +1 -1
- package/packages/event-bus/dist/src/index.js +1 -0
- package/packages/event-bus/dist/src/index.js.map +1 -1
- package/packages/event-bus/package.json +1 -1
- package/packages/event-bus/src/herdr-bus.ts +525 -0
- package/packages/event-bus/src/index.ts +29 -0
- package/packages/event-store/package.json +1 -1
- package/packages/experience-replay/dist/replay.js +7 -7
- package/packages/experience-replay/package.json +1 -1
- package/packages/experience-replay/src/replay.ts +7 -7
- package/packages/experience-replay/src/types.ts +5 -5
- package/packages/feedback-collector/package.json +1 -1
- package/packages/framework-detector/README.md +18 -18
- package/packages/framework-detector/dist/detector.js +3 -3
- package/packages/framework-detector/dist/index.js +3 -3
- package/packages/framework-detector/dist/signatures/registry.js +24 -24
- package/packages/framework-detector/dist/types.js +1 -1
- package/packages/framework-detector/package.json +1 -1
- package/packages/framework-detector/src/detector.ts +3 -3
- package/packages/framework-detector/src/index.ts +3 -3
- package/packages/framework-detector/src/signatures/registry.ts +24 -24
- package/packages/framework-detector/src/types.ts +7 -7
- package/packages/framework-detector/tsconfig.tsbuildinfo +1 -1
- package/packages/framework-plugin-sdk/README.md +23 -23
- package/packages/framework-plugin-sdk/dist/index.js +2 -2
- package/packages/framework-plugin-sdk/dist/manager.js +3 -3
- package/packages/framework-plugin-sdk/dist/types.js +2 -2
- package/packages/framework-plugin-sdk/package.json +1 -1
- package/packages/framework-plugin-sdk/src/index.ts +2 -2
- package/packages/framework-plugin-sdk/src/manager.ts +3 -3
- package/packages/framework-plugin-sdk/src/types.ts +10 -10
- package/packages/framework-plugin-sdk/tsconfig.tsbuildinfo +1 -1
- package/packages/frappe-plugin/dist/analyzer.js +8 -8
- package/packages/frappe-plugin/dist/types.js +1 -1
- package/packages/frappe-plugin/package.json +1 -1
- package/packages/frappe-plugin/src/analyzer.ts +8 -8
- package/packages/frappe-plugin/src/types.ts +10 -10
- package/packages/generic-web-plugin/dist/analyzer.js +5 -5
- package/packages/generic-web-plugin/package.json +1 -1
- package/packages/generic-web-plugin/src/analyzer.ts +5 -5
- package/packages/health-monitor/package.json +1 -1
- package/packages/health-monitor/src/monitor.ts +1 -1
- package/packages/intent-analyzer/package.json +1 -1
- package/packages/laravel-plugin/dist/analyzer.js +11 -11
- package/packages/laravel-plugin/package.json +1 -1
- package/packages/laravel-plugin/src/analyzer.ts +11 -11
- package/packages/learning-engine/dist/engine.js +5 -5
- package/packages/learning-engine/dist/types.js +1 -1
- package/packages/learning-engine/package.json +1 -1
- package/packages/learning-engine/src/engine.ts +5 -5
- package/packages/learning-engine/src/types.ts +6 -6
- package/packages/mcp-adapter/package.json +1 -1
- package/packages/memory-engine/dist/engine.js +8 -8
- package/packages/memory-engine/dist/types.js +2 -2
- package/packages/memory-engine/package.json +1 -1
- package/packages/memory-engine/src/engine.ts +8 -8
- package/packages/memory-engine/src/types.ts +9 -9
- package/packages/model-registry/package.json +1 -1
- package/packages/model-registry/src/types.ts +4 -4
- package/packages/nextjs-plugin/dist/analyzer.js +9 -9
- package/packages/nextjs-plugin/package.json +1 -1
- package/packages/nextjs-plugin/src/analyzer.ts +9 -9
- package/packages/notification/dist/notification-center.js +1 -1
- package/packages/notification/package.json +1 -1
- package/packages/notification/src/notification-center.ts +1 -1
- package/packages/observability/dist/alerts.js +2 -2
- package/packages/observability/dist/health.js +4 -4
- package/packages/observability/dist/index.js +6 -6
- package/packages/observability/dist/logger.js +7 -7
- package/packages/observability/dist/metrics.js +11 -11
- package/packages/observability/dist/tracer.js +3 -3
- package/packages/observability/dist/types.js +1 -1
- package/packages/observability/package.json +1 -1
- package/packages/observability/src/alerts.ts +2 -2
- package/packages/observability/src/health.ts +4 -4
- package/packages/observability/src/index.ts +6 -6
- package/packages/observability/src/logger.ts +7 -7
- package/packages/observability/src/metrics.ts +11 -11
- package/packages/observability/src/tracer.ts +3 -3
- package/packages/observability/src/types.ts +7 -7
- package/packages/observability/test/observability.test.ts +4 -4
- package/packages/observability/tsconfig.tsbuildinfo +1 -1
- package/packages/performance-optimizer/dist/optimizer.js +1 -1
- package/packages/performance-optimizer/package.json +1 -1
- package/packages/performance-optimizer/src/optimizer.ts +1 -1
- package/packages/performance-optimizer/src/types.ts +4 -4
- package/packages/privilege-broker/package.json +1 -1
- package/packages/project-analyzer/dist/analyzer.js +4 -4
- package/packages/project-analyzer/dist/index.js +8 -8
- package/packages/project-analyzer/dist/signals.js +3 -3
- package/packages/project-analyzer/dist/types.js +1 -1
- package/packages/project-analyzer/package.json +1 -1
- package/packages/project-analyzer/src/analyzer.ts +4 -4
- package/packages/project-analyzer/src/index.ts +9 -9
- package/packages/project-analyzer/src/signals.ts +4 -4
- package/packages/project-analyzer/src/types.ts +15 -15
- package/packages/project-analyzer/test/index.test.ts +17 -17
- package/packages/project-analyzer/tsconfig.tsbuildinfo +1 -1
- package/packages/projection-engine/package.json +1 -1
- package/packages/prompt-compiler/dist/section-builder.js +1 -1
- package/packages/prompt-compiler/dist/types.js +3 -3
- package/packages/prompt-compiler/package.json +1 -1
- package/packages/prompt-compiler/src/section-builder.ts +1 -1
- package/packages/prompt-compiler/src/types.ts +12 -12
- package/packages/prompt-compiler/test/prompt-compiler.test.ts +12 -12
- package/packages/prompt-versioning/package.json +1 -1
- package/packages/provider-adapter-sdk/dist/builder.js +1 -1
- package/packages/provider-adapter-sdk/dist/index.js +5 -5
- package/packages/provider-adapter-sdk/dist/registry.js +1 -1
- package/packages/provider-adapter-sdk/dist/tester.js +1 -1
- package/packages/provider-adapter-sdk/dist/types.js +1 -1
- package/packages/provider-adapter-sdk/package.json +1 -1
- package/packages/provider-adapter-sdk/src/builder.ts +1 -1
- package/packages/provider-adapter-sdk/src/index.ts +6 -6
- package/packages/provider-adapter-sdk/src/registry.ts +1 -1
- package/packages/provider-adapter-sdk/src/tester.ts +1 -1
- package/packages/provider-adapter-sdk/src/types.ts +5 -5
- package/packages/provider-adapter-sdk/tsconfig.tsbuildinfo +1 -1
- package/packages/provider-router/package.json +1 -1
- package/packages/provider-router/src/types.ts +4 -4
- package/packages/provider-selector/package.json +1 -1
- package/packages/providers/dist/deepagents-adapter.js +1 -1
- package/packages/providers/package.json +1 -1
- package/packages/providers/src/deepagents-adapter.ts +1 -1
- package/packages/quota-manager/package.json +1 -1
- package/packages/rate-limiter/package.json +1 -1
- package/packages/react-vite-plugin/dist/analyzer.js +7 -7
- package/packages/react-vite-plugin/package.json +1 -1
- package/packages/react-vite-plugin/src/analyzer.ts +7 -7
- package/packages/release-manager/package.json +1 -1
- package/packages/requirement-compiler/dist/compiler.js +17 -17
- package/packages/requirement-compiler/dist/types.js +2 -2
- package/packages/requirement-compiler/package.json +1 -1
- package/packages/requirement-compiler/src/compiler.ts +17 -17
- package/packages/requirement-compiler/src/types.ts +21 -21
- package/packages/requirement-compiler/test/requirement-compiler.test.ts +17 -17
- package/packages/runtime/dist/command-executor.js +1 -1
- package/packages/runtime/dist/local-runtime-agent.js +1 -1
- package/packages/runtime/dist/policy-engine.js +1 -1
- package/packages/runtime/dist/runtime-api.js +1 -1
- package/packages/runtime/dist/workspace-manager.js +1 -1
- package/packages/runtime/package.json +1 -1
- package/packages/runtime/src/command-executor.ts +1 -1
- package/packages/runtime/src/local-runtime-agent.ts +1 -1
- package/packages/runtime/src/policy-engine.ts +1 -1
- package/packages/runtime/src/runtime-api.ts +1 -1
- package/packages/runtime/src/workspace-manager.ts +1 -1
- package/packages/scheduler/package.json +1 -1
- package/packages/scheduler-adapter/package.json +1 -1
- package/packages/session/README.md +18 -18
- package/packages/session/dist/history.js +3 -3
- package/packages/session/dist/index.js +5 -5
- package/packages/session/dist/manager.js +3 -3
- package/packages/session/dist/policy.js +2 -2
- package/packages/session/dist/store.js +2 -2
- package/packages/session/dist/types.js +1 -1
- package/packages/session/package.json +1 -1
- package/packages/session/src/history.ts +3 -3
- package/packages/session/src/index.ts +5 -5
- package/packages/session/src/manager.ts +3 -3
- package/packages/session/src/policy.ts +4 -4
- package/packages/session/src/store.ts +3 -3
- package/packages/session/src/types.ts +10 -10
- package/packages/session/tsconfig.tsbuildinfo +1 -1
- package/packages/session-api/package.json +1 -1
- package/packages/session-export/package.json +1 -1
- package/packages/shared-context/package.json +1 -1
- package/packages/skill-registry/package.json +1 -1
- package/packages/skill-registry/src/types.ts +4 -4
- package/packages/sprint-planner/package.json +1 -1
- package/packages/subscription-engine/package.json +1 -1
- package/packages/task-compiler/dist/compiler.js +7 -7
- package/packages/task-compiler/dist/decompose.js +11 -11
- package/packages/task-compiler/dist/file-scope.js +6 -6
- package/packages/task-compiler/dist/graph.js +6 -6
- package/packages/task-compiler/dist/index.js +2 -2
- package/packages/task-compiler/dist/types.js +5 -5
- package/packages/task-compiler/dist/validate.js +2 -2
- package/packages/task-compiler/dist/verification.js +2 -2
- package/packages/task-compiler/package.json +1 -1
- package/packages/task-compiler/src/command-policy.ts +1 -1
- package/packages/task-compiler/src/compiler.ts +7 -7
- package/packages/task-compiler/src/decompose.ts +11 -11
- package/packages/task-compiler/src/file-scope.ts +6 -6
- package/packages/task-compiler/src/graph.ts +6 -6
- package/packages/task-compiler/src/index.ts +3 -3
- package/packages/task-compiler/src/types.ts +14 -14
- package/packages/task-compiler/src/validate.ts +2 -2
- package/packages/task-compiler/src/verification.ts +2 -2
- package/packages/task-compiler/test/task-compiler.test.ts +10 -10
- package/packages/test-data-generator/README.md +13 -13
- package/packages/test-data-generator/dist/faker-adapter.js +4 -4
- package/packages/test-data-generator/dist/generator.js +3 -3
- package/packages/test-data-generator/dist/index.js +3 -3
- package/packages/test-data-generator/dist/types.js +1 -1
- package/packages/test-data-generator/package.json +1 -1
- package/packages/test-data-generator/src/faker-adapter.ts +4 -4
- package/packages/test-data-generator/src/generator.ts +3 -3
- package/packages/test-data-generator/src/index.ts +3 -3
- package/packages/test-data-generator/src/types.ts +9 -9
- package/packages/test-data-generator/tsconfig.tsbuildinfo +1 -1
- package/packages/test-generator/package.json +1 -1
- package/packages/token-estimation/package.json +1 -1
- package/packages/token-optimizer/package.json +1 -1
- package/packages/tui/package.json +1 -1
- package/packages/types/package.json +1 -1
- package/packages/types/src/agent-worker-types.ts +5 -5
- package/packages/types/src/runtime-types.ts +12 -12
- package/packages/types/tsconfig.tsbuildinfo +1 -1
- package/packages/workflow-events/package.json +1 -1
- package/packages/workspace-scanner/package.json +1 -1
- package/packages/worktree/package.json +1 -1
- package/renderer.ts +7 -7
- package/skills/harness-runtime/SKILL.md +15 -15
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Loop Review Agent (GPT) — coordinates via blackboard.
|
|
3
|
+
*
|
|
4
|
+
* Polls blackboard for nextAction where agentType="review".
|
|
5
|
+
* Reviews code, writes verdict, updates node status.
|
|
6
|
+
*
|
|
7
|
+
* Usage: bun harness/loop-review-agent.ts
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { existsSync, readFileSync, writeFileSync, mkdirSync } from "fs";
|
|
11
|
+
import { join } from "path";
|
|
12
|
+
import {
|
|
13
|
+
ensureHerdrWorkspace,
|
|
14
|
+
parseVerdict,
|
|
15
|
+
} from "../packages/event-bus/src/herdr-bus.js";
|
|
16
|
+
import { SharedBlackboard } from "./blackboard.js";
|
|
17
|
+
import type {
|
|
18
|
+
LoopNextAction,
|
|
19
|
+
LoopAgentReport,
|
|
20
|
+
LoopVerdict,
|
|
21
|
+
} from "./loop-types.js";
|
|
22
|
+
|
|
23
|
+
const AGENT_ID = "review-agent";
|
|
24
|
+
const AGENT_TYPE = "review";
|
|
25
|
+
const POLL_MS = 1000;
|
|
26
|
+
const REVIEW_TIMEOUT_MS = 5 * 60 * 1000;
|
|
27
|
+
|
|
28
|
+
async function main(): Promise<void> {
|
|
29
|
+
console.log(`[${AGENT_ID}] Starting...`);
|
|
30
|
+
const paths = ensureHerdrWorkspace();
|
|
31
|
+
|
|
32
|
+
// Find active loop config
|
|
33
|
+
const loopId = await findActiveLoop(paths.root);
|
|
34
|
+
if (!loopId) console.log(`[${AGENT_ID}] No active loop found. Waiting...`);
|
|
35
|
+
|
|
36
|
+
const blackboard = new SharedBlackboard(loopId ?? "no-loop", paths.root);
|
|
37
|
+
blackboard.load();
|
|
38
|
+
blackboard.registerAgent(AGENT_ID, "Review Agent", "openai", "gpt-4o");
|
|
39
|
+
blackboard.updateAgentStatus(AGENT_ID, "idle");
|
|
40
|
+
console.log(`[${AGENT_ID}] Registered. Blackboard: ${blackboard.getPath()}`);
|
|
41
|
+
|
|
42
|
+
while (true) {
|
|
43
|
+
await sleep(POLL_MS);
|
|
44
|
+
|
|
45
|
+
blackboard.load();
|
|
46
|
+
const record = blackboard.getRecord();
|
|
47
|
+
if (!record) continue;
|
|
48
|
+
if (record.jobId !== loopId) continue;
|
|
49
|
+
|
|
50
|
+
// Check for early exit
|
|
51
|
+
const earlyExit = checkEarlyExit(record);
|
|
52
|
+
if (earlyExit) {
|
|
53
|
+
console.log(`[${AGENT_ID}] Loop ended: ${earlyExit}`);
|
|
54
|
+
break;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// Check nextAction for review agent
|
|
58
|
+
const action = parseNextAction(record.nextAction);
|
|
59
|
+
if (!action || action.agentType !== AGENT_TYPE) continue;
|
|
60
|
+
|
|
61
|
+
// Claim the task
|
|
62
|
+
const locked = blackboard.acquireLock(action.taskId, AGENT_ID);
|
|
63
|
+
if (!locked) continue;
|
|
64
|
+
|
|
65
|
+
blackboard.updateAgentStatus(AGENT_ID, "working", action.taskId);
|
|
66
|
+
console.log(`[${AGENT_ID}] Claimed: ${action.taskId}`);
|
|
67
|
+
|
|
68
|
+
// Handle report task
|
|
69
|
+
if (action.taskId === "report") {
|
|
70
|
+
await finishReport(blackboard, record);
|
|
71
|
+
break;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// Do the review
|
|
75
|
+
const verdict = await doReview(action, paths, record.jobId);
|
|
76
|
+
|
|
77
|
+
// Update task status
|
|
78
|
+
updateTaskStatus(blackboard, record, action.taskId, verdict);
|
|
79
|
+
|
|
80
|
+
// Release and report
|
|
81
|
+
blackboard.releaseLock(action.taskId, AGENT_ID);
|
|
82
|
+
blackboard.writeReport({
|
|
83
|
+
agentId: AGENT_ID,
|
|
84
|
+
taskId: action.taskId,
|
|
85
|
+
status: "success",
|
|
86
|
+
message: verdict,
|
|
87
|
+
} as unknown as Parameters<typeof blackboard.writeReport>[0]);
|
|
88
|
+
blackboard.updateAgentStatus(AGENT_ID, "idle");
|
|
89
|
+
|
|
90
|
+
// Decide next action based on verdict
|
|
91
|
+
if (verdict === "approved" || verdict === "blocked") {
|
|
92
|
+
// Early exit — go to report
|
|
93
|
+
blackboard.setNextAction(
|
|
94
|
+
encodeNextAction({
|
|
95
|
+
taskId: "report",
|
|
96
|
+
agentType: "review",
|
|
97
|
+
iteration: 0,
|
|
98
|
+
}),
|
|
99
|
+
);
|
|
100
|
+
console.log(
|
|
101
|
+
`[${AGENT_ID}] ${verdict.toUpperCase()} — nextAction: report`,
|
|
102
|
+
);
|
|
103
|
+
} else {
|
|
104
|
+
// Changes requested — continue to next write
|
|
105
|
+
const nextWrite = getNextWriteTask(record, action.iteration);
|
|
106
|
+
if (nextWrite) {
|
|
107
|
+
blackboard.setNextAction(
|
|
108
|
+
encodeNextAction({
|
|
109
|
+
taskId: nextWrite,
|
|
110
|
+
agentType: "code",
|
|
111
|
+
iteration: getWriteIteration(nextWrite),
|
|
112
|
+
prompt: action.prompt,
|
|
113
|
+
}),
|
|
114
|
+
);
|
|
115
|
+
console.log(`[${AGENT_ID}] CHANGES — nextAction: code ${nextWrite}`);
|
|
116
|
+
} else {
|
|
117
|
+
blackboard.setNextAction({
|
|
118
|
+
taskId: "report",
|
|
119
|
+
agentType: "review",
|
|
120
|
+
iteration: 0,
|
|
121
|
+
} as unknown as ReturnType<typeof encodeNextAction>);
|
|
122
|
+
console.log(`[${AGENT_ID}] CHANGES — nextAction: report`);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// ─── Review Logic ────────────────────────────────────────────────────────
|
|
129
|
+
|
|
130
|
+
async function doReview(
|
|
131
|
+
action: LoopNextAction,
|
|
132
|
+
paths: { reviews: string },
|
|
133
|
+
loopId: string,
|
|
134
|
+
): Promise<LoopVerdict> {
|
|
135
|
+
const reviewDir = join(paths.reviews, loopId);
|
|
136
|
+
mkdirSync(reviewDir, { recursive: true });
|
|
137
|
+
|
|
138
|
+
const reviewFile = join(reviewDir, `review-${action.iteration}.md`);
|
|
139
|
+
|
|
140
|
+
// Read code files
|
|
141
|
+
const codeBlocks = await Promise.all(
|
|
142
|
+
(action.codeFiles ?? []).map(async (file) => {
|
|
143
|
+
const content = existsSync(file)
|
|
144
|
+
? readFileSync(file, "utf-8").slice(0, 3000)
|
|
145
|
+
: `[Not found: ${file}]`;
|
|
146
|
+
return `## ${file}\n\n\`\`\`\n${content}\n\`\`\`\n`;
|
|
147
|
+
}),
|
|
148
|
+
);
|
|
149
|
+
|
|
150
|
+
// Write review stub
|
|
151
|
+
const review = `# Review — Iteration ${action.iteration}
|
|
152
|
+
|
|
153
|
+
> GPT tab: Edit this file and add your verdict at the bottom.
|
|
154
|
+
> Use: \`## Verdict: APPROVED\`, \`## Verdict: CHANGES_REQUESTED\`, or \`## Verdict: BLOCKED\`
|
|
155
|
+
> GPT tab has ${REVIEW_TIMEOUT_MS / 1000 / 60} minutes to complete.
|
|
156
|
+
|
|
157
|
+
${codeBlocks.join("\n")}
|
|
158
|
+
`;
|
|
159
|
+
writeFileSync(reviewFile, review);
|
|
160
|
+
console.log(`[${AGENT_ID}] Review stub: ${reviewFile}`);
|
|
161
|
+
console.log(`[${AGENT_ID}] Waiting for GPT verdict...`);
|
|
162
|
+
|
|
163
|
+
// Poll for verdict
|
|
164
|
+
return await pollVerdict(reviewFile);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
async function pollVerdict(reviewFile: string): Promise<LoopVerdict> {
|
|
168
|
+
const deadline = Date.now() + REVIEW_TIMEOUT_MS;
|
|
169
|
+
while (Date.now() < deadline) {
|
|
170
|
+
if (existsSync(reviewFile)) {
|
|
171
|
+
const content = readFileSync(reviewFile, "utf-8");
|
|
172
|
+
const verdict = parseVerdict(content);
|
|
173
|
+
if (verdict) return verdict;
|
|
174
|
+
}
|
|
175
|
+
await sleep(3000);
|
|
176
|
+
}
|
|
177
|
+
console.log(
|
|
178
|
+
`[${AGENT_ID}] Verdict timeout — defaulting to CHANGES_REQUESTED`,
|
|
179
|
+
);
|
|
180
|
+
return "changes_requested";
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
async function finishReport(
|
|
184
|
+
blackboard: SharedBlackboard,
|
|
185
|
+
record: { tasks: { nodes: Record<string, { status: string }> } },
|
|
186
|
+
): Promise<void> {
|
|
187
|
+
const reportNode = record.tasks.nodes["report"] as { status: string };
|
|
188
|
+
reportNode.status = "done";
|
|
189
|
+
blackboard.save();
|
|
190
|
+
console.log(`[${AGENT_ID}] Report complete. Loop finished.`);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
// ─── Helpers ────────────────────────────────────────────────────────────────
|
|
194
|
+
|
|
195
|
+
async function findActiveLoop(rootDir: string): Promise<string | null> {
|
|
196
|
+
const { readdirSync } = await import("fs");
|
|
197
|
+
try {
|
|
198
|
+
const files = readdirSync(rootDir).filter(
|
|
199
|
+
(f) => f.startsWith("loop-") && f.endsWith(".config.json"),
|
|
200
|
+
);
|
|
201
|
+
if (files.length > 0) {
|
|
202
|
+
const config = JSON.parse(readFileSync(join(rootDir, files[0]), "utf-8"));
|
|
203
|
+
return config.loopId;
|
|
204
|
+
}
|
|
205
|
+
} catch {
|
|
206
|
+
// no loop yet
|
|
207
|
+
}
|
|
208
|
+
return null;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
function checkEarlyExit(record: {
|
|
212
|
+
tasks: { nodes: Record<string, { status: string }> };
|
|
213
|
+
jobId: string;
|
|
214
|
+
}): string | null {
|
|
215
|
+
const reportNode = record.tasks.nodes["report"];
|
|
216
|
+
if (
|
|
217
|
+
reportNode &&
|
|
218
|
+
(reportNode.status === "done" || reportNode.status === "blocked")
|
|
219
|
+
) {
|
|
220
|
+
return reportNode.status === "done" ? "finished" : "blocked";
|
|
221
|
+
}
|
|
222
|
+
return null;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
function updateTaskStatus(
|
|
226
|
+
blackboard: SharedBlackboard,
|
|
227
|
+
record: {
|
|
228
|
+
tasks: { nodes: Record<string, { status: string; result?: string }> };
|
|
229
|
+
},
|
|
230
|
+
taskId: string,
|
|
231
|
+
verdict: LoopVerdict,
|
|
232
|
+
): void {
|
|
233
|
+
const node = record.tasks.nodes[taskId] as
|
|
234
|
+
| { status: string; result?: string }
|
|
235
|
+
| undefined;
|
|
236
|
+
if (node) {
|
|
237
|
+
node.status = verdict === "blocked" ? "blocked" : "done";
|
|
238
|
+
node.result = verdict;
|
|
239
|
+
node.updatedAt = new Date().toISOString();
|
|
240
|
+
blackboard.save();
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
function encodeNextAction(action: Partial<LoopNextAction>) {
|
|
245
|
+
return {
|
|
246
|
+
taskId: action.taskId,
|
|
247
|
+
instruction: "LOOP:" + JSON.stringify(action),
|
|
248
|
+
priority: "high" as const,
|
|
249
|
+
createdAt: new Date().toISOString(),
|
|
250
|
+
};
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
function parseNextAction(nextAction: unknown): LoopNextAction | null {
|
|
254
|
+
if (!nextAction) return null;
|
|
255
|
+
const a = nextAction as Record<string, unknown>;
|
|
256
|
+
if (!a.taskId) return null;
|
|
257
|
+
if (typeof a.instruction === "string" && a.instruction.startsWith("LOOP:")) {
|
|
258
|
+
try {
|
|
259
|
+
return JSON.parse(a.instruction.slice(5)) as LoopNextAction;
|
|
260
|
+
} catch {
|
|
261
|
+
return null;
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
return null;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
function getNextWriteTask(
|
|
268
|
+
record: { tasks: { nodes: Record<string, { status: string }> } },
|
|
269
|
+
currentReviewIteration: number,
|
|
270
|
+
): string | null {
|
|
271
|
+
const writeCount = Object.keys(record.tasks.nodes).filter((id) =>
|
|
272
|
+
id.startsWith("write-"),
|
|
273
|
+
).length;
|
|
274
|
+
// After review N, next write is N+1
|
|
275
|
+
const nextWrite = currentReviewIteration + 1;
|
|
276
|
+
const taskId = `write-${nextWrite}`;
|
|
277
|
+
if (
|
|
278
|
+
record.tasks.nodes[taskId] &&
|
|
279
|
+
record.tasks.nodes[taskId].status === "pending"
|
|
280
|
+
) {
|
|
281
|
+
return taskId;
|
|
282
|
+
}
|
|
283
|
+
return null;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
function getWriteIteration(taskId: string): number {
|
|
287
|
+
const m = taskId.match(/^write-(\d+)$/);
|
|
288
|
+
return m ? parseInt(m[1], 10) : 0;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
function sleep(ms: number): Promise<void> {
|
|
292
|
+
return new Promise((r) => setTimeout(r, ms));
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
main().catch(console.error);
|
package/harness/loop-runtime.ts
CHANGED
|
@@ -46,12 +46,12 @@ import {
|
|
|
46
46
|
createForkedSummarizer,
|
|
47
47
|
} from "./forked-summarizer.js";
|
|
48
48
|
|
|
49
|
-
//
|
|
49
|
+
// --- Constants ----------------------------------------------------------------
|
|
50
50
|
|
|
51
51
|
const DEFAULT_MAX_COMPACT_RETRIES = 3;
|
|
52
52
|
const DEFAULT_MAX_OUTPUT_TOKENS = 4096;
|
|
53
53
|
|
|
54
|
-
//
|
|
54
|
+
// --- Lifecycle Callbacks ----------------------------------------------------
|
|
55
55
|
|
|
56
56
|
export interface LoopCallbacks {
|
|
57
57
|
/** Fetch next task from queue */
|
|
@@ -97,7 +97,7 @@ export interface LoopCallbacks {
|
|
|
97
97
|
onCompaction?: (result: CompactResult) => void;
|
|
98
98
|
}
|
|
99
99
|
|
|
100
|
-
//
|
|
100
|
+
// --- Loop Result -----------------------------------------------------------
|
|
101
101
|
|
|
102
102
|
export interface LoopResult {
|
|
103
103
|
success: boolean;
|
|
@@ -109,7 +109,7 @@ export interface LoopResult {
|
|
|
109
109
|
totalCompactions?: number;
|
|
110
110
|
}
|
|
111
111
|
|
|
112
|
-
//
|
|
112
|
+
// --- Loop Runtime -----------------------------------------------------------
|
|
113
113
|
|
|
114
114
|
export class LoopRuntime {
|
|
115
115
|
private readonly config: Required<LoopConfig>;
|
|
@@ -221,12 +221,12 @@ export class LoopRuntime {
|
|
|
221
221
|
}
|
|
222
222
|
}
|
|
223
223
|
|
|
224
|
-
//
|
|
224
|
+
// --- Public API ---------------------------------------------------------
|
|
225
225
|
|
|
226
226
|
async run(): Promise<LoopResult> {
|
|
227
227
|
this.running = true;
|
|
228
228
|
|
|
229
|
-
//
|
|
229
|
+
// --- Auto-resume from quota pause ----------------------------------
|
|
230
230
|
const checkpoint = await this.callbacks.onGetCheckpoint?.();
|
|
231
231
|
if (checkpoint?.status === "paused_quota" && checkpoint.resumeAt) {
|
|
232
232
|
const resumeMs = new Date(checkpoint.resumeAt).getTime();
|
|
@@ -348,7 +348,7 @@ export class LoopRuntime {
|
|
|
348
348
|
return this.sessionMemory;
|
|
349
349
|
}
|
|
350
350
|
|
|
351
|
-
//
|
|
351
|
+
// --- Task Execution with Compact ---------------------------------------
|
|
352
352
|
|
|
353
353
|
private async executeTaskWithCompact(task: RuntimeTask): Promise<void> {
|
|
354
354
|
// 1. Pick model
|
|
@@ -690,7 +690,7 @@ export class LoopRuntime {
|
|
|
690
690
|
return parts.join("\n");
|
|
691
691
|
}
|
|
692
692
|
|
|
693
|
-
//
|
|
693
|
+
// --- Quota Handling ----------------------------------------------------
|
|
694
694
|
|
|
695
695
|
private async handleQuotaPause(): Promise<void> {
|
|
696
696
|
this.paused = true;
|
|
@@ -717,7 +717,7 @@ export class LoopRuntime {
|
|
|
717
717
|
await this.saveCheckpoint();
|
|
718
718
|
}
|
|
719
719
|
|
|
720
|
-
//
|
|
720
|
+
// --- Persistence --------------------------------------------------------
|
|
721
721
|
|
|
722
722
|
private async saveCheckpoint(): Promise<void> {
|
|
723
723
|
const now = new Date().toISOString();
|
|
@@ -736,7 +736,7 @@ export class LoopRuntime {
|
|
|
736
736
|
await this.callbacks.onCheckpoint?.(checkpoint);
|
|
737
737
|
}
|
|
738
738
|
|
|
739
|
-
//
|
|
739
|
+
// --- Resume from Checkpoint --------------------------------------------
|
|
740
740
|
|
|
741
741
|
async resumeFromCheckpoint(
|
|
742
742
|
checkpoint: RuntimeCheckpoint,
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared types for loop coordination via blackboard.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import type {
|
|
6
|
+
TaskGraph,
|
|
7
|
+
TaskNode,
|
|
8
|
+
} from "../packages/types/src/runtime-types.ts";
|
|
9
|
+
|
|
10
|
+
export type LoopVerdict = "approved" | "changes_requested" | "blocked";
|
|
11
|
+
export type LoopNodeType = "write" | "review" | "decide" | "report";
|
|
12
|
+
export type LoopNodeStatus = "pending" | "running" | "done" | "blocked";
|
|
13
|
+
|
|
14
|
+
export interface LoopNextAction {
|
|
15
|
+
taskId: string;
|
|
16
|
+
agentType: "code" | "review";
|
|
17
|
+
iteration: number;
|
|
18
|
+
prompt?: string;
|
|
19
|
+
codeFiles?: string[];
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export interface LoopAgentReport {
|
|
23
|
+
agentId: string;
|
|
24
|
+
taskId: string;
|
|
25
|
+
status: "running" | "done" | "failed";
|
|
26
|
+
message?: string;
|
|
27
|
+
files?: string[];
|
|
28
|
+
verdict?: LoopVerdict;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export interface LoopTaskGraph {
|
|
32
|
+
nodes: Record<string, TaskNode>;
|
|
33
|
+
topologicalOrder: string[];
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export function buildLoopTaskGraph(
|
|
37
|
+
writeCount: number,
|
|
38
|
+
reviewCount: number,
|
|
39
|
+
loopId: string,
|
|
40
|
+
): TaskGraph {
|
|
41
|
+
const now = new Date().toISOString();
|
|
42
|
+
const nodes: Record<string, TaskNode> = {};
|
|
43
|
+
const order: string[] = [];
|
|
44
|
+
|
|
45
|
+
// Write tasks
|
|
46
|
+
for (let i = 1; i <= writeCount; i++) {
|
|
47
|
+
const id = `write-${i}`;
|
|
48
|
+
nodes[id] = {
|
|
49
|
+
id,
|
|
50
|
+
title: `Code Write ${i}`,
|
|
51
|
+
description: `Write iteration ${i}`,
|
|
52
|
+
status: "pending",
|
|
53
|
+
dependencies: [],
|
|
54
|
+
dependents: [],
|
|
55
|
+
createdAt: now,
|
|
56
|
+
updatedAt: now,
|
|
57
|
+
};
|
|
58
|
+
order.push(id);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// Review tasks
|
|
62
|
+
const step = Math.max(1, Math.floor(writeCount / (reviewCount || 1)));
|
|
63
|
+
for (let i = 1; i <= reviewCount; i++) {
|
|
64
|
+
const id = `review-${i}`;
|
|
65
|
+
const writeIdx = i * step;
|
|
66
|
+
nodes[id] = {
|
|
67
|
+
id,
|
|
68
|
+
title: `Code Review ${i}`,
|
|
69
|
+
description: `Review iteration ${i}`,
|
|
70
|
+
status: "pending",
|
|
71
|
+
dependencies: writeIdx <= writeCount ? [`write-${writeIdx}`] : [],
|
|
72
|
+
dependents: [],
|
|
73
|
+
createdAt: now,
|
|
74
|
+
updatedAt: now,
|
|
75
|
+
};
|
|
76
|
+
// Wire dependencies
|
|
77
|
+
if (writeIdx <= writeCount) {
|
|
78
|
+
nodes[`write-${writeIdx}`].dependents.push(id);
|
|
79
|
+
}
|
|
80
|
+
order.push(id);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// Report task
|
|
84
|
+
const reportId = "report";
|
|
85
|
+
nodes[reportId] = {
|
|
86
|
+
id: reportId,
|
|
87
|
+
title: "Loop Report",
|
|
88
|
+
description: "Final summary",
|
|
89
|
+
status: "pending",
|
|
90
|
+
dependencies: [],
|
|
91
|
+
dependents: [],
|
|
92
|
+
createdAt: now,
|
|
93
|
+
updatedAt: now,
|
|
94
|
+
};
|
|
95
|
+
order.push(reportId);
|
|
96
|
+
|
|
97
|
+
return {
|
|
98
|
+
jobId: loopId,
|
|
99
|
+
nodes,
|
|
100
|
+
topologicalOrder: order,
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export function getNodeStatus(
|
|
105
|
+
graph: TaskGraph,
|
|
106
|
+
nodeId: string,
|
|
107
|
+
): LoopNodeStatus | undefined {
|
|
108
|
+
return graph.nodes[nodeId]?.status as LoopNodeStatus | undefined;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
export function getReviewVerdict(
|
|
112
|
+
graph: TaskGraph,
|
|
113
|
+
reviewId: string,
|
|
114
|
+
): LoopVerdict | undefined {
|
|
115
|
+
const node = graph.nodes[reviewId];
|
|
116
|
+
if (!node) return undefined;
|
|
117
|
+
return (node as unknown as { result?: LoopVerdict }).result;
|
|
118
|
+
}
|
|
@@ -73,7 +73,7 @@ export class HarnessNotificationEvents {
|
|
|
73
73
|
return this.center.listChannels();
|
|
74
74
|
}
|
|
75
75
|
|
|
76
|
-
//
|
|
76
|
+
// --- Event Emitters ------------------------------------------------
|
|
77
77
|
|
|
78
78
|
/**
|
|
79
79
|
* Emit JobStarted event
|
|
@@ -173,7 +173,7 @@ export class HarnessNotificationEvents {
|
|
|
173
173
|
await this.emit("Error", { error });
|
|
174
174
|
}
|
|
175
175
|
|
|
176
|
-
//
|
|
176
|
+
// --- State Machine Event Listeners ---------------------------------
|
|
177
177
|
|
|
178
178
|
/**
|
|
179
179
|
* Wire up with JobStateMachine to emit events on transitions
|
|
@@ -207,7 +207,7 @@ export class HarnessNotificationEvents {
|
|
|
207
207
|
}
|
|
208
208
|
}
|
|
209
209
|
|
|
210
|
-
//
|
|
210
|
+
// --- Private Methods -----------------------------------------------
|
|
211
211
|
|
|
212
212
|
private async emit(
|
|
213
213
|
event: NotificationEvent,
|
|
@@ -277,7 +277,7 @@ export class OutputLimitHandler {
|
|
|
277
277
|
return this.attempts >= this.maxAttempts;
|
|
278
278
|
}
|
|
279
279
|
|
|
280
|
-
//
|
|
280
|
+
// --- Private Methods ------------------------------------------------
|
|
281
281
|
|
|
282
282
|
private ensureDir(): void {
|
|
283
283
|
if (!existsSync(this.rootDir)) {
|
|
@@ -70,7 +70,7 @@ export class PartialRecovery {
|
|
|
70
70
|
this.loadExistingPartials();
|
|
71
71
|
}
|
|
72
72
|
|
|
73
|
-
//
|
|
73
|
+
// --- Public API -----------------------------------------------------------
|
|
74
74
|
|
|
75
75
|
/**
|
|
76
76
|
* Save a partial response
|
|
@@ -285,7 +285,7 @@ export class PartialRecovery {
|
|
|
285
285
|
}
|
|
286
286
|
}
|
|
287
287
|
|
|
288
|
-
//
|
|
288
|
+
// --- Private Methods ------------------------------------------------
|
|
289
289
|
|
|
290
290
|
private ensureDir(): void {
|
|
291
291
|
if (!existsSync(this.rootDir)) {
|
|
@@ -517,7 +517,7 @@ export class PartialRecovery {
|
|
|
517
517
|
}
|
|
518
518
|
}
|
|
519
519
|
|
|
520
|
-
//
|
|
520
|
+
// --- Factory ----------------------------------------------------------------
|
|
521
521
|
|
|
522
522
|
/**
|
|
523
523
|
* Create a PartialRecovery manager for a task
|
|
@@ -11,7 +11,7 @@ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
|
11
11
|
import { join } from "node:path";
|
|
12
12
|
import type { CompactableMessage } from "../packages/types/src/runtime-types.js";
|
|
13
13
|
|
|
14
|
-
//
|
|
14
|
+
// --- Types ------------------------------------------------------------------
|
|
15
15
|
|
|
16
16
|
export interface SessionMemory {
|
|
17
17
|
jobId: string;
|
|
@@ -41,7 +41,7 @@ export interface TestResult {
|
|
|
41
41
|
timestamp: string;
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
-
//
|
|
44
|
+
// --- Session Memory Manager -------------------------------------------------
|
|
45
45
|
|
|
46
46
|
export class SessionMemoryManager {
|
|
47
47
|
private memory: SessionMemory;
|
|
@@ -66,7 +66,7 @@ export class SessionMemoryManager {
|
|
|
66
66
|
};
|
|
67
67
|
}
|
|
68
68
|
|
|
69
|
-
//
|
|
69
|
+
// --- Public API -----------------------------------------------------------
|
|
70
70
|
|
|
71
71
|
/**
|
|
72
72
|
* Extract key facts from recent messages
|
|
@@ -362,7 +362,7 @@ export class SessionMemoryManager {
|
|
|
362
362
|
this.save();
|
|
363
363
|
}
|
|
364
364
|
|
|
365
|
-
//
|
|
365
|
+
// --- Private Methods --------------------------------------------------
|
|
366
366
|
|
|
367
367
|
private load(): SessionMemory | null {
|
|
368
368
|
if (!existsSync(this.memoryPath)) {
|
|
@@ -388,7 +388,7 @@ export class SessionMemoryManager {
|
|
|
388
388
|
}
|
|
389
389
|
}
|
|
390
390
|
|
|
391
|
-
//
|
|
391
|
+
// --- Factory ----------------------------------------------------------------
|
|
392
392
|
|
|
393
393
|
/**
|
|
394
394
|
* Create a SessionMemoryManager for a job
|