feat(page-data): add validation suggestions, repair path, and thinking fixes
Memind CI / Test, build, and release guards (push) Failing after 3m18s
Memind CI / Test, build, and release guards (push) Failing after 3m18s
Map Page Data failure codes to Chinese remediation hints, trigger one-shot goosed repair for remediable cases, and recover poisoned thinking sessions. Route local DeepSeek through the no-think proxy via host.docker.internal so tool rounds no longer hit reasoning_content 400; document gate and case-study scenarios for event registration repair. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -44,12 +44,17 @@ test('Goosed adapter uses the current session API, streams bounded metadata and
|
||||
const adapter = createGoosedExecutorAdapter({
|
||||
baseUrl: 'http://127.0.0.1:18006',
|
||||
secret: 'secret',
|
||||
provider: 'custom_deepseek',
|
||||
model: 'deepseek-v4-pro',
|
||||
workspaceResolver: async () => '/tmp/canary',
|
||||
fetchImpl: async (url, init) => {
|
||||
calls.push({ url, init });
|
||||
if (url.endsWith('/agent/start')) {
|
||||
return Response.json({ id: 'session-1' });
|
||||
}
|
||||
if (url.endsWith('/agent/update_provider')) {
|
||||
return Response.json({ ok: true });
|
||||
}
|
||||
if (url.endsWith('/events')) {
|
||||
return sseResponse([
|
||||
{ type: 'message', data: { type: 'message', secret: 'not-projected' } },
|
||||
@@ -70,15 +75,27 @@ test('Goosed adapter uses the current session API, streams bounded metadata and
|
||||
assert.equal(calls[0].url, 'http://127.0.0.1:18006/agent/start');
|
||||
assert.equal(calls[0].init.headers['X-Secret-Key'], 'secret');
|
||||
assert.equal(JSON.parse(calls[0].init.body).working_dir, '/tmp/canary');
|
||||
assert.equal(
|
||||
JSON.parse(calls.find((call) => call.url.endsWith('/reply')).init.body)
|
||||
.user_message.content[0].text,
|
||||
'Fix the validation',
|
||||
const providerBody = JSON.parse(
|
||||
calls.find((call) => call.url.endsWith('/agent/update_provider')).init.body,
|
||||
);
|
||||
assert.deepEqual(providerBody, {
|
||||
session_id: 'session-1',
|
||||
provider: 'custom_deepseek',
|
||||
model: 'deepseek-v4-pro',
|
||||
});
|
||||
const replyBody = JSON.parse(
|
||||
calls.find((call) => call.url.endsWith('/reply')).init.body,
|
||||
);
|
||||
assert.equal(replyBody.user_message.content[0].text, 'Fix the validation');
|
||||
assert.equal(replyBody.user_message.role, 'user');
|
||||
assert.equal(typeof replyBody.user_message.created, 'number');
|
||||
assert.equal(replyBody.user_message.metadata.userVisible, true);
|
||||
assert.equal(replyBody.user_message.metadata.agentVisible, true);
|
||||
assert.deepEqual(
|
||||
emitted.map((event) => event.type),
|
||||
[
|
||||
'executor_job_session_created',
|
||||
'executor_job_provider_set',
|
||||
'executor_job_adapter_event',
|
||||
'executor_job_adapter_event',
|
||||
],
|
||||
@@ -87,6 +104,51 @@ test('Goosed adapter uses the current session API, streams bounded metadata and
|
||||
assert.deepEqual(await adapter.health(), { ok: true, status: 200 });
|
||||
});
|
||||
|
||||
test('Goosed adapter treats data.type Finish as terminal when SSE event is message', async () => {
|
||||
// Real Goosed emits: event: message + data: {"type":"Finish",...}
|
||||
const emitted = [];
|
||||
const adapter = createGoosedExecutorAdapter({
|
||||
baseUrl: 'http://127.0.0.1:18006',
|
||||
secret: 'secret',
|
||||
workspaceResolver: async () => '/tmp/canary',
|
||||
fetchImpl: async (url) => {
|
||||
if (url.endsWith('/agent/start')) {
|
||||
return Response.json({ id: 'session-finish' });
|
||||
}
|
||||
if (url.endsWith('/events')) {
|
||||
return sseResponse([
|
||||
{
|
||||
type: 'message',
|
||||
data: {
|
||||
type: 'Message',
|
||||
message: { role: 'assistant', content: [{ type: 'text', text: 'ok' }] },
|
||||
},
|
||||
},
|
||||
{
|
||||
type: 'message',
|
||||
data: { type: 'Finish', reason: 'stop', request_id: 'req-1' },
|
||||
},
|
||||
]);
|
||||
}
|
||||
if (url.endsWith('/reply')) return Response.json({ ok: true });
|
||||
if (url.endsWith('/status')) return Response.json({ ok: true });
|
||||
throw new Error(`Unexpected URL: ${url}`);
|
||||
},
|
||||
});
|
||||
const result = await adapter.submit(request(), {
|
||||
jobId: 'job-finish',
|
||||
emit: async (type, data) => emitted.push({ type, data }),
|
||||
});
|
||||
assert.equal(result.outcome, 'completed');
|
||||
assert.equal(result.metrics.eventCount, 2);
|
||||
assert.deepEqual(
|
||||
emitted
|
||||
.filter((event) => event.type === 'executor_job_adapter_event')
|
||||
.map((event) => event.data.eventType),
|
||||
['message', 'finish'],
|
||||
);
|
||||
});
|
||||
|
||||
test('Goosed adapter rejects remote targets unless explicitly allowed', () => {
|
||||
assert.throws(
|
||||
() => createGoosedExecutorAdapter({ baseUrl: 'https://executor.example.com' }),
|
||||
|
||||
Reference in New Issue
Block a user