@ai-sdk/harness-pi 1.0.64 → 1.0.66
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/CHANGELOG.md +17 -0
- package/README.md +20 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.js +149 -31
- package/dist/index.js.map +1 -1
- package/package.json +5 -3
- package/src/pi-harness.ts +16 -0
- package/src/pi-model-resolver.ts +40 -5
- package/src/pi-session.ts +150 -25
- package/src/pi-translate.ts +26 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,22 @@
|
|
|
1
1
|
# @ai-sdk/harness-pi
|
|
2
2
|
|
|
3
|
+
## 1.0.66
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- b6642fa: fix(harness-pi): resolve compound provider/id model ids under their scoped provider
|
|
8
|
+
|
|
9
|
+
## 1.0.65
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- c20a315: feat(harness-pi): support caller-supplied inline Pi extension factories
|
|
14
|
+
- a03ff6c: feat(harness): add support for per-harness MCP servers
|
|
15
|
+
- Updated dependencies [401a4ba]
|
|
16
|
+
- Updated dependencies [a03ff6c]
|
|
17
|
+
- @ai-sdk/provider-utils@5.0.26
|
|
18
|
+
- @ai-sdk/harness@1.0.65
|
|
19
|
+
|
|
3
20
|
## 1.0.64
|
|
4
21
|
|
|
5
22
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -50,3 +50,23 @@ try {
|
|
|
50
50
|
```
|
|
51
51
|
|
|
52
52
|
The adapter requires a `HarnessV1SandboxProvider`. Pi has no in-sandbox bridge, so the sandbox doesn't need to expose any ports — `@ai-sdk/sandbox-vercel` or `@ai-sdk/sandbox-just-bash` both work.
|
|
53
|
+
|
|
54
|
+
## Inline extensions
|
|
55
|
+
|
|
56
|
+
Use `extensionFactories` to load trusted inline Pi extensions for each harness session:
|
|
57
|
+
|
|
58
|
+
```ts
|
|
59
|
+
import { createPi } from '@ai-sdk/harness-pi';
|
|
60
|
+
|
|
61
|
+
const harness = createPi({
|
|
62
|
+
extensionFactories: [
|
|
63
|
+
pi => {
|
|
64
|
+
pi.on('agent_start', () => {
|
|
65
|
+
console.log('Pi agent started');
|
|
66
|
+
});
|
|
67
|
+
},
|
|
68
|
+
],
|
|
69
|
+
});
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
Routine resource refreshes between turns do not reinitialize extension factories. If the underlying Pi session is rebuilt, factories initialize for the new Pi runtime. Extension factories execute in the host Node.js process, so only pass factories you trust. This option does not enable filesystem extension discovery: user, project, personal, and settings-based Pi extensions remain disabled. Themes and prompt templates also remain disabled.
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import * as _ai_sdk_harness from '@ai-sdk/harness';
|
|
2
2
|
import { HarnessV1, HarnessV1BuiltinTool } from '@ai-sdk/harness';
|
|
3
|
+
import { ExtensionFactory } from '@earendil-works/pi-coding-agent';
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
6
|
* Pi auth options. Exactly one of `gateway` or `customEnv` is honoured
|
|
@@ -52,6 +53,17 @@ type PiHarnessSettings = {
|
|
|
52
53
|
* model settings.
|
|
53
54
|
*/
|
|
54
55
|
readonly agentDir?: string;
|
|
56
|
+
/**
|
|
57
|
+
* MCP server definitions keyed by server name. Each definition uses the
|
|
58
|
+
* underlying runtime's native MCP server configuration format.
|
|
59
|
+
*/
|
|
60
|
+
readonly mcpServers?: Record<string, unknown>;
|
|
61
|
+
/**
|
|
62
|
+
* Trusted inline Pi extensions loaded for each harness session.
|
|
63
|
+
*
|
|
64
|
+
* Filesystem-discovered user and project extensions remain disabled.
|
|
65
|
+
*/
|
|
66
|
+
readonly extensionFactories?: ReadonlyArray<ExtensionFactory>;
|
|
55
67
|
};
|
|
56
68
|
declare const PI_BUILTIN_TOOLS: {
|
|
57
69
|
readonly read: HarnessV1BuiltinTool<{
|
package/dist/index.js
CHANGED
|
@@ -108,7 +108,7 @@ import { resolveSandboxHomeDir } from "@ai-sdk/harness/utils";
|
|
|
108
108
|
import { getAiGatewayAuthFromEnv } from "@ai-sdk/harness/utils";
|
|
109
109
|
|
|
110
110
|
// src/version.ts
|
|
111
|
-
var VERSION = true ? "1.0.
|
|
111
|
+
var VERSION = true ? "1.0.66" : "0.0.0-test";
|
|
112
112
|
|
|
113
113
|
// src/pi-auth.ts
|
|
114
114
|
var DEFAULT_GATEWAY_BASE_URL = "https://ai-gateway.vercel.sh";
|
|
@@ -368,6 +368,15 @@ function extractAssistantText(message) {
|
|
|
368
368
|
// src/pi-model-resolver.ts
|
|
369
369
|
import { getAiGatewayAuthFromEnv as getAiGatewayAuthFromEnv2 } from "@ai-sdk/harness/utils";
|
|
370
370
|
var DEFAULT_PI_GATEWAY_MODEL_ID = "anthropic/claude-sonnet-4.6";
|
|
371
|
+
var findScopedMatch = (effectiveId, models) => {
|
|
372
|
+
const slashIndex = effectiveId.indexOf("/");
|
|
373
|
+
if (slashIndex === -1) return void 0;
|
|
374
|
+
const prefix = effectiveId.slice(0, slashIndex);
|
|
375
|
+
const bareId = effectiveId.slice(slashIndex + 1);
|
|
376
|
+
return models.find(
|
|
377
|
+
(m) => m.provider === prefix && (m.id === bareId || m.name === bareId)
|
|
378
|
+
);
|
|
379
|
+
};
|
|
371
380
|
function createPiModelResolver({
|
|
372
381
|
modelRegistry,
|
|
373
382
|
env = process.env
|
|
@@ -390,7 +399,18 @@ function createPiModelResolver({
|
|
|
390
399
|
if (!effectiveId) return void 0;
|
|
391
400
|
const models = loadModels();
|
|
392
401
|
const matches = (m) => m.id === effectiveId || m.name === effectiveId;
|
|
393
|
-
|
|
402
|
+
const gatewayMatch = useGateway ? models.find((m) => m.provider === "vercel-ai-gateway" && matches(m)) : void 0;
|
|
403
|
+
if (gatewayMatch) return gatewayMatch;
|
|
404
|
+
const scopedMatch = findScopedMatch(effectiveId, models);
|
|
405
|
+
if (scopedMatch && !modelRegistry.hasConfiguredAuth(scopedMatch)) {
|
|
406
|
+
const authenticatedFlatMatches = models.filter(
|
|
407
|
+
(m) => m.id === effectiveId && modelRegistry.hasConfiguredAuth(m)
|
|
408
|
+
);
|
|
409
|
+
if (authenticatedFlatMatches.length === 1) {
|
|
410
|
+
return authenticatedFlatMatches[0];
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
return scopedMatch ?? models.find(matches);
|
|
394
414
|
};
|
|
395
415
|
}
|
|
396
416
|
|
|
@@ -740,6 +760,7 @@ async function writePiSkills(args) {
|
|
|
740
760
|
|
|
741
761
|
// src/pi-translate.ts
|
|
742
762
|
import { randomBytes } from "crypto";
|
|
763
|
+
import { secureJsonParse } from "@ai-sdk/provider-utils";
|
|
743
764
|
|
|
744
765
|
// src/pi-utils.ts
|
|
745
766
|
import {
|
|
@@ -804,7 +825,9 @@ function createPiTranslatorState(options = {}) {
|
|
|
804
825
|
pendingStepToolCallIds: /* @__PURE__ */ new Set(),
|
|
805
826
|
stepOpen: false,
|
|
806
827
|
hostToolResults: /* @__PURE__ */ new Map(),
|
|
828
|
+
dynamicToolCallIds: /* @__PURE__ */ new Set(),
|
|
807
829
|
builtinToolNames: new Set(options.builtinToolNames ?? []),
|
|
830
|
+
hostToolNames: new Set(options.hostToolNames ?? []),
|
|
808
831
|
nativeToCommonNameMap: map
|
|
809
832
|
};
|
|
810
833
|
}
|
|
@@ -830,6 +853,14 @@ function unwrapPiToolResult(event) {
|
|
|
830
853
|
if (typeof event.content === "string") return event.content;
|
|
831
854
|
return event.result ?? event.content ?? null;
|
|
832
855
|
}
|
|
856
|
+
function parseMcpToolResult(content) {
|
|
857
|
+
if (typeof content !== "string") return content;
|
|
858
|
+
try {
|
|
859
|
+
return secureJsonParse(content);
|
|
860
|
+
} catch {
|
|
861
|
+
return content;
|
|
862
|
+
}
|
|
863
|
+
}
|
|
833
864
|
function resolveToolName(state, nativeName) {
|
|
834
865
|
const common = state.nativeToCommonNameMap.get(nativeName);
|
|
835
866
|
return { wire: common ?? nativeName, native: nativeName };
|
|
@@ -969,7 +1000,9 @@ function translatePiEvent(event, state) {
|
|
|
969
1000
|
if (!event.toolCallId || !event.toolName) return [];
|
|
970
1001
|
const { wire, native } = resolveToolName(state, event.toolName);
|
|
971
1002
|
state.observedToolNames.set(event.toolCallId, wire);
|
|
972
|
-
const
|
|
1003
|
+
const isMcpTool = !state.hostToolNames.has(native) && (native === "mcp" || native.startsWith("mcp__"));
|
|
1004
|
+
const providerExecuted = state.builtinToolNames.has(native) || isMcpTool;
|
|
1005
|
+
if (isMcpTool) state.dynamicToolCallIds.add(event.toolCallId);
|
|
973
1006
|
const input = serializeToolOutput(event.args ?? event.input ?? {});
|
|
974
1007
|
return [
|
|
975
1008
|
{
|
|
@@ -978,7 +1011,8 @@ function translatePiEvent(event, state) {
|
|
|
978
1011
|
toolName: wire,
|
|
979
1012
|
input,
|
|
980
1013
|
...wire !== native ? { nativeName: native } : {},
|
|
981
|
-
...providerExecuted ? { providerExecuted: true } : {}
|
|
1014
|
+
...providerExecuted ? { providerExecuted: true } : {},
|
|
1015
|
+
...isMcpTool ? { dynamic: true } : {}
|
|
982
1016
|
}
|
|
983
1017
|
];
|
|
984
1018
|
}
|
|
@@ -989,7 +1023,8 @@ function translatePiEvent(event, state) {
|
|
|
989
1023
|
const nativeName = event.toolName;
|
|
990
1024
|
const wire = recordedName ?? (nativeName ? resolveToolName(state, nativeName).wire : void 0);
|
|
991
1025
|
if (!wire) return [];
|
|
992
|
-
const
|
|
1026
|
+
const dynamic = state.dynamicToolCallIds.delete(event.toolCallId);
|
|
1027
|
+
const result = state.hostToolResults.has(event.toolCallId) ? state.hostToolResults.get(event.toolCallId) ?? null : dynamic ? parseMcpToolResult(unwrapPiToolResult(event)) : unwrapPiToolResult(event);
|
|
993
1028
|
state.hostToolResults.delete(event.toolCallId);
|
|
994
1029
|
state.pendingStepToolCallIds.delete(event.toolCallId);
|
|
995
1030
|
return [
|
|
@@ -998,7 +1033,8 @@ function translatePiEvent(event, state) {
|
|
|
998
1033
|
toolCallId: event.toolCallId,
|
|
999
1034
|
toolName: wire,
|
|
1000
1035
|
result,
|
|
1001
|
-
...event.isError ? { isError: true } : {}
|
|
1036
|
+
...event.isError ? { isError: true } : {},
|
|
1037
|
+
...dynamic ? { dynamic: true } : {}
|
|
1002
1038
|
},
|
|
1003
1039
|
...finishStep(state)
|
|
1004
1040
|
];
|
|
@@ -1505,6 +1541,7 @@ async function syncHostWorkspaceFromSandbox(args) {
|
|
|
1505
1541
|
|
|
1506
1542
|
// src/pi-session.ts
|
|
1507
1543
|
var HARNESS_ID2 = "pi";
|
|
1544
|
+
var PI_MCP_ADAPTER_PACKAGE = "pi-mcp-adapter";
|
|
1508
1545
|
var parkedPiSessions = /* @__PURE__ */ new Map();
|
|
1509
1546
|
function isWithinDirectory(parent, child) {
|
|
1510
1547
|
const rel = path7.relative(parent, child);
|
|
@@ -1670,18 +1707,56 @@ async function createPiSession(input) {
|
|
|
1670
1707
|
env: resolverEnv
|
|
1671
1708
|
});
|
|
1672
1709
|
const resolvedModel = resolveModel(input.settings.model);
|
|
1710
|
+
const mcpServers = resolvePiMcpServers({
|
|
1711
|
+
mcpServers: input.settings.mcpServers
|
|
1712
|
+
});
|
|
1713
|
+
const hasMcpServers = Object.keys(mcpServers).length > 0;
|
|
1714
|
+
const extensionFactories = [
|
|
1715
|
+
...input.settings.extensionFactories ?? []
|
|
1716
|
+
];
|
|
1717
|
+
if (hasMcpServers) {
|
|
1718
|
+
const { createMcpAdapter } = await import(PI_MCP_ADAPTER_PACKAGE);
|
|
1719
|
+
extensionFactories.push(
|
|
1720
|
+
createMcpAdapter({
|
|
1721
|
+
config: {
|
|
1722
|
+
mcpServers,
|
|
1723
|
+
settings: {
|
|
1724
|
+
directTools: true,
|
|
1725
|
+
toolPrefix: "mcp",
|
|
1726
|
+
disableProxyTool: true
|
|
1727
|
+
}
|
|
1728
|
+
}
|
|
1729
|
+
})
|
|
1730
|
+
);
|
|
1731
|
+
}
|
|
1732
|
+
const hasExtensionFactories = extensionFactories.length > 0;
|
|
1733
|
+
let preserveExtensionsResult = false;
|
|
1734
|
+
let currentExtensionsResult;
|
|
1673
1735
|
const resourceLoader = new DefaultResourceLoader({
|
|
1674
1736
|
cwd: sessionWorkDir,
|
|
1675
1737
|
agentDir: hostAgentDir,
|
|
1676
1738
|
settingsManager,
|
|
1677
1739
|
appendSystemPromptOverride: () => [],
|
|
1678
|
-
extensionFactories
|
|
1740
|
+
extensionFactories,
|
|
1741
|
+
...hasExtensionFactories ? {
|
|
1742
|
+
// DefaultResourceLoader invokes inline factories on every reload.
|
|
1743
|
+
// Resource-only reloads retain the active extension runtime, while a
|
|
1744
|
+
// genuine Pi session rebuild is allowed to replace that runtime.
|
|
1745
|
+
extensionsOverride: (extensions) => {
|
|
1746
|
+
if (preserveExtensionsResult && currentExtensionsResult != null) {
|
|
1747
|
+
return currentExtensionsResult;
|
|
1748
|
+
}
|
|
1749
|
+
currentExtensionsResult = extensions;
|
|
1750
|
+
return extensions;
|
|
1751
|
+
}
|
|
1752
|
+
} : {},
|
|
1679
1753
|
// Pi runs in the host process, so its default resource discovery reaches
|
|
1680
1754
|
// the host developer's personal config (`~/.pi/agent/*`, `~/.agents/*`).
|
|
1681
|
-
// The harness
|
|
1682
|
-
// disable
|
|
1683
|
-
// developer's personal Pi extensions inside
|
|
1684
|
-
//
|
|
1755
|
+
// The harness exposes only explicitly supplied inline extension factories;
|
|
1756
|
+
// disable filesystem extension discovery entirely to avoid loading and
|
|
1757
|
+
// executing a host developer's personal or project Pi extensions inside
|
|
1758
|
+
// the server process. Themes and prompt templates stay disabled. Skills
|
|
1759
|
+
// are kept but filtered to workspace project skills plus harness-provided
|
|
1685
1760
|
// skills whose files live in sandbox HOME.
|
|
1686
1761
|
noExtensions: true,
|
|
1687
1762
|
noThemes: true,
|
|
@@ -1697,6 +1772,20 @@ async function createPiSession(input) {
|
|
|
1697
1772
|
})
|
|
1698
1773
|
});
|
|
1699
1774
|
await resourceLoader.reload();
|
|
1775
|
+
async function reloadResourcesOnly() {
|
|
1776
|
+
if (!hasExtensionFactories) {
|
|
1777
|
+
await resourceLoader.reload();
|
|
1778
|
+
return;
|
|
1779
|
+
}
|
|
1780
|
+
const factories = extensionFactories.splice(0);
|
|
1781
|
+
preserveExtensionsResult = true;
|
|
1782
|
+
try {
|
|
1783
|
+
await resourceLoader.reload();
|
|
1784
|
+
} finally {
|
|
1785
|
+
preserveExtensionsResult = false;
|
|
1786
|
+
extensionFactories.push(...factories);
|
|
1787
|
+
}
|
|
1788
|
+
}
|
|
1700
1789
|
let piSession;
|
|
1701
1790
|
let unsubscribe;
|
|
1702
1791
|
let lastToolsSignature;
|
|
@@ -1824,13 +1913,27 @@ async function createPiSession(input) {
|
|
|
1824
1913
|
builtinNames: [...builtinNames]
|
|
1825
1914
|
};
|
|
1826
1915
|
}
|
|
1916
|
+
async function disposePiSession() {
|
|
1917
|
+
unsubscribe?.();
|
|
1918
|
+
unsubscribe = void 0;
|
|
1919
|
+
const session = piSession;
|
|
1920
|
+
piSession = void 0;
|
|
1921
|
+
if (!session) return;
|
|
1922
|
+
if (hasMcpServers) {
|
|
1923
|
+
await session.reload().catch(() => {
|
|
1924
|
+
});
|
|
1925
|
+
}
|
|
1926
|
+
session.dispose();
|
|
1927
|
+
}
|
|
1827
1928
|
async function rebuildPiSession(userTools, isFirstBuild) {
|
|
1929
|
+
let resourcesReloaded = false;
|
|
1828
1930
|
if (piSession) {
|
|
1829
|
-
|
|
1830
|
-
unsubscribe = void 0;
|
|
1831
|
-
piSession.dispose();
|
|
1832
|
-
piSession = void 0;
|
|
1931
|
+
await disposePiSession();
|
|
1833
1932
|
await new Promise((resolve) => setTimeout(resolve, 25));
|
|
1933
|
+
if (hasExtensionFactories) {
|
|
1934
|
+
await resourceLoader.reload();
|
|
1935
|
+
resourcesReloaded = true;
|
|
1936
|
+
}
|
|
1834
1937
|
}
|
|
1835
1938
|
const { customTools, builtinNames } = buildToolDefinitions(userTools);
|
|
1836
1939
|
const toolNames = customTools.map((t) => t.name);
|
|
@@ -1847,17 +1950,21 @@ async function createPiSession(input) {
|
|
|
1847
1950
|
settingsManager,
|
|
1848
1951
|
resourceLoader,
|
|
1849
1952
|
customTools,
|
|
1850
|
-
tools: toolNames,
|
|
1953
|
+
...hasMcpServers ? { noTools: "builtin" } : { tools: toolNames },
|
|
1851
1954
|
...input.settings.thinkingLevel ? { thinkingLevel: input.settings.thinkingLevel } : {},
|
|
1852
1955
|
...resolvedModel ? { model: resolvedModel } : {}
|
|
1853
1956
|
});
|
|
1854
1957
|
piSession = session;
|
|
1958
|
+
if (hasMcpServers) {
|
|
1959
|
+
await piSession.bindExtensions({ mode: "print" });
|
|
1960
|
+
}
|
|
1855
1961
|
const candidatePath = sessionManager.getSessionFile();
|
|
1856
1962
|
if (candidatePath) {
|
|
1857
1963
|
sessionFileName = safePiSessionFileName(path7.basename(candidatePath));
|
|
1858
1964
|
}
|
|
1859
1965
|
translatorState = createPiTranslatorState({
|
|
1860
1966
|
builtinToolNames: builtinNames,
|
|
1967
|
+
hostToolNames: userTools.map((tool2) => tool2.name),
|
|
1861
1968
|
nativeToCommon: NATIVE_TO_COMMON
|
|
1862
1969
|
});
|
|
1863
1970
|
unsubscribe = piSession.subscribe((rawEvent) => {
|
|
@@ -1872,6 +1979,7 @@ async function createPiSession(input) {
|
|
|
1872
1979
|
}
|
|
1873
1980
|
}
|
|
1874
1981
|
});
|
|
1982
|
+
return resourcesReloaded;
|
|
1875
1983
|
}
|
|
1876
1984
|
async function runTurn(turnOpts) {
|
|
1877
1985
|
if (stopped) {
|
|
@@ -1880,11 +1988,14 @@ async function createPiSession(input) {
|
|
|
1880
1988
|
const userTools = turnOpts.tools;
|
|
1881
1989
|
const signature = JSON.stringify(userTools.map((t) => t.name).sort());
|
|
1882
1990
|
const needsRebuild = piSession == null || signature !== lastToolsSignature;
|
|
1991
|
+
let resourcesReloaded = false;
|
|
1883
1992
|
if (needsRebuild) {
|
|
1884
|
-
await rebuildPiSession(userTools, piSession == null);
|
|
1993
|
+
resourcesReloaded = await rebuildPiSession(userTools, piSession == null);
|
|
1885
1994
|
lastToolsSignature = signature;
|
|
1886
1995
|
}
|
|
1887
|
-
|
|
1996
|
+
if (!resourcesReloaded) {
|
|
1997
|
+
await reloadResourcesOnly();
|
|
1998
|
+
}
|
|
1888
1999
|
await syncHostWorkspaceFromSandbox({
|
|
1889
2000
|
sandbox,
|
|
1890
2001
|
sandboxWorkDir: input.sessionWorkDir,
|
|
@@ -1893,6 +2004,7 @@ async function createPiSession(input) {
|
|
|
1893
2004
|
currentEmit = turnOpts.emit;
|
|
1894
2005
|
translatorState = createPiTranslatorState({
|
|
1895
2006
|
builtinToolNames: [...PI_NATIVE_BUILTIN_NAMES],
|
|
2007
|
+
hostToolNames: userTools.map((tool2) => tool2.name),
|
|
1896
2008
|
nativeToCommon: NATIVE_TO_COMMON
|
|
1897
2009
|
});
|
|
1898
2010
|
turnOpts.emit({ type: "stream-start" });
|
|
@@ -1974,10 +2086,7 @@ async function createPiSession(input) {
|
|
|
1974
2086
|
} catch {
|
|
1975
2087
|
}
|
|
1976
2088
|
}
|
|
1977
|
-
|
|
1978
|
-
unsubscribe = void 0;
|
|
1979
|
-
piSession?.dispose();
|
|
1980
|
-
piSession = void 0;
|
|
2089
|
+
await disposePiSession();
|
|
1981
2090
|
workspaceVfs.unmount();
|
|
1982
2091
|
await rm2(hostRoot, { recursive: true, force: true });
|
|
1983
2092
|
return {
|
|
@@ -2036,10 +2145,7 @@ async function createPiSession(input) {
|
|
|
2036
2145
|
parkedPiSessions.delete(input.sessionId);
|
|
2037
2146
|
settlePendingToolResults("Pi session stopped");
|
|
2038
2147
|
settlePendingToolApprovals("Pi session stopped");
|
|
2039
|
-
|
|
2040
|
-
unsubscribe = void 0;
|
|
2041
|
-
piSession?.dispose();
|
|
2042
|
-
piSession = void 0;
|
|
2148
|
+
await disposePiSession();
|
|
2043
2149
|
workspaceVfs.unmount();
|
|
2044
2150
|
await rm2(hostRoot, { recursive: true, force: true });
|
|
2045
2151
|
},
|
|
@@ -2094,10 +2200,7 @@ async function createPiSession(input) {
|
|
|
2094
2200
|
parkedPiSessions.delete(input.sessionId);
|
|
2095
2201
|
settlePendingToolResults("Pi session suspended");
|
|
2096
2202
|
settlePendingToolApprovals("Pi session suspended");
|
|
2097
|
-
|
|
2098
|
-
unsubscribe = void 0;
|
|
2099
|
-
piSession?.dispose();
|
|
2100
|
-
piSession = void 0;
|
|
2203
|
+
await disposePiSession();
|
|
2101
2204
|
workspaceVfs.unmount();
|
|
2102
2205
|
await rm2(hostRoot, { recursive: true, force: true });
|
|
2103
2206
|
return {
|
|
@@ -2110,6 +2213,19 @@ async function createPiSession(input) {
|
|
|
2110
2213
|
};
|
|
2111
2214
|
return sessionImpl;
|
|
2112
2215
|
}
|
|
2216
|
+
function resolvePiMcpServers({
|
|
2217
|
+
mcpServers
|
|
2218
|
+
}) {
|
|
2219
|
+
if (mcpServers == null) return {};
|
|
2220
|
+
for (const [name, value] of Object.entries(mcpServers)) {
|
|
2221
|
+
if (value == null || typeof value !== "object" || Array.isArray(value)) {
|
|
2222
|
+
throw new Error(
|
|
2223
|
+
`Pi MCP server ${JSON.stringify(name)} must be configured with an object value.`
|
|
2224
|
+
);
|
|
2225
|
+
}
|
|
2226
|
+
}
|
|
2227
|
+
return mcpServers;
|
|
2228
|
+
}
|
|
2113
2229
|
function isAbortError(value) {
|
|
2114
2230
|
if (value == null) return false;
|
|
2115
2231
|
if (typeof value === "object" && value.name === "AbortError") {
|
|
@@ -2428,7 +2544,9 @@ function createPi(settings = {}) {
|
|
|
2428
2544
|
settings: {
|
|
2429
2545
|
...settings.auth ? { auth: settings.auth } : {},
|
|
2430
2546
|
...settings.model ? { model: settings.model } : {},
|
|
2431
|
-
...settings.thinkingLevel ? { thinkingLevel: settings.thinkingLevel } : {}
|
|
2547
|
+
...settings.thinkingLevel ? { thinkingLevel: settings.thinkingLevel } : {},
|
|
2548
|
+
...settings.mcpServers ? { mcpServers: settings.mcpServers } : {},
|
|
2549
|
+
...settings.extensionFactories ? { extensionFactories: settings.extensionFactories } : {}
|
|
2432
2550
|
},
|
|
2433
2551
|
clientApp: PI_CLIENT_APP,
|
|
2434
2552
|
isResume: lifecycleState != null,
|