@cydm/pie 2.5.1 → 2.6.0
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/builtin/extensions/ask-user/index.js +3 -3
- package/dist/builtin/extensions/computer-use/index.js +17 -2
- package/dist/builtin/extensions/computer-use/prebuilt/macos/arm64/pie-computer-use +0 -0
- package/dist/builtin/extensions/computer-use/prebuilt/macos/universal/pie-computer-use.app/Contents/MacOS/pie-computer-use +0 -0
- package/dist/builtin/extensions/computer-use/prebuilt/macos/x64/pie-computer-use +0 -0
- package/dist/builtin/extensions/computer-use/scripts/setup-helper.mjs +90 -9
- package/dist/builtin/extensions/mcp-adapter/index.js +135 -27
- package/dist/builtin/extensions/plan-mode/index.js +3 -3
- package/dist/builtin/extensions/subagent/index.js +8 -5
- package/dist/builtin/extensions/todo/index.js +3 -3
- package/dist/builtin/skills/chrome-devtools-axi/chrome-devtools-axi-bridge.js +199 -40
- package/dist/builtin/skills/chrome-devtools-axi/chrome-devtools-axi-cli.js +5 -2
- package/dist/builtin/skills/chrome-devtools-axi/chrome-devtools-axi-runtime.js +1 -1
- package/dist/builtin/skills/chrome-devtools-axi/{cli-P4VG6ZZG.js → cli-GB37NZHQ.js} +78 -29
- package/dist/builtin/skills/tui-use/SKILL.md +44 -0
- package/dist/builtin/skills/tui-use/tui-use-cli.cjs +40 -16
- package/dist/builtin/skills/tui-use/tui-use-daemon.cjs +7 -1
- package/dist/chunks/{chunk-REP6QANY.js → chunk-AZ336HKF.js} +405 -70
- package/dist/chunks/{chunk-N2MK46AE.js → chunk-G6KCJA6B.js} +7 -2
- package/dist/chunks/{chunk-YRXXRLMQ.js → chunk-O2DKMLNX.js} +152 -8
- package/dist/chunks/{chunk-ZKHMNEXL.js → chunk-Y4CYXJR7.js} +27 -2
- package/dist/chunks/src-VCWCE7YV.js +20 -0
- package/dist/chunks/{test-stream-OD3B57AS.js → test-stream-GOSEWMJ3.js} +1 -1
- package/dist/cli.js +67 -17
- package/package.json +2 -2
- package/dist/chunks/src-SXUQ7OY6.js +0 -14
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { createRequire as __createRequire } from "node:module"; const require = __createRequire(import.meta.url);
|
|
2
2
|
import {
|
|
3
3
|
createAskUserCapability
|
|
4
|
-
} from "../../../chunks/chunk-
|
|
5
|
-
import "../../../chunks/chunk-
|
|
6
|
-
import "../../../chunks/chunk-
|
|
4
|
+
} from "../../../chunks/chunk-AZ336HKF.js";
|
|
5
|
+
import "../../../chunks/chunk-Y4CYXJR7.js";
|
|
6
|
+
import "../../../chunks/chunk-O2DKMLNX.js";
|
|
7
7
|
import "../../../chunks/chunk-XXGYUYXI.js";
|
|
8
8
|
import "../../../chunks/chunk-LZQXQOPJ.js";
|
|
9
9
|
|
|
@@ -3787,8 +3787,23 @@ function wireableInputDescendants(node) {
|
|
|
3787
3787
|
visit(node);
|
|
3788
3788
|
return matches;
|
|
3789
3789
|
}
|
|
3790
|
+
var FOCUS_CHANGING_KEYS = /* @__PURE__ */ new Set(["TAB", "SHIFT+TAB", "ENTER", "RETURN", "SPACE", "UP", "DOWN", "LEFT", "RIGHT", "UP_ARROW", "DOWN_ARROW", "LEFT_ARROW", "RIGHT_ARROW", "ESC", "ESCAPE", "HOME", "END", "PAGE_UP", "PAGE_DOWN", "PAGEDOWN", "PAGEUP"]);
|
|
3791
|
+
function isFocusChangingKey(keys2) {
|
|
3792
|
+
const list = typeof keys2 === "string" ? [keys2] : Array.isArray(keys2) ? keys2 : [];
|
|
3793
|
+
for (const raw of list) {
|
|
3794
|
+
if (typeof raw !== "string") continue;
|
|
3795
|
+
const token = raw.trim().toUpperCase().split("+").pop() ?? "";
|
|
3796
|
+
if (FOCUS_CHANGING_KEYS.has(token) || FOCUS_CHANGING_KEYS.has(raw.trim().toUpperCase())) return true;
|
|
3797
|
+
}
|
|
3798
|
+
return false;
|
|
3799
|
+
}
|
|
3790
3800
|
function recordActionFocus(action, state, node, coordinateFocus = false) {
|
|
3791
|
-
if (
|
|
3801
|
+
if (action.action === "keypress" && !action.ref && isFocusChangingKey(action.keys)) {
|
|
3802
|
+
state.currentFocus = true;
|
|
3803
|
+
state.focusRef = void 0;
|
|
3804
|
+
return;
|
|
3805
|
+
}
|
|
3806
|
+
if (!["click", "press", "keypress", "typeText"].includes(action.action) || !action.ref && action.action !== "click" && action.action !== "press" && !coordinateFocus) return;
|
|
3792
3807
|
state.currentFocus = Boolean(node?.isTextInput && !node.pictureOnly) || coordinateFocus;
|
|
3793
3808
|
state.focusRef = node?.isTextInput && node.wireRef && !node.pictureOnly ? node.ref : void 0;
|
|
3794
3809
|
if (!state.currentFocus && node && !node.pictureOnly && action.ref && (action.action === "click" || action.action === "press") && containsEditable(node)) {
|
|
@@ -8546,7 +8561,7 @@ async function dispatchUiAction(action, target, look, headless, state, signal) {
|
|
|
8546
8561
|
}
|
|
8547
8562
|
const trace = await helperAct(target, prepared, headless, signal);
|
|
8548
8563
|
if (!headless) {
|
|
8549
|
-
const coordinateFocus = prepared.action === "click" && "x" in prepared.target;
|
|
8564
|
+
const coordinateFocus = (prepared.action === "click" || prepared.action === "press") && "x" in prepared.target;
|
|
8550
8565
|
const node = action.ref ? outlineNodeByRef(action.ref.trim()) : coordinateFocus ? editorAtPoint(currentOutlineOrThrow().nodes, action.x, action.y) : void 0;
|
|
8551
8566
|
recordActionFocus(action, state, node, coordinateFocus);
|
|
8552
8567
|
}
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -313,19 +313,100 @@ async function installPrebuiltHelperApp(sourceAppPath) {
|
|
|
313
313
|
const existingInfo = await fs.readFile(path.join(helperAppPath, "Contents", "Info.plist"), "utf8").catch(() => undefined);
|
|
314
314
|
const sourceInfo = await fs.readFile(sourceInfoPath, "utf8");
|
|
315
315
|
if (existingExecutable?.equals(sourceExecutable) && existingInfo === sourceInfo) {
|
|
316
|
-
|
|
317
|
-
|
|
316
|
+
// Byte equality alone is NOT sufficient for the no-change shortcut: a
|
|
317
|
+
// damaged/missing _CodeSignature (CodeResources tampered or deleted
|
|
318
|
+
// around an otherwise-identical executable) would otherwise survive
|
|
319
|
+
// every repair invocation. The existing bundle must still verify.
|
|
320
|
+
let existingVerifies = false;
|
|
321
|
+
try {
|
|
322
|
+
await run("codesign", ["--verify", "--strict", helperAppPath]);
|
|
323
|
+
existingVerifies = true;
|
|
324
|
+
} catch {
|
|
325
|
+
// Fall through to the replacement path below, which re-installs (and
|
|
326
|
+
// re-verifies) a complete bundle.
|
|
327
|
+
}
|
|
328
|
+
if (existingVerifies) {
|
|
329
|
+
await registerHelperApp();
|
|
330
|
+
return false;
|
|
331
|
+
}
|
|
318
332
|
}
|
|
319
333
|
// The sealed bundle must arrive intact — a broken signature would burn
|
|
320
334
|
// the user's TCC grants on an identity that can never validate.
|
|
321
335
|
await run("codesign", ["--verify", "--strict", sourceAppPath]);
|
|
322
|
-
|
|
323
|
-
//
|
|
324
|
-
//
|
|
325
|
-
//
|
|
326
|
-
//
|
|
327
|
-
|
|
328
|
-
|
|
336
|
+
// Sweep staging directories abandoned by crashed installers (the finally
|
|
337
|
+
// below only runs on ordinary unwinding). Reclaim is ownership-aware:
|
|
338
|
+
// the staging name embeds its creator's PID, and ONLY a demonstrably dead
|
|
339
|
+
// owner (ESRCH on signal-0) plus age beyond a generous slow-install window
|
|
340
|
+
// makes a stage garbage — mtime alone is not ownership evidence, so a
|
|
341
|
+
// live/slow installer's stage is never touched.
|
|
342
|
+
try {
|
|
343
|
+
const parent = path.dirname(helperAppPath);
|
|
344
|
+
const base = path.basename(helperAppPath);
|
|
345
|
+
const entries = await fs.readdir(parent);
|
|
346
|
+
const cutoff = Date.now() - 60 * 60 * 1000;
|
|
347
|
+
for (const entry of entries) {
|
|
348
|
+
// Exact staging format <app>.staged-<pid>-<ts36>: anything else that
|
|
349
|
+
// merely contains ".staged-" is not ours to touch.
|
|
350
|
+
const match = new RegExp(`^${base.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}\\.staged-(\\d+)-[0-9a-z]+$`).exec(entry);
|
|
351
|
+
if (!match) continue;
|
|
352
|
+
const staged = path.join(parent, entry);
|
|
353
|
+
try {
|
|
354
|
+
const stat = await fs.stat(staged);
|
|
355
|
+
if (stat.mtimeMs >= cutoff) continue;
|
|
356
|
+
const ownerPid = Number(match[1]);
|
|
357
|
+
let ownerAlive = false;
|
|
358
|
+
try {
|
|
359
|
+
process.kill(ownerPid, 0);
|
|
360
|
+
ownerAlive = true;
|
|
361
|
+
} catch (error) {
|
|
362
|
+
// ESRCH: dead. EPERM (exists, other user): treat as alive —
|
|
363
|
+
// conservative, never delete on unknown liveness.
|
|
364
|
+
ownerAlive = error && error.code === "EPERM";
|
|
365
|
+
}
|
|
366
|
+
if (!ownerAlive) await fs.rm(staged, { force: true, recursive: true });
|
|
367
|
+
} catch { /* raced away */ }
|
|
368
|
+
}
|
|
369
|
+
} catch { /* no parent dir yet */ }
|
|
370
|
+
// Stage-then-swap: the staged copy is verified before publication and the
|
|
371
|
+
// previous installation survives every failure up to the final swap.
|
|
372
|
+
// NOTE: the swap itself (rm + rename) is NOT atomic — directory bundles
|
|
373
|
+
// have no atomic exchange on stock Node — but the failure window no longer
|
|
374
|
+
// starts before verification, and a crash mid-swap self-heals on the next
|
|
375
|
+
// run (which re-stages from the verified source).
|
|
376
|
+
const stagingPath = `${helperAppPath}.staged-${process.pid}-${Date.now().toString(36)}`;
|
|
377
|
+
await fs.rm(stagingPath, { force: true, recursive: true });
|
|
378
|
+
try {
|
|
379
|
+
// ditto preserves the bundle byte-for-byte (signature + stapled
|
|
380
|
+
// notarization ticket). The sealed app is NEVER re-signed here: its
|
|
381
|
+
// Developer ID designated requirement (identifier + team) is exactly
|
|
382
|
+
// what gives release builds their best chance of retaining TCC grants.
|
|
383
|
+
await run("/usr/bin/ditto", [sourceAppPath, stagingPath]);
|
|
384
|
+
// Verify the STAGED bundle (not just the source): source mutation
|
|
385
|
+
// between the verify above and the copy, or a torn copy, stops here.
|
|
386
|
+
await run("codesign", ["--verify", "--strict", stagingPath]);
|
|
387
|
+
let published = false;
|
|
388
|
+
try {
|
|
389
|
+
await fs.rm(helperAppPath, { force: true, recursive: true });
|
|
390
|
+
await fs.rename(stagingPath, helperAppPath);
|
|
391
|
+
published = true;
|
|
392
|
+
} catch (renameError) {
|
|
393
|
+
// Cross-device or otherwise unrenamable staging: fall back to a
|
|
394
|
+
// second ditto onto the final path, then verify the destination. A
|
|
395
|
+
// VERIFIED fallback is a successful installation — continue to
|
|
396
|
+
// registration instead of failing after doing the work.
|
|
397
|
+
try {
|
|
398
|
+
await run("/usr/bin/ditto", [stagingPath, helperAppPath]);
|
|
399
|
+
await run("codesign", ["--verify", "--strict", helperAppPath]);
|
|
400
|
+
published = true;
|
|
401
|
+
} catch (fallbackError) {
|
|
402
|
+
fallbackError.cause = renameError;
|
|
403
|
+
throw fallbackError;
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
if (published) await registerHelperApp();
|
|
407
|
+
} finally {
|
|
408
|
+
await fs.rm(stagingPath, { force: true, recursive: true }).catch(() => {});
|
|
409
|
+
}
|
|
329
410
|
return true;
|
|
330
411
|
}
|
|
331
412
|
|
|
@@ -24434,6 +24434,7 @@ var StdioClientTransport = class {
|
|
|
24434
24434
|
};
|
|
24435
24435
|
|
|
24436
24436
|
// builtin/extensions/mcp-adapter/src/server-manager.ts
|
|
24437
|
+
import { createHash } from "node:crypto";
|
|
24437
24438
|
import * as fs2 from "node:fs";
|
|
24438
24439
|
import * as path2 from "node:path";
|
|
24439
24440
|
var CONNECT_TIMEOUT_MS = 3e4;
|
|
@@ -24442,6 +24443,56 @@ var PACKAGE_MANAGER_COMMANDS = /* @__PURE__ */ new Set(["npx", "npm", "bunx", "u
|
|
|
24442
24443
|
var METADATA_TTL_MS = 30 * 24 * 60 * 60 * 1e3;
|
|
24443
24444
|
var CALL_TIMEOUT_MS = 12e4;
|
|
24444
24445
|
var STDERR_TAIL_LIMIT = 4e3;
|
|
24446
|
+
var DIAGNOSTIC_TEXT_LIMIT = 1500;
|
|
24447
|
+
function definitionSecrets(definition) {
|
|
24448
|
+
const secrets = [];
|
|
24449
|
+
for (const value of Object.values(definition.env ?? {})) {
|
|
24450
|
+
if (typeof value === "string" && value.length > 0) secrets.push(value);
|
|
24451
|
+
}
|
|
24452
|
+
for (const value of Object.values(definition.headers ?? {})) {
|
|
24453
|
+
if (typeof value === "string" && value.length > 0) secrets.push(value);
|
|
24454
|
+
}
|
|
24455
|
+
return secrets.sort((a, b) => b.length - a.length);
|
|
24456
|
+
}
|
|
24457
|
+
function redactSecrets(text, secrets) {
|
|
24458
|
+
let sanitized = text;
|
|
24459
|
+
for (const secret of secrets) {
|
|
24460
|
+
sanitized = sanitized.split(secret).join("[redacted]");
|
|
24461
|
+
}
|
|
24462
|
+
return sanitized;
|
|
24463
|
+
}
|
|
24464
|
+
function redactLeadingSecretSuffix(text, secrets) {
|
|
24465
|
+
if (secrets.length === 0 || text.length === 0) return text;
|
|
24466
|
+
for (const secret of secrets) {
|
|
24467
|
+
for (let keep = Math.min(secret.length - 1, text.length); keep >= 4; keep--) {
|
|
24468
|
+
if (text.startsWith(secret.slice(secret.length - keep))) {
|
|
24469
|
+
return `[redacted]${text.slice(keep)}`;
|
|
24470
|
+
}
|
|
24471
|
+
}
|
|
24472
|
+
}
|
|
24473
|
+
return text;
|
|
24474
|
+
}
|
|
24475
|
+
function redactTrailingSecretPrefix(text, secrets) {
|
|
24476
|
+
if (secrets.length === 0 || text.length === 0) return text;
|
|
24477
|
+
for (const secret of secrets) {
|
|
24478
|
+
for (let keep = Math.min(secret.length - 1, text.length); keep >= 4; keep--) {
|
|
24479
|
+
if (text.endsWith(secret.slice(0, keep))) {
|
|
24480
|
+
return `${text.slice(0, text.length - keep)}[redacted]`;
|
|
24481
|
+
}
|
|
24482
|
+
}
|
|
24483
|
+
}
|
|
24484
|
+
return text;
|
|
24485
|
+
}
|
|
24486
|
+
function redactStderrTail(tail, secrets) {
|
|
24487
|
+
return redactTrailingSecretPrefix(redactLeadingSecretSuffix(redactSecrets(tail, secrets), secrets), secrets);
|
|
24488
|
+
}
|
|
24489
|
+
function sanitizeDiagnostic(text, secrets) {
|
|
24490
|
+
const sanitized = redactLeadingSecretSuffix(redactSecrets(text, secrets), secrets);
|
|
24491
|
+
if (sanitized.length > DIAGNOSTIC_TEXT_LIMIT) {
|
|
24492
|
+
return `${sanitized.slice(0, DIAGNOSTIC_TEXT_LIMIT)}\u2026[truncated ${sanitized.length - DIAGNOSTIC_TEXT_LIMIT} chars]`;
|
|
24493
|
+
}
|
|
24494
|
+
return sanitized;
|
|
24495
|
+
}
|
|
24445
24496
|
function connectTimeoutFor(definition) {
|
|
24446
24497
|
if (definition.connectTimeoutMs !== void 0) return definition.connectTimeoutMs;
|
|
24447
24498
|
const base = path2.basename(definition.command ?? "");
|
|
@@ -24499,6 +24550,28 @@ function withTimeout(promise, timeoutMs, label, signal) {
|
|
|
24499
24550
|
);
|
|
24500
24551
|
});
|
|
24501
24552
|
}
|
|
24553
|
+
function cacheFingerprint(definition) {
|
|
24554
|
+
return createHash("sha256").update(JSON.stringify({
|
|
24555
|
+
sourceScope: definition.sourceScope,
|
|
24556
|
+
sourcePath: definition.sourcePath,
|
|
24557
|
+
name: definition.name,
|
|
24558
|
+
command: definition.command,
|
|
24559
|
+
args: definition.args,
|
|
24560
|
+
// Canonicalized (key-sorted) so reordering equivalent env/header keys
|
|
24561
|
+
// does not invalidate cached metadata. Sorting must be locale-stable
|
|
24562
|
+
// (code-unit order, not localeCompare) so the same definition
|
|
24563
|
+
// fingerprints identically on every machine.
|
|
24564
|
+
env: canonicalizeKeys(definition.env),
|
|
24565
|
+
serverCwd: definition.cwd,
|
|
24566
|
+
url: definition.url,
|
|
24567
|
+
headers: canonicalizeKeys(definition.headers),
|
|
24568
|
+
inheritEnv: definition.inheritEnv
|
|
24569
|
+
})).digest("hex").slice(0, 24);
|
|
24570
|
+
}
|
|
24571
|
+
function canonicalizeKeys(record2) {
|
|
24572
|
+
if (!record2) return {};
|
|
24573
|
+
return Object.fromEntries(Object.entries(record2).sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0));
|
|
24574
|
+
}
|
|
24502
24575
|
var McpServerManager = class {
|
|
24503
24576
|
constructor(definitions, cacheDir, log, now = Date.now) {
|
|
24504
24577
|
this.now = now;
|
|
@@ -24577,8 +24650,9 @@ var McpServerManager = class {
|
|
|
24577
24650
|
stderr: "pipe"
|
|
24578
24651
|
});
|
|
24579
24652
|
if (transport2.stderr) {
|
|
24653
|
+
const captureSecrets = definitionSecrets(definition);
|
|
24580
24654
|
transport2.stderr.on("data", (chunk) => {
|
|
24581
|
-
runtime.stderrTail = appendTail(runtime.stderrTail, chunk);
|
|
24655
|
+
runtime.stderrTail = appendTail(runtime.stderrTail, redactSecrets(String(chunk), captureSecrets));
|
|
24582
24656
|
});
|
|
24583
24657
|
}
|
|
24584
24658
|
return { client, transport: transport2 };
|
|
@@ -24669,7 +24743,7 @@ var McpServerManager = class {
|
|
|
24669
24743
|
if (!runtime.tools) continue;
|
|
24670
24744
|
const shardPath = path2.join(this.cacheDir, `${key}.json`);
|
|
24671
24745
|
const tempPath = `${shardPath}.${process.pid}.${Math.random().toString(36).slice(2)}.tmp`;
|
|
24672
|
-
fs2.writeFileSync(tempPath, JSON.stringify({ updatedAt: this.now(), tools: runtime.tools }, null, 2), "utf8");
|
|
24746
|
+
fs2.writeFileSync(tempPath, JSON.stringify({ updatedAt: this.now(), fingerprint: cacheFingerprint(runtime.definition), tools: runtime.tools }, null, 2), "utf8");
|
|
24673
24747
|
try {
|
|
24674
24748
|
fs2.renameSync(tempPath, shardPath);
|
|
24675
24749
|
} catch (error2) {
|
|
@@ -24722,10 +24796,11 @@ var McpServerManager = class {
|
|
|
24722
24796
|
catalog.set(tool.prefixedName, tool);
|
|
24723
24797
|
ownerOf.set(tool.prefixedName, tool.server);
|
|
24724
24798
|
};
|
|
24725
|
-
for (const
|
|
24726
|
-
|
|
24727
|
-
|
|
24728
|
-
|
|
24799
|
+
for (const [key, shard] of Object.entries(this.readCacheFile())) {
|
|
24800
|
+
const definition = this.definitions.get(key);
|
|
24801
|
+
if (!definition || definition.disabled) continue;
|
|
24802
|
+
if (shard.fingerprint !== cacheFingerprint(definition)) continue;
|
|
24803
|
+
for (const tool of shard.tools) {
|
|
24729
24804
|
claim2(tool, false);
|
|
24730
24805
|
}
|
|
24731
24806
|
}
|
|
@@ -24786,7 +24861,10 @@ var McpServerManager = class {
|
|
|
24786
24861
|
if (typeof parsed.updatedAt !== "number" || this.now() - parsed.updatedAt > METADATA_TTL_MS) continue;
|
|
24787
24862
|
if (!Array.isArray(parsed.tools)) continue;
|
|
24788
24863
|
const key = name.slice(0, -".json".length);
|
|
24789
|
-
snapshot[key] =
|
|
24864
|
+
snapshot[key] = {
|
|
24865
|
+
tools: parsed.tools,
|
|
24866
|
+
...typeof parsed.fingerprint === "string" ? { fingerprint: parsed.fingerprint } : {}
|
|
24867
|
+
};
|
|
24790
24868
|
updatedAt[key] = parsed.updatedAt;
|
|
24791
24869
|
} catch {
|
|
24792
24870
|
}
|
|
@@ -24829,13 +24907,17 @@ var McpServerManager = class {
|
|
|
24829
24907
|
runtime = await this.connect(server, signal);
|
|
24830
24908
|
} catch (error2) {
|
|
24831
24909
|
const runtimeState = this.runtimes.get(server);
|
|
24832
|
-
const
|
|
24910
|
+
const secrets = definitionSecrets(definition);
|
|
24911
|
+
const tail = redactStderrTail(runtimeState?.stderrTail ?? "", secrets).trim();
|
|
24833
24912
|
return {
|
|
24834
24913
|
delivery: "not_sent",
|
|
24835
|
-
error:
|
|
24914
|
+
error: sanitizeDiagnostic(
|
|
24915
|
+
`MCP server "${server}" failed to start: ${error2 instanceof Error ? error2.message : String(error2)}` + (tail ? `
|
|
24836
24916
|
|
|
24837
24917
|
Server stderr tail:
|
|
24838
|
-
${tail}` : "")
|
|
24918
|
+
${tail}` : ""),
|
|
24919
|
+
secrets
|
|
24920
|
+
)
|
|
24839
24921
|
};
|
|
24840
24922
|
}
|
|
24841
24923
|
const client = runtime.client;
|
|
@@ -24879,7 +24961,7 @@ ${tail}` : "")
|
|
|
24879
24961
|
isError: result.isError === true
|
|
24880
24962
|
};
|
|
24881
24963
|
} catch (error2) {
|
|
24882
|
-
const message = error2 instanceof Error ? error2.message : String(error2);
|
|
24964
|
+
const message = sanitizeDiagnostic(error2 instanceof Error ? error2.message : String(error2), definitionSecrets(definition));
|
|
24883
24965
|
if (error2 instanceof ProtocolError && (error2.code === ProtocolErrorCode.InvalidRequest || error2.code === ProtocolErrorCode.InvalidParams) && /output schema|structured content/i.test(message)) {
|
|
24884
24966
|
return {
|
|
24885
24967
|
delivery: "invalid_result",
|
|
@@ -24914,7 +24996,7 @@ ${tail}` : "")
|
|
|
24914
24996
|
};
|
|
24915
24997
|
|
|
24916
24998
|
// builtin/extensions/mcp-adapter/src/trust.ts
|
|
24917
|
-
import { createHash } from "node:crypto";
|
|
24999
|
+
import { createHash as createHash2 } from "node:crypto";
|
|
24918
25000
|
import * as fs3 from "node:fs";
|
|
24919
25001
|
import * as path3 from "node:path";
|
|
24920
25002
|
function serverFingerprint(cwd, definition) {
|
|
@@ -24933,7 +25015,7 @@ function serverFingerprint(cwd, definition) {
|
|
|
24933
25015
|
inheritEnv: definition.inheritEnv,
|
|
24934
25016
|
headers: definition.headers
|
|
24935
25017
|
});
|
|
24936
|
-
return
|
|
25018
|
+
return createHash2("sha256").update(spec).digest("hex").slice(0, 24);
|
|
24937
25019
|
}
|
|
24938
25020
|
var McpTrustStore = class {
|
|
24939
25021
|
filePath;
|
|
@@ -25034,8 +25116,9 @@ function structuredContentIsMirroredInText(textBlocks, structured) {
|
|
|
25034
25116
|
function mapMcpOutcome(outcome, maxBytes) {
|
|
25035
25117
|
if (outcome.delivery !== "ok") {
|
|
25036
25118
|
const prefix = outcome.delivery === "may_have_run" || outcome.delivery === "invalid_result" ? "[outcome unknown]" : "[not executed]";
|
|
25119
|
+
const errorText = truncate(`${outcome.error ?? "MCP call failed"}`, maxBytes);
|
|
25037
25120
|
return {
|
|
25038
|
-
content: [{ type: "text", text: `${prefix} ${
|
|
25121
|
+
content: [{ type: "text", text: `${prefix} ${errorText}` }],
|
|
25039
25122
|
details: { mode: "mcp", delivery: outcome.delivery, ...outcome.protocolCode !== void 0 ? { protocolCode: outcome.protocolCode } : {} },
|
|
25040
25123
|
isError: true
|
|
25041
25124
|
};
|
|
@@ -25070,8 +25153,9 @@ ${JSON.stringify(outcome.structuredContent, null, 2)}` });
|
|
|
25070
25153
|
isError: outcome.isError === true
|
|
25071
25154
|
};
|
|
25072
25155
|
}
|
|
25073
|
-
function createMcpProxyTool(getManager, ensureTrusted, options = {}) {
|
|
25074
|
-
const
|
|
25156
|
+
function createMcpProxyTool(getManager, ensureTrusted, optionsOrVerify = {}, options = {}) {
|
|
25157
|
+
const verifyTrusted = typeof optionsOrVerify === "function" ? optionsOrVerify : void 0;
|
|
25158
|
+
const maxBytes = typeof optionsOrVerify === "object" && optionsOrVerify.outputMaxBytes || options.outputMaxBytes || DEFAULT_OUTPUT_MAX_BYTES;
|
|
25075
25159
|
return {
|
|
25076
25160
|
name: "mcp",
|
|
25077
25161
|
label: "MCP",
|
|
@@ -25122,8 +25206,10 @@ ${truncate(JSON.stringify(schema ?? {}, null, 2), maxBytes)}` : `unknown MCP too
|
|
|
25122
25206
|
}
|
|
25123
25207
|
const resolved = getManager().resolvePrefixedName(params.tool);
|
|
25124
25208
|
const server = descriptor?.server ?? resolved?.server ?? "";
|
|
25209
|
+
let dispatchManager;
|
|
25125
25210
|
if (server) {
|
|
25126
|
-
const
|
|
25211
|
+
const managerAtGate = getManager();
|
|
25212
|
+
const trust = await ensureTrusted(server, managerAtGate);
|
|
25127
25213
|
if (!trust.trusted) {
|
|
25128
25214
|
return {
|
|
25129
25215
|
content: [{ type: "text", text: `[not executed] ${trust.reason ?? "MCP server not trusted"}` }],
|
|
@@ -25131,6 +25217,15 @@ ${truncate(JSON.stringify(schema ?? {}, null, 2), maxBytes)}` : `unknown MCP too
|
|
|
25131
25217
|
isError: true
|
|
25132
25218
|
};
|
|
25133
25219
|
}
|
|
25220
|
+
const managerNow = getManager();
|
|
25221
|
+
if (managerNow !== managerAtGate || verifyTrusted !== void 0 && !verifyTrusted(server, managerNow)) {
|
|
25222
|
+
return {
|
|
25223
|
+
content: [{ type: "text", text: `[not executed] MCP config changed during approval for server "${server}" \u2014 the approved definition and the current one differ. Retry the call to approve the new definition.` }],
|
|
25224
|
+
details: { mode: "mcp", delivery: "not_sent" },
|
|
25225
|
+
isError: true
|
|
25226
|
+
};
|
|
25227
|
+
}
|
|
25228
|
+
dispatchManager = managerNow;
|
|
25134
25229
|
}
|
|
25135
25230
|
let args = {};
|
|
25136
25231
|
if (typeof params.args === "string") {
|
|
@@ -25146,7 +25241,7 @@ ${truncate(JSON.stringify(schema ?? {}, null, 2), maxBytes)}` : `unknown MCP too
|
|
|
25146
25241
|
} else if (params.args && typeof params.args === "object" && !Array.isArray(params.args)) {
|
|
25147
25242
|
args = params.args;
|
|
25148
25243
|
}
|
|
25149
|
-
const outcome = await getManager().callTool(params.tool, args, toolContext.signal);
|
|
25244
|
+
const outcome = await (dispatchManager ?? getManager()).callTool(params.tool, args, toolContext.signal);
|
|
25150
25245
|
return mapMcpOutcome(outcome, maxBytes);
|
|
25151
25246
|
}
|
|
25152
25247
|
};
|
|
@@ -25204,7 +25299,7 @@ function jsonSchemaToTypebox(schema) {
|
|
|
25204
25299
|
// builtin/extensions/mcp-adapter/src/direct-tools.ts
|
|
25205
25300
|
var FALLBACK_PARAMS = Type.Object({}, { description: "MCP tool arguments (schema unknown until first connect)" });
|
|
25206
25301
|
var DEFAULT_DIRECT_OUTPUT_MAX_BYTES = 8192;
|
|
25207
|
-
function registerDirectTools(ctx, getManager, ensureTrusted, outputMaxBytes) {
|
|
25302
|
+
function registerDirectTools(ctx, getManager, ensureTrusted, verifyTrusted, outputMaxBytes) {
|
|
25208
25303
|
const registered = [];
|
|
25209
25304
|
const seenNames = /* @__PURE__ */ new Set();
|
|
25210
25305
|
for (const definition of getManager().listDefinitions()) {
|
|
@@ -25218,13 +25313,13 @@ function registerDirectTools(ctx, getManager, ensureTrusted, outputMaxBytes) {
|
|
|
25218
25313
|
continue;
|
|
25219
25314
|
}
|
|
25220
25315
|
seenNames.add(descriptor.prefixedName);
|
|
25221
|
-
registerDirectTool(ctx, getManager, ensureTrusted, definition, descriptor.prefixedName, descriptor.description, descriptor.inputSchema, outputMaxBytes);
|
|
25316
|
+
registerDirectTool(ctx, getManager, ensureTrusted, verifyTrusted, definition, descriptor.prefixedName, descriptor.description, descriptor.inputSchema, outputMaxBytes);
|
|
25222
25317
|
registered.push(descriptor.prefixedName);
|
|
25223
25318
|
}
|
|
25224
25319
|
}
|
|
25225
25320
|
return registered;
|
|
25226
25321
|
}
|
|
25227
|
-
function registerDirectTool(ctx, getManager, ensureTrusted, definition, prefixedName, description, inputSchema, outputMaxBytes) {
|
|
25322
|
+
function registerDirectTool(ctx, getManager, ensureTrusted, verifyTrusted, definition, prefixedName, description, inputSchema, outputMaxBytes) {
|
|
25228
25323
|
const parameters = inputSchema ? jsonSchemaToTypebox(inputSchema) : FALLBACK_PARAMS;
|
|
25229
25324
|
ctx.registerTool({
|
|
25230
25325
|
name: prefixedName,
|
|
@@ -25232,7 +25327,8 @@ function registerDirectTool(ctx, getManager, ensureTrusted, definition, prefixed
|
|
|
25232
25327
|
description: `${(description ?? prefixedName).trim()} (MCP server: ${definition.name})`,
|
|
25233
25328
|
parameters,
|
|
25234
25329
|
async execute(args, toolContext) {
|
|
25235
|
-
const
|
|
25330
|
+
const managerAtGate = getManager();
|
|
25331
|
+
const trust = await ensureTrusted(definition.name, managerAtGate);
|
|
25236
25332
|
if (!trust.trusted) {
|
|
25237
25333
|
return {
|
|
25238
25334
|
content: [{ type: "text", text: `[not executed] ${trust.reason ?? "MCP server not trusted"}` }],
|
|
@@ -25240,7 +25336,15 @@ function registerDirectTool(ctx, getManager, ensureTrusted, definition, prefixed
|
|
|
25240
25336
|
isError: true
|
|
25241
25337
|
};
|
|
25242
25338
|
}
|
|
25243
|
-
const
|
|
25339
|
+
const managerNow = getManager();
|
|
25340
|
+
if (managerNow !== managerAtGate || verifyTrusted !== void 0 && !verifyTrusted(definition.name, managerNow)) {
|
|
25341
|
+
return {
|
|
25342
|
+
content: [{ type: "text", text: `[not executed] MCP config changed during approval for server "${definition.name}" \u2014 retry the call to approve the new definition.` }],
|
|
25343
|
+
details: { delivery: "not_sent" },
|
|
25344
|
+
isError: true
|
|
25345
|
+
};
|
|
25346
|
+
}
|
|
25347
|
+
const outcome = await managerNow.callTool(
|
|
25244
25348
|
prefixedName,
|
|
25245
25349
|
args && typeof args === "object" && !Array.isArray(args) ? args : {},
|
|
25246
25350
|
toolContext.signal
|
|
@@ -25335,8 +25439,8 @@ function mcpAdapter(ctx) {
|
|
|
25335
25439
|
fs4.writeFileSync(filePath, JSON.stringify(parsed, null, 2) + "\n", "utf8");
|
|
25336
25440
|
return filePath;
|
|
25337
25441
|
}
|
|
25338
|
-
async function ensureTrusted(serverName) {
|
|
25339
|
-
const definition =
|
|
25442
|
+
async function ensureTrusted(serverName, managerAtGate = manager) {
|
|
25443
|
+
const definition = managerAtGate.getDefinition(serverName);
|
|
25340
25444
|
if (!definition) return { trusted: false, reason: `unknown MCP server "${serverName}"` };
|
|
25341
25445
|
if (trustStore.isTrusted(ctx.cwd, definition)) return { trusted: true };
|
|
25342
25446
|
if (!ctx.interactions.isAvailable()) {
|
|
@@ -25360,8 +25464,12 @@ function mcpAdapter(ctx) {
|
|
|
25360
25464
|
reason: `MCP server "${definition.name}" was not approved. It was NOT started. Ask the user to approve it, or remove it from ${definition.sourcePath}.`
|
|
25361
25465
|
};
|
|
25362
25466
|
}
|
|
25363
|
-
|
|
25364
|
-
|
|
25467
|
+
function verifyTrusted(serverName, currentManager) {
|
|
25468
|
+
const definition = currentManager.getDefinition(serverName);
|
|
25469
|
+
return !!definition && trustStore.isTrusted(ctx.cwd, definition);
|
|
25470
|
+
}
|
|
25471
|
+
ctx.registerTool(createMcpProxyTool(() => manager, ensureTrusted, verifyTrusted));
|
|
25472
|
+
const eagerRegistered = registerDirectTools(ctx, () => manager, ensureTrusted, verifyTrusted);
|
|
25365
25473
|
if (eagerRegistered.length > 0) {
|
|
25366
25474
|
ctx.log(`mcp: registered ${eagerRegistered.length} direct tool(s) from metadata cache: ${eagerRegistered.join(", ")}`);
|
|
25367
25475
|
}
|
|
@@ -7,9 +7,9 @@ import {
|
|
|
7
7
|
isPlanModeSafeCommand,
|
|
8
8
|
markCompletedPlanSteps,
|
|
9
9
|
restoreExecutionState
|
|
10
|
-
} from "../../../chunks/chunk-
|
|
11
|
-
import "../../../chunks/chunk-
|
|
12
|
-
import "../../../chunks/chunk-
|
|
10
|
+
} from "../../../chunks/chunk-AZ336HKF.js";
|
|
11
|
+
import "../../../chunks/chunk-Y4CYXJR7.js";
|
|
12
|
+
import "../../../chunks/chunk-O2DKMLNX.js";
|
|
13
13
|
import {
|
|
14
14
|
Type
|
|
15
15
|
} from "../../../chunks/chunk-XXGYUYXI.js";
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { createRequire as __createRequire } from "node:module"; const require = __createRequire(import.meta.url);
|
|
2
2
|
import {
|
|
3
3
|
createCliHostCapabilities
|
|
4
|
-
} from "../../../chunks/chunk-
|
|
4
|
+
} from "../../../chunks/chunk-G6KCJA6B.js";
|
|
5
5
|
import {
|
|
6
6
|
createSharedFileSystemTools,
|
|
7
7
|
createSubagentCapability
|
|
8
|
-
} from "../../../chunks/chunk-
|
|
9
|
-
import "../../../chunks/chunk-
|
|
10
|
-
import "../../../chunks/chunk-
|
|
8
|
+
} from "../../../chunks/chunk-AZ336HKF.js";
|
|
9
|
+
import "../../../chunks/chunk-Y4CYXJR7.js";
|
|
10
|
+
import "../../../chunks/chunk-O2DKMLNX.js";
|
|
11
11
|
import "../../../chunks/chunk-5353DEEC.js";
|
|
12
12
|
import "../../../chunks/chunk-XXGYUYXI.js";
|
|
13
13
|
import "../../../chunks/chunk-LZQXQOPJ.js";
|
|
@@ -39,11 +39,14 @@ function subagentExtension(ctx) {
|
|
|
39
39
|
debugLog: (module, message, data) => ctx.log(`[subagent:${module}] ${message}${data !== void 0 ? ` ${JSON.stringify(data)}` : ""}`),
|
|
40
40
|
resolveModelClass: (modelClass) => ctx.resolveModelClass?.(modelClass),
|
|
41
41
|
resolveModelRef: (modelRef) => ctx.resolveModelRef?.(modelRef),
|
|
42
|
-
createRuntimeTools: () => {
|
|
42
|
+
createRuntimeTools: (mode) => {
|
|
43
43
|
const parentRuntimeTools = ctx.getRuntimeTools();
|
|
44
44
|
if (Array.isArray(parentRuntimeTools) && parentRuntimeTools.length > 0) {
|
|
45
45
|
return parentRuntimeTools.filter((tool) => tool?.name !== "spawn_subagents_parallel");
|
|
46
46
|
}
|
|
47
|
+
if (mode === "edit") {
|
|
48
|
+
throw new Error("Edit delegation requires the parent's executable runtime tools; fallback tools are read-mode only.");
|
|
49
|
+
}
|
|
47
50
|
const configDir = path.join(os.homedir(), ".pie");
|
|
48
51
|
const fsOptions = ctx.yoloMode ? { allowlistedDirs: ["/"] } : {
|
|
49
52
|
accessRoots: [
|
|
@@ -8,9 +8,9 @@ import {
|
|
|
8
8
|
executeManageTodoList,
|
|
9
9
|
executionStateToTodos,
|
|
10
10
|
restoreExecutionState
|
|
11
|
-
} from "../../../chunks/chunk-
|
|
12
|
-
import "../../../chunks/chunk-
|
|
13
|
-
import "../../../chunks/chunk-
|
|
11
|
+
} from "../../../chunks/chunk-AZ336HKF.js";
|
|
12
|
+
import "../../../chunks/chunk-Y4CYXJR7.js";
|
|
13
|
+
import "../../../chunks/chunk-O2DKMLNX.js";
|
|
14
14
|
import "../../../chunks/chunk-XXGYUYXI.js";
|
|
15
15
|
import "../../../chunks/chunk-LZQXQOPJ.js";
|
|
16
16
|
|