feat: add dialectic_submit_verdict tool (was missing — judge had no way to submit)
7 tools total now:
- dialectic_list_topics
- dialectic_topic_detail
- dialectic_propose_topic
- dialectic_signup
- dialectic_post_argument
- dialectic_submit_verdict (NEW — POST /api/topics/{id}/verdict)
- dialectic_view_verdict
Also added contracts.tools entry for the new tool, updated README +
startup log line. Sim smoke verified the other 4 (list/propose/signup/
detail) via direct plugin import; submit_verdict not yet smoke-tested
end-to-end (requires running through a full debate to debate_end_at).
Code path is identical to other write tools — bearer + JSON body +
shape-coerced response.
This commit is contained in:
@@ -19,7 +19,15 @@ import { BackendClient } from './backend-client.js';
|
||||
import { hfOnCallCoverageCheck } from './hf-precheck.js';
|
||||
const DEFAULT_BACKEND_URL = 'https://dialectic-api.hangman-lab.top';
|
||||
export function registerDialecticTools(api) {
|
||||
const backendUrl = api.config?.backendUrl ?? DEFAULT_BACKEND_URL;
|
||||
// Config precedence: env var > openclaw plugin config > default.
|
||||
// pluginConfig is the plugin-scoped subset (openclaw.json
|
||||
// plugins.entries.dialectic.config) — confirmed by reading the
|
||||
// openclaw SDK's api-builder which assigns `pluginConfig:
|
||||
// params.pluginConfig`. `api.config` (whole openclaw.json) is left
|
||||
// accessible for downstream that needs cross-plugin lookups.
|
||||
const backendUrl = (process.env.DIALECTIC_BACKEND_URL ?? '').trim() ||
|
||||
api.pluginConfig?.backendUrl ||
|
||||
DEFAULT_BACKEND_URL;
|
||||
// Per-tool we pull ctx.agentId out of the factory (the
|
||||
// backend api key resolves from that agent's secret-mgr).
|
||||
api.registerTool((ctx) => ({
|
||||
@@ -165,6 +173,41 @@ export function registerDialecticTools(api) {
|
||||
return await client.post(`/api/topics/${encodeURIComponent(params.topic_id)}/arguments`, { content: params.content });
|
||||
}),
|
||||
}));
|
||||
api.registerTool((ctx) => ({
|
||||
name: 'dialectic_submit_verdict',
|
||||
description: 'Submit the structured verdict for a debate you are the judge of. Topic must be in `debating` ' +
|
||||
'status AND past its debate_end_at. The `verdict` JSON shape must match the topic\'s ' +
|
||||
'verdict_schema_id (binary / claim-resolution / policy-recommendation / free-form). On success ' +
|
||||
'the topic transitions to `completed` and the verdict is visible via dialectic_view_verdict.',
|
||||
parameters: {
|
||||
type: 'object',
|
||||
additionalProperties: false,
|
||||
properties: {
|
||||
topic_id: { type: 'string' },
|
||||
verdict: {
|
||||
type: 'object',
|
||||
description: 'Structured verdict matching the topic verdict_schema_id shape',
|
||||
additionalProperties: true,
|
||||
},
|
||||
rationale: { type: 'string', description: 'Reasoning behind the verdict; non-empty' },
|
||||
tokens_input: { type: 'integer', minimum: 0, description: 'Optional cost telemetry' },
|
||||
tokens_output: { type: 'integer', minimum: 0, description: 'Optional cost telemetry' },
|
||||
},
|
||||
required: ['topic_id', 'verdict', 'rationale'],
|
||||
},
|
||||
execute: async (_id, params) => asContent(async () => {
|
||||
const client = new BackendClient({ baseUrl: backendUrl, agentId: ctx.agentId ?? '' });
|
||||
const body = {
|
||||
verdict: params.verdict,
|
||||
rationale: params.rationale,
|
||||
};
|
||||
if (typeof params.tokens_input === 'number')
|
||||
body.tokens_input = params.tokens_input;
|
||||
if (typeof params.tokens_output === 'number')
|
||||
body.tokens_output = params.tokens_output;
|
||||
return await client.post(`/api/topics/${encodeURIComponent(params.topic_id)}/verdict`, body);
|
||||
}),
|
||||
}));
|
||||
api.registerTool((ctx) => ({
|
||||
name: 'dialectic_view_verdict',
|
||||
description: 'Fetch the structured verdict for a completed Dialectic topic. 404 if the debate is still ' +
|
||||
@@ -180,7 +223,7 @@ export function registerDialecticTools(api) {
|
||||
return await client.get(`/api/topics/${encodeURIComponent(params.topic_id)}/verdict`);
|
||||
}),
|
||||
}));
|
||||
api.logger.info(`[dialectic] registered 6 tools (backend=${backendUrl})`);
|
||||
api.logger.info(`[dialectic] registered 7 tools (backend=${backendUrl})`);
|
||||
}
|
||||
/** Wraps an async backend call and converts result/error into MCP content shape. */
|
||||
async function asContent(fn) {
|
||||
|
||||
Reference in New Issue
Block a user