create-walle 0.9.11 → 0.9.13
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/README.md +3 -3
- package/package.json +2 -2
- package/template/bin/dev.sh +7 -1
- package/template/bin/setup.js +53 -9
- package/template/bin/sync-images.js +53 -0
- package/template/builder-journal.md +17 -0
- package/template/claude-task-manager/api-prompts.js +98 -13
- package/template/claude-task-manager/api-reviews.js +82 -5
- package/template/claude-task-manager/db.js +32 -5
- package/template/claude-task-manager/docs/session-capture-foundation-design.md +1273 -0
- package/template/claude-task-manager/lib/claude-desktop-sessions.js +696 -0
- package/template/claude-task-manager/lib/coding-agent-models.js +49 -1
- package/template/claude-task-manager/lib/session-capture.js +421 -0
- package/template/claude-task-manager/lib/session-history.js +135 -15
- package/template/claude-task-manager/lib/session-jobs.js +10 -5
- package/template/claude-task-manager/lib/session-stream.js +87 -19
- package/template/claude-task-manager/lib/setup-provider-config.js +115 -0
- package/template/claude-task-manager/lib/walle-ctm-history.js +72 -0
- package/template/claude-task-manager/lib/walle-session-context.js +61 -0
- package/template/claude-task-manager/lib/walle-transcript.js +176 -0
- package/template/claude-task-manager/public/css/setup.css +35 -8
- package/template/claude-task-manager/public/css/walle-session.css +56 -0
- package/template/claude-task-manager/public/css/walle.css +120 -0
- package/template/claude-task-manager/public/index.html +814 -181
- package/template/claude-task-manager/public/js/message-renderer.js +148 -19
- package/template/claude-task-manager/public/js/reviews.js +120 -62
- package/template/claude-task-manager/public/js/setup.js +75 -31
- package/template/claude-task-manager/public/js/stream-view.js +115 -55
- package/template/claude-task-manager/public/js/walle-session.js +84 -2
- package/template/claude-task-manager/public/js/walle.js +308 -54
- package/template/claude-task-manager/server.js +1092 -146
- package/template/claude-task-manager/session-integrity.js +181 -54
- package/template/claude-task-manager/session-utils.js +123 -41
- package/template/claude-task-manager/workers/state-detectors/codex.js +5 -2
- package/template/package.json +1 -1
- package/template/wall-e/adapters/ctm.js +39 -18
- package/template/wall-e/agent-runners/contract.js +17 -0
- package/template/wall-e/agent-runners/index.js +22 -0
- package/template/wall-e/agent-runtime/harness.js +212 -0
- package/template/wall-e/agent-runtime/index.js +8 -0
- package/template/wall-e/agent-runtime/registry.js +67 -0
- package/template/wall-e/agent-runtime/session-store.js +179 -0
- package/template/wall-e/agent-runtime/spawn.js +208 -0
- package/template/wall-e/api-walle.js +174 -7
- package/template/wall-e/brain.js +266 -28
- package/template/wall-e/channels/policy.js +88 -0
- package/template/wall-e/channels/registry.js +15 -1
- package/template/wall-e/channels/reply-dispatcher.js +70 -0
- package/template/wall-e/channels/session-bindings.js +51 -0
- package/template/wall-e/chat/code-review-context.js +29 -0
- package/template/wall-e/chat.js +188 -42
- package/template/wall-e/coding/acp-adapter.js +188 -0
- package/template/wall-e/coding/agent-catalog.js +129 -0
- package/template/wall-e/coding/compaction-service.js +247 -0
- package/template/wall-e/coding/execution-trace.js +3 -0
- package/template/wall-e/coding/instruction-service.js +224 -0
- package/template/wall-e/coding/model-message.js +67 -0
- package/template/wall-e/coding/permission-rules-store.js +111 -0
- package/template/wall-e/coding/permission-service.js +266 -0
- package/template/wall-e/coding/prompt-bundle.js +67 -0
- package/template/wall-e/coding/prompt-runtime.js +243 -0
- package/template/wall-e/coding/provider-transform.js +188 -0
- package/template/wall-e/coding/runtime-mode.js +132 -0
- package/template/wall-e/coding/snapshot-service.js +155 -0
- package/template/wall-e/coding/stream-processor.js +268 -0
- package/template/wall-e/coding/task-tool.js +255 -0
- package/template/wall-e/coding/tool-registry.js +361 -0
- package/template/wall-e/coding/transcript-writer.js +143 -0
- package/template/wall-e/coding/workspace-replay.js +324 -0
- package/template/wall-e/coding-context.js +4 -22
- package/template/wall-e/coding-orchestrator.js +307 -18
- package/template/wall-e/coding-prompts.js +44 -3
- package/template/wall-e/context/context-builder.js +43 -1
- package/template/wall-e/context/topic-matcher.js +1 -1
- package/template/wall-e/eval/agent-runner.js +59 -13
- package/template/wall-e/eval/benchmarks/memory-retrieval.json +155 -57
- package/template/wall-e/eval/benchmarks.js +100 -16
- package/template/wall-e/eval/eval-orchestrator.js +218 -8
- package/template/wall-e/eval/harvester.js +62 -5
- package/template/wall-e/eval/head-to-head.js +23 -2
- package/template/wall-e/eval/humaneval-adapter.js +30 -5
- package/template/wall-e/eval/livecodebench-adapter.js +29 -5
- package/template/wall-e/eval/manifest.js +186 -0
- package/template/wall-e/eval/run-agent-benchmarks.js +66 -2
- package/template/wall-e/eval/session-retrieval-benchmark.js +150 -0
- package/template/wall-e/eval/session-transcripts.js +57 -4
- package/template/wall-e/eval/swebench-adapter.js +109 -3
- package/template/wall-e/evaluation/agent-router.js +53 -1
- package/template/wall-e/evaluation/coding-quorum.js +48 -1
- package/template/wall-e/evaluation/router.js +4 -2
- package/template/wall-e/evaluation/tier-selector.js +11 -1
- package/template/wall-e/extraction/contradiction.js +2 -2
- package/template/wall-e/extraction/indexer.js +2 -1
- package/template/wall-e/extraction/knowledge-extractor.js +2 -2
- package/template/wall-e/hooks/cli.js +92 -0
- package/template/wall-e/hooks/discovery.js +119 -0
- package/template/wall-e/hooks/index.js +7 -0
- package/template/wall-e/hooks/manifest.js +55 -0
- package/template/wall-e/hooks/runtime.js +84 -0
- package/template/wall-e/hooks/session-memory.js +225 -0
- package/template/wall-e/http/auth.js +6 -2
- package/template/wall-e/http/chat-api.js +54 -8
- package/template/wall-e/integrations/claude-plugin/hooks/hooks.json +27 -0
- package/template/wall-e/integrations/claude-plugin/hooks/walle-precompact-hook.sh +5 -0
- package/template/wall-e/integrations/claude-plugin/hooks/walle-stop-hook.sh +5 -0
- package/template/wall-e/integrations/codex-plugin/hooks/walle-hook.sh +7 -0
- package/template/wall-e/integrations/codex-plugin/hooks.json +37 -0
- package/template/wall-e/listening/calendar.js +3 -1
- package/template/wall-e/llm/client.js +64 -10
- package/template/wall-e/llm/google.js +39 -5
- package/template/wall-e/llm/ollama.js +1 -1
- package/template/wall-e/llm/ollama.plugin.json +1 -1
- package/template/wall-e/llm/provider-availability.js +10 -0
- package/template/wall-e/llm/provider-error.js +269 -0
- package/template/wall-e/llm/tool-adapter.js +48 -12
- package/template/wall-e/loops/boot.js +2 -1
- package/template/wall-e/loops/initiative.js +2 -2
- package/template/wall-e/loops/tasks.js +8 -47
- package/template/wall-e/loops/workspace-prompts.js +20 -0
- package/template/wall-e/mcp-server.js +442 -1
- package/template/wall-e/memory/session-ingest-service.js +159 -0
- package/template/wall-e/memory/source-indexer.js +289 -0
- package/template/wall-e/plugins/discovery.js +83 -0
- package/template/wall-e/plugins/manifest-loader.js +50 -10
- package/template/wall-e/plugins/manifest-schema.js +69 -0
- package/template/wall-e/plugins/model-catalog.js +55 -0
- package/template/wall-e/prompts/coding/base.txt +2 -0
- package/template/wall-e/prompts/coding/deepseek.txt +1 -0
- package/template/wall-e/prompts/coding/memory-protocol.md +9 -0
- package/template/wall-e/prompts/coding/plan.txt +1 -0
- package/template/wall-e/runtime/execution-trace.js +220 -0
- package/template/wall-e/security/audit.js +266 -0
- package/template/wall-e/security/ssrf.js +236 -0
- package/template/wall-e/session-files.js +303 -0
- package/template/wall-e/skills/_bundled/slack-backfill/SKILL.md +3 -0
- package/template/wall-e/skills/_bundled/slack-sync/SKILL.md +3 -0
- package/template/wall-e/skills/internal-skill-registry.js +2 -2
- package/template/wall-e/skills/script-skill-runner.js +143 -0
- package/template/wall-e/skills/skill-executor.js +5 -6
- package/template/wall-e/skills/skill-fallback.js +3 -1
- package/template/wall-e/skills/skill-harness-registry.js +7 -8
- package/template/wall-e/skills/skill-planner.js +52 -4
- package/template/wall-e/skills/slack-ingest.js +11 -3
- package/template/wall-e/sources/base.js +90 -0
- package/template/wall-e/sources/builtin.js +33 -0
- package/template/wall-e/sources/claude-code-jsonl.js +78 -0
- package/template/wall-e/sources/codex-jsonl.js +125 -0
- package/template/wall-e/sources/coding-session-utils.js +117 -0
- package/template/wall-e/sources/contract-suite.js +59 -0
- package/template/wall-e/sources/gemini-jsonl.js +85 -0
- package/template/wall-e/sources/index.js +9 -0
- package/template/wall-e/sources/jsonl-utils.js +181 -0
- package/template/wall-e/sources/record-types.js +252 -0
- package/template/wall-e/sources/registry.js +92 -0
- package/template/wall-e/sources/transforms.js +100 -0
- package/template/wall-e/sources/walle-jsonl.js +108 -0
- package/template/wall-e/tools/coding-middleware.js +31 -1
- package/template/wall-e/tools/file-tracker.js +25 -1
- package/template/wall-e/tools/local-tools.js +75 -47
- package/template/wall-e/tools/session-sharing.js +68 -1
- package/template/wall-e/tools/shell-analyzer.js +1 -1
- package/template/wall-e/tools/shell-policy.js +47 -0
- package/template/wall-e/tools/snapshot.js +42 -0
- package/template/wall-e/training/harvester.js +62 -5
- package/template/wall-e/utils/repair.js +253 -1
- package/template/website/index.html +3 -3
- package/template/wall-e/skills/_bundled/slack-mentions/.watched-threads.json +0 -18
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const { createAgentRunId, normalizeAgentMode, normalizeAgentRunResult } = require('../agent-runners/contract');
|
|
4
|
+
const { createDefaultHarnessRegistry, selectAgentHarness } = require('./harness');
|
|
5
|
+
const { createDefaultRuntimeRegistry } = require('./registry');
|
|
6
|
+
const { defaultSessionStore } = require('./session-store');
|
|
7
|
+
const {
|
|
8
|
+
attachTraceToResult,
|
|
9
|
+
createExecutionTrace,
|
|
10
|
+
finalizeTrace,
|
|
11
|
+
recordAttemptFinish,
|
|
12
|
+
recordAttemptStart,
|
|
13
|
+
recordSelection,
|
|
14
|
+
} = require('../runtime/execution-trace');
|
|
15
|
+
|
|
16
|
+
function normalizeAgentTaskRequest(input = {}) {
|
|
17
|
+
const task = input.task || input.prompt || '';
|
|
18
|
+
return {
|
|
19
|
+
id: input.id || input.runId || createAgentRunId(),
|
|
20
|
+
parentRunId: input.parentRunId || input.parentId || null,
|
|
21
|
+
harnessId: input.harnessId || null,
|
|
22
|
+
runtime: input.runtime || input.runtimePreference || 'cli-agent',
|
|
23
|
+
runnerId: input.runnerId || input.runner || input.agent || 'claude-code',
|
|
24
|
+
providerType: input.providerType || input.provider || 'unknown',
|
|
25
|
+
model: input.model || null,
|
|
26
|
+
mode: normalizeAgentMode(input.mode),
|
|
27
|
+
task,
|
|
28
|
+
prompt: task,
|
|
29
|
+
cwd: input.cwd || process.cwd(),
|
|
30
|
+
writeScope: Array.isArray(input.writeScope) ? input.writeScope : (input.writeScope ? [input.writeScope] : ['.']),
|
|
31
|
+
sandbox: input.sandbox || null,
|
|
32
|
+
timeoutMs: input.timeoutMs || 300000,
|
|
33
|
+
sessionId: input.sessionId || null,
|
|
34
|
+
persistent: Boolean(input.persistent),
|
|
35
|
+
cleanupPolicy: input.cleanupPolicy || (input.persistent ? 'manual' : 'delete-on-complete'),
|
|
36
|
+
threadId: input.threadId || null,
|
|
37
|
+
contextPolicy: input.contextPolicy || null,
|
|
38
|
+
attachments: Array.isArray(input.attachments) ? input.attachments : [],
|
|
39
|
+
reviewPolicy: input.reviewPolicy || null,
|
|
40
|
+
metadata: { ...(input.metadata || {}) },
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
async function spawnAgentSession(input = {}, deps = {}) {
|
|
45
|
+
const request = normalizeAgentTaskRequest(input);
|
|
46
|
+
const trace = deps.trace || createExecutionTrace({
|
|
47
|
+
runId: request.id,
|
|
48
|
+
parentRunId: request.parentRunId,
|
|
49
|
+
mode: request.mode,
|
|
50
|
+
provider: request.providerType,
|
|
51
|
+
model: request.model,
|
|
52
|
+
runnerId: request.runnerId,
|
|
53
|
+
harnessId: request.harnessId,
|
|
54
|
+
sessionId: request.sessionId || '',
|
|
55
|
+
cwd: request.cwd,
|
|
56
|
+
sandbox: request.sandbox,
|
|
57
|
+
taskType: 'agent-runtime',
|
|
58
|
+
});
|
|
59
|
+
if (deps.harnessRegistry || request.harnessId) {
|
|
60
|
+
const harnessRegistry = deps.harnessRegistry || createDefaultHarnessRegistry();
|
|
61
|
+
const selection = selectAgentHarness(request, [], {
|
|
62
|
+
registry: harnessRegistry,
|
|
63
|
+
providerAvailability: deps.providerAvailability,
|
|
64
|
+
});
|
|
65
|
+
if (!selection.selected) {
|
|
66
|
+
const error = `No supported agent harness found for ${request.harnessId || request.runnerId}`;
|
|
67
|
+
recordSelection(trace, selection);
|
|
68
|
+
finalizeTrace(trace, { status: 'failed', error });
|
|
69
|
+
return normalizeAgentRunResult({
|
|
70
|
+
runId: request.id,
|
|
71
|
+
parentRunId: request.parentRunId,
|
|
72
|
+
runnerId: request.runnerId,
|
|
73
|
+
providerType: request.providerType,
|
|
74
|
+
mode: request.mode,
|
|
75
|
+
sessionId: request.sessionId,
|
|
76
|
+
success: false,
|
|
77
|
+
stderr: error,
|
|
78
|
+
error,
|
|
79
|
+
trace,
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
recordSelection(trace, selection);
|
|
83
|
+
request.harnessId = selection.selected.id;
|
|
84
|
+
request.runnerId = selection.selected.runnerId;
|
|
85
|
+
request.providerType = selection.selected.providerType;
|
|
86
|
+
request.metadata = { ...request.metadata, harnessSelection: selection.reason };
|
|
87
|
+
}
|
|
88
|
+
const sessionStore = deps.sessionStore || defaultSessionStore;
|
|
89
|
+
const registry = deps.registry || createDefaultRuntimeRegistry({ runTask: deps.runTask });
|
|
90
|
+
const runtime = registry.getRuntime(request.runtime);
|
|
91
|
+
if (!runtime) {
|
|
92
|
+
const error = `Unknown agent runtime: ${request.runtime}`;
|
|
93
|
+
return normalizeAgentRunResult({
|
|
94
|
+
runId: request.id,
|
|
95
|
+
parentRunId: request.parentRunId,
|
|
96
|
+
runnerId: request.runnerId,
|
|
97
|
+
providerType: request.providerType,
|
|
98
|
+
mode: request.mode,
|
|
99
|
+
sessionId: request.sessionId,
|
|
100
|
+
success: false,
|
|
101
|
+
stderr: error,
|
|
102
|
+
error,
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
const existingSession = request.sessionId ? sessionStore.getSession(request.sessionId) : null;
|
|
107
|
+
const session = existingSession || sessionStore.createSession({
|
|
108
|
+
id: request.sessionId,
|
|
109
|
+
parentRunId: request.parentRunId,
|
|
110
|
+
runtime: request.runtime,
|
|
111
|
+
runnerId: request.runnerId,
|
|
112
|
+
harnessId: request.harnessId,
|
|
113
|
+
providerType: request.providerType,
|
|
114
|
+
model: request.model,
|
|
115
|
+
mode: request.mode,
|
|
116
|
+
cwd: request.cwd,
|
|
117
|
+
sandbox: request.sandbox,
|
|
118
|
+
task: request.task,
|
|
119
|
+
persistent: request.persistent,
|
|
120
|
+
cleanupPolicy: request.cleanupPolicy,
|
|
121
|
+
threadId: request.threadId,
|
|
122
|
+
metadata: request.metadata,
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
sessionStore.markRunning(session.id, {
|
|
126
|
+
parentRunId: request.parentRunId,
|
|
127
|
+
runtime: request.runtime,
|
|
128
|
+
runnerId: request.runnerId,
|
|
129
|
+
providerType: request.providerType,
|
|
130
|
+
model: request.model,
|
|
131
|
+
mode: request.mode,
|
|
132
|
+
cwd: request.cwd,
|
|
133
|
+
sandbox: request.sandbox,
|
|
134
|
+
task: request.task,
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
trace.sessionId = session.id;
|
|
138
|
+
trace.request.runnerId = request.runnerId;
|
|
139
|
+
trace.request.harnessId = request.harnessId;
|
|
140
|
+
trace.request.modelPreference = request.model || '';
|
|
141
|
+
const startedAt = Date.now();
|
|
142
|
+
const attempt = recordAttemptStart(trace, {
|
|
143
|
+
providerType: request.providerType,
|
|
144
|
+
model: request.model,
|
|
145
|
+
runnerId: request.runnerId,
|
|
146
|
+
harnessId: request.harnessId,
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
try {
|
|
150
|
+
const raw = await runtime.run({
|
|
151
|
+
...request,
|
|
152
|
+
sessionId: session.id,
|
|
153
|
+
resumeHandle: session.resumeHandle,
|
|
154
|
+
});
|
|
155
|
+
const completedSession = sessionStore.markCompleted(session.id, raw || {}) || sessionStore.getSession(session.id);
|
|
156
|
+
recordAttemptFinish(trace, attempt.id, {
|
|
157
|
+
success: raw?.success !== false,
|
|
158
|
+
status: raw?.success === false ? 'failed' : 'completed',
|
|
159
|
+
error: raw?.error || raw?.stderr || null,
|
|
160
|
+
usage: raw?.usage || null,
|
|
161
|
+
});
|
|
162
|
+
trace.latencyMs = Date.now() - startedAt;
|
|
163
|
+
finalizeTrace(trace, { status: raw?.success === false ? 'failed' : 'completed' });
|
|
164
|
+
|
|
165
|
+
const normalized = normalizeAgentRunResult(raw || {}, {
|
|
166
|
+
runId: request.id,
|
|
167
|
+
parentRunId: request.parentRunId,
|
|
168
|
+
runnerId: request.runnerId,
|
|
169
|
+
harnessId: request.harnessId,
|
|
170
|
+
providerType: request.providerType,
|
|
171
|
+
mode: request.mode,
|
|
172
|
+
sessionId: session.id,
|
|
173
|
+
persistent: completedSession?.persistent,
|
|
174
|
+
cleanupPolicy: completedSession?.cleanupPolicy,
|
|
175
|
+
threadId: completedSession?.threadId,
|
|
176
|
+
sessionStatus: completedSession?.status,
|
|
177
|
+
trace,
|
|
178
|
+
});
|
|
179
|
+
return attachTraceToResult(normalized, trace);
|
|
180
|
+
} catch (err) {
|
|
181
|
+
const failedSession = sessionStore.markFailed(session.id, err) || sessionStore.getSession(session.id);
|
|
182
|
+
recordAttemptFinish(trace, attempt.id, { status: 'failed', error: err.message });
|
|
183
|
+
trace.latencyMs = Date.now() - startedAt;
|
|
184
|
+
finalizeTrace(trace, { status: 'failed', error: err.message });
|
|
185
|
+
return normalizeAgentRunResult({
|
|
186
|
+
runId: request.id,
|
|
187
|
+
parentRunId: request.parentRunId,
|
|
188
|
+
runnerId: request.runnerId,
|
|
189
|
+
harnessId: request.harnessId,
|
|
190
|
+
providerType: request.providerType,
|
|
191
|
+
mode: request.mode,
|
|
192
|
+
sessionId: session.id,
|
|
193
|
+
persistent: failedSession?.persistent,
|
|
194
|
+
cleanupPolicy: failedSession?.cleanupPolicy,
|
|
195
|
+
threadId: failedSession?.threadId,
|
|
196
|
+
sessionStatus: failedSession?.status,
|
|
197
|
+
success: false,
|
|
198
|
+
stderr: err.message,
|
|
199
|
+
error: err.message,
|
|
200
|
+
trace,
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
module.exports = {
|
|
206
|
+
normalizeAgentTaskRequest,
|
|
207
|
+
spawnAgentSession,
|
|
208
|
+
};
|
|
@@ -124,13 +124,25 @@ function _invalidateSkillSnapshot() {
|
|
|
124
124
|
// Inspired by OpenCode Question service (packages/opencode/src/question/index.ts)
|
|
125
125
|
const { QuestionManager } = require('./tools/question-manager');
|
|
126
126
|
const _questionRegistry = new QuestionManager(null);
|
|
127
|
+
const { PermissionService } = require('./coding/permission-service');
|
|
128
|
+
const _permissionRegistry = new PermissionService();
|
|
127
129
|
|
|
128
130
|
let _tasksBootstrapped = false;
|
|
131
|
+
let _runtimeDefaultsSynced = false;
|
|
129
132
|
function ensureBrainInit() {
|
|
130
133
|
if (!brain) return false;
|
|
131
134
|
try { brain.getDb(); } catch {
|
|
132
135
|
try { brain.initDb(); } catch { return false; }
|
|
133
136
|
}
|
|
137
|
+
if (!_runtimeDefaultsSynced) {
|
|
138
|
+
try {
|
|
139
|
+
const provider = brain.getKv('walle_provider');
|
|
140
|
+
const model = brain.getKv('walle_model');
|
|
141
|
+
if (provider) process.env.WALLE_PROVIDER = provider;
|
|
142
|
+
if (model) process.env.WALLE_MODEL = model;
|
|
143
|
+
_runtimeDefaultsSynced = true;
|
|
144
|
+
} catch {}
|
|
145
|
+
}
|
|
134
146
|
// Bootstrap core tasks if DB is empty (first run)
|
|
135
147
|
if (!_tasksBootstrapped) {
|
|
136
148
|
_tasksBootstrapped = true;
|
|
@@ -830,6 +842,18 @@ function handleWalleApi(req, res, url) {
|
|
|
830
842
|
}
|
|
831
843
|
if (!hasApiKey && walleProvider === 'openai' && process.env.OPENAI_API_KEY) hasApiKey = true;
|
|
832
844
|
if (!hasApiKey && walleProvider === 'google' && (process.env.GOOGLE_API_KEY || process.env.GEMINI_API_KEY)) hasApiKey = true;
|
|
845
|
+
if (!hasApiKey && walleProvider === 'anthropic') {
|
|
846
|
+
let authMethod = process.env.WALLE_AUTH_METHOD || '';
|
|
847
|
+
try { authMethod = brain?.getProviderAuthMethod?.('anthropic') || authMethod; } catch {}
|
|
848
|
+
if (authMethod === 'oauth_proxy' || authMethod === 'claude_cli' || authMethod === 'devbox') hasApiKey = true;
|
|
849
|
+
if (process.env.ANTHROPIC_AUTH_TOKEN || process.env.ANTHROPIC_BASE_URL) hasApiKey = true;
|
|
850
|
+
}
|
|
851
|
+
if (!hasApiKey && walleProvider === 'openai') {
|
|
852
|
+
let authMethod = process.env.WALLE_AUTH_METHOD || '';
|
|
853
|
+
try { authMethod = brain?.getProviderAuthMethod?.('openai') || authMethod; } catch {}
|
|
854
|
+
if (authMethod === 'codex_cli') hasApiKey = true;
|
|
855
|
+
}
|
|
856
|
+
if (!hasApiKey && walleProvider === 'deepseek' && process.env.DEEPSEEK_API_KEY) hasApiKey = true;
|
|
833
857
|
if (!hasApiKey && (walleProvider === 'ollama' || walleProvider === 'mlx')) hasApiKey = true;
|
|
834
858
|
|
|
835
859
|
let serviceAlerts = [];
|
|
@@ -939,8 +963,14 @@ function handleWalleApi(req, res, url) {
|
|
|
939
963
|
const ownerName = body.ownerName || '';
|
|
940
964
|
const providerConfig = body.providerConfig || null;
|
|
941
965
|
|
|
942
|
-
if (provider)
|
|
943
|
-
|
|
966
|
+
if (provider) {
|
|
967
|
+
brain.setKv('walle_provider', provider);
|
|
968
|
+
process.env.WALLE_PROVIDER = provider;
|
|
969
|
+
}
|
|
970
|
+
if (model) {
|
|
971
|
+
brain.setKv('walle_model', model);
|
|
972
|
+
process.env.WALLE_MODEL = model;
|
|
973
|
+
}
|
|
944
974
|
if (ownerName) brain.setKv('walle_owner_name', ownerName);
|
|
945
975
|
|
|
946
976
|
if (provider && providerConfig) {
|
|
@@ -2616,6 +2646,63 @@ function handleWalleApi(req, res, url) {
|
|
|
2616
2646
|
return true;
|
|
2617
2647
|
}
|
|
2618
2648
|
|
|
2649
|
+
// GET /api/wall-e/coding/sessions/:id/transcript?offset=&sequence=&limit=
|
|
2650
|
+
// Replay durable Wall-E JSONL records for reconnecting clients without fs.watch.
|
|
2651
|
+
const transcriptRangeMatch = p.match(/^\/api\/wall-e\/coding\/sessions\/([^/]+)\/transcript$/);
|
|
2652
|
+
if (transcriptRangeMatch && m === 'GET') {
|
|
2653
|
+
try {
|
|
2654
|
+
const { WorkspaceReplay } = require('./coding/workspace-replay');
|
|
2655
|
+
const replay = new WorkspaceReplay();
|
|
2656
|
+
const range = replay.replayRange(decodeURIComponent(transcriptRangeMatch[1]), {
|
|
2657
|
+
offset: params.get('offset') || 0,
|
|
2658
|
+
sequence: params.get('sequence') || 0,
|
|
2659
|
+
limitBytes: params.get('limit') || params.get('limitBytes') || undefined,
|
|
2660
|
+
});
|
|
2661
|
+
return jsonResponse(res, { ok: true, ...range }), true;
|
|
2662
|
+
} catch (e) {
|
|
2663
|
+
return jsonResponse(res, { error: e.message }, 500), true;
|
|
2664
|
+
}
|
|
2665
|
+
}
|
|
2666
|
+
|
|
2667
|
+
// POST /api/wall-e/coding/sessions/:id/transcript/append
|
|
2668
|
+
// Direct append signal for CTM/ACP clients that already have structured parts.
|
|
2669
|
+
const transcriptAppendMatch = p.match(/^\/api\/wall-e\/coding\/sessions\/([^/]+)\/transcript\/append$/);
|
|
2670
|
+
if (transcriptAppendMatch && m === 'POST') {
|
|
2671
|
+
readBody(req).then(body => {
|
|
2672
|
+
try {
|
|
2673
|
+
const { WorkspaceReplay } = require('./coding/workspace-replay');
|
|
2674
|
+
const replay = new WorkspaceReplay();
|
|
2675
|
+
const sessionId = decodeURIComponent(transcriptAppendMatch[1]);
|
|
2676
|
+
const result = body.record
|
|
2677
|
+
? replay.appendRecord(sessionId, body.record)
|
|
2678
|
+
: replay.appendPart(sessionId, body.partType || 'event', body.data || {}, {
|
|
2679
|
+
cwd: body.cwd || '',
|
|
2680
|
+
chatSessionId: body.chatSessionId || '',
|
|
2681
|
+
parentUuid: body.parentUuid || null,
|
|
2682
|
+
});
|
|
2683
|
+
jsonResponse(res, { ok: true, ...result });
|
|
2684
|
+
} catch (e) {
|
|
2685
|
+
jsonResponse(res, { error: e.message }, 500);
|
|
2686
|
+
}
|
|
2687
|
+
}).catch(e => jsonResponse(res, { error: e.message }, 500));
|
|
2688
|
+
return true;
|
|
2689
|
+
}
|
|
2690
|
+
|
|
2691
|
+
// GET /api/wall-e/coding/sessions/:id/replay — rebuild message/part state from JSONL.
|
|
2692
|
+
const replayStateMatch = p.match(/^\/api\/wall-e\/coding\/sessions\/([^/]+)\/replay$/);
|
|
2693
|
+
if (replayStateMatch && m === 'GET') {
|
|
2694
|
+
try {
|
|
2695
|
+
const { WorkspaceReplay } = require('./coding/workspace-replay');
|
|
2696
|
+
const replay = new WorkspaceReplay();
|
|
2697
|
+
const state = replay.rebuildState(decodeURIComponent(replayStateMatch[1]), {
|
|
2698
|
+
cwd: params.get('cwd') || '',
|
|
2699
|
+
});
|
|
2700
|
+
return jsonResponse(res, { ok: true, ...state }), true;
|
|
2701
|
+
} catch (e) {
|
|
2702
|
+
return jsonResponse(res, { error: e.message }, 500), true;
|
|
2703
|
+
}
|
|
2704
|
+
}
|
|
2705
|
+
|
|
2619
2706
|
// POST /api/wall-e/coding/question/:sessionId/answer — answer an interactive question
|
|
2620
2707
|
// Inspired by OpenCode Question.reply() (packages/opencode/src/question/index.ts)
|
|
2621
2708
|
if (m === 'POST' && p.match(/^\/api\/wall-e\/coding\/question\/[^/]+\/answer$/)) {
|
|
@@ -3043,21 +3130,42 @@ function handleWalleApi(req, res, url) {
|
|
|
3043
3130
|
if (p === '/api/wall-e/eval/dashboard' && m === 'GET') {
|
|
3044
3131
|
try {
|
|
3045
3132
|
const leaderboard = brain.getBenchmarkLeaderboardWithDimensions({ days: 30 });
|
|
3046
|
-
const shadowResults = brain.getShadowResults({ limit: 1, offset: 0 });
|
|
3047
3133
|
const shadowTotal = (typeof brain.getShadowResults === 'function')
|
|
3048
3134
|
? brain.getShadowResults({}).length : 0;
|
|
3135
|
+
const providerCount = new Set(leaderboard.map(r => r.provider).filter(Boolean)).size;
|
|
3136
|
+
const benchmarkEvals = leaderboard.reduce((s, r) => s + (Number(r.total_evals) || 0), 0);
|
|
3137
|
+
const trustedBenchmarkEvals = leaderboard.reduce((s, r) => s + (Number(r.trusted_evals) || 0), 0);
|
|
3138
|
+
const trustedBenchmarkModels = leaderboard.filter(r => r.trust_status === 'trusted').length;
|
|
3139
|
+
const provisionalBenchmarkModels = leaderboard.filter(r => r.trust_status === 'provisional').length;
|
|
3140
|
+
const legacyBenchmarkModels = leaderboard.filter(r => r.trust_status === 'legacy').length;
|
|
3049
3141
|
return jsonResponse(res, {
|
|
3050
3142
|
data: {
|
|
3051
|
-
providers:
|
|
3052
|
-
|
|
3143
|
+
providers: providerCount,
|
|
3144
|
+
modelGroups: leaderboard.length,
|
|
3145
|
+
totalEvals: benchmarkEvals + shadowTotal,
|
|
3053
3146
|
shadowEvals: shadowTotal,
|
|
3054
|
-
benchmarkEvals
|
|
3147
|
+
benchmarkEvals,
|
|
3148
|
+
trustedBenchmarkEvals,
|
|
3149
|
+
trustedBenchmarkModels,
|
|
3150
|
+
provisionalBenchmarkModels,
|
|
3151
|
+
legacyBenchmarkModels,
|
|
3055
3152
|
leaderboard,
|
|
3056
3153
|
}
|
|
3057
3154
|
}), true;
|
|
3058
3155
|
} catch (e) {
|
|
3059
3156
|
return jsonResponse(res, {
|
|
3060
|
-
data: {
|
|
3157
|
+
data: {
|
|
3158
|
+
providers: 0,
|
|
3159
|
+
modelGroups: 0,
|
|
3160
|
+
totalEvals: 0,
|
|
3161
|
+
shadowEvals: 0,
|
|
3162
|
+
benchmarkEvals: 0,
|
|
3163
|
+
trustedBenchmarkEvals: 0,
|
|
3164
|
+
trustedBenchmarkModels: 0,
|
|
3165
|
+
provisionalBenchmarkModels: 0,
|
|
3166
|
+
legacyBenchmarkModels: 0,
|
|
3167
|
+
leaderboard: [],
|
|
3168
|
+
},
|
|
3061
3169
|
error: e.message
|
|
3062
3170
|
}), true;
|
|
3063
3171
|
}
|
|
@@ -3399,6 +3507,7 @@ function handleWalleApi(req, res, url) {
|
|
|
3399
3507
|
if (p === '/api/wall-e/eval/benchmarks' && m === 'GET') {
|
|
3400
3508
|
try {
|
|
3401
3509
|
const { listBenchmarkSuites, loadBenchmarkSuite } = require('./eval/benchmarks');
|
|
3510
|
+
const { listAdapterSuites } = require('./eval/eval-orchestrator');
|
|
3402
3511
|
const suites = [];
|
|
3403
3512
|
const errors = [];
|
|
3404
3513
|
for (const name of listBenchmarkSuites()) {
|
|
@@ -3415,6 +3524,7 @@ function handleWalleApi(req, res, url) {
|
|
|
3415
3524
|
errors.push({ suite: name, error: e.message });
|
|
3416
3525
|
}
|
|
3417
3526
|
}
|
|
3527
|
+
suites.push(...listAdapterSuites());
|
|
3418
3528
|
return jsonResponse(res, errors.length ? { data: suites, errors } : { data: suites }), true;
|
|
3419
3529
|
} catch (e) {
|
|
3420
3530
|
return jsonResponse(res, { data: [], error: e.message }), true;
|
|
@@ -3426,6 +3536,30 @@ function handleWalleApi(req, res, url) {
|
|
|
3426
3536
|
readBody(req).then(async body => {
|
|
3427
3537
|
try {
|
|
3428
3538
|
const data = typeof body === 'string' ? JSON.parse(body) : body;
|
|
3539
|
+
const { isAdapterSuite, EvalOrchestrator } = require('./eval/eval-orchestrator');
|
|
3540
|
+
if (isAdapterSuite(data.suite)) {
|
|
3541
|
+
const { getAvailableProviders } = require('./eval/head-to-head');
|
|
3542
|
+
const models = Array.isArray(data.models) && data.models.length
|
|
3543
|
+
? data.models
|
|
3544
|
+
: Array.isArray(data.providers) && data.providers.length
|
|
3545
|
+
? data.providers.map(p => p.model).filter(Boolean)
|
|
3546
|
+
: getAvailableProviders(brain).map(p => p.model);
|
|
3547
|
+
const { runAgentLoop } = require('./coding-orchestrator');
|
|
3548
|
+
const orchestrator = new EvalOrchestrator({
|
|
3549
|
+
brain,
|
|
3550
|
+
timeoutMs: data.timeoutMs || 600000,
|
|
3551
|
+
concurrency: data.concurrency || 1,
|
|
3552
|
+
budgetDollars: data.budgetDollars || 10,
|
|
3553
|
+
});
|
|
3554
|
+
const result = await orchestrator.run({
|
|
3555
|
+
suite: data.suite,
|
|
3556
|
+
models,
|
|
3557
|
+
runAgentLoop,
|
|
3558
|
+
maxTasks: data.maxTasks,
|
|
3559
|
+
afterDate: data.afterDate,
|
|
3560
|
+
});
|
|
3561
|
+
return jsonResponse(res, { data: result });
|
|
3562
|
+
}
|
|
3429
3563
|
const { runBenchmark } = require('./eval/benchmarks');
|
|
3430
3564
|
const result = await runBenchmark(brain, {
|
|
3431
3565
|
suite: data.suite,
|
|
@@ -4179,6 +4313,38 @@ function handleWalleApi(req, res, url) {
|
|
|
4179
4313
|
return true;
|
|
4180
4314
|
}
|
|
4181
4315
|
|
|
4316
|
+
// ── Coding Permission Requests ──
|
|
4317
|
+
|
|
4318
|
+
// GET /api/wall-e/permissions?session_id=... — list pending approvals
|
|
4319
|
+
if (p === '/api/wall-e/permissions' && m === 'GET') {
|
|
4320
|
+
try {
|
|
4321
|
+
return jsonResponse(res, {
|
|
4322
|
+
data: _permissionRegistry.list({ sessionId: params.get('session_id') || '' }),
|
|
4323
|
+
}), true;
|
|
4324
|
+
} catch (e) {
|
|
4325
|
+
return jsonResponse(res, { error: e.message }, 500), true;
|
|
4326
|
+
}
|
|
4327
|
+
}
|
|
4328
|
+
|
|
4329
|
+
// POST /api/wall-e/permissions/:id/reply — reply once/always/reject
|
|
4330
|
+
const permissionReplyMatch = p.match(/^\/api\/wall-e\/permissions\/([^/]+)\/reply$/);
|
|
4331
|
+
if (permissionReplyMatch && m === 'POST') {
|
|
4332
|
+
readBody(req).then(body => {
|
|
4333
|
+
const reply = body.reply || body.decision;
|
|
4334
|
+
if (!['once', 'always', 'reject'].includes(reply)) {
|
|
4335
|
+
return jsonResponse(res, { error: 'reply must be once, always, or reject' }, 400);
|
|
4336
|
+
}
|
|
4337
|
+
const ok = _permissionRegistry.reply({
|
|
4338
|
+
requestId: decodeURIComponent(permissionReplyMatch[1]),
|
|
4339
|
+
reply,
|
|
4340
|
+
message: body.message || '',
|
|
4341
|
+
});
|
|
4342
|
+
if (!ok) return jsonResponse(res, { error: 'Permission request not found' }, 404);
|
|
4343
|
+
jsonResponse(res, { ok: true });
|
|
4344
|
+
}).catch(e => jsonResponse(res, { error: e.message }, 500));
|
|
4345
|
+
return true;
|
|
4346
|
+
}
|
|
4347
|
+
|
|
4182
4348
|
const listeningHandled = handleListeningApi(req, res, url, { brain, ensureBrainInit });
|
|
4183
4349
|
if (listeningHandled) return true;
|
|
4184
4350
|
|
|
@@ -4210,4 +4376,5 @@ module.exports = {
|
|
|
4210
4376
|
// Test helpers
|
|
4211
4377
|
_setReadDb,
|
|
4212
4378
|
_setBrain,
|
|
4379
|
+
_permissionRegistry,
|
|
4213
4380
|
};
|