@vanillagreen/pi-claude-bridge 4.0.1 → 4.0.2

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/README.md CHANGED
@@ -28,7 +28,11 @@ Fable 5.1 requires [Claude Code 2.1.255 or later](https://code.claude.com/docs/e
28
28
 
29
29
  ## How it works
30
30
 
31
- You select a pi-claude model in Pi. Select **Claude Fable 5.1** (`pi-claude/claude-fable-5-1`) for Fable. The bridge starts or resumes Claude Code through the Agent SDK. It sends the prompt and makes Pi's tools available to Claude Code. Tool calls return to Pi for execution, then their results return to Claude Code. Pi displays the response and saves the Claude session identifier.
31
+ - You pick one of the `pi-claude` models in Pi's model menu; **Claude Fable 5.1** is `pi-claude/claude-fable-5-1`.
32
+ - The bridge starts Claude Code, or resumes it, through the Claude Agent SDK, Anthropic's library for driving Claude Code from another program.
33
+ - It sends your prompt to Claude Code and offers it Pi's tools.
34
+ - When Claude Code calls a tool, Pi runs the tool and sends the result back to Claude Code.
35
+ - Pi shows the reply and remembers which Claude Code conversation it belongs to, so your next message continues it.
32
36
 
33
37
  ## Settings
34
38
 
@@ -68,7 +68,8 @@ async function listAccountConnectors(deps) {
68
68
  const { credentials, apiBase, signal } = deps;
69
69
  const fetchImpl = deps.fetchImpl ?? fetch;
70
70
  const url = connectorsListUrl(credentials.organizationUuid, apiBase);
71
- const fail = (reason) => ({ ok: false, complete: false, reason: redactSecret(reason, credentials.accessToken) });
71
+ const fail = (key, value, reason) => ({ ok: false, complete: false, reason: redactSecret(`${key}=${JSON.stringify(value)}
72
+ ${reason}`, credentials.accessToken) });
72
73
  let response;
73
74
  try {
74
75
  response = await fetchImpl(url, {
@@ -82,32 +83,32 @@ async function listAccountConnectors(deps) {
82
83
  signal
83
84
  });
84
85
  } catch (error) {
85
- return fail(`connector list request failed: ${errorText(error)}`);
86
+ return fail("connector-request", "transport", `connector list request failed: ${errorText(error)}`);
86
87
  }
87
88
  let bodyText;
88
89
  try {
89
90
  bodyText = await response.text();
90
91
  } catch (error) {
91
- return fail(`connector list response unreadable: ${errorText(error)}`);
92
+ return fail("connector-response", "unreadable", `connector list response unreadable: ${errorText(error)}`);
92
93
  }
93
94
  if (!response.ok) {
94
- return fail(`connector list returned HTTP ${response.status}${apiErrorSuffix(bodyText)}`);
95
+ return fail("connector-http", response.status, `connector list returned HTTP ${response.status}${apiErrorSuffix(bodyText)}`);
95
96
  }
96
97
  let parsed;
97
98
  try {
98
99
  parsed = JSON.parse(bodyText);
99
100
  } catch {
100
- return fail("connector list returned a non-JSON body");
101
+ return fail("connector-json", "invalid", "connector list returned a non-JSON body");
101
102
  }
102
103
  if (!Array.isArray(parsed?.results)) {
103
- return fail("connector list response had no results array");
104
+ return fail("connector-results", "not-array", "connector list response had no results array");
104
105
  }
105
106
  const connectors = [];
106
107
  for (const raw of parsed.results) {
107
108
  const entry = raw;
108
109
  const name = nonEmptyString(entry?.name);
109
110
  if (!name) {
110
- return fail("connector list contained an entry with no name");
111
+ return fail("connector-name", connectors.length, "connector list contained an entry with no name");
111
112
  }
112
113
  connectors.push({
113
114
  name,