Skip to content

pi 0.86: streamSimple gets a TranscriptContext — system prompt and tools are never sent #244

Description

@KhangHLe

On pi 0.86.x, streamSimple no longer gets context.systemPrompt or context.tools. pi-ai now passes a normalized TranscriptContext ({ messages } only) — the system prompt and tool declarations are folded into a leading role: "system" message and have to be read back with getCurrentSystemPrompt(context.messages) / getCurrentTools(context.messages) (docs: packages/coding-agent/docs/custom-provider.md, "Custom Streaming API", v0.86.0; types in pi-ai/dist/types.d.ts, helpers in pi-ai/dist/utils/transcript.js).

packages/pi/src/convert.ts still reads context.systemPrompt (L580) and context.tools (L621), and stream.ts L1270 reads context.tools for the tool_use name un-mapping. On 0.86 both are undefined, so every request goes out with the billing header + Claude Code identity as the whole system prompt and no tools. No error — HTTP 200 and a normal-looking reply.

Repro (pi 0.86.1, @cortexkit/pi-anthropic-auth 1.22.0, from an empty dir):

pi -p --no-session --no-extensions -e <extension> \
  --model anthropic-personal/claude-haiku-4-5 --tools bash \
  --system-prompt "Your name is Wren. Always state your name first." \
  "State your name, then run this with the bash tool: echo probe-ok"

Result: I'm Claude, made by Anthropic. However … I don't actually have access to a bash tool. Same command on the built-in anthropic provider answers "Wren" and runs the command.

Fix that worked for me (in a vendored copy of the extension): resolve the prompt/tools/messages once, before building the request —

import * as piAi from "@earendil-works/pi-ai";

function resolveRequestContext(context) {
  const hasHelpers =
    typeof piAi.collapseSystemMessages === "function" &&
    typeof piAi.getCurrentSystemPrompt === "function" &&
    typeof piAi.getCurrentTools === "function";
  const hasSystemMessages = context.messages.some((m) => m?.role === "system");
  if (hasHelpers && hasSystemMessages) {
    const transcript = piAi.collapseSystemMessages(context);
    return {
      systemPrompt: piAi.getCurrentSystemPrompt(transcript.messages),
      tools: piAi.getCurrentTools(transcript.messages),
      messages: transcript.messages.filter((m) => m.role !== "system"),
    };
  }
  return {
    systemPrompt: context.systemPrompt ?? "",
    tools: context.tools ?? [],
    messages: context.messages,
  };
}

then use request.systemPrompt / request.tools / request.messages in buildAnthropicRequest, and the resolved tools in the tool_use branch of stream.ts. The typeof checks + namespace import keep the extension loading on pi < 0.86, where the helpers don't exist and the old fields are still populated. convertMessages already skips the system role, so nothing else changes on the wire.

Happy to open a PR if you want it in that shape.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions