@kontextmind/kxm 0.7.17 → 0.7.18

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.
Files changed (30) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/package.json +8 -6
  3. package/plugins/kxm/.claude-plugin/plugin.json +1 -1
  4. package/plugins/kxm/dist/cli.js +43 -39
  5. package/plugins/kxm/dist/core.js +3 -2
  6. package/plugins/kxm/dist/extension.js +34472 -11328
  7. package/plugins/kxm/dist/mcp-server.js +1 -1
  8. package/plugins/kxm/dist/runtime.js +43 -39
  9. package/plugins/kxm/dist/server.js +43 -39
  10. package/plugins/kxm/dist/vnext-runtime-supervisor.js +40 -37
  11. package/plugins/kxm/package.json +4 -1
  12. package/plugins/kxm/src/extension.ts +9 -0
  13. package/plugins/kxm/src/mcp-server.ts +1 -1
  14. package/plugins/kxm/src/providers/claude-bridge/LICENSE +21 -0
  15. package/plugins/kxm/src/providers/claude-bridge/README.md +18 -0
  16. package/plugins/kxm/src/providers/claude-bridge/config.ts +53 -0
  17. package/plugins/kxm/src/providers/claude-bridge/convert.ts +180 -0
  18. package/plugins/kxm/src/providers/claude-bridge/index.ts +28 -0
  19. package/plugins/kxm/src/providers/claude-bridge/mcp-server.ts +59 -0
  20. package/plugins/kxm/src/providers/claude-bridge/models.ts +166 -0
  21. package/plugins/kxm/src/providers/claude-bridge/pi-compat.ts +215 -0
  22. package/plugins/kxm/src/providers/claude-bridge/prompt-stream.ts +89 -0
  23. package/plugins/kxm/src/providers/claude-bridge/provider.ts +286 -0
  24. package/plugins/kxm/src/providers/claude-bridge/query-state.ts +72 -0
  25. package/plugins/kxm/src/providers/claude-bridge/redact.ts +26 -0
  26. package/plugins/kxm/src/providers/claude-bridge/register.ts +124 -0
  27. package/plugins/kxm/src/providers/claude-bridge/stream.ts +390 -0
  28. package/plugins/kxm/src/providers/claude-bridge/tools.ts +140 -0
  29. package/plugins/kxm/src/redact.ts +3 -2
  30. package/scripts/build-runtime.mjs +5 -1
@@ -17036,7 +17036,7 @@ async function deliverInboxNotification(messageId, delivered, notify) {
17036
17036
  }
17037
17037
 
17038
17038
  // plugins/kxm/src/mcp-server.ts
17039
- var VERSION = "0.7.17";
17039
+ var VERSION = "0.7.18";
17040
17040
  var inbox = /* @__PURE__ */ new Map();
17041
17041
  var notifiedInbox = /* @__PURE__ */ new Set();
17042
17042
  var meshClient;
@@ -8071,36 +8071,38 @@ var require_Alias = __commonJS({
8071
8071
  if (node.anchor === this.source)
8072
8072
  found = node;
8073
8073
  }
8074
+ if (found && ctx) {
8075
+ const { anchors: anchors2, doc: doc2, maxAliasCount } = ctx;
8076
+ let data = anchors2.get(found);
8077
+ if (!data) {
8078
+ toJS.toJS(found, null, ctx);
8079
+ data = anchors2.get(found);
8080
+ }
8081
+ if (data?.res === void 0) {
8082
+ const msg = "This should not happen: Alias anchor was not resolved?";
8083
+ throw new ReferenceError(msg);
8084
+ }
8085
+ if (maxAliasCount >= 0) {
8086
+ data.count += 1;
8087
+ if (data.aliasCount === 0)
8088
+ data.aliasCount = getAliasCount(doc2, found, anchors2);
8089
+ if (data.count * data.aliasCount > maxAliasCount) {
8090
+ const msg = "Excessive alias count indicates a resource exhaustion attack";
8091
+ throw new ReferenceError(msg);
8092
+ }
8093
+ }
8094
+ }
8074
8095
  return found;
8075
8096
  }
8076
8097
  toJSON(_arg, ctx) {
8077
8098
  if (!ctx)
8078
8099
  return { source: this.source };
8079
- const { anchors: anchors2, doc, maxAliasCount } = ctx;
8080
- const source = this.resolve(doc, ctx);
8100
+ const source = this.resolve(ctx.doc, ctx);
8081
8101
  if (!source) {
8082
8102
  const msg = `Unresolved alias (the anchor must be set before the alias): ${this.source}`;
8083
8103
  throw new ReferenceError(msg);
8084
8104
  }
8085
- let data = anchors2.get(source);
8086
- if (!data) {
8087
- toJS.toJS(source, null, ctx);
8088
- data = anchors2.get(source);
8089
- }
8090
- if (data?.res === void 0) {
8091
- const msg = "This should not happen: Alias anchor was not resolved?";
8092
- throw new ReferenceError(msg);
8093
- }
8094
- if (maxAliasCount >= 0) {
8095
- data.count += 1;
8096
- if (data.aliasCount === 0)
8097
- data.aliasCount = getAliasCount(doc, source, anchors2);
8098
- if (data.count * data.aliasCount > maxAliasCount) {
8099
- const msg = "Excessive alias count indicates a resource exhaustion attack";
8100
- throw new ReferenceError(msg);
8101
- }
8102
- }
8103
- return data.res;
8105
+ return ctx.anchors.get(source).res;
8104
8106
  }
8105
8107
  toString(ctx, _onComment, _onChompKeep) {
8106
8108
  const src = `*${this.source}`;
@@ -12102,37 +12104,38 @@ var require_resolve_flow_scalar = __commonJS({
12102
12104
  }
12103
12105
  if (badChar)
12104
12106
  onError(0, "BAD_SCALAR_START", `Plain value cannot start with ${badChar}`);
12105
- return foldLines(source);
12107
+ return unfoldLines(source);
12106
12108
  }
12107
12109
  function singleQuotedValue(source, onError) {
12108
12110
  if (source[source.length - 1] !== "'" || source.length === 1)
12109
12111
  onError(source.length, "MISSING_CHAR", "Missing closing 'quote");
12110
- return foldLines(source.slice(1, -1)).replace(/''/g, "'");
12112
+ return unfoldLines(source.slice(1, -1)).replace(/''/g, "'");
12111
12113
  }
12112
- function foldLines(source) {
12113
- let first, line;
12114
+ function unfoldLines(source) {
12115
+ const line = /(.*?)\r?\n/sy;
12116
+ let match = line.exec(source);
12117
+ if (!match)
12118
+ return source;
12119
+ let trimEnd, trimBoth;
12114
12120
  try {
12115
- first = new RegExp("(.*?)(?<![ ])[ ]*\r?\n", "sy");
12116
- line = new RegExp("[ ]*(.*?)(?:(?<![ ])[ ]*)?\r?\n", "sy");
12121
+ trimEnd = new RegExp("(?<![ ])[ ]+$");
12122
+ trimBoth = new RegExp("^[ ]+|(?<![ ])[ ]+$", "g");
12117
12123
  } catch {
12118
- first = /(.*?)[ \t]*\r?\n/sy;
12119
- line = /[ \t]*(.*?)[ \t]*\r?\n/sy;
12124
+ trimEnd = /[ \t]+$/;
12125
+ trimBoth = /^[ \t]+|[ \t]+$/g;
12120
12126
  }
12121
- let match = first.exec(source);
12122
- if (!match)
12123
- return source;
12124
- let res = match[1];
12127
+ let res = match[1].replace(trimEnd, "");
12125
12128
  let sep3 = " ";
12126
- let pos = first.lastIndex;
12127
- line.lastIndex = pos;
12129
+ let pos = line.lastIndex;
12128
12130
  while (match = line.exec(source)) {
12129
- if (match[1] === "") {
12131
+ const lm = match[1].replace(trimBoth, "");
12132
+ if (lm === "") {
12130
12133
  if (sep3 === "\n")
12131
12134
  res += sep3;
12132
12135
  else
12133
12136
  sep3 = "\n";
12134
12137
  } else {
12135
- res += sep3 + match[1];
12138
+ res += sep3 + lm;
12136
12139
  sep3 = " ";
12137
12140
  }
12138
12141
  pos = line.lastIndex;
@@ -27556,6 +27559,7 @@ import { dirname as dirname6 } from "node:path";
27556
27559
  // plugins/kxm/src/redact.ts
27557
27560
  var SECRET_PATTERNS = [
27558
27561
  /\bsk-[A-Za-z0-9_-]{8,}\b/g,
27562
+ /\bsk-ant-[A-Za-z0-9_-]{8,}\b/g,
27559
27563
  /\bghp_[A-Za-z0-9_]{20,}\b/g,
27560
27564
  /\bgithub_pat_[A-Za-z0-9_]{20,}\b/g,
27561
27565
  /\bxox[baprs]-[A-Za-z0-9-]{10,}\b/gi,
@@ -27563,9 +27567,9 @@ var SECRET_PATTERNS = [
27563
27567
  /\bya29\.[A-Za-z0-9._~+/-]+=*/g,
27564
27568
  /\b1\/\/[A-Za-z0-9_-]+/g,
27565
27569
  /\b1\/[A-Za-z0-9_-]{20,}/g,
27566
- /("?(?:access_token|refresh_token|id_token)"?\s*[:=]\s*")[^"]*(")/gi,
27570
+ /("?(?:access_token|refresh_token|id_token|sessionKey|session_key|claude_oauth_token|anthropicApiKey)"?\s*[:=]\s*")[^"]*(")/gi,
27567
27571
  /\bKXM_[A-Z0-9_]*(TOKEN|SECRET|KEY)[A-Z0-9_]*=\S+/gi,
27568
- /\b(GITHUB_TOKEN|GH_TOKEN|KXM_AUTH_TOKEN|KXM_WORKFLOW_SIGNAL_SECRET)=\S+/gi,
27572
+ /\b(GITHUB_TOKEN|GH_TOKEN|KXM_AUTH_TOKEN|KXM_WORKFLOW_SIGNAL_SECRET|ANTHROPIC_API_KEY|ANTHROPIC_AUTH_TOKEN|CLAUDE_API_KEY)=\S+/gi,
27569
27573
  /\b[A-Fa-f0-9]{64}\b/g
27570
27574
  ];
27571
27575
  function redactSecrets(value) {
@@ -660,36 +660,38 @@ var require_Alias = __commonJS({
660
660
  if (node.anchor === this.source)
661
661
  found = node;
662
662
  }
663
+ if (found && ctx) {
664
+ const { anchors: anchors2, doc: doc2, maxAliasCount } = ctx;
665
+ let data = anchors2.get(found);
666
+ if (!data) {
667
+ toJS.toJS(found, null, ctx);
668
+ data = anchors2.get(found);
669
+ }
670
+ if (data?.res === void 0) {
671
+ const msg = "This should not happen: Alias anchor was not resolved?";
672
+ throw new ReferenceError(msg);
673
+ }
674
+ if (maxAliasCount >= 0) {
675
+ data.count += 1;
676
+ if (data.aliasCount === 0)
677
+ data.aliasCount = getAliasCount(doc2, found, anchors2);
678
+ if (data.count * data.aliasCount > maxAliasCount) {
679
+ const msg = "Excessive alias count indicates a resource exhaustion attack";
680
+ throw new ReferenceError(msg);
681
+ }
682
+ }
683
+ }
663
684
  return found;
664
685
  }
665
686
  toJSON(_arg, ctx) {
666
687
  if (!ctx)
667
688
  return { source: this.source };
668
- const { anchors: anchors2, doc, maxAliasCount } = ctx;
669
- const source = this.resolve(doc, ctx);
689
+ const source = this.resolve(ctx.doc, ctx);
670
690
  if (!source) {
671
691
  const msg = `Unresolved alias (the anchor must be set before the alias): ${this.source}`;
672
692
  throw new ReferenceError(msg);
673
693
  }
674
- let data = anchors2.get(source);
675
- if (!data) {
676
- toJS.toJS(source, null, ctx);
677
- data = anchors2.get(source);
678
- }
679
- if (data?.res === void 0) {
680
- const msg = "This should not happen: Alias anchor was not resolved?";
681
- throw new ReferenceError(msg);
682
- }
683
- if (maxAliasCount >= 0) {
684
- data.count += 1;
685
- if (data.aliasCount === 0)
686
- data.aliasCount = getAliasCount(doc, source, anchors2);
687
- if (data.count * data.aliasCount > maxAliasCount) {
688
- const msg = "Excessive alias count indicates a resource exhaustion attack";
689
- throw new ReferenceError(msg);
690
- }
691
- }
692
- return data.res;
694
+ return ctx.anchors.get(source).res;
693
695
  }
694
696
  toString(ctx, _onComment, _onChompKeep) {
695
697
  const src = `*${this.source}`;
@@ -4691,37 +4693,38 @@ var require_resolve_flow_scalar = __commonJS({
4691
4693
  }
4692
4694
  if (badChar)
4693
4695
  onError(0, "BAD_SCALAR_START", `Plain value cannot start with ${badChar}`);
4694
- return foldLines(source);
4696
+ return unfoldLines(source);
4695
4697
  }
4696
4698
  function singleQuotedValue(source, onError) {
4697
4699
  if (source[source.length - 1] !== "'" || source.length === 1)
4698
4700
  onError(source.length, "MISSING_CHAR", "Missing closing 'quote");
4699
- return foldLines(source.slice(1, -1)).replace(/''/g, "'");
4701
+ return unfoldLines(source.slice(1, -1)).replace(/''/g, "'");
4700
4702
  }
4701
- function foldLines(source) {
4702
- let first, line;
4703
+ function unfoldLines(source) {
4704
+ const line = /(.*?)\r?\n/sy;
4705
+ let match = line.exec(source);
4706
+ if (!match)
4707
+ return source;
4708
+ let trimEnd, trimBoth;
4703
4709
  try {
4704
- first = new RegExp("(.*?)(?<![ ])[ ]*\r?\n", "sy");
4705
- line = new RegExp("[ ]*(.*?)(?:(?<![ ])[ ]*)?\r?\n", "sy");
4710
+ trimEnd = new RegExp("(?<![ ])[ ]+$");
4711
+ trimBoth = new RegExp("^[ ]+|(?<![ ])[ ]+$", "g");
4706
4712
  } catch {
4707
- first = /(.*?)[ \t]*\r?\n/sy;
4708
- line = /[ \t]*(.*?)[ \t]*\r?\n/sy;
4713
+ trimEnd = /[ \t]+$/;
4714
+ trimBoth = /^[ \t]+|[ \t]+$/g;
4709
4715
  }
4710
- let match = first.exec(source);
4711
- if (!match)
4712
- return source;
4713
- let res = match[1];
4716
+ let res = match[1].replace(trimEnd, "");
4714
4717
  let sep2 = " ";
4715
- let pos = first.lastIndex;
4716
- line.lastIndex = pos;
4718
+ let pos = line.lastIndex;
4717
4719
  while (match = line.exec(source)) {
4718
- if (match[1] === "") {
4720
+ const lm = match[1].replace(trimBoth, "");
4721
+ if (lm === "") {
4719
4722
  if (sep2 === "\n")
4720
4723
  res += sep2;
4721
4724
  else
4722
4725
  sep2 = "\n";
4723
4726
  } else {
4724
- res += sep2 + match[1];
4727
+ res += sep2 + lm;
4725
4728
  sep2 = " ";
4726
4729
  }
4727
4730
  pos = line.lastIndex;
@@ -9211,6 +9214,7 @@ function timingSafeStringCompare(a, b) {
9211
9214
  // plugins/kxm/src/redact.ts
9212
9215
  var SECRET_PATTERNS = [
9213
9216
  /\bsk-[A-Za-z0-9_-]{8,}\b/g,
9217
+ /\bsk-ant-[A-Za-z0-9_-]{8,}\b/g,
9214
9218
  /\bghp_[A-Za-z0-9_]{20,}\b/g,
9215
9219
  /\bgithub_pat_[A-Za-z0-9_]{20,}\b/g,
9216
9220
  /\bxox[baprs]-[A-Za-z0-9-]{10,}\b/gi,
@@ -9218,9 +9222,9 @@ var SECRET_PATTERNS = [
9218
9222
  /\bya29\.[A-Za-z0-9._~+/-]+=*/g,
9219
9223
  /\b1\/\/[A-Za-z0-9_-]+/g,
9220
9224
  /\b1\/[A-Za-z0-9_-]{20,}/g,
9221
- /("?(?:access_token|refresh_token|id_token)"?\s*[:=]\s*")[^"]*(")/gi,
9225
+ /("?(?:access_token|refresh_token|id_token|sessionKey|session_key|claude_oauth_token|anthropicApiKey)"?\s*[:=]\s*")[^"]*(")/gi,
9222
9226
  /\bKXM_[A-Z0-9_]*(TOKEN|SECRET|KEY)[A-Z0-9_]*=\S+/gi,
9223
- /\b(GITHUB_TOKEN|GH_TOKEN|KXM_AUTH_TOKEN|KXM_WORKFLOW_SIGNAL_SECRET)=\S+/gi,
9227
+ /\b(GITHUB_TOKEN|GH_TOKEN|KXM_AUTH_TOKEN|KXM_WORKFLOW_SIGNAL_SECRET|ANTHROPIC_API_KEY|ANTHROPIC_AUTH_TOKEN|CLAUDE_API_KEY)=\S+/gi,
9224
9228
  /\b[A-Fa-f0-9]{64}\b/g
9225
9229
  ];
9226
9230
  function redactSecrets(value) {
@@ -8072,36 +8072,38 @@ var require_Alias = __commonJS({
8072
8072
  if (node.anchor === this.source)
8073
8073
  found = node;
8074
8074
  }
8075
+ if (found && ctx) {
8076
+ const { anchors: anchors2, doc: doc2, maxAliasCount } = ctx;
8077
+ let data = anchors2.get(found);
8078
+ if (!data) {
8079
+ toJS.toJS(found, null, ctx);
8080
+ data = anchors2.get(found);
8081
+ }
8082
+ if (data?.res === void 0) {
8083
+ const msg = "This should not happen: Alias anchor was not resolved?";
8084
+ throw new ReferenceError(msg);
8085
+ }
8086
+ if (maxAliasCount >= 0) {
8087
+ data.count += 1;
8088
+ if (data.aliasCount === 0)
8089
+ data.aliasCount = getAliasCount(doc2, found, anchors2);
8090
+ if (data.count * data.aliasCount > maxAliasCount) {
8091
+ const msg = "Excessive alias count indicates a resource exhaustion attack";
8092
+ throw new ReferenceError(msg);
8093
+ }
8094
+ }
8095
+ }
8075
8096
  return found;
8076
8097
  }
8077
8098
  toJSON(_arg, ctx) {
8078
8099
  if (!ctx)
8079
8100
  return { source: this.source };
8080
- const { anchors: anchors2, doc, maxAliasCount } = ctx;
8081
- const source = this.resolve(doc, ctx);
8101
+ const source = this.resolve(ctx.doc, ctx);
8082
8102
  if (!source) {
8083
8103
  const msg = `Unresolved alias (the anchor must be set before the alias): ${this.source}`;
8084
8104
  throw new ReferenceError(msg);
8085
8105
  }
8086
- let data = anchors2.get(source);
8087
- if (!data) {
8088
- toJS.toJS(source, null, ctx);
8089
- data = anchors2.get(source);
8090
- }
8091
- if (data?.res === void 0) {
8092
- const msg = "This should not happen: Alias anchor was not resolved?";
8093
- throw new ReferenceError(msg);
8094
- }
8095
- if (maxAliasCount >= 0) {
8096
- data.count += 1;
8097
- if (data.aliasCount === 0)
8098
- data.aliasCount = getAliasCount(doc, source, anchors2);
8099
- if (data.count * data.aliasCount > maxAliasCount) {
8100
- const msg = "Excessive alias count indicates a resource exhaustion attack";
8101
- throw new ReferenceError(msg);
8102
- }
8103
- }
8104
- return data.res;
8106
+ return ctx.anchors.get(source).res;
8105
8107
  }
8106
8108
  toString(ctx, _onComment, _onChompKeep) {
8107
8109
  const src = `*${this.source}`;
@@ -12103,37 +12105,38 @@ var require_resolve_flow_scalar = __commonJS({
12103
12105
  }
12104
12106
  if (badChar)
12105
12107
  onError(0, "BAD_SCALAR_START", `Plain value cannot start with ${badChar}`);
12106
- return foldLines(source);
12108
+ return unfoldLines(source);
12107
12109
  }
12108
12110
  function singleQuotedValue(source, onError) {
12109
12111
  if (source[source.length - 1] !== "'" || source.length === 1)
12110
12112
  onError(source.length, "MISSING_CHAR", "Missing closing 'quote");
12111
- return foldLines(source.slice(1, -1)).replace(/''/g, "'");
12113
+ return unfoldLines(source.slice(1, -1)).replace(/''/g, "'");
12112
12114
  }
12113
- function foldLines(source) {
12114
- let first, line;
12115
+ function unfoldLines(source) {
12116
+ const line = /(.*?)\r?\n/sy;
12117
+ let match = line.exec(source);
12118
+ if (!match)
12119
+ return source;
12120
+ let trimEnd, trimBoth;
12115
12121
  try {
12116
- first = new RegExp("(.*?)(?<![ ])[ ]*\r?\n", "sy");
12117
- line = new RegExp("[ ]*(.*?)(?:(?<![ ])[ ]*)?\r?\n", "sy");
12122
+ trimEnd = new RegExp("(?<![ ])[ ]+$");
12123
+ trimBoth = new RegExp("^[ ]+|(?<![ ])[ ]+$", "g");
12118
12124
  } catch {
12119
- first = /(.*?)[ \t]*\r?\n/sy;
12120
- line = /[ \t]*(.*?)[ \t]*\r?\n/sy;
12125
+ trimEnd = /[ \t]+$/;
12126
+ trimBoth = /^[ \t]+|[ \t]+$/g;
12121
12127
  }
12122
- let match = first.exec(source);
12123
- if (!match)
12124
- return source;
12125
- let res = match[1];
12128
+ let res = match[1].replace(trimEnd, "");
12126
12129
  let sep3 = " ";
12127
- let pos = first.lastIndex;
12128
- line.lastIndex = pos;
12130
+ let pos = line.lastIndex;
12129
12131
  while (match = line.exec(source)) {
12130
- if (match[1] === "") {
12132
+ const lm = match[1].replace(trimBoth, "");
12133
+ if (lm === "") {
12131
12134
  if (sep3 === "\n")
12132
12135
  res += sep3;
12133
12136
  else
12134
12137
  sep3 = "\n";
12135
12138
  } else {
12136
- res += sep3 + match[1];
12139
+ res += sep3 + lm;
12137
12140
  sep3 = " ";
12138
12141
  }
12139
12142
  pos = line.lastIndex;
@@ -1,11 +1,14 @@
1
1
  {
2
2
  "name": "kxm-claude-plugin",
3
- "version": "0.7.17",
3
+ "version": "0.7.18",
4
4
  "private": true,
5
5
  "type": "module",
6
6
  "engines": {
7
7
  "node": "^22.19.0 || >=24.0.0"
8
8
  },
9
+ "dependencies": {
10
+ "@anthropic-ai/claude-agent-sdk": "0.2.141"
11
+ },
9
12
  "devDependencies": {
10
13
  "@modelcontextprotocol/sdk": "1.30.0"
11
14
  }
@@ -10,6 +10,11 @@ import {
10
10
  registerAntigravityProvider,
11
11
  type AntigravityRegistration,
12
12
  } from "./providers/antigravity/register.ts";
13
+ import {
14
+ claudeBridgeRegistrationNotice,
15
+ registerClaudeBridgeProvider,
16
+ type ClaudeBridgeRegistration,
17
+ } from "./providers/claude-bridge/register.ts";
13
18
  import { areaForTool, classifyFailure, diagnosticEvidence, diagnosticSummary, type Diagnostic } from "./diagnostics.ts";
14
19
  import {
15
20
  MAX_CONTENT_CHARS,
@@ -166,6 +171,7 @@ export default function piMeshExtension(pi: ExtensionAPI): void | Promise<void>
166
171
  let client: HubClient | undefined;
167
172
  let nousReport: NousRegistrationReport | undefined;
168
173
  let antigravityReport: AntigravityRegistration | undefined;
174
+ let claudeBridgeReport: ClaudeBridgeRegistration | undefined;
169
175
  let pending: MessageRecord[] = [];
170
176
  let activatingInbound: MessageRecord | undefined;
171
177
  let awaitingActivation: MessageRecord | undefined;
@@ -648,6 +654,8 @@ export default function piMeshExtension(pi: ExtensionAPI): void | Promise<void>
648
654
  shuttingDown = false;
649
655
  const antigravityNotice = antigravityRegistrationNotice(antigravityReport, pi);
650
656
  if (antigravityNotice) ctx.ui.notify(antigravityNotice.message, antigravityNotice.type);
657
+ const claudeBridgeNotice = claudeBridgeRegistrationNotice(claudeBridgeReport, pi);
658
+ if (claudeBridgeNotice) ctx.ui.notify(claudeBridgeNotice.message, claudeBridgeNotice.type);
651
659
  if (nousReport?.guidance.length) {
652
660
  for (const item of nousReport.guidance) {
653
661
  ctx.ui.notify(item.message, item.level);
@@ -933,6 +941,7 @@ export default function piMeshExtension(pi: ExtensionAPI): void | Promise<void>
933
941
  });
934
942
 
935
943
  antigravityReport = registerAntigravityProvider(pi);
944
+ claudeBridgeReport = registerClaudeBridgeProvider(pi);
936
945
  return nousFactoryWork(pi, (report) => {
937
946
  nousReport = report;
938
947
  });
@@ -7,7 +7,7 @@ import { AGENT_COMMANDS_MAP, enforceToolPolicy, getMcpTools, reconcileInbox } fr
7
7
  import { deliverInboxNotification } from "./inbox.ts";
8
8
  import type { HubEvent, MessageRecord } from "./protocol.ts";
9
9
 
10
- const VERSION = "0.7.17";
10
+ const VERSION = "0.7.18";
11
11
  const inbox = new Map<string, MessageRecord>();
12
12
  const notifiedInbox = new Set<string>();
13
13
  let meshClient: HubClient | undefined;
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Eli Dickinson
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,18 @@
1
+ # Claude-bridge provider (vendored)
2
+
3
+ Provider-only subset of `pi-claude-bridge` 0.7.0, built into the kxm plugin.
4
+
5
+ - Upstream: [elidickinson/pi-claude-bridge](https://github.com/elidickinson/pi-claude-bridge)
6
+ - npm: `pi-claude-bridge@0.7.0`
7
+ - License: MIT, Copyright (c) 2026 Eli Dickinson — see `LICENSE`
8
+ - Author: Eli Dickinson
9
+
10
+ The Pi provider id remains `claude-bridge` so existing `claude login` /
11
+ subscription credentials carry over. This slice vendors model registration
12
+ (Opus/Sonnet/Haiku/Fable ids the plugin actually registers), Anthropic Agent
13
+ SDK streaming, thinking/effort mapping, and the in-process MCP bridge that
14
+ exposes Pi tools to Claude Code.
15
+
16
+ Not vendored here: the AskClaude tool, user-facing MCP/UI panels, TUI extras,
17
+ session JSONL rebuild (`cc-session-io`), and skills/prompt-capture forwarding.
18
+ No `@earendil-works/pi-ai` import.
@@ -0,0 +1,53 @@
1
+ import { existsSync, readFileSync } from "node:fs";
2
+ import { homedir } from "node:os";
3
+ import { join } from "node:path";
4
+ import type { LongContextSettings } from "./models.ts";
5
+
6
+ export interface ClaudeBridgeConfig {
7
+ provider?: {
8
+ strictMcpConfig?: boolean;
9
+ autoMemoryEnabled?: boolean;
10
+ pathToClaudeCodeExecutable?: string;
11
+ plan?: "pro" | "max";
12
+ longContextExtraUsage?: boolean;
13
+ };
14
+ }
15
+
16
+ export function tryParseJson(path: string): Partial<ClaudeBridgeConfig> {
17
+ if (!existsSync(path)) return {};
18
+ try {
19
+ return JSON.parse(readFileSync(path, "utf-8")) as Partial<ClaudeBridgeConfig>;
20
+ } catch (error) {
21
+ console.error(`claude-bridge: failed to parse ${path}: ${error}`);
22
+ return {};
23
+ }
24
+ }
25
+
26
+ export function globalConfigPath(home = homedir()): string {
27
+ return join(home, ".pi", "agent", "claude-bridge.json");
28
+ }
29
+
30
+ export function projectConfigPath(cwd: string): string {
31
+ return join(cwd, ".pi", "claude-bridge.json");
32
+ }
33
+
34
+ export function loadConfig(cwd: string, home = homedir()): ClaudeBridgeConfig {
35
+ const global = tryParseJson(globalConfigPath(home));
36
+ const project = tryParseJson(projectConfigPath(cwd));
37
+ return {
38
+ provider: { ...global.provider, ...project.provider },
39
+ };
40
+ }
41
+
42
+ export function longContextFromConfig(config: ClaudeBridgeConfig): LongContextSettings {
43
+ return {
44
+ plan: config.provider?.plan === "max" ? "max" : "pro",
45
+ longContextExtraUsage: Boolean(config.provider?.longContextExtraUsage),
46
+ };
47
+ }
48
+
49
+ export function claudeCodeSettings(provider: ClaudeBridgeConfig["provider"] = {}): {
50
+ autoMemoryEnabled: boolean;
51
+ } {
52
+ return { autoMemoryEnabled: provider.autoMemoryEnabled ?? false };
53
+ }