pi-claude-agent-sdk 0.8.2 → 0.8.3

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": "pi-claude-agent-sdk",
3
- "version": "0.8.2",
3
+ "version": "0.8.3",
4
4
  "private": false,
5
5
  "description": "Pi extension that uses Claude Code (via Agent SDK) as a model provider.",
6
6
  "keywords": [
package/src/index.ts CHANGED
@@ -17,6 +17,7 @@ import { QueryContext, ctx } from "./query-state.js";
17
17
  import { makePromptStream, userMessage, type PromptStream } from "./prompt-stream.js";
18
18
  import { claudeCodeSettings, loadConfig, markStartupNoticeShown, type Config } from "./config.js";
19
19
  import {
20
+ getSharedPromptCaptures,
20
21
  projectPromptCapture,
21
22
  PromptCaptures,
22
23
  } from "./prompt-capture.js";
@@ -133,6 +134,10 @@ function diagDump(label: string, data: Record<string, unknown>) {
133
134
  //
134
135
  // On session_shutdown (including /reload), clearSession() resets this so a fresh
135
136
  // registration can occur for the next session.
137
+ //
138
+ // The prompt-capture table is shared the same way (PROMPT_CAPTURES_KEY): skipping
139
+ // re-registration is not enough when the first copy's before_agent_start handler
140
+ // is dropped and a second copy records into a different Map.
136
141
  const ACTIVE_STREAM_SIMPLE_KEY = Symbol.for("claude-bridge:activeStreamSimple");
137
142
 
138
143
  // MODELS is buildModels(getModels("anthropic")) — projection kept in models.js.
@@ -790,8 +795,10 @@ function showStartupNoticeOnce(): void {
790
795
  }
791
796
 
792
797
  // Captures of what pi assembled per agent; see src/prompt-capture.ts for why this
793
- // is keyed rather than held in a single slot.
794
- const promptCaptures = new PromptCaptures(256, (diagnostic) => {
798
+ // is keyed rather than held in a single slot. Process-wide: a second evaluation
799
+ // of this module (user vs project package root, or a subagent) must record into
800
+ // the same table the first evaluation's streamSimple reads.
801
+ const promptCaptures = getSharedPromptCaptures(() => new PromptCaptures(256, (diagnostic) => {
795
802
  const first = diagnostic.matches[0];
796
803
  debug(
797
804
  `prompt-capture: no match for ${diagnostic.systemPrompt.length}-char system prompt. `
@@ -801,7 +808,7 @@ const promptCaptures = new PromptCaptures(256, (diagnostic) => {
801
808
  : "no known captures to compare against."
802
809
  ) + ` known keys=${diagnostic.matches.length}`,
803
810
  );
804
- });
811
+ }));
805
812
 
806
813
  /** Whatever a settled session left behind, named in one greppable line.
807
814
  *
@@ -162,7 +162,10 @@ export class PromptCaptures {
162
162
  + `Claude Code would receive none of this turn's context files, skills or custom instructions. `
163
163
  + `The usual cause is an extension loaded after claude-bridge that rewrites the system prompt from before_agent_start — `
164
164
  + `one that wraps it is fine, one that rebuilds or strips it leaves nothing to match. `
165
- + `(Also possible: pi rebuilt the prompt outside before_agent_start — a late-registered tool or fresh resource discovery.)`,
165
+ + `(Also possible: pi rebuilt the prompt outside before_agent_start — a late-registered tool or fresh resource discovery.)`
166
+ + (this.captures.size === 0
167
+ ? ` Zero known also means before_agent_start never recorded into this table — often a second copy of this extension loaded from another package root after the first registered the provider.`
168
+ : ""),
166
169
  );
167
170
  }
168
171
 
@@ -232,6 +235,30 @@ export class PromptCaptures {
232
235
  }
233
236
  }
234
237
 
238
+ /** Process-wide slot for the capture table.
239
+ *
240
+ * `src/index.ts` is evaluated once per package root. Pi's pre-trust pass loads
241
+ * the user install, which registers the provider; the post-trust pass then
242
+ * loads the project install as a different module and drops the first copy's
243
+ * event handlers. A per-module Map means `before_agent_start` records into a
244
+ * table the live `streamSimple` never reads.
245
+ *
246
+ * Symbol.for shares one table across those evaluations, the same way
247
+ * `ACTIVE_STREAM_SIMPLE_KEY` shares the stream. Do not use `instanceof
248
+ * PromptCaptures` to recognize the stored value: two package roots evaluate
249
+ * two copies of the class, so a cross-realm check would replace the table
250
+ * the first copy's stream already closed over. */
251
+ export const PROMPT_CAPTURES_KEY = Symbol.for("claude-bridge:promptCaptures");
252
+
253
+ export function getSharedPromptCaptures(create: () => PromptCaptures): PromptCaptures {
254
+ const g = globalThis as Record<symbol, unknown>;
255
+ const existing = g[PROMPT_CAPTURES_KEY];
256
+ if (existing) return existing as PromptCaptures;
257
+ const created = create();
258
+ g[PROMPT_CAPTURES_KEY] = created;
259
+ return created;
260
+ }
261
+
235
262
  export function projectPromptCapture(
236
263
  capture: PromptCapture,
237
264
  options: { skillReadTool: SkillReadTool },