@@ -49,6 +49,39 @@ static void sb_append(adapter_sb_t *sb, const char *s) {
4949 sb -> buf [sb -> len ] = '\0' ;
5050}
5151
52+ /* Append a single-quoted JavaScript string literal, escaping the characters
53+ * that could terminate or corrupt it. Avoids the fixed buffer sizing that
54+ * cbm_client_adapter_escape_js imposes, so long registry descriptions fit. */
55+ static void sb_append_js_string (adapter_sb_t * sb , const char * s ) {
56+ if (!s ) {
57+ sb_append (sb , "''" );
58+ return ;
59+ }
60+ sb_append (sb , "'" );
61+ for (const char * p = s ; * p ; p ++ ) {
62+ switch (* p ) {
63+ case '\\' :
64+ sb_append (sb , "\\\\" );
65+ break ;
66+ case '\'' :
67+ sb_append (sb , "\\'" );
68+ break ;
69+ case '\n' :
70+ sb_append (sb , "\\n" );
71+ break ;
72+ case '\r' :
73+ sb_append (sb , "\\r" );
74+ break ;
75+ default : {
76+ char ch [2 ] = {* p , '\0' };
77+ sb_append (sb , ch );
78+ break ;
79+ }
80+ }
81+ }
82+ sb_append (sb , "'" );
83+ }
84+
5285bool cbm_client_adapter_escape_js (const char * in , char * out , size_t out_sz ) {
5386 if (!in || !out || out_sz == 0 ) {
5487 return false;
@@ -120,6 +153,10 @@ char *cbm_client_adapter_pi(const char *binary_path) {
120153
121154 adapter_sb_t sb = {0 };
122155 emit_header (& sb , "pi" );
156+ /* Pin the coding-agent contract so a probe against @mariozechner/pi
157+ * (pods CLI) or an old AgentTool arity cannot be mistaken for this file. */
158+ sb_append (& sb , "// Target: @earendil-works/pi-coding-agent >= 0.74.0 (verified 0.84.2)\n"
159+ "// ToolDefinition.execute(toolCallId, params, signal, onUpdate, ctx)\n" );
123160 sb_append (& sb , "import { spawn } from 'node:child_process';\n\n" );
124161 sb_append (& sb , "const BIN = '" );
125162 sb_append (& sb , bin );
@@ -131,7 +168,7 @@ char *cbm_client_adapter_pi(const char *binary_path) {
131168 sb_append (
132169 & sb , "async function call(tool, args, signal) {\n"
133170 " return new Promise((resolve) => {\n"
134- " const child = spawn(BIN, ['cli', tool, JSON.stringify(args ?? {})], {\n"
171+ " const child = spawn(BIN, ['cli', '--json', tool, JSON.stringify(args ?? {})], {\n"
135172 " stdio: ['ignore', 'pipe', 'pipe'],\n"
136173 " env: { ...process.env, CBM_LOG_LEVEL: 'error' },\n"
137174 " });\n"
@@ -170,11 +207,37 @@ char *cbm_client_adapter_pi(const char *binary_path) {
170207 if (!name || !name [0 ]) {
171208 continue ;
172209 }
173- sb_append (& sb , " pi.registerTool({ name: '" );
174- sb_append (& sb , name );
175- sb_append (& sb , "', run: (args, ctx) => call('" );
176- sb_append (& sb , name );
177- sb_append (& sb , "', args, ctx?.signal) });\n" );
210+ const char * title = cbm_mcp_tool_title (name );
211+ const char * description = cbm_mcp_tool_description (name );
212+ const char * schema = cbm_mcp_tool_input_schema (name );
213+ sb_append (& sb , " pi.registerTool({\n" );
214+ sb_append (& sb , " name: " );
215+ sb_append_js_string (& sb , name );
216+ sb_append (& sb , ",\n label: " );
217+ sb_append_js_string (& sb , title ? title : name );
218+ sb_append (& sb , ",\n description: " );
219+ sb_append_js_string (& sb , description ? description : "" );
220+ sb_append (& sb , ",\n parameters: " );
221+ /* input_schema is compact JSON, which is a valid JavaScript object
222+ * literal; embedding it directly keeps the generated module free of a
223+ * JSON.parse indirection and of any escaping drift. */
224+ sb_append (& sb , schema ? schema : "{}" );
225+ /* 0.84.2 calls execute(toolCallId, params, signal, onUpdate, ctx).
226+ * The previous (args, ctx) shape bound the call id as the MCP args. */
227+ sb_append (& sb , ",\n execute: async (toolCallId, params, signal, _onUpdate, ctx) => {\n" );
228+ sb_append (& sb , " const result = await call(" );
229+ sb_append_js_string (& sb , name );
230+ sb_append (& sb ,
231+ ", params, signal ?? ctx?.signal);\n"
232+ " if (result && typeof result === 'object' && result.error) {\n"
233+ " throw new Error(String(result.error));\n"
234+ " }\n"
235+ " const content = result && Array.isArray(result.content)\n"
236+ " ? result.content\n"
237+ " : [{ type: 'text', text: JSON.stringify(result ?? null, null, 2) }];\n"
238+ " return { content, details: result ?? {} };\n"
239+ " },\n"
240+ " });\n" );
178241 }
179242 sb_append (& sb , "}\n" );
180243
0 commit comments