@raoxxxwq/pi-codebuddy-sdk 0.4.0 → 0.5.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@raoxxxwq/pi-codebuddy-sdk",
3
- "version": "0.4.0",
3
+ "version": "0.5.0",
4
4
  "description": "Pi extension that uses CodeBuddy (via Agent SDK) as a model provider and adds an AskCodebuddy tool.",
5
5
  "author": "raoxxxwq",
6
6
  "license": "MIT",
package/src/config.ts CHANGED
@@ -26,6 +26,7 @@ export interface Config {
26
26
  appendSystemPrompt?: boolean;
27
27
  settingSources?: SettingSource[];
28
28
  strictMcpConfig?: boolean;
29
+ serialToolCalls?: boolean;
29
30
  pathToCodebuddyCode?: string;
30
31
  };
31
32
  }
package/src/index.ts CHANGED
@@ -700,11 +700,13 @@ function stripToolHistoryForDelegation(messages: Context["messages"]): Context["
700
700
  function buildProviderBoundaryOptions(settings: NonNullable<Config["provider"]>) {
701
701
  const appendSystemPrompt = settings.appendSystemPrompt !== false;
702
702
  const strictMcpConfigEnabled = settings.strictMcpConfig !== false;
703
+ const serialToolCalls = settings.serialToolCalls !== false;
703
704
  const extraArgs: Record<string, string | null> = {};
704
705
  if (strictMcpConfigEnabled) extraArgs["strict-mcp-config"] = null;
705
706
  return {
706
707
  appendSystemPrompt,
707
708
  strictMcpConfigEnabled,
709
+ serialToolCalls,
708
710
  tools: [] as string[],
709
711
  extraArgs,
710
712
  settingSources: appendSystemPrompt
@@ -1581,7 +1583,7 @@ function streamCodebuddySdk(model: Model<any>, context: Context, options?: Simpl
1581
1583
  const boundaryOptions = buildProviderBoundaryOptions(providerSettings);
1582
1584
  const appendSystemPrompt = boundaryOptions.appendSystemPrompt;
1583
1585
  const systemPrompt = appendSystemPrompt
1584
- ? buildCodebuddySystemPrompt(context.systemPrompt, { availableToolNames: mcpTools.map((tool) => tool.name) })
1586
+ ? buildCodebuddySystemPrompt(context.systemPrompt, { availableToolNames: mcpTools.map((tool) => tool.name), serialToolCalls: boundaryOptions.serialToolCalls })
1585
1587
  : undefined;
1586
1588
 
1587
1589
  // Provider Path keeps CodeBuddy inside Pi's tool boundary: no built-in SDK
package/src/skills.ts CHANGED
@@ -20,6 +20,7 @@ const BUILTIN_TOOL_GUIDANCE: Record<string, string> = {
20
20
 
21
21
  export interface ToolBridgeInstructionOptions {
22
22
  availableToolNames?: Iterable<string>;
23
+ serialToolCalls?: boolean;
23
24
  }
24
25
 
25
26
  function normalizeToolNames(names: Iterable<string> | undefined): Set<string> {
@@ -71,7 +72,16 @@ export function buildPiToolBridgeInstruction(options: ToolBridgeInstructionOptio
71
72
  if (has("bash")) {
72
73
  lines.push(`- Use \`${mcpName("bash")}\` only when file tools are insufficient, for search/test/build/git information, or when command execution is requested.`);
73
74
  }
74
- if (toolNames.size > 1) {
75
+ if (options.serialToolCalls !== false) {
76
+ // Force serial tool calls. CodeBuddy's MCP client drops arguments for
77
+ // 2nd+ parallel tool_call blocks in a single response: the
78
+ // content_block_stop for those blocks never arrives, so pi finalizes a
79
+ // dangling toolcall_start with empty {} args and the call fails
80
+ // validation. Instructing one-tool-per-turn avoids the failure at the
81
+ // source. The stream-side backfill defense cannot catch this because it
82
+ // keys off content_block_stop, which never fires for the dropped call.
83
+ lines.push("Call AT MOST ONE tool per turn. Never emit multiple tool_call blocks in a single response. Issue one tool call, wait for its result, then decide the next call in the following turn. Parallel tool calls are unsupported and will fail.");
84
+ } else if (toolNames.size > 1) {
75
85
  lines.push("When calling multiple tools in a single response, ensure each tool_call has complete arguments — do not leave required fields empty or rely on defaults. Incomplete parallel tool calls will be rejected.");
76
86
  }
77
87
  lines.push("Tool arguments must match the Pi tool schema exactly. After a tool result, base the next step on that result; if it is an error, correct the call instead of assuming success.");
@@ -130,13 +140,13 @@ function applySkillsRewrite(systemPrompt: string): string {
130
140
  /** Pi system prompt as CodeBuddy override (replaces default "CodeBuddy Code" identity). */
131
141
  export function buildCodebuddySystemPrompt(
132
142
  piSystemPrompt: string | undefined,
133
- options?: { includeAgents?: boolean; includeSkills?: boolean; includeToolBridge?: boolean; availableToolNames?: Iterable<string> },
143
+ options?: { includeAgents?: boolean; includeSkills?: boolean; includeToolBridge?: boolean; availableToolNames?: Iterable<string>; serialToolCalls?: boolean },
134
144
  ): string | undefined {
135
145
  const parts: string[] = [];
136
146
  const includeToolBridge = options?.includeToolBridge !== false;
137
147
 
138
148
  if (includeToolBridge) {
139
- parts.push(buildPiToolBridgeInstruction({ availableToolNames: options?.availableToolNames }));
149
+ parts.push(buildPiToolBridgeInstruction({ availableToolNames: options?.availableToolNames, serialToolCalls: options?.serialToolCalls }));
140
150
  }
141
151
 
142
152
  if (piSystemPrompt) {