@agentprojectcontext/apx 1.53.0 → 1.53.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/package.json
CHANGED
package/src/core/mcp/runner.js
CHANGED
|
@@ -211,6 +211,37 @@ function sanitizeHeaders(h) {
|
|
|
211
211
|
return out;
|
|
212
212
|
}
|
|
213
213
|
|
|
214
|
+
function redactHeaderValue(key, value) {
|
|
215
|
+
const k = String(key || "").toLowerCase();
|
|
216
|
+
if (
|
|
217
|
+
k === "authorization" ||
|
|
218
|
+
k === "proxy-authorization" ||
|
|
219
|
+
k.includes("token") ||
|
|
220
|
+
k.includes("secret") ||
|
|
221
|
+
k.includes("key")
|
|
222
|
+
) {
|
|
223
|
+
return "[redacted]";
|
|
224
|
+
}
|
|
225
|
+
const s = String(value ?? "");
|
|
226
|
+
return s.length > 96 ? `${s.slice(0, 24)}...${s.slice(-12)}` : s;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
function redactHeaders(headers) {
|
|
230
|
+
const out = {};
|
|
231
|
+
for (const [k, v] of Object.entries(headers || {})) {
|
|
232
|
+
out[k] = redactHeaderValue(k, v);
|
|
233
|
+
}
|
|
234
|
+
return out;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
function summarizeRpcBody(method, params) {
|
|
238
|
+
return JSON.stringify({
|
|
239
|
+
jsonrpc: "2.0",
|
|
240
|
+
method,
|
|
241
|
+
params_keys: params && typeof params === "object" ? Object.keys(params) : [],
|
|
242
|
+
});
|
|
243
|
+
}
|
|
244
|
+
|
|
214
245
|
class HttpMcpClient {
|
|
215
246
|
constructor({ name, url, headers = {} }) {
|
|
216
247
|
this.name = name;
|
|
@@ -220,6 +251,7 @@ class HttpMcpClient {
|
|
|
220
251
|
this._nextId = 1;
|
|
221
252
|
this._initialized = false;
|
|
222
253
|
this._initPromise = null;
|
|
254
|
+
this.sessionId = null;
|
|
223
255
|
this.logs = [];
|
|
224
256
|
this.startedAt = null;
|
|
225
257
|
this.lastError = null;
|
|
@@ -230,23 +262,32 @@ class HttpMcpClient {
|
|
|
230
262
|
if (this.logs.length > LOG_CAP) this.logs.shift();
|
|
231
263
|
}
|
|
232
264
|
|
|
265
|
+
_requestHeaders({ accept = "application/json, text/event-stream" } = {}) {
|
|
266
|
+
return {
|
|
267
|
+
"Content-Type": "application/json",
|
|
268
|
+
Accept: accept,
|
|
269
|
+
"MCP-Protocol-Version": "2024-11-05",
|
|
270
|
+
...(this.sessionId ? { "Mcp-Session-Id": this.sessionId } : {}),
|
|
271
|
+
...this.headers,
|
|
272
|
+
};
|
|
273
|
+
}
|
|
274
|
+
|
|
233
275
|
async _rpc(method, params, timeoutMs = DEFAULT_TIMEOUT_MS) {
|
|
234
276
|
if (!this.startedAt) this.startedAt = nowIso();
|
|
235
277
|
const id = this._nextId++;
|
|
236
278
|
const body = JSON.stringify({ jsonrpc: "2.0", id, method, params });
|
|
237
279
|
const ctrl = new AbortController();
|
|
238
280
|
const timer = setTimeout(() => ctrl.abort(), timeoutMs);
|
|
239
|
-
this.
|
|
281
|
+
const headers = this._requestHeaders();
|
|
282
|
+
this._log(
|
|
283
|
+
"info",
|
|
284
|
+
`POST ${method} headers=${JSON.stringify(redactHeaders(headers))} body=${summarizeRpcBody(method, params)}`
|
|
285
|
+
);
|
|
240
286
|
let res;
|
|
241
287
|
try {
|
|
242
288
|
res = await fetch(this.url, {
|
|
243
289
|
method: "POST",
|
|
244
|
-
headers
|
|
245
|
-
"Content-Type": "application/json",
|
|
246
|
-
Accept: "application/json, text/event-stream",
|
|
247
|
-
"MCP-Protocol-Version": "2024-11-05",
|
|
248
|
-
...this.headers,
|
|
249
|
-
},
|
|
290
|
+
headers,
|
|
250
291
|
body,
|
|
251
292
|
signal: ctrl.signal,
|
|
252
293
|
});
|
|
@@ -258,6 +299,11 @@ class HttpMcpClient {
|
|
|
258
299
|
clearTimeout(timer);
|
|
259
300
|
}
|
|
260
301
|
const contentType = res.headers.get("content-type") || "";
|
|
302
|
+
const sessionId = res.headers.get("mcp-session-id");
|
|
303
|
+
if (sessionId) {
|
|
304
|
+
this.sessionId = sessionId;
|
|
305
|
+
this._log("info", `session ${sessionId}`);
|
|
306
|
+
}
|
|
261
307
|
const text = await res.text();
|
|
262
308
|
if (!res.ok) {
|
|
263
309
|
this.lastError = `HTTP ${res.status}`;
|
|
@@ -306,14 +352,14 @@ class HttpMcpClient {
|
|
|
306
352
|
);
|
|
307
353
|
// Best-effort notification — many servers ignore this for HTTP.
|
|
308
354
|
try {
|
|
355
|
+
const headers = this._requestHeaders({ accept: "application/json" });
|
|
356
|
+
this._log(
|
|
357
|
+
"info",
|
|
358
|
+
`POST notifications/initialized headers=${JSON.stringify(redactHeaders(headers))} body=${summarizeRpcBody("notifications/initialized", {})}`
|
|
359
|
+
);
|
|
309
360
|
await fetch(this.url, {
|
|
310
361
|
method: "POST",
|
|
311
|
-
headers
|
|
312
|
-
"Content-Type": "application/json",
|
|
313
|
-
Accept: "application/json",
|
|
314
|
-
"MCP-Protocol-Version": "2024-11-05",
|
|
315
|
-
...this.headers,
|
|
316
|
-
},
|
|
362
|
+
headers,
|
|
317
363
|
body: JSON.stringify({
|
|
318
364
|
jsonrpc: "2.0",
|
|
319
365
|
method: "notifications/initialized",
|
|
@@ -349,6 +395,7 @@ class HttpMcpClient {
|
|
|
349
395
|
stop() {
|
|
350
396
|
this._initialized = false;
|
|
351
397
|
this._initPromise = null;
|
|
398
|
+
this.sessionId = null;
|
|
352
399
|
}
|
|
353
400
|
}
|
|
354
401
|
|
|
@@ -24,6 +24,7 @@ import {
|
|
|
24
24
|
} from "../../desktop-ws.js";
|
|
25
25
|
import { runSuperAgent, isSuperAgentEnabled } from "#core/agent/super-agent.js";
|
|
26
26
|
import { appendGlobalMessage } from "#core/stores/messages.js";
|
|
27
|
+
import { stripEmotionTags } from "#core/voice/emotions.js";
|
|
27
28
|
import { CHANNELS } from "#core/constants/channels.js";
|
|
28
29
|
import { tryResolveSkillCommand } from "#core/agent/skills/trigger.js";
|
|
29
30
|
|
|
@@ -120,7 +121,9 @@ async function _handleMessage({ ws, text, previousMessages }, { projects, config
|
|
|
120
121
|
if (!seg || seg === lastSegText) return;
|
|
121
122
|
lastSegText = seg;
|
|
122
123
|
emittedSegments.push(seg);
|
|
123
|
-
|
|
124
|
+
// `text` is what the bubble shows (no [tags]); `speak` keeps the inline
|
|
125
|
+
// emotion tags so the renderer's per-segment TTS can use them.
|
|
126
|
+
_send(ws, { type: "segment", seq: ++segSeq, text: stripEmotionTags(seg), speak: seg });
|
|
124
127
|
};
|
|
125
128
|
|
|
126
129
|
try {
|
|
@@ -178,7 +181,9 @@ async function _handleMessage({ ws, text, previousMessages }, { projects, config
|
|
|
178
181
|
// the closing segment (deduped against the last one).
|
|
179
182
|
emitSegment((result.text || "").trim() || liveBuf.trim());
|
|
180
183
|
|
|
181
|
-
|
|
184
|
+
// Emotion tags are a TTS-only signal — strip them from the text we display,
|
|
185
|
+
// persist, and feed back as conversation context.
|
|
186
|
+
const finalText = stripEmotionTags(emittedSegments.join("\n\n"));
|
|
182
187
|
log(`desktop: super-agent turn done in ${Date.now() - t0}ms segments=${segSeq} text_len=${finalText.length} tools=${toolsExecuted.length}`);
|
|
183
188
|
|
|
184
189
|
// Turn end. `segments` lets the renderer know how many bubbles to expect.
|
|
@@ -1187,8 +1187,10 @@
|
|
|
1187
1187
|
appendTurn(m, true);
|
|
1188
1188
|
queueRegisterSegment(m);
|
|
1189
1189
|
// Synthesize THIS segment; tts-ready(seg=id) attaches its audio + queues
|
|
1190
|
-
// it for gapless sequential playback.
|
|
1191
|
-
|
|
1190
|
+
// it for gapless sequential playback. `speak` carries the inline emotion
|
|
1191
|
+
// tags (the bubble `text` has them stripped) so a tag-aware engine like
|
|
1192
|
+
// QVox can act on them; falls back to the visible text.
|
|
1193
|
+
window.apx?.requestTts?.(msg.speak || text, id);
|
|
1192
1194
|
requestWindowResize();
|
|
1193
1195
|
scrollConvToBottom();
|
|
1194
1196
|
break;
|
|
@@ -2236,9 +2236,9 @@
|
|
|
2236
2236
|
}
|
|
2237
2237
|
},
|
|
2238
2238
|
"node_modules/caniuse-lite": {
|
|
2239
|
-
"version": "1.0.
|
|
2240
|
-
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.
|
|
2241
|
-
"integrity": "sha512-
|
|
2239
|
+
"version": "1.0.30001800",
|
|
2240
|
+
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001800.tgz",
|
|
2241
|
+
"integrity": "sha512-MMHtuAz9Ys840zAY5F4k6fV5GaivZ9sPk+nz0mY+GYVzRBnYkN0mpqkSR92oWRQ19yQWo4HvBV/FnC16AJX8MA==",
|
|
2242
2242
|
"dev": true,
|
|
2243
2243
|
"funding": [
|
|
2244
2244
|
{
|
|
@@ -2598,9 +2598,9 @@
|
|
|
2598
2598
|
"license": "MIT"
|
|
2599
2599
|
},
|
|
2600
2600
|
"node_modules/electron-to-chromium": {
|
|
2601
|
-
"version": "1.5.
|
|
2602
|
-
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.
|
|
2603
|
-
"integrity": "sha512-
|
|
2601
|
+
"version": "1.5.382",
|
|
2602
|
+
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.382.tgz",
|
|
2603
|
+
"integrity": "sha512-8ETaWbV6SZOrno+G93Ffd9ENsMtetqdnqj4nlfxFW90Sm5GgnuV28Kf62hqQVD6VUgzm7qFQKsTsAPmeUiU3Ug==",
|
|
2604
2604
|
"dev": true,
|
|
2605
2605
|
"license": "ISC"
|
|
2606
2606
|
},
|