@aexol/spectral 0.1.1 → 0.1.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/dist/server/pi-bridge.js +67 -15
- package/package.json +2 -1
package/dist/server/pi-bridge.js
CHANGED
|
@@ -48,8 +48,11 @@
|
|
|
48
48
|
* conversations within a single WS connection work normally.
|
|
49
49
|
*/
|
|
50
50
|
import { AuthStorage, createAgentSession, DefaultResourceLoader, ModelRegistry, SessionManager, } from "@mariozechner/pi-coding-agent";
|
|
51
|
-
import {
|
|
51
|
+
import { createJiti } from "@mariozechner/jiti";
|
|
52
52
|
import { randomUUID } from "node:crypto";
|
|
53
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
54
|
+
import { dirname, resolve } from "node:path";
|
|
55
|
+
import { fileURLToPath } from "node:url";
|
|
53
56
|
import aexolMcpExtension from "../extensions/aexol-mcp.js";
|
|
54
57
|
import { fetchAllowedModels as defaultFetchAllowedModels, } from "../relay/models-fetch.js";
|
|
55
58
|
/**
|
|
@@ -87,6 +90,41 @@ function extractTextFromContent(content) {
|
|
|
87
90
|
}
|
|
88
91
|
return out;
|
|
89
92
|
}
|
|
93
|
+
/**
|
|
94
|
+
* Resolve the entry point of the pi-mcp-adapter extension (index.ts)
|
|
95
|
+
* by walking up from this file's location through node_modules.
|
|
96
|
+
* Returns the absolute path, or null if the package is not installed.
|
|
97
|
+
*/
|
|
98
|
+
function resolveMcpAdapterEntry() {
|
|
99
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
100
|
+
const rel = "node_modules/pi-mcp-adapter/package.json";
|
|
101
|
+
const root = "/";
|
|
102
|
+
let dir = __dirname;
|
|
103
|
+
for (let i = 0; i < 20; i++) {
|
|
104
|
+
const pkgPath = resolve(dir, rel);
|
|
105
|
+
try {
|
|
106
|
+
const raw = readFileSync(pkgPath, "utf8");
|
|
107
|
+
const pkg = JSON.parse(raw);
|
|
108
|
+
const extRel = pkg.pi?.extensions?.[0];
|
|
109
|
+
if (extRel) {
|
|
110
|
+
return resolve(dirname(pkgPath), extRel);
|
|
111
|
+
}
|
|
112
|
+
// Package found but no pi.extensions — try index.ts as fallback
|
|
113
|
+
const indexTs = resolve(dirname(pkgPath), "index.ts");
|
|
114
|
+
if (existsSync(indexTs))
|
|
115
|
+
return indexTs;
|
|
116
|
+
break;
|
|
117
|
+
}
|
|
118
|
+
catch {
|
|
119
|
+
// package.json not readable at this level, keep walking up
|
|
120
|
+
}
|
|
121
|
+
const parent = dirname(dir);
|
|
122
|
+
if (parent === dir || parent === root)
|
|
123
|
+
break;
|
|
124
|
+
dir = parent;
|
|
125
|
+
}
|
|
126
|
+
return null;
|
|
127
|
+
}
|
|
90
128
|
export class PiBridge {
|
|
91
129
|
session;
|
|
92
130
|
unsubscribe;
|
|
@@ -117,23 +155,25 @@ export class PiBridge {
|
|
|
117
155
|
async start() {
|
|
118
156
|
if (this.disposed)
|
|
119
157
|
throw new Error("PiBridge already disposed");
|
|
120
|
-
// Build extension factories. Always include the Aexol MCP extension;
|
|
121
|
-
// dynamically load the pi-mcp-adapter (standard MCP servers) with
|
|
122
|
-
// graceful degradation when the package is not installed.
|
|
123
158
|
const extensionFactories = [aexolMcpExtension];
|
|
124
|
-
//
|
|
125
|
-
//
|
|
126
|
-
//
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
159
|
+
// Load pi-mcp-adapter via jiti so tsc never crawls its .ts files in
|
|
160
|
+
// node_modules. The static `import` was causing tsc to type-check
|
|
161
|
+
// pi-mcp-adapter's source and fail the build on its type errors.
|
|
162
|
+
// jiti is the same loader pi uses internally for all extensions.
|
|
163
|
+
const mcpAdapterPath = resolveMcpAdapterEntry();
|
|
164
|
+
if (mcpAdapterPath) {
|
|
165
|
+
try {
|
|
166
|
+
const jiti = createJiti(import.meta.url, { moduleCache: false });
|
|
167
|
+
const mcpAdapterFactory = await jiti.import(mcpAdapterPath, { default: true });
|
|
168
|
+
if (typeof mcpAdapterFactory === "function") {
|
|
169
|
+
extensionFactories.push(async (pi) => mcpAdapterFactory(pi));
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
catch {
|
|
173
|
+
console.info("[PiBridge] pi-mcp-adapter not found; standard MCP servers disabled.");
|
|
134
174
|
}
|
|
135
175
|
}
|
|
136
|
-
|
|
176
|
+
else {
|
|
137
177
|
console.info("[PiBridge] pi-mcp-adapter not found; standard MCP servers disabled.");
|
|
138
178
|
}
|
|
139
179
|
// ResourceLoader with extensions wired in via factories.
|
|
@@ -189,6 +229,18 @@ export class PiBridge {
|
|
|
189
229
|
modelRegistry: this.modelRegistry,
|
|
190
230
|
});
|
|
191
231
|
this.session = result.session;
|
|
232
|
+
// Emit session_start so extensions can initialize (e.g. pi-mcp-adapter
|
|
233
|
+
// connects to MCP servers, loads configs from ~/.config/mcp/mcp.json etc.).
|
|
234
|
+
// bindExtensions also fires resources_discover for dynamic skill/prompt
|
|
235
|
+
// registration. No UI/command context needed in serve mode.
|
|
236
|
+
try {
|
|
237
|
+
await this.session.bindExtensions({});
|
|
238
|
+
console.info("[PiBridge] session_start emitted; extensions initialized.");
|
|
239
|
+
}
|
|
240
|
+
catch (err) {
|
|
241
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
242
|
+
console.warn(`[PiBridge] session_start failed (extension init error): ${msg}`);
|
|
243
|
+
}
|
|
192
244
|
// Subscribe BEFORE any prompt fires.
|
|
193
245
|
this.unsubscribe = this.session.subscribe((ev) => this.handleEvent(ev));
|
|
194
246
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aexol/spectral",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"description": "Always-on coding agent for Aexol — branded pi wrapper with relay-based browser access.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"private": false,
|
|
@@ -51,6 +51,7 @@
|
|
|
51
51
|
},
|
|
52
52
|
"dependencies": {
|
|
53
53
|
"@inquirer/prompts": "^7.2.0",
|
|
54
|
+
"@mariozechner/jiti": "^2.6.5",
|
|
54
55
|
"@mariozechner/pi-coding-agent": "^0.70.2",
|
|
55
56
|
"better-sqlite3": "^12.9.0",
|
|
56
57
|
"pi-mcp-adapter": "^2.5.4",
|